forked from owasp-amass/amass
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathactive.go
138 lines (117 loc) · 2.72 KB
/
active.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// Copyright © by Jeff Foley 2017-2023. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// SPDX-License-Identifier: Apache-2.0
package intel
import (
"context"
"net"
"strings"
"github.com/caffix/pipeline"
"github.com/caffix/queue"
"github.com/owasp-amass/amass/v4/net/http"
"github.com/owasp-amass/amass/v4/requests"
"golang.org/x/net/publicsuffix"
)
// activeTask is the task that handles all requests related to active methods within the pipeline.
type activeTask struct {
c *Collection
queue queue.Queue
tokenPool chan struct{}
}
type taskArgs struct {
Ctx context.Context
Data pipeline.Data
Params pipeline.TaskParams
}
// newActiveTask returns a activeTask specific to the provided Collection.
func newActiveTask(c *Collection, max int) *activeTask {
if max <= 0 {
return nil
}
tokenPool := make(chan struct{}, max)
for i := 0; i < max; i++ {
tokenPool <- struct{}{}
}
a := &activeTask{
c: c,
queue: queue.NewQueue(),
tokenPool: tokenPool,
}
go a.processQueue()
return a
}
// Process implements the pipeline Task interface.
func (a *activeTask) Process(ctx context.Context, data pipeline.Data, tp pipeline.TaskParams) (pipeline.Data, error) {
select {
case <-ctx.Done():
return nil, nil
default:
}
var ok bool
switch data.(type) {
case *requests.AddrRequest:
ok = true
}
if ok {
a.queue.Append(&taskArgs{
Ctx: ctx,
Data: data.Clone(),
Params: tp,
})
}
return data, nil
}
func (a *activeTask) processQueue() {
for {
select {
case <-a.c.done:
return
case <-a.queue.Signal():
a.processTask()
}
}
}
func (a *activeTask) processTask() {
select {
case <-a.c.done:
return
case <-a.tokenPool:
element, ok := a.queue.Next()
if !ok {
a.tokenPool <- struct{}{}
return
}
args := element.(*taskArgs)
switch v := args.Data.(type) {
case *requests.AddrRequest:
go a.certEnumeration(args.Ctx, v, args.Params)
}
}
}
func (a *activeTask) certEnumeration(ctx context.Context, req *requests.AddrRequest, tp pipeline.TaskParams) {
defer func() { a.tokenPool <- struct{}{} }()
if req == nil || !req.Valid() {
return
}
ip := net.ParseIP(req.Address)
if ip == nil {
return
}
c := a.c
addrinfo := requests.AddressInfo{Address: ip}
for _, name := range http.PullCertificateNames(ctx, req.Address, c.Config.Scope.Ports) {
if n := strings.TrimSpace(name); n != "" {
domain, err := publicsuffix.EffectiveTLDPlusOne(n)
if err != nil {
continue
}
if domain != "" {
go pipeline.SendData(ctx, "filter", &requests.Output{
Name: domain,
Domain: domain,
Addresses: []requests.AddressInfo{addrinfo},
}, tp)
}
}
}
}