rustls / tokio-rustls

Async TLS for the Tokio runtime
Apache License 2.0
123 stars 69 forks source link

Changed client.rs example to use client certs and am getting error. #74

Closed eswenson1 closed 5 months ago

eswenson1 commented 5 months ago

I'm trying to get mTLS client authentication to work. I changed client.rs in a couple ways. First, I stole the load_certs and load_private_key functions from examples in the base rustls project. Then, I changed client.rs from:

    let config = rustls::ClientConfig::builder()
        .with_root_certificates(root_cert_store)
        .with_no_client_auth(); // i guess this was previously the default?

to:

    let config = rustls::ClientConfig::builder()
        .with_root_certificates(root_cert_store)
    .with_client_auth_cert(certs, key);

And initialized certs and keys thus:

    let certs = load_certs("rcfd2_o1.crt");
    let key = load_private_key("rcfd_o1.key");

And with those two changes, I get this error:

➜  tokio-rustls git:(main) ✗ cargo run --example client localhost -p 8770 -c ~/AET/src/aet_demo/ca_certs.pem
   Compiling tokio-rustls v0.26.0 (/Users/eswenson/AET/src/rust/tokio-rustls)
error[E0277]: the trait bound `TlsConnector: From<Arc<Result<ClientConfig, rustls::Error>>>` is not satisfied
  --> examples/client.rs:94:21
   |
94 |     let connector = TlsConnector::from(Arc::new(config));
   |                     ^^^^^^^^^^^^ the trait `From<Arc<Result<ClientConfig, rustls::Error>>>` is not implemented for `TlsConnector`
   |
   = help: the trait `From<Arc<ClientConfig>>` is implemented for `TlsConnector`
   = help: for that trait implementation, expected `ClientConfig`, found `Result<ClientConfig, rustls::Error>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `tokio-rustls` (example "client") due to 1 previous error
➜  tokio-rustls git:(main) ✗

What is causing this? I've made no other changes. Does .with_client_auth_cert(...) work?

cpu commented 5 months ago

Hi @eswenson1,

The issue here is that with_no_client_auth() returns a ClientConfig directly - it has no possibility of error. The function you changed it to, with_client_auth_cert(), returns a Result<ClientConfig, Error> - it can error if given an invalid client certificate or private key.

You need to decide how to handle the error case to pull out the ClientConfig that the code that follows expects. If this was a simple example where you don't care about errors, you could use with_client_auth_cert(...).unwrap(), but for a production use-case you'll probably want to handle the error.

Hope that helps

cpu commented 5 months ago

Going to close this as resolved but if you run into further issues feel free to re-open or file a new issue. Thanks!

eswenson1 commented 5 months ago

So now the issue is that I'm getting this error:

Custom { kind: InvalidData, error: InvalidCertificate(UnknownIssuer) }

I'm using my own PKI hierarchy, where the rootCA is a self-signed cert. There is an intermediate (signing) CA, and then the leaf cert.

Should this work?

I read somewhere that there is a bug that if the signing algorithm isn't supported, the UnknownIssuer error is erroneously returned. I'm using the SHA256 hash algorithm in my PKI CA with RSA keys. Is this supported by rustls (tokyo-rustls)? Note: openssl s_client works fine against my server and I'm specifying the same trusted CA certs in my RootCertStore as my server is using (and which I use with openssl s_client.

A reference to the aforementioned bug is here: https://users.rust-lang.org/t/rustls-unknownissuer-with-own-ca/88575/5

cpu commented 5 months ago

Should this work?

Yes, but you'll need to share more detail to help diagnose the issue. Can you post a complete reproduction?