diff --git a/apps/src/args.rs b/apps/src/args.rs index 18f1da1a8a..bb992260e9 100644 --- a/apps/src/args.rs +++ b/apps/src/args.rs @@ -289,6 +289,8 @@ Options: --session-file PATH File used to cache a TLS session for resumption. --source-port PORT Source port to use when connecting to the server [default: 0]. --initial-cwnd-packets PACKETS The initial congestion window size in terms of packet count [default: 10]. + --cert TLS certificate path for client authentication + --key TLS certificate key path for client authentication -h --help Show this screen. "; @@ -309,6 +311,8 @@ pub struct ClientArgs { pub source_port: u16, pub perform_migration: bool, pub send_priority_update: bool, + pub cert: Option, + pub key: Option, } impl Args for ClientArgs { @@ -386,6 +390,18 @@ impl Args for ClientArgs { let send_priority_update = args.get_bool("--send-priority-update"); + let cert = if args.get_bool("--cert") { + Some(args.get_str("--cert").to_string()) + } else { + None + }; + + let key = if args.get_bool("--key") { + Some(args.get_str("--key").to_string()) + } else { + None + }; + ClientArgs { version, dump_response_path, @@ -402,6 +418,8 @@ impl Args for ClientArgs { source_port, perform_migration, send_priority_update, + cert, + key, } } } @@ -424,6 +442,8 @@ impl Default for ClientArgs { source_port: 0, perform_migration: false, send_priority_update: false, + cert: None, + key: None, } } } @@ -464,6 +484,8 @@ Options: --disable-gso Disable GSO (linux only). --disable-pacing Disable pacing (linux only). --initial-cwnd-packets PACKETS The initial congestion window size in terms of packet count [default: 10]. + --trust-origin-ca-pem Path to the pem file of the client origin's CA for mutual TLS. + --trust-strict Enable mandatory client certificate presence when using mutual TLS. -h --help Show this screen. "; @@ -478,6 +500,8 @@ pub struct ServerArgs { pub disable_gso: bool, pub disable_pacing: bool, pub enable_pmtud: bool, + pub trust_origin_ca_pem: Option, + pub trust_strict: bool, } impl Args for ServerArgs { @@ -494,6 +518,14 @@ impl Args for ServerArgs { let disable_pacing = args.get_bool("--disable-pacing"); let enable_pmtud = args.get_bool("--enable-pmtud"); + let trust_origin_ca_pem = if args.get_bool("--trust-origin-ca-pem") { + Some(args.get_str("--trust-origin-ca-pem").to_string()) + } else { + None + }; + + let trust_strict = args.get_bool("--trust-strict"); + ServerArgs { listen, no_retry, @@ -504,6 +536,8 @@ impl Args for ServerArgs { disable_gso, disable_pacing, enable_pmtud, + trust_origin_ca_pem, + trust_strict, } } } diff --git a/apps/src/bin/quiche-server.rs b/apps/src/bin/quiche-server.rs index add38a7ac0..fcd9f95d79 100644 --- a/apps/src/bin/quiche-server.rs +++ b/apps/src/bin/quiche-server.rs @@ -106,6 +106,14 @@ fn main() { config.load_cert_chain_from_pem_file(&args.cert).unwrap(); config.load_priv_key_from_pem_file(&args.key).unwrap(); + if let Some(ref trust_origin_ca_pem) = args.trust_origin_ca_pem { + config + .load_verify_locations_from_file(trust_origin_ca_pem) + .map_err(|e| format!("error loading origin CA file : {}", e)) + .unwrap(); + config.verify_peer(true); + } + config.set_application_protos(&conn_args.alpns).unwrap(); config.discover_pmtu(args.enable_pmtud); @@ -441,6 +449,12 @@ fn main() { (client.conn.is_in_early_data() || client.conn.is_established()) { + if args.trust_origin_ca_pem.is_some() && args.trust_strict && client.conn.peer_cert().is_none() { + info!("anonymous client connections disallowed due to trust-strict, closing connection"); + let reason = "no certificate received".as_bytes(); + let _ = client.conn.close(false, 0x3e5b, &reason); + } + // At this stage the ALPN negotiation succeeded and selected a // single application protocol name. We'll use this to construct // the correct type of HttpConn but `application_proto()` diff --git a/apps/src/client.rs b/apps/src/client.rs index 6c1ea1196b..261033dad1 100644 --- a/apps/src/client.rs +++ b/apps/src/client.rs @@ -99,7 +99,15 @@ pub fn connect( }; // Create the configuration for the QUIC connection. - let mut config = quiche::Config::new(args.version).unwrap(); + let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION).unwrap(); + + if let Some(cert) = args.cert { + config.load_cert_chain_from_pem_file(&cert).unwrap(); + } + + if let Some(key) = args.key { + config.load_priv_key_from_pem_file(&key).unwrap(); + } if let Some(ref trust_origin_ca_pem) = args.trust_origin_ca_pem { config