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