Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto/x509: Other Names in x509 Certificate SAN causing certificate verification failure #35467

Closed
chrisbrowning opened this issue Nov 8, 2019 · 4 comments

Comments

@chrisbrowning
Copy link

@chrisbrowning chrisbrowning commented Nov 8, 2019

What version of Go are you using (go version)?

$ go version
go version go1.13.4 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOOS="linux"

What did you do?

Attempted to bind to an LDAP Server over 636 w/ TLS

What did you expect to see?

Successful binding

What did you see instead?

LDAP Result Code 200 "Network Error": x509: certificate is not valid for any names, but wanted to match

By debugging I determine that the source of this error is that my LDAP host is serving a certificate without a DNSName in the SAN but with two Other Name elements. These two elements are related to OID 1.3.6.1.5.2.2 (Kerberos/Microsoft NT Principal Name). In this scenario, hasSANExtension() == true which makes commonNameAsHostName() == false. Because of this, the x509's verify function expects to find the hostname in the SAN but cannot, and throws an error. Interestingly, the hostname is parsable from the Microsoft NT Principal Name.

When I look at RFC 6125:

As noted, a client MUST NOT seek a match for a reference identifier
of CN-ID if the presented identifiers include a DNS-ID, SRV-ID,
URI-ID, or any application-specific identifier types supported by the
client.

My question is: is there a way to call my own custom middleware or function for hostname verification in support of the above-mentioned "application-specific identifier types" like my Kerberos application? Speaking to the issuer of my certificate, it sounds like I am unlikely to get them to modify the certificate anytime soon.

Any guidance is appreciated. Thank you!

@chrisbrowning chrisbrowning changed the title Other Names in x509 Certificate SAN causing certificate verification failure crypto/x509: Other Names in x509 Certificate SAN causing certificate verification failure Nov 8, 2019
@bcmills

This comment has been minimized.

Copy link
Member

@bcmills bcmills commented Nov 8, 2019

@bcmills bcmills added this to the Unplanned milestone Nov 8, 2019
@agl

This comment has been minimized.

Copy link
Contributor

@agl agl commented Nov 8, 2019

I think you would want to set InsecureSkipVerify on the tls.Config to disable all certificate checking and then verify it yourself. To do so, you would install a VerifyPeerCertificate callback on the tls.Config, setup a VerifyOptions with the second and subsequent rawCerts certificates as Intermediates, call Verify on the first peer certificate, and then dig around in the Extensions of the that first peer certificate to determine, in an LDAP-specific way, whether the certificate is for the correct host.

Seeing the default verification might be useful to crib from — the thing you need to avoid is configuring a DNSName in the VerifyOptions.

(If @FiloSottile suggests something different, listen to him.)

@gopherbot

This comment has been minimized.

Copy link

@gopherbot gopherbot commented Nov 9, 2019

Change https://golang.org/cl/193620 mentions this issue: crypto/tls: add ExampleConfig_VerifyPeerCertificate

gopherbot pushed a commit that referenced this issue Nov 9, 2019
Setting InsecureSkipVerify and VerifyPeerCertificate is the recommended
way to customize and override certificate validation.

However, there is boilerplate involved and it usually requires first
reimplementing the default validation strategy to then customize it.
Provide an example that does the same thing as the default as a starting
point.

Examples of where we directed users to do something similar are in
issues #35467, #31791, #28754, #21971, and #24151.

Fixes #31792

Change-Id: Id033e9fa3cac9dff1f7be05c72dfb34b4f973fd4
Reviewed-on: https://go-review.googlesource.com/c/go/+/193620
Reviewed-by: Adam Langley <agl@golang.org>
@FiloSottile

This comment has been minimized.

Copy link
Member

@FiloSottile FiloSottile commented Nov 9, 2019

Indeed, a custom verifier is your best bet. I just submitted an example to the docs that should help you. https://tip.golang.org/pkg/crypto/tls/#example_Config_verifyPeerCertificate

(The logic ignoring CN is more complex than just letting SAN take priority per RFC 6125, because it interacts with Name Constraints due to our VerifyHostname API only having access to the leaf. #24151)

@FiloSottile FiloSottile closed this Nov 9, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
5 participants
You can’t perform that action at this time.