|
|
|
|
@ -11,9 +11,14 @@ |
|
|
|
|
// control, DERP).
|
|
|
|
|
package tlsdial |
|
|
|
|
|
|
|
|
|
import "crypto/tls" |
|
|
|
|
import ( |
|
|
|
|
"crypto/tls" |
|
|
|
|
"crypto/x509" |
|
|
|
|
"errors" |
|
|
|
|
"time" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// Config returns a tls.Config for dialing the given host.
|
|
|
|
|
// Config returns a tls.Config for connecting to a server.
|
|
|
|
|
// If base is non-nil, it's cloned as the base config before
|
|
|
|
|
// being configured and returned.
|
|
|
|
|
func Config(host string, base *tls.Config) *tls.Config { |
|
|
|
|
@ -27,3 +32,45 @@ func Config(host string, base *tls.Config) *tls.Config { |
|
|
|
|
|
|
|
|
|
return conf |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// SetConfigExpectedCert modifies c to expect and verify that the server returns
|
|
|
|
|
// a certificate for the provided certDNSName.
|
|
|
|
|
func SetConfigExpectedCert(c *tls.Config, certDNSName string) { |
|
|
|
|
if c.ServerName == certDNSName { |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if c.ServerName == "" { |
|
|
|
|
c.ServerName = certDNSName |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if c.VerifyPeerCertificate != nil { |
|
|
|
|
panic("refusing to override tls.Config.VerifyPeerCertificate") |
|
|
|
|
} |
|
|
|
|
// Set InsecureSkipVerify to prevent crypto/tls from doing its
|
|
|
|
|
// own cert verification, but do the same work that it'd do
|
|
|
|
|
// (but using certDNSName) in the VerifyPeerCertificate hook.
|
|
|
|
|
c.InsecureSkipVerify = true |
|
|
|
|
c.VerifyPeerCertificate = func(rawCerts [][]byte, _ [][]*x509.Certificate) error { |
|
|
|
|
if len(rawCerts) == 0 { |
|
|
|
|
return errors.New("no certs presented") |
|
|
|
|
} |
|
|
|
|
certs := make([]*x509.Certificate, len(rawCerts)) |
|
|
|
|
for i, asn1Data := range rawCerts { |
|
|
|
|
cert, err := x509.ParseCertificate(asn1Data) |
|
|
|
|
if err != nil { |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
certs[i] = cert |
|
|
|
|
} |
|
|
|
|
opts := x509.VerifyOptions{ |
|
|
|
|
CurrentTime: time.Now(), |
|
|
|
|
DNSName: certDNSName, |
|
|
|
|
Intermediates: x509.NewCertPool(), |
|
|
|
|
} |
|
|
|
|
for _, cert := range certs[1:] { |
|
|
|
|
opts.Intermediates.AddCert(cert) |
|
|
|
|
} |
|
|
|
|
_, err := certs[0].Verify(opts) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|