1 use crate::anchors; 2 use crate::builder::{ConfigBuilder, WantsVerifier}; 3 use crate::client::handy; 4 use crate::client::{ClientConfig, ResolvesClientCert}; 5 use crate::error::Error; 6 use crate::key; 7 use crate::keylog::NoKeyLog; 8 use crate::kx::SupportedKxGroup; 9 use crate::suites::SupportedCipherSuite; 10 use crate::verify::{self, CertificateTransparencyPolicy}; 11 use crate::versions; 12 13 use std::marker::PhantomData; 14 use std::sync::Arc; 15 use std::time::SystemTime; 16 17 impl ConfigBuilder<ClientConfig, WantsVerifier> { 18 /// Choose how to verify client certificates. with_root_certificates( self, root_store: anchors::RootCertStore, ) -> ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert>19 pub fn with_root_certificates( 20 self, 21 root_store: anchors::RootCertStore, 22 ) -> ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert> { 23 ConfigBuilder { 24 state: WantsTransparencyPolicyOrClientCert { 25 cipher_suites: self.state.cipher_suites, 26 kx_groups: self.state.kx_groups, 27 versions: self.state.versions, 28 root_store, 29 }, 30 side: PhantomData::default(), 31 } 32 } 33 34 #[cfg(feature = "dangerous_configuration")] 35 /// Set a custom certificate verifier. with_custom_certificate_verifier( self, verifier: Arc<dyn verify::ServerCertVerifier>, ) -> ConfigBuilder<ClientConfig, WantsClientCert>36 pub fn with_custom_certificate_verifier( 37 self, 38 verifier: Arc<dyn verify::ServerCertVerifier>, 39 ) -> ConfigBuilder<ClientConfig, WantsClientCert> { 40 ConfigBuilder { 41 state: WantsClientCert { 42 cipher_suites: self.state.cipher_suites, 43 kx_groups: self.state.kx_groups, 44 versions: self.state.versions, 45 verifier, 46 }, 47 side: PhantomData::default(), 48 } 49 } 50 } 51 52 /// A config builder state where the caller needs to supply a certificate transparency policy or 53 /// client certificate resolver. 54 /// 55 /// In this state, the caller can optionally enable certificate transparency, or ignore CT and 56 /// invoke one of the methods related to client certificates (as in the [`WantsClientCert`] state). 57 /// 58 /// For more information, see the [`ConfigBuilder`] documentation. 59 pub struct WantsTransparencyPolicyOrClientCert { 60 cipher_suites: Vec<SupportedCipherSuite>, 61 kx_groups: Vec<&'static SupportedKxGroup>, 62 versions: versions::EnabledVersions, 63 root_store: anchors::RootCertStore, 64 } 65 66 impl ConfigBuilder<ClientConfig, WantsTransparencyPolicyOrClientCert> { 67 /// Set Certificate Transparency logs to use for server certificate validation. 68 /// 69 /// Because Certificate Transparency logs are sharded on a per-year basis and can be trusted or 70 /// distrusted relatively quickly, rustls stores a validation deadline. Server certificates will 71 /// be validated against the configured CT logs until the deadline expires. After the deadline, 72 /// certificates will no longer be validated, and a warning message will be logged. The deadline 73 /// may vary depending on how often you deploy builds with updated dependencies. with_certificate_transparency_logs( self, logs: &'static [&'static sct::Log], validation_deadline: SystemTime, ) -> ConfigBuilder<ClientConfig, WantsClientCert>74 pub fn with_certificate_transparency_logs( 75 self, 76 logs: &'static [&'static sct::Log], 77 validation_deadline: SystemTime, 78 ) -> ConfigBuilder<ClientConfig, WantsClientCert> { 79 self.with_logs(Some(CertificateTransparencyPolicy::new( 80 logs, 81 validation_deadline, 82 ))) 83 } 84 85 /// Sets a single certificate chain and matching private key for use 86 /// in client authentication. 87 /// 88 /// `cert_chain` is a vector of DER-encoded certificates. 89 /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key. 90 /// 91 /// This function fails if `key_der` is invalid. with_single_cert( self, cert_chain: Vec<key::Certificate>, key_der: key::PrivateKey, ) -> Result<ClientConfig, Error>92 pub fn with_single_cert( 93 self, 94 cert_chain: Vec<key::Certificate>, 95 key_der: key::PrivateKey, 96 ) -> Result<ClientConfig, Error> { 97 self.with_logs(None) 98 .with_single_cert(cert_chain, key_der) 99 } 100 101 /// Do not support client auth. with_no_client_auth(self) -> ClientConfig102 pub fn with_no_client_auth(self) -> ClientConfig { 103 self.with_logs(None) 104 .with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {})) 105 } 106 107 /// Sets a custom [`ResolvesClientCert`]. with_client_cert_resolver( self, client_auth_cert_resolver: Arc<dyn ResolvesClientCert>, ) -> ClientConfig108 pub fn with_client_cert_resolver( 109 self, 110 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>, 111 ) -> ClientConfig { 112 self.with_logs(None) 113 .with_client_cert_resolver(client_auth_cert_resolver) 114 } 115 with_logs( self, ct_policy: Option<CertificateTransparencyPolicy>, ) -> ConfigBuilder<ClientConfig, WantsClientCert>116 fn with_logs( 117 self, 118 ct_policy: Option<CertificateTransparencyPolicy>, 119 ) -> ConfigBuilder<ClientConfig, WantsClientCert> { 120 ConfigBuilder { 121 state: WantsClientCert { 122 cipher_suites: self.state.cipher_suites, 123 kx_groups: self.state.kx_groups, 124 versions: self.state.versions, 125 verifier: Arc::new(verify::WebPkiVerifier::new( 126 self.state.root_store, 127 ct_policy, 128 )), 129 }, 130 side: PhantomData, 131 } 132 } 133 } 134 135 /// A config builder state where the caller needs to supply whether and how to provide a client 136 /// certificate. 137 /// 138 /// For more information, see the [`ConfigBuilder`] documentation. 139 pub struct WantsClientCert { 140 cipher_suites: Vec<SupportedCipherSuite>, 141 kx_groups: Vec<&'static SupportedKxGroup>, 142 versions: versions::EnabledVersions, 143 verifier: Arc<dyn verify::ServerCertVerifier>, 144 } 145 146 impl ConfigBuilder<ClientConfig, WantsClientCert> { 147 /// Sets a single certificate chain and matching private key for use 148 /// in client authentication. 149 /// 150 /// `cert_chain` is a vector of DER-encoded certificates. 151 /// `key_der` is a DER-encoded RSA, ECDSA, or Ed25519 private key. 152 /// 153 /// This function fails if `key_der` is invalid. with_single_cert( self, cert_chain: Vec<key::Certificate>, key_der: key::PrivateKey, ) -> Result<ClientConfig, Error>154 pub fn with_single_cert( 155 self, 156 cert_chain: Vec<key::Certificate>, 157 key_der: key::PrivateKey, 158 ) -> Result<ClientConfig, Error> { 159 let resolver = handy::AlwaysResolvesClientCert::new(cert_chain, &key_der)?; 160 Ok(self.with_client_cert_resolver(Arc::new(resolver))) 161 } 162 163 /// Do not support client auth. with_no_client_auth(self) -> ClientConfig164 pub fn with_no_client_auth(self) -> ClientConfig { 165 self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {})) 166 } 167 168 /// Sets a custom [`ResolvesClientCert`]. with_client_cert_resolver( self, client_auth_cert_resolver: Arc<dyn ResolvesClientCert>, ) -> ClientConfig169 pub fn with_client_cert_resolver( 170 self, 171 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>, 172 ) -> ClientConfig { 173 ClientConfig { 174 cipher_suites: self.state.cipher_suites, 175 kx_groups: self.state.kx_groups, 176 alpn_protocols: Vec::new(), 177 session_storage: handy::ClientSessionMemoryCache::new(256), 178 max_fragment_size: None, 179 client_auth_cert_resolver, 180 enable_tickets: true, 181 versions: self.state.versions, 182 enable_sni: true, 183 verifier: self.state.verifier, 184 key_log: Arc::new(NoKeyLog {}), 185 enable_early_data: false, 186 } 187 } 188 } 189