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