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