Coverage Report

Created: 2025-08-28 06:06

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