briansmith / webpki

WebPKI X.509 Certificate Validation in Rust
https://briansmith.org/rustdoc/webpki/
Other
463 stars 165 forks source link

Self-signed certificate rejected with WebPKIError(CAUsedAsEndEntity) #114

Closed elf-bot closed 3 years ago

elf-bot commented 4 years ago

Hello, I'm trying to connect to a gRPC server that provides a self-signed certificate. However I'm getting the following error WebPKIError(CAUsedAsEndEntity). If I understand correctly WebPKI wants the CA to issue an end entity certificate instead of using just the self-signed CA cert itself. Unfortunately I don't control the server software that generates the certificate, so I was wondering if there is a way to allow a self-signed CA cert to be used as an End Entity cert?

https://github.com/briansmith/webpki/blob/0573c1ec3fa4da14d74b9c6ee52087b80dadf16e/src/verify_cert.rs#L234 (fwiw removing this line passes the validation of the cert and the connection happens on rustls tlsclient example)

Here is an example of the certificate used in case it helps: Thank you

-----BEGIN CERTIFICATE-----
MIICcTCCAhagAwIBAgIQDojMgC+HAukHYJZqAr1SpTAKBggqhkjOPQQDAjAwMR8w
HQYDVQQKExZsbmQgYXV0b2dlbmVyYXRlZCBjZXJ0MQ0wCwYDVQQDEwRkaXZhMB4X
DTIwMDEwNzEzMTcxNloXDTIxMDMwMzEzMTcxNlowMDEfMB0GA1UEChMWbG5kIGF1
dG9nZW5lcmF0ZWQgY2VydDENMAsGA1UEAxMEZGl2YTBZMBMGByqGSM49AgEGCCqG
SM49AwEHA0IABEp6UaeVXTezbuWdAxl9Bs3EAZIVjdrpBm1/ejz4tCy5exvLUl53
7xATtOHM0Ge1mQ2FqtckSBgGlh4n1EW7cvKjggEQMIIBDDAOBgNVHQ8BAf8EBAMC
AqQwDwYDVR0TAQH/BAUwAwEB/zCB6AYDVR0RBIHgMIHdggRkaXZhgglsb2NhbGhv
c3SCBHVuaXiCCnVuaXhwYWNrZXSHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAGHBMCo
AcOHBKwTAAGHBKwSAAGHBKwRAAGHBAqTFLWHBKwUAAGHEP3yBa9KDwAATsxq//6w
HRWHEP6AAAAAAAAATsxq//6wHRWHEP6AAAAAAAAAAEKD//7cLCmHEP6AAAAAAAAA
WAe7//7DpFuHEP6AAAAAAAAAAEIt//7LJ5KHEP6AAAAAAAAAWAXw//6dcH6HEP6A
AAAAAAAAQJm2//44NHwwCgYIKoZIzj0EAwIDSQAwRgIhAKsgfl5XCcFUF9SUKsZw
eHQX0p/gIn79PdzilaX7uodzAiEAivOYSZcPz7BtqHD+MIP2NopFL84b3yK+T/a+
ZueR0PE=
-----END CERTIFICATE-----
briansmith commented 4 years ago

Imagine we had a flag on each trust anchor indicating whether it was supposed to be a normal CA certificate or a self-signed end-entity certificate. Then on any such trust anchors, we could skip this check. I would be happy to review a PR that adds such a mechanism with appropriate tests.

jbg commented 4 years ago

I sent a PR (#127) adding support for self-signed certificates using the mechanism proposed by @briansmith

jbg commented 4 years ago

@briansmith Have you got any feedback, or is there anything I can do to help #127 get merged?

Stargateur commented 4 years ago

wow I blocked here, what the hell, I just want a TLS tunnel with full self signed certificate... I really need to make a root and sign it for nothing ?

briansmith commented 3 years ago

One of the original ideas I had for webpki was to support self-signed certificates as described above. The idea was implement roughly what web browsers do with respect to "certificate error exceptions." However, given all the other things that need to be done, I think we have to be realistic about the prioritization of this feature. In particular, I think we should first focus on correctly implementing and verifying the correctness of the real, correct (web) PKI semantics, and de-prioritize other things. So, I'm just going to close this. Once we're past 1.0 we might reconsider.

briansmith commented 3 years ago

Also, as far as I know, most users of this webpki crate are using it through Rustls. If you look in the Rustls issue tracker, you can see a relatively recent discussion about making it possible to implement alternate certificate validation that doesn't depend on webpki, and such an alternative mechanism was implemented in Rustls. So now you can use Rustls and plug in your own certificate processing to get the semantics you need.

casey commented 3 years ago

We're running into this with self-signed certificates generated by LND that are accepted by OpenSSL, but not rustls/webpki. We don't have an in-depth understanding of the relevant specs, and don't fully understand why exactly webpki rejects the certificates.

We'd like to understand the situation better so we can make LND generate certificates that work with both rustls and OpenSSL. Is the cause of the different behavior of webpki and OpenSSL that OpenSSL will accept a self-signed end-entity certificate to be added as a root certificate, which makes it trust servers that present that certificate, but this isn't spec-complaint, so webpki doesn't do this?

casey commented 3 years ago

I created an issue in the lnd repo, and they mentioned that they had run into similar problems in the past, which they had fixed by adding the Extended Key Usage value serverAuth to the certificate. Is this a spec-complient way of getting this to work, or is it OpenSSL-specific?

jbg commented 3 years ago

@casey using webpki with LND was the original motivation for the PR I made which is linked above. It was never merged.

LND's self-signed certs are not invalid in any way according to any spec that I'm aware of. webpki just doesn't support trusting self signed certs.

You can apply the linked patch to webpki, or you can replace LND's certs with certs from a CA (and add that CA as a root for webpki if it's not an existing trusted one). The latter approach is what I ended up doing since I don't want to maintain a fork of webpki.

You can also bypass webpki. For example, if using rustls, set your own certificate verifier.

casey commented 3 years ago

@jbg Ahhh, I see. Thank you for clarifying!

Kixunil commented 3 years ago

LOL, I had the same problem also with lnd and I managed to figure it out. I have published my own lnd client library based on tonic.

Not sure if just bytewise comparing of the certificate is good idea but at least I don't see any way it could be insecure. If anyone has pointers I'd appreciate any advice.

casey commented 3 years ago

@Kixunil Great minds think alike!

We were doing the same thing, just making sure that the certificate that the server presented was the same certificate that the user presented. Aside from not handling certificate expiration, we don't know of any security issues when doing so, but to be cautious, we switched to using OpenSSL instead of webpki.

This is the issue we opened in the rustls repo: https://github.com/ctz/rustls/issues/772#issue-933122221

In case you're interested, here's where we use OpenSSL with tonic.

Kixunil commented 3 years ago

Thanks for hints! Depending on what exactly you do, not checking hostname and expiration may be completely OK. In case of LND, I believe it's usually used on the same machine and the certificate is on the same FS or securely transferred to a different machine. There's no good reason to care about hostname if you consider the certificate to be authoritative proof of identity.

To put it differently, it works more like onion domains - you only have the key and if the key is correct, nobody can MITM you. You don't care which IP they are on, there's no domain name.

Expiration is also somewhat funny. It assumes that rotating certificates mitigates key compromise. But TLS key is stored on filesystem with much more sensitive stuff: admin macaroon. Basically the security model is reversed here - certificate protects the server, not the client. If the server is compromised, you're already screwed and MITM is no longer needed.

The only reason expiration might be interesting is cryptography break that takes a long time. If it ever happens I guess we will have bigger problems. But perhaps worth adding the check. As I said, I'm more concerned with it stopping working than with it being unsecure.

Anyway it seems our libraries are quite similar. Do you think we could join our forces?

briansmith commented 3 years ago

This issue was closed 6 months ago. I locked the conversation here to avoid distracting people. I am open to making webpki more flexible but doing things that are just flat-out wrong and dangerous is out of scope of this project, so I'd rather not discuss such solutions here. I know this sounds harsh; not trying to be. I just want to keep discussion here focused on implementing correct certificate validation. I hope you understand.