1//! SSL/TLS support. 2//! 3//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle 4//! configuration of the OpenSSL primitives for you. 5//! 6//! # Examples 7//! 8//! To connect as a client to a remote server: 9//! 10//! ```no_run 11//! use openssl::ssl::{SslMethod, SslConnector}; 12//! use std::io::{Read, Write}; 13//! use std::net::TcpStream; 14//! 15//! let connector = SslConnector::builder(SslMethod::tls()).unwrap().build(); 16//! 17//! let stream = TcpStream::connect("google.com:443").unwrap(); 18//! let mut stream = connector.connect("google.com", stream).unwrap(); 19//! 20//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); 21//! let mut res = vec![]; 22//! stream.read_to_end(&mut res).unwrap(); 23//! println!("{}", String::from_utf8_lossy(&res)); 24//! ``` 25//! 26//! To accept connections as a server from remote clients: 27//! 28//! ```no_run 29//! use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; 30//! use std::net::{TcpListener, TcpStream}; 31//! use std::sync::Arc; 32//! use std::thread; 33//! 34//! 35//! let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); 36//! acceptor.set_private_key_file("key.pem", SslFiletype::PEM).unwrap(); 37//! acceptor.set_certificate_chain_file("certs.pem").unwrap(); 38//! acceptor.check_private_key().unwrap(); 39//! let acceptor = Arc::new(acceptor.build()); 40//! 41//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap(); 42//! 43//! fn handle_client(stream: SslStream<TcpStream>) { 44//! // ... 45//! } 46//! 47//! for stream in listener.incoming() { 48//! match stream { 49//! Ok(stream) => { 50//! let acceptor = acceptor.clone(); 51//! thread::spawn(move || { 52//! let stream = acceptor.accept(stream).unwrap(); 53//! handle_client(stream); 54//! }); 55//! } 56//! Err(e) => { /* connection failed */ } 57//! } 58//! } 59//! ``` 60use crate::dh::{Dh, DhRef}; 61#[cfg(all(ossl101, not(ossl110)))] 62use crate::ec::EcKey; 63use crate::ec::EcKeyRef; 64use crate::error::ErrorStack; 65use crate::ex_data::Index; 66#[cfg(ossl111)] 67use crate::hash::MessageDigest; 68#[cfg(any(ossl110, libressl270))] 69use crate::nid::Nid; 70use crate::pkey::{HasPrivate, PKeyRef, Params, Private}; 71use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef}; 72use crate::ssl::bio::BioMethod; 73use crate::ssl::callbacks::*; 74use crate::ssl::error::InnerError; 75use crate::stack::{Stack, StackRef, Stackable}; 76use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; 77use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef}; 78#[cfg(any(ossl102, libressl261))] 79use crate::x509::verify::X509VerifyParamRef; 80use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509}; 81use crate::{cvt, cvt_n, cvt_p, init}; 82use bitflags::bitflags; 83use cfg_if::cfg_if; 84use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; 85use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void}; 86use once_cell::sync::{Lazy, OnceCell}; 87use openssl_macros::corresponds; 88use std::any::TypeId; 89use std::cmp; 90use std::collections::HashMap; 91use std::ffi::{CStr, CString}; 92use std::fmt; 93use std::io; 94use std::io::prelude::*; 95use std::marker::PhantomData; 96use std::mem::{self, ManuallyDrop}; 97use std::ops::{Deref, DerefMut}; 98use std::panic::resume_unwind; 99use std::path::Path; 100use std::ptr; 101use std::slice; 102use std::str; 103use std::sync::{Arc, Mutex}; 104 105pub use crate::ssl::connector::{ 106 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder, 107}; 108pub use crate::ssl::error::{Error, ErrorCode, HandshakeError}; 109 110mod bio; 111mod callbacks; 112mod connector; 113mod error; 114#[cfg(test)] 115mod test; 116 117/// Returns the OpenSSL name of a cipher corresponding to an RFC-standard cipher name. 118/// 119/// If the cipher has no corresponding OpenSSL name, the string `(NONE)` is returned. 120/// 121/// Requires OpenSSL 1.1.1 or newer. 122#[corresponds(OPENSSL_cipher_name)] 123#[cfg(ossl111)] 124pub fn cipher_name(std_name: &str) -> &'static str { 125 unsafe { 126 ffi::init(); 127 128 let s = CString::new(std_name).unwrap(); 129 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr()); 130 CStr::from_ptr(ptr).to_str().unwrap() 131 } 132} 133 134cfg_if! { 135 if #[cfg(ossl300)] { 136 type SslOptionsRepr = u64; 137 } else if #[cfg(boringssl)] { 138 type SslOptionsRepr = u32; 139 } else { 140 type SslOptionsRepr = libc::c_ulong; 141 } 142} 143 144bitflags! { 145 /// Options controlling the behavior of an `SslContext`. 146 pub struct SslOptions: SslOptionsRepr { 147 /// Disables a countermeasure against an SSLv3/TLSv1.0 vulnerability affecting CBC ciphers. 148 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr; 149 150 /// A "reasonable default" set of options which enables compatibility flags. 151 #[cfg(not(boringssl))] 152 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr; 153 154 /// Do not query the MTU. 155 /// 156 /// Only affects DTLS connections. 157 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr; 158 159 /// Enables Cookie Exchange as described in [RFC 4347 Section 4.2.1]. 160 /// 161 /// Only affects DTLS connections. 162 /// 163 /// [RFC 4347 Section 4.2.1]: https://tools.ietf.org/html/rfc4347#section-4.2.1 164 #[cfg(not(boringssl))] 165 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr; 166 167 /// Disables the use of session tickets for session resumption. 168 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr; 169 170 /// Always start a new session when performing a renegotiation on the server side. 171 #[cfg(not(boringssl))] 172 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 173 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr; 174 175 /// Disables the use of TLS compression. 176 #[cfg(not(boringssl))] 177 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr; 178 179 /// Allow legacy insecure renegotiation with servers or clients that do not support secure 180 /// renegotiation. 181 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION = 182 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr; 183 184 /// Creates a new key for each session when using ECDHE. 185 /// 186 /// This is always enabled in OpenSSL 1.1.0. 187 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr; 188 189 /// Creates a new key for each session when using DHE. 190 /// 191 /// This is always enabled in OpenSSL 1.1.0. 192 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr; 193 194 /// Use the server's preferences rather than the client's when selecting a cipher. 195 /// 196 /// This has no effect on the client side. 197 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr; 198 199 /// Disables version rollback attach detection. 200 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr; 201 202 /// Disables the use of SSLv2. 203 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr; 204 205 /// Disables the use of SSLv3. 206 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr; 207 208 /// Disables the use of TLSv1.0. 209 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr; 210 211 /// Disables the use of TLSv1.1. 212 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr; 213 214 /// Disables the use of TLSv1.2. 215 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr; 216 217 /// Disables the use of TLSv1.3. 218 /// 219 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 220 #[cfg(any(boringssl, ossl111, libressl340))] 221 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr; 222 223 /// Disables the use of DTLSv1.0 224 /// 225 /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer. 226 #[cfg(any(boringssl, ossl102, ossl110, libressl332))] 227 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr; 228 229 /// Disables the use of DTLSv1.2. 230 /// 231 /// Requires OpenSSL 1.0.2 or LibreSSL 3.3.2 or newer. 232 #[cfg(any(boringssl, ossl102, ossl110, libressl332))] 233 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr; 234 235 /// Disables the use of all (D)TLS protocol versions. 236 /// 237 /// This can be used as a mask when whitelisting protocol versions. 238 /// 239 /// Requires OpenSSL 1.0.2 or newer. 240 /// 241 /// # Examples 242 /// 243 /// Only support TLSv1.2: 244 /// 245 /// ```rust 246 /// use openssl::ssl::SslOptions; 247 /// 248 /// let options = SslOptions::NO_SSL_MASK & !SslOptions::NO_TLSV1_2; 249 /// ``` 250 #[cfg(any(ossl102, ossl110))] 251 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr; 252 253 /// Disallow all renegotiation in TLSv1.2 and earlier. 254 /// 255 /// Requires OpenSSL 1.1.0h or newer. 256 #[cfg(any(boringssl, ossl110h))] 257 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr; 258 259 /// Enable TLSv1.3 Compatibility mode. 260 /// 261 /// Requires OpenSSL 1.1.1 or newer. This is on by default in 1.1.1, but a future version 262 /// may have this disabled by default. 263 #[cfg(ossl111)] 264 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr; 265 266 /// Prioritize ChaCha ciphers when preferred by clients. 267 /// 268 /// Temporarily reprioritize ChaCha20-Poly1305 ciphers to the top of the server cipher list 269 /// if a ChaCha20-Poly1305 cipher is at the top of the client cipher list. This helps those 270 /// clients (e.g. mobile) use ChaCha20-Poly1305 if that cipher is anywhere in the server 271 /// cipher list; but still allows other clients to use AES and other ciphers. 272 /// 273 /// Requires enable [`SslOptions::CIPHER_SERVER_PREFERENCE`]. 274 /// Requires OpenSSL 1.1.1 or newer. 275 /// 276 /// [`SslOptions::CIPHER_SERVER_PREFERENCE`]: struct.SslOptions.html#associatedconstant.CIPHER_SERVER_PREFERENCE 277 #[cfg(ossl111)] 278 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr; 279 } 280} 281 282bitflags! { 283 /// Options controlling the behavior of an `SslContext`. 284 pub struct SslMode: SslBitType { 285 /// Enables "short writes". 286 /// 287 /// Normally, a write in OpenSSL will always write out all of the requested data, even if it 288 /// requires more than one TLS record or write to the underlying stream. This option will 289 /// cause a write to return after writing a single TLS record instead. 290 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE; 291 292 /// Disables a check that the data buffer has not moved between calls when operating in a 293 /// non-blocking context. 294 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER; 295 296 /// Enables automatic retries after TLS session events such as renegotiations or heartbeats. 297 /// 298 /// By default, OpenSSL will return a `WantRead` error after a renegotiation or heartbeat. 299 /// This option will cause OpenSSL to automatically continue processing the requested 300 /// operation instead. 301 /// 302 /// Note that `SslStream::read` and `SslStream::write` will automatically retry regardless 303 /// of the state of this option. It only affects `SslStream::ssl_read` and 304 /// `SslStream::ssl_write`. 305 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY; 306 307 /// Disables automatic chain building when verifying a peer's certificate. 308 /// 309 /// TLS peers are responsible for sending the entire certificate chain from the leaf to a 310 /// trusted root, but some will incorrectly not do so. OpenSSL will try to build the chain 311 /// out of certificates it knows of, and this option will disable that behavior. 312 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN; 313 314 /// Release memory buffers when the session does not need them. 315 /// 316 /// This saves ~34 KiB of memory for idle streams. 317 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS; 318 319 /// Sends the fake `TLS_FALLBACK_SCSV` cipher suite in the ClientHello message of a 320 /// handshake. 321 /// 322 /// This should only be enabled if a client has failed to connect to a server which 323 /// attempted to downgrade the protocol version of the session. 324 /// 325 /// Do not use this unless you know what you're doing! 326 #[cfg(not(libressl))] 327 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV; 328 } 329} 330 331/// A type specifying the kind of protocol an `SslContext` will speak. 332#[derive(Copy, Clone)] 333pub struct SslMethod(*const ffi::SSL_METHOD); 334 335impl SslMethod { 336 /// Support all versions of the TLS protocol. 337 #[corresponds(TLS_method)] 338 pub fn tls() -> SslMethod { 339 unsafe { SslMethod(TLS_method()) } 340 } 341 342 /// Support all versions of the DTLS protocol. 343 #[corresponds(DTLS_method)] 344 pub fn dtls() -> SslMethod { 345 unsafe { SslMethod(DTLS_method()) } 346 } 347 348 /// Support all versions of the TLS protocol, explicitly as a client. 349 #[corresponds(TLS_client_method)] 350 pub fn tls_client() -> SslMethod { 351 unsafe { SslMethod(TLS_client_method()) } 352 } 353 354 /// Support all versions of the TLS protocol, explicitly as a server. 355 #[corresponds(TLS_server_method)] 356 pub fn tls_server() -> SslMethod { 357 unsafe { SslMethod(TLS_server_method()) } 358 } 359 360 /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value. 361 /// 362 /// # Safety 363 /// 364 /// The caller must ensure the pointer is valid. 365 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod { 366 SslMethod(ptr) 367 } 368 369 /// Returns a pointer to the underlying OpenSSL value. 370 #[allow(clippy::trivially_copy_pass_by_ref)] 371 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD { 372 self.0 373 } 374} 375 376unsafe impl Sync for SslMethod {} 377unsafe impl Send for SslMethod {} 378 379bitflags! { 380 /// Options controlling the behavior of certificate verification. 381 pub struct SslVerifyMode: i32 { 382 /// Verifies that the peer's certificate is trusted. 383 /// 384 /// On the server side, this will cause OpenSSL to request a certificate from the client. 385 const PEER = ffi::SSL_VERIFY_PEER; 386 387 /// Disables verification of the peer's certificate. 388 /// 389 /// On the server side, this will cause OpenSSL to not request a certificate from the 390 /// client. On the client side, the certificate will be checked for validity, but the 391 /// negotiation will continue regardless of the result of that check. 392 const NONE = ffi::SSL_VERIFY_NONE; 393 394 /// On the server side, abort the handshake if the client did not send a certificate. 395 /// 396 /// This should be paired with `SSL_VERIFY_PEER`. It has no effect on the client side. 397 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT; 398 } 399} 400 401#[cfg(boringssl)] 402type SslBitType = c_int; 403#[cfg(not(boringssl))] 404type SslBitType = c_long; 405 406#[cfg(boringssl)] 407type SslTimeTy = u64; 408#[cfg(not(boringssl))] 409type SslTimeTy = c_long; 410 411bitflags! { 412 /// Options controlling the behavior of session caching. 413 pub struct SslSessionCacheMode: SslBitType { 414 /// No session caching for the client or server takes place. 415 const OFF = ffi::SSL_SESS_CACHE_OFF; 416 417 /// Enable session caching on the client side. 418 /// 419 /// OpenSSL has no way of identifying the proper session to reuse automatically, so the 420 /// application is responsible for setting it explicitly via [`SslRef::set_session`]. 421 /// 422 /// [`SslRef::set_session`]: struct.SslRef.html#method.set_session 423 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT; 424 425 /// Enable session caching on the server side. 426 /// 427 /// This is the default mode. 428 const SERVER = ffi::SSL_SESS_CACHE_SERVER; 429 430 /// Enable session caching on both the client and server side. 431 const BOTH = ffi::SSL_SESS_CACHE_BOTH; 432 433 /// Disable automatic removal of expired sessions from the session cache. 434 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR; 435 436 /// Disable use of the internal session cache for session lookups. 437 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; 438 439 /// Disable use of the internal session cache for session storage. 440 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE; 441 442 /// Disable use of the internal session cache for storage and lookup. 443 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL; 444 } 445} 446 447#[cfg(ossl111)] 448bitflags! { 449 /// Which messages and under which conditions an extension should be added or expected. 450 pub struct ExtensionContext: c_uint { 451 /// This extension is only allowed in TLS 452 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY; 453 /// This extension is only allowed in DTLS 454 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY; 455 /// Some extensions may be allowed in DTLS but we don't implement them for it 456 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY; 457 /// Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is 458 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED; 459 /// Extension is only defined for TLS1.2 and below 460 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY; 461 /// Extension is only defined for TLS1.3 and above 462 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY; 463 /// Ignore this extension during parsing if we are resuming 464 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION; 465 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO; 466 /// Really means TLS1.2 or below 467 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO; 468 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO; 469 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS; 470 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST; 471 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE; 472 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET; 473 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST; 474 } 475} 476 477/// An identifier of the format of a certificate or key file. 478#[derive(Copy, Clone)] 479pub struct SslFiletype(c_int); 480 481impl SslFiletype { 482 /// The PEM format. 483 /// 484 /// This corresponds to `SSL_FILETYPE_PEM`. 485 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM); 486 487 /// The ASN1 format. 488 /// 489 /// This corresponds to `SSL_FILETYPE_ASN1`. 490 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1); 491 492 /// Constructs an `SslFiletype` from a raw OpenSSL value. 493 pub fn from_raw(raw: c_int) -> SslFiletype { 494 SslFiletype(raw) 495 } 496 497 /// Returns the raw OpenSSL value represented by this type. 498 #[allow(clippy::trivially_copy_pass_by_ref)] 499 pub fn as_raw(&self) -> c_int { 500 self.0 501 } 502} 503 504/// An identifier of a certificate status type. 505#[derive(Copy, Clone)] 506pub struct StatusType(c_int); 507 508impl StatusType { 509 /// An OSCP status. 510 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp); 511 512 /// Constructs a `StatusType` from a raw OpenSSL value. 513 pub fn from_raw(raw: c_int) -> StatusType { 514 StatusType(raw) 515 } 516 517 /// Returns the raw OpenSSL value represented by this type. 518 #[allow(clippy::trivially_copy_pass_by_ref)] 519 pub fn as_raw(&self) -> c_int { 520 self.0 521 } 522} 523 524/// An identifier of a session name type. 525#[derive(Copy, Clone)] 526pub struct NameType(c_int); 527 528impl NameType { 529 /// A host name. 530 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name); 531 532 /// Constructs a `StatusType` from a raw OpenSSL value. 533 pub fn from_raw(raw: c_int) -> StatusType { 534 StatusType(raw) 535 } 536 537 /// Returns the raw OpenSSL value represented by this type. 538 #[allow(clippy::trivially_copy_pass_by_ref)] 539 pub fn as_raw(&self) -> c_int { 540 self.0 541 } 542} 543 544static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new())); 545static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new())); 546static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new(); 547 548fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> { 549 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index) 550} 551 552unsafe extern "C" fn free_data_box<T>( 553 _parent: *mut c_void, 554 ptr: *mut c_void, 555 _ad: *mut ffi::CRYPTO_EX_DATA, 556 _idx: c_int, 557 _argl: c_long, 558 _argp: *mut c_void, 559) { 560 if !ptr.is_null() { 561 let _ = Box::<T>::from_raw(ptr as *mut T); 562 } 563} 564 565/// An error returned from the SNI callback. 566#[derive(Debug, Copy, Clone, PartialEq, Eq)] 567pub struct SniError(c_int); 568 569impl SniError { 570 /// Abort the handshake with a fatal alert. 571 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); 572 573 /// Send a warning alert to the client and continue the handshake. 574 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING); 575 576 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK); 577} 578 579/// An SSL/TLS alert. 580#[derive(Debug, Copy, Clone, PartialEq, Eq)] 581pub struct SslAlert(c_int); 582 583impl SslAlert { 584 /// Alert 112 - `unrecognized_name`. 585 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME); 586 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER); 587 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR); 588} 589 590/// An error returned from an ALPN selection callback. 591/// 592/// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 593#[cfg(any(ossl102, libressl261))] 594#[derive(Debug, Copy, Clone, PartialEq, Eq)] 595pub struct AlpnError(c_int); 596 597#[cfg(any(ossl102, libressl261))] 598impl AlpnError { 599 /// Terminate the handshake with a fatal alert. 600 /// 601 /// Requires OpenSSL 1.1.0 or newer. 602 #[cfg(ossl110)] 603 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL); 604 605 /// Do not select a protocol, but continue the handshake. 606 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK); 607} 608 609/// The result of a client hello callback. 610/// 611/// Requires OpenSSL 1.1.1 or newer. 612#[cfg(ossl111)] 613#[derive(Debug, Copy, Clone, PartialEq, Eq)] 614pub struct ClientHelloResponse(c_int); 615 616#[cfg(ossl111)] 617impl ClientHelloResponse { 618 /// Continue the handshake. 619 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS); 620 621 /// Return from the handshake with an `ErrorCode::WANT_CLIENT_HELLO_CB` error. 622 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY); 623} 624 625/// An SSL/TLS protocol version. 626#[derive(Debug, Copy, Clone, PartialEq, Eq)] 627pub struct SslVersion(c_int); 628 629impl SslVersion { 630 /// SSLv3 631 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION); 632 633 /// TLSv1.0 634 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION); 635 636 /// TLSv1.1 637 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION); 638 639 /// TLSv1.2 640 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION); 641 642 /// TLSv1.3 643 /// 644 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 645 #[cfg(any(ossl111, libressl340))] 646 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION); 647 648 /// DTLSv1.0 649 /// 650 /// DTLS 1.0 corresponds to TLS 1.1. 651 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION); 652 653 /// DTLSv1.2 654 /// 655 /// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1. 656 #[cfg(any(ossl102, libressl332))] 657 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION); 658} 659 660cfg_if! { 661 if #[cfg(boringssl)] { 662 type SslCacheTy = i64; 663 type SslCacheSize = libc::c_ulong; 664 type MtuTy = u32; 665 type SizeTy = usize; 666 } else { 667 type SslCacheTy = i64; 668 type SslCacheSize = c_long; 669 type MtuTy = c_long; 670 type SizeTy = u32; 671 } 672} 673 674/// A standard implementation of protocol selection for Application Layer Protocol Negotiation 675/// (ALPN). 676/// 677/// `server` should contain the server's list of supported protocols and `client` the client's. They 678/// must both be in the ALPN wire format. See the documentation for 679/// [`SslContextBuilder::set_alpn_protos`] for details. 680/// 681/// It will select the first protocol supported by the server which is also supported by the client. 682/// 683/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 684#[corresponds(SSL_select_next_proto)] 685pub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8]> { 686 unsafe { 687 let mut out = ptr::null_mut(); 688 let mut outlen = 0; 689 let r = ffi::SSL_select_next_proto( 690 &mut out, 691 &mut outlen, 692 server.as_ptr(), 693 server.len() as c_uint, 694 client.as_ptr(), 695 client.len() as c_uint, 696 ); 697 if r == ffi::OPENSSL_NPN_NEGOTIATED { 698 Some(slice::from_raw_parts(out as *const u8, outlen as usize)) 699 } else { 700 None 701 } 702 } 703} 704 705/// A builder for `SslContext`s. 706pub struct SslContextBuilder(SslContext); 707 708impl SslContextBuilder { 709 /// Creates a new `SslContextBuilder`. 710 #[corresponds(SSL_CTX_new)] 711 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> { 712 unsafe { 713 init(); 714 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?; 715 716 Ok(SslContextBuilder::from_ptr(ctx)) 717 } 718 } 719 720 /// Creates an `SslContextBuilder` from a pointer to a raw OpenSSL value. 721 /// 722 /// # Safety 723 /// 724 /// The caller must ensure that the pointer is valid and uniquely owned by the builder. 725 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder { 726 SslContextBuilder(SslContext::from_ptr(ctx)) 727 } 728 729 /// Returns a pointer to the raw OpenSSL value. 730 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { 731 self.0.as_ptr() 732 } 733 734 /// Configures the certificate verification method for new connections. 735 #[corresponds(SSL_CTX_set_verify)] 736 pub fn set_verify(&mut self, mode: SslVerifyMode) { 737 unsafe { 738 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, None); 739 } 740 } 741 742 /// Configures the certificate verification method for new connections and 743 /// registers a verification callback. 744 /// 745 /// The callback is passed a boolean indicating if OpenSSL's internal verification succeeded as 746 /// well as a reference to the `X509StoreContext` which can be used to examine the certificate 747 /// chain. It should return a boolean indicating if verification succeeded. 748 #[corresponds(SSL_CTX_set_verify)] 749 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) 750 where 751 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, 752 { 753 unsafe { 754 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify); 755 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::<F>)); 756 } 757 } 758 759 /// Configures the server name indication (SNI) callback for new connections. 760 /// 761 /// SNI is used to allow a single server to handle requests for multiple domains, each of which 762 /// has its own certificate chain and configuration. 763 /// 764 /// Obtain the server name with the `servername` method and then set the corresponding context 765 /// with `set_ssl_context` 766 #[corresponds(SSL_CTX_set_tlsext_servername_callback)] 767 // FIXME tlsext prefix? 768 pub fn set_servername_callback<F>(&mut self, callback: F) 769 where 770 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send, 771 { 772 unsafe { 773 // The SNI callback is somewhat unique in that the callback associated with the original 774 // context associated with an SSL can be used even if the SSL's context has been swapped 775 // out. When that happens, we wouldn't be able to look up the callback's state in the 776 // context's ex data. Instead, pass the pointer directly as the servername arg. It's 777 // still stored in ex data to manage the lifetime. 778 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback); 779 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg); 780 #[cfg(boringssl)] 781 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>)); 782 #[cfg(not(boringssl))] 783 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust( 784 self.as_ptr(), 785 Some(raw_sni::<F>), 786 ); 787 } 788 } 789 790 /// Sets the certificate verification depth. 791 /// 792 /// If the peer's certificate chain is longer than this value, verification will fail. 793 #[corresponds(SSL_CTX_set_verify_depth)] 794 pub fn set_verify_depth(&mut self, depth: u32) { 795 unsafe { 796 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int); 797 } 798 } 799 800 /// Sets a custom certificate store for verifying peer certificates. 801 /// 802 /// Requires OpenSSL 1.0.2 or newer. 803 #[corresponds(SSL_CTX_set0_verify_cert_store)] 804 #[cfg(ossl102)] 805 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { 806 unsafe { 807 let ptr = cert_store.as_ptr(); 808 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?; 809 mem::forget(cert_store); 810 811 Ok(()) 812 } 813 } 814 815 /// Replaces the context's certificate store. 816 #[corresponds(SSL_CTX_set_cert_store)] 817 pub fn set_cert_store(&mut self, cert_store: X509Store) { 818 unsafe { 819 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr()); 820 mem::forget(cert_store); 821 } 822 } 823 824 /// Controls read ahead behavior. 825 /// 826 /// If enabled, OpenSSL will read as much data as is available from the underlying stream, 827 /// instead of a single record at a time. 828 /// 829 /// It has no effect when used with DTLS. 830 #[corresponds(SSL_CTX_set_read_ahead)] 831 pub fn set_read_ahead(&mut self, read_ahead: bool) { 832 unsafe { 833 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType); 834 } 835 } 836 837 /// Sets the mode used by the context, returning the previous mode. 838 #[corresponds(SSL_CTX_set_mode)] 839 pub fn set_mode(&mut self, mode: SslMode) -> SslMode { 840 unsafe { 841 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType; 842 SslMode { bits } 843 } 844 } 845 846 /// Sets the parameters to be used during ephemeral Diffie-Hellman key exchange. 847 #[corresponds(SSL_CTX_set_tmp_dh)] 848 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { 849 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } 850 } 851 852 /// Sets the callback which will generate parameters to be used during ephemeral Diffie-Hellman 853 /// key exchange. 854 /// 855 /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean 856 /// indicating if the selected cipher is export-grade, and the key length. The export and key 857 /// length options are archaic and should be ignored in almost all cases. 858 #[corresponds(SSL_CTX_set_tmp_dh_callback)] 859 pub fn set_tmp_dh_callback<F>(&mut self, callback: F) 860 where 861 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, 862 { 863 unsafe { 864 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 865 866 #[cfg(not(boringssl))] 867 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>)); 868 #[cfg(boringssl)] 869 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>)); 870 } 871 } 872 873 /// Sets the parameters to be used during ephemeral elliptic curve Diffie-Hellman key exchange. 874 #[corresponds(SSL_CTX_set_tmp_ecdh)] 875 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { 876 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } 877 } 878 879 /// Sets the callback which will generate parameters to be used during ephemeral elliptic curve 880 /// Diffie-Hellman key exchange. 881 /// 882 /// The callback is provided with a reference to the `Ssl` for the session, as well as a boolean 883 /// indicating if the selected cipher is export-grade, and the key length. The export and key 884 /// length options are archaic and should be ignored in almost all cases. 885 /// 886 /// Requires OpenSSL 1.0.1 or 1.0.2. 887 #[corresponds(SSL_CTX_set_tmp_ecdh_callback)] 888 #[cfg(all(ossl101, not(ossl110)))] 889 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] 890 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) 891 where 892 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, 893 { 894 unsafe { 895 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 896 ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>)); 897 } 898 } 899 900 /// Use the default locations of trusted certificates for verification. 901 /// 902 /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` environment variables 903 /// if present, or defaults specified at OpenSSL build time otherwise. 904 #[corresponds(SSL_CTX_set_default_verify_paths)] 905 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { 906 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) } 907 } 908 909 /// Loads trusted root certificates from a file. 910 /// 911 /// The file should contain a sequence of PEM-formatted CA certificates. 912 #[corresponds(SSL_CTX_load_verify_locations)] 913 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> { 914 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 915 unsafe { 916 cvt(ffi::SSL_CTX_load_verify_locations( 917 self.as_ptr(), 918 file.as_ptr() as *const _, 919 ptr::null(), 920 )) 921 .map(|_| ()) 922 } 923 } 924 925 /// Sets the list of CA names sent to the client. 926 /// 927 /// The CA certificates must still be added to the trust root - they are not automatically set 928 /// as trusted by this method. 929 #[corresponds(SSL_CTX_set_client_CA_list)] 930 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { 931 unsafe { 932 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr()); 933 mem::forget(list); 934 } 935 } 936 937 /// Add the provided CA certificate to the list sent by the server to the client when 938 /// requesting client-side TLS authentication. 939 #[corresponds(SSL_CTX_add_client_CA)] 940 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { 941 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) } 942 } 943 944 /// Set the context identifier for sessions. 945 /// 946 /// This value identifies the server's session cache to clients, telling them when they're 947 /// able to reuse sessions. It should be set to a unique value per server, unless multiple 948 /// servers share a session cache. 949 /// 950 /// This value should be set when using client certificates, or each request will fail its 951 /// handshake and need to be restarted. 952 #[corresponds(SSL_CTX_set_session_id_context)] 953 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { 954 unsafe { 955 assert!(sid_ctx.len() <= c_uint::max_value() as usize); 956 cvt(ffi::SSL_CTX_set_session_id_context( 957 self.as_ptr(), 958 sid_ctx.as_ptr(), 959 sid_ctx.len() as SizeTy, 960 )) 961 .map(|_| ()) 962 } 963 } 964 965 /// Loads a leaf certificate from a file. 966 /// 967 /// Only a single certificate will be loaded - use `add_extra_chain_cert` to add the remainder 968 /// of the certificate chain, or `set_certificate_chain_file` to load the entire chain from a 969 /// single file. 970 #[corresponds(SSL_CTX_use_certificate_file)] 971 pub fn set_certificate_file<P: AsRef<Path>>( 972 &mut self, 973 file: P, 974 file_type: SslFiletype, 975 ) -> Result<(), ErrorStack> { 976 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 977 unsafe { 978 cvt(ffi::SSL_CTX_use_certificate_file( 979 self.as_ptr(), 980 file.as_ptr() as *const _, 981 file_type.as_raw(), 982 )) 983 .map(|_| ()) 984 } 985 } 986 987 /// Loads a certificate chain from a file. 988 /// 989 /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf 990 /// certificate, and the remainder forming the chain of certificates up to and including the 991 /// trusted root certificate. 992 #[corresponds(SSL_CTX_use_certificate_chain_file)] 993 pub fn set_certificate_chain_file<P: AsRef<Path>>( 994 &mut self, 995 file: P, 996 ) -> Result<(), ErrorStack> { 997 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 998 unsafe { 999 cvt(ffi::SSL_CTX_use_certificate_chain_file( 1000 self.as_ptr(), 1001 file.as_ptr() as *const _, 1002 )) 1003 .map(|_| ()) 1004 } 1005 } 1006 1007 /// Sets the leaf certificate. 1008 /// 1009 /// Use `add_extra_chain_cert` to add the remainder of the certificate chain. 1010 #[corresponds(SSL_CTX_use_certificate)] 1011 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { 1012 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) } 1013 } 1014 1015 /// Appends a certificate to the certificate chain. 1016 /// 1017 /// This chain should contain all certificates necessary to go from the certificate specified by 1018 /// `set_certificate` to a trusted root. 1019 #[corresponds(SSL_CTX_add_extra_chain_cert)] 1020 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { 1021 unsafe { 1022 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?; 1023 mem::forget(cert); 1024 Ok(()) 1025 } 1026 } 1027 1028 /// Loads the private key from a file. 1029 #[corresponds(SSL_CTX_use_PrivateKey_file)] 1030 pub fn set_private_key_file<P: AsRef<Path>>( 1031 &mut self, 1032 file: P, 1033 file_type: SslFiletype, 1034 ) -> Result<(), ErrorStack> { 1035 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 1036 unsafe { 1037 cvt(ffi::SSL_CTX_use_PrivateKey_file( 1038 self.as_ptr(), 1039 file.as_ptr() as *const _, 1040 file_type.as_raw(), 1041 )) 1042 .map(|_| ()) 1043 } 1044 } 1045 1046 /// Sets the private key. 1047 #[corresponds(SSL_CTX_use_PrivateKey)] 1048 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 1049 where 1050 T: HasPrivate, 1051 { 1052 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) } 1053 } 1054 1055 /// Sets the list of supported ciphers for protocols before TLSv1.3. 1056 /// 1057 /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. 1058 /// 1059 /// See [`ciphers`] for details on the format. 1060 /// 1061 /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html 1062 #[corresponds(SSL_CTX_set_cipher_list)] 1063 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 1064 let cipher_list = CString::new(cipher_list).unwrap(); 1065 unsafe { 1066 cvt(ffi::SSL_CTX_set_cipher_list( 1067 self.as_ptr(), 1068 cipher_list.as_ptr() as *const _, 1069 )) 1070 .map(|_| ()) 1071 } 1072 } 1073 1074 /// Sets the list of supported ciphers for the TLSv1.3 protocol. 1075 /// 1076 /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. 1077 /// 1078 /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of 1079 /// preference. 1080 /// 1081 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 1082 #[corresponds(SSL_CTX_set_ciphersuites)] 1083 #[cfg(any(ossl111, libressl340))] 1084 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 1085 let cipher_list = CString::new(cipher_list).unwrap(); 1086 unsafe { 1087 cvt(ffi::SSL_CTX_set_ciphersuites( 1088 self.as_ptr(), 1089 cipher_list.as_ptr() as *const _, 1090 )) 1091 .map(|_| ()) 1092 } 1093 } 1094 1095 /// Enables ECDHE key exchange with an automatically chosen curve list. 1096 /// 1097 /// Requires OpenSSL 1.0.2. 1098 #[corresponds(SSL_CTX_set_ecdh_auto)] 1099 #[cfg(any(libressl, all(ossl102, not(ossl110))))] 1100 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { 1101 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } 1102 } 1103 1104 /// Sets the options used by the context, returning the old set. 1105 /// 1106 /// # Note 1107 /// 1108 /// This *enables* the specified options, but does not disable unspecified options. Use 1109 /// `clear_options` for that. 1110 #[corresponds(SSL_CTX_set_options)] 1111 pub fn set_options(&mut self, option: SslOptions) -> SslOptions { 1112 let bits = 1113 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; 1114 SslOptions { bits } 1115 } 1116 1117 /// Returns the options used by the context. 1118 #[corresponds(SSL_CTX_get_options)] 1119 pub fn options(&self) -> SslOptions { 1120 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr; 1121 SslOptions { bits } 1122 } 1123 1124 /// Clears the options used by the context, returning the old set. 1125 #[corresponds(SSL_CTX_clear_options)] 1126 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions { 1127 let bits = 1128 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr; 1129 SslOptions { bits } 1130 } 1131 1132 /// Sets the minimum supported protocol version. 1133 /// 1134 /// A value of `None` will enable protocol versions down to the lowest version supported by 1135 /// OpenSSL. 1136 /// 1137 /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer. 1138 #[corresponds(SSL_CTX_set_min_proto_version)] 1139 #[cfg(any(ossl110, libressl261))] 1140 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 1141 unsafe { 1142 cvt(ffi::SSL_CTX_set_min_proto_version( 1143 self.as_ptr(), 1144 version.map_or(0, |v| v.0 as _), 1145 )) 1146 .map(|_| ()) 1147 } 1148 } 1149 1150 /// Sets the maximum supported protocol version. 1151 /// 1152 /// A value of `None` will enable protocol versions up to the highest version supported by 1153 /// OpenSSL. 1154 /// 1155 /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer. 1156 #[corresponds(SSL_CTX_set_max_proto_version)] 1157 #[cfg(any(ossl110, libressl261))] 1158 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 1159 unsafe { 1160 cvt(ffi::SSL_CTX_set_max_proto_version( 1161 self.as_ptr(), 1162 version.map_or(0, |v| v.0 as _), 1163 )) 1164 .map(|_| ()) 1165 } 1166 } 1167 1168 /// Gets the minimum supported protocol version. 1169 /// 1170 /// A value of `None` indicates that all versions down to the lowest version supported by 1171 /// OpenSSL are enabled. 1172 /// 1173 /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer. 1174 #[corresponds(SSL_CTX_get_min_proto_version)] 1175 #[cfg(any(ossl110g, libressl270))] 1176 pub fn min_proto_version(&mut self) -> Option<SslVersion> { 1177 unsafe { 1178 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); 1179 if r == 0 { 1180 None 1181 } else { 1182 Some(SslVersion(r)) 1183 } 1184 } 1185 } 1186 1187 /// Gets the maximum supported protocol version. 1188 /// 1189 /// A value of `None` indicates that all versions up to the highest version supported by 1190 /// OpenSSL are enabled. 1191 /// 1192 /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer. 1193 #[corresponds(SSL_CTX_get_max_proto_version)] 1194 #[cfg(any(ossl110g, libressl270))] 1195 pub fn max_proto_version(&mut self) -> Option<SslVersion> { 1196 unsafe { 1197 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); 1198 if r == 0 { 1199 None 1200 } else { 1201 Some(SslVersion(r)) 1202 } 1203 } 1204 } 1205 1206 /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). 1207 /// 1208 /// The input must be in ALPN "wire format". It consists of a sequence of supported protocol 1209 /// names prefixed by their byte length. For example, the protocol list consisting of `spdy/1` 1210 /// and `http/1.1` is encoded as `b"\x06spdy/1\x08http/1.1"`. The protocols are ordered by 1211 /// preference. 1212 /// 1213 /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 1214 #[corresponds(SSL_CTX_set_alpn_protos)] 1215 #[cfg(any(ossl102, libressl261))] 1216 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { 1217 unsafe { 1218 assert!(protocols.len() <= c_uint::max_value() as usize); 1219 let r = ffi::SSL_CTX_set_alpn_protos( 1220 self.as_ptr(), 1221 protocols.as_ptr(), 1222 protocols.len() as c_uint, 1223 ); 1224 // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D: 1225 if r == 0 { 1226 Ok(()) 1227 } else { 1228 Err(ErrorStack::get()) 1229 } 1230 } 1231 } 1232 1233 /// Enables the DTLS extension "use_srtp" as defined in RFC5764. 1234 #[corresponds(SSL_CTX_set_tlsext_use_srtp)] 1235 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { 1236 unsafe { 1237 let cstr = CString::new(protocols).unwrap(); 1238 1239 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); 1240 // fun fact, set_tlsext_use_srtp has a reversed return code D: 1241 if r == 0 { 1242 Ok(()) 1243 } else { 1244 Err(ErrorStack::get()) 1245 } 1246 } 1247 } 1248 1249 /// Sets the callback used by a server to select a protocol for Application Layer Protocol 1250 /// Negotiation (ALPN). 1251 /// 1252 /// The callback is provided with the client's protocol list in ALPN wire format. See the 1253 /// documentation for [`SslContextBuilder::set_alpn_protos`] for details. It should return one 1254 /// of those protocols on success. The [`select_next_proto`] function implements the standard 1255 /// protocol selection algorithm. 1256 /// 1257 /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 1258 /// 1259 /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 1260 /// [`select_next_proto`]: fn.select_next_proto.html 1261 #[corresponds(SSL_CTX_set_alpn_select_cb)] 1262 #[cfg(any(ossl102, libressl261))] 1263 pub fn set_alpn_select_callback<F>(&mut self, callback: F) 1264 where 1265 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, 1266 { 1267 unsafe { 1268 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1269 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust( 1270 self.as_ptr(), 1271 Some(callbacks::raw_alpn_select::<F>), 1272 ptr::null_mut(), 1273 ); 1274 } 1275 } 1276 1277 /// Checks for consistency between the private key and certificate. 1278 #[corresponds(SSL_CTX_check_private_key)] 1279 pub fn check_private_key(&self) -> Result<(), ErrorStack> { 1280 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) } 1281 } 1282 1283 /// Returns a shared reference to the context's certificate store. 1284 #[corresponds(SSL_CTX_get_cert_store)] 1285 pub fn cert_store(&self) -> &X509StoreBuilderRef { 1286 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 1287 } 1288 1289 /// Returns a mutable reference to the context's certificate store. 1290 #[corresponds(SSL_CTX_get_cert_store)] 1291 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef { 1292 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 1293 } 1294 1295 /// Returns a reference to the X509 verification configuration. 1296 /// 1297 /// Requires OpenSSL 1.0.2 or newer. 1298 #[corresponds(SSL_CTX_get0_param)] 1299 #[cfg(any(ossl102, libressl261))] 1300 pub fn verify_param(&self) -> &X509VerifyParamRef { 1301 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) } 1302 } 1303 1304 /// Returns a mutable reference to the X509 verification configuration. 1305 /// 1306 /// Requires OpenSSL 1.0.2 or newer. 1307 #[corresponds(SSL_CTX_get0_param)] 1308 #[cfg(any(ossl102, libressl261))] 1309 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef { 1310 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) } 1311 } 1312 1313 /// Sets the callback dealing with OCSP stapling. 1314 /// 1315 /// On the client side, this callback is responsible for validating the OCSP status response 1316 /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method. 1317 /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of 1318 /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be 1319 /// terminated. 1320 /// 1321 /// On the server side, this callback is responsible for setting the OCSP status response to be 1322 /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A 1323 /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and 1324 /// `Ok(false)` indicates that the status should not be returned to the client. 1325 #[corresponds(SSL_CTX_set_tlsext_status_cb)] 1326 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack> 1327 where 1328 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, 1329 { 1330 unsafe { 1331 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1332 cvt( 1333 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>)) 1334 as c_int, 1335 ) 1336 .map(|_| ()) 1337 } 1338 } 1339 1340 /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client. 1341 /// 1342 /// The callback will be called with the SSL context, an identity hint if one was provided 1343 /// by the server, a mutable slice for each of the identity and pre-shared key bytes. The 1344 /// identity must be written as a null-terminated C string. 1345 #[corresponds(SSL_CTX_set_psk_client_callback)] 1346 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 1347 pub fn set_psk_client_callback<F>(&mut self, callback: F) 1348 where 1349 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> 1350 + 'static 1351 + Sync 1352 + Send, 1353 { 1354 unsafe { 1355 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1356 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>)); 1357 } 1358 } 1359 1360 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")] 1361 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 1362 pub fn set_psk_callback<F>(&mut self, callback: F) 1363 where 1364 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack> 1365 + 'static 1366 + Sync 1367 + Send, 1368 { 1369 self.set_psk_client_callback(callback) 1370 } 1371 1372 /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK server. 1373 /// 1374 /// The callback will be called with the SSL context, an identity provided by the client, 1375 /// and, a mutable slice for the pre-shared key bytes. The callback returns the number of 1376 /// bytes in the pre-shared key. 1377 #[corresponds(SSL_CTX_set_psk_server_callback)] 1378 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 1379 pub fn set_psk_server_callback<F>(&mut self, callback: F) 1380 where 1381 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack> 1382 + 'static 1383 + Sync 1384 + Send, 1385 { 1386 unsafe { 1387 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1388 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>)); 1389 } 1390 } 1391 1392 /// Sets the callback which is called when new sessions are negotiated. 1393 /// 1394 /// This can be used by clients to implement session caching. While in TLSv1.2 the session is 1395 /// available to access via [`SslRef::session`] immediately after the handshake completes, this 1396 /// is not the case for TLSv1.3. There, a session is not generally available immediately, and 1397 /// the server may provide multiple session tokens to the client over a single session. The new 1398 /// session callback is a portable way to deal with both cases. 1399 /// 1400 /// Note that session caching must be enabled for the callback to be invoked, and it defaults 1401 /// off for clients. [`set_session_cache_mode`] controls that behavior. 1402 /// 1403 /// [`SslRef::session`]: struct.SslRef.html#method.session 1404 /// [`set_session_cache_mode`]: #method.set_session_cache_mode 1405 #[corresponds(SSL_CTX_sess_set_new_cb)] 1406 pub fn set_new_session_callback<F>(&mut self, callback: F) 1407 where 1408 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, 1409 { 1410 unsafe { 1411 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1412 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>)); 1413 } 1414 } 1415 1416 /// Sets the callback which is called when sessions are removed from the context. 1417 /// 1418 /// Sessions can be removed because they have timed out or because they are considered faulty. 1419 #[corresponds(SSL_CTX_sess_set_remove_cb)] 1420 pub fn set_remove_session_callback<F>(&mut self, callback: F) 1421 where 1422 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, 1423 { 1424 unsafe { 1425 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1426 ffi::SSL_CTX_sess_set_remove_cb( 1427 self.as_ptr(), 1428 Some(callbacks::raw_remove_session::<F>), 1429 ); 1430 } 1431 } 1432 1433 /// Sets the callback which is called when a client proposed to resume a session but it was not 1434 /// found in the internal cache. 1435 /// 1436 /// The callback is passed a reference to the session ID provided by the client. It should 1437 /// return the session corresponding to that ID if available. This is only used for servers, not 1438 /// clients. 1439 /// 1440 /// # Safety 1441 /// 1442 /// The returned `SslSession` must not be associated with a different `SslContext`. 1443 #[corresponds(SSL_CTX_sess_set_get_cb)] 1444 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F) 1445 where 1446 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, 1447 { 1448 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1449 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>)); 1450 } 1451 1452 /// Sets the TLS key logging callback. 1453 /// 1454 /// The callback is invoked whenever TLS key material is generated, and is passed a line of NSS 1455 /// SSLKEYLOGFILE-formatted text. This can be used by tools like Wireshark to decrypt message 1456 /// traffic. The line does not contain a trailing newline. 1457 /// 1458 /// Requires OpenSSL 1.1.1 or newer. 1459 #[corresponds(SSL_CTX_set_keylog_callback)] 1460 #[cfg(ossl111)] 1461 pub fn set_keylog_callback<F>(&mut self, callback: F) 1462 where 1463 F: Fn(&SslRef, &str) + 'static + Sync + Send, 1464 { 1465 unsafe { 1466 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1467 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>)); 1468 } 1469 } 1470 1471 /// Sets the session caching mode use for connections made with the context. 1472 /// 1473 /// Returns the previous session caching mode. 1474 #[corresponds(SSL_CTX_set_session_cache_mode)] 1475 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode { 1476 unsafe { 1477 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits()); 1478 SslSessionCacheMode { bits } 1479 } 1480 } 1481 1482 /// Sets the callback for generating an application cookie for TLS1.3 1483 /// stateless handshakes. 1484 /// 1485 /// The callback will be called with the SSL context and a slice into which the cookie 1486 /// should be written. The callback should return the number of bytes written. 1487 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)] 1488 #[cfg(ossl111)] 1489 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F) 1490 where 1491 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, 1492 { 1493 unsafe { 1494 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1495 ffi::SSL_CTX_set_stateless_cookie_generate_cb( 1496 self.as_ptr(), 1497 Some(raw_stateless_cookie_generate::<F>), 1498 ); 1499 } 1500 } 1501 1502 /// Sets the callback for verifying an application cookie for TLS1.3 1503 /// stateless handshakes. 1504 /// 1505 /// The callback will be called with the SSL context and the cookie supplied by the 1506 /// client. It should return true if and only if the cookie is valid. 1507 /// 1508 /// Note that the OpenSSL implementation independently verifies the integrity of 1509 /// application cookies using an HMAC before invoking the supplied callback. 1510 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)] 1511 #[cfg(ossl111)] 1512 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F) 1513 where 1514 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, 1515 { 1516 unsafe { 1517 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1518 ffi::SSL_CTX_set_stateless_cookie_verify_cb( 1519 self.as_ptr(), 1520 Some(raw_stateless_cookie_verify::<F>), 1521 ) 1522 } 1523 } 1524 1525 /// Sets the callback for generating a DTLSv1 cookie 1526 /// 1527 /// The callback will be called with the SSL context and a slice into which the cookie 1528 /// should be written. The callback should return the number of bytes written. 1529 #[corresponds(SSL_CTX_set_cookie_generate_cb)] 1530 #[cfg(not(boringssl))] 1531 pub fn set_cookie_generate_cb<F>(&mut self, callback: F) 1532 where 1533 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, 1534 { 1535 unsafe { 1536 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1537 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>)); 1538 } 1539 } 1540 1541 /// Sets the callback for verifying a DTLSv1 cookie 1542 /// 1543 /// The callback will be called with the SSL context and the cookie supplied by the 1544 /// client. It should return true if and only if the cookie is valid. 1545 #[corresponds(SSL_CTX_set_cookie_verify_cb)] 1546 #[cfg(not(boringssl))] 1547 pub fn set_cookie_verify_cb<F>(&mut self, callback: F) 1548 where 1549 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, 1550 { 1551 unsafe { 1552 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback); 1553 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>)); 1554 } 1555 } 1556 1557 /// Sets the extra data at the specified index. 1558 /// 1559 /// This can be used to provide data to callbacks registered with the context. Use the 1560 /// `SslContext::new_ex_index` method to create an `Index`. 1561 #[corresponds(SSL_CTX_set_ex_data)] 1562 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) { 1563 self.set_ex_data_inner(index, data); 1564 } 1565 1566 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void { 1567 unsafe { 1568 let data = Box::into_raw(Box::new(data)) as *mut c_void; 1569 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data); 1570 data 1571 } 1572 } 1573 1574 /// Adds a custom extension for a TLS/DTLS client or server for all supported protocol versions. 1575 /// 1576 /// Requires OpenSSL 1.1.1 or newer. 1577 #[corresponds(SSL_CTX_add_custom_ext)] 1578 #[cfg(ossl111)] 1579 pub fn add_custom_ext<AddFn, ParseFn, T>( 1580 &mut self, 1581 ext_type: u16, 1582 context: ExtensionContext, 1583 add_cb: AddFn, 1584 parse_cb: ParseFn, 1585 ) -> Result<(), ErrorStack> 1586 where 1587 AddFn: Fn( 1588 &mut SslRef, 1589 ExtensionContext, 1590 Option<(usize, &X509Ref)>, 1591 ) -> Result<Option<T>, SslAlert> 1592 + 'static 1593 + Sync 1594 + Send, 1595 T: AsRef<[u8]> + 'static + Sync + Send, 1596 ParseFn: Fn( 1597 &mut SslRef, 1598 ExtensionContext, 1599 &[u8], 1600 Option<(usize, &X509Ref)>, 1601 ) -> Result<(), SslAlert> 1602 + 'static 1603 + Sync 1604 + Send, 1605 { 1606 let ret = unsafe { 1607 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb); 1608 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb); 1609 1610 ffi::SSL_CTX_add_custom_ext( 1611 self.as_ptr(), 1612 ext_type as c_uint, 1613 context.bits(), 1614 Some(raw_custom_ext_add::<AddFn, T>), 1615 Some(raw_custom_ext_free::<T>), 1616 ptr::null_mut(), 1617 Some(raw_custom_ext_parse::<ParseFn>), 1618 ptr::null_mut(), 1619 ) 1620 }; 1621 if ret == 1 { 1622 Ok(()) 1623 } else { 1624 Err(ErrorStack::get()) 1625 } 1626 } 1627 1628 /// Sets the maximum amount of early data that will be accepted on incoming connections. 1629 /// 1630 /// Defaults to 0. 1631 /// 1632 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 1633 #[corresponds(SSL_CTX_set_max_early_data)] 1634 #[cfg(any(ossl111, libressl340))] 1635 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { 1636 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 { 1637 Ok(()) 1638 } else { 1639 Err(ErrorStack::get()) 1640 } 1641 } 1642 1643 /// Sets a callback which will be invoked just after the client's hello message is received. 1644 /// 1645 /// Requires OpenSSL 1.1.1 or newer. 1646 #[corresponds(SSL_CTX_set_client_hello_cb)] 1647 #[cfg(ossl111)] 1648 pub fn set_client_hello_callback<F>(&mut self, callback: F) 1649 where 1650 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack> 1651 + 'static 1652 + Sync 1653 + Send, 1654 { 1655 unsafe { 1656 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback); 1657 ffi::SSL_CTX_set_client_hello_cb( 1658 self.as_ptr(), 1659 Some(callbacks::raw_client_hello::<F>), 1660 ptr, 1661 ); 1662 } 1663 } 1664 1665 /// Sets the context's session cache size limit, returning the previous limit. 1666 /// 1667 /// A value of 0 means that the cache size is unbounded. 1668 #[corresponds(SSL_CTX_sess_set_cache_size)] 1669 #[allow(clippy::useless_conversion)] 1670 pub fn set_session_cache_size(&mut self, size: i32) -> i64 { 1671 unsafe { 1672 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy 1673 } 1674 } 1675 1676 /// Sets the context's supported signature algorithms. 1677 /// 1678 /// Requires OpenSSL 1.0.2 or newer. 1679 #[corresponds(SSL_CTX_set1_sigalgs_list)] 1680 #[cfg(ossl102)] 1681 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> { 1682 let sigalgs = CString::new(sigalgs).unwrap(); 1683 unsafe { 1684 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int) 1685 .map(|_| ()) 1686 } 1687 } 1688 1689 /// Sets the context's supported elliptic curve groups. 1690 /// 1691 /// Requires OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer. 1692 #[corresponds(SSL_CTX_set1_groups_list)] 1693 #[cfg(any(ossl111, libressl251))] 1694 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> { 1695 let groups = CString::new(groups).unwrap(); 1696 unsafe { 1697 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ()) 1698 } 1699 } 1700 1701 /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full 1702 /// handshake. 1703 /// 1704 /// Requires OpenSSL 1.1.1 or newer. 1705 #[corresponds(SSL_CTX_set_num_tickets)] 1706 #[cfg(ossl111)] 1707 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { 1708 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } 1709 } 1710 1711 /// Consumes the builder, returning a new `SslContext`. 1712 pub fn build(self) -> SslContext { 1713 self.0 1714 } 1715} 1716 1717foreign_type_and_impl_send_sync! { 1718 type CType = ffi::SSL_CTX; 1719 fn drop = ffi::SSL_CTX_free; 1720 1721 /// A context object for TLS streams. 1722 /// 1723 /// Applications commonly configure a single `SslContext` that is shared by all of its 1724 /// `SslStreams`. 1725 pub struct SslContext; 1726 1727 /// Reference to [`SslContext`] 1728 /// 1729 /// [`SslContext`]: struct.SslContext.html 1730 pub struct SslContextRef; 1731} 1732 1733impl Clone for SslContext { 1734 fn clone(&self) -> Self { 1735 (**self).to_owned() 1736 } 1737} 1738 1739impl ToOwned for SslContextRef { 1740 type Owned = SslContext; 1741 1742 fn to_owned(&self) -> Self::Owned { 1743 unsafe { 1744 SSL_CTX_up_ref(self.as_ptr()); 1745 SslContext::from_ptr(self.as_ptr()) 1746 } 1747 } 1748} 1749 1750// TODO: add useful info here 1751impl fmt::Debug for SslContext { 1752 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 1753 write!(fmt, "SslContext") 1754 } 1755} 1756 1757impl SslContext { 1758 /// Creates a new builder object for an `SslContext`. 1759 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> { 1760 SslContextBuilder::new(method) 1761 } 1762 1763 /// Returns a new extra data index. 1764 /// 1765 /// Each invocation of this function is guaranteed to return a distinct index. These can be used 1766 /// to store data in the context that can be retrieved later by callbacks, for example. 1767 #[corresponds(SSL_CTX_get_ex_new_index)] 1768 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack> 1769 where 1770 T: 'static + Sync + Send, 1771 { 1772 unsafe { 1773 ffi::init(); 1774 #[cfg(boringssl)] 1775 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?; 1776 #[cfg(not(boringssl))] 1777 let idx = cvt_n(get_new_idx(free_data_box::<T>))?; 1778 Ok(Index::from_raw(idx)) 1779 } 1780 } 1781 1782 // FIXME should return a result? 1783 fn cached_ex_index<T>() -> Index<SslContext, T> 1784 where 1785 T: 'static + Sync + Send, 1786 { 1787 unsafe { 1788 let idx = *INDEXES 1789 .lock() 1790 .unwrap_or_else(|e| e.into_inner()) 1791 .entry(TypeId::of::<T>()) 1792 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw()); 1793 Index::from_raw(idx) 1794 } 1795 } 1796} 1797 1798impl SslContextRef { 1799 /// Returns the certificate associated with this `SslContext`, if present. 1800 /// 1801 /// Requires OpenSSL 1.0.2 or LibreSSL 2.7.0 or newer. 1802 #[corresponds(SSL_CTX_get0_certificate)] 1803 #[cfg(any(ossl102, libressl270))] 1804 pub fn certificate(&self) -> Option<&X509Ref> { 1805 unsafe { 1806 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr()); 1807 X509Ref::from_const_ptr_opt(ptr) 1808 } 1809 } 1810 1811 /// Returns the private key associated with this `SslContext`, if present. 1812 /// 1813 /// Requires OpenSSL 1.0.2 or LibreSSL 3.4.0 or newer. 1814 #[corresponds(SSL_CTX_get0_privatekey)] 1815 #[cfg(any(ossl102, libressl340))] 1816 pub fn private_key(&self) -> Option<&PKeyRef<Private>> { 1817 unsafe { 1818 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr()); 1819 PKeyRef::from_const_ptr_opt(ptr) 1820 } 1821 } 1822 1823 /// Returns a shared reference to the certificate store used for verification. 1824 #[corresponds(SSL_CTX_get_cert_store)] 1825 pub fn cert_store(&self) -> &X509StoreRef { 1826 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) } 1827 } 1828 1829 /// Returns a shared reference to the stack of certificates making up the chain from the leaf. 1830 #[corresponds(SSL_CTX_get_extra_chain_certs)] 1831 pub fn extra_chain_certs(&self) -> &StackRef<X509> { 1832 unsafe { 1833 let mut chain = ptr::null_mut(); 1834 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain); 1835 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null") 1836 } 1837 } 1838 1839 /// Returns a reference to the extra data at the specified index. 1840 #[corresponds(SSL_CTX_get_ex_data)] 1841 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> { 1842 unsafe { 1843 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw()); 1844 if data.is_null() { 1845 None 1846 } else { 1847 Some(&*(data as *const T)) 1848 } 1849 } 1850 } 1851 1852 /// Gets the maximum amount of early data that will be accepted on incoming connections. 1853 /// 1854 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 1855 #[corresponds(SSL_CTX_get_max_early_data)] 1856 #[cfg(any(ossl111, libressl340))] 1857 pub fn max_early_data(&self) -> u32 { 1858 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) } 1859 } 1860 1861 /// Adds a session to the context's cache. 1862 /// 1863 /// Returns `true` if the session was successfully added to the cache, and `false` if it was already present. 1864 /// 1865 /// # Safety 1866 /// 1867 /// The caller of this method is responsible for ensuring that the session has never been used with another 1868 /// `SslContext` than this one. 1869 #[corresponds(SSL_CTX_add_session)] 1870 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool { 1871 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0 1872 } 1873 1874 /// Removes a session from the context's cache and marks it as non-resumable. 1875 /// 1876 /// Returns `true` if the session was successfully found and removed, and `false` otherwise. 1877 /// 1878 /// # Safety 1879 /// 1880 /// The caller of this method is responsible for ensuring that the session has never been used with another 1881 /// `SslContext` than this one. 1882 #[corresponds(SSL_CTX_remove_session)] 1883 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool { 1884 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0 1885 } 1886 1887 /// Returns the context's session cache size limit. 1888 /// 1889 /// A value of 0 means that the cache size is unbounded. 1890 #[corresponds(SSL_CTX_sess_get_cache_size)] 1891 #[allow(clippy::unnecessary_cast)] 1892 pub fn session_cache_size(&self) -> i64 { 1893 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 } 1894 } 1895 1896 /// Returns the verify mode that was set on this context from [`SslContextBuilder::set_verify`]. 1897 /// 1898 /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify 1899 #[corresponds(SSL_CTX_get_verify_mode)] 1900 pub fn verify_mode(&self) -> SslVerifyMode { 1901 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) }; 1902 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode") 1903 } 1904 1905 /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full 1906 /// handshake. 1907 /// 1908 /// Requires OpenSSL 1.1.1 or newer. 1909 #[corresponds(SSL_CTX_get_num_tickets)] 1910 #[cfg(ossl111)] 1911 pub fn num_tickets(&self) -> usize { 1912 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) } 1913 } 1914} 1915 1916/// Information about the state of a cipher. 1917pub struct CipherBits { 1918 /// The number of secret bits used for the cipher. 1919 pub secret: i32, 1920 1921 /// The number of bits processed by the chosen algorithm. 1922 pub algorithm: i32, 1923} 1924 1925/// Information about a cipher. 1926pub struct SslCipher(*mut ffi::SSL_CIPHER); 1927 1928impl ForeignType for SslCipher { 1929 type CType = ffi::SSL_CIPHER; 1930 type Ref = SslCipherRef; 1931 1932 #[inline] 1933 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher { 1934 SslCipher(ptr) 1935 } 1936 1937 #[inline] 1938 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER { 1939 self.0 1940 } 1941} 1942 1943impl Stackable for SslCipher { 1944 type StackType = ffi::stack_st_SSL_CIPHER; 1945} 1946 1947impl Deref for SslCipher { 1948 type Target = SslCipherRef; 1949 1950 fn deref(&self) -> &SslCipherRef { 1951 unsafe { SslCipherRef::from_ptr(self.0) } 1952 } 1953} 1954 1955impl DerefMut for SslCipher { 1956 fn deref_mut(&mut self) -> &mut SslCipherRef { 1957 unsafe { SslCipherRef::from_ptr_mut(self.0) } 1958 } 1959} 1960 1961/// Reference to an [`SslCipher`]. 1962/// 1963/// [`SslCipher`]: struct.SslCipher.html 1964pub struct SslCipherRef(Opaque); 1965 1966impl ForeignTypeRef for SslCipherRef { 1967 type CType = ffi::SSL_CIPHER; 1968} 1969 1970impl SslCipherRef { 1971 /// Returns the name of the cipher. 1972 #[corresponds(SSL_CIPHER_get_name)] 1973 pub fn name(&self) -> &'static str { 1974 unsafe { 1975 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr()); 1976 CStr::from_ptr(ptr).to_str().unwrap() 1977 } 1978 } 1979 1980 /// Returns the RFC-standard name of the cipher, if one exists. 1981 /// 1982 /// Requires OpenSSL 1.1.1 or newer. 1983 #[corresponds(SSL_CIPHER_standard_name)] 1984 #[cfg(ossl111)] 1985 pub fn standard_name(&self) -> Option<&'static str> { 1986 unsafe { 1987 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr()); 1988 if ptr.is_null() { 1989 None 1990 } else { 1991 Some(CStr::from_ptr(ptr).to_str().unwrap()) 1992 } 1993 } 1994 } 1995 1996 /// Returns the SSL/TLS protocol version that first defined the cipher. 1997 #[corresponds(SSL_CIPHER_get_version)] 1998 pub fn version(&self) -> &'static str { 1999 let version = unsafe { 2000 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr()); 2001 CStr::from_ptr(ptr as *const _) 2002 }; 2003 2004 str::from_utf8(version.to_bytes()).unwrap() 2005 } 2006 2007 /// Returns the number of bits used for the cipher. 2008 #[corresponds(SSL_CIPHER_get_bits)] 2009 #[allow(clippy::useless_conversion)] 2010 pub fn bits(&self) -> CipherBits { 2011 unsafe { 2012 let mut algo_bits = 0; 2013 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits); 2014 CipherBits { 2015 secret: secret_bits.into(), 2016 algorithm: algo_bits.into(), 2017 } 2018 } 2019 } 2020 2021 /// Returns a textual description of the cipher. 2022 #[corresponds(SSL_CIPHER_description)] 2023 pub fn description(&self) -> String { 2024 unsafe { 2025 // SSL_CIPHER_description requires a buffer of at least 128 bytes. 2026 let mut buf = [0; 128]; 2027 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128); 2028 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap() 2029 } 2030 } 2031 2032 /// Returns the handshake digest of the cipher. 2033 /// 2034 /// Requires OpenSSL 1.1.1 or newer. 2035 #[corresponds(SSL_CIPHER_get_handshake_digest)] 2036 #[cfg(ossl111)] 2037 pub fn handshake_digest(&self) -> Option<MessageDigest> { 2038 unsafe { 2039 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr()); 2040 if ptr.is_null() { 2041 None 2042 } else { 2043 Some(MessageDigest::from_ptr(ptr)) 2044 } 2045 } 2046 } 2047 2048 /// Returns the NID corresponding to the cipher. 2049 /// 2050 /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 2051 #[corresponds(SSL_CIPHER_get_cipher_nid)] 2052 #[cfg(any(ossl110, libressl270))] 2053 pub fn cipher_nid(&self) -> Option<Nid> { 2054 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) }; 2055 if n == 0 { 2056 None 2057 } else { 2058 Some(Nid::from_raw(n)) 2059 } 2060 } 2061} 2062 2063impl fmt::Debug for SslCipherRef { 2064 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 2065 write!(fmt, "{}", self.name()) 2066 } 2067} 2068 2069/// A stack of selected ciphers, and a stack of selected signalling cipher suites 2070#[derive(Debug)] 2071pub struct CipherLists { 2072 pub suites: Stack<SslCipher>, 2073 pub signalling_suites: Stack<SslCipher>, 2074} 2075 2076foreign_type_and_impl_send_sync! { 2077 type CType = ffi::SSL_SESSION; 2078 fn drop = ffi::SSL_SESSION_free; 2079 2080 /// An encoded SSL session. 2081 /// 2082 /// These can be cached to share sessions across connections. 2083 pub struct SslSession; 2084 2085 /// Reference to [`SslSession`]. 2086 /// 2087 /// [`SslSession`]: struct.SslSession.html 2088 pub struct SslSessionRef; 2089} 2090 2091impl Clone for SslSession { 2092 fn clone(&self) -> SslSession { 2093 SslSessionRef::to_owned(self) 2094 } 2095} 2096 2097impl SslSession { 2098 from_der! { 2099 /// Deserializes a DER-encoded session structure. 2100 #[corresponds(d2i_SSL_SESSION)] 2101 from_der, 2102 SslSession, 2103 ffi::d2i_SSL_SESSION 2104 } 2105} 2106 2107impl ToOwned for SslSessionRef { 2108 type Owned = SslSession; 2109 2110 fn to_owned(&self) -> SslSession { 2111 unsafe { 2112 SSL_SESSION_up_ref(self.as_ptr()); 2113 SslSession(self.as_ptr()) 2114 } 2115 } 2116} 2117 2118impl SslSessionRef { 2119 /// Returns the SSL session ID. 2120 #[corresponds(SSL_SESSION_get_id)] 2121 pub fn id(&self) -> &[u8] { 2122 unsafe { 2123 let mut len = 0; 2124 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len); 2125 slice::from_raw_parts(p as *const u8, len as usize) 2126 } 2127 } 2128 2129 /// Returns the length of the master key. 2130 #[corresponds(SSL_SESSION_get_master_key)] 2131 pub fn master_key_len(&self) -> usize { 2132 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) } 2133 } 2134 2135 /// Copies the master key into the provided buffer. 2136 /// 2137 /// Returns the number of bytes written, or the size of the master key if the buffer is empty. 2138 #[corresponds(SSL_SESSION_get_master_key)] 2139 pub fn master_key(&self, buf: &mut [u8]) -> usize { 2140 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } 2141 } 2142 2143 /// Gets the maximum amount of early data that can be sent on this session. 2144 /// 2145 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 2146 #[corresponds(SSL_SESSION_get_max_early_data)] 2147 #[cfg(any(ossl111, libressl340))] 2148 pub fn max_early_data(&self) -> u32 { 2149 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) } 2150 } 2151 2152 /// Returns the time at which the session was established, in seconds since the Unix epoch. 2153 #[corresponds(SSL_SESSION_get_time)] 2154 #[allow(clippy::useless_conversion)] 2155 pub fn time(&self) -> SslTimeTy { 2156 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) } 2157 } 2158 2159 /// Returns the sessions timeout, in seconds. 2160 /// 2161 /// A session older than this time should not be used for session resumption. 2162 #[corresponds(SSL_SESSION_get_timeout)] 2163 #[allow(clippy::useless_conversion)] 2164 pub fn timeout(&self) -> i64 { 2165 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() } 2166 } 2167 2168 /// Returns the session's TLS protocol version. 2169 /// 2170 /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 2171 #[corresponds(SSL_SESSION_get_protocol_version)] 2172 #[cfg(any(ossl110, libressl270))] 2173 pub fn protocol_version(&self) -> SslVersion { 2174 unsafe { 2175 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr()); 2176 SslVersion(version) 2177 } 2178 } 2179 2180 to_der! { 2181 /// Serializes the session into a DER-encoded structure. 2182 #[corresponds(i2d_SSL_SESSION)] 2183 to_der, 2184 ffi::i2d_SSL_SESSION 2185 } 2186} 2187 2188foreign_type_and_impl_send_sync! { 2189 type CType = ffi::SSL; 2190 fn drop = ffi::SSL_free; 2191 2192 /// The state of an SSL/TLS session. 2193 /// 2194 /// `Ssl` objects are created from an [`SslContext`], which provides configuration defaults. 2195 /// These defaults can be overridden on a per-`Ssl` basis, however. 2196 /// 2197 /// [`SslContext`]: struct.SslContext.html 2198 pub struct Ssl; 2199 2200 /// Reference to an [`Ssl`]. 2201 /// 2202 /// [`Ssl`]: struct.Ssl.html 2203 pub struct SslRef; 2204} 2205 2206impl fmt::Debug for Ssl { 2207 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 2208 fmt::Debug::fmt(&**self, fmt) 2209 } 2210} 2211 2212impl Ssl { 2213 /// Returns a new extra data index. 2214 /// 2215 /// Each invocation of this function is guaranteed to return a distinct index. These can be used 2216 /// to store data in the context that can be retrieved later by callbacks, for example. 2217 #[corresponds(SSL_get_ex_new_index)] 2218 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack> 2219 where 2220 T: 'static + Sync + Send, 2221 { 2222 unsafe { 2223 ffi::init(); 2224 #[cfg(boringssl)] 2225 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?; 2226 #[cfg(not(boringssl))] 2227 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?; 2228 Ok(Index::from_raw(idx)) 2229 } 2230 } 2231 2232 // FIXME should return a result? 2233 fn cached_ex_index<T>() -> Index<Ssl, T> 2234 where 2235 T: 'static + Sync + Send, 2236 { 2237 unsafe { 2238 let idx = *SSL_INDEXES 2239 .lock() 2240 .unwrap_or_else(|e| e.into_inner()) 2241 .entry(TypeId::of::<T>()) 2242 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw()); 2243 Index::from_raw(idx) 2244 } 2245 } 2246 2247 /// Creates a new `Ssl`. 2248 /// 2249 /// This corresponds to [`SSL_new`]. 2250 /// 2251 /// [`SSL_new`]: https://www.openssl.org/docs/manmaster/ssl/SSL_new.html 2252 #[corresponds(SSL_new)] 2253 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> { 2254 let session_ctx_index = try_get_session_ctx_index()?; 2255 unsafe { 2256 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?; 2257 let mut ssl = Ssl::from_ptr(ptr); 2258 ssl.set_ex_data(*session_ctx_index, ctx.to_owned()); 2259 2260 Ok(ssl) 2261 } 2262 } 2263 2264 /// Initiates a client-side TLS handshake. 2265 /// 2266 /// This corresponds to [`SSL_connect`]. 2267 /// 2268 /// # Warning 2269 /// 2270 /// OpenSSL's default configuration is insecure. It is highly recommended to use 2271 /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. 2272 /// 2273 /// [`SSL_connect`]: https://www.openssl.org/docs/manmaster/man3/SSL_connect.html 2274 #[corresponds(SSL_connect)] 2275 #[allow(deprecated)] 2276 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> 2277 where 2278 S: Read + Write, 2279 { 2280 SslStreamBuilder::new(self, stream).connect() 2281 } 2282 2283 /// Initiates a server-side TLS handshake. 2284 /// 2285 /// This corresponds to [`SSL_accept`]. 2286 /// 2287 /// # Warning 2288 /// 2289 /// OpenSSL's default configuration is insecure. It is highly recommended to use 2290 /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. 2291 /// 2292 /// [`SSL_accept`]: https://www.openssl.org/docs/manmaster/man3/SSL_accept.html 2293 #[corresponds(SSL_accept)] 2294 #[allow(deprecated)] 2295 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>> 2296 where 2297 S: Read + Write, 2298 { 2299 SslStreamBuilder::new(self, stream).accept() 2300 } 2301} 2302 2303impl fmt::Debug for SslRef { 2304 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 2305 fmt.debug_struct("Ssl") 2306 .field("state", &self.state_string_long()) 2307 .field("verify_result", &self.verify_result()) 2308 .finish() 2309 } 2310} 2311 2312impl SslRef { 2313 fn get_raw_rbio(&self) -> *mut ffi::BIO { 2314 unsafe { ffi::SSL_get_rbio(self.as_ptr()) } 2315 } 2316 2317 fn read(&mut self, buf: &mut [u8]) -> c_int { 2318 let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 2319 unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } 2320 } 2321 2322 fn peek(&mut self, buf: &mut [u8]) -> c_int { 2323 let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 2324 unsafe { ffi::SSL_peek(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } 2325 } 2326 2327 fn write(&mut self, buf: &[u8]) -> c_int { 2328 let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; 2329 unsafe { ffi::SSL_write(self.as_ptr(), buf.as_ptr() as *const c_void, len) } 2330 } 2331 2332 fn get_error(&self, ret: c_int) -> ErrorCode { 2333 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) } 2334 } 2335 2336 /// Configure as an outgoing stream from a client. 2337 #[corresponds(SSL_set_connect_state)] 2338 pub fn set_connect_state(&mut self) { 2339 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) } 2340 } 2341 2342 /// Configure as an incoming stream to a server. 2343 #[corresponds(SSL_set_accept_state)] 2344 pub fn set_accept_state(&mut self) { 2345 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) } 2346 } 2347 2348 /// Like [`SslContextBuilder::set_verify`]. 2349 /// 2350 /// [`SslContextBuilder::set_verify`]: struct.SslContextBuilder.html#method.set_verify 2351 #[corresponds(SSL_set_verify)] 2352 pub fn set_verify(&mut self, mode: SslVerifyMode) { 2353 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) } 2354 } 2355 2356 /// Returns the verify mode that was set using `set_verify`. 2357 #[corresponds(SSL_set_verify_mode)] 2358 pub fn verify_mode(&self) -> SslVerifyMode { 2359 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) }; 2360 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode") 2361 } 2362 2363 /// Like [`SslContextBuilder::set_verify_callback`]. 2364 /// 2365 /// [`SslContextBuilder::set_verify_callback`]: struct.SslContextBuilder.html#method.set_verify_callback 2366 #[corresponds(SSL_set_verify)] 2367 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F) 2368 where 2369 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send, 2370 { 2371 unsafe { 2372 // this needs to be in an Arc since the callback can register a new callback! 2373 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify)); 2374 ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, Some(ssl_raw_verify::<F>)); 2375 } 2376 } 2377 2378 /// Like [`SslContextBuilder::set_tmp_dh`]. 2379 /// 2380 /// [`SslContextBuilder::set_tmp_dh`]: struct.SslContextBuilder.html#method.set_tmp_dh 2381 #[corresponds(SSL_set_tmp_dh)] 2382 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> { 2383 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } 2384 } 2385 2386 /// Like [`SslContextBuilder::set_tmp_dh_callback`]. 2387 /// 2388 /// [`SslContextBuilder::set_tmp_dh_callback`]: struct.SslContextBuilder.html#method.set_tmp_dh_callback 2389 #[corresponds(SSL_set_tmp_dh_callback)] 2390 pub fn set_tmp_dh_callback<F>(&mut self, callback: F) 2391 where 2392 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, 2393 { 2394 unsafe { 2395 // this needs to be in an Arc since the callback can register a new callback! 2396 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); 2397 #[cfg(boringssl)] 2398 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>)); 2399 #[cfg(not(boringssl))] 2400 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>)); 2401 } 2402 } 2403 2404 /// Like [`SslContextBuilder::set_tmp_ecdh`]. 2405 /// 2406 /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh 2407 #[corresponds(SSL_set_tmp_ecdh)] 2408 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> { 2409 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } 2410 } 2411 2412 /// Like [`SslContextBuilder::set_tmp_ecdh_callback`]. 2413 /// 2414 /// Requires OpenSSL 1.0.1 or 1.0.2. 2415 #[corresponds(SSL_set_tmp_ecdh_callback)] 2416 #[cfg(all(ossl101, not(ossl110)))] 2417 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")] 2418 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) 2419 where 2420 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, 2421 { 2422 unsafe { 2423 // this needs to be in an Arc since the callback can register a new callback! 2424 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback)); 2425 ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::<F>)); 2426 } 2427 } 2428 2429 /// Like [`SslContextBuilder::set_ecdh_auto`]. 2430 /// 2431 /// Requires OpenSSL 1.0.2 or LibreSSL. 2432 /// 2433 /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh 2434 #[corresponds(SSL_set_ecdh_auto)] 2435 #[cfg(any(all(ossl102, not(ossl110)), libressl))] 2436 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { 2437 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } 2438 } 2439 2440 /// Like [`SslContextBuilder::set_alpn_protos`]. 2441 /// 2442 /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 2443 /// 2444 /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos 2445 #[corresponds(SSL_set_alpn_protos)] 2446 #[cfg(any(ossl102, libressl261))] 2447 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { 2448 unsafe { 2449 assert!(protocols.len() <= c_uint::max_value() as usize); 2450 let r = ffi::SSL_set_alpn_protos( 2451 self.as_ptr(), 2452 protocols.as_ptr(), 2453 protocols.len() as c_uint, 2454 ); 2455 // fun fact, SSL_set_alpn_protos has a reversed return code D: 2456 if r == 0 { 2457 Ok(()) 2458 } else { 2459 Err(ErrorStack::get()) 2460 } 2461 } 2462 } 2463 2464 /// Returns the current cipher if the session is active. 2465 #[corresponds(SSL_get_current_cipher)] 2466 pub fn current_cipher(&self) -> Option<&SslCipherRef> { 2467 unsafe { 2468 let ptr = ffi::SSL_get_current_cipher(self.as_ptr()); 2469 2470 SslCipherRef::from_const_ptr_opt(ptr) 2471 } 2472 } 2473 2474 /// Returns a short string describing the state of the session. 2475 #[corresponds(SSL_state_string)] 2476 pub fn state_string(&self) -> &'static str { 2477 let state = unsafe { 2478 let ptr = ffi::SSL_state_string(self.as_ptr()); 2479 CStr::from_ptr(ptr as *const _) 2480 }; 2481 2482 str::from_utf8(state.to_bytes()).unwrap() 2483 } 2484 2485 /// Returns a longer string describing the state of the session. 2486 #[corresponds(SSL_state_string_long)] 2487 pub fn state_string_long(&self) -> &'static str { 2488 let state = unsafe { 2489 let ptr = ffi::SSL_state_string_long(self.as_ptr()); 2490 CStr::from_ptr(ptr as *const _) 2491 }; 2492 2493 str::from_utf8(state.to_bytes()).unwrap() 2494 } 2495 2496 /// Sets the host name to be sent to the server for Server Name Indication (SNI). 2497 /// 2498 /// It has no effect for a server-side connection. 2499 #[corresponds(SSL_set_tlsext_host_name)] 2500 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { 2501 let cstr = CString::new(hostname).unwrap(); 2502 unsafe { 2503 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) 2504 .map(|_| ()) 2505 } 2506 } 2507 2508 /// Returns the peer's certificate, if present. 2509 #[corresponds(SSL_get_peer_certificate)] 2510 pub fn peer_certificate(&self) -> Option<X509> { 2511 unsafe { 2512 let ptr = SSL_get1_peer_certificate(self.as_ptr()); 2513 X509::from_ptr_opt(ptr) 2514 } 2515 } 2516 2517 /// Returns the certificate chain of the peer, if present. 2518 /// 2519 /// On the client side, the chain includes the leaf certificate, but on the server side it does 2520 /// not. Fun! 2521 #[corresponds(SSL_get_peer_cert_chain)] 2522 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> { 2523 unsafe { 2524 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr()); 2525 StackRef::from_const_ptr_opt(ptr) 2526 } 2527 } 2528 2529 /// Returns the verified certificate chain of the peer, including the leaf certificate. 2530 /// 2531 /// If verification was not successful (i.e. [`verify_result`] does not return 2532 /// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid. 2533 /// 2534 /// Requires OpenSSL 1.1.0 or newer. 2535 /// 2536 /// [`verify_result`]: #method.verify_result 2537 /// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK 2538 #[corresponds(SSL_get0_verified_chain)] 2539 #[cfg(ossl110)] 2540 pub fn verified_chain(&self) -> Option<&StackRef<X509>> { 2541 unsafe { 2542 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr()); 2543 StackRef::from_const_ptr_opt(ptr) 2544 } 2545 } 2546 2547 /// Like [`SslContext::certificate`]. 2548 #[corresponds(SSL_get_certificate)] 2549 pub fn certificate(&self) -> Option<&X509Ref> { 2550 unsafe { 2551 let ptr = ffi::SSL_get_certificate(self.as_ptr()); 2552 X509Ref::from_const_ptr_opt(ptr) 2553 } 2554 } 2555 2556 /// Like [`SslContext::private_key`]. 2557 /// 2558 /// [`SslContext::private_key`]: struct.SslContext.html#method.private_key 2559 #[corresponds(SSL_get_privatekey)] 2560 pub fn private_key(&self) -> Option<&PKeyRef<Private>> { 2561 unsafe { 2562 let ptr = ffi::SSL_get_privatekey(self.as_ptr()); 2563 PKeyRef::from_const_ptr_opt(ptr) 2564 } 2565 } 2566 2567 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")] 2568 pub fn version(&self) -> &str { 2569 self.version_str() 2570 } 2571 2572 /// Returns the protocol version of the session. 2573 #[corresponds(SSL_version)] 2574 pub fn version2(&self) -> Option<SslVersion> { 2575 unsafe { 2576 let r = ffi::SSL_version(self.as_ptr()); 2577 if r == 0 { 2578 None 2579 } else { 2580 Some(SslVersion(r)) 2581 } 2582 } 2583 } 2584 2585 /// Returns a string describing the protocol version of the session. 2586 #[corresponds(SSL_get_version)] 2587 pub fn version_str(&self) -> &'static str { 2588 let version = unsafe { 2589 let ptr = ffi::SSL_get_version(self.as_ptr()); 2590 CStr::from_ptr(ptr as *const _) 2591 }; 2592 2593 str::from_utf8(version.to_bytes()).unwrap() 2594 } 2595 2596 /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN). 2597 /// 2598 /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client 2599 /// to interpret it. 2600 /// 2601 /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer. 2602 #[corresponds(SSL_get0_alpn_selected)] 2603 #[cfg(any(ossl102, libressl261))] 2604 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { 2605 unsafe { 2606 let mut data: *const c_uchar = ptr::null(); 2607 let mut len: c_uint = 0; 2608 // Get the negotiated protocol from the SSL instance. 2609 // `data` will point at a `c_uchar` array; `len` will contain the length of this array. 2610 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len); 2611 2612 if data.is_null() { 2613 None 2614 } else { 2615 Some(slice::from_raw_parts(data, len as usize)) 2616 } 2617 } 2618 } 2619 2620 /// Enables the DTLS extension "use_srtp" as defined in RFC5764. 2621 /// 2622 /// This corresponds to [`SSL_set_tlsext_use_srtp`]. 2623 /// 2624 /// [`SSL_set_tlsext_use_srtp`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html 2625 #[corresponds(SSL_set_tlsext_use_srtp)] 2626 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> { 2627 unsafe { 2628 let cstr = CString::new(protocols).unwrap(); 2629 2630 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr()); 2631 // fun fact, set_tlsext_use_srtp has a reversed return code D: 2632 if r == 0 { 2633 Ok(()) 2634 } else { 2635 Err(ErrorStack::get()) 2636 } 2637 } 2638 } 2639 2640 /// Gets all SRTP profiles that are enabled for handshake via set_tlsext_use_srtp 2641 /// 2642 /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. 2643 /// 2644 /// This corresponds to [`SSL_get_srtp_profiles`]. 2645 /// 2646 /// [`SSL_get_srtp_profiles`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_tlsext_use_srtp.html 2647 #[corresponds(SSL_get_srtp_profiles)] 2648 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> { 2649 unsafe { 2650 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr()); 2651 2652 StackRef::from_const_ptr_opt(chain) 2653 } 2654 } 2655 2656 /// Gets the SRTP profile selected by handshake. 2657 /// 2658 /// DTLS extension "use_srtp" as defined in RFC5764 has to be enabled. 2659 #[corresponds(SSL_get_selected_srtp_profile)] 2660 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> { 2661 unsafe { 2662 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr()); 2663 2664 SrtpProtectionProfileRef::from_const_ptr_opt(profile) 2665 } 2666 } 2667 2668 /// Returns the number of bytes remaining in the currently processed TLS record. 2669 /// 2670 /// If this is greater than 0, the next call to `read` will not call down to the underlying 2671 /// stream. 2672 #[corresponds(SSL_pending)] 2673 pub fn pending(&self) -> usize { 2674 unsafe { ffi::SSL_pending(self.as_ptr()) as usize } 2675 } 2676 2677 /// Returns the servername sent by the client via Server Name Indication (SNI). 2678 /// 2679 /// It is only useful on the server side. 2680 /// 2681 /// # Note 2682 /// 2683 /// While the SNI specification requires that servernames be valid domain names (and therefore 2684 /// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client 2685 /// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns 2686 /// the raw bytes and does not have this restriction. 2687 /// 2688 /// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html 2689 #[corresponds(SSL_get_servername)] 2690 // FIXME maybe rethink in 0.11? 2691 pub fn servername(&self, type_: NameType) -> Option<&str> { 2692 self.servername_raw(type_) 2693 .and_then(|b| str::from_utf8(b).ok()) 2694 } 2695 2696 /// Returns the servername sent by the client via Server Name Indication (SNI). 2697 /// 2698 /// It is only useful on the server side. 2699 /// 2700 /// # Note 2701 /// 2702 /// Unlike `servername`, this method does not require the name be valid UTF-8. 2703 #[corresponds(SSL_get_servername)] 2704 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> { 2705 unsafe { 2706 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0); 2707 if name.is_null() { 2708 None 2709 } else { 2710 Some(CStr::from_ptr(name as *const _).to_bytes()) 2711 } 2712 } 2713 } 2714 2715 /// Changes the context corresponding to the current connection. 2716 /// 2717 /// It is most commonly used in the Server Name Indication (SNI) callback. 2718 #[corresponds(SSL_set_SSL_CTX)] 2719 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> { 2720 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) } 2721 } 2722 2723 /// Returns the context corresponding to the current connection. 2724 #[corresponds(SSL_get_SSL_CTX)] 2725 pub fn ssl_context(&self) -> &SslContextRef { 2726 unsafe { 2727 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); 2728 SslContextRef::from_ptr(ssl_ctx) 2729 } 2730 } 2731 2732 /// Returns a mutable reference to the X509 verification configuration. 2733 /// 2734 /// Requires OpenSSL 1.0.2 or newer. 2735 #[corresponds(SSL_get0_param)] 2736 #[cfg(any(ossl102, libressl261))] 2737 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { 2738 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } 2739 } 2740 2741 /// Returns the certificate verification result. 2742 #[corresponds(SSL_get_verify_result)] 2743 pub fn verify_result(&self) -> X509VerifyResult { 2744 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) } 2745 } 2746 2747 /// Returns a shared reference to the SSL session. 2748 #[corresponds(SSL_get_session)] 2749 pub fn session(&self) -> Option<&SslSessionRef> { 2750 unsafe { 2751 let p = ffi::SSL_get_session(self.as_ptr()); 2752 SslSessionRef::from_const_ptr_opt(p) 2753 } 2754 } 2755 2756 /// Copies the `client_random` value sent by the client in the TLS handshake into a buffer. 2757 /// 2758 /// Returns the number of bytes copied, or if the buffer is empty, the size of the `client_random` 2759 /// value. 2760 /// 2761 /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 2762 #[corresponds(SSL_get_client_random)] 2763 #[cfg(any(ossl110, libressl270))] 2764 pub fn client_random(&self, buf: &mut [u8]) -> usize { 2765 unsafe { 2766 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) 2767 } 2768 } 2769 2770 /// Copies the `server_random` value sent by the server in the TLS handshake into a buffer. 2771 /// 2772 /// Returns the number of bytes copied, or if the buffer is empty, the size of the `server_random` 2773 /// value. 2774 /// 2775 /// Requires OpenSSL 1.1.0 or LibreSSL 2.7.0 or newer. 2776 #[corresponds(SSL_get_server_random)] 2777 #[cfg(any(ossl110, libressl270))] 2778 pub fn server_random(&self, buf: &mut [u8]) -> usize { 2779 unsafe { 2780 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len()) 2781 } 2782 } 2783 2784 /// Derives keying material for application use in accordance to RFC 5705. 2785 #[corresponds(SSL_export_keying_material)] 2786 pub fn export_keying_material( 2787 &self, 2788 out: &mut [u8], 2789 label: &str, 2790 context: Option<&[u8]>, 2791 ) -> Result<(), ErrorStack> { 2792 unsafe { 2793 let (context, contextlen, use_context) = match context { 2794 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1), 2795 None => (ptr::null(), 0, 0), 2796 }; 2797 cvt(ffi::SSL_export_keying_material( 2798 self.as_ptr(), 2799 out.as_mut_ptr() as *mut c_uchar, 2800 out.len(), 2801 label.as_ptr() as *const c_char, 2802 label.len(), 2803 context, 2804 contextlen, 2805 use_context, 2806 )) 2807 .map(|_| ()) 2808 } 2809 } 2810 2811 /// Derives keying material for application use in accordance to RFC 5705. 2812 /// 2813 /// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no 2814 /// context. Therefore, unlike `export_keying_material`, `context` must always be supplied. 2815 /// 2816 /// Requires OpenSSL 1.1.1 or newer. 2817 #[corresponds(SSL_export_keying_material_early)] 2818 #[cfg(ossl111)] 2819 pub fn export_keying_material_early( 2820 &self, 2821 out: &mut [u8], 2822 label: &str, 2823 context: &[u8], 2824 ) -> Result<(), ErrorStack> { 2825 unsafe { 2826 cvt(ffi::SSL_export_keying_material_early( 2827 self.as_ptr(), 2828 out.as_mut_ptr() as *mut c_uchar, 2829 out.len(), 2830 label.as_ptr() as *const c_char, 2831 label.len(), 2832 context.as_ptr() as *const c_uchar, 2833 context.len(), 2834 )) 2835 .map(|_| ()) 2836 } 2837 } 2838 2839 /// Sets the session to be used. 2840 /// 2841 /// This should be called before the handshake to attempt to reuse a previously established 2842 /// session. If the server is not willing to reuse the session, a new one will be transparently 2843 /// negotiated. 2844 /// 2845 /// # Safety 2846 /// 2847 /// The caller of this method is responsible for ensuring that the session is associated 2848 /// with the same `SslContext` as this `Ssl`. 2849 #[corresponds(SSL_set_session)] 2850 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> { 2851 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ()) 2852 } 2853 2854 /// Determines if the session provided to `set_session` was successfully reused. 2855 #[corresponds(SSL_session_reused)] 2856 pub fn session_reused(&self) -> bool { 2857 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 } 2858 } 2859 2860 /// Sets the status response a client wishes the server to reply with. 2861 #[corresponds(SSL_set_tlsext_status_type)] 2862 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { 2863 unsafe { 2864 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ()) 2865 } 2866 } 2867 2868 /// Determines if current session used Extended Master Secret 2869 /// 2870 /// Returns `None` if the handshake is still in-progress. 2871 #[corresponds(SSL_get_extms_support)] 2872 #[cfg(ossl110)] 2873 pub fn extms_support(&self) -> Option<bool> { 2874 unsafe { 2875 match ffi::SSL_get_extms_support(self.as_ptr()) { 2876 -1 => None, 2877 ret => Some(ret != 0), 2878 } 2879 } 2880 } 2881 2882 /// Returns the server's OCSP response, if present. 2883 #[corresponds(SSL_get_tlsext_status_ocsp_resp)] 2884 #[cfg(not(boringssl))] 2885 pub fn ocsp_status(&self) -> Option<&[u8]> { 2886 unsafe { 2887 let mut p = ptr::null_mut(); 2888 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p); 2889 2890 if len < 0 { 2891 None 2892 } else { 2893 Some(slice::from_raw_parts(p as *const u8, len as usize)) 2894 } 2895 } 2896 } 2897 2898 /// Sets the OCSP response to be returned to the client. 2899 #[corresponds(SSL_set_tlsext_status_oscp_resp)] 2900 #[cfg(not(boringssl))] 2901 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> { 2902 unsafe { 2903 assert!(response.len() <= c_int::max_value() as usize); 2904 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?; 2905 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len()); 2906 cvt(ffi::SSL_set_tlsext_status_ocsp_resp( 2907 self.as_ptr(), 2908 p as *mut c_uchar, 2909 response.len() as c_long, 2910 ) as c_int) 2911 .map(|_| ()) 2912 .map_err(|e| { 2913 ffi::OPENSSL_free(p); 2914 e 2915 }) 2916 } 2917 } 2918 2919 /// Determines if this `Ssl` is configured for server-side or client-side use. 2920 #[corresponds(SSL_is_server)] 2921 pub fn is_server(&self) -> bool { 2922 unsafe { SSL_is_server(self.as_ptr()) != 0 } 2923 } 2924 2925 /// Sets the extra data at the specified index. 2926 /// 2927 /// This can be used to provide data to callbacks registered with the context. Use the 2928 /// `Ssl::new_ex_index` method to create an `Index`. 2929 #[corresponds(SSL_set_ex_data)] 2930 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) { 2931 unsafe { 2932 let data = Box::new(data); 2933 ffi::SSL_set_ex_data( 2934 self.as_ptr(), 2935 index.as_raw(), 2936 Box::into_raw(data) as *mut c_void, 2937 ); 2938 } 2939 } 2940 2941 /// Returns a reference to the extra data at the specified index. 2942 #[corresponds(SSL_get_ex_data)] 2943 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> { 2944 unsafe { 2945 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); 2946 if data.is_null() { 2947 None 2948 } else { 2949 Some(&*(data as *const T)) 2950 } 2951 } 2952 } 2953 2954 /// Returns a mutable reference to the extra data at the specified index. 2955 #[corresponds(SSL_get_ex_data)] 2956 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> { 2957 unsafe { 2958 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw()); 2959 if data.is_null() { 2960 None 2961 } else { 2962 Some(&mut *(data as *mut T)) 2963 } 2964 } 2965 } 2966 2967 /// Sets the maximum amount of early data that will be accepted on this connection. 2968 /// 2969 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 2970 #[corresponds(SSL_set_max_early_data)] 2971 #[cfg(any(ossl111, libressl340))] 2972 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> { 2973 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 { 2974 Ok(()) 2975 } else { 2976 Err(ErrorStack::get()) 2977 } 2978 } 2979 2980 /// Gets the maximum amount of early data that can be sent on this connection. 2981 /// 2982 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 2983 #[corresponds(SSL_get_max_early_data)] 2984 #[cfg(any(ossl111, libressl340))] 2985 pub fn max_early_data(&self) -> u32 { 2986 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) } 2987 } 2988 2989 /// Copies the contents of the last Finished message sent to the peer into the provided buffer. 2990 /// 2991 /// The total size of the message is returned, so this can be used to determine the size of the 2992 /// buffer required. 2993 #[corresponds(SSL_get_finished)] 2994 pub fn finished(&self, buf: &mut [u8]) -> usize { 2995 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) } 2996 } 2997 2998 /// Copies the contents of the last Finished message received from the peer into the provided 2999 /// buffer. 3000 /// 3001 /// The total size of the message is returned, so this can be used to determine the size of the 3002 /// buffer required. 3003 #[corresponds(SSL_get_peer_finished)] 3004 pub fn peer_finished(&self, buf: &mut [u8]) -> usize { 3005 unsafe { 3006 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) 3007 } 3008 } 3009 3010 /// Determines if the initial handshake has been completed. 3011 #[corresponds(SSL_is_init_finished)] 3012 #[cfg(ossl110)] 3013 pub fn is_init_finished(&self) -> bool { 3014 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 } 3015 } 3016 3017 /// Determines if the client's hello message is in the SSLv2 format. 3018 /// 3019 /// This can only be used inside of the client hello callback. Otherwise, `false` is returned. 3020 /// 3021 /// Requires OpenSSL 1.1.1 or newer. 3022 #[corresponds(SSL_client_hello_isv2)] 3023 #[cfg(ossl111)] 3024 pub fn client_hello_isv2(&self) -> bool { 3025 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 } 3026 } 3027 3028 /// Returns the legacy version field of the client's hello message. 3029 /// 3030 /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 3031 /// 3032 /// Requires OpenSSL 1.1.1 or newer. 3033 #[corresponds(SSL_client_hello_get0_legacy_version)] 3034 #[cfg(ossl111)] 3035 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> { 3036 unsafe { 3037 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr()); 3038 if version == 0 { 3039 None 3040 } else { 3041 Some(SslVersion(version as c_int)) 3042 } 3043 } 3044 } 3045 3046 /// Returns the random field of the client's hello message. 3047 /// 3048 /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 3049 /// 3050 /// Requires OpenSSL 1.1.1 or newer. 3051 #[corresponds(SSL_client_hello_get0_random)] 3052 #[cfg(ossl111)] 3053 pub fn client_hello_random(&self) -> Option<&[u8]> { 3054 unsafe { 3055 let mut ptr = ptr::null(); 3056 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr); 3057 if len == 0 { 3058 None 3059 } else { 3060 Some(slice::from_raw_parts(ptr, len)) 3061 } 3062 } 3063 } 3064 3065 /// Returns the session ID field of the client's hello message. 3066 /// 3067 /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 3068 /// 3069 /// Requires OpenSSL 1.1.1 or newer. 3070 #[corresponds(SSL_client_hello_get0_session_id)] 3071 #[cfg(ossl111)] 3072 pub fn client_hello_session_id(&self) -> Option<&[u8]> { 3073 unsafe { 3074 let mut ptr = ptr::null(); 3075 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr); 3076 if len == 0 { 3077 None 3078 } else { 3079 Some(slice::from_raw_parts(ptr, len)) 3080 } 3081 } 3082 } 3083 3084 /// Returns the ciphers field of the client's hello message. 3085 /// 3086 /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 3087 /// 3088 /// Requires OpenSSL 1.1.1 or newer. 3089 #[corresponds(SSL_client_hello_get0_ciphers)] 3090 #[cfg(ossl111)] 3091 pub fn client_hello_ciphers(&self) -> Option<&[u8]> { 3092 unsafe { 3093 let mut ptr = ptr::null(); 3094 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr); 3095 if len == 0 { 3096 None 3097 } else { 3098 Some(slice::from_raw_parts(ptr, len)) 3099 } 3100 } 3101 } 3102 3103 /// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites 3104 /// are ignored. 3105 /// 3106 /// Requires OpenSSL 1.1.1 or newer. 3107 #[corresponds(SSL_bytes_to_cipher_list)] 3108 #[cfg(ossl111)] 3109 pub fn bytes_to_cipher_list( 3110 &self, 3111 bytes: &[u8], 3112 isv2format: bool, 3113 ) -> Result<CipherLists, ErrorStack> { 3114 unsafe { 3115 let ptr = bytes.as_ptr(); 3116 let len = bytes.len(); 3117 let mut sk = ptr::null_mut(); 3118 let mut scsvs = ptr::null_mut(); 3119 let res = ffi::SSL_bytes_to_cipher_list( 3120 self.as_ptr(), 3121 ptr, 3122 len, 3123 isv2format as c_int, 3124 &mut sk, 3125 &mut scsvs, 3126 ); 3127 if res == 1 { 3128 Ok(CipherLists { 3129 suites: Stack::from_ptr(sk), 3130 signalling_suites: Stack::from_ptr(scsvs), 3131 }) 3132 } else { 3133 Err(ErrorStack::get()) 3134 } 3135 } 3136 } 3137 3138 /// Returns the compression methods field of the client's hello message. 3139 /// 3140 /// This can only be used inside of the client hello callback. Otherwise, `None` is returned. 3141 /// 3142 /// Requires OpenSSL 1.1.1 or newer. 3143 #[corresponds(SSL_client_hello_get0_compression_methods)] 3144 #[cfg(ossl111)] 3145 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> { 3146 unsafe { 3147 let mut ptr = ptr::null(); 3148 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr); 3149 if len == 0 { 3150 None 3151 } else { 3152 Some(slice::from_raw_parts(ptr, len)) 3153 } 3154 } 3155 } 3156 3157 /// Sets the MTU used for DTLS connections. 3158 #[corresponds(SSL_set_mtu)] 3159 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> { 3160 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) } 3161 } 3162 3163 /// Returns the PSK identity hint used during connection setup. 3164 /// 3165 /// May return `None` if no PSK identity hint was used during the connection setup. 3166 #[corresponds(SSL_get_psk_identity_hint)] 3167 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 3168 pub fn psk_identity_hint(&self) -> Option<&[u8]> { 3169 unsafe { 3170 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr()); 3171 if ptr.is_null() { 3172 None 3173 } else { 3174 Some(CStr::from_ptr(ptr).to_bytes()) 3175 } 3176 } 3177 } 3178 3179 /// Returns the PSK identity used during connection setup. 3180 #[corresponds(SSL_get_psk_identity)] 3181 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] 3182 pub fn psk_identity(&self) -> Option<&[u8]> { 3183 unsafe { 3184 let ptr = ffi::SSL_get_psk_identity(self.as_ptr()); 3185 if ptr.is_null() { 3186 None 3187 } else { 3188 Some(CStr::from_ptr(ptr).to_bytes()) 3189 } 3190 } 3191 } 3192 3193 #[corresponds(SSL_add0_chain_cert)] 3194 #[cfg(ossl102)] 3195 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> { 3196 unsafe { 3197 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?; 3198 mem::forget(chain); 3199 } 3200 Ok(()) 3201 } 3202 3203 /// Sets a new default TLS/SSL method for SSL objects 3204 #[cfg(not(boringssl))] 3205 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> { 3206 unsafe { 3207 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?; 3208 }; 3209 Ok(()) 3210 } 3211 3212 /// Loads the private key from a file. 3213 #[corresponds(SSL_use_Private_Key_file)] 3214 pub fn set_private_key_file<P: AsRef<Path>>( 3215 &mut self, 3216 path: P, 3217 ssl_file_type: SslFiletype, 3218 ) -> Result<(), ErrorStack> { 3219 let p = path.as_ref().as_os_str().to_str().unwrap(); 3220 let key_file = CString::new(p).unwrap(); 3221 unsafe { 3222 cvt(ffi::SSL_use_PrivateKey_file( 3223 self.as_ptr(), 3224 key_file.as_ptr(), 3225 ssl_file_type.as_raw(), 3226 ))?; 3227 }; 3228 Ok(()) 3229 } 3230 3231 /// Sets the private key. 3232 #[corresponds(SSL_use_PrivateKey)] 3233 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> { 3234 unsafe { 3235 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?; 3236 }; 3237 Ok(()) 3238 } 3239 3240 /// Sets the certificate 3241 #[corresponds(SSL_use_certificate)] 3242 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { 3243 unsafe { 3244 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?; 3245 }; 3246 Ok(()) 3247 } 3248 3249 /// Loads a certificate chain from a file. 3250 /// 3251 /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf 3252 /// certificate, and the remainder forming the chain of certificates up to and including the 3253 /// trusted root certificate. 3254 #[corresponds(SSL_use_certificate_chain_file)] 3255 #[cfg(any(ossl110, libressl332))] 3256 pub fn set_certificate_chain_file<P: AsRef<Path>>( 3257 &mut self, 3258 path: P, 3259 ) -> Result<(), ErrorStack> { 3260 let p = path.as_ref().as_os_str().to_str().unwrap(); 3261 let cert_file = CString::new(p).unwrap(); 3262 unsafe { 3263 cvt(ffi::SSL_use_certificate_chain_file( 3264 self.as_ptr(), 3265 cert_file.as_ptr(), 3266 ))?; 3267 }; 3268 Ok(()) 3269 } 3270 3271 /// Sets ca certificate that client trusted 3272 #[corresponds(SSL_add_client_CA)] 3273 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> { 3274 unsafe { 3275 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?; 3276 }; 3277 Ok(()) 3278 } 3279 3280 // Sets the list of CAs sent to the client when requesting a client certificate for the chosen ssl 3281 #[corresponds(SSL_set_client_CA_list)] 3282 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) { 3283 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) } 3284 mem::forget(list); 3285 } 3286 3287 /// Sets the minimum supported protocol version. 3288 /// 3289 /// A value of `None` will enable protocol versions down to the lowest version supported by 3290 /// OpenSSL. 3291 /// 3292 /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer. 3293 #[corresponds(SSL_set_min_proto_version)] 3294 #[cfg(any(ossl110, libressl261))] 3295 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 3296 unsafe { 3297 cvt(ffi::SSL_set_min_proto_version( 3298 self.as_ptr(), 3299 version.map_or(0, |v| v.0 as _), 3300 )) 3301 .map(|_| ()) 3302 } 3303 } 3304 3305 /// Sets the maximum supported protocol version. 3306 /// 3307 /// A value of `None` will enable protocol versions up to the highest version supported by 3308 /// OpenSSL. 3309 /// 3310 /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer. 3311 #[corresponds(SSL_set_max_proto_version)] 3312 #[cfg(any(ossl110, libressl261))] 3313 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { 3314 unsafe { 3315 cvt(ffi::SSL_set_max_proto_version( 3316 self.as_ptr(), 3317 version.map_or(0, |v| v.0 as _), 3318 )) 3319 .map(|_| ()) 3320 } 3321 } 3322 3323 /// Sets the list of supported ciphers for the TLSv1.3 protocol. 3324 /// 3325 /// The `set_cipher_list` method controls the cipher suites for protocols before TLSv1.3. 3326 /// 3327 /// The format consists of TLSv1.3 cipher suite names separated by `:` characters in order of 3328 /// preference. 3329 /// 3330 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 3331 #[corresponds(SSL_set_ciphersuites)] 3332 #[cfg(any(ossl111, libressl340))] 3333 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 3334 let cipher_list = CString::new(cipher_list).unwrap(); 3335 unsafe { 3336 cvt(ffi::SSL_set_ciphersuites( 3337 self.as_ptr(), 3338 cipher_list.as_ptr() as *const _, 3339 )) 3340 .map(|_| ()) 3341 } 3342 } 3343 3344 /// Sets the list of supported ciphers for protocols before TLSv1.3. 3345 /// 3346 /// The `set_ciphersuites` method controls the cipher suites for TLSv1.3. 3347 /// 3348 /// See [`ciphers`] for details on the format. 3349 /// 3350 /// [`ciphers`]: https://www.openssl.org/docs/manmaster/apps/ciphers.html 3351 #[corresponds(SSL_set_cipher_list)] 3352 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { 3353 let cipher_list = CString::new(cipher_list).unwrap(); 3354 unsafe { 3355 cvt(ffi::SSL_set_cipher_list( 3356 self.as_ptr(), 3357 cipher_list.as_ptr() as *const _, 3358 )) 3359 .map(|_| ()) 3360 } 3361 } 3362 3363 /// Set the certificate store used for certificate verification 3364 #[corresponds(SSL_set_cert_store)] 3365 #[cfg(ossl102)] 3366 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { 3367 unsafe { 3368 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?; 3369 mem::forget(cert_store); 3370 Ok(()) 3371 } 3372 } 3373 3374 /// Sets the number of TLS 1.3 session tickets that will be sent to a client after a full 3375 /// handshake. 3376 /// 3377 /// Requires OpenSSL 1.1.1 or newer. 3378 #[corresponds(SSL_set_num_tickets)] 3379 #[cfg(ossl111)] 3380 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> { 3381 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) } 3382 } 3383 3384 /// Gets the number of TLS 1.3 session tickets that will be sent to a client after a full 3385 /// handshake. 3386 /// 3387 /// Requires OpenSSL 1.1.1 or newer. 3388 #[corresponds(SSL_get_num_tickets)] 3389 #[cfg(ossl111)] 3390 pub fn num_tickets(&self) -> usize { 3391 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) } 3392 } 3393} 3394 3395/// An SSL stream midway through the handshake process. 3396#[derive(Debug)] 3397pub struct MidHandshakeSslStream<S> { 3398 stream: SslStream<S>, 3399 error: Error, 3400} 3401 3402impl<S> MidHandshakeSslStream<S> { 3403 /// Returns a shared reference to the inner stream. 3404 pub fn get_ref(&self) -> &S { 3405 self.stream.get_ref() 3406 } 3407 3408 /// Returns a mutable reference to the inner stream. 3409 pub fn get_mut(&mut self) -> &mut S { 3410 self.stream.get_mut() 3411 } 3412 3413 /// Returns a shared reference to the `Ssl` of the stream. 3414 pub fn ssl(&self) -> &SslRef { 3415 self.stream.ssl() 3416 } 3417 3418 /// Returns the underlying error which interrupted this handshake. 3419 pub fn error(&self) -> &Error { 3420 &self.error 3421 } 3422 3423 /// Consumes `self`, returning its error. 3424 pub fn into_error(self) -> Error { 3425 self.error 3426 } 3427} 3428 3429impl<S> MidHandshakeSslStream<S> 3430where 3431 S: Read + Write, 3432{ 3433 /// Restarts the handshake process. 3434 /// 3435 /// This corresponds to [`SSL_do_handshake`]. 3436 /// 3437 /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html 3438 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 3439 match self.stream.do_handshake() { 3440 Ok(()) => Ok(self.stream), 3441 Err(error) => { 3442 self.error = error; 3443 match self.error.code() { 3444 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 3445 Err(HandshakeError::WouldBlock(self)) 3446 } 3447 _ => Err(HandshakeError::Failure(self)), 3448 } 3449 } 3450 } 3451 } 3452} 3453 3454/// A TLS session over a stream. 3455pub struct SslStream<S> { 3456 ssl: ManuallyDrop<Ssl>, 3457 method: ManuallyDrop<BioMethod>, 3458 _p: PhantomData<S>, 3459} 3460 3461impl<S> Drop for SslStream<S> { 3462 fn drop(&mut self) { 3463 // ssl holds a reference to method internally so it has to drop first 3464 unsafe { 3465 ManuallyDrop::drop(&mut self.ssl); 3466 ManuallyDrop::drop(&mut self.method); 3467 } 3468 } 3469} 3470 3471impl<S> fmt::Debug for SslStream<S> 3472where 3473 S: fmt::Debug, 3474{ 3475 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 3476 fmt.debug_struct("SslStream") 3477 .field("stream", &self.get_ref()) 3478 .field("ssl", &self.ssl()) 3479 .finish() 3480 } 3481} 3482 3483impl<S: Read + Write> SslStream<S> { 3484 /// Creates a new `SslStream`. 3485 /// 3486 /// This function performs no IO; the stream will not have performed any part of the handshake 3487 /// with the peer. If the `Ssl` was configured with [`SslRef::set_connect_state`] or 3488 /// [`SslRef::set_accept_state`], the handshake can be performed automatically during the first 3489 /// call to read or write. Otherwise the `connect` and `accept` methods can be used to 3490 /// explicitly perform the handshake. 3491 #[corresponds(SSL_set_bio)] 3492 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> { 3493 let (bio, method) = bio::new(stream)?; 3494 unsafe { 3495 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio); 3496 } 3497 3498 Ok(SslStream { 3499 ssl: ManuallyDrop::new(ssl), 3500 method: ManuallyDrop::new(method), 3501 _p: PhantomData, 3502 }) 3503 } 3504 3505 /// Constructs an `SslStream` from a pointer to the underlying OpenSSL `SSL` struct. 3506 /// 3507 /// This is useful if the handshake has already been completed elsewhere. 3508 /// 3509 /// # Safety 3510 /// 3511 /// The caller must ensure the pointer is valid. 3512 #[deprecated( 3513 since = "0.10.32", 3514 note = "use Ssl::from_ptr and SslStream::new instead" 3515 )] 3516 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self { 3517 let ssl = Ssl::from_ptr(ssl); 3518 Self::new(ssl, stream).unwrap() 3519 } 3520 3521 /// Read application data transmitted by a client before handshake completion. 3522 /// 3523 /// Useful for reducing latency, but vulnerable to replay attacks. Call 3524 /// [`SslRef::set_accept_state`] first. 3525 /// 3526 /// Returns `Ok(0)` if all early data has been read. 3527 /// 3528 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 3529 #[corresponds(SSL_read_early_data)] 3530 #[cfg(any(ossl111, libressl340))] 3531 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 3532 let mut read = 0; 3533 let ret = unsafe { 3534 ffi::SSL_read_early_data( 3535 self.ssl.as_ptr(), 3536 buf.as_ptr() as *mut c_void, 3537 buf.len(), 3538 &mut read, 3539 ) 3540 }; 3541 match ret { 3542 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)), 3543 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read), 3544 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0), 3545 _ => unreachable!(), 3546 } 3547 } 3548 3549 /// Send data to the server without blocking on handshake completion. 3550 /// 3551 /// Useful for reducing latency, but vulnerable to replay attacks. Call 3552 /// [`SslRef::set_connect_state`] first. 3553 /// 3554 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 3555 #[corresponds(SSL_write_early_data)] 3556 #[cfg(any(ossl111, libressl340))] 3557 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> { 3558 let mut written = 0; 3559 let ret = unsafe { 3560 ffi::SSL_write_early_data( 3561 self.ssl.as_ptr(), 3562 buf.as_ptr() as *const c_void, 3563 buf.len(), 3564 &mut written, 3565 ) 3566 }; 3567 if ret > 0 { 3568 Ok(written) 3569 } else { 3570 Err(self.make_error(ret)) 3571 } 3572 } 3573 3574 /// Initiates a client-side TLS handshake. 3575 /// 3576 /// # Warning 3577 /// 3578 /// OpenSSL's default configuration is insecure. It is highly recommended to use 3579 /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. 3580 #[corresponds(SSL_connect)] 3581 pub fn connect(&mut self) -> Result<(), Error> { 3582 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) }; 3583 if ret > 0 { 3584 Ok(()) 3585 } else { 3586 Err(self.make_error(ret)) 3587 } 3588 } 3589 3590 /// Initiates a server-side TLS handshake. 3591 /// 3592 /// # Warning 3593 /// 3594 /// OpenSSL's default configuration is insecure. It is highly recommended to use 3595 /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. 3596 #[corresponds(SSL_accept)] 3597 pub fn accept(&mut self) -> Result<(), Error> { 3598 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) }; 3599 if ret > 0 { 3600 Ok(()) 3601 } else { 3602 Err(self.make_error(ret)) 3603 } 3604 } 3605 3606 /// Initiates the handshake. 3607 /// 3608 /// This will fail if `set_accept_state` or `set_connect_state` was not called first. 3609 #[corresponds(SSL_do_handshake)] 3610 pub fn do_handshake(&mut self) -> Result<(), Error> { 3611 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) }; 3612 if ret > 0 { 3613 Ok(()) 3614 } else { 3615 Err(self.make_error(ret)) 3616 } 3617 } 3618 3619 /// Perform a stateless server-side handshake. 3620 /// 3621 /// Requires that cookie generation and verification callbacks were 3622 /// set on the SSL context. 3623 /// 3624 /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie 3625 /// was read, in which case the handshake should be continued via 3626 /// `accept`. If a HelloRetryRequest containing a fresh cookie was 3627 /// transmitted, `Ok(false)` is returned instead. If the handshake cannot 3628 /// proceed at all, `Err` is returned. 3629 #[corresponds(SSL_stateless)] 3630 #[cfg(ossl111)] 3631 pub fn stateless(&mut self) -> Result<bool, ErrorStack> { 3632 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } { 3633 1 => Ok(true), 3634 0 => Ok(false), 3635 -1 => Err(ErrorStack::get()), 3636 _ => unreachable!(), 3637 } 3638 } 3639 3640 /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. 3641 /// 3642 /// It is particularly useful with a non-blocking socket, where the error value will identify if 3643 /// OpenSSL is waiting on read or write readiness. 3644 #[corresponds(SSL_read)] 3645 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 3646 // The interpretation of the return code here is a little odd with a 3647 // zero-length write. OpenSSL will likely correctly report back to us 3648 // that it read zero bytes, but zero is also the sentinel for "error". 3649 // To avoid that confusion short-circuit that logic and return quickly 3650 // if `buf` has a length of zero. 3651 if buf.is_empty() { 3652 return Ok(0); 3653 } 3654 3655 let ret = self.ssl.read(buf); 3656 if ret > 0 { 3657 Ok(ret as usize) 3658 } else { 3659 Err(self.make_error(ret)) 3660 } 3661 } 3662 3663 /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`. 3664 /// 3665 /// It is particularly useful with a non-blocking socket, where the error value will identify if 3666 /// OpenSSL is waiting on read or write readiness. 3667 #[corresponds(SSL_write)] 3668 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> { 3669 // See above for why we short-circuit on zero-length buffers 3670 if buf.is_empty() { 3671 return Ok(0); 3672 } 3673 3674 let ret = self.ssl.write(buf); 3675 if ret > 0 { 3676 Ok(ret as usize) 3677 } else { 3678 Err(self.make_error(ret)) 3679 } 3680 } 3681 3682 /// Reads data from the stream, without removing it from the queue. 3683 #[corresponds(SSL_peek)] 3684 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 3685 // See above for why we short-circuit on zero-length buffers 3686 if buf.is_empty() { 3687 return Ok(0); 3688 } 3689 3690 let ret = self.ssl.peek(buf); 3691 if ret > 0 { 3692 Ok(ret as usize) 3693 } else { 3694 Err(self.make_error(ret)) 3695 } 3696 } 3697 3698 /// Shuts down the session. 3699 /// 3700 /// The shutdown process consists of two steps. The first step sends a close notify message to 3701 /// the peer, after which `ShutdownResult::Sent` is returned. The second step awaits the receipt 3702 /// of a close notify message from the peer, after which `ShutdownResult::Received` is returned. 3703 /// 3704 /// While the connection may be closed after the first step, it is recommended to fully shut the 3705 /// session down. In particular, it must be fully shut down if the connection is to be used for 3706 /// further communication in the future. 3707 #[corresponds(SSL_shutdown)] 3708 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> { 3709 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { 3710 0 => Ok(ShutdownResult::Sent), 3711 1 => Ok(ShutdownResult::Received), 3712 n => Err(self.make_error(n)), 3713 } 3714 } 3715 3716 /// Returns the session's shutdown state. 3717 #[corresponds(SSL_get_shutdown)] 3718 pub fn get_shutdown(&mut self) -> ShutdownState { 3719 unsafe { 3720 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr()); 3721 ShutdownState { bits } 3722 } 3723 } 3724 3725 /// Sets the session's shutdown state. 3726 /// 3727 /// This can be used to tell OpenSSL that the session should be cached even if a full two-way 3728 /// shutdown was not completed. 3729 #[corresponds(SSL_set_shutdown)] 3730 pub fn set_shutdown(&mut self, state: ShutdownState) { 3731 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) } 3732 } 3733} 3734 3735impl<S> SslStream<S> { 3736 fn make_error(&mut self, ret: c_int) -> Error { 3737 self.check_panic(); 3738 3739 let code = self.ssl.get_error(ret); 3740 3741 let cause = match code { 3742 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())), 3743 ErrorCode::SYSCALL => { 3744 let errs = ErrorStack::get(); 3745 if errs.errors().is_empty() { 3746 self.get_bio_error().map(InnerError::Io) 3747 } else { 3748 Some(InnerError::Ssl(errs)) 3749 } 3750 } 3751 ErrorCode::ZERO_RETURN => None, 3752 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 3753 self.get_bio_error().map(InnerError::Io) 3754 } 3755 _ => None, 3756 }; 3757 3758 Error { code, cause } 3759 } 3760 3761 fn check_panic(&mut self) { 3762 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } { 3763 resume_unwind(err) 3764 } 3765 } 3766 3767 fn get_bio_error(&mut self) -> Option<io::Error> { 3768 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) } 3769 } 3770 3771 /// Returns a shared reference to the underlying stream. 3772 pub fn get_ref(&self) -> &S { 3773 unsafe { 3774 let bio = self.ssl.get_raw_rbio(); 3775 bio::get_ref(bio) 3776 } 3777 } 3778 3779 /// Returns a mutable reference to the underlying stream. 3780 /// 3781 /// # Warning 3782 /// 3783 /// It is inadvisable to read from or write to the underlying stream as it 3784 /// will most likely corrupt the SSL session. 3785 pub fn get_mut(&mut self) -> &mut S { 3786 unsafe { 3787 let bio = self.ssl.get_raw_rbio(); 3788 bio::get_mut(bio) 3789 } 3790 } 3791 3792 /// Returns a shared reference to the `Ssl` object associated with this stream. 3793 pub fn ssl(&self) -> &SslRef { 3794 &self.ssl 3795 } 3796} 3797 3798impl<S: Read + Write> Read for SslStream<S> { 3799 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { 3800 loop { 3801 match self.ssl_read(buf) { 3802 Ok(n) => return Ok(n), 3803 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0), 3804 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => { 3805 return Ok(0); 3806 } 3807 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} 3808 Err(e) => { 3809 return Err(e 3810 .into_io_error() 3811 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); 3812 } 3813 } 3814 } 3815 } 3816} 3817 3818impl<S: Read + Write> Write for SslStream<S> { 3819 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { 3820 loop { 3821 match self.ssl_write(buf) { 3822 Ok(n) => return Ok(n), 3823 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} 3824 Err(e) => { 3825 return Err(e 3826 .into_io_error() 3827 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))); 3828 } 3829 } 3830 } 3831 } 3832 3833 fn flush(&mut self) -> io::Result<()> { 3834 self.get_mut().flush() 3835 } 3836} 3837 3838/// A partially constructed `SslStream`, useful for unusual handshakes. 3839#[deprecated( 3840 since = "0.10.32", 3841 note = "use the methods directly on Ssl/SslStream instead" 3842)] 3843pub struct SslStreamBuilder<S> { 3844 inner: SslStream<S>, 3845} 3846 3847#[allow(deprecated)] 3848impl<S> SslStreamBuilder<S> 3849where 3850 S: Read + Write, 3851{ 3852 /// Begin creating an `SslStream` atop `stream` 3853 pub fn new(ssl: Ssl, stream: S) -> Self { 3854 Self { 3855 inner: SslStream::new(ssl, stream).unwrap(), 3856 } 3857 } 3858 3859 /// Perform a stateless server-side handshake 3860 /// 3861 /// Requires that cookie generation and verification callbacks were 3862 /// set on the SSL context. 3863 /// 3864 /// Returns `Ok(true)` if a complete ClientHello containing a valid cookie 3865 /// was read, in which case the handshake should be continued via 3866 /// `accept`. If a HelloRetryRequest containing a fresh cookie was 3867 /// transmitted, `Ok(false)` is returned instead. If the handshake cannot 3868 /// proceed at all, `Err` is returned. 3869 /// 3870 /// This corresponds to [`SSL_stateless`] 3871 /// 3872 /// [`SSL_stateless`]: https://www.openssl.org/docs/manmaster/man3/SSL_stateless.html 3873 #[cfg(ossl111)] 3874 pub fn stateless(&mut self) -> Result<bool, ErrorStack> { 3875 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } { 3876 1 => Ok(true), 3877 0 => Ok(false), 3878 -1 => Err(ErrorStack::get()), 3879 _ => unreachable!(), 3880 } 3881 } 3882 3883 /// Configure as an outgoing stream from a client. 3884 /// 3885 /// This corresponds to [`SSL_set_connect_state`]. 3886 /// 3887 /// [`SSL_set_connect_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_connect_state.html 3888 pub fn set_connect_state(&mut self) { 3889 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) } 3890 } 3891 3892 /// Configure as an incoming stream to a server. 3893 /// 3894 /// This corresponds to [`SSL_set_accept_state`]. 3895 /// 3896 /// [`SSL_set_accept_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_accept_state.html 3897 pub fn set_accept_state(&mut self) { 3898 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) } 3899 } 3900 3901 /// See `Ssl::connect` 3902 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 3903 match self.inner.connect() { 3904 Ok(()) => Ok(self.inner), 3905 Err(error) => match error.code() { 3906 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 3907 Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 3908 stream: self.inner, 3909 error, 3910 })) 3911 } 3912 _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 3913 stream: self.inner, 3914 error, 3915 })), 3916 }, 3917 } 3918 } 3919 3920 /// See `Ssl::accept` 3921 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 3922 match self.inner.accept() { 3923 Ok(()) => Ok(self.inner), 3924 Err(error) => match error.code() { 3925 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 3926 Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 3927 stream: self.inner, 3928 error, 3929 })) 3930 } 3931 _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 3932 stream: self.inner, 3933 error, 3934 })), 3935 }, 3936 } 3937 } 3938 3939 /// Initiates the handshake. 3940 /// 3941 /// This will fail if `set_accept_state` or `set_connect_state` was not called first. 3942 /// 3943 /// This corresponds to [`SSL_do_handshake`]. 3944 /// 3945 /// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html 3946 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> { 3947 match self.inner.do_handshake() { 3948 Ok(()) => Ok(self.inner), 3949 Err(error) => match error.code() { 3950 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => { 3951 Err(HandshakeError::WouldBlock(MidHandshakeSslStream { 3952 stream: self.inner, 3953 error, 3954 })) 3955 } 3956 _ => Err(HandshakeError::Failure(MidHandshakeSslStream { 3957 stream: self.inner, 3958 error, 3959 })), 3960 }, 3961 } 3962 } 3963 3964 /// Read application data transmitted by a client before handshake 3965 /// completion. 3966 /// 3967 /// Useful for reducing latency, but vulnerable to replay attacks. Call 3968 /// `set_accept_state` first. 3969 /// 3970 /// Returns `Ok(0)` if all early data has been read. 3971 /// 3972 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 3973 /// 3974 /// This corresponds to [`SSL_read_early_data`]. 3975 /// 3976 /// [`SSL_read_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_read_early_data.html 3977 #[cfg(any(ossl111, libressl340))] 3978 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> { 3979 self.inner.read_early_data(buf) 3980 } 3981 3982 /// Send data to the server without blocking on handshake completion. 3983 /// 3984 /// Useful for reducing latency, but vulnerable to replay attacks. Call 3985 /// `set_connect_state` first. 3986 /// 3987 /// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer. 3988 /// 3989 /// This corresponds to [`SSL_write_early_data`]. 3990 /// 3991 /// [`SSL_write_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_write_early_data.html 3992 #[cfg(any(ossl111, libressl340))] 3993 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> { 3994 self.inner.write_early_data(buf) 3995 } 3996} 3997 3998#[allow(deprecated)] 3999impl<S> SslStreamBuilder<S> { 4000 /// Returns a shared reference to the underlying stream. 4001 pub fn get_ref(&self) -> &S { 4002 unsafe { 4003 let bio = self.inner.ssl.get_raw_rbio(); 4004 bio::get_ref(bio) 4005 } 4006 } 4007 4008 /// Returns a mutable reference to the underlying stream. 4009 /// 4010 /// # Warning 4011 /// 4012 /// It is inadvisable to read from or write to the underlying stream as it 4013 /// will most likely corrupt the SSL session. 4014 pub fn get_mut(&mut self) -> &mut S { 4015 unsafe { 4016 let bio = self.inner.ssl.get_raw_rbio(); 4017 bio::get_mut(bio) 4018 } 4019 } 4020 4021 /// Returns a shared reference to the `Ssl` object associated with this builder. 4022 pub fn ssl(&self) -> &SslRef { 4023 &self.inner.ssl 4024 } 4025 4026 /// Set the DTLS MTU size. 4027 /// 4028 /// It will be ignored if the value is smaller than the minimum packet size 4029 /// the DTLS protocol requires. 4030 /// 4031 /// # Panics 4032 /// This function panics if the given mtu size can't be represented in a positive `c_long` range 4033 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")] 4034 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) { 4035 unsafe { 4036 let bio = self.inner.ssl.get_raw_rbio(); 4037 bio::set_dtls_mtu_size::<S>(bio, mtu_size); 4038 } 4039 } 4040} 4041 4042/// The result of a shutdown request. 4043#[derive(Copy, Clone, Debug, PartialEq, Eq)] 4044pub enum ShutdownResult { 4045 /// A close notify message has been sent to the peer. 4046 Sent, 4047 4048 /// A close notify response message has been received from the peer. 4049 Received, 4050} 4051 4052bitflags! { 4053 /// The shutdown state of a session. 4054 pub struct ShutdownState: c_int { 4055 /// A close notify message has been sent to the peer. 4056 const SENT = ffi::SSL_SENT_SHUTDOWN; 4057 /// A close notify message has been received from the peer. 4058 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN; 4059 } 4060} 4061 4062cfg_if! { 4063 if #[cfg(any(boringssl, ossl110, libressl273))] { 4064 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; 4065 } else { 4066 #[allow(bad_style)] 4067 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int { 4068 ffi::CRYPTO_add_lock( 4069 &mut (*ssl).references, 4070 1, 4071 ffi::CRYPTO_LOCK_SSL_CTX, 4072 "mod.rs\0".as_ptr() as *const _, 4073 line!() as c_int, 4074 ); 4075 0 4076 } 4077 4078 #[allow(bad_style)] 4079 pub unsafe fn SSL_SESSION_get_master_key( 4080 session: *const ffi::SSL_SESSION, 4081 out: *mut c_uchar, 4082 mut outlen: usize, 4083 ) -> usize { 4084 if outlen == 0 { 4085 return (*session).master_key_length as usize; 4086 } 4087 if outlen > (*session).master_key_length as usize { 4088 outlen = (*session).master_key_length as usize; 4089 } 4090 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen); 4091 outlen 4092 } 4093 4094 #[allow(bad_style)] 4095 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int { 4096 (*s).server 4097 } 4098 4099 #[allow(bad_style)] 4100 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { 4101 ffi::CRYPTO_add_lock( 4102 &mut (*ses).references, 4103 1, 4104 ffi::CRYPTO_LOCK_SSL_CTX, 4105 "mod.rs\0".as_ptr() as *const _, 4106 line!() as c_int, 4107 ); 4108 0 4109 } 4110 } 4111} 4112 4113cfg_if! { 4114 if #[cfg(ossl300)] { 4115 use ffi::SSL_get1_peer_certificate; 4116 } else { 4117 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate; 4118 } 4119} 4120cfg_if! { 4121 if #[cfg(any(boringssl, ossl110, libressl291))] { 4122 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method}; 4123 } else { 4124 use ffi::{ 4125 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method, 4126 SSLv23_server_method as TLS_server_method, 4127 }; 4128 } 4129} 4130cfg_if! { 4131 if #[cfg(ossl110)] { 4132 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { 4133 ffi::CRYPTO_get_ex_new_index( 4134 ffi::CRYPTO_EX_INDEX_SSL_CTX, 4135 0, 4136 ptr::null_mut(), 4137 None, 4138 None, 4139 Some(f), 4140 ) 4141 } 4142 4143 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { 4144 ffi::CRYPTO_get_ex_new_index( 4145 ffi::CRYPTO_EX_INDEX_SSL, 4146 0, 4147 ptr::null_mut(), 4148 None, 4149 None, 4150 Some(f), 4151 ) 4152 } 4153 } else { 4154 use std::sync::Once; 4155 4156 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { 4157 // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest 4158 static ONCE: Once = Once::new(); 4159 ONCE.call_once(|| { 4160 cfg_if! { 4161 if #[cfg(not(boringssl))] { 4162 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None); 4163 } else { 4164 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); 4165 } 4166 } 4167 }); 4168 4169 cfg_if! { 4170 if #[cfg(not(boringssl))] { 4171 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) 4172 } else { 4173 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f) 4174 } 4175 } 4176 } 4177 4178 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int { 4179 // hack around https://rt.openssl.org/Ticket/Display.html?id=3710&user=guest&pass=guest 4180 static ONCE: Once = Once::new(); 4181 ONCE.call_once(|| { 4182 #[cfg(not(boringssl))] 4183 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None); 4184 #[cfg(boringssl)] 4185 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None); 4186 }); 4187 4188 #[cfg(not(boringssl))] 4189 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)); 4190 #[cfg(boringssl)] 4191 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f); 4192 } 4193 } 4194} 4195