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