File: broad.go

package info (click to toggle)
golang-github-cloudflare-cfssl 1.2.0%2Bgit20160825.89.7fb22c8-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 4,916 kB
  • ctags: 2,827
  • sloc: sh: 146; sql: 62; python: 11; makefile: 8
file content (84 lines) | stat: -rw-r--r-- 1,896 bytes parent folder | download | duplicates (3)
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
package scan

import (
	"crypto/tls"
	"crypto/x509"
	"net"
	"sync"
	"time"

	"github.com/cloudflare/cfssl/bundler"
)

// Broad contains scanners for large swaths of TLS hosts on the internet.
var Broad = &Family{
	Description: "Large scale scans of TLS hosts",
	Scanners: map[string]*Scanner{
		"IntermediateCAs": {
			"Scans a CIDR IP range for unknown Intermediate CAs",
			intermediateCAScan,
		},
	},
}

func incrementBytes(bytes []byte) {
	lsb := len(bytes) - 1
	bytes[lsb]++
	if bytes[lsb] == 0 {
		incrementBytes(bytes[:lsb])
	}
}

var (
	caBundleFile  = "/etc/cfssl/ca-bundle.crt"
	intBundleFile = "/etc/cfssl/int-bundle.crt"
	numWorkers    = 32
	timeout       = time.Second
)

// intermediateCAScan scans for new intermediate CAs not in the trust store.
func intermediateCAScan(addr, hostname string) (grade Grade, output Output, err error) {
	cidr, port, _ := net.SplitHostPort(addr)
	_, ipnet, err := net.ParseCIDR(cidr)
	if err != nil {
		return Skipped, nil, nil
	}
	b, err := bundler.NewBundler(caBundleFile, intBundleFile)
	if err != nil {
		return
	}
	var wg sync.WaitGroup
	wg.Add(numWorkers)
	dialer := &net.Dialer{Timeout: timeout}
	config := &tls.Config{InsecureSkipVerify: true}
	addrs := make(chan string)
	chains := make(chan []*x509.Certificate, numWorkers)
	go func() {
		for chain := range chains {
			b.Bundle(chain, nil, bundler.Force)
		}
	}()
	for i := 0; i < numWorkers; i++ {
		go func() {
			for addr := range addrs {
				conn, err := tls.DialWithDialer(dialer, Network, addr, config)
				if err != nil {
					continue
				}
				conn.Close()
				if conn.ConnectionState().HandshakeComplete {
					chains <- conn.ConnectionState().PeerCertificates
				}
			}
			wg.Done()
		}()
	}
	for ip := ipnet.IP.To16(); ipnet.Contains(ip); incrementBytes(ip) {
		addrs <- net.JoinHostPort(ip.String(), port)
	}
	close(addrs)
	wg.Wait()
	close(chains)
	grade = Good
	return
}