1 use crate::builder::{ConfigBuilder, WantsCipherSuites}; 2 use crate::conn::{CommonState, ConnectionCommon, Protocol}; 3 use crate::error::Error; 4 use crate::keylog::KeyLog; 5 use crate::kx::SupportedKxGroup; 6 #[cfg(feature = "logging")] 7 use crate::log::trace; 8 #[cfg(feature = "quic")] 9 use crate::msgs::enums::AlertDescription; 10 use crate::msgs::enums::CipherSuite; 11 use crate::msgs::enums::ProtocolVersion; 12 use crate::msgs::enums::SignatureScheme; 13 use crate::msgs::handshake::ClientExtension; 14 use crate::sign; 15 use crate::suites::SupportedCipherSuite; 16 use crate::verify; 17 use crate::versions; 18 19 use super::hs; 20 #[cfg(feature = "quic")] 21 use crate::quic; 22 23 use std::convert::TryFrom; 24 use std::error::Error as StdError; 25 use std::marker::PhantomData; 26 use std::ops::{Deref, DerefMut}; 27 use std::sync::Arc; 28 use std::{fmt, io, mem}; 29 30 /// A trait for the ability to store client session data. 31 /// The keys and values are opaque. 32 /// 33 /// Both the keys and values should be treated as 34 /// **highly sensitive data**, containing enough key material 35 /// to break all security of the corresponding session. 36 /// 37 /// `put` is a mutating operation; this isn't expressed 38 /// in the type system to allow implementations freedom in 39 /// how to achieve interior mutability. `Mutex` is a common 40 /// choice. 41 pub trait StoresClientSessions: Send + Sync { 42 /// Stores a new `value` for `key`. Returns `true` 43 /// if the value was stored. 44 fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool; 45 46 /// Returns the latest value for `key`. Returns `None` 47 /// if there's no such value. 48 fn get(&self, key: &[u8]) -> Option<Vec<u8>>; 49 } 50 51 /// A trait for the ability to choose a certificate chain and 52 /// private key for the purposes of client authentication. 53 pub trait ResolvesClientCert: Send + Sync { 54 /// With the server-supplied acceptable issuers in `acceptable_issuers`, 55 /// the server's supported signature schemes in `sigschemes`, 56 /// return a certificate chain and signing key to authenticate. 57 /// 58 /// `acceptable_issuers` is undecoded and unverified by the rustls 59 /// library, but it should be expected to contain a DER encodings 60 /// of X501 NAMEs. 61 /// 62 /// Return None to continue the handshake without any client 63 /// authentication. The server may reject the handshake later 64 /// if it requires authentication. 65 fn resolve( 66 &self, 67 acceptable_issuers: &[&[u8]], 68 sigschemes: &[SignatureScheme], 69 ) -> Option<Arc<sign::CertifiedKey>>; 70 71 /// Return true if any certificates at all are available. 72 fn has_certs(&self) -> bool; 73 } 74 75 /// Common configuration for (typically) all connections made by 76 /// a program. 77 /// 78 /// Making one of these can be expensive, and should be 79 /// once per process rather than once per connection. 80 /// 81 /// These must be created via the [`ClientConfig::builder()`] function. 82 /// 83 /// # Defaults 84 /// 85 /// * [`ClientConfig::max_fragment_size`]: the default is `None`: TLS packets are not fragmented to a specific size. 86 /// * [`ClientConfig::session_storage`]: the default stores 256 sessions in memory. 87 /// * [`ClientConfig::alpn_protocols`]: the default is empty -- no ALPN protocol is negotiated. 88 /// * [`ClientConfig::key_log`]: key material is not logged. 89 #[derive(Clone)] 90 pub struct ClientConfig { 91 /// List of ciphersuites, in preference order. 92 pub(super) cipher_suites: Vec<SupportedCipherSuite>, 93 94 /// List of supported key exchange algorithms, in preference order -- the 95 /// first element is the highest priority. 96 /// 97 /// The first element in this list is the _default key share algorithm_, 98 /// and in TLS1.3 a key share for it is sent in the client hello. 99 pub(super) kx_groups: Vec<&'static SupportedKxGroup>, 100 101 /// Which ALPN protocols we include in our client hello. 102 /// If empty, no ALPN extension is sent. 103 pub alpn_protocols: Vec<Vec<u8>>, 104 105 /// How we store session data or tickets. 106 pub session_storage: Arc<dyn StoresClientSessions>, 107 108 /// The maximum size of TLS message we'll emit. If None, we don't limit TLS 109 /// message lengths except to the 2**16 limit specified in the standard. 110 /// 111 /// rustls enforces an arbitrary minimum of 32 bytes for this field. 112 /// Out of range values are reported as errors from ClientConnection::new. 113 /// 114 /// Setting this value to the TCP MSS may improve latency for stream-y workloads. 115 pub max_fragment_size: Option<usize>, 116 117 /// How to decide what client auth certificate/keys to use. 118 pub client_auth_cert_resolver: Arc<dyn ResolvesClientCert>, 119 120 /// Whether to support RFC5077 tickets. You must provide a working 121 /// `session_storage` member for this to have any meaningful 122 /// effect. 123 /// 124 /// The default is true. 125 pub enable_tickets: bool, 126 127 /// Supported versions, in no particular order. The default 128 /// is all supported versions. 129 pub(super) versions: versions::EnabledVersions, 130 131 /// Whether to send the Server Name Indication (SNI) extension 132 /// during the client handshake. 133 /// 134 /// The default is true. 135 pub enable_sni: bool, 136 137 /// How to verify the server certificate chain. 138 pub(super) verifier: Arc<dyn verify::ServerCertVerifier>, 139 140 /// How to output key material for debugging. The default 141 /// does nothing. 142 pub key_log: Arc<dyn KeyLog>, 143 144 /// Whether to send data on the first flight ("early data") in 145 /// TLS 1.3 handshakes. 146 /// 147 /// The default is false. 148 pub enable_early_data: bool, 149 } 150 151 impl ClientConfig { 152 /// Create a builder to build up the client configuration. 153 /// 154 /// For more information, see the [`ConfigBuilder`] documentation. 155 pub fn builder() -> ConfigBuilder<Self, WantsCipherSuites> { 156 ConfigBuilder { 157 state: WantsCipherSuites(()), 158 side: PhantomData::default(), 159 } 160 } 161 162 #[doc(hidden)] 163 /// We support a given TLS version if it's quoted in the configured 164 /// versions *and* at least one ciphersuite for this version is 165 /// also configured. 166 pub fn supports_version(&self, v: ProtocolVersion) -> bool { 167 self.versions.contains(v) 168 && self 169 .cipher_suites 170 .iter() 171 .any(|cs| cs.version().version == v) 172 } 173 174 /// Access configuration options whose use is dangerous and requires 175 /// extra care. 176 #[cfg(feature = "dangerous_configuration")] 177 pub fn dangerous(&mut self) -> danger::DangerousClientConfig { 178 danger::DangerousClientConfig { cfg: self } 179 } 180 181 pub(super) fn find_cipher_suite(&self, suite: CipherSuite) -> Option<SupportedCipherSuite> { 182 self.cipher_suites 183 .iter() 184 .copied() 185 .find(|&scs| scs.suite() == suite) 186 } 187 } 188 189 /// Encodes ways a client can know the expected name of the server. 190 /// 191 /// This currently covers knowing the DNS name of the server, but 192 /// will be extended in the future to knowing the IP address of the 193 /// server, as well as supporting privacy-preserving names for the 194 /// server ("ECH"). For this reason this enum is `non_exhaustive`. 195 /// 196 /// # Making one 197 /// 198 /// If you have a DNS name as a `&str`, this type implements `TryFrom<&str>`, 199 /// so you can do: 200 /// 201 /// ``` 202 /// # use std::convert::{TryInto, TryFrom}; 203 /// # use rustls::ServerName; 204 /// ServerName::try_from("example.com").expect("invalid DNS name"); 205 /// 206 /// // or, alternatively... 207 /// 208 /// let x = "example.com".try_into().expect("invalid DNS name"); 209 /// # let _: ServerName = x; 210 /// ``` 211 #[non_exhaustive] 212 #[derive(Debug, PartialEq, Clone)] 213 pub enum ServerName { 214 /// The server is identified by a DNS name. The name 215 /// is sent in the TLS Server Name Indication (SNI) 216 /// extension. 217 DnsName(verify::DnsName), 218 } 219 220 impl ServerName { 221 /// Return the name that should go in the SNI extension. 222 /// If [`None`] is returned, the SNI extension is not included 223 /// in the handshake. 224 pub(crate) fn for_sni(&self) -> Option<webpki::DnsNameRef> { 225 match self { 226 Self::DnsName(dns_name) => Some(dns_name.0.as_ref()), 227 } 228 } 229 230 /// Return a prefix-free, unique encoding for the name. 231 pub(crate) fn encode(&self) -> Vec<u8> { 232 enum UniqueTypeCode { 233 DnsName = 0x01, 234 } 235 236 let Self::DnsName(dns_name) = self; 237 let bytes = dns_name.0.as_ref(); 238 239 let mut r = Vec::with_capacity(2 + bytes.as_ref().len()); 240 r.push(UniqueTypeCode::DnsName as u8); 241 r.push(bytes.as_ref().len() as u8); 242 r.extend_from_slice(bytes.as_ref()); 243 244 r 245 } 246 } 247 248 /// Attempt to make a ServerName from a string by parsing 249 /// it as a DNS name. 250 impl TryFrom<&str> for ServerName { 251 type Error = InvalidDnsNameError; 252 fn try_from(s: &str) -> Result<Self, Self::Error> { 253 match webpki::DnsNameRef::try_from_ascii_str(s) { 254 Ok(dns) => Ok(Self::DnsName(verify::DnsName(dns.into()))), 255 Err(webpki::InvalidDnsNameError) => Err(InvalidDnsNameError), 256 } 257 } 258 } 259 260 /// The provided input could not be parsed because 261 /// it is not a syntactically-valid DNS Name. 262 #[derive(Debug)] 263 pub struct InvalidDnsNameError; 264 265 impl fmt::Display for InvalidDnsNameError { 266 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 267 f.write_str("invalid dns name") 268 } 269 } 270 271 impl StdError for InvalidDnsNameError {} 272 273 /// Container for unsafe APIs 274 #[cfg(feature = "dangerous_configuration")] 275 pub(super) mod danger { 276 use std::sync::Arc; 277 278 use super::verify::ServerCertVerifier; 279 use super::ClientConfig; 280 281 /// Accessor for dangerous configuration options. 282 pub struct DangerousClientConfig<'a> { 283 /// The underlying ClientConfig 284 pub cfg: &'a mut ClientConfig, 285 } 286 287 impl<'a> DangerousClientConfig<'a> { 288 /// Overrides the default `ServerCertVerifier` with something else. 289 pub fn set_certificate_verifier(&mut self, verifier: Arc<dyn ServerCertVerifier>) { 290 self.cfg.verifier = verifier; 291 } 292 } 293 } 294 295 #[derive(Debug, PartialEq)] 296 enum EarlyDataState { 297 Disabled, 298 Ready, 299 Accepted, 300 AcceptedFinished, 301 Rejected, 302 } 303 304 pub(super) struct EarlyData { 305 state: EarlyDataState, 306 left: usize, 307 } 308 309 impl EarlyData { 310 fn new() -> Self { 311 Self { 312 left: 0, 313 state: EarlyDataState::Disabled, 314 } 315 } 316 317 pub(super) fn is_enabled(&self) -> bool { 318 matches!(self.state, EarlyDataState::Ready | EarlyDataState::Accepted) 319 } 320 321 fn is_accepted(&self) -> bool { 322 matches!( 323 self.state, 324 EarlyDataState::Accepted | EarlyDataState::AcceptedFinished 325 ) 326 } 327 328 pub(super) fn enable(&mut self, max_data: usize) { 329 assert_eq!(self.state, EarlyDataState::Disabled); 330 self.state = EarlyDataState::Ready; 331 self.left = max_data; 332 } 333 334 pub(super) fn rejected(&mut self) { 335 trace!("EarlyData rejected"); 336 self.state = EarlyDataState::Rejected; 337 } 338 339 pub(super) fn accepted(&mut self) { 340 trace!("EarlyData accepted"); 341 assert_eq!(self.state, EarlyDataState::Ready); 342 self.state = EarlyDataState::Accepted; 343 } 344 345 pub(super) fn finished(&mut self) { 346 trace!("EarlyData finished"); 347 self.state = match self.state { 348 EarlyDataState::Accepted => EarlyDataState::AcceptedFinished, 349 _ => panic!("bad EarlyData state"), 350 } 351 } 352 353 fn check_write(&mut self, sz: usize) -> io::Result<usize> { 354 match self.state { 355 EarlyDataState::Disabled => unreachable!(), 356 EarlyDataState::Ready | EarlyDataState::Accepted => { 357 let take = if self.left < sz { 358 mem::replace(&mut self.left, 0) 359 } else { 360 self.left -= sz; 361 sz 362 }; 363 364 Ok(take) 365 } 366 EarlyDataState::Rejected | EarlyDataState::AcceptedFinished => { 367 Err(io::Error::from(io::ErrorKind::InvalidInput)) 368 } 369 } 370 } 371 372 fn bytes_left(&self) -> usize { 373 self.left 374 } 375 } 376 377 /// Stub that implements io::Write and dispatches to `write_early_data`. 378 pub struct WriteEarlyData<'a> { 379 sess: &'a mut ClientConnection, 380 } 381 382 impl<'a> WriteEarlyData<'a> { 383 fn new(sess: &'a mut ClientConnection) -> WriteEarlyData<'a> { 384 WriteEarlyData { sess } 385 } 386 387 /// How many bytes you may send. Writes will become short 388 /// once this reaches zero. 389 pub fn bytes_left(&self) -> usize { 390 self.sess 391 .inner 392 .data 393 .early_data 394 .bytes_left() 395 } 396 } 397 398 impl<'a> io::Write for WriteEarlyData<'a> { 399 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 400 self.sess.write_early_data(buf) 401 } 402 403 fn flush(&mut self) -> io::Result<()> { 404 Ok(()) 405 } 406 } 407 408 /// This represents a single TLS client connection. 409 pub struct ClientConnection { 410 inner: ConnectionCommon<ClientConnectionData>, 411 } 412 413 impl fmt::Debug for ClientConnection { 414 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 415 f.debug_struct("ClientConnection") 416 .finish() 417 } 418 } 419 420 impl ClientConnection { 421 /// Make a new ClientConnection. `config` controls how 422 /// we behave in the TLS protocol, `name` is the 423 /// name of the server we want to talk to. 424 pub fn new(config: Arc<ClientConfig>, name: ServerName) -> Result<Self, Error> { 425 Self::new_inner(config, name, Vec::new(), Protocol::Tcp) 426 } 427 428 fn new_inner( 429 config: Arc<ClientConfig>, 430 name: ServerName, 431 extra_exts: Vec<ClientExtension>, 432 proto: Protocol, 433 ) -> Result<Self, Error> { 434 let mut common_state = CommonState::new(config.max_fragment_size, true)?; 435 common_state.protocol = proto; 436 let mut data = ClientConnectionData::new(); 437 438 let mut cx = hs::ClientContext { 439 common: &mut common_state, 440 data: &mut data, 441 }; 442 443 let state = hs::start_handshake(name, extra_exts, config, &mut cx)?; 444 let inner = ConnectionCommon::new(state, data, common_state); 445 446 Ok(Self { inner }) 447 } 448 449 /// Returns an `io::Write` implementer you can write bytes to 450 /// to send TLS1.3 early data (a.k.a. "0-RTT data") to the server. 451 /// 452 /// This returns None in many circumstances when the capability to 453 /// send early data is not available, including but not limited to: 454 /// 455 /// - The server hasn't been talked to previously. 456 /// - The server does not support resumption. 457 /// - The server does not support early data. 458 /// - The resumption data for the server has expired. 459 /// 460 /// The server specifies a maximum amount of early data. You can 461 /// learn this limit through the returned object, and writes through 462 /// it will process only this many bytes. 463 /// 464 /// The server can choose not to accept any sent early data -- 465 /// in this case the data is lost but the connection continues. You 466 /// can tell this happened using `is_early_data_accepted`. 467 pub fn early_data(&mut self) -> Option<WriteEarlyData> { 468 if self.inner.data.early_data.is_enabled() { 469 Some(WriteEarlyData::new(self)) 470 } else { 471 None 472 } 473 } 474 475 /// Returns True if the server signalled it will process early data. 476 /// 477 /// If you sent early data and this returns false at the end of the 478 /// handshake then the server will not process the data. This 479 /// is not an error, but you may wish to resend the data. 480 pub fn is_early_data_accepted(&self) -> bool { 481 self.inner.data.early_data.is_accepted() 482 } 483 484 fn write_early_data(&mut self, data: &[u8]) -> io::Result<usize> { 485 self.inner 486 .data 487 .early_data 488 .check_write(data.len()) 489 .map(|sz| { 490 self.inner 491 .common_state 492 .send_early_plaintext(&data[..sz]) 493 }) 494 } 495 } 496 497 impl Deref for ClientConnection { 498 type Target = ConnectionCommon<ClientConnectionData>; 499 500 fn deref(&self) -> &Self::Target { 501 &self.inner 502 } 503 } 504 505 impl DerefMut for ClientConnection { 506 fn deref_mut(&mut self) -> &mut Self::Target { 507 &mut self.inner 508 } 509 } 510 511 #[doc(hidden)] 512 impl<'a> TryFrom<&'a mut crate::Connection> for &'a mut ClientConnection { 513 type Error = (); 514 515 fn try_from(value: &'a mut crate::Connection) -> Result<Self, Self::Error> { 516 use crate::Connection::*; 517 match value { 518 Client(conn) => Ok(conn), 519 Server(_) => Err(()), 520 } 521 } 522 } 523 524 impl From<ClientConnection> for crate::Connection { 525 fn from(conn: ClientConnection) -> Self { 526 Self::Client(conn) 527 } 528 } 529 530 /// State associated with a client connection. 531 pub struct ClientConnectionData { 532 pub(super) early_data: EarlyData, 533 pub(super) resumption_ciphersuite: Option<SupportedCipherSuite>, 534 } 535 536 impl ClientConnectionData { 537 fn new() -> Self { 538 Self { 539 early_data: EarlyData::new(), 540 resumption_ciphersuite: None, 541 } 542 } 543 } 544 545 impl crate::conn::SideData for ClientConnectionData {} 546 547 #[cfg(feature = "quic")] 548 impl quic::QuicExt for ClientConnection { 549 fn quic_transport_parameters(&self) -> Option<&[u8]> { 550 self.inner 551 .common_state 552 .quic 553 .params 554 .as_ref() 555 .map(|v| v.as_ref()) 556 } 557 558 fn zero_rtt_keys(&self) -> Option<quic::DirectionalKeys> { 559 Some(quic::DirectionalKeys::new( 560 self.inner 561 .data 562 .resumption_ciphersuite 563 .and_then(|suite| suite.tls13())?, 564 self.inner 565 .common_state 566 .quic 567 .early_secret 568 .as_ref()?, 569 )) 570 } 571 572 fn read_hs(&mut self, plaintext: &[u8]) -> Result<(), Error> { 573 self.inner.read_quic_hs(plaintext) 574 } 575 576 fn write_hs(&mut self, buf: &mut Vec<u8>) -> Option<quic::KeyChange> { 577 quic::write_hs(&mut self.inner.common_state, buf) 578 } 579 580 fn alert(&self) -> Option<AlertDescription> { 581 self.inner.common_state.quic.alert 582 } 583 } 584 585 /// Methods specific to QUIC client sessions 586 #[cfg(feature = "quic")] 587 pub trait ClientQuicExt { 588 /// Make a new QUIC ClientConnection. This differs from `ClientConnection::new()` 589 /// in that it takes an extra argument, `params`, which contains the 590 /// TLS-encoded transport parameters to send. 591 fn new_quic( 592 config: Arc<ClientConfig>, 593 quic_version: quic::Version, 594 name: ServerName, 595 params: Vec<u8>, 596 ) -> Result<ClientConnection, Error> { 597 if !config.supports_version(ProtocolVersion::TLSv1_3) { 598 return Err(Error::General( 599 "TLS 1.3 support is required for QUIC".into(), 600 )); 601 } 602 603 let ext = match quic_version { 604 quic::Version::V1Draft => ClientExtension::TransportParametersDraft(params), 605 quic::Version::V1 => ClientExtension::TransportParameters(params), 606 }; 607 608 ClientConnection::new_inner(config, name, vec![ext], Protocol::Quic) 609 } 610 } 611 612 #[cfg(feature = "quic")] 613 impl ClientQuicExt for ClientConnection {} 614