2023-11-27 19:54:45 +01:00
|
|
|
package scan
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2024-01-08 05:12:11 +05:30
|
|
|
"fmt"
|
2023-11-27 19:54:45 +01:00
|
|
|
"strings"
|
2024-01-08 05:12:11 +05:30
|
|
|
"sync"
|
2023-11-27 19:54:45 +01:00
|
|
|
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/output"
|
|
|
|
|
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ScanContext struct {
|
|
|
|
|
context.Context
|
2024-01-08 05:12:11 +05:30
|
|
|
// exported / configurable fields
|
|
|
|
|
Input *contextargs.Context
|
2023-11-27 19:54:45 +01:00
|
|
|
|
2024-01-08 05:12:11 +05:30
|
|
|
// callbacks or hooks
|
2023-11-27 19:54:45 +01:00
|
|
|
OnError func(error)
|
|
|
|
|
OnResult func(e *output.InternalWrappedEvent)
|
2024-01-08 05:12:11 +05:30
|
|
|
|
|
|
|
|
// unexported state fields
|
|
|
|
|
errors []error
|
|
|
|
|
warnings []string
|
|
|
|
|
events []*output.InternalWrappedEvent
|
|
|
|
|
|
|
|
|
|
// might not be required but better to sync
|
|
|
|
|
m sync.Mutex
|
2023-11-27 19:54:45 +01:00
|
|
|
}
|
|
|
|
|
|
2024-01-08 05:12:11 +05:30
|
|
|
// NewScanContext creates a new scan context using input
|
2023-11-27 19:54:45 +01:00
|
|
|
func NewScanContext(input *contextargs.Context) *ScanContext {
|
|
|
|
|
return &ScanContext{Input: input}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 05:12:11 +05:30
|
|
|
// GenerateResult returns final results slice from all events
|
2023-11-27 19:54:45 +01:00
|
|
|
func (s *ScanContext) GenerateResult() []*output.ResultEvent {
|
2024-01-08 05:12:11 +05:30
|
|
|
s.m.Lock()
|
|
|
|
|
defer s.m.Unlock()
|
2023-11-27 19:54:45 +01:00
|
|
|
return aggregateResults(s.events)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 05:12:11 +05:30
|
|
|
// LogEvent logs events to all events and triggeres any callbacks
|
2023-11-27 19:54:45 +01:00
|
|
|
func (s *ScanContext) LogEvent(e *output.InternalWrappedEvent) {
|
2024-01-08 05:12:11 +05:30
|
|
|
s.m.Lock()
|
|
|
|
|
defer s.m.Unlock()
|
|
|
|
|
if e == nil {
|
|
|
|
|
// do not log nil events
|
|
|
|
|
return
|
|
|
|
|
}
|
2023-11-27 19:54:45 +01:00
|
|
|
if s.OnResult != nil {
|
|
|
|
|
s.OnResult(e)
|
|
|
|
|
}
|
|
|
|
|
s.events = append(s.events, e)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-08 05:12:11 +05:30
|
|
|
// LogError logs error to all events and triggeres any callbacks
|
2023-11-27 19:54:45 +01:00
|
|
|
func (s *ScanContext) LogError(err error) {
|
2024-01-08 05:12:11 +05:30
|
|
|
s.m.Lock()
|
|
|
|
|
defer s.m.Unlock()
|
2023-11-27 19:54:45 +01:00
|
|
|
if err == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s.OnError != nil {
|
|
|
|
|
s.OnError(err)
|
|
|
|
|
}
|
|
|
|
|
s.errors = append(s.errors, err)
|
|
|
|
|
|
|
|
|
|
errorMessage := joinErrors(s.errors)
|
|
|
|
|
results := aggregateResults(s.events)
|
|
|
|
|
for _, result := range results {
|
|
|
|
|
result.Error = errorMessage
|
|
|
|
|
}
|
|
|
|
|
for _, e := range s.events {
|
|
|
|
|
e.InternalEvent["error"] = errorMessage
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-01-08 05:12:11 +05:30
|
|
|
|
|
|
|
|
// LogWarning logs warning to all events
|
|
|
|
|
func (s *ScanContext) LogWarning(format string, args ...any) {
|
|
|
|
|
s.m.Lock()
|
|
|
|
|
defer s.m.Unlock()
|
|
|
|
|
val := fmt.Sprintf(format, args...)
|
|
|
|
|
s.warnings = append(s.warnings, val)
|
|
|
|
|
|
|
|
|
|
for _, e := range s.events {
|
|
|
|
|
if e.InternalEvent != nil {
|
|
|
|
|
e.InternalEvent["warning"] = strings.Join(s.warnings, "; ")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// aggregateResults aggregates results from multiple events
|
|
|
|
|
func aggregateResults(events []*output.InternalWrappedEvent) []*output.ResultEvent {
|
|
|
|
|
var results []*output.ResultEvent
|
|
|
|
|
for _, e := range events {
|
|
|
|
|
results = append(results, e.Results...)
|
|
|
|
|
}
|
|
|
|
|
return results
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// joinErrors joins multiple errors and returns a single error string
|
|
|
|
|
func joinErrors(errors []error) string {
|
|
|
|
|
var errorMessages []string
|
|
|
|
|
for _, e := range errors {
|
|
|
|
|
if e != nil {
|
|
|
|
|
errorMessages = append(errorMessages, e.Error())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return strings.Join(errorMessages, "; ")
|
|
|
|
|
}
|