From 60d9c2adcbe26cbcb3f6ee4c32cc79ca85c1b9c1 Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Tue, 2 Nov 2021 17:26:00 -0700 Subject: [PATCH] Switch to setter-based config builder (#154) --- src/client.rs | 136 +++++++++++++++++++++------------------- src/rustls.h | 76 +++++++---------------- src/server.rs | 164 ++++++++++++++++++++++--------------------------- tests/client.c | 13 ++-- tests/server.c | 14 ++--- 5 files changed, 178 insertions(+), 225 deletions(-) diff --git a/src/client.rs b/src/client.rs index 8e8c291b..fe047a0e 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,10 +7,10 @@ use std::sync::Arc; use std::time::SystemTime; use libc::{c_char, size_t}; -use rustls::client::{ResolvesClientCert, ServerCertVerified}; +use rustls::client::{ResolvesClientCert, ServerCertVerified, ServerCertVerifier}; use rustls::{ - sign::CertifiedKey, Certificate, ClientConfig, ClientConnection, ConfigBuilder, - ProtocolVersion, RootCertStore, SupportedCipherSuite, WantsVerifier, ALL_CIPHER_SUITES, + sign::CertifiedKey, Certificate, ClientConfig, ClientConnection, ProtocolVersion, + RootCertStore, SupportedCipherSuite, WantsVerifier, ALL_CIPHER_SUITES, }; use crate::cipher::{rustls_certified_key, rustls_root_cert_store, rustls_supported_ciphersuite}; @@ -31,25 +31,23 @@ use crate::{ /// for concurrent mutation. Under the hood, it corresponds to a /// Box. /// https://docs.rs/rustls/0.20.0/rustls/struct.ClientConfig.html -pub struct rustls_client_config_builder_wants_verifier { +pub struct rustls_client_config_builder { // We use the opaque struct pattern to tell C about our types without // telling them what's inside. // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs _private: [u8; 0], } -impl CastPtr for rustls_client_config_builder_wants_verifier { - type RustType = ConfigBuilder; -} - -impl BoxCastPtr for rustls_client_config_builder_wants_verifier {} - -pub struct rustls_client_config_builder { - _private: [u8; 0], +pub(crate) struct ClientConfigBuilder { + base: rustls::ConfigBuilder, + verifier: Arc, + alpn_protocols: Vec>, + enable_sni: bool, + cert_resolver: Option>, } impl CastPtr for rustls_client_config_builder { - type RustType = ClientConfig; + type RustType = ClientConfigBuilder; } impl BoxCastPtr for rustls_client_config_builder {} @@ -70,6 +68,22 @@ impl CastConstPtr for rustls_client_config { impl ArcCastPtr for rustls_client_config {} +struct NoneVerifier; + +impl ServerCertVerifier for NoneVerifier { + fn verify_server_cert( + &self, + _end_entity: &Certificate, + _intermediates: &[Certificate], + _server_name: &rustls::ServerName, + _scts: &mut dyn Iterator, + _ocsp_response: &[u8], + _now: SystemTime, + ) -> Result { + Err(rustls::Error::InvalidCertificateSignature) + } +} + impl rustls_client_config_builder { /// Create a rustls_client_config_builder. Caller owns the memory and must /// eventually call rustls_client_config_builder_build, then free the @@ -80,10 +94,15 @@ impl rustls_client_config_builder { /// Caller must add roots with rustls_client_config_builder_load_roots_from_file /// or provide a custom verifier. #[no_mangle] - pub extern "C" fn rustls_client_config_builder_new_with_safe_defaults( - ) -> *mut rustls_client_config_builder_wants_verifier { + pub extern "C" fn rustls_client_config_builder_new() -> *mut rustls_client_config_builder { ffi_panic_boundary! { - let builder = rustls::ClientConfig::builder().with_safe_defaults(); + let builder = ClientConfigBuilder { + base: rustls::ClientConfig::builder().with_safe_defaults(), + verifier: Arc::new(NoneVerifier), + cert_resolver: None, + alpn_protocols: vec![], + enable_sni: true, + }; BoxCastPtr::to_mut_ptr(builder) } } @@ -103,12 +122,12 @@ impl rustls_client_config_builder { /// `versions` will only be used during the call and the application retains /// ownership. `len` is the number of consecutive `ui16` pointed to by `versions`. #[no_mangle] - pub extern "C" fn rustls_client_config_builder_new( + pub extern "C" fn rustls_client_config_builder_new_custom( cipher_suites: *const *const rustls_supported_ciphersuite, cipher_suites_len: size_t, tls_versions: *const u16, tls_versions_len: size_t, - builder: *mut *mut rustls_client_config_builder_wants_verifier, + builder_out: *mut *mut rustls_client_config_builder, ) -> rustls_result { ffi_panic_boundary! { let cipher_suites: &[*const rustls_supported_ciphersuite] = try_slice!(cipher_suites, cipher_suites_len); @@ -133,12 +152,19 @@ impl rustls_client_config_builder { } let result = rustls::ClientConfig::builder().with_cipher_suites(&cs_vec).with_safe_default_kx_groups().with_protocol_versions(&versions); - let new = match result { + let base = match result { Ok(new) => new, Err(_) => return rustls_result::InvalidParameter, }; + let config_builder = ClientConfigBuilder { + base: base, + verifier: Arc::new(NoneVerifier), + cert_resolver: None, + alpn_protocols: vec![], + enable_sni: true, + }; - BoxCastPtr::set_mut_ptr(builder, new); + BoxCastPtr::set_mut_ptr(builder_out, config_builder); rustls_result::Ok } } @@ -276,21 +302,18 @@ impl rustls_client_config_builder { /// https://docs.rs/rustls/0.20.0/rustls/client/struct.DangerousClientConfig.html#method.set_certificate_verifier #[no_mangle] pub extern "C" fn rustls_client_config_builder_dangerous_set_certificate_verifier( - wants_verifier: *mut rustls_client_config_builder_wants_verifier, + config_builder: *mut rustls_client_config_builder, callback: rustls_verify_server_cert_callback, - builder: *mut *mut rustls_client_config_builder, ) -> rustls_result { ffi_panic_boundary! { + let config_builder = try_mut_from_ptr!(config_builder); let callback: VerifyCallback = match callback { Some(cb) => cb, None => return rustls_result::InvalidParameter, }; - let new = *try_box_from_ptr!(wants_verifier); let verifier: Verifier = Verifier{callback: callback}; - // TODO: no client authentication support for now - let config = new.with_custom_certificate_verifier(Arc::new(verifier)).with_no_client_auth(); - BoxCastPtr::set_mut_ptr(builder, config); + config_builder.verifier = Arc::new(verifier); rustls_result::Ok } } @@ -303,15 +326,13 @@ impl rustls_client_config_builder { /// those will subtract 1 from the refcount for `roots`. #[no_mangle] pub extern "C" fn rustls_client_config_builder_use_roots( - wants_verifier: *mut rustls_client_config_builder_wants_verifier, + config_builder: *mut rustls_client_config_builder, roots: *const rustls_root_cert_store, - builder: *mut *mut rustls_client_config_builder, ) -> rustls_result { ffi_panic_boundary! { + let builder = try_mut_from_ptr!(config_builder); let root_store: &RootCertStore = try_ref_from_ptr!(roots); - let prev = *try_box_from_ptr!(wants_verifier); - let config = prev.with_root_certificates(root_store.clone()).with_no_client_auth(); - BoxCastPtr::set_mut_ptr(builder, config); + builder.verifier = Arc::new(rustls::client::WebPkiVerifier::new(root_store.clone(), None)); rustls_result::Ok } } @@ -320,18 +341,17 @@ impl rustls_client_config_builder { /// PEM-formatted certificates. #[no_mangle] pub extern "C" fn rustls_client_config_builder_load_roots_from_file( - wants_verifier: *mut rustls_client_config_builder_wants_verifier, + config_builder: *mut rustls_client_config_builder, filename: *const c_char, - builder: *mut *mut rustls_client_config_builder, ) -> rustls_result { ffi_panic_boundary! { - let prev = *try_box_from_ptr!(wants_verifier); - let filename: &CStr = unsafe { - if filename.is_null() { - return rustls_result::NullParameter; - } - CStr::from_ptr(filename) - }; + let config_builder = try_mut_from_ptr!(config_builder); + let filename: &CStr = unsafe { + if filename.is_null() { + return rustls_result::NullParameter; + } + CStr::from_ptr(filename) + }; let filename: &[u8] = filename.to_bytes(); let filename: &str = match std::str::from_utf8(filename) { @@ -356,10 +376,7 @@ impl rustls_client_config_builder { return rustls_result::CertificateParseError; } - // TODO: no client authentication support for now - let config = prev.with_root_certificates(roots).with_no_client_auth(); - BoxCastPtr::set_mut_ptr(builder, config); - + config_builder.verifier = Arc::new(rustls::client::WebPkiVerifier::new(roots, None)); rustls_result::Ok } } @@ -382,7 +399,7 @@ impl rustls_client_config_builder { len: size_t, ) -> rustls_result { ffi_panic_boundary! { - let config: &mut ClientConfig = try_mut_from_ptr!(builder); + let config: &mut ClientConfigBuilder = try_mut_from_ptr!(builder); let protocols: &[rustls_slice_bytes] = try_slice!(protocols, len); let mut vv: Vec> = Vec::with_capacity(protocols.len()); @@ -403,25 +420,11 @@ impl rustls_client_config_builder { enable: bool, ) { ffi_panic_boundary! { - let config: &mut ClientConfig = try_mut_from_ptr!(config); + let config: &mut ClientConfigBuilder = try_mut_from_ptr!(config); config.enable_sni = enable; } } - /// "Free" a client_config_builder_wants_verifier before transmogrifying it into a client_config. - /// Normally builders are consumed to client_configs via `rustls_client_config_builder_build` - /// and may not be free'd or otherwise used afterwards. - /// Use free only when the building of a config has to be aborted before a config - /// was created. - #[no_mangle] - pub extern "C" fn rustls_client_config_builder_wants_verifier_free( - builder: *mut rustls_client_config_builder_wants_verifier, - ) { - ffi_panic_boundary! { - BoxCastPtr::to_box(builder); - } - } - /// Provide the configuration a list of certificates where the session /// will select the first one that is compatible with the server's signature /// verification capabilities. Clients that want to support both ECDSA and @@ -441,14 +444,14 @@ impl rustls_client_config_builder { certified_keys_len: size_t, ) -> rustls_result { ffi_panic_boundary! { - let config: &mut ClientConfig = try_mut_from_ptr!(builder); + let config: &mut ClientConfigBuilder = try_mut_from_ptr!(builder); let keys_ptrs: &[*const rustls_certified_key] = try_slice!(certified_keys, certified_keys_len); let mut keys: Vec> = Vec::new(); for &key_ptr in keys_ptrs { let certified_key: Arc = try_arc_from_ptr!(key_ptr); keys.push(certified_key); } - config.client_auth_cert_resolver = Arc::new(ResolvesClientCertFromChoices { keys }); + config.cert_resolver = Some(Arc::new(ResolvesClientCertFromChoices { keys })); rustls_result::Ok } } @@ -486,8 +489,13 @@ impl rustls_client_config_builder { builder: *mut rustls_client_config_builder, ) -> *const rustls_client_config { ffi_panic_boundary! { - let b = try_box_from_ptr!(builder); - ArcCastPtr::to_const_ptr(*b) + let builder: Box = try_box_from_ptr!(builder); + let config = builder.base.with_custom_certificate_verifier(builder.verifier); + let config = match builder.cert_resolver { + Some(r) => config.with_client_cert_resolver(r), + None => config.with_no_client_auth(), + }; + ArcCastPtr::to_const_ptr(config) } } diff --git a/src/rustls.h b/src/rustls.h index 810134c3..e18f5be1 100644 --- a/src/rustls.h +++ b/src/rustls.h @@ -136,8 +136,6 @@ typedef struct rustls_client_cert_verifier_optional rustls_client_cert_verifier_ */ typedef struct rustls_client_config rustls_client_config; -typedef struct rustls_client_config_builder rustls_client_config_builder; - /** * A client config being constructed. A builder can be modified by, * e.g. rustls_client_config_builder_load_roots_from_file. Once you're @@ -147,7 +145,7 @@ typedef struct rustls_client_config_builder rustls_client_config_builder; * Box. * https://docs.rs/rustls/0.20.0/rustls/struct.ClientConfig.html */ -typedef struct rustls_client_config_builder_wants_verifier rustls_client_config_builder_wants_verifier; +typedef struct rustls_client_config_builder rustls_client_config_builder; typedef struct rustls_connection rustls_connection; @@ -184,10 +182,6 @@ typedef struct rustls_server_config rustls_server_config; */ typedef struct rustls_server_config_builder rustls_server_config_builder; -typedef struct rustls_server_config_builder_wants_server_cert rustls_server_config_builder_wants_server_cert; - -typedef struct rustls_server_config_builder_wants_verifier rustls_server_config_builder_wants_verifier; - /** * A read-only view of a slice of Rust byte slices. * @@ -645,7 +639,7 @@ void rustls_client_cert_verifier_optional_free(const struct rustls_client_cert_v * Caller must add roots with rustls_client_config_builder_load_roots_from_file * or provide a custom verifier. */ -struct rustls_client_config_builder_wants_verifier *rustls_client_config_builder_new_with_safe_defaults(void); +struct rustls_client_config_builder *rustls_client_config_builder_new(void); /** * Create a rustls_client_config_builder. Caller owns the memory and must @@ -663,11 +657,11 @@ struct rustls_client_config_builder_wants_verifier *rustls_client_config_builder * `versions` will only be used during the call and the application retains * ownership. `len` is the number of consecutive `ui16` pointed to by `versions`. */ -enum rustls_result rustls_client_config_builder_new(const struct rustls_supported_ciphersuite *const *cipher_suites, - size_t cipher_suites_len, - const uint16_t *tls_versions, - size_t tls_versions_len, - struct rustls_client_config_builder_wants_verifier **builder); +enum rustls_result rustls_client_config_builder_new_custom(const struct rustls_supported_ciphersuite *const *cipher_suites, + size_t cipher_suites_len, + const uint16_t *tls_versions, + size_t tls_versions_len, + struct rustls_client_config_builder **builder_out); /** * Set a custom server certificate verifier. @@ -703,9 +697,8 @@ enum rustls_result rustls_client_config_builder_new(const struct rustls_supporte * * https://docs.rs/rustls/0.20.0/rustls/client/struct.DangerousClientConfig.html#method.set_certificate_verifier */ -enum rustls_result rustls_client_config_builder_dangerous_set_certificate_verifier(struct rustls_client_config_builder_wants_verifier *wants_verifier, - rustls_verify_server_cert_callback callback, - struct rustls_client_config_builder **builder); +enum rustls_result rustls_client_config_builder_dangerous_set_certificate_verifier(struct rustls_client_config_builder *config_builder, + rustls_verify_server_cert_callback callback); /** * Use the trusted root certificates from the provided store. @@ -715,17 +708,15 @@ enum rustls_result rustls_client_config_builder_dangerous_set_certificate_verifi * call rustls_client_config_free or rustls_client_config_builder_free, * those will subtract 1 from the refcount for `roots`. */ -enum rustls_result rustls_client_config_builder_use_roots(struct rustls_client_config_builder_wants_verifier *wants_verifier, - const struct rustls_root_cert_store *roots, - struct rustls_client_config_builder **builder); +enum rustls_result rustls_client_config_builder_use_roots(struct rustls_client_config_builder *config_builder, + const struct rustls_root_cert_store *roots); /** * Add trusted root certificates from the named file, which should contain * PEM-formatted certificates. */ -enum rustls_result rustls_client_config_builder_load_roots_from_file(struct rustls_client_config_builder_wants_verifier *wants_verifier, - const char *filename, - struct rustls_client_config_builder **builder); +enum rustls_result rustls_client_config_builder_load_roots_from_file(struct rustls_client_config_builder *config_builder, + const char *filename); /** * Set the ALPN protocol list to the given protocols. `protocols` must point @@ -751,15 +742,6 @@ enum rustls_result rustls_client_config_builder_set_alpn_protocols(struct rustls void rustls_client_config_builder_set_enable_sni(struct rustls_client_config_builder *config, bool enable); -/** - * "Free" a client_config_builder_wants_verifier before transmogrifying it into a client_config. - * Normally builders are consumed to client_configs via `rustls_client_config_builder_build` - * and may not be free'd or otherwise used afterwards. - * Use free only when the building of a config has to be aborted before a config - * was created. - */ -void rustls_client_config_builder_wants_verifier_free(struct rustls_client_config_builder_wants_verifier *builder); - /** * Provide the configuration a list of certificates where the session * will select the first one that is compatible with the server's signature @@ -1027,7 +1009,7 @@ struct rustls_str rustls_slice_str_get(const struct rustls_slice_str *input, siz * resulting rustls_server_config. This uses rustls safe default values * for the cipher suites, key exchange groups and protocol versions. */ -struct rustls_server_config_builder_wants_verifier *rustls_server_config_builder_new_with_safe_defaults(void); +struct rustls_server_config_builder *rustls_server_config_builder_new(void); /** * Create a rustls_server_config_builder. Caller owns the memory and must @@ -1045,16 +1027,11 @@ struct rustls_server_config_builder_wants_verifier *rustls_server_config_builder * `versions` will only be used during the call and the application retains * ownership. `len` is the number of consecutive `ui16` pointed to by `versions`. */ -enum rustls_result rustls_server_config_builder_new(const struct rustls_supported_ciphersuite *const *cipher_suites, - size_t cipher_suites_len, - const uint16_t *tls_versions, - size_t tls_versions_len, - struct rustls_server_config_builder_wants_verifier **builder); - -/** - * For memory lifetime, see rustls_server_config_builder_new. - */ -struct rustls_server_config_builder *rustls_server_config_builder_with_no_client_auth(struct rustls_server_config_builder_wants_verifier *wants_verifier); +enum rustls_result rustls_server_config_builder_new_custom(const struct rustls_supported_ciphersuite *const *cipher_suites, + size_t cipher_suites_len, + const uint16_t *tls_versions, + size_t tls_versions_len, + struct rustls_server_config_builder **builder_out); /** * Create a rustls_server_config_builder for TLS sessions that require @@ -1063,9 +1040,8 @@ struct rustls_server_config_builder *rustls_server_config_builder_with_no_client * If input is NULL, this will return NULL. * For memory lifetime, see rustls_server_config_builder_new. */ -enum rustls_result rustls_server_config_builder_with_client_verifier(struct rustls_server_config_builder_wants_verifier *wants_verifier, - const struct rustls_client_cert_verifier *verifier, - struct rustls_server_config_builder_wants_server_cert **builder); +void rustls_server_config_builder_set_client_verifier(struct rustls_server_config_builder *config_builder, + const struct rustls_client_cert_verifier *verifier); /** * Create a rustls_server_config_builder for TLS sessions that accept @@ -1074,7 +1050,8 @@ enum rustls_result rustls_server_config_builder_with_client_verifier(struct rust * If input is NULL, this will return NULL. * For memory lifetime, see rustls_server_config_builder_new. */ -struct rustls_server_config_builder *rustls_server_config_builder_with_client_verifier_optional(const struct rustls_client_cert_verifier_optional *verifier); +void rustls_server_config_builder_set_client_verifier_optional(struct rustls_server_config_builder *config_builder, + const struct rustls_client_cert_verifier_optional *verifier); /** * "Free" a server_config_builder before transmogrifying it into a server_config. @@ -1085,13 +1062,6 @@ struct rustls_server_config_builder *rustls_server_config_builder_with_client_ve */ void rustls_server_config_builder_free(struct rustls_server_config_builder *config); -/** - * Create a rustls_server_config_builder from an existing rustls_server_config. The - * builder will be used to create a new, separate config that starts with the settings - * from the supplied configuration. - */ -struct rustls_server_config_builder *rustls_server_config_builder_from_config(const struct rustls_server_config *config); - /** * With `ignore` != 0, the server will ignore the client ordering of cipher * suites, aka preference, during handshake and respect its own ordering diff --git a/src/server.rs b/src/server.rs index 5ad7bb5d..1f3399a5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,17 +1,18 @@ use std::convert::TryInto; use std::ffi::c_void; +use std::ptr::null; use std::slice; use std::sync::Arc; use libc::size_t; use rustls::server::{ - AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, ClientHello, - ResolvesServerCert, ServerConfig, ServerConnection, WantsServerCert, + AllowAnyAnonymousOrAuthenticatedClient, AllowAnyAuthenticatedClient, ClientCertVerifier, + ClientHello, NoClientAuth, ResolvesServerCert, ServerConfig, ServerConnection, + StoresServerSessions, }; use rustls::sign::CertifiedKey; use rustls::{ - ConfigBuilder, ProtocolVersion, SignatureScheme, SupportedCipherSuite, WantsVerifier, - ALL_CIPHER_SUITES, + ProtocolVersion, SignatureScheme, SupportedCipherSuite, WantsVerifier, ALL_CIPHER_SUITES, }; use crate::cipher::{ @@ -45,37 +46,20 @@ pub struct rustls_server_config_builder { _private: [u8; 0], } -impl CastPtr for rustls_server_config_builder { - type RustType = ServerConfig; +pub(crate) struct ServerConfigBuilder { + base: rustls::ConfigBuilder, + verifier: Arc, + cert_resolver: Option>, + session_storage: Option>, + alpn_protocols: Vec>, + ignore_client_order: Option, } -impl BoxCastPtr for rustls_server_config_builder {} - -pub struct rustls_server_config_builder_wants_verifier { - // We use the opaque struct pattern to tell C about our types without - // telling them what's inside. - // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs - _private: [u8; 0], -} - -impl CastPtr for rustls_server_config_builder_wants_verifier { - type RustType = ConfigBuilder; -} - -impl BoxCastPtr for rustls_server_config_builder_wants_verifier {} - -pub struct rustls_server_config_builder_wants_server_cert { - // We use the opaque struct pattern to tell C about our types without - // telling them what's inside. - // https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs - _private: [u8; 0], -} - -impl CastPtr for rustls_server_config_builder_wants_server_cert { - type RustType = ConfigBuilder; +impl CastPtr for rustls_server_config_builder { + type RustType = ServerConfigBuilder; } -impl BoxCastPtr for rustls_server_config_builder_wants_server_cert {} +impl BoxCastPtr for rustls_server_config_builder {} /// A server config that is done being constructed and is now read-only. /// Under the hood, this object corresponds to an Arc. @@ -99,11 +83,17 @@ impl rustls_server_config_builder { /// resulting rustls_server_config. This uses rustls safe default values /// for the cipher suites, key exchange groups and protocol versions. #[no_mangle] - pub extern "C" fn rustls_server_config_builder_new_with_safe_defaults( - ) -> *mut rustls_server_config_builder_wants_verifier { + pub extern "C" fn rustls_server_config_builder_new() -> *mut rustls_server_config_builder { ffi_panic_boundary! { - let builder = rustls::ServerConfig::builder().with_safe_defaults(); - BoxCastPtr::to_mut_ptr(builder) + let builder = ServerConfigBuilder { + base: rustls::ServerConfig::builder().with_safe_defaults(), + verifier: NoClientAuth::new(), + cert_resolver: None, + session_storage: None, + alpn_protocols: vec![], + ignore_client_order: None, + }; + BoxCastPtr::to_mut_ptr(builder) } } @@ -122,12 +112,12 @@ impl rustls_server_config_builder { /// `versions` will only be used during the call and the application retains /// ownership. `len` is the number of consecutive `ui16` pointed to by `versions`. #[no_mangle] - pub extern "C" fn rustls_server_config_builder_new( + pub extern "C" fn rustls_server_config_builder_new_custom( cipher_suites: *const *const rustls_supported_ciphersuite, cipher_suites_len: size_t, tls_versions: *const u16, tls_versions_len: size_t, - builder: *mut *mut rustls_server_config_builder_wants_verifier, + builder_out: *mut *mut rustls_server_config_builder, ) -> rustls_result { ffi_panic_boundary! { let cipher_suites: &[*const rustls_supported_ciphersuite] = try_slice!(cipher_suites, cipher_suites_len); @@ -152,46 +142,38 @@ impl rustls_server_config_builder { } let result = rustls::ServerConfig::builder().with_cipher_suites(&cs_vec).with_safe_default_kx_groups().with_protocol_versions(&versions); - let new = match result { + let base = match result { Ok(new) => new, Err(_) => return rustls_result::InvalidParameter, }; - BoxCastPtr::set_mut_ptr(builder, new); + let builder = ServerConfigBuilder { + base, + verifier: NoClientAuth::new(), + cert_resolver: None, + session_storage: None, + alpn_protocols: vec![], + ignore_client_order: None, + }; + BoxCastPtr::set_mut_ptr(builder_out, builder); rustls_result::Ok } } - /// For memory lifetime, see rustls_server_config_builder_new. - #[no_mangle] - pub extern "C" fn rustls_server_config_builder_with_no_client_auth( - wants_verifier: *mut rustls_server_config_builder_wants_verifier, - ) -> *mut rustls_server_config_builder { - ffi_panic_boundary! { - let prev = *try_box_from_ptr!(wants_verifier); - let config: ServerConfig = prev.with_no_client_auth().with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new())); - BoxCastPtr::to_mut_ptr(config) - } - } - /// Create a rustls_server_config_builder for TLS sessions that require /// valid client certificates. The passed rustls_client_cert_verifier may /// be used in several builders. /// If input is NULL, this will return NULL. /// For memory lifetime, see rustls_server_config_builder_new. #[no_mangle] - pub extern "C" fn rustls_server_config_builder_with_client_verifier( - wants_verifier: *mut rustls_server_config_builder_wants_verifier, + pub extern "C" fn rustls_server_config_builder_set_client_verifier( + config_builder: *mut rustls_server_config_builder, verifier: *const rustls_client_cert_verifier, - builder: *mut *mut rustls_server_config_builder_wants_server_cert, - ) -> rustls_result { + ) { ffi_panic_boundary! { + let mut config_builder = *try_box_from_ptr!(config_builder); let verifier: Arc = try_arc_from_ptr!(verifier); - - let prev = *try_box_from_ptr!(wants_verifier); - let new = prev.with_client_cert_verifier(verifier); - BoxCastPtr::set_mut_ptr(builder, new); - rustls_result::Ok + config_builder.verifier = verifier; } } @@ -201,15 +183,15 @@ impl rustls_server_config_builder { /// If input is NULL, this will return NULL. /// For memory lifetime, see rustls_server_config_builder_new. #[no_mangle] - pub extern "C" fn rustls_server_config_builder_with_client_verifier_optional( + pub extern "C" fn rustls_server_config_builder_set_client_verifier_optional( + config_builder: *mut rustls_server_config_builder, verifier: *const rustls_client_cert_verifier_optional, - ) -> *mut rustls_server_config_builder { + ) { ffi_panic_boundary! { + let mut config_builder = *try_box_from_ptr!(config_builder); let verifier: Arc = try_arc_from_ptr!(verifier); - let builder = rustls::ServerConfig::builder().with_safe_defaults(); - let config: ServerConfig = builder.with_client_cert_verifier(verifier).with_cert_resolver(Arc::new(rustls::server::ResolvesServerCertUsingSni::new())); - BoxCastPtr::to_mut_ptr(config) + config_builder.verifier = verifier; } } @@ -225,19 +207,6 @@ impl rustls_server_config_builder { } } - /// Create a rustls_server_config_builder from an existing rustls_server_config. The - /// builder will be used to create a new, separate config that starts with the settings - /// from the supplied configuration. - #[no_mangle] - pub extern "C" fn rustls_server_config_builder_from_config( - config: *const rustls_server_config, - ) -> *mut rustls_server_config_builder { - ffi_panic_boundary! { - let config: &ServerConfig = try_ref_from_ptr!(config); - BoxCastPtr::to_mut_ptr(config.clone()) - } - } - /// With `ignore` != 0, the server will ignore the client ordering of cipher /// suites, aka preference, during handshake and respect its own ordering /// as configured. @@ -248,8 +217,8 @@ impl rustls_server_config_builder { ignore: bool, ) -> rustls_result { ffi_panic_boundary! { - let config: &mut ServerConfig = try_mut_from_ptr!(builder); - config.ignore_client_order = ignore; + let config: &mut ServerConfigBuilder = try_mut_from_ptr!(builder); + config.ignore_client_order = Some(ignore); rustls_result::Ok } } @@ -271,7 +240,7 @@ impl rustls_server_config_builder { len: size_t, ) -> rustls_result { ffi_panic_boundary! { - let config: &mut ServerConfig = try_mut_from_ptr!(builder); + let config: &mut ServerConfigBuilder = try_mut_from_ptr!(builder); let protocols: &[rustls_slice_bytes] = try_slice!(protocols, len); let mut vv: Vec> = Vec::new(); @@ -303,14 +272,14 @@ impl rustls_server_config_builder { certified_keys_len: size_t, ) -> rustls_result { ffi_panic_boundary! { - let config: &mut ServerConfig = try_mut_from_ptr!(builder); + let builder: &mut ServerConfigBuilder = try_mut_from_ptr!(builder); let keys_ptrs: &[*const rustls_certified_key] = try_slice!(certified_keys, certified_keys_len); let mut keys: Vec> = Vec::new(); for &key_ptr in keys_ptrs { let certified_key: Arc = try_arc_from_ptr!(key_ptr); keys.push(certified_key); } - config.cert_resolver = Arc::new(ResolvesServerCertFromChoices::new(&keys)); + builder.cert_resolver = Some(Arc::new(ResolvesServerCertFromChoices::new(&keys))); rustls_result::Ok } } @@ -322,8 +291,21 @@ impl rustls_server_config_builder { builder: *mut rustls_server_config_builder, ) -> *const rustls_server_config { ffi_panic_boundary! { - let b = try_box_from_ptr!(builder); - ArcCastPtr::to_const_ptr(*b) + let builder = try_box_from_ptr!(builder); + let base = builder.base.with_client_cert_verifier(builder.verifier); + let mut config = if let Some(r) = builder.cert_resolver { + base.with_cert_resolver(r) + } else { + return null(); + }; + if let Some(ss) = builder.session_storage { + config.session_storage = ss; + } + config.alpn_protocols = builder.alpn_protocols; + if let Some(ignore_client_order) = builder.ignore_client_order { + config.ignore_client_order = ignore_client_order; + } + ArcCastPtr::to_const_ptr(config) } } } @@ -586,10 +568,10 @@ impl rustls_server_config_builder { Some(cb) => cb, None => return rustls_result::NullParameter, }; - let config: &mut ServerConfig = try_mut_from_ptr!(builder); - config.cert_resolver = Arc::new(ClientHelloResolver::new( + let builder: &mut ServerConfigBuilder = try_mut_from_ptr!(builder); + builder.cert_resolver = Some(Arc::new(ClientHelloResolver::new( callback - )); + ))); rustls_result::Ok } } @@ -685,10 +667,10 @@ impl rustls_server_config_builder { Some(cb) => cb, None => return rustls_result::NullParameter, }; - let config: &mut ServerConfig = try_mut_from_ptr!(builder); - config.session_storage = Arc::new(SessionStoreBroker::new( + let builder: &mut ServerConfigBuilder = try_mut_from_ptr!(builder); + builder.session_storage = Some(Arc::new(SessionStoreBroker::new( get_cb, put_cb - )); + ))); rustls_result::Ok } } diff --git a/tests/client.c b/tests/client.c index 00918c62..0e420a56 100644 --- a/tests/client.c +++ b/tests/client.c @@ -440,9 +440,8 @@ main(int argc, const char **argv) const char *port = argv[2]; const char *path = argv[3]; - struct rustls_client_config_builder_wants_verifier *config_builder = - rustls_client_config_builder_new_with_safe_defaults(); - struct rustls_client_config_builder *config_builder2 = NULL; + struct rustls_client_config_builder *config_builder = + rustls_client_config_builder_new(); const struct rustls_client_config *client_config = NULL; struct rustls_slice_bytes alpn_http11; @@ -457,22 +456,22 @@ main(int argc, const char **argv) if(getenv("CA_FILE")) { result = rustls_client_config_builder_load_roots_from_file( - config_builder, getenv("CA_FILE"), &config_builder2); + config_builder, getenv("CA_FILE")); if(result != RUSTLS_RESULT_OK) { print_error("loading trusted certificates", result); goto cleanup; } } else if(getenv("NO_CHECK_CERTIFICATE")) { rustls_client_config_builder_dangerous_set_certificate_verifier( - config_builder, verify, &config_builder2); + config_builder, verify); } else { fprintf(stderr, "must set either CA_FILE or NO_CHECK_CERTIFICATE env var\n"); goto cleanup; } - rustls_client_config_builder_set_alpn_protocols(config_builder2, &alpn_http11, 1); + rustls_client_config_builder_set_alpn_protocols(config_builder, &alpn_http11, 1); - client_config = rustls_client_config_builder_build(config_builder2); + client_config = rustls_client_config_builder_build(config_builder); int i; for(i = 0; i < 3; i++) { diff --git a/tests/server.c b/tests/server.c index ee2daba6..ad4aff79 100644 --- a/tests/server.c +++ b/tests/server.c @@ -299,17 +299,11 @@ main(int argc, const char **argv) int ret = 1; int result = 1; int sockfd = 0; - struct rustls_server_config_builder_wants_verifier *config_builder = - rustls_server_config_builder_new_with_safe_defaults(); - struct rustls_server_config_builder *config_builder2 = NULL; + struct rustls_server_config_builder *config_builder = + rustls_server_config_builder_new(); const struct rustls_server_config *server_config = NULL; struct rustls_connection *rconn = NULL; - config_builder2 = rustls_server_config_builder_with_no_client_auth(config_builder); - if(config_builder2 == NULL) { - goto cleanup; - } - if(argc <= 2) { fprintf(stderr, "usage: %s cert.pem key.pem\n\n" @@ -325,8 +319,8 @@ main(int argc, const char **argv) } rustls_server_config_builder_set_certified_keys( - config_builder2, &certified_key, 1); - server_config = rustls_server_config_builder_build(config_builder2); + config_builder, &certified_key, 1); + server_config = rustls_server_config_builder_build(config_builder); #ifdef _WIN32 WSADATA wsa;