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/tls: expose all presented certs in error type on handshake failure #48152

Closed
ptagrawal opened this issue Sep 2, 2021 · 18 comments
Closed

Comments

@ptagrawal
Copy link

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

$ go version
1.14.12

Does this issue reproduce with the latest release?

Not sure

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

BusyBox OS, ARM architecture

go env Output
$ go env

What did you do?

This is related to another issue #48151 (comment)

What did you expect to see?

What did you see instead?

@seankhliao seankhliao changed the title Handshake should return a different error type that wraps the original x509 error in a struct that also includes all the presented certs. proposal: crypto/tls: expose all presented certs in error type on handshake failure Sep 2, 2021
@seankhliao
Copy link
Member

cc @FiloSottile

@gopherbot gopherbot added this to the Proposal milestone Sep 2, 2021
@rsc
Copy link
Contributor

rsc commented Oct 13, 2021

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@FiloSottile
Copy link
Contributor

Generally this sounds good. What's the proposed API? An error wrapper type for certificate validation failure that includes the peer certificates? Should it also be raise on a failed VerifyPeerCertificates or VerifyConnection?

How is this different from #48151 and why does that issue say "it's done wrong for client certificates"? We could generally use a more detailed "what did you do" / "what did you expect" / "what did you see".

@rsc
Copy link
Contributor

rsc commented Oct 27, 2021

Ping @ptagrawal for answers to @FiloSottile's questions.

@rsc
Copy link
Contributor

rsc commented Nov 10, 2021

ping @ptagrawal

@ptagrawal
Copy link
Author

An error wrapper type for certificate validation failure that includes the peer certificates?
Yes, because, this would help debug what certs were presented while trying to make the connection.

Should it also be raise on a failed VerifyPeerCertificates or VerifyConnection?
Not sure about this, but I believe, if VerifyPeerCertificate is set, its upto up to parse and verify the certificate which I guess, we could anyways do in case of an error. So, maybe not required.

How is this different from #48151 and why does that issue say "it's done wrong for client certificates"?
So, I mentioned that because, looking at the logs I couldn't find the cert in the err.Error() where as the string preceeding that called out "failed to verify client certificate". I hoped the returned error would contain the certificate that was presented.

@rsc
Copy link
Contributor

rsc commented Dec 1, 2021

It sounds like the answer is to suggest a new error wrapper type that will hold the certificates and be returned on validation failure?

Alternately, is it possible to get this info using a custom VerifyPeerCertificates? Or is there no way to invoke the usual code in that case?

@rsc
Copy link
Contributor

rsc commented Jan 5, 2022

/cc @golang/security

@FiloSottile
Copy link
Contributor

You can do it with VerifyConnection/VerifyPeerCertificates, although you have to maintain some state at a higher lexical scope and it's kind of hard to associate a VerifyConnection/VerifyPeerCertificates invocation with an error returned by Handshake.

Assuming it's possible to unwrap the Handshake return value to get an error as returned by VerifyConnection/VerifyPeerCertificates, one can implement the certificate check there and return a wrapped error.

Still, setting InsecureSkipVerify to bypass the normal checks, then reimplementing them just to return an error wrapper to get access to the certificates is quite burdensome.

I wouldn't be opposed to a new error wrapper with an UnverifiedCertificates field, that can be accessed with errors.As.

@rsc
Copy link
Contributor

rsc commented Feb 2, 2022

It sounds like we need an API, then, specifically a name for the error.

type UnverifiedCertificatesError struct {
    UnverifiedCertificates []*x509.Certificate
}

func (e *UnverifiedCertificatesError) Error() string { ... }

Is this the API?

@FiloSottile
Copy link
Contributor

Maybe the error name is CertificateVerificationError?

@rsc
Copy link
Contributor

rsc commented Feb 9, 2022

OK, so it sounds like:

type CertificateVerificationError struct {
    UnverifiedCertificates []*x509.Certificate
}

func (e * CertificateVerificationError) Error() string { ... }

Does anyone object to that API?

@rsc
Copy link
Contributor

rsc commented Feb 16, 2022

Does anyone object to the API in the preceding comment?

@rsc
Copy link
Contributor

rsc commented Feb 23, 2022

Based on the discussion above, this proposal seems like a likely accept.
— rsc for the proposal review group

@FiloSottile FiloSottile modified the milestones: Proposal, Go1.19 Mar 2, 2022
@FiloSottile FiloSottile self-assigned this Mar 2, 2022
@rsc
Copy link
Contributor

rsc commented Mar 2, 2022

No change in consensus, so accepted. 🎉
This issue now tracks the work of implementing the proposal.
— rsc for the proposal review group

@rsc rsc changed the title proposal: crypto/tls: expose all presented certs in error type on handshake failure crypto/tls: expose all presented certs in error type on handshake failure Mar 2, 2022
@ianlancetaylor
Copy link
Contributor

CC @golang/security

Looks like this didn't make 1.19. Moving to backlog. Please recategorize as appropriate. Thanks.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/449336 mentions this issue: crypto/tls: add CertificateVerificationError to tls handshake

@joanlopez
Copy link

Hi there,

I realized that calls to net/http2.readFrameHeader may end up returning an error due to a bad certificate, that's modelled with a tls.permanentError, that holds a net.OpError that internally points to an alertBadCertificate.

So, I'm wondering whether or not, now that we have the CertificateVerificationError in place, would make sense to use it in such cases in order to let consumers know the reason why it failed. Or perhaps expose it through a similar but different error?

I'd be happy to open an issue with all the details, but first I wanted to know your opinion, as I see it very tight to this issue, as it just looks as the same/very similar situation may arise from different code locations.

cc/ @FiloSottile

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging a pull request may close this issue.

8 participants