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