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