Skip to main content

openssl/ssl/
mod.rs

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