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