1use crate::cipher_ctx::CipherCtxRef;
61#[cfg(ossl300)]
62use crate::cvt_long;
63use crate::dh::{Dh, DhRef};
64use crate::ec::EcKeyRef;
65use crate::error::ErrorStack;
66use crate::ex_data::Index;
67#[cfg(ossl111)]
68use crate::hash::MessageDigest;
69use crate::hmac::HMacCtxRef;
70#[cfg(ossl300)]
71use crate::mac_ctx::MacCtxRef;
72#[cfg(any(ossl110, libressl270))]
73use crate::nid::Nid;
74use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
75#[cfg(ossl300)]
76use crate::pkey::{PKey, Public};
77#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
78use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
79use crate::ssl::bio::BioMethod;
80use crate::ssl::callbacks::*;
81use crate::ssl::error::InnerError;
82use crate::stack::{Stack, StackRef, Stackable};
83use crate::util;
84use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
85use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
86#[cfg(any(ossl102, boringssl, libressl261, awslc))]
87use crate::x509::verify::X509VerifyParamRef;
88use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
89use crate::{cvt, cvt_n, cvt_p, init};
90use bitflags::bitflags;
91use cfg_if::cfg_if;
92use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
93use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
94use once_cell::sync::{Lazy, OnceCell};
95use openssl_macros::corresponds;
96use std::any::TypeId;
97use std::collections::HashMap;
98use std::ffi::{CStr, CString};
99use std::fmt;
100use std::io;
101use std::io::prelude::*;
102use std::marker::PhantomData;
103use std::mem::{self, ManuallyDrop, MaybeUninit};
104use std::ops::{Deref, DerefMut};
105use std::panic::resume_unwind;
106use std::path::Path;
107use std::ptr;
108use std::str;
109use std::sync::{Arc, Mutex};
110
111pub use crate::ssl::connector::{
112 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
113};
114pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
115
116mod bio;
117mod callbacks;
118#[cfg(any(boringssl, awslc))]
119mod client_hello;
120mod connector;
121mod error;
122#[cfg(test)]
123mod test;
124
125#[cfg(any(boringssl, awslc))]
126pub use client_hello::ClientHello;
127
128#[corresponds(OPENSSL_cipher_name)]
134#[cfg(ossl111)]
135pub fn cipher_name(std_name: &str) -> &'static str {
136 unsafe {
137 ffi::init();
138
139 let s = CString::new(std_name).unwrap();
140 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
141 CStr::from_ptr(ptr).to_str().unwrap()
142 }
143}
144
145cfg_if! {
146 if #[cfg(ossl300)] {
147 type SslOptionsRepr = u64;
148 } else if #[cfg(any(boringssl, awslc))] {
149 type SslOptionsRepr = u32;
150 } else {
151 type SslOptionsRepr = libc::c_ulong;
152 }
153}
154
155bitflags! {
156 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
158 #[repr(transparent)]
159 pub struct SslOptions: SslOptionsRepr {
160 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
162
163 #[cfg(not(any(boringssl, awslc)))]
165 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
166
167 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
171
172 #[cfg(not(any(boringssl, awslc)))]
178 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
179
180 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
182
183 #[cfg(not(any(boringssl, awslc)))]
185 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
186 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
187
188 #[cfg(not(any(boringssl, awslc)))]
190 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
191
192 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
195 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
196
197 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
201
202 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
206
207 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
211
212 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
214
215 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
217
218 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
220
221 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
223
224 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
226
227 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
229
230 #[cfg(any(boringssl, ossl111, libressl340, awslc))]
234 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
235
236 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
240 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
241
242 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
246 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
247
248 #[cfg(any(ossl102, ossl110))]
264 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
265
266 #[cfg(any(boringssl, ossl110h, awslc))]
270 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
271
272 #[cfg(ossl111)]
277 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
278
279 #[cfg(ossl111)]
291 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
292 }
293}
294
295bitflags! {
296 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
298 #[repr(transparent)]
299 pub struct SslMode: SslBitType {
300 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
306
307 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
310
311 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
321
322 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
328
329 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
333
334 #[cfg(not(libressl))]
342 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
343
344 #[cfg(ossl110)]
351 const ASYNC = ffi::SSL_MODE_ASYNC;
352 }
353}
354
355#[derive(Copy, Clone)]
357pub struct SslMethod(*const ffi::SSL_METHOD);
358
359impl SslMethod {
360 #[corresponds(TLS_method)]
362 pub fn tls() -> SslMethod {
363 unsafe { SslMethod(TLS_method()) }
364 }
365
366 #[corresponds(DTLS_method)]
368 pub fn dtls() -> SslMethod {
369 unsafe { SslMethod(DTLS_method()) }
370 }
371
372 #[corresponds(TLS_client_method)]
374 pub fn tls_client() -> SslMethod {
375 unsafe { SslMethod(TLS_client_method()) }
376 }
377
378 #[corresponds(TLS_server_method)]
380 pub fn tls_server() -> SslMethod {
381 unsafe { SslMethod(TLS_server_method()) }
382 }
383
384 #[cfg(tongsuo)]
385 #[corresponds(NTLS_client_method)]
386 pub fn ntls_client() -> SslMethod {
387 unsafe { SslMethod(ffi::NTLS_client_method()) }
388 }
389
390 #[cfg(tongsuo)]
391 #[corresponds(NTLS_server_method)]
392 pub fn ntls_server() -> SslMethod {
393 unsafe { SslMethod(ffi::NTLS_server_method()) }
394 }
395
396 #[corresponds(DTLS_client_method)]
398 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
399 pub fn dtls_client() -> SslMethod {
400 unsafe { SslMethod(DTLS_client_method()) }
401 }
402
403 #[corresponds(DTLS_server_method)]
405 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
406 pub fn dtls_server() -> SslMethod {
407 unsafe { SslMethod(DTLS_server_method()) }
408 }
409
410 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
416 SslMethod(ptr)
417 }
418
419 #[allow(clippy::trivially_copy_pass_by_ref)]
421 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
422 self.0
423 }
424}
425
426unsafe impl Sync for SslMethod {}
427unsafe impl Send for SslMethod {}
428
429bitflags! {
430 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
432 #[repr(transparent)]
433 pub struct SslVerifyMode: i32 {
434 const PEER = ffi::SSL_VERIFY_PEER;
438
439 const NONE = ffi::SSL_VERIFY_NONE;
445
446 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
450 }
451}
452
453#[cfg(any(boringssl, awslc))]
454type SslBitType = c_int;
455#[cfg(not(any(boringssl, awslc)))]
456type SslBitType = c_long;
457
458#[cfg(any(boringssl, awslc))]
459type SslTimeTy = u64;
460#[cfg(not(any(boringssl, awslc)))]
461type SslTimeTy = c_long;
462
463bitflags! {
464 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
466 #[repr(transparent)]
467 pub struct SslSessionCacheMode: SslBitType {
468 const OFF = ffi::SSL_SESS_CACHE_OFF;
470
471 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
478
479 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
483
484 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
486
487 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
489
490 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
492
493 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
495
496 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
498 }
499}
500
501#[cfg(ossl111)]
502bitflags! {
503 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
505 #[repr(transparent)]
506 pub struct ExtensionContext: c_uint {
507 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
509 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
511 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
513 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
515 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
517 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
519 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
521 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
522 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
524 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
525 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
526 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
527 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
528 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
529 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
530 }
531}
532
533#[derive(Copy, Clone)]
535pub struct TlsExtType(c_uint);
536
537impl TlsExtType {
538 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
542
543 pub const ALPN: TlsExtType =
547 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
548
549 pub fn from_raw(raw: c_uint) -> TlsExtType {
551 TlsExtType(raw)
552 }
553
554 #[allow(clippy::trivially_copy_pass_by_ref)]
556 pub fn as_raw(&self) -> c_uint {
557 self.0
558 }
559}
560
561#[derive(Copy, Clone)]
563pub struct SslFiletype(c_int);
564
565impl SslFiletype {
566 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
570
571 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
575
576 pub fn from_raw(raw: c_int) -> SslFiletype {
578 SslFiletype(raw)
579 }
580
581 #[allow(clippy::trivially_copy_pass_by_ref)]
583 pub fn as_raw(&self) -> c_int {
584 self.0
585 }
586}
587
588#[derive(Copy, Clone)]
590pub struct StatusType(c_int);
591
592impl StatusType {
593 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
595
596 pub fn from_raw(raw: c_int) -> StatusType {
598 StatusType(raw)
599 }
600
601 #[allow(clippy::trivially_copy_pass_by_ref)]
603 pub fn as_raw(&self) -> c_int {
604 self.0
605 }
606}
607
608#[derive(Copy, Clone)]
610pub struct NameType(c_int);
611
612impl NameType {
613 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
615
616 pub fn from_raw(raw: c_int) -> StatusType {
618 StatusType(raw)
619 }
620
621 #[allow(clippy::trivially_copy_pass_by_ref)]
623 pub fn as_raw(&self) -> c_int {
624 self.0
625 }
626}
627
628static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
629static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
630static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
631
632fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
633 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
634}
635
636unsafe extern "C" fn free_data_box<T>(
637 _parent: *mut c_void,
638 ptr: *mut c_void,
639 _ad: *mut ffi::CRYPTO_EX_DATA,
640 _idx: c_int,
641 _argl: c_long,
642 _argp: *mut c_void,
643) {
644 if !ptr.is_null() {
645 let _ = Box::<T>::from_raw(ptr as *mut T);
646 }
647}
648
649#[derive(Debug, Copy, Clone, PartialEq, Eq)]
651pub struct SniError(c_int);
652
653impl SniError {
654 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
656
657 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
659
660 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
661}
662
663#[derive(Debug, Copy, Clone, PartialEq, Eq)]
665pub struct SslAlert(c_int);
666
667impl SslAlert {
668 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
670 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
671 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
672 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
673}
674
675#[derive(Debug, Copy, Clone, PartialEq, Eq)]
677pub struct AlpnError(c_int);
678
679impl AlpnError {
680 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
682
683 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
685}
686
687#[cfg(ossl111)]
691#[derive(Debug, Copy, Clone, PartialEq, Eq)]
692pub struct ClientHelloError(c_int);
693
694#[cfg(ossl111)]
695impl ClientHelloError {
696 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
698
699 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
701}
702
703#[derive(Debug, Copy, Clone, PartialEq, Eq)]
705pub struct TicketKeyStatus(c_int);
706
707impl TicketKeyStatus {
708 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
710 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
712 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
714}
715
716#[derive(Debug, Copy, Clone, PartialEq, Eq)]
718#[cfg(any(boringssl, awslc))]
719pub struct SelectCertError(ffi::ssl_select_cert_result_t);
720
721#[cfg(any(boringssl, awslc))]
722impl SelectCertError {
723 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
725
726 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
728
729 #[cfg(boringssl)]
735 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
736}
737
738#[cfg(ossl111)]
740#[derive(Debug, Copy, Clone, PartialEq, Eq)]
741pub struct SslCtValidationMode(c_int);
742
743#[cfg(ossl111)]
744impl SslCtValidationMode {
745 pub const PERMISSIVE: SslCtValidationMode =
746 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
747 pub const STRICT: SslCtValidationMode =
748 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
749}
750
751#[derive(Debug, Copy, Clone, PartialEq, Eq)]
753pub struct CertCompressionAlgorithm(c_int);
754
755impl CertCompressionAlgorithm {
756 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
757 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
758 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
759}
760
761#[derive(Debug, Copy, Clone, PartialEq, Eq)]
763pub struct SslVersion(c_int);
764
765impl SslVersion {
766 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
768
769 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
771
772 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
774
775 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
777
778 #[cfg(any(ossl111, libressl340, boringssl, awslc))]
782 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
783
784 #[cfg(tongsuo)]
785 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
786
787 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
791
792 #[cfg(any(ossl102, libressl332, boringssl, awslc))]
796 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
797}
798
799cfg_if! {
800 if #[cfg(any(boringssl, awslc))] {
801 type SslCacheTy = i64;
802 type SslCacheSize = libc::c_ulong;
803 type MtuTy = u32;
804 type ModeTy = u32;
805 type SizeTy = usize;
806 } else {
807 type SslCacheTy = i64;
808 type SslCacheSize = c_long;
809 type MtuTy = c_long;
810 type ModeTy = c_long;
811 type SizeTy = u32;
812 }
813}
814
815#[corresponds(SSL_select_next_proto)]
826pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
827 unsafe {
828 let mut out = ptr::null_mut();
829 let mut outlen = 0;
830 let r = ffi::SSL_select_next_proto(
831 &mut out,
832 &mut outlen,
833 server.as_ptr(),
834 server.len() as c_uint,
835 client.as_ptr(),
836 client.len() as c_uint,
837 );
838 if r == ffi::OPENSSL_NPN_NEGOTIATED {
839 Some(util::from_raw_parts(out as *const u8, outlen as usize))
840 } else {
841 None
842 }
843 }
844}
845
846pub struct SslContextBuilder(SslContext);
848
849impl SslContextBuilder {
850 #[corresponds(SSL_CTX_new)]
852 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
853 unsafe {
854 init();
855 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
856
857 Ok(SslContextBuilder::from_ptr(ctx))
858 }
859 }
860
861 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
867 SslContextBuilder(SslContext::from_ptr(ctx))
868 }
869
870 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
872 self.0.as_ptr()
873 }
874
875 #[cfg(tongsuo)]
876 #[corresponds(SSL_CTX_enable_ntls)]
877 pub fn enable_ntls(&mut self) {
878 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
879 }
880
881 #[cfg(tongsuo)]
882 #[corresponds(SSL_CTX_disable_ntls)]
883 pub fn disable_ntls(&mut self) {
884 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
885 }
886
887 #[cfg(all(tongsuo, ossl300))]
888 #[corresponds(SSL_CTX_enable_force_ntls)]
889 pub fn enable_force_ntls(&mut self) {
890 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
891 }
892
893 #[cfg(all(tongsuo, ossl300))]
894 #[corresponds(SSL_CTX_disable_force_ntls)]
895 pub fn disable_force_ntls(&mut self) {
896 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
897 }
898
899 #[cfg(tongsuo)]
900 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
901 pub fn enable_sm_tls13_strict(&mut self) {
902 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
903 }
904
905 #[cfg(tongsuo)]
906 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
907 pub fn disable_sm_tls13_strict(&mut self) {
908 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
909 }
910
911 #[corresponds(SSL_CTX_set_verify)]
913 pub fn set_verify(&mut self, mode: SslVerifyMode) {
914 unsafe {
915 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
916 }
917 }
918
919 #[corresponds(SSL_CTX_set_verify)]
926 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
927 where
928 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
929 {
930 unsafe {
931 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
932 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
933 }
934 }
935
936 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
944 pub fn set_servername_callback<F>(&mut self, callback: F)
946 where
947 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
948 {
949 unsafe {
950 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
956 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
957 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
958 }
959 }
960
961 #[corresponds(SSL_CTX_set_verify_depth)]
965 pub fn set_verify_depth(&mut self, depth: u32) {
966 unsafe {
967 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
968 }
969 }
970
971 #[corresponds(SSL_CTX_set0_verify_cert_store)]
975 #[cfg(any(ossl102, boringssl, awslc))]
976 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
977 unsafe {
978 let ptr = cert_store.as_ptr();
979 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
980 mem::forget(cert_store);
981
982 Ok(())
983 }
984 }
985
986 #[corresponds(SSL_CTX_set_cert_store)]
988 pub fn set_cert_store(&mut self, cert_store: X509Store) {
989 unsafe {
990 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
991 mem::forget(cert_store);
992 }
993 }
994
995 #[corresponds(SSL_CTX_set_read_ahead)]
1002 pub fn set_read_ahead(&mut self, read_ahead: bool) {
1003 unsafe {
1004 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
1005 }
1006 }
1007
1008 #[corresponds(SSL_CTX_set_mode)]
1012 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1013 unsafe {
1014 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1015 SslMode::from_bits_retain(bits)
1016 }
1017 }
1018
1019 #[corresponds(SSL_CTX_clear_mode)]
1021 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1022 unsafe {
1023 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1024 SslMode::from_bits_retain(bits)
1025 }
1026 }
1027
1028 #[corresponds(SSL_CTX_get_mode)]
1030 pub fn mode(&self) -> SslMode {
1031 unsafe {
1032 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1033 SslMode::from_bits_retain(bits)
1034 }
1035 }
1036
1037 #[corresponds(SSL_CTX_set_dh_auto)]
1046 #[cfg(ossl300)]
1047 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1048 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1049 }
1050
1051 #[corresponds(SSL_CTX_set_tmp_dh)]
1053 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1054 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1055 }
1056
1057 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1064 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1065 where
1066 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1067 {
1068 unsafe {
1069 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1070
1071 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1077 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1078 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1079 }
1080
1081 #[corresponds(SSL_CTX_set_default_verify_paths)]
1086 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1087 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1088 }
1089
1090 #[corresponds(SSL_CTX_load_verify_locations)]
1094 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1095 self.load_verify_locations(Some(file.as_ref()), None)
1096 }
1097
1098 #[corresponds(SSL_CTX_load_verify_locations)]
1100 pub fn load_verify_locations(
1101 &mut self,
1102 ca_file: Option<&Path>,
1103 ca_path: Option<&Path>,
1104 ) -> Result<(), ErrorStack> {
1105 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1106 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1107 unsafe {
1108 cvt(ffi::SSL_CTX_load_verify_locations(
1109 self.as_ptr(),
1110 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1111 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1112 ))
1113 .map(|_| ())
1114 }
1115 }
1116
1117 #[corresponds(SSL_CTX_set_client_CA_list)]
1122 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1123 unsafe {
1124 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1125 mem::forget(list);
1126 }
1127 }
1128
1129 #[corresponds(SSL_CTX_add_client_CA)]
1132 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1133 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1134 }
1135
1136 #[corresponds(SSL_CTX_set_session_id_context)]
1145 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1146 unsafe {
1147 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1148 cvt(ffi::SSL_CTX_set_session_id_context(
1149 self.as_ptr(),
1150 sid_ctx.as_ptr(),
1151 sid_ctx.len() as SizeTy,
1152 ))
1153 .map(|_| ())
1154 }
1155 }
1156
1157 #[corresponds(SSL_CTX_use_certificate_file)]
1163 pub fn set_certificate_file<P: AsRef<Path>>(
1164 &mut self,
1165 file: P,
1166 file_type: SslFiletype,
1167 ) -> Result<(), ErrorStack> {
1168 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1169 unsafe {
1170 cvt(ffi::SSL_CTX_use_certificate_file(
1171 self.as_ptr(),
1172 file.as_ptr() as *const _,
1173 file_type.as_raw(),
1174 ))
1175 .map(|_| ())
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1185 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1186 &mut self,
1187 file: P,
1188 ) -> Result<(), ErrorStack> {
1189 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1190 unsafe {
1191 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1192 self.as_ptr(),
1193 file.as_ptr() as *const _,
1194 ))
1195 .map(|_| ())
1196 }
1197 }
1198
1199 #[corresponds(SSL_CTX_use_certificate)]
1203 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1204 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1205 }
1206
1207 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1212 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1213 unsafe {
1214 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1215 mem::forget(cert);
1216 Ok(())
1217 }
1218 }
1219
1220 #[cfg(tongsuo)]
1221 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1222 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1223 &mut self,
1224 file: P,
1225 file_type: SslFiletype,
1226 ) -> Result<(), ErrorStack> {
1227 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1228 unsafe {
1229 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1230 self.as_ptr(),
1231 file.as_ptr() as *const _,
1232 file_type.as_raw(),
1233 ))
1234 .map(|_| ())
1235 }
1236 }
1237
1238 #[cfg(tongsuo)]
1239 #[corresponds(SSL_CTX_use_enc_certificate)]
1240 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1241 unsafe {
1242 cvt(ffi::SSL_CTX_use_enc_certificate(
1243 self.as_ptr(),
1244 cert.as_ptr(),
1245 ))
1246 .map(|_| ())
1247 }
1248 }
1249
1250 #[cfg(tongsuo)]
1251 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1252 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1253 &mut self,
1254 file: P,
1255 file_type: SslFiletype,
1256 ) -> Result<(), ErrorStack> {
1257 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1258 unsafe {
1259 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1260 self.as_ptr(),
1261 file.as_ptr() as *const _,
1262 file_type.as_raw(),
1263 ))
1264 .map(|_| ())
1265 }
1266 }
1267
1268 #[cfg(tongsuo)]
1269 #[corresponds(SSL_CTX_use_sign_certificate)]
1270 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1271 unsafe {
1272 cvt(ffi::SSL_CTX_use_sign_certificate(
1273 self.as_ptr(),
1274 cert.as_ptr(),
1275 ))
1276 .map(|_| ())
1277 }
1278 }
1279
1280 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1282 pub fn set_private_key_file<P: AsRef<Path>>(
1283 &mut self,
1284 file: P,
1285 file_type: SslFiletype,
1286 ) -> Result<(), ErrorStack> {
1287 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1288 unsafe {
1289 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1290 self.as_ptr(),
1291 file.as_ptr() as *const _,
1292 file_type.as_raw(),
1293 ))
1294 .map(|_| ())
1295 }
1296 }
1297
1298 #[corresponds(SSL_CTX_use_PrivateKey)]
1300 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1301 where
1302 T: HasPrivate,
1303 {
1304 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1305 }
1306
1307 #[cfg(tongsuo)]
1308 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1309 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1310 &mut self,
1311 file: P,
1312 file_type: SslFiletype,
1313 ) -> Result<(), ErrorStack> {
1314 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1315 unsafe {
1316 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1317 self.as_ptr(),
1318 file.as_ptr() as *const _,
1319 file_type.as_raw(),
1320 ))
1321 .map(|_| ())
1322 }
1323 }
1324
1325 #[cfg(tongsuo)]
1326 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1327 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1328 where
1329 T: HasPrivate,
1330 {
1331 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1332 }
1333
1334 #[cfg(tongsuo)]
1335 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1336 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1337 &mut self,
1338 file: P,
1339 file_type: SslFiletype,
1340 ) -> Result<(), ErrorStack> {
1341 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1342 unsafe {
1343 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1344 self.as_ptr(),
1345 file.as_ptr() as *const _,
1346 file_type.as_raw(),
1347 ))
1348 .map(|_| ())
1349 }
1350 }
1351
1352 #[cfg(tongsuo)]
1353 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1354 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1355 where
1356 T: HasPrivate,
1357 {
1358 unsafe {
1359 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1360 self.as_ptr(),
1361 key.as_ptr(),
1362 ))
1363 .map(|_| ())
1364 }
1365 }
1366
1367 #[corresponds(SSL_CTX_set_cipher_list)]
1375 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1376 let cipher_list = CString::new(cipher_list).unwrap();
1377 unsafe {
1378 cvt(ffi::SSL_CTX_set_cipher_list(
1379 self.as_ptr(),
1380 cipher_list.as_ptr() as *const _,
1381 ))
1382 .map(|_| ())
1383 }
1384 }
1385
1386 #[corresponds(SSL_CTX_set_ciphersuites)]
1395 #[cfg(any(ossl111, libressl340, awslc))]
1396 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1397 let cipher_list = CString::new(cipher_list).unwrap();
1398 unsafe {
1399 cvt(ffi::SSL_CTX_set_ciphersuites(
1400 self.as_ptr(),
1401 cipher_list.as_ptr() as *const _,
1402 ))
1403 .map(|_| ())
1404 }
1405 }
1406
1407 #[corresponds(SSL_CTX_set_ecdh_auto)]
1411 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1412 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1413 unsafe {
1414 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1415 }
1416 }
1417
1418 #[corresponds(SSL_CTX_set_options)]
1425 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1426 let bits =
1427 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1428 SslOptions::from_bits_retain(bits)
1429 }
1430
1431 #[corresponds(SSL_CTX_get_options)]
1433 pub fn options(&self) -> SslOptions {
1434 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1435 SslOptions::from_bits_retain(bits)
1436 }
1437
1438 #[corresponds(SSL_CTX_clear_options)]
1440 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1441 let bits =
1442 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1443 SslOptions::from_bits_retain(bits)
1444 }
1445
1446 #[corresponds(SSL_CTX_set_min_proto_version)]
1453 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1454 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1455 unsafe {
1456 cvt(ffi::SSL_CTX_set_min_proto_version(
1457 self.as_ptr(),
1458 version.map_or(0, |v| v.0 as _),
1459 ))
1460 .map(|_| ())
1461 }
1462 }
1463
1464 #[corresponds(SSL_CTX_set_max_proto_version)]
1471 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1472 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1473 unsafe {
1474 cvt(ffi::SSL_CTX_set_max_proto_version(
1475 self.as_ptr(),
1476 version.map_or(0, |v| v.0 as _),
1477 ))
1478 .map(|_| ())
1479 }
1480 }
1481
1482 #[corresponds(SSL_CTX_get_min_proto_version)]
1489 #[cfg(any(ossl110g, libressl270))]
1490 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1491 unsafe {
1492 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1493 if r == 0 {
1494 None
1495 } else {
1496 Some(SslVersion(r))
1497 }
1498 }
1499 }
1500
1501 #[corresponds(SSL_CTX_get_max_proto_version)]
1508 #[cfg(any(ossl110g, libressl270))]
1509 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1510 unsafe {
1511 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1512 if r == 0 {
1513 None
1514 } else {
1515 Some(SslVersion(r))
1516 }
1517 }
1518 }
1519
1520 #[corresponds(SSL_CTX_set_alpn_protos)]
1529 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1530 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1531 unsafe {
1532 assert!(protocols.len() <= c_uint::MAX as usize);
1533 let r = ffi::SSL_CTX_set_alpn_protos(
1534 self.as_ptr(),
1535 protocols.as_ptr(),
1536 protocols.len() as _,
1537 );
1538 if r == 0 {
1540 Ok(())
1541 } else {
1542 Err(ErrorStack::get())
1543 }
1544 }
1545 }
1546
1547 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1549 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1550 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1551 unsafe {
1552 let cstr = CString::new(protocols).unwrap();
1553
1554 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1555 if r == 0 {
1557 Ok(())
1558 } else {
1559 Err(ErrorStack::get())
1560 }
1561 }
1562 }
1563
1564 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1575 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1576 where
1577 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1578 {
1579 unsafe {
1580 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1581 ffi::SSL_CTX_set_alpn_select_cb(
1582 self.as_ptr(),
1583 Some(callbacks::raw_alpn_select::<F>),
1584 ptr::null_mut(),
1585 );
1586 }
1587 }
1588
1589 #[corresponds(SSL_CTX_check_private_key)]
1591 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1592 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1593 }
1594
1595 #[corresponds(SSL_CTX_get_cert_store)]
1597 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1598 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1599 }
1600
1601 #[corresponds(SSL_CTX_get_cert_store)]
1603 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1604 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1605 }
1606
1607 #[corresponds(SSL_CTX_get0_param)]
1611 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1612 pub fn verify_param(&self) -> &X509VerifyParamRef {
1613 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1614 }
1615
1616 #[corresponds(SSL_CTX_get0_param)]
1620 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1621 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1622 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1623 }
1624
1625 #[cfg(any(boringssl, tongsuo, awslc))]
1633 pub fn add_cert_decompression_alg<F>(
1634 &mut self,
1635 alg_id: CertCompressionAlgorithm,
1636 decompress: F,
1637 ) -> Result<(), ErrorStack>
1638 where
1639 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1640 {
1641 unsafe {
1642 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1643 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1644 self.as_ptr(),
1645 alg_id.0 as _,
1646 None,
1647 Some(raw_cert_decompression::<F>),
1648 ))
1649 .map(|_| ())
1650 }
1651 }
1652
1653 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1655 #[cfg(ossl320)]
1656 pub fn set_cert_comp_preference(
1657 &mut self,
1658 algs: &[CertCompressionAlgorithm],
1659 ) -> Result<(), ErrorStack> {
1660 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1661 unsafe {
1662 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1663 self.as_ptr(),
1664 algs.as_mut_ptr(),
1665 algs.len(),
1666 ))
1667 .map(|_| ())
1668 }
1669 }
1670
1671 #[cfg(any(boringssl, awslc))]
1679 pub fn enable_ocsp_stapling(&mut self) {
1680 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1681 }
1682
1683 #[cfg(any(boringssl, awslc))]
1691 pub fn enable_signed_cert_timestamps(&mut self) {
1692 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1693 }
1694
1695 #[cfg(any(boringssl, awslc))]
1703 pub fn set_grease_enabled(&mut self, enabled: bool) {
1704 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1705 }
1706
1707 #[cfg(any(boringssl, awslc))]
1715 pub fn set_permute_extensions(&mut self, enabled: bool) {
1716 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1717 }
1718
1719 #[corresponds(SSL_CTX_enable_ct)]
1721 #[cfg(ossl111)]
1722 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1723 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1724 }
1725
1726 #[corresponds(SSL_CTX_ct_is_enabled)]
1728 #[cfg(ossl111)]
1729 pub fn ct_is_enabled(&self) -> bool {
1730 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1731 }
1732
1733 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1735 #[cfg(not(any(boringssl, awslc)))]
1736 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1737 unsafe {
1738 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1739 .map(|_| ())
1740 }
1741 }
1742
1743 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1756 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1757 where
1758 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1759 {
1760 unsafe {
1761 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1762 cvt(
1763 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1764 as c_int,
1765 )
1766 .map(|_| ())
1767 }
1768 }
1769
1770 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1771 #[cfg(ossl300)]
1772 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1773 where
1774 F: Fn(
1775 &mut SslRef,
1776 &mut [u8],
1777 &mut [u8],
1778 &mut CipherCtxRef,
1779 &mut MacCtxRef,
1780 bool,
1781 ) -> Result<TicketKeyStatus, ErrorStack>
1782 + 'static
1783 + Sync
1784 + Send,
1785 {
1786 unsafe {
1787 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1788 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1789 self.as_ptr(),
1790 Some(raw_tlsext_ticket_key_evp::<F>),
1791 ) as c_int)
1792 .map(|_| ())
1793 }
1794 }
1795
1796 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1797 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1798 where
1799 F: Fn(
1800 &mut SslRef,
1801 &mut [u8],
1802 &mut [u8],
1803 &mut CipherCtxRef,
1804 &mut HMacCtxRef,
1805 bool,
1806 ) -> Result<TicketKeyStatus, ErrorStack>
1807 + 'static
1808 + Sync
1809 + Send,
1810 {
1811 unsafe {
1812 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1813 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1814 self.as_ptr(),
1815 Some(raw_tlsext_ticket_key::<F>),
1816 ) as c_int)
1817 .map(|_| ())
1818 }
1819 }
1820
1821 #[corresponds(SSL_CTX_set_psk_client_callback)]
1827 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1828 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1829 where
1830 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1831 + 'static
1832 + Sync
1833 + Send,
1834 {
1835 unsafe {
1836 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1837 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1838 }
1839 }
1840
1841 #[corresponds(SSL_CTX_set_psk_server_callback)]
1847 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1848 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1849 where
1850 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1851 + 'static
1852 + Sync
1853 + Send,
1854 {
1855 unsafe {
1856 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1857 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1858 }
1859 }
1860
1861 #[corresponds(SSL_CTX_sess_set_new_cb)]
1875 pub fn set_new_session_callback<F>(&mut self, callback: F)
1876 where
1877 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1878 {
1879 unsafe {
1880 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1881 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1882 }
1883 }
1884
1885 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1889 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1890 where
1891 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1892 {
1893 unsafe {
1894 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1895 ffi::SSL_CTX_sess_set_remove_cb(
1896 self.as_ptr(),
1897 Some(callbacks::raw_remove_session::<F>),
1898 );
1899 }
1900 }
1901
1902 #[corresponds(SSL_CTX_sess_set_get_cb)]
1913 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1914 where
1915 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1916 {
1917 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1918 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1919 }
1920
1921 #[corresponds(SSL_CTX_set_keylog_callback)]
1929 #[cfg(any(ossl111, boringssl, awslc))]
1930 pub fn set_keylog_callback<F>(&mut self, callback: F)
1931 where
1932 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1933 {
1934 unsafe {
1935 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1936 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1937 }
1938 }
1939
1940 #[corresponds(SSL_CTX_set_session_cache_mode)]
1944 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1945 unsafe {
1946 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1947 SslSessionCacheMode::from_bits_retain(bits)
1948 }
1949 }
1950
1951 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1957 #[cfg(ossl111)]
1958 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1959 where
1960 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1961 {
1962 unsafe {
1963 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1964 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1965 self.as_ptr(),
1966 Some(raw_stateless_cookie_generate::<F>),
1967 );
1968 }
1969 }
1970
1971 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1980 #[cfg(ossl111)]
1981 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1982 where
1983 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1984 {
1985 unsafe {
1986 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1987 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1988 self.as_ptr(),
1989 Some(raw_stateless_cookie_verify::<F>),
1990 )
1991 }
1992 }
1993
1994 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1999 #[cfg(not(any(boringssl, awslc)))]
2000 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
2001 where
2002 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
2003 {
2004 unsafe {
2005 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2006 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
2007 }
2008 }
2009
2010 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
2015 #[cfg(not(any(boringssl, awslc)))]
2016 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2017 where
2018 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2019 {
2020 unsafe {
2021 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2022 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2023 }
2024 }
2025
2026 #[corresponds(SSL_CTX_set_ex_data)]
2032 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2033 self.set_ex_data_inner(index, data);
2034 }
2035
2036 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2037 match self.ex_data_mut(index) {
2038 Some(v) => {
2039 *v = data;
2040 (v as *mut T).cast()
2041 }
2042 _ => unsafe {
2043 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2044 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2045 data
2046 },
2047 }
2048 }
2049
2050 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2051 unsafe {
2052 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2053 if data.is_null() {
2054 None
2055 } else {
2056 Some(&mut *data.cast())
2057 }
2058 }
2059 }
2060
2061 #[corresponds(SSL_CTX_add_custom_ext)]
2065 #[cfg(ossl111)]
2066 pub fn add_custom_ext<AddFn, ParseFn, T>(
2067 &mut self,
2068 ext_type: u16,
2069 context: ExtensionContext,
2070 add_cb: AddFn,
2071 parse_cb: ParseFn,
2072 ) -> Result<(), ErrorStack>
2073 where
2074 AddFn: Fn(
2075 &mut SslRef,
2076 ExtensionContext,
2077 Option<(usize, &X509Ref)>,
2078 ) -> Result<Option<T>, SslAlert>
2079 + 'static
2080 + Sync
2081 + Send,
2082 T: AsRef<[u8]> + 'static + Sync + Send,
2083 ParseFn: Fn(
2084 &mut SslRef,
2085 ExtensionContext,
2086 &[u8],
2087 Option<(usize, &X509Ref)>,
2088 ) -> Result<(), SslAlert>
2089 + 'static
2090 + Sync
2091 + Send,
2092 {
2093 let ret = unsafe {
2094 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2095 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2096
2097 ffi::SSL_CTX_add_custom_ext(
2098 self.as_ptr(),
2099 ext_type as c_uint,
2100 context.bits(),
2101 Some(raw_custom_ext_add::<AddFn, T>),
2102 Some(raw_custom_ext_free::<T>),
2103 ptr::null_mut(),
2104 Some(raw_custom_ext_parse::<ParseFn>),
2105 ptr::null_mut(),
2106 )
2107 };
2108 if ret == 1 {
2109 Ok(())
2110 } else {
2111 Err(ErrorStack::get())
2112 }
2113 }
2114
2115 #[corresponds(SSL_CTX_set_max_early_data)]
2121 #[cfg(any(ossl111, libressl340))]
2122 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2123 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2124 Ok(())
2125 } else {
2126 Err(ErrorStack::get())
2127 }
2128 }
2129
2130 #[cfg(any(boringssl, awslc))]
2140 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2141 where
2142 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2143 {
2144 unsafe {
2145 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2146 ffi::SSL_CTX_set_select_certificate_cb(
2147 self.as_ptr(),
2148 Some(callbacks::raw_select_cert::<F>),
2149 );
2150 }
2151 }
2152
2153 #[corresponds(SSL_CTX_set_client_hello_cb)]
2157 #[cfg(ossl111)]
2158 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2159 where
2160 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2161 {
2162 unsafe {
2163 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2164 ffi::SSL_CTX_set_client_hello_cb(
2165 self.as_ptr(),
2166 Some(callbacks::raw_client_hello::<F>),
2167 ptr,
2168 );
2169 }
2170 }
2171
2172 #[corresponds(SSL_CTX_set_info_callback)]
2175 pub fn set_info_callback<F>(&mut self, callback: F)
2176 where
2177 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2178 {
2179 unsafe {
2180 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2181 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2182 }
2183 }
2184
2185 #[corresponds(SSL_CTX_sess_set_cache_size)]
2189 #[allow(clippy::useless_conversion)]
2190 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2191 unsafe {
2192 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2193 }
2194 }
2195
2196 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2200 #[cfg(ossl102)]
2201 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2202 let sigalgs = CString::new(sigalgs).unwrap();
2203 unsafe {
2204 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2205 .map(|_| ())
2206 }
2207 }
2208
2209 #[corresponds(SSL_CTX_set1_groups_list)]
2213 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
2214 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2215 let groups = CString::new(groups).unwrap();
2216 unsafe {
2217 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2218 }
2219 }
2220
2221 #[corresponds(SSL_CTX_set_num_tickets)]
2226 #[cfg(any(ossl111, boringssl, awslc))]
2227 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2228 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2229 }
2230
2231 #[corresponds(SSL_CTX_set_security_level)]
2236 #[cfg(any(ossl110, libressl360))]
2237 pub fn set_security_level(&mut self, level: u32) {
2238 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2239 }
2240
2241 pub fn build(self) -> SslContext {
2243 self.0
2244 }
2245}
2246
2247foreign_type_and_impl_send_sync! {
2248 type CType = ffi::SSL_CTX;
2249 fn drop = ffi::SSL_CTX_free;
2250
2251 pub struct SslContext;
2256
2257 pub struct SslContextRef;
2261}
2262
2263impl Clone for SslContext {
2264 fn clone(&self) -> Self {
2265 (**self).to_owned()
2266 }
2267}
2268
2269impl ToOwned for SslContextRef {
2270 type Owned = SslContext;
2271
2272 fn to_owned(&self) -> Self::Owned {
2273 unsafe {
2274 SSL_CTX_up_ref(self.as_ptr());
2275 SslContext::from_ptr(self.as_ptr())
2276 }
2277 }
2278}
2279
2280impl fmt::Debug for SslContext {
2282 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2283 write!(fmt, "SslContext")
2284 }
2285}
2286
2287impl SslContext {
2288 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2290 SslContextBuilder::new(method)
2291 }
2292
2293 #[corresponds(SSL_CTX_get_ex_new_index)]
2298 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2299 where
2300 T: 'static + Sync + Send,
2301 {
2302 unsafe {
2303 ffi::init();
2304 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2305 Ok(Index::from_raw(idx))
2306 }
2307 }
2308
2309 fn cached_ex_index<T>() -> Index<SslContext, T>
2311 where
2312 T: 'static + Sync + Send,
2313 {
2314 unsafe {
2315 let idx = *INDEXES
2316 .lock()
2317 .unwrap_or_else(|e| e.into_inner())
2318 .entry(TypeId::of::<T>())
2319 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2320 Index::from_raw(idx)
2321 }
2322 }
2323}
2324
2325impl SslContextRef {
2326 #[corresponds(SSL_CTX_get0_certificate)]
2330 #[cfg(any(ossl102, libressl270))]
2331 pub fn certificate(&self) -> Option<&X509Ref> {
2332 unsafe {
2333 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2334 X509Ref::from_const_ptr_opt(ptr)
2335 }
2336 }
2337
2338 #[corresponds(SSL_CTX_get0_privatekey)]
2342 #[cfg(any(ossl102, libressl340))]
2343 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2344 unsafe {
2345 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2346 PKeyRef::from_const_ptr_opt(ptr)
2347 }
2348 }
2349
2350 #[corresponds(SSL_CTX_get_cert_store)]
2352 pub fn cert_store(&self) -> &X509StoreRef {
2353 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2354 }
2355
2356 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2358 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2359 unsafe {
2360 let mut chain = ptr::null_mut();
2361 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2362 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2363 }
2364 }
2365
2366 #[corresponds(SSL_CTX_get_ex_data)]
2368 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2369 unsafe {
2370 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2371 if data.is_null() {
2372 None
2373 } else {
2374 Some(&*(data as *const T))
2375 }
2376 }
2377 }
2378
2379 #[corresponds(SSL_CTX_get_max_early_data)]
2383 #[cfg(any(ossl111, libressl340))]
2384 pub fn max_early_data(&self) -> u32 {
2385 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2386 }
2387
2388 #[corresponds(SSL_CTX_add_session)]
2397 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2398 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2399 }
2400
2401 #[corresponds(SSL_CTX_remove_session)]
2410 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2411 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2412 }
2413
2414 #[corresponds(SSL_CTX_sess_get_cache_size)]
2418 #[allow(clippy::unnecessary_cast)]
2419 pub fn session_cache_size(&self) -> i64 {
2420 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2421 }
2422
2423 #[corresponds(SSL_CTX_get_verify_mode)]
2427 pub fn verify_mode(&self) -> SslVerifyMode {
2428 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2429 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2430 }
2431
2432 #[corresponds(SSL_CTX_get_num_tickets)]
2437 #[cfg(ossl111)]
2438 pub fn num_tickets(&self) -> usize {
2439 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2440 }
2441
2442 #[corresponds(SSL_CTX_get_security_level)]
2447 #[cfg(any(ossl110, libressl360))]
2448 pub fn security_level(&self) -> u32 {
2449 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2450 }
2451}
2452
2453pub struct CipherBits {
2455 pub secret: i32,
2457
2458 pub algorithm: i32,
2460}
2461
2462pub struct SslCipher(*mut ffi::SSL_CIPHER);
2464
2465impl ForeignType for SslCipher {
2466 type CType = ffi::SSL_CIPHER;
2467 type Ref = SslCipherRef;
2468
2469 #[inline]
2470 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2471 SslCipher(ptr)
2472 }
2473
2474 #[inline]
2475 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2476 self.0
2477 }
2478}
2479
2480impl Stackable for SslCipher {
2481 type StackType = ffi::stack_st_SSL_CIPHER;
2482}
2483
2484impl Deref for SslCipher {
2485 type Target = SslCipherRef;
2486
2487 fn deref(&self) -> &SslCipherRef {
2488 unsafe { SslCipherRef::from_ptr(self.0) }
2489 }
2490}
2491
2492impl DerefMut for SslCipher {
2493 fn deref_mut(&mut self) -> &mut SslCipherRef {
2494 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2495 }
2496}
2497
2498pub struct SslCipherRef(Opaque);
2502
2503impl ForeignTypeRef for SslCipherRef {
2504 type CType = ffi::SSL_CIPHER;
2505}
2506
2507impl SslCipherRef {
2508 #[corresponds(SSL_CIPHER_get_name)]
2510 pub fn name(&self) -> &'static str {
2511 unsafe {
2512 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2513 CStr::from_ptr(ptr).to_str().unwrap()
2514 }
2515 }
2516
2517 #[corresponds(SSL_CIPHER_standard_name)]
2521 #[cfg(ossl111)]
2522 pub fn standard_name(&self) -> Option<&'static str> {
2523 unsafe {
2524 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2525 if ptr.is_null() {
2526 None
2527 } else {
2528 Some(CStr::from_ptr(ptr).to_str().unwrap())
2529 }
2530 }
2531 }
2532
2533 #[corresponds(SSL_CIPHER_get_version)]
2535 pub fn version(&self) -> &'static str {
2536 let version = unsafe {
2537 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2538 CStr::from_ptr(ptr as *const _)
2539 };
2540
2541 str::from_utf8(version.to_bytes()).unwrap()
2542 }
2543
2544 #[corresponds(SSL_CIPHER_get_bits)]
2546 #[allow(clippy::useless_conversion)]
2547 pub fn bits(&self) -> CipherBits {
2548 unsafe {
2549 let mut algo_bits = 0;
2550 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2551 CipherBits {
2552 secret: secret_bits.into(),
2553 algorithm: algo_bits.into(),
2554 }
2555 }
2556 }
2557
2558 #[corresponds(SSL_CIPHER_description)]
2560 pub fn description(&self) -> String {
2561 unsafe {
2562 let mut buf = [0; 128];
2564 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2565 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2566 }
2567 }
2568
2569 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2573 #[cfg(ossl111)]
2574 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2575 unsafe {
2576 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2577 if ptr.is_null() {
2578 None
2579 } else {
2580 Some(MessageDigest::from_ptr(ptr))
2581 }
2582 }
2583 }
2584
2585 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2589 #[cfg(any(ossl110, libressl270))]
2590 pub fn cipher_nid(&self) -> Option<Nid> {
2591 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2592 if n == 0 {
2593 None
2594 } else {
2595 Some(Nid::from_raw(n))
2596 }
2597 }
2598}
2599
2600impl fmt::Debug for SslCipherRef {
2601 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2602 write!(fmt, "{}", self.name())
2603 }
2604}
2605
2606#[derive(Debug)]
2608pub struct CipherLists {
2609 pub suites: Stack<SslCipher>,
2610 pub signalling_suites: Stack<SslCipher>,
2611}
2612
2613foreign_type_and_impl_send_sync! {
2614 type CType = ffi::SSL_SESSION;
2615 fn drop = ffi::SSL_SESSION_free;
2616
2617 pub struct SslSession;
2621
2622 pub struct SslSessionRef;
2626}
2627
2628impl Clone for SslSession {
2629 fn clone(&self) -> SslSession {
2630 SslSessionRef::to_owned(self)
2631 }
2632}
2633
2634impl SslSession {
2635 from_der! {
2636 #[corresponds(d2i_SSL_SESSION)]
2638 from_der,
2639 SslSession,
2640 ffi::d2i_SSL_SESSION
2641 }
2642}
2643
2644impl ToOwned for SslSessionRef {
2645 type Owned = SslSession;
2646
2647 fn to_owned(&self) -> SslSession {
2648 unsafe {
2649 SSL_SESSION_up_ref(self.as_ptr());
2650 SslSession(self.as_ptr())
2651 }
2652 }
2653}
2654
2655impl SslSessionRef {
2656 #[corresponds(SSL_SESSION_get_id)]
2658 pub fn id(&self) -> &[u8] {
2659 unsafe {
2660 let mut len = 0;
2661 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2662 #[allow(clippy::unnecessary_cast)]
2663 util::from_raw_parts(p as *const u8, len as usize)
2664 }
2665 }
2666
2667 #[corresponds(SSL_SESSION_get_master_key)]
2669 pub fn master_key_len(&self) -> usize {
2670 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2671 }
2672
2673 #[corresponds(SSL_SESSION_get_master_key)]
2677 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2678 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2679 }
2680
2681 #[corresponds(SSL_SESSION_get_max_early_data)]
2685 #[cfg(any(ossl111, libressl340))]
2686 pub fn max_early_data(&self) -> u32 {
2687 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2688 }
2689
2690 #[corresponds(SSL_SESSION_get_time)]
2692 #[allow(clippy::useless_conversion)]
2693 pub fn time(&self) -> SslTimeTy {
2694 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2695 }
2696
2697 #[corresponds(SSL_SESSION_get_timeout)]
2701 #[allow(clippy::useless_conversion)]
2702 pub fn timeout(&self) -> i64 {
2703 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2704 }
2705
2706 #[corresponds(SSL_SESSION_get_protocol_version)]
2710 #[cfg(any(ossl110, libressl270))]
2711 pub fn protocol_version(&self) -> SslVersion {
2712 unsafe {
2713 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2714 SslVersion(version)
2715 }
2716 }
2717
2718 #[corresponds(SSL_SESSION_get_protocol_version)]
2720 #[cfg(any(boringssl, awslc))]
2721 pub fn protocol_version(&self) -> SslVersion {
2722 unsafe {
2723 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2724 SslVersion(version as _)
2725 }
2726 }
2727
2728 to_der! {
2729 #[corresponds(i2d_SSL_SESSION)]
2731 to_der,
2732 ffi::i2d_SSL_SESSION
2733 }
2734}
2735
2736foreign_type_and_impl_send_sync! {
2737 type CType = ffi::SSL;
2738 fn drop = ffi::SSL_free;
2739
2740 pub struct Ssl;
2747
2748 pub struct SslRef;
2752}
2753
2754impl fmt::Debug for Ssl {
2755 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2756 fmt::Debug::fmt(&**self, fmt)
2757 }
2758}
2759
2760impl Ssl {
2761 #[corresponds(SSL_get_ex_new_index)]
2766 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2767 where
2768 T: 'static + Sync + Send,
2769 {
2770 unsafe {
2771 ffi::init();
2772 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2773 Ok(Index::from_raw(idx))
2774 }
2775 }
2776
2777 fn cached_ex_index<T>() -> Index<Ssl, T>
2779 where
2780 T: 'static + Sync + Send,
2781 {
2782 unsafe {
2783 let idx = *SSL_INDEXES
2784 .lock()
2785 .unwrap_or_else(|e| e.into_inner())
2786 .entry(TypeId::of::<T>())
2787 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2788 Index::from_raw(idx)
2789 }
2790 }
2791
2792 #[corresponds(SSL_new)]
2794 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2795 let session_ctx_index = try_get_session_ctx_index()?;
2796 unsafe {
2797 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2798 let mut ssl = Ssl::from_ptr(ptr);
2799 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2800
2801 Ok(ssl)
2802 }
2803 }
2804
2805 #[corresponds(SSL_connect)]
2811 #[allow(deprecated)]
2812 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2813 where
2814 S: Read + Write,
2815 {
2816 SslStreamBuilder::new(self, stream).connect()
2817 }
2818
2819 #[corresponds(SSL_accept)]
2826 #[allow(deprecated)]
2827 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2828 where
2829 S: Read + Write,
2830 {
2831 SslStreamBuilder::new(self, stream).accept()
2832 }
2833}
2834
2835impl fmt::Debug for SslRef {
2836 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2837 fmt.debug_struct("Ssl")
2838 .field("state", &self.state_string_long())
2839 .field("verify_result", &self.verify_result())
2840 .finish()
2841 }
2842}
2843
2844impl SslRef {
2845 #[cfg(not(feature = "tongsuo"))]
2846 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2847 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2848 }
2849
2850 #[cfg(feature = "tongsuo")]
2851 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2852 unsafe {
2853 let bio = ffi::SSL_get_rbio(self.as_ptr());
2854 bio::find_correct_bio(bio)
2855 }
2856 }
2857
2858 fn get_error(&self, ret: c_int) -> ErrorCode {
2859 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2860 }
2861
2862 #[corresponds(SSL_set_mode)]
2866 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2867 unsafe {
2868 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2869 SslMode::from_bits_retain(bits)
2870 }
2871 }
2872
2873 #[corresponds(SSL_clear_mode)]
2875 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2876 unsafe {
2877 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2878 SslMode::from_bits_retain(bits)
2879 }
2880 }
2881
2882 #[corresponds(SSL_get_mode)]
2884 pub fn mode(&self) -> SslMode {
2885 unsafe {
2886 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2887 SslMode::from_bits_retain(bits)
2888 }
2889 }
2890
2891 #[corresponds(SSL_set_connect_state)]
2893 pub fn set_connect_state(&mut self) {
2894 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2895 }
2896
2897 #[corresponds(SSL_set_accept_state)]
2899 pub fn set_accept_state(&mut self) {
2900 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2901 }
2902
2903 #[cfg(any(boringssl, awslc))]
2904 #[corresponds(SSL_ech_accepted)]
2905 pub fn ech_accepted(&self) -> bool {
2906 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2907 }
2908
2909 #[cfg(tongsuo)]
2910 #[corresponds(SSL_is_ntls)]
2911 pub fn is_ntls(&mut self) -> bool {
2912 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2913 }
2914
2915 #[cfg(tongsuo)]
2916 #[corresponds(SSL_enable_ntls)]
2917 pub fn enable_ntls(&mut self) {
2918 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2919 }
2920
2921 #[cfg(tongsuo)]
2922 #[corresponds(SSL_disable_ntls)]
2923 pub fn disable_ntls(&mut self) {
2924 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2925 }
2926
2927 #[cfg(all(tongsuo, ossl300))]
2928 #[corresponds(SSL_enable_force_ntls)]
2929 pub fn enable_force_ntls(&mut self) {
2930 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2931 }
2932
2933 #[cfg(all(tongsuo, ossl300))]
2934 #[corresponds(SSL_disable_force_ntls)]
2935 pub fn disable_force_ntls(&mut self) {
2936 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2937 }
2938
2939 #[cfg(tongsuo)]
2940 #[corresponds(SSL_enable_sm_tls13_strict)]
2941 pub fn enable_sm_tls13_strict(&mut self) {
2942 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2943 }
2944
2945 #[cfg(tongsuo)]
2946 #[corresponds(SSL_disable_sm_tls13_strict)]
2947 pub fn disable_sm_tls13_strict(&mut self) {
2948 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2949 }
2950
2951 #[corresponds(SSL_set_verify)]
2955 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2956 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2957 }
2958
2959 #[corresponds(SSL_set_verify_mode)]
2961 pub fn verify_mode(&self) -> SslVerifyMode {
2962 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2963 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2964 }
2965
2966 #[corresponds(SSL_set_verify)]
2970 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2971 where
2972 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2973 {
2974 unsafe {
2975 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2977 ffi::SSL_set_verify(
2978 self.as_ptr(),
2979 mode.bits() as c_int,
2980 Some(ssl_raw_verify::<F>),
2981 );
2982 }
2983 }
2984
2985 #[corresponds(SSL_set_info_callback)]
2988 pub fn set_info_callback<F>(&mut self, callback: F)
2989 where
2990 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2991 {
2992 unsafe {
2993 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2995 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2996 }
2997 }
2998
2999 #[corresponds(SSL_set_dh_auto)]
3003 #[cfg(ossl300)]
3004 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3005 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3006 }
3007
3008 #[corresponds(SSL_set_tmp_dh)]
3012 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3013 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3014 }
3015
3016 #[corresponds(SSL_set_tmp_dh_callback)]
3020 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3021 where
3022 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3023 {
3024 unsafe {
3025 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3027 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3028 }
3029 }
3030
3031 #[corresponds(SSL_set_tmp_ecdh)]
3035 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3036 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3037 }
3038
3039 #[corresponds(SSL_set_ecdh_auto)]
3045 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
3046 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3047 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3048 }
3049
3050 #[corresponds(SSL_set_alpn_protos)]
3056 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3057 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3058 unsafe {
3059 assert!(protocols.len() <= c_uint::MAX as usize);
3060 let r =
3061 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3062 if r == 0 {
3064 Ok(())
3065 } else {
3066 Err(ErrorStack::get())
3067 }
3068 }
3069 }
3070
3071 #[corresponds(SSL_get_current_cipher)]
3073 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3074 unsafe {
3075 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3076
3077 SslCipherRef::from_const_ptr_opt(ptr)
3078 }
3079 }
3080
3081 #[corresponds(SSL_state_string)]
3083 pub fn state_string(&self) -> &'static str {
3084 let state = unsafe {
3085 let ptr = ffi::SSL_state_string(self.as_ptr());
3086 CStr::from_ptr(ptr as *const _)
3087 };
3088
3089 str::from_utf8(state.to_bytes()).unwrap()
3090 }
3091
3092 #[corresponds(SSL_state_string_long)]
3094 pub fn state_string_long(&self) -> &'static str {
3095 let state = unsafe {
3096 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3097 CStr::from_ptr(ptr as *const _)
3098 };
3099
3100 str::from_utf8(state.to_bytes()).unwrap()
3101 }
3102
3103 #[corresponds(SSL_set_tlsext_host_name)]
3107 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3108 let cstr = CString::new(hostname).unwrap();
3109 unsafe {
3110 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3111 .map(|_| ())
3112 }
3113 }
3114
3115 #[corresponds(SSL_get_peer_certificate)]
3117 pub fn peer_certificate(&self) -> Option<X509> {
3118 unsafe {
3119 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3120 X509::from_ptr_opt(ptr)
3121 }
3122 }
3123
3124 #[corresponds(SSL_get_peer_cert_chain)]
3129 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3130 unsafe {
3131 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3132 StackRef::from_const_ptr_opt(ptr)
3133 }
3134 }
3135
3136 #[corresponds(SSL_get0_verified_chain)]
3146 #[cfg(ossl110)]
3147 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3148 unsafe {
3149 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3150 StackRef::from_const_ptr_opt(ptr)
3151 }
3152 }
3153
3154 #[corresponds(SSL_get_certificate)]
3156 pub fn certificate(&self) -> Option<&X509Ref> {
3157 unsafe {
3158 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3159 X509Ref::from_const_ptr_opt(ptr)
3160 }
3161 }
3162
3163 #[corresponds(SSL_get_privatekey)]
3167 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3168 unsafe {
3169 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3170 PKeyRef::from_const_ptr_opt(ptr)
3171 }
3172 }
3173
3174 #[corresponds(SSL_version)]
3176 pub fn version2(&self) -> Option<SslVersion> {
3177 unsafe {
3178 let r = ffi::SSL_version(self.as_ptr());
3179 if r == 0 {
3180 None
3181 } else {
3182 Some(SslVersion(r))
3183 }
3184 }
3185 }
3186
3187 #[corresponds(SSL_get_version)]
3189 pub fn version_str(&self) -> &'static str {
3190 let version = unsafe {
3191 let ptr = ffi::SSL_get_version(self.as_ptr());
3192 CStr::from_ptr(ptr as *const _)
3193 };
3194
3195 str::from_utf8(version.to_bytes()).unwrap()
3196 }
3197
3198 #[corresponds(SSL_get0_alpn_selected)]
3205 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
3206 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3207 unsafe {
3208 let mut data: *const c_uchar = ptr::null();
3209 let mut len: c_uint = 0;
3210 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3213
3214 if data.is_null() {
3215 None
3216 } else {
3217 Some(util::from_raw_parts(data, len as usize))
3218 }
3219 }
3220 }
3221
3222 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3224 #[corresponds(SSL_set_tlsext_use_srtp)]
3225 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3226 unsafe {
3227 let cstr = CString::new(protocols).unwrap();
3228
3229 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3230 if r == 0 {
3232 Ok(())
3233 } else {
3234 Err(ErrorStack::get())
3235 }
3236 }
3237 }
3238
3239 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3243 #[corresponds(SSL_get_srtp_profiles)]
3244 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3245 unsafe {
3246 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3247
3248 StackRef::from_const_ptr_opt(chain)
3249 }
3250 }
3251
3252 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3256 #[corresponds(SSL_get_selected_srtp_profile)]
3257 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3258 unsafe {
3259 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3260
3261 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3262 }
3263 }
3264
3265 #[corresponds(SSL_pending)]
3270 pub fn pending(&self) -> usize {
3271 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3272 }
3273
3274 #[corresponds(SSL_get_servername)]
3287 pub fn servername(&self, type_: NameType) -> Option<&str> {
3289 self.servername_raw(type_)
3290 .and_then(|b| str::from_utf8(b).ok())
3291 }
3292
3293 #[corresponds(SSL_get_servername)]
3301 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3302 unsafe {
3303 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3304 if name.is_null() {
3305 None
3306 } else {
3307 Some(CStr::from_ptr(name as *const _).to_bytes())
3308 }
3309 }
3310 }
3311
3312 #[corresponds(SSL_set_SSL_CTX)]
3316 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3317 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3318 }
3319
3320 #[corresponds(SSL_get_SSL_CTX)]
3322 pub fn ssl_context(&self) -> &SslContextRef {
3323 unsafe {
3324 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3325 SslContextRef::from_ptr(ssl_ctx)
3326 }
3327 }
3328
3329 #[corresponds(SSL_get0_param)]
3333 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
3334 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3335 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3336 }
3337
3338 #[corresponds(SSL_get_verify_result)]
3340 pub fn verify_result(&self) -> X509VerifyResult {
3341 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3342 }
3343
3344 #[corresponds(SSL_get_session)]
3346 pub fn session(&self) -> Option<&SslSessionRef> {
3347 unsafe {
3348 let p = ffi::SSL_get_session(self.as_ptr());
3349 SslSessionRef::from_const_ptr_opt(p)
3350 }
3351 }
3352
3353 #[corresponds(SSL_get_client_random)]
3360 #[cfg(any(ossl110, libressl270))]
3361 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3362 unsafe {
3363 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3364 }
3365 }
3366
3367 #[corresponds(SSL_get_server_random)]
3374 #[cfg(any(ossl110, libressl270))]
3375 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3376 unsafe {
3377 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3378 }
3379 }
3380
3381 #[corresponds(SSL_export_keying_material)]
3383 pub fn export_keying_material(
3384 &self,
3385 out: &mut [u8],
3386 label: &str,
3387 context: Option<&[u8]>,
3388 ) -> Result<(), ErrorStack> {
3389 unsafe {
3390 let (context, contextlen, use_context) = match context {
3391 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3392 None => (ptr::null(), 0, 0),
3393 };
3394 cvt(ffi::SSL_export_keying_material(
3395 self.as_ptr(),
3396 out.as_mut_ptr() as *mut c_uchar,
3397 out.len(),
3398 label.as_ptr() as *const c_char,
3399 label.len(),
3400 context,
3401 contextlen,
3402 use_context,
3403 ))
3404 .map(|_| ())
3405 }
3406 }
3407
3408 #[corresponds(SSL_export_keying_material_early)]
3415 #[cfg(ossl111)]
3416 pub fn export_keying_material_early(
3417 &self,
3418 out: &mut [u8],
3419 label: &str,
3420 context: &[u8],
3421 ) -> Result<(), ErrorStack> {
3422 unsafe {
3423 cvt(ffi::SSL_export_keying_material_early(
3424 self.as_ptr(),
3425 out.as_mut_ptr() as *mut c_uchar,
3426 out.len(),
3427 label.as_ptr() as *const c_char,
3428 label.len(),
3429 context.as_ptr() as *const c_uchar,
3430 context.len(),
3431 ))
3432 .map(|_| ())
3433 }
3434 }
3435
3436 #[corresponds(SSL_set_session)]
3447 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3448 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3449 }
3450
3451 #[corresponds(SSL_session_reused)]
3453 pub fn session_reused(&self) -> bool {
3454 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3455 }
3456
3457 #[cfg(any(boringssl, awslc))]
3465 pub fn enable_ocsp_stapling(&mut self) {
3466 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3467 }
3468
3469 #[cfg(any(boringssl, awslc))]
3477 pub fn enable_signed_cert_timestamps(&mut self) {
3478 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3479 }
3480
3481 #[cfg(any(boringssl, awslc))]
3489 pub fn set_permute_extensions(&mut self, enabled: bool) {
3490 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3491 }
3492
3493 #[corresponds(SSL_enable_ct)]
3495 #[cfg(ossl111)]
3496 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3497 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3498 }
3499
3500 #[corresponds(SSL_ct_is_enabled)]
3502 #[cfg(ossl111)]
3503 pub fn ct_is_enabled(&self) -> bool {
3504 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3505 }
3506
3507 #[corresponds(SSL_set_tlsext_status_type)]
3509 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3510 unsafe {
3511 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3512 }
3513 }
3514
3515 #[corresponds(SSL_get_extms_support)]
3519 #[cfg(ossl110)]
3520 pub fn extms_support(&self) -> Option<bool> {
3521 unsafe {
3522 match ffi::SSL_get_extms_support(self.as_ptr()) {
3523 -1 => None,
3524 ret => Some(ret != 0),
3525 }
3526 }
3527 }
3528
3529 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3531 #[cfg(not(any(boringssl, awslc)))]
3532 pub fn ocsp_status(&self) -> Option<&[u8]> {
3533 unsafe {
3534 let mut p = ptr::null_mut();
3535 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3536
3537 if len < 0 {
3538 None
3539 } else {
3540 Some(util::from_raw_parts(p as *const u8, len as usize))
3541 }
3542 }
3543 }
3544
3545 #[corresponds(SSL_get0_ocsp_response)]
3547 #[cfg(any(boringssl, awslc))]
3548 pub fn ocsp_status(&self) -> Option<&[u8]> {
3549 unsafe {
3550 let mut p = ptr::null();
3551 let mut len: usize = 0;
3552 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3553
3554 if len == 0 {
3555 None
3556 } else {
3557 Some(util::from_raw_parts(p as *const u8, len))
3558 }
3559 }
3560 }
3561
3562 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3564 #[cfg(not(any(boringssl, awslc)))]
3565 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3566 unsafe {
3567 assert!(response.len() <= c_int::MAX as usize);
3568 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3569 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3570 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3571 self.as_ptr(),
3572 p as *mut c_uchar,
3573 response.len() as c_long,
3574 ) as c_int)
3575 .map(|_| ())
3576 .map_err(|e| {
3577 ffi::OPENSSL_free(p);
3578 e
3579 })
3580 }
3581 }
3582
3583 #[corresponds(SSL_set_ocsp_response)]
3585 #[cfg(any(boringssl, awslc))]
3586 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3587 unsafe {
3588 cvt(ffi::SSL_set_ocsp_response(
3589 self.as_ptr(),
3590 response.as_ptr(),
3591 response.len(),
3592 ))
3593 .map(|_| ())
3594 }
3595 }
3596
3597 #[corresponds(SSL_is_server)]
3599 pub fn is_server(&self) -> bool {
3600 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3601 }
3602
3603 #[corresponds(SSL_set_ex_data)]
3609 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3610 match self.ex_data_mut(index) {
3611 Some(v) => *v = data,
3612 None => unsafe {
3613 let data = Box::new(data);
3614 ffi::SSL_set_ex_data(
3615 self.as_ptr(),
3616 index.as_raw(),
3617 Box::into_raw(data) as *mut c_void,
3618 );
3619 },
3620 }
3621 }
3622
3623 #[corresponds(SSL_get_ex_data)]
3625 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3626 unsafe {
3627 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3628 if data.is_null() {
3629 None
3630 } else {
3631 Some(&*(data as *const T))
3632 }
3633 }
3634 }
3635
3636 #[corresponds(SSL_get_ex_data)]
3638 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3639 unsafe {
3640 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3641 if data.is_null() {
3642 None
3643 } else {
3644 Some(&mut *(data as *mut T))
3645 }
3646 }
3647 }
3648
3649 #[corresponds(SSL_set_max_early_data)]
3653 #[cfg(any(ossl111, libressl340))]
3654 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3655 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3656 Ok(())
3657 } else {
3658 Err(ErrorStack::get())
3659 }
3660 }
3661
3662 #[corresponds(SSL_get_max_early_data)]
3666 #[cfg(any(ossl111, libressl340))]
3667 pub fn max_early_data(&self) -> u32 {
3668 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3669 }
3670
3671 #[corresponds(SSL_get_finished)]
3676 pub fn finished(&self, buf: &mut [u8]) -> usize {
3677 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3678 }
3679
3680 #[corresponds(SSL_get_peer_finished)]
3686 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3687 unsafe {
3688 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3689 }
3690 }
3691
3692 #[corresponds(SSL_is_init_finished)]
3694 #[cfg(ossl110)]
3695 pub fn is_init_finished(&self) -> bool {
3696 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3697 }
3698
3699 #[corresponds(SSL_client_hello_isv2)]
3705 #[cfg(ossl111)]
3706 pub fn client_hello_isv2(&self) -> bool {
3707 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3708 }
3709
3710 #[corresponds(SSL_client_hello_get0_legacy_version)]
3716 #[cfg(ossl111)]
3717 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3718 unsafe {
3719 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3720 if version == 0 {
3721 None
3722 } else {
3723 Some(SslVersion(version as c_int))
3724 }
3725 }
3726 }
3727
3728 #[corresponds(SSL_client_hello_get0_random)]
3734 #[cfg(ossl111)]
3735 pub fn client_hello_random(&self) -> Option<&[u8]> {
3736 unsafe {
3737 let mut ptr = ptr::null();
3738 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3739 if len == 0 {
3740 None
3741 } else {
3742 Some(util::from_raw_parts(ptr, len))
3743 }
3744 }
3745 }
3746
3747 #[corresponds(SSL_client_hello_get0_session_id)]
3753 #[cfg(ossl111)]
3754 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3755 unsafe {
3756 let mut ptr = ptr::null();
3757 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3758 if len == 0 {
3759 None
3760 } else {
3761 Some(util::from_raw_parts(ptr, len))
3762 }
3763 }
3764 }
3765
3766 #[corresponds(SSL_client_hello_get0_ciphers)]
3772 #[cfg(ossl111)]
3773 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3774 unsafe {
3775 let mut ptr = ptr::null();
3776 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3777 if len == 0 {
3778 None
3779 } else {
3780 Some(util::from_raw_parts(ptr, len))
3781 }
3782 }
3783 }
3784
3785 #[cfg(ossl111)]
3791 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3792 unsafe {
3793 let mut ptr = ptr::null();
3794 let mut len = 0usize;
3795 let r = ffi::SSL_client_hello_get0_ext(
3796 self.as_ptr(),
3797 ext_type.as_raw() as _,
3798 &mut ptr,
3799 &mut len,
3800 );
3801 if r == 0 {
3802 None
3803 } else {
3804 Some(util::from_raw_parts(ptr, len))
3805 }
3806 }
3807 }
3808
3809 #[corresponds(SSL_bytes_to_cipher_list)]
3814 #[cfg(ossl111)]
3815 pub fn bytes_to_cipher_list(
3816 &self,
3817 bytes: &[u8],
3818 isv2format: bool,
3819 ) -> Result<CipherLists, ErrorStack> {
3820 unsafe {
3821 let ptr = bytes.as_ptr();
3822 let len = bytes.len();
3823 let mut sk = ptr::null_mut();
3824 let mut scsvs = ptr::null_mut();
3825 let res = ffi::SSL_bytes_to_cipher_list(
3826 self.as_ptr(),
3827 ptr,
3828 len,
3829 isv2format as c_int,
3830 &mut sk,
3831 &mut scsvs,
3832 );
3833 if res == 1 {
3834 Ok(CipherLists {
3835 suites: Stack::from_ptr(sk),
3836 signalling_suites: Stack::from_ptr(scsvs),
3837 })
3838 } else {
3839 Err(ErrorStack::get())
3840 }
3841 }
3842 }
3843
3844 #[corresponds(SSL_client_hello_get0_compression_methods)]
3850 #[cfg(ossl111)]
3851 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3852 unsafe {
3853 let mut ptr = ptr::null();
3854 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3855 if len == 0 {
3856 None
3857 } else {
3858 Some(util::from_raw_parts(ptr, len))
3859 }
3860 }
3861 }
3862
3863 #[corresponds(SSL_set_mtu)]
3865 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3866 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3867 }
3868
3869 #[corresponds(SSL_get_psk_identity_hint)]
3873 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3874 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3875 unsafe {
3876 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3877 if ptr.is_null() {
3878 None
3879 } else {
3880 Some(CStr::from_ptr(ptr).to_bytes())
3881 }
3882 }
3883 }
3884
3885 #[corresponds(SSL_get_psk_identity)]
3887 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3888 pub fn psk_identity(&self) -> Option<&[u8]> {
3889 unsafe {
3890 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3891 if ptr.is_null() {
3892 None
3893 } else {
3894 Some(CStr::from_ptr(ptr).to_bytes())
3895 }
3896 }
3897 }
3898
3899 #[corresponds(SSL_add0_chain_cert)]
3900 #[cfg(any(ossl102, libressl291, boringssl, awslc))]
3901 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3902 unsafe {
3903 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3904 mem::forget(chain);
3905 }
3906 Ok(())
3907 }
3908
3909 #[cfg(not(any(boringssl, awslc)))]
3911 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3912 unsafe {
3913 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3914 };
3915 Ok(())
3916 }
3917
3918 #[corresponds(SSL_use_Private_Key_file)]
3920 pub fn set_private_key_file<P: AsRef<Path>>(
3921 &mut self,
3922 path: P,
3923 ssl_file_type: SslFiletype,
3924 ) -> Result<(), ErrorStack> {
3925 let p = path.as_ref().as_os_str().to_str().unwrap();
3926 let key_file = CString::new(p).unwrap();
3927 unsafe {
3928 cvt(ffi::SSL_use_PrivateKey_file(
3929 self.as_ptr(),
3930 key_file.as_ptr(),
3931 ssl_file_type.as_raw(),
3932 ))?;
3933 };
3934 Ok(())
3935 }
3936
3937 #[corresponds(SSL_use_PrivateKey)]
3939 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3940 unsafe {
3941 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3942 };
3943 Ok(())
3944 }
3945
3946 #[cfg(tongsuo)]
3947 #[corresponds(SSL_use_enc_Private_Key_file)]
3948 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3949 &mut self,
3950 path: P,
3951 ssl_file_type: SslFiletype,
3952 ) -> Result<(), ErrorStack> {
3953 let p = path.as_ref().as_os_str().to_str().unwrap();
3954 let key_file = CString::new(p).unwrap();
3955 unsafe {
3956 cvt(ffi::SSL_use_enc_PrivateKey_file(
3957 self.as_ptr(),
3958 key_file.as_ptr(),
3959 ssl_file_type.as_raw(),
3960 ))?;
3961 };
3962 Ok(())
3963 }
3964
3965 #[cfg(tongsuo)]
3966 #[corresponds(SSL_use_enc_PrivateKey)]
3967 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3968 unsafe {
3969 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3970 };
3971 Ok(())
3972 }
3973
3974 #[cfg(tongsuo)]
3975 #[corresponds(SSL_use_sign_Private_Key_file)]
3976 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3977 &mut self,
3978 path: P,
3979 ssl_file_type: SslFiletype,
3980 ) -> Result<(), ErrorStack> {
3981 let p = path.as_ref().as_os_str().to_str().unwrap();
3982 let key_file = CString::new(p).unwrap();
3983 unsafe {
3984 cvt(ffi::SSL_use_sign_PrivateKey_file(
3985 self.as_ptr(),
3986 key_file.as_ptr(),
3987 ssl_file_type.as_raw(),
3988 ))?;
3989 };
3990 Ok(())
3991 }
3992
3993 #[cfg(tongsuo)]
3994 #[corresponds(SSL_use_sign_PrivateKey)]
3995 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3996 unsafe {
3997 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3998 };
3999 Ok(())
4000 }
4001
4002 #[corresponds(SSL_use_certificate)]
4004 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4005 unsafe {
4006 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
4007 };
4008 Ok(())
4009 }
4010
4011 #[cfg(tongsuo)]
4012 #[corresponds(SSL_use_enc_certificate)]
4013 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4014 unsafe {
4015 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4016 };
4017 Ok(())
4018 }
4019
4020 #[cfg(tongsuo)]
4021 #[corresponds(SSL_use_sign_certificate)]
4022 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4023 unsafe {
4024 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4025 };
4026 Ok(())
4027 }
4028
4029 #[corresponds(SSL_use_certificate_chain_file)]
4035 #[cfg(any(ossl110, libressl332))]
4036 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4037 &mut self,
4038 path: P,
4039 ) -> Result<(), ErrorStack> {
4040 let p = path.as_ref().as_os_str().to_str().unwrap();
4041 let cert_file = CString::new(p).unwrap();
4042 unsafe {
4043 cvt(ffi::SSL_use_certificate_chain_file(
4044 self.as_ptr(),
4045 cert_file.as_ptr(),
4046 ))?;
4047 };
4048 Ok(())
4049 }
4050
4051 #[corresponds(SSL_add_client_CA)]
4053 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4054 unsafe {
4055 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4056 };
4057 Ok(())
4058 }
4059
4060 #[corresponds(SSL_set_client_CA_list)]
4062 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4063 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4064 mem::forget(list);
4065 }
4066
4067 #[corresponds(SSL_set_min_proto_version)]
4074 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4075 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4076 unsafe {
4077 cvt(ffi::SSL_set_min_proto_version(
4078 self.as_ptr(),
4079 version.map_or(0, |v| v.0 as _),
4080 ))
4081 .map(|_| ())
4082 }
4083 }
4084
4085 #[corresponds(SSL_set_max_proto_version)]
4092 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
4093 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4094 unsafe {
4095 cvt(ffi::SSL_set_max_proto_version(
4096 self.as_ptr(),
4097 version.map_or(0, |v| v.0 as _),
4098 ))
4099 .map(|_| ())
4100 }
4101 }
4102
4103 #[corresponds(SSL_set_ciphersuites)]
4112 #[cfg(any(ossl111, libressl340))]
4113 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4114 let cipher_list = CString::new(cipher_list).unwrap();
4115 unsafe {
4116 cvt(ffi::SSL_set_ciphersuites(
4117 self.as_ptr(),
4118 cipher_list.as_ptr() as *const _,
4119 ))
4120 .map(|_| ())
4121 }
4122 }
4123
4124 #[corresponds(SSL_set_cipher_list)]
4132 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4133 let cipher_list = CString::new(cipher_list).unwrap();
4134 unsafe {
4135 cvt(ffi::SSL_set_cipher_list(
4136 self.as_ptr(),
4137 cipher_list.as_ptr() as *const _,
4138 ))
4139 .map(|_| ())
4140 }
4141 }
4142
4143 #[corresponds(SSL_set_cert_store)]
4145 #[cfg(any(ossl102, boringssl, awslc))]
4146 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4147 unsafe {
4148 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4149 mem::forget(cert_store);
4150 Ok(())
4151 }
4152 }
4153
4154 #[corresponds(SSL_set_num_tickets)]
4159 #[cfg(ossl111)]
4160 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4161 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4162 }
4163
4164 #[corresponds(SSL_get_num_tickets)]
4169 #[cfg(ossl111)]
4170 pub fn num_tickets(&self) -> usize {
4171 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4172 }
4173
4174 #[corresponds(SSL_set_security_level)]
4179 #[cfg(any(ossl110, libressl360))]
4180 pub fn set_security_level(&mut self, level: u32) {
4181 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4182 }
4183
4184 #[corresponds(SSL_get_security_level)]
4189 #[cfg(any(ossl110, libressl360))]
4190 pub fn security_level(&self) -> u32 {
4191 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4192 }
4193
4194 #[corresponds(SSL_get_peer_tmp_key)]
4199 #[cfg(ossl300)]
4200 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4201 unsafe {
4202 let mut key = ptr::null_mut();
4203 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4204 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4205 Err(e) => Err(e),
4206 }
4207 }
4208 }
4209
4210 #[corresponds(SSL_get_tmp_key)]
4215 #[cfg(ossl300)]
4216 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4217 unsafe {
4218 let mut key = ptr::null_mut();
4219 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4220 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4221 Err(e) => Err(e),
4222 }
4223 }
4224 }
4225}
4226
4227#[derive(Debug)]
4229pub struct MidHandshakeSslStream<S> {
4230 stream: SslStream<S>,
4231 error: Error,
4232}
4233
4234impl<S> MidHandshakeSslStream<S> {
4235 pub fn get_ref(&self) -> &S {
4237 self.stream.get_ref()
4238 }
4239
4240 pub fn get_mut(&mut self) -> &mut S {
4242 self.stream.get_mut()
4243 }
4244
4245 pub fn ssl(&self) -> &SslRef {
4247 self.stream.ssl()
4248 }
4249
4250 pub fn ssl_mut(&mut self) -> &mut SslRef {
4252 self.stream.ssl_mut()
4253 }
4254
4255 pub fn error(&self) -> &Error {
4257 &self.error
4258 }
4259
4260 pub fn into_error(self) -> Error {
4262 self.error
4263 }
4264}
4265
4266impl<S> MidHandshakeSslStream<S>
4267where
4268 S: Read + Write,
4269{
4270 #[corresponds(SSL_do_handshake)]
4273 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4274 match self.stream.do_handshake() {
4275 Ok(()) => Ok(self.stream),
4276 Err(error) => {
4277 self.error = error;
4278 match self.error.code() {
4279 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4280 Err(HandshakeError::WouldBlock(self))
4281 }
4282 _ => Err(HandshakeError::Failure(self)),
4283 }
4284 }
4285 }
4286 }
4287}
4288
4289pub struct SslStream<S> {
4291 ssl: ManuallyDrop<Ssl>,
4292 method: ManuallyDrop<BioMethod>,
4293 _p: PhantomData<S>,
4294}
4295
4296impl<S> Drop for SslStream<S> {
4297 fn drop(&mut self) {
4298 unsafe {
4300 ManuallyDrop::drop(&mut self.ssl);
4301 ManuallyDrop::drop(&mut self.method);
4302 }
4303 }
4304}
4305
4306impl<S> fmt::Debug for SslStream<S>
4307where
4308 S: fmt::Debug,
4309{
4310 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4311 fmt.debug_struct("SslStream")
4312 .field("stream", &self.get_ref())
4313 .field("ssl", &self.ssl())
4314 .finish()
4315 }
4316}
4317
4318impl<S: Read + Write> SslStream<S> {
4319 #[corresponds(SSL_set_bio)]
4327 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4328 let (bio, method) = bio::new(stream)?;
4329 unsafe {
4330 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4331 }
4332
4333 Ok(SslStream {
4334 ssl: ManuallyDrop::new(ssl),
4335 method: ManuallyDrop::new(method),
4336 _p: PhantomData,
4337 })
4338 }
4339
4340 #[corresponds(SSL_read_early_data)]
4349 #[cfg(any(ossl111, libressl340))]
4350 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4351 let mut read = 0;
4352 let ret = unsafe {
4353 ffi::SSL_read_early_data(
4354 self.ssl.as_ptr(),
4355 buf.as_ptr() as *mut c_void,
4356 buf.len(),
4357 &mut read,
4358 )
4359 };
4360 match ret {
4361 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4362 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4363 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4364 _ => unreachable!(),
4365 }
4366 }
4367
4368 #[corresponds(SSL_write_early_data)]
4375 #[cfg(any(ossl111, libressl340))]
4376 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4377 let mut written = 0;
4378 let ret = unsafe {
4379 ffi::SSL_write_early_data(
4380 self.ssl.as_ptr(),
4381 buf.as_ptr() as *const c_void,
4382 buf.len(),
4383 &mut written,
4384 )
4385 };
4386 if ret > 0 {
4387 Ok(written)
4388 } else {
4389 Err(self.make_error(ret))
4390 }
4391 }
4392
4393 #[corresponds(SSL_connect)]
4400 pub fn connect(&mut self) -> Result<(), Error> {
4401 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4402 if ret > 0 {
4403 Ok(())
4404 } else {
4405 Err(self.make_error(ret))
4406 }
4407 }
4408
4409 #[corresponds(SSL_accept)]
4416 pub fn accept(&mut self) -> Result<(), Error> {
4417 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4418 if ret > 0 {
4419 Ok(())
4420 } else {
4421 Err(self.make_error(ret))
4422 }
4423 }
4424
4425 #[corresponds(SSL_do_handshake)]
4429 pub fn do_handshake(&mut self) -> Result<(), Error> {
4430 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4431 if ret > 0 {
4432 Ok(())
4433 } else {
4434 Err(self.make_error(ret))
4435 }
4436 }
4437
4438 #[corresponds(SSL_stateless)]
4449 #[cfg(ossl111)]
4450 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4451 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4452 1 => Ok(true),
4453 0 => Ok(false),
4454 -1 => Err(ErrorStack::get()),
4455 _ => unreachable!(),
4456 }
4457 }
4458
4459 #[corresponds(SSL_read_ex)]
4466 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4467 loop {
4468 match self.ssl_read_uninit(buf) {
4469 Ok(n) => return Ok(n),
4470 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4471 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4472 return Ok(0);
4473 }
4474 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4475 Err(e) => {
4476 return Err(e
4477 .into_io_error()
4478 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4479 }
4480 }
4481 }
4482 }
4483
4484 #[corresponds(SSL_read_ex)]
4489 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4490 unsafe {
4492 self.ssl_read_uninit(util::from_raw_parts_mut(
4493 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4494 buf.len(),
4495 ))
4496 }
4497 }
4498
4499 #[corresponds(SSL_read_ex)]
4506 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4507 cfg_if! {
4508 if #[cfg(any(ossl111, libressl350))] {
4509 let mut readbytes = 0;
4510 let ret = unsafe {
4511 ffi::SSL_read_ex(
4512 self.ssl().as_ptr(),
4513 buf.as_mut_ptr().cast(),
4514 buf.len(),
4515 &mut readbytes,
4516 )
4517 };
4518
4519 if ret > 0 {
4520 Ok(readbytes)
4521 } else {
4522 Err(self.make_error(ret))
4523 }
4524 } else {
4525 if buf.is_empty() {
4526 return Ok(0);
4527 }
4528
4529 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4530 let ret = unsafe {
4531 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4532 };
4533 if ret > 0 {
4534 Ok(ret as usize)
4535 } else {
4536 Err(self.make_error(ret))
4537 }
4538 }
4539 }
4540 }
4541
4542 #[corresponds(SSL_write_ex)]
4547 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4548 cfg_if! {
4549 if #[cfg(any(ossl111, libressl350))] {
4550 let mut written = 0;
4551 let ret = unsafe {
4552 ffi::SSL_write_ex(
4553 self.ssl().as_ptr(),
4554 buf.as_ptr().cast(),
4555 buf.len(),
4556 &mut written,
4557 )
4558 };
4559
4560 if ret > 0 {
4561 Ok(written)
4562 } else {
4563 Err(self.make_error(ret))
4564 }
4565 } else {
4566 if buf.is_empty() {
4567 return Ok(0);
4568 }
4569
4570 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4571 let ret = unsafe {
4572 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4573 };
4574 if ret > 0 {
4575 Ok(ret as usize)
4576 } else {
4577 Err(self.make_error(ret))
4578 }
4579 }
4580 }
4581 }
4582
4583 #[corresponds(SSL_peek_ex)]
4585 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4586 unsafe {
4588 self.ssl_peek_uninit(util::from_raw_parts_mut(
4589 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4590 buf.len(),
4591 ))
4592 }
4593 }
4594
4595 #[corresponds(SSL_peek_ex)]
4602 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4603 cfg_if! {
4604 if #[cfg(any(ossl111, libressl350))] {
4605 let mut readbytes = 0;
4606 let ret = unsafe {
4607 ffi::SSL_peek_ex(
4608 self.ssl().as_ptr(),
4609 buf.as_mut_ptr().cast(),
4610 buf.len(),
4611 &mut readbytes,
4612 )
4613 };
4614
4615 if ret > 0 {
4616 Ok(readbytes)
4617 } else {
4618 Err(self.make_error(ret))
4619 }
4620 } else {
4621 if buf.is_empty() {
4622 return Ok(0);
4623 }
4624
4625 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4626 let ret = unsafe {
4627 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4628 };
4629 if ret > 0 {
4630 Ok(ret as usize)
4631 } else {
4632 Err(self.make_error(ret))
4633 }
4634 }
4635 }
4636 }
4637
4638 #[corresponds(SSL_shutdown)]
4648 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4649 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4650 0 => Ok(ShutdownResult::Sent),
4651 1 => Ok(ShutdownResult::Received),
4652 n => Err(self.make_error(n)),
4653 }
4654 }
4655
4656 #[corresponds(SSL_get_shutdown)]
4658 pub fn get_shutdown(&mut self) -> ShutdownState {
4659 unsafe {
4660 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4661 ShutdownState::from_bits_retain(bits)
4662 }
4663 }
4664
4665 #[corresponds(SSL_set_shutdown)]
4670 pub fn set_shutdown(&mut self, state: ShutdownState) {
4671 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4672 }
4673}
4674
4675impl<S> SslStream<S> {
4676 fn make_error(&mut self, ret: c_int) -> Error {
4677 self.check_panic();
4678
4679 let code = self.ssl.get_error(ret);
4680
4681 let cause = match code {
4682 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4683 ErrorCode::SYSCALL => {
4684 let errs = ErrorStack::get();
4685 if errs.errors().is_empty() {
4686 self.get_bio_error().map(InnerError::Io)
4687 } else {
4688 Some(InnerError::Ssl(errs))
4689 }
4690 }
4691 ErrorCode::ZERO_RETURN => None,
4692 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4693 self.get_bio_error().map(InnerError::Io)
4694 }
4695 _ => None,
4696 };
4697
4698 Error { code, cause }
4699 }
4700
4701 fn check_panic(&mut self) {
4702 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4703 resume_unwind(err)
4704 }
4705 }
4706
4707 fn get_bio_error(&mut self) -> Option<io::Error> {
4708 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4709 }
4710
4711 pub fn get_ref(&self) -> &S {
4713 unsafe {
4714 let bio = self.ssl.get_raw_rbio();
4715 bio::get_ref(bio)
4716 }
4717 }
4718
4719 pub fn get_mut(&mut self) -> &mut S {
4726 unsafe {
4727 let bio = self.ssl.get_raw_rbio();
4728 bio::get_mut(bio)
4729 }
4730 }
4731
4732 pub fn ssl(&self) -> &SslRef {
4734 &self.ssl
4735 }
4736
4737 pub fn ssl_mut(&mut self) -> &mut SslRef {
4739 &mut self.ssl
4740 }
4741}
4742
4743impl<S: Read + Write> Read for SslStream<S> {
4744 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4745 unsafe {
4747 self.read_uninit(util::from_raw_parts_mut(
4748 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4749 buf.len(),
4750 ))
4751 }
4752 }
4753}
4754
4755impl<S: Read + Write> Write for SslStream<S> {
4756 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4757 loop {
4758 match self.ssl_write(buf) {
4759 Ok(n) => return Ok(n),
4760 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4761 Err(e) => {
4762 return Err(e
4763 .into_io_error()
4764 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4765 }
4766 }
4767 }
4768 }
4769
4770 fn flush(&mut self) -> io::Result<()> {
4771 self.get_mut().flush()
4772 }
4773}
4774
4775#[deprecated(
4777 since = "0.10.32",
4778 note = "use the methods directly on Ssl/SslStream instead"
4779)]
4780pub struct SslStreamBuilder<S> {
4781 inner: SslStream<S>,
4782}
4783
4784#[allow(deprecated)]
4785impl<S> SslStreamBuilder<S>
4786where
4787 S: Read + Write,
4788{
4789 pub fn new(ssl: Ssl, stream: S) -> Self {
4791 Self {
4792 inner: SslStream::new(ssl, stream).unwrap(),
4793 }
4794 }
4795
4796 #[corresponds(SSL_stateless)]
4807 #[cfg(ossl111)]
4808 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4809 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4810 1 => Ok(true),
4811 0 => Ok(false),
4812 -1 => Err(ErrorStack::get()),
4813 _ => unreachable!(),
4814 }
4815 }
4816
4817 #[corresponds(SSL_set_connect_state)]
4819 pub fn set_connect_state(&mut self) {
4820 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4821 }
4822
4823 #[corresponds(SSL_set_accept_state)]
4825 pub fn set_accept_state(&mut self) {
4826 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4827 }
4828
4829 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4831 match self.inner.connect() {
4832 Ok(()) => Ok(self.inner),
4833 Err(error) => match error.code() {
4834 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4835 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4836 stream: self.inner,
4837 error,
4838 }))
4839 }
4840 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4841 stream: self.inner,
4842 error,
4843 })),
4844 },
4845 }
4846 }
4847
4848 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4850 match self.inner.accept() {
4851 Ok(()) => Ok(self.inner),
4852 Err(error) => match error.code() {
4853 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4854 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4855 stream: self.inner,
4856 error,
4857 }))
4858 }
4859 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4860 stream: self.inner,
4861 error,
4862 })),
4863 },
4864 }
4865 }
4866
4867 #[corresponds(SSL_do_handshake)]
4871 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4872 match self.inner.do_handshake() {
4873 Ok(()) => Ok(self.inner),
4874 Err(error) => match error.code() {
4875 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4876 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4877 stream: self.inner,
4878 error,
4879 }))
4880 }
4881 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4882 stream: self.inner,
4883 error,
4884 })),
4885 },
4886 }
4887 }
4888
4889 #[corresponds(SSL_read_early_data)]
4899 #[cfg(any(ossl111, libressl340))]
4900 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4901 self.inner.read_early_data(buf)
4902 }
4903
4904 #[corresponds(SSL_write_early_data)]
4911 #[cfg(any(ossl111, libressl340))]
4912 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4913 self.inner.write_early_data(buf)
4914 }
4915}
4916
4917#[allow(deprecated)]
4918impl<S> SslStreamBuilder<S> {
4919 pub fn get_ref(&self) -> &S {
4921 unsafe {
4922 let bio = self.inner.ssl.get_raw_rbio();
4923 bio::get_ref(bio)
4924 }
4925 }
4926
4927 pub fn get_mut(&mut self) -> &mut S {
4934 unsafe {
4935 let bio = self.inner.ssl.get_raw_rbio();
4936 bio::get_mut(bio)
4937 }
4938 }
4939
4940 pub fn ssl(&self) -> &SslRef {
4942 &self.inner.ssl
4943 }
4944
4945 pub fn ssl_mut(&mut self) -> &mut SslRef {
4947 &mut self.inner.ssl
4948 }
4949}
4950
4951#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4953pub enum ShutdownResult {
4954 Sent,
4956
4957 Received,
4959}
4960
4961bitflags! {
4962 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4964 #[repr(transparent)]
4965 pub struct ShutdownState: c_int {
4966 const SENT = ffi::SSL_SENT_SHUTDOWN;
4968 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4970 }
4971}
4972
4973cfg_if! {
4974 if #[cfg(any(boringssl, ossl110, libressl273, awslc))] {
4975 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4976 } else {
4977 #[allow(bad_style)]
4978 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4979 ffi::CRYPTO_add_lock(
4980 &mut (*ssl).references,
4981 1,
4982 ffi::CRYPTO_LOCK_SSL_CTX,
4983 "mod.rs\0".as_ptr() as *const _,
4984 line!() as c_int,
4985 );
4986 0
4987 }
4988
4989 #[allow(bad_style)]
4990 pub unsafe fn SSL_SESSION_get_master_key(
4991 session: *const ffi::SSL_SESSION,
4992 out: *mut c_uchar,
4993 mut outlen: usize,
4994 ) -> usize {
4995 if outlen == 0 {
4996 return (*session).master_key_length as usize;
4997 }
4998 if outlen > (*session).master_key_length as usize {
4999 outlen = (*session).master_key_length as usize;
5000 }
5001 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
5002 outlen
5003 }
5004
5005 #[allow(bad_style)]
5006 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
5007 (*s).server
5008 }
5009
5010 #[allow(bad_style)]
5011 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
5012 ffi::CRYPTO_add_lock(
5013 &mut (*ses).references,
5014 1,
5015 ffi::CRYPTO_LOCK_SSL_CTX,
5016 "mod.rs\0".as_ptr() as *const _,
5017 line!() as c_int,
5018 );
5019 0
5020 }
5021 }
5022}
5023
5024cfg_if! {
5025 if #[cfg(ossl300)] {
5026 use ffi::SSL_get1_peer_certificate;
5027 } else {
5028 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
5029 }
5030}
5031cfg_if! {
5032 if #[cfg(any(boringssl, ossl110, libressl291, awslc))] {
5033 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
5034 } else {
5035 use ffi::{
5036 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
5037 SSLv23_server_method as TLS_server_method,
5038 };
5039 }
5040}
5041cfg_if! {
5042 if #[cfg(ossl110)] {
5043 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5044 ffi::CRYPTO_get_ex_new_index(
5045 ffi::CRYPTO_EX_INDEX_SSL_CTX,
5046 0,
5047 ptr::null_mut(),
5048 None,
5049 None,
5050 f,
5051 )
5052 }
5053
5054 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5055 ffi::CRYPTO_get_ex_new_index(
5056 ffi::CRYPTO_EX_INDEX_SSL,
5057 0,
5058 ptr::null_mut(),
5059 None,
5060 None,
5061 f,
5062 )
5063 }
5064 } else {
5065 use std::sync::Once;
5066
5067 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5068 static ONCE: Once = Once::new();
5070 ONCE.call_once(|| {
5071 cfg_if! {
5072 if #[cfg(not(any(boringssl, awslc)))] {
5073 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5074 } else {
5075 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5076 }
5077 }
5078 });
5079
5080 cfg_if! {
5081 if #[cfg(not(any(boringssl, awslc)))] {
5082 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5083 } else {
5084 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5085 }
5086 }
5087 }
5088
5089 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5090 static ONCE: Once = Once::new();
5092 ONCE.call_once(|| {
5093 #[cfg(not(any(boringssl, awslc)))]
5094 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5095 #[cfg(any(boringssl, awslc))]
5096 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5097 });
5098
5099 #[cfg(not(any(boringssl, awslc)))]
5100 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5101 #[cfg(any(boringssl, awslc))]
5102 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5103 }
5104 }
5105}