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