Skip to content

Commit 98948d0

Browse files
support stop-at-first-match for network templates (#5554)
1 parent 2c832f5 commit 98948d0

File tree

2 files changed

+33
-4
lines changed

2 files changed

+33
-4
lines changed

pkg/protocols/network/network.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ type Request struct {
8585
// SelfContained specifies if the request is self-contained.
8686
SelfContained bool `yaml:"-" json:"-"`
8787

88+
// description: |
89+
// StopAtFirstMatch stops the execution of the requests and template as soon as a match is found.
90+
StopAtFirstMatch bool `yaml:"stop-at-first-match,omitempty" json:"stop-at-first-match,omitempty" jsonschema:"title=stop at first match,description=Stop the execution after a match is found"`
91+
8892
// description: |
8993
// ports is post processed list of ports to scan (obtained from Port)
9094
ports []string `yaml:"-" json:"-"`

pkg/protocols/network/request.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os"
99
"strings"
1010
"sync"
11+
"sync/atomic"
1112
"time"
1213

1314
"github.com/pkg/errors"
@@ -99,6 +100,16 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, metadata
99100
gologger.Verbose().Msgf("[%v] got errors while checking open ports: %s\n", request.options.TemplateID, err)
100101
}
101102

103+
// stop at first match if requested
104+
atomicBool := &atomic.Bool{}
105+
shouldStopAtFirstMatch := request.StopAtFirstMatch || request.options.StopAtFirstMatch || request.options.Options.StopAtFirstMatch
106+
wrappedCallback := func(event *output.InternalWrappedEvent) {
107+
if event != nil && event.HasOperatorResult() {
108+
atomicBool.Store(true)
109+
}
110+
callback(event)
111+
}
112+
102113
for _, port := range ports {
103114
input := target.Clone()
104115
// use network port updates input with new port requested in template file
@@ -107,9 +118,12 @@ func (request *Request) ExecuteWithResults(target *contextargs.Context, metadata
107118
if err := input.UseNetworkPort(port, request.ExcludePorts); err != nil {
108119
gologger.Debug().Msgf("Could not network port from constants: %s\n", err)
109120
}
110-
if err := request.executeOnTarget(input, visitedAddresses, metadata, previous, callback); err != nil {
121+
if err := request.executeOnTarget(input, visitedAddresses, metadata, previous, wrappedCallback); err != nil {
111122
return err
112123
}
124+
if shouldStopAtFirstMatch && atomicBool.Load() {
125+
break
126+
}
113127
}
114128

115129
return nil
@@ -141,6 +155,16 @@ func (request *Request) executeOnTarget(input *contextargs.Context, visited maps
141155
variablesMap := request.options.Variables.Evaluate(variables)
142156
variables = generators.MergeMaps(variablesMap, variables, request.options.Constants)
143157

158+
// stop at first match if requested
159+
atomicBool := &atomic.Bool{}
160+
shouldStopAtFirstMatch := request.StopAtFirstMatch || request.options.StopAtFirstMatch || request.options.Options.StopAtFirstMatch
161+
wrappedCallback := func(event *output.InternalWrappedEvent) {
162+
if event != nil && event.HasOperatorResult() {
163+
atomicBool.Store(true)
164+
}
165+
callback(event)
166+
}
167+
144168
for _, kv := range request.addresses {
145169
select {
146170
case <-input.Context().Done():
@@ -154,12 +178,13 @@ func (request *Request) executeOnTarget(input *contextargs.Context, visited maps
154178
continue
155179
}
156180
visited.Set(actualAddress, struct{}{})
157-
158-
if err = request.executeAddress(variables, actualAddress, address, input, kv.tls, previous, callback); err != nil {
181+
if err = request.executeAddress(variables, actualAddress, address, input, kv.tls, previous, wrappedCallback); err != nil {
159182
outputEvent := request.responseToDSLMap("", "", "", address, "")
160183
callback(&output.InternalWrappedEvent{InternalEvent: outputEvent})
161184
gologger.Warning().Msgf("[%v] Could not make network request for (%s) : %s\n", request.options.TemplateID, actualAddress, err)
162-
continue
185+
}
186+
if shouldStopAtFirstMatch && atomicBool.Load() {
187+
break
163188
}
164189
}
165190
return err

0 commit comments

Comments
 (0)