-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtls.go
71 lines (59 loc) · 1.79 KB
/
tls.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
// TLS config and verification
package main
import (
"crypto/tls"
"crypto/x509"
"errors"
"fmt"
"strings"
)
// Get TLS configuration based on SNI
func getConfigForClient(hello *tls.ClientHelloInfo) (*tls.Config, error) {
if hello.ServerName == "" {
return nil, errors.New("SNI is empty")
}
_, suffix, server, ok := suffixes.parse(hello.ServerName)
if !ok {
return nil, fmt.Errorf("SNI %s does not match any suffix", hello.ServerName)
}
config := &tls.Config{Certificates: []tls.Certificate{suffix.certs}}
// Request client certificate from azure clients
if server {
config.ClientAuth = tls.RequestClientCert
config.VerifyConnection = verifyClientCertificate
}
return config, nil
}
// Verify azure client certificate if presented
func verifyClientCertificate(cs tls.ConnectionState) error {
_, suffix, server, ok := suffixes.parse(cs.ServerName)
if !ok || !server {
// rare
return fmt.Errorf("SNI %s does not match any control server", cs.ServerName)
}
// Authenticate by other methods
if len(cs.PeerCertificates) == 0 {
return nil
}
// Use CN as hostname
hostname := strings.ToLower(cs.PeerCertificates[0].Subject.CommonName)
clientInfo, ok := auths.find(hostname, suffix.suffix)
if !ok {
return fmt.Errorf("CN %s is not a valid hostname", hostname)
}
if clientInfo.method != authCert {
return fmt.Errorf("client certificate received but %s does not authenticate by certificate", hostname)
}
// Verify client certificate
opts := x509.VerifyOptions{
Intermediates: x509.NewCertPool(),
Roots: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
for _, cert := range cs.PeerCertificates[1:] {
opts.Intermediates.AddCert(cert)
}
opts.Roots.AddCert(clientInfo.cert)
_, err := cs.PeerCertificates[0].Verify(opts)
return err
}