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