-
Notifications
You must be signed in to change notification settings - Fork 6
/
quickcert.go
155 lines (124 loc) · 3.15 KB
/
quickcert.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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"bufio"
"context"
"fmt"
"log"
"os"
"strings"
"sync"
"github.com/jackc/pgx/v5"
)
// psql -h crt.sh -p 5432 -U guest certwatch
var CRTSH_DATABASE_URL = "postgres://[email protected]:5432/certwatch?sslmode=disable&default_query_exec_mode=simple_protocol"
func IterStdin() []string {
out := []string{}
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
out = append(out, scanner.Text())
}
return out
}
var Limit = 15000
func main() {
uniqueMap := make(map[string]bool)
uniqueMapMutex := sync.Mutex{}
query := `
WITH ci AS (
SELECT
x509_commonName(sub.CERTIFICATE) COMMON_NAME
FROM (SELECT cai.CERTIFICATE CERTIFICATE
FROM certificate_and_identities cai
WHERE plainto_tsquery('certwatch', '%s') @@ identities(cai.CERTIFICATE)
AND cai.NAME_VALUE ILIKE ('%%' || '%s')
LIMIT %d OFFSET %d
) sub
GROUP BY sub.CERTIFICATE
)
SELECT
ci.COMMON_NAME COMMON_NAME
FROM ci
WHERE COMMON_NAME IS NOT NULL
`
// iterate lines in stdin
// for each line, prepare a query
stdin := IterStdin()
for _, line := range stdin {
page := 0
var routineQueue = make(chan bool, 10)
stop := false
var wait sync.WaitGroup
lineCopy := line
for {
if stop {
break
}
offset := Limit * page
line := strings.ToLower(lineCopy)
preparedQuery := fmt.Sprintf(query, line, line, Limit, offset)
wait.Add(1)
routineQueue <- true
pageTmp := page
go func(page int) {
retries := 0
success := false
for !success && retries <= 5 {
conn, err := pgx.Connect(context.Background(), CRTSH_DATABASE_URL)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
rows, err := conn.Query(context.Background(), preparedQuery)
if err != nil {
log.Println(err)
rows, err = conn.Query(context.Background(), preparedQuery)
if err != nil {
retries += 1
conn.Close(context.Background())
continue
}
}
subdomains, err := pgx.CollectRows(rows, pgx.RowTo[string])
if err != nil {
log.Println(err)
subdomains, err = pgx.CollectRows(rows, pgx.RowTo[string])
if err != nil {
retries += 1
conn.Close(context.Background())
continue
}
}
if len(subdomains) == 0 {
stop = true
<-routineQueue
wait.Done()
success = true
conn.Close(context.Background())
return
}
for _, subdomain := range subdomains {
subdomain = strings.ToLower(subdomain)
if !strings.Contains(subdomain, line) {
continue
}
if strings.HasPrefix(subdomain, "*.") {
subdomain = strings.Replace(subdomain, "*.", "", 1)
}
uniqueMapMutex.Lock()
if _, ok := uniqueMap[subdomain]; !ok {
fmt.Println(subdomain)
uniqueMap[subdomain] = true
}
uniqueMapMutex.Unlock()
}
conn.Close(context.Background())
success = true
}
wait.Done()
<-routineQueue
}(pageTmp)
page += 1
}
wait.Wait()
}
}