S2n-quic mTLS Getting Certificate Info

I am trying to get client certificate information (e.g. SAN(Subject Alternative Name) and fingerprint etc.) based on the mTLS example that s2n-quic provides in the repository: s2n-quic/examples/s2n-mtls at main · aws/s2n-quic · GitHub

I could get SAN value by using with_verify_host_name_callback, but it seems impossible to link that value to connection.

use s2n_quic::provider::tls::s2n_tls::server::Builder as TlsBuilder;
use s2n_quic::provider::tls::s2n_tls::callbacks::VerifyHostNameCallback;
use s2n_quic::Server;
use std::{error::Error, path::Path};

pub static CA_CERT_PEM: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/certs/ca-cert.pem");
pub static SERVER_CERT_PEM: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/certs/server-cert.pem");
pub static SERVER_KEY_PEM: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/certs/server-key.pem");

struct DumpSan;
impl VerifyHostNameCallback for DumpSan {
    fn verify_host_name(&self, host: &str) -> bool {
        eprintln!("SAN={host}");
        true
    }
}


#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let tls = TlsBuilder::default()
        .with_trusted_certificate(Path::new(CA_CERT_PEM))?
        .with_certificate(Path::new(SERVER_CERT_PEM), Path::new(SERVER_KEY_PEM))?
        .with_client_authentication()?
        .with_verify_host_name_callback(DumpSan)?
        .build()?;

    let mut server = Server::builder()
        .with_tls(tls)?
        .with_io("127.0.0.1:4433")?
        .start()?;

    while let Some(mut connection) = server.accept().await {
        // spawn a new task for the connection
        tokio::spawn(async move {
            eprintln!("Connection accepted from {:?}", connection.remote_addr());
            eprintln!("Connection Internal ID {:?}", connection.id());

            while let Ok(Some(mut stream)) = connection.accept_bidirectional_stream().await {
                // spawn a new task for the stream
                tokio::spawn(async move {
                    eprintln!("Stream opened from {:?}", stream.connection().remote_addr());
                    eprintln!("Stream take_tls_context() {:?}", stream.connection().take_tls_context());

                    // echo any data back to the stream
                    while let Ok(Some(data)) = stream.receive().await {
                        stream.send(data).await.expect("stream should be open");
                    }
                });
            }
        });
    }

    Ok(())
}

In order to obtain the client certificate information from connection, pub fn take_tls_context seems to be useful, but s2n-tls and rustls returns None when I use the function.

I would really appreciate it if you could teach me how to get client certificate information from the connection.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.