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