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
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone

Comments

@chrisbrowning
Copy link

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
Copy link
Contributor

bcmills commented Nov 8, 2019

CC @agl @FiloSottile

@bcmills bcmills added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Nov 8, 2019
@bcmills bcmills added this to the Unplanned milestone Nov 8, 2019
@agl
Copy link
Contributor

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
Copy link

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
Copy link
Contributor

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)

@golang golang locked and limited conversation to collaborators Nov 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Projects
None yet
Development

No branches or pull requests

5 participants