-
-
Notifications
You must be signed in to change notification settings - Fork 812
Description
The client certificate example shows how to gain access to TLS client certificate data and how to pass this data into higher-level handlers. However, the code that extracts the certificate is misleading at best:
examples/https-tls/rustls-client-cert/src/main.rs
Lines 53 to 57 in aab1bc4
| if let Some(certs) = tls_session.peer_certificates() { | |
| info!("client certificate found"); | |
| // insert a `rustls::Certificate` into request data | |
| data.insert(certs.last().unwrap().clone()); |
peer_certificates says:
The order of the certificate chain is as it appears in the TLS protocol: the first certificate relates to the peer, the second certifies the first, the third certifies the second, and so on.
As we are using last on the certificate chain, this means we’ll insert the root CA certificate, or some parent certificate, into the request data. When using the curl example command line from the example, this is exactly what happens. I’ve also tested it with OpenSSL, generating a local CA and certificates signed by it. (mkcert doesn’t add SAN to client certificates, which is why I can’t use it in the first place. I didn’t get around to testing this with a production Letsencrypt certificate, which can be used as a client certificate too.)
This certificate is valid, but in many cases it doesn’t relate to the client at all. As the text above clearly says (and as the TLS spec will say), the first certificate is always the one that actually relates to the client, and the one most applications will want to inspect.
I suggest changing the example to call first() instead, which is what users will likely want to do in practice.