Reputation: 7709
Context: I want to establish a TLS Connection to a server, which has a certificate with a different (but known!) domain.
So I want to use tls.Dial('tcp', 'real-domain', conf)
, but verify the domain of the certificate as if it would be the other domain (lets call it wrong-domain
), of which I know the server should return it.
So I think the way to do this is override VerifyPeerCertificate
in the clients tls.Config
.
VerifyPeerCertificate
gets rawCerts [][]byte
as parameter, but to use x509.Verify
I need the certificate as a x509.Certificate
type.
The question is: How do I cenvert the rawCerts [][]byte
, which are passed as a parameter to VerifyPeerCertificate
converted to x509.Certificate
?
This is how I want to use it:
conf := &tls.Config{
VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
verifyOptions := x509.VerifyOptions{
DNSName: "wrong-domain",
Roots: serverCertPool,
}
cert := &x509.Certificate{???} // How do I get the x509.Certificate out of the rawCerts [][]byte parameter?
_, err := cert.Verify(verifyOptions)
return err
},
InsecureSkipVerify: true, // We verify in VerifyPeerCertificate
}
Upvotes: 2
Views: 2248
Reputation: 45100
ParseCertificate parses a single certificate from the given ASN.1 DER data.
Example: cert, err := x509.ParseCertificate(rawCerts[0])
By the way this is also how the function that calls VerifyPeerCertificate
does:
// crypto/tls/handshake/handshake_client.go
func (c *Conn) verifyServerCertificate(certificates [][]byte) error {
for i, asn1Data := range certificates {
cert, err := x509.ParseCertificate(asn1Data)
if err != nil {
c.sendAlert(alertBadCertificate)
return errors.New("tls: failed to parse certificate from server: " + err.Error())
}
certs[i] = cert
}
// later on...
if c.config.VerifyPeerCertificate != nil {
if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
c.sendAlert(alertBadCertificate)
return err
}
}
Upvotes: 2