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