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, libressl))]
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};
86use crate::x509::verify::X509VerifyParamRef;
87use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
88use crate::{cvt, cvt_n, cvt_p, init};
89use bitflags::bitflags;
90use cfg_if::cfg_if;
91use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
92use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
93use once_cell::sync::{Lazy, OnceCell};
94use openssl_macros::corresponds;
95use std::any::TypeId;
96use std::collections::HashMap;
97use std::ffi::{CStr, CString};
98use std::fmt;
99use std::io;
100use std::io::prelude::*;
101use std::marker::PhantomData;
102use std::mem::{self, ManuallyDrop, MaybeUninit};
103use std::ops::{Deref, DerefMut};
104use std::panic::resume_unwind;
105use std::path::Path;
106use std::ptr;
107use std::str;
108use std::sync::{Arc, Mutex};
109
110pub use crate::ssl::connector::{
111 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
112};
113pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
114
115mod bio;
116mod callbacks;
117#[cfg(any(boringssl, awslc))]
118mod client_hello;
119mod connector;
120mod error;
121#[cfg(test)]
122mod test;
123
124#[cfg(any(boringssl, awslc))]
125pub use client_hello::ClientHello;
126
127#[corresponds(OPENSSL_cipher_name)]
133#[cfg(ossl111)]
134pub fn cipher_name(std_name: &str) -> &'static str {
135 unsafe {
136 ffi::init();
137
138 let s = CString::new(std_name).unwrap();
139 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
140 CStr::from_ptr(ptr).to_str().unwrap()
141 }
142}
143
144cfg_if! {
145 if #[cfg(ossl300)] {
146 type SslOptionsRepr = u64;
147 } else if #[cfg(any(boringssl, awslc))] {
148 type SslOptionsRepr = u32;
149 } else {
150 type SslOptionsRepr = libc::c_ulong;
151 }
152}
153
154bitflags! {
155 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
157 #[repr(transparent)]
158 pub struct SslOptions: SslOptionsRepr {
159 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
161
162 #[cfg(not(any(boringssl, awslc)))]
164 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
165
166 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
170
171 #[cfg(not(any(boringssl, awslc)))]
177 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
178
179 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
181
182 #[cfg(not(any(boringssl, awslc)))]
184 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
185 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
186
187 #[cfg(not(any(boringssl, awslc)))]
189 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
190
191 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
194 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
195
196 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
200
201 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
205
206 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
210
211 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
213
214 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
216
217 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
219
220 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
222
223 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
225
226 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
228
229 #[cfg(any(ossl111, boringssl, libressl, awslc))]
233 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
234
235 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
237
238 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
240
241 #[cfg(ossl110)]
257 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
258
259 #[cfg(any(boringssl, ossl110h, awslc))]
263 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
264
265 #[cfg(ossl111)]
270 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
271
272 #[cfg(ossl111)]
284 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
285 }
286}
287
288bitflags! {
289 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
291 #[repr(transparent)]
292 pub struct SslMode: SslBitType {
293 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
299
300 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
303
304 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
314
315 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
321
322 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
326
327 #[cfg(not(libressl))]
335 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
336
337 #[cfg(ossl110)]
344 const ASYNC = ffi::SSL_MODE_ASYNC;
345 }
346}
347
348#[derive(Copy, Clone)]
350pub struct SslMethod(*const ffi::SSL_METHOD);
351
352impl SslMethod {
353 #[corresponds(TLS_method)]
355 pub fn tls() -> SslMethod {
356 unsafe { SslMethod(TLS_method()) }
357 }
358
359 #[corresponds(DTLS_method)]
361 pub fn dtls() -> SslMethod {
362 unsafe { SslMethod(DTLS_method()) }
363 }
364
365 #[corresponds(TLS_client_method)]
367 pub fn tls_client() -> SslMethod {
368 unsafe { SslMethod(TLS_client_method()) }
369 }
370
371 #[corresponds(TLS_server_method)]
373 pub fn tls_server() -> SslMethod {
374 unsafe { SslMethod(TLS_server_method()) }
375 }
376
377 #[cfg(tongsuo)]
378 #[corresponds(NTLS_client_method)]
379 pub fn ntls_client() -> SslMethod {
380 unsafe { SslMethod(ffi::NTLS_client_method()) }
381 }
382
383 #[cfg(tongsuo)]
384 #[corresponds(NTLS_server_method)]
385 pub fn ntls_server() -> SslMethod {
386 unsafe { SslMethod(ffi::NTLS_server_method()) }
387 }
388
389 #[corresponds(DTLS_client_method)]
391 pub fn dtls_client() -> SslMethod {
392 unsafe { SslMethod(DTLS_client_method()) }
393 }
394
395 #[corresponds(DTLS_server_method)]
397 pub fn dtls_server() -> SslMethod {
398 unsafe { SslMethod(DTLS_server_method()) }
399 }
400
401 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
407 SslMethod(ptr)
408 }
409
410 #[allow(clippy::trivially_copy_pass_by_ref)]
412 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
413 self.0
414 }
415}
416
417unsafe impl Sync for SslMethod {}
418unsafe impl Send for SslMethod {}
419
420bitflags! {
421 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
423 #[repr(transparent)]
424 pub struct SslVerifyMode: i32 {
425 const PEER = ffi::SSL_VERIFY_PEER;
429
430 const NONE = ffi::SSL_VERIFY_NONE;
436
437 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
441 }
442}
443
444#[cfg(any(boringssl, awslc))]
445type SslBitType = c_int;
446#[cfg(not(any(boringssl, awslc)))]
447type SslBitType = c_long;
448
449#[cfg(any(boringssl, awslc))]
450type SslTimeTy = u64;
451#[cfg(not(any(boringssl, awslc)))]
452type SslTimeTy = c_long;
453
454bitflags! {
455 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
457 #[repr(transparent)]
458 pub struct SslSessionCacheMode: SslBitType {
459 const OFF = ffi::SSL_SESS_CACHE_OFF;
461
462 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
469
470 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
474
475 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
477
478 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
480
481 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
483
484 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
486
487 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
489 }
490}
491
492#[cfg(ossl111)]
493bitflags! {
494 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
496 #[repr(transparent)]
497 pub struct ExtensionContext: c_uint {
498 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
500 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
502 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
504 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
506 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
508 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
510 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
512 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
513 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
515 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
516 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
517 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
518 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
519 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
520 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
521 }
522}
523
524#[derive(Copy, Clone)]
526pub struct TlsExtType(c_uint);
527
528impl TlsExtType {
529 pub const SERVER_NAME: TlsExtType = TlsExtType(ffi::TLSEXT_TYPE_server_name as _);
533
534 pub const ALPN: TlsExtType =
538 TlsExtType(ffi::TLSEXT_TYPE_application_layer_protocol_negotiation as _);
539
540 pub fn from_raw(raw: c_uint) -> TlsExtType {
542 TlsExtType(raw)
543 }
544
545 #[allow(clippy::trivially_copy_pass_by_ref)]
547 pub fn as_raw(&self) -> c_uint {
548 self.0
549 }
550}
551
552#[derive(Copy, Clone)]
554pub struct SslFiletype(c_int);
555
556impl SslFiletype {
557 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
561
562 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
566
567 pub fn from_raw(raw: c_int) -> SslFiletype {
569 SslFiletype(raw)
570 }
571
572 #[allow(clippy::trivially_copy_pass_by_ref)]
574 pub fn as_raw(&self) -> c_int {
575 self.0
576 }
577}
578
579#[derive(Copy, Clone)]
581pub struct StatusType(c_int);
582
583impl StatusType {
584 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
586
587 pub fn from_raw(raw: c_int) -> StatusType {
589 StatusType(raw)
590 }
591
592 #[allow(clippy::trivially_copy_pass_by_ref)]
594 pub fn as_raw(&self) -> c_int {
595 self.0
596 }
597}
598
599#[derive(Copy, Clone)]
601pub struct NameType(c_int);
602
603impl NameType {
604 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
606
607 pub fn from_raw(raw: c_int) -> StatusType {
609 StatusType(raw)
610 }
611
612 #[allow(clippy::trivially_copy_pass_by_ref)]
614 pub fn as_raw(&self) -> c_int {
615 self.0
616 }
617}
618
619static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
620static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
621static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
622
623fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
624 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
625}
626
627unsafe extern "C" fn free_data_box<T>(
628 _parent: *mut c_void,
629 ptr: *mut c_void,
630 _ad: *mut ffi::CRYPTO_EX_DATA,
631 _idx: c_int,
632 _argl: c_long,
633 _argp: *mut c_void,
634) {
635 if !ptr.is_null() {
636 let _ = Box::<T>::from_raw(ptr as *mut T);
637 }
638}
639
640#[derive(Debug, Copy, Clone, PartialEq, Eq)]
642pub struct SniError(c_int);
643
644impl SniError {
645 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
647
648 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
650
651 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
652}
653
654#[derive(Debug, Copy, Clone, PartialEq, Eq)]
656pub struct SslAlert(c_int);
657
658impl SslAlert {
659 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
661 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
662 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
663 pub const NO_APPLICATION_PROTOCOL: SslAlert = SslAlert(ffi::SSL_AD_NO_APPLICATION_PROTOCOL);
664}
665
666#[derive(Debug, Copy, Clone, PartialEq, Eq)]
670pub struct AlpnError(c_int);
671
672impl AlpnError {
673 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
675
676 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
678}
679
680#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
684#[derive(Debug, Copy, Clone, PartialEq, Eq)]
685pub struct ClientHelloError(c_int);
686
687#[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
688impl ClientHelloError {
689 pub const ERROR: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_ERROR);
691
692 pub const RETRY: ClientHelloError = ClientHelloError(ffi::SSL_CLIENT_HELLO_RETRY);
694}
695
696#[derive(Debug, Copy, Clone, PartialEq, Eq)]
698pub struct TicketKeyStatus(c_int);
699
700impl TicketKeyStatus {
701 pub const FAILED: TicketKeyStatus = TicketKeyStatus(0);
703 pub const SUCCESS: TicketKeyStatus = TicketKeyStatus(1);
705 pub const SUCCESS_AND_RENEW: TicketKeyStatus = TicketKeyStatus(2);
707}
708
709#[derive(Debug, Copy, Clone, PartialEq, Eq)]
711#[cfg(any(boringssl, awslc))]
712pub struct SelectCertError(ffi::ssl_select_cert_result_t);
713
714#[cfg(any(boringssl, awslc))]
715impl SelectCertError {
716 pub const ERROR: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_error);
718
719 pub const RETRY: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_retry);
721
722 #[cfg(boringssl)]
728 pub const DISABLE_ECH: Self = Self(ffi::ssl_select_cert_result_t_ssl_select_cert_disable_ech);
729}
730
731#[cfg(ossl111)]
733#[derive(Debug, Copy, Clone, PartialEq, Eq)]
734pub struct SslCtValidationMode(c_int);
735
736#[cfg(ossl111)]
737impl SslCtValidationMode {
738 pub const PERMISSIVE: SslCtValidationMode =
739 SslCtValidationMode(ffi::SSL_CT_VALIDATION_PERMISSIVE as c_int);
740 pub const STRICT: SslCtValidationMode =
741 SslCtValidationMode(ffi::SSL_CT_VALIDATION_STRICT as c_int);
742}
743
744#[derive(Debug, Copy, Clone, PartialEq, Eq)]
746pub struct CertCompressionAlgorithm(c_int);
747
748impl CertCompressionAlgorithm {
749 pub const ZLIB: CertCompressionAlgorithm = CertCompressionAlgorithm(1);
750 pub const BROTLI: CertCompressionAlgorithm = CertCompressionAlgorithm(2);
751 pub const ZSTD: CertCompressionAlgorithm = CertCompressionAlgorithm(3);
752}
753
754#[derive(Debug, Copy, Clone, PartialEq, Eq)]
756pub struct SslVersion(c_int);
757
758impl SslVersion {
759 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
761
762 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
764
765 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
767
768 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
770
771 #[cfg(any(ossl111, libressl, boringssl, awslc))]
775 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
776
777 #[cfg(tongsuo)]
778 pub const NTLS1_1: SslVersion = SslVersion(ffi::NTLS1_1_VERSION);
779
780 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
784
785 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
789}
790
791cfg_if! {
792 if #[cfg(any(boringssl, awslc))] {
793 type SslCacheTy = i64;
794 type SslCacheSize = libc::c_ulong;
795 type MtuTy = u32;
796 type ModeTy = u32;
797 type SizeTy = usize;
798 } else {
799 type SslCacheTy = i64;
800 type SslCacheSize = c_long;
801 type MtuTy = c_long;
802 type ModeTy = c_long;
803 type SizeTy = u32;
804 }
805}
806
807#[corresponds(SSL_select_next_proto)]
818pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
819 unsafe {
820 let mut out = ptr::null_mut();
821 let mut outlen = 0;
822 let r = ffi::SSL_select_next_proto(
823 &mut out,
824 &mut outlen,
825 server.as_ptr(),
826 server.len() as c_uint,
827 client.as_ptr(),
828 client.len() as c_uint,
829 );
830 if r == ffi::OPENSSL_NPN_NEGOTIATED {
831 Some(util::from_raw_parts(out as *const u8, outlen as usize))
832 } else {
833 None
834 }
835 }
836}
837
838pub struct SslContextBuilder(SslContext);
840
841impl SslContextBuilder {
842 #[corresponds(SSL_CTX_new)]
844 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
845 unsafe {
846 init();
847 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
848
849 Ok(SslContextBuilder::from_ptr(ctx))
850 }
851 }
852
853 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
859 SslContextBuilder(SslContext::from_ptr(ctx))
860 }
861
862 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
864 self.0.as_ptr()
865 }
866
867 #[cfg(tongsuo)]
868 #[corresponds(SSL_CTX_enable_ntls)]
869 pub fn enable_ntls(&mut self) {
870 unsafe { ffi::SSL_CTX_enable_ntls(self.as_ptr()) }
871 }
872
873 #[cfg(tongsuo)]
874 #[corresponds(SSL_CTX_disable_ntls)]
875 pub fn disable_ntls(&mut self) {
876 unsafe { ffi::SSL_CTX_disable_ntls(self.as_ptr()) }
877 }
878
879 #[cfg(all(tongsuo, ossl300))]
880 #[corresponds(SSL_CTX_enable_force_ntls)]
881 pub fn enable_force_ntls(&mut self) {
882 unsafe { ffi::SSL_CTX_enable_force_ntls(self.as_ptr()) }
883 }
884
885 #[cfg(all(tongsuo, ossl300))]
886 #[corresponds(SSL_CTX_disable_force_ntls)]
887 pub fn disable_force_ntls(&mut self) {
888 unsafe { ffi::SSL_CTX_disable_force_ntls(self.as_ptr()) }
889 }
890
891 #[cfg(tongsuo)]
892 #[corresponds(SSL_CTX_enable_sm_tls13_strict)]
893 pub fn enable_sm_tls13_strict(&mut self) {
894 unsafe { ffi::SSL_CTX_enable_sm_tls13_strict(self.as_ptr()) }
895 }
896
897 #[cfg(tongsuo)]
898 #[corresponds(SSL_CTX_disable_sm_tls13_strict)]
899 pub fn disable_sm_tls13_strict(&mut self) {
900 unsafe { ffi::SSL_CTX_disable_sm_tls13_strict(self.as_ptr()) }
901 }
902
903 #[corresponds(SSL_CTX_set_verify)]
905 pub fn set_verify(&mut self, mode: SslVerifyMode) {
906 unsafe {
907 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
908 }
909 }
910
911 #[corresponds(SSL_CTX_set_verify)]
918 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
919 where
920 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
921 {
922 unsafe {
923 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
924 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
925 }
926 }
927
928 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
936 pub fn set_servername_callback<F>(&mut self, callback: F)
938 where
939 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
940 {
941 unsafe {
942 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
948 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
949 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
950 }
951 }
952
953 #[corresponds(SSL_CTX_set_verify_depth)]
957 pub fn set_verify_depth(&mut self, depth: u32) {
958 unsafe {
959 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
960 }
961 }
962
963 #[corresponds(SSL_CTX_set0_verify_cert_store)]
967 #[cfg(any(ossl110, boringssl, awslc))]
968 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
969 unsafe {
970 let ptr = cert_store.as_ptr();
971 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
972 mem::forget(cert_store);
973
974 Ok(())
975 }
976 }
977
978 #[corresponds(SSL_CTX_set_cert_store)]
980 pub fn set_cert_store(&mut self, cert_store: X509Store) {
981 unsafe {
982 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
983 mem::forget(cert_store);
984 }
985 }
986
987 #[corresponds(SSL_CTX_set_read_ahead)]
994 pub fn set_read_ahead(&mut self, read_ahead: bool) {
995 unsafe {
996 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
997 }
998 }
999
1000 #[corresponds(SSL_CTX_set_mode)]
1004 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
1005 unsafe {
1006 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1007 SslMode::from_bits_retain(bits)
1008 }
1009 }
1010
1011 #[corresponds(SSL_CTX_clear_mode)]
1013 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
1014 unsafe {
1015 let bits = ffi::SSL_CTX_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
1016 SslMode::from_bits_retain(bits)
1017 }
1018 }
1019
1020 #[corresponds(SSL_CTX_get_mode)]
1022 pub fn mode(&self) -> SslMode {
1023 unsafe {
1024 let bits = ffi::SSL_CTX_get_mode(self.as_ptr()) as SslBitType;
1025 SslMode::from_bits_retain(bits)
1026 }
1027 }
1028
1029 #[corresponds(SSL_CTX_set_dh_auto)]
1038 #[cfg(ossl300)]
1039 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1040 unsafe { cvt(ffi::SSL_CTX_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
1041 }
1042
1043 #[corresponds(SSL_CTX_set_tmp_dh)]
1045 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
1046 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1047 }
1048
1049 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
1056 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
1057 where
1058 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
1059 {
1060 unsafe {
1061 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1062
1063 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
1064 }
1065 }
1066
1067 #[corresponds(SSL_CTX_set_tmp_ecdh)]
1069 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
1070 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1071 }
1072
1073 #[corresponds(SSL_CTX_set_default_verify_paths)]
1078 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
1079 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
1080 }
1081
1082 #[corresponds(SSL_CTX_load_verify_locations)]
1086 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
1087 self.load_verify_locations(Some(file.as_ref()), None)
1088 }
1089
1090 #[corresponds(SSL_CTX_load_verify_locations)]
1092 pub fn load_verify_locations(
1093 &mut self,
1094 ca_file: Option<&Path>,
1095 ca_path: Option<&Path>,
1096 ) -> Result<(), ErrorStack> {
1097 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1098 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
1099 unsafe {
1100 cvt(ffi::SSL_CTX_load_verify_locations(
1101 self.as_ptr(),
1102 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1103 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
1104 ))
1105 .map(|_| ())
1106 }
1107 }
1108
1109 #[corresponds(SSL_CTX_set_client_CA_list)]
1114 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
1115 unsafe {
1116 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
1117 mem::forget(list);
1118 }
1119 }
1120
1121 #[corresponds(SSL_CTX_add_client_CA)]
1124 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
1125 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
1126 }
1127
1128 #[corresponds(SSL_CTX_set_session_id_context)]
1137 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
1138 unsafe {
1139 assert!(sid_ctx.len() <= c_uint::MAX as usize);
1140 cvt(ffi::SSL_CTX_set_session_id_context(
1141 self.as_ptr(),
1142 sid_ctx.as_ptr(),
1143 sid_ctx.len() as SizeTy,
1144 ))
1145 .map(|_| ())
1146 }
1147 }
1148
1149 #[corresponds(SSL_CTX_use_certificate_file)]
1155 pub fn set_certificate_file<P: AsRef<Path>>(
1156 &mut self,
1157 file: P,
1158 file_type: SslFiletype,
1159 ) -> Result<(), ErrorStack> {
1160 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1161 unsafe {
1162 cvt(ffi::SSL_CTX_use_certificate_file(
1163 self.as_ptr(),
1164 file.as_ptr() as *const _,
1165 file_type.as_raw(),
1166 ))
1167 .map(|_| ())
1168 }
1169 }
1170
1171 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1177 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1178 &mut self,
1179 file: P,
1180 ) -> Result<(), ErrorStack> {
1181 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1182 unsafe {
1183 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1184 self.as_ptr(),
1185 file.as_ptr() as *const _,
1186 ))
1187 .map(|_| ())
1188 }
1189 }
1190
1191 #[corresponds(SSL_CTX_use_certificate)]
1195 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1196 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1197 }
1198
1199 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1204 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1205 unsafe {
1206 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1207 mem::forget(cert);
1208 Ok(())
1209 }
1210 }
1211
1212 #[cfg(tongsuo)]
1213 #[corresponds(SSL_CTX_use_enc_certificate_file)]
1214 pub fn set_enc_certificate_file<P: AsRef<Path>>(
1215 &mut self,
1216 file: P,
1217 file_type: SslFiletype,
1218 ) -> Result<(), ErrorStack> {
1219 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1220 unsafe {
1221 cvt(ffi::SSL_CTX_use_enc_certificate_file(
1222 self.as_ptr(),
1223 file.as_ptr() as *const _,
1224 file_type.as_raw(),
1225 ))
1226 .map(|_| ())
1227 }
1228 }
1229
1230 #[cfg(tongsuo)]
1231 #[corresponds(SSL_CTX_use_enc_certificate)]
1232 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1233 unsafe {
1234 cvt(ffi::SSL_CTX_use_enc_certificate(
1235 self.as_ptr(),
1236 cert.as_ptr(),
1237 ))
1238 .map(|_| ())
1239 }
1240 }
1241
1242 #[cfg(tongsuo)]
1243 #[corresponds(SSL_CTX_use_sign_certificate_file)]
1244 pub fn set_sign_certificate_file<P: AsRef<Path>>(
1245 &mut self,
1246 file: P,
1247 file_type: SslFiletype,
1248 ) -> Result<(), ErrorStack> {
1249 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1250 unsafe {
1251 cvt(ffi::SSL_CTX_use_sign_certificate_file(
1252 self.as_ptr(),
1253 file.as_ptr() as *const _,
1254 file_type.as_raw(),
1255 ))
1256 .map(|_| ())
1257 }
1258 }
1259
1260 #[cfg(tongsuo)]
1261 #[corresponds(SSL_CTX_use_sign_certificate)]
1262 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1263 unsafe {
1264 cvt(ffi::SSL_CTX_use_sign_certificate(
1265 self.as_ptr(),
1266 cert.as_ptr(),
1267 ))
1268 .map(|_| ())
1269 }
1270 }
1271
1272 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1274 pub fn set_private_key_file<P: AsRef<Path>>(
1275 &mut self,
1276 file: P,
1277 file_type: SslFiletype,
1278 ) -> Result<(), ErrorStack> {
1279 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1280 unsafe {
1281 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1282 self.as_ptr(),
1283 file.as_ptr() as *const _,
1284 file_type.as_raw(),
1285 ))
1286 .map(|_| ())
1287 }
1288 }
1289
1290 #[corresponds(SSL_CTX_use_PrivateKey)]
1292 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1293 where
1294 T: HasPrivate,
1295 {
1296 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1297 }
1298
1299 #[cfg(tongsuo)]
1300 #[corresponds(SSL_CTX_use_enc_PrivateKey_file)]
1301 pub fn set_enc_private_key_file<P: AsRef<Path>>(
1302 &mut self,
1303 file: P,
1304 file_type: SslFiletype,
1305 ) -> Result<(), ErrorStack> {
1306 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1307 unsafe {
1308 cvt(ffi::SSL_CTX_use_enc_PrivateKey_file(
1309 self.as_ptr(),
1310 file.as_ptr() as *const _,
1311 file_type.as_raw(),
1312 ))
1313 .map(|_| ())
1314 }
1315 }
1316
1317 #[cfg(tongsuo)]
1318 #[corresponds(SSL_CTX_use_enc_PrivateKey)]
1319 pub fn set_enc_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1320 where
1321 T: HasPrivate,
1322 {
1323 unsafe { cvt(ffi::SSL_CTX_use_enc_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1324 }
1325
1326 #[cfg(tongsuo)]
1327 #[corresponds(SSL_CTX_use_sign_PrivateKey_file)]
1328 pub fn set_sign_private_key_file<P: AsRef<Path>>(
1329 &mut self,
1330 file: P,
1331 file_type: SslFiletype,
1332 ) -> Result<(), ErrorStack> {
1333 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1334 unsafe {
1335 cvt(ffi::SSL_CTX_use_sign_PrivateKey_file(
1336 self.as_ptr(),
1337 file.as_ptr() as *const _,
1338 file_type.as_raw(),
1339 ))
1340 .map(|_| ())
1341 }
1342 }
1343
1344 #[cfg(tongsuo)]
1345 #[corresponds(SSL_CTX_use_sign_PrivateKey)]
1346 pub fn set_sign_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1347 where
1348 T: HasPrivate,
1349 {
1350 unsafe {
1351 cvt(ffi::SSL_CTX_use_sign_PrivateKey(
1352 self.as_ptr(),
1353 key.as_ptr(),
1354 ))
1355 .map(|_| ())
1356 }
1357 }
1358
1359 #[corresponds(SSL_CTX_set_cipher_list)]
1367 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1368 let cipher_list = CString::new(cipher_list).unwrap();
1369 unsafe {
1370 cvt(ffi::SSL_CTX_set_cipher_list(
1371 self.as_ptr(),
1372 cipher_list.as_ptr() as *const _,
1373 ))
1374 .map(|_| ())
1375 }
1376 }
1377
1378 #[corresponds(SSL_CTX_set_ciphersuites)]
1387 #[cfg(any(ossl111, libressl, awslc))]
1388 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1389 let cipher_list = CString::new(cipher_list).unwrap();
1390 unsafe {
1391 cvt(ffi::SSL_CTX_set_ciphersuites(
1392 self.as_ptr(),
1393 cipher_list.as_ptr() as *const _,
1394 ))
1395 .map(|_| ())
1396 }
1397 }
1398
1399 #[corresponds(SSL_CTX_set_ecdh_auto)]
1403 #[cfg(libressl)]
1404 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1405 unsafe {
1406 cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ())
1407 }
1408 }
1409
1410 #[corresponds(SSL_CTX_set_options)]
1417 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1418 let bits =
1419 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1420 SslOptions::from_bits_retain(bits)
1421 }
1422
1423 #[corresponds(SSL_CTX_get_options)]
1425 pub fn options(&self) -> SslOptions {
1426 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1427 SslOptions::from_bits_retain(bits)
1428 }
1429
1430 #[corresponds(SSL_CTX_clear_options)]
1432 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1433 let bits =
1434 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1435 SslOptions::from_bits_retain(bits)
1436 }
1437
1438 #[corresponds(SSL_CTX_set_min_proto_version)]
1443 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1444 unsafe {
1445 cvt(ffi::SSL_CTX_set_min_proto_version(
1446 self.as_ptr(),
1447 version.map_or(0, |v| v.0 as _),
1448 ))
1449 .map(|_| ())
1450 }
1451 }
1452
1453 #[corresponds(SSL_CTX_set_max_proto_version)]
1458 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1459 unsafe {
1460 cvt(ffi::SSL_CTX_set_max_proto_version(
1461 self.as_ptr(),
1462 version.map_or(0, |v| v.0 as _),
1463 ))
1464 .map(|_| ())
1465 }
1466 }
1467
1468 #[corresponds(SSL_CTX_get_min_proto_version)]
1475 #[cfg(any(ossl110g, libressl))]
1476 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1477 unsafe {
1478 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1479 if r == 0 {
1480 None
1481 } else {
1482 Some(SslVersion(r))
1483 }
1484 }
1485 }
1486
1487 #[corresponds(SSL_CTX_get_max_proto_version)]
1494 #[cfg(any(ossl110g, libressl))]
1495 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1496 unsafe {
1497 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1498 if r == 0 {
1499 None
1500 } else {
1501 Some(SslVersion(r))
1502 }
1503 }
1504 }
1505
1506 #[corresponds(SSL_CTX_set_alpn_protos)]
1515 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1516 unsafe {
1517 assert!(protocols.len() <= c_uint::MAX as usize);
1518 let r = ffi::SSL_CTX_set_alpn_protos(
1519 self.as_ptr(),
1520 protocols.as_ptr(),
1521 protocols.len() as _,
1522 );
1523 if r == 0 {
1525 Ok(())
1526 } else {
1527 Err(ErrorStack::get())
1528 }
1529 }
1530 }
1531
1532 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1534 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1535 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1536 unsafe {
1537 let cstr = CString::new(protocols).unwrap();
1538
1539 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1540 if r == 0 {
1542 Ok(())
1543 } else {
1544 Err(ErrorStack::get())
1545 }
1546 }
1547 }
1548
1549 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1560 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1561 where
1562 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1563 {
1564 unsafe {
1565 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1566 ffi::SSL_CTX_set_alpn_select_cb(
1567 self.as_ptr(),
1568 Some(callbacks::raw_alpn_select::<F>),
1569 ptr::null_mut(),
1570 );
1571 }
1572 }
1573
1574 #[corresponds(SSL_CTX_check_private_key)]
1576 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1577 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1578 }
1579
1580 #[corresponds(SSL_CTX_get_cert_store)]
1582 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1583 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1584 }
1585
1586 #[corresponds(SSL_CTX_get_cert_store)]
1588 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1589 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1590 }
1591
1592 #[corresponds(SSL_CTX_get0_param)]
1596 pub fn verify_param(&self) -> &X509VerifyParamRef {
1597 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1598 }
1599
1600 #[corresponds(SSL_CTX_get0_param)]
1604 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1605 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1606 }
1607
1608 #[cfg(any(boringssl, tongsuo, awslc))]
1616 pub fn add_cert_decompression_alg<F>(
1617 &mut self,
1618 alg_id: CertCompressionAlgorithm,
1619 decompress: F,
1620 ) -> Result<(), ErrorStack>
1621 where
1622 F: Fn(&[u8], &mut [u8]) -> usize + Send + Sync + 'static,
1623 {
1624 unsafe {
1625 self.set_ex_data(SslContext::cached_ex_index::<F>(), decompress);
1626 cvt(ffi::SSL_CTX_add_cert_compression_alg(
1627 self.as_ptr(),
1628 alg_id.0 as _,
1629 None,
1630 Some(raw_cert_decompression::<F>),
1631 ))
1632 .map(|_| ())
1633 }
1634 }
1635
1636 #[corresponds(SSL_CTX_set1_cert_comp_preference)]
1638 #[cfg(ossl320)]
1639 pub fn set_cert_comp_preference(
1640 &mut self,
1641 algs: &[CertCompressionAlgorithm],
1642 ) -> Result<(), ErrorStack> {
1643 let mut algs = algs.iter().map(|v| v.0).collect::<Vec<c_int>>();
1644 unsafe {
1645 cvt(ffi::SSL_CTX_set1_cert_comp_preference(
1646 self.as_ptr(),
1647 algs.as_mut_ptr(),
1648 algs.len(),
1649 ))
1650 .map(|_| ())
1651 }
1652 }
1653
1654 #[cfg(any(boringssl, awslc))]
1662 pub fn enable_ocsp_stapling(&mut self) {
1663 unsafe { ffi::SSL_CTX_enable_ocsp_stapling(self.as_ptr()) }
1664 }
1665
1666 #[cfg(any(boringssl, awslc))]
1674 pub fn enable_signed_cert_timestamps(&mut self) {
1675 unsafe { ffi::SSL_CTX_enable_signed_cert_timestamps(self.as_ptr()) }
1676 }
1677
1678 #[cfg(any(boringssl, awslc))]
1686 pub fn set_grease_enabled(&mut self, enabled: bool) {
1687 unsafe { ffi::SSL_CTX_set_grease_enabled(self.as_ptr(), enabled as c_int) }
1688 }
1689
1690 #[cfg(any(boringssl, awslc))]
1698 pub fn set_permute_extensions(&mut self, enabled: bool) {
1699 unsafe { ffi::SSL_CTX_set_permute_extensions(self.as_ptr(), enabled as c_int) }
1700 }
1701
1702 #[corresponds(SSL_CTX_enable_ct)]
1704 #[cfg(ossl111)]
1705 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
1706 unsafe { cvt(ffi::SSL_CTX_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
1707 }
1708
1709 #[corresponds(SSL_CTX_ct_is_enabled)]
1711 #[cfg(ossl111)]
1712 pub fn ct_is_enabled(&self) -> bool {
1713 unsafe { ffi::SSL_CTX_ct_is_enabled(self.as_ptr()) == 1 }
1714 }
1715
1716 #[corresponds(SSL_CTX_set_tlsext_status_type)]
1718 #[cfg(not(any(boringssl, awslc)))]
1719 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
1720 unsafe {
1721 cvt(ffi::SSL_CTX_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int)
1722 .map(|_| ())
1723 }
1724 }
1725
1726 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1739 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1740 where
1741 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1742 {
1743 unsafe {
1744 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1745 cvt(
1746 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1747 as c_int,
1748 )
1749 .map(|_| ())
1750 }
1751 }
1752
1753 #[corresponds(SSL_CTX_set_tlsext_ticket_key_evp_cb)]
1754 #[cfg(ossl300)]
1755 pub fn set_ticket_key_evp_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1756 where
1757 F: Fn(
1758 &mut SslRef,
1759 &mut [u8],
1760 &mut [u8],
1761 &mut CipherCtxRef,
1762 &mut MacCtxRef,
1763 bool,
1764 ) -> Result<TicketKeyStatus, ErrorStack>
1765 + 'static
1766 + Sync
1767 + Send,
1768 {
1769 unsafe {
1770 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1771 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_evp_cb(
1772 self.as_ptr(),
1773 Some(raw_tlsext_ticket_key_evp::<F>),
1774 ) as c_int)
1775 .map(|_| ())
1776 }
1777 }
1778
1779 #[corresponds(SSL_CTX_set_tlsext_ticket_key_cb)]
1780 pub fn set_ticket_key_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1781 where
1782 F: Fn(
1783 &mut SslRef,
1784 &mut [u8],
1785 &mut [u8],
1786 &mut CipherCtxRef,
1787 &mut HMacCtxRef,
1788 bool,
1789 ) -> Result<TicketKeyStatus, ErrorStack>
1790 + 'static
1791 + Sync
1792 + Send,
1793 {
1794 unsafe {
1795 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1796 cvt(ffi::SSL_CTX_set_tlsext_ticket_key_cb(
1797 self.as_ptr(),
1798 Some(raw_tlsext_ticket_key::<F>),
1799 ) as c_int)
1800 .map(|_| ())
1801 }
1802 }
1803
1804 #[corresponds(SSL_CTX_set_psk_client_callback)]
1810 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1811 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1812 where
1813 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1814 + 'static
1815 + Sync
1816 + Send,
1817 {
1818 unsafe {
1819 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1820 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1821 }
1822 }
1823
1824 #[corresponds(SSL_CTX_set_psk_server_callback)]
1830 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1831 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1832 where
1833 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1834 + 'static
1835 + Sync
1836 + Send,
1837 {
1838 unsafe {
1839 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1840 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1841 }
1842 }
1843
1844 #[corresponds(SSL_CTX_sess_set_new_cb)]
1858 pub fn set_new_session_callback<F>(&mut self, callback: F)
1859 where
1860 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1861 {
1862 unsafe {
1863 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1864 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1865 }
1866 }
1867
1868 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1872 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1873 where
1874 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1875 {
1876 unsafe {
1877 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1878 ffi::SSL_CTX_sess_set_remove_cb(
1879 self.as_ptr(),
1880 Some(callbacks::raw_remove_session::<F>),
1881 );
1882 }
1883 }
1884
1885 #[corresponds(SSL_CTX_sess_set_get_cb)]
1896 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1897 where
1898 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1899 {
1900 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1901 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1902 }
1903
1904 #[corresponds(SSL_CTX_set_keylog_callback)]
1912 #[cfg(any(ossl111, boringssl, awslc))]
1913 pub fn set_keylog_callback<F>(&mut self, callback: F)
1914 where
1915 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1916 {
1917 unsafe {
1918 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1919 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1920 }
1921 }
1922
1923 #[corresponds(SSL_CTX_set_session_cache_mode)]
1927 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1928 unsafe {
1929 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1930 SslSessionCacheMode::from_bits_retain(bits)
1931 }
1932 }
1933
1934 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1940 #[cfg(ossl111)]
1941 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1942 where
1943 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1944 {
1945 unsafe {
1946 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1947 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1948 self.as_ptr(),
1949 Some(raw_stateless_cookie_generate::<F>),
1950 );
1951 }
1952 }
1953
1954 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1963 #[cfg(ossl111)]
1964 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1965 where
1966 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1967 {
1968 unsafe {
1969 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1970 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1971 self.as_ptr(),
1972 Some(raw_stateless_cookie_verify::<F>),
1973 )
1974 }
1975 }
1976
1977 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1982 #[cfg(not(any(boringssl, awslc)))]
1983 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1984 where
1985 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1986 {
1987 unsafe {
1988 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1989 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1990 }
1991 }
1992
1993 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1998 #[cfg(not(any(boringssl, awslc)))]
1999 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
2000 where
2001 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
2002 {
2003 unsafe {
2004 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2005 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
2006 }
2007 }
2008
2009 #[corresponds(SSL_CTX_set_ex_data)]
2015 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
2016 self.set_ex_data_inner(index, data);
2017 }
2018
2019 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
2020 match self.ex_data_mut(index) {
2021 Some(v) => {
2022 *v = data;
2023 (v as *mut T).cast()
2024 }
2025 _ => unsafe {
2026 let data = Box::into_raw(Box::new(data)) as *mut c_void;
2027 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
2028 data
2029 },
2030 }
2031 }
2032
2033 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
2034 unsafe {
2035 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2036 if data.is_null() {
2037 None
2038 } else {
2039 Some(&mut *data.cast())
2040 }
2041 }
2042 }
2043
2044 #[corresponds(SSL_CTX_add_custom_ext)]
2048 #[cfg(ossl111)]
2049 pub fn add_custom_ext<AddFn, ParseFn, T>(
2050 &mut self,
2051 ext_type: u16,
2052 context: ExtensionContext,
2053 add_cb: AddFn,
2054 parse_cb: ParseFn,
2055 ) -> Result<(), ErrorStack>
2056 where
2057 AddFn: Fn(
2058 &mut SslRef,
2059 ExtensionContext,
2060 Option<(usize, &X509Ref)>,
2061 ) -> Result<Option<T>, SslAlert>
2062 + 'static
2063 + Sync
2064 + Send,
2065 T: AsRef<[u8]> + 'static + Sync + Send,
2066 ParseFn: Fn(
2067 &mut SslRef,
2068 ExtensionContext,
2069 &[u8],
2070 Option<(usize, &X509Ref)>,
2071 ) -> Result<(), SslAlert>
2072 + 'static
2073 + Sync
2074 + Send,
2075 {
2076 let ret = unsafe {
2077 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
2078 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
2079
2080 ffi::SSL_CTX_add_custom_ext(
2081 self.as_ptr(),
2082 ext_type as c_uint,
2083 context.bits(),
2084 Some(raw_custom_ext_add::<AddFn, T>),
2085 Some(raw_custom_ext_free::<T>),
2086 ptr::null_mut(),
2087 Some(raw_custom_ext_parse::<ParseFn>),
2088 ptr::null_mut(),
2089 )
2090 };
2091 if ret == 1 {
2092 Ok(())
2093 } else {
2094 Err(ErrorStack::get())
2095 }
2096 }
2097
2098 #[corresponds(SSL_CTX_set_max_early_data)]
2104 #[cfg(any(ossl111, libressl))]
2105 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2106 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2107 Ok(())
2108 } else {
2109 Err(ErrorStack::get())
2110 }
2111 }
2112
2113 #[cfg(any(boringssl, awslc))]
2123 pub fn set_select_certificate_callback<F>(&mut self, callback: F)
2124 where
2125 F: Fn(ClientHello<'_>) -> Result<(), SelectCertError> + Sync + Send + 'static,
2126 {
2127 unsafe {
2128 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
2129 ffi::SSL_CTX_set_select_certificate_cb(
2130 self.as_ptr(),
2131 Some(callbacks::raw_select_cert::<F>),
2132 );
2133 }
2134 }
2135
2136 #[corresponds(SSL_CTX_set_client_hello_cb)]
2140 #[cfg(any(ossl111, all(awslc, not(awslc_fips))))]
2141 pub fn set_client_hello_callback<F>(&mut self, callback: F)
2142 where
2143 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), ClientHelloError> + 'static + Sync + Send,
2144 {
2145 unsafe {
2146 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2147 ffi::SSL_CTX_set_client_hello_cb(
2148 self.as_ptr(),
2149 Some(callbacks::raw_client_hello::<F>),
2150 ptr,
2151 );
2152 }
2153 }
2154
2155 #[corresponds(SSL_CTX_set_info_callback)]
2158 pub fn set_info_callback<F>(&mut self, callback: F)
2159 where
2160 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2161 {
2162 unsafe {
2163 self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
2164 ffi::SSL_CTX_set_info_callback(self.as_ptr(), Some(callbacks::raw_info::<F>));
2165 }
2166 }
2167
2168 #[corresponds(SSL_CTX_sess_set_cache_size)]
2172 #[allow(clippy::useless_conversion)]
2173 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
2174 unsafe {
2175 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
2176 }
2177 }
2178
2179 #[corresponds(SSL_CTX_set1_sigalgs_list)]
2183 #[cfg(ossl110)]
2184 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
2185 let sigalgs = CString::new(sigalgs).unwrap();
2186 unsafe {
2187 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
2188 .map(|_| ())
2189 }
2190 }
2191
2192 #[corresponds(SSL_CTX_set1_groups_list)]
2196 #[cfg(any(ossl111, boringssl, libressl, awslc))]
2197 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
2198 let groups = CString::new(groups).unwrap();
2199 unsafe {
2200 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
2201 }
2202 }
2203
2204 #[corresponds(SSL_CTX_set_num_tickets)]
2209 #[cfg(any(ossl111, boringssl, awslc))]
2210 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
2211 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
2212 }
2213
2214 #[corresponds(SSL_CTX_set_security_level)]
2219 #[cfg(any(ossl110, libressl360))]
2220 pub fn set_security_level(&mut self, level: u32) {
2221 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
2222 }
2223
2224 pub fn build(self) -> SslContext {
2226 self.0
2227 }
2228}
2229
2230foreign_type_and_impl_send_sync! {
2231 type CType = ffi::SSL_CTX;
2232 fn drop = ffi::SSL_CTX_free;
2233
2234 pub struct SslContext;
2239
2240 pub struct SslContextRef;
2244}
2245
2246impl Clone for SslContext {
2247 fn clone(&self) -> Self {
2248 (**self).to_owned()
2249 }
2250}
2251
2252impl ToOwned for SslContextRef {
2253 type Owned = SslContext;
2254
2255 fn to_owned(&self) -> Self::Owned {
2256 unsafe {
2257 SSL_CTX_up_ref(self.as_ptr());
2258 SslContext::from_ptr(self.as_ptr())
2259 }
2260 }
2261}
2262
2263impl fmt::Debug for SslContext {
2265 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2266 write!(fmt, "SslContext")
2267 }
2268}
2269
2270impl SslContext {
2271 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
2273 SslContextBuilder::new(method)
2274 }
2275
2276 #[corresponds(SSL_CTX_get_ex_new_index)]
2281 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
2282 where
2283 T: 'static + Sync + Send,
2284 {
2285 unsafe {
2286 ffi::init();
2287 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
2288 Ok(Index::from_raw(idx))
2289 }
2290 }
2291
2292 fn cached_ex_index<T>() -> Index<SslContext, T>
2294 where
2295 T: 'static + Sync + Send,
2296 {
2297 unsafe {
2298 let idx = *INDEXES
2299 .lock()
2300 .unwrap_or_else(|e| e.into_inner())
2301 .entry(TypeId::of::<T>())
2302 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
2303 Index::from_raw(idx)
2304 }
2305 }
2306}
2307
2308impl SslContextRef {
2309 #[corresponds(SSL_CTX_get0_certificate)]
2313 #[cfg(any(ossl110, libressl))]
2314 pub fn certificate(&self) -> Option<&X509Ref> {
2315 unsafe {
2316 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
2317 X509Ref::from_const_ptr_opt(ptr)
2318 }
2319 }
2320
2321 #[corresponds(SSL_CTX_get0_privatekey)]
2325 #[cfg(any(ossl110, libressl))]
2326 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2327 unsafe {
2328 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
2329 PKeyRef::from_const_ptr_opt(ptr)
2330 }
2331 }
2332
2333 #[corresponds(SSL_CTX_get_cert_store)]
2335 pub fn cert_store(&self) -> &X509StoreRef {
2336 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
2337 }
2338
2339 #[corresponds(SSL_CTX_get_extra_chain_certs)]
2341 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
2342 unsafe {
2343 let mut chain = ptr::null_mut();
2344 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
2345 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
2346 }
2347 }
2348
2349 #[corresponds(SSL_CTX_get_ex_data)]
2351 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
2352 unsafe {
2353 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
2354 if data.is_null() {
2355 None
2356 } else {
2357 Some(&*(data as *const T))
2358 }
2359 }
2360 }
2361
2362 #[corresponds(SSL_CTX_get_max_early_data)]
2366 #[cfg(any(ossl111, libressl))]
2367 pub fn max_early_data(&self) -> u32 {
2368 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
2369 }
2370
2371 #[corresponds(SSL_CTX_add_session)]
2380 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
2381 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
2382 }
2383
2384 #[corresponds(SSL_CTX_remove_session)]
2393 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
2394 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
2395 }
2396
2397 #[corresponds(SSL_CTX_sess_get_cache_size)]
2401 #[allow(clippy::unnecessary_cast)]
2402 pub fn session_cache_size(&self) -> i64 {
2403 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
2404 }
2405
2406 #[corresponds(SSL_CTX_get_verify_mode)]
2410 pub fn verify_mode(&self) -> SslVerifyMode {
2411 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
2412 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
2413 }
2414
2415 #[corresponds(SSL_CTX_get_num_tickets)]
2420 #[cfg(ossl111)]
2421 pub fn num_tickets(&self) -> usize {
2422 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
2423 }
2424
2425 #[corresponds(SSL_CTX_get_security_level)]
2430 #[cfg(any(ossl110, libressl360))]
2431 pub fn security_level(&self) -> u32 {
2432 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
2433 }
2434}
2435
2436pub struct CipherBits {
2438 pub secret: i32,
2440
2441 pub algorithm: i32,
2443}
2444
2445pub struct SslCipher(*mut ffi::SSL_CIPHER);
2447
2448impl ForeignType for SslCipher {
2449 type CType = ffi::SSL_CIPHER;
2450 type Ref = SslCipherRef;
2451
2452 #[inline]
2453 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2454 SslCipher(ptr)
2455 }
2456
2457 #[inline]
2458 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2459 self.0
2460 }
2461}
2462
2463impl Stackable for SslCipher {
2464 type StackType = ffi::stack_st_SSL_CIPHER;
2465}
2466
2467impl Deref for SslCipher {
2468 type Target = SslCipherRef;
2469
2470 fn deref(&self) -> &SslCipherRef {
2471 unsafe { SslCipherRef::from_ptr(self.0) }
2472 }
2473}
2474
2475impl DerefMut for SslCipher {
2476 fn deref_mut(&mut self) -> &mut SslCipherRef {
2477 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2478 }
2479}
2480
2481pub struct SslCipherRef(Opaque);
2485
2486impl ForeignTypeRef for SslCipherRef {
2487 type CType = ffi::SSL_CIPHER;
2488}
2489
2490impl SslCipherRef {
2491 #[corresponds(SSL_CIPHER_get_name)]
2493 pub fn name(&self) -> &'static str {
2494 unsafe {
2495 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2496 CStr::from_ptr(ptr).to_str().unwrap()
2497 }
2498 }
2499
2500 #[corresponds(SSL_CIPHER_standard_name)]
2504 #[cfg(ossl111)]
2505 pub fn standard_name(&self) -> Option<&'static str> {
2506 unsafe {
2507 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2508 if ptr.is_null() {
2509 None
2510 } else {
2511 Some(CStr::from_ptr(ptr).to_str().unwrap())
2512 }
2513 }
2514 }
2515
2516 #[corresponds(SSL_CIPHER_get_version)]
2518 pub fn version(&self) -> &'static str {
2519 let version = unsafe {
2520 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2521 CStr::from_ptr(ptr as *const _)
2522 };
2523
2524 str::from_utf8(version.to_bytes()).unwrap()
2525 }
2526
2527 #[corresponds(SSL_CIPHER_get_bits)]
2529 #[allow(clippy::useless_conversion)]
2530 pub fn bits(&self) -> CipherBits {
2531 unsafe {
2532 let mut algo_bits = 0;
2533 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2534 CipherBits {
2535 secret: secret_bits.into(),
2536 algorithm: algo_bits.into(),
2537 }
2538 }
2539 }
2540
2541 #[corresponds(SSL_CIPHER_description)]
2543 pub fn description(&self) -> String {
2544 unsafe {
2545 let mut buf = [0; 128];
2547 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2548 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2549 }
2550 }
2551
2552 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2556 #[cfg(ossl111)]
2557 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2558 unsafe {
2559 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2560 if ptr.is_null() {
2561 None
2562 } else {
2563 Some(MessageDigest::from_ptr(ptr))
2564 }
2565 }
2566 }
2567
2568 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2572 #[cfg(any(ossl110, libressl))]
2573 pub fn cipher_nid(&self) -> Option<Nid> {
2574 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2575 if n == 0 {
2576 None
2577 } else {
2578 Some(Nid::from_raw(n))
2579 }
2580 }
2581
2582 #[corresponds(SSL_CIPHER_get_protocol_id)]
2586 #[cfg(ossl111)]
2587 pub fn protocol_id(&self) -> [u8; 2] {
2588 unsafe {
2589 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2590 id.to_be_bytes()
2591 }
2592 }
2593}
2594
2595impl fmt::Debug for SslCipherRef {
2596 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2597 write!(fmt, "{}", self.name())
2598 }
2599}
2600
2601#[derive(Debug)]
2603pub struct CipherLists {
2604 pub suites: Stack<SslCipher>,
2605 pub signalling_suites: Stack<SslCipher>,
2606}
2607
2608foreign_type_and_impl_send_sync! {
2609 type CType = ffi::SSL_SESSION;
2610 fn drop = ffi::SSL_SESSION_free;
2611
2612 pub struct SslSession;
2616
2617 pub struct SslSessionRef;
2621}
2622
2623impl Clone for SslSession {
2624 fn clone(&self) -> SslSession {
2625 SslSessionRef::to_owned(self)
2626 }
2627}
2628
2629impl SslSession {
2630 from_der! {
2631 #[corresponds(d2i_SSL_SESSION)]
2633 from_der,
2634 SslSession,
2635 ffi::d2i_SSL_SESSION
2636 }
2637}
2638
2639impl ToOwned for SslSessionRef {
2640 type Owned = SslSession;
2641
2642 fn to_owned(&self) -> SslSession {
2643 unsafe {
2644 SSL_SESSION_up_ref(self.as_ptr());
2645 SslSession(self.as_ptr())
2646 }
2647 }
2648}
2649
2650impl SslSessionRef {
2651 #[corresponds(SSL_SESSION_get_id)]
2653 pub fn id(&self) -> &[u8] {
2654 unsafe {
2655 let mut len = 0;
2656 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2657 #[allow(clippy::unnecessary_cast)]
2658 util::from_raw_parts(p as *const u8, len as usize)
2659 }
2660 }
2661
2662 #[corresponds(SSL_SESSION_get_master_key)]
2664 pub fn master_key_len(&self) -> usize {
2665 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2666 }
2667
2668 #[corresponds(SSL_SESSION_get_master_key)]
2672 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2673 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2674 }
2675
2676 #[corresponds(SSL_SESSION_get_max_early_data)]
2680 #[cfg(any(ossl111, libressl))]
2681 pub fn max_early_data(&self) -> u32 {
2682 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2683 }
2684
2685 #[corresponds(SSL_SESSION_get_time)]
2687 #[allow(clippy::useless_conversion)]
2688 pub fn time(&self) -> SslTimeTy {
2689 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2690 }
2691
2692 #[corresponds(SSL_SESSION_get_timeout)]
2696 #[allow(clippy::useless_conversion)]
2697 pub fn timeout(&self) -> i64 {
2698 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2699 }
2700
2701 #[corresponds(SSL_SESSION_get_protocol_version)]
2705 #[cfg(any(ossl110, libressl))]
2706 pub fn protocol_version(&self) -> SslVersion {
2707 unsafe {
2708 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2709 SslVersion(version)
2710 }
2711 }
2712
2713 #[corresponds(SSL_SESSION_get_protocol_version)]
2715 #[cfg(any(boringssl, awslc))]
2716 pub fn protocol_version(&self) -> SslVersion {
2717 unsafe {
2718 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2719 SslVersion(version as _)
2720 }
2721 }
2722
2723 to_der! {
2724 #[corresponds(i2d_SSL_SESSION)]
2726 to_der,
2727 ffi::i2d_SSL_SESSION
2728 }
2729}
2730
2731foreign_type_and_impl_send_sync! {
2732 type CType = ffi::SSL;
2733 fn drop = ffi::SSL_free;
2734
2735 pub struct Ssl;
2742
2743 pub struct SslRef;
2747}
2748
2749impl fmt::Debug for Ssl {
2750 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2751 fmt::Debug::fmt(&**self, fmt)
2752 }
2753}
2754
2755impl Ssl {
2756 #[corresponds(SSL_get_ex_new_index)]
2761 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2762 where
2763 T: 'static + Sync + Send,
2764 {
2765 unsafe {
2766 ffi::init();
2767 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2768 Ok(Index::from_raw(idx))
2769 }
2770 }
2771
2772 fn cached_ex_index<T>() -> Index<Ssl, T>
2774 where
2775 T: 'static + Sync + Send,
2776 {
2777 unsafe {
2778 let idx = *SSL_INDEXES
2779 .lock()
2780 .unwrap_or_else(|e| e.into_inner())
2781 .entry(TypeId::of::<T>())
2782 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2783 Index::from_raw(idx)
2784 }
2785 }
2786
2787 #[corresponds(SSL_new)]
2789 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2790 let session_ctx_index = try_get_session_ctx_index()?;
2791 unsafe {
2792 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2793 let mut ssl = Ssl::from_ptr(ptr);
2794 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2795
2796 Ok(ssl)
2797 }
2798 }
2799
2800 #[corresponds(SSL_connect)]
2806 #[allow(deprecated)]
2807 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2808 where
2809 S: Read + Write,
2810 {
2811 SslStreamBuilder::new(self, stream).connect()
2812 }
2813
2814 #[corresponds(SSL_accept)]
2821 #[allow(deprecated)]
2822 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2823 where
2824 S: Read + Write,
2825 {
2826 SslStreamBuilder::new(self, stream).accept()
2827 }
2828}
2829
2830impl fmt::Debug for SslRef {
2831 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2832 fmt.debug_struct("Ssl")
2833 .field("state", &self.state_string_long())
2834 .field("verify_result", &self.verify_result())
2835 .finish()
2836 }
2837}
2838
2839impl SslRef {
2840 #[cfg(not(feature = "tongsuo"))]
2841 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2842 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2843 }
2844
2845 #[cfg(feature = "tongsuo")]
2846 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2847 unsafe {
2848 let bio = ffi::SSL_get_rbio(self.as_ptr());
2849 bio::find_correct_bio(bio)
2850 }
2851 }
2852
2853 fn get_error(&self, ret: c_int) -> ErrorCode {
2854 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2855 }
2856
2857 #[corresponds(SSL_set_mode)]
2861 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
2862 unsafe {
2863 let bits = ffi::SSL_set_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2864 SslMode::from_bits_retain(bits)
2865 }
2866 }
2867
2868 #[corresponds(SSL_clear_mode)]
2870 pub fn clear_mode(&mut self, mode: SslMode) -> SslMode {
2871 unsafe {
2872 let bits = ffi::SSL_clear_mode(self.as_ptr(), mode.bits() as ModeTy) as SslBitType;
2873 SslMode::from_bits_retain(bits)
2874 }
2875 }
2876
2877 #[corresponds(SSL_get_mode)]
2879 pub fn mode(&self) -> SslMode {
2880 unsafe {
2881 let bits = ffi::SSL_get_mode(self.as_ptr()) as SslBitType;
2882 SslMode::from_bits_retain(bits)
2883 }
2884 }
2885
2886 #[corresponds(SSL_set_connect_state)]
2888 pub fn set_connect_state(&mut self) {
2889 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2890 }
2891
2892 #[corresponds(SSL_set_accept_state)]
2894 pub fn set_accept_state(&mut self) {
2895 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2896 }
2897
2898 #[cfg(any(boringssl, awslc))]
2899 #[corresponds(SSL_ech_accepted)]
2900 pub fn ech_accepted(&self) -> bool {
2901 unsafe { ffi::SSL_ech_accepted(self.as_ptr()) != 0 }
2902 }
2903
2904 #[cfg(tongsuo)]
2905 #[corresponds(SSL_is_ntls)]
2906 pub fn is_ntls(&mut self) -> bool {
2907 unsafe { ffi::SSL_is_ntls(self.as_ptr()) != 0 }
2908 }
2909
2910 #[cfg(tongsuo)]
2911 #[corresponds(SSL_enable_ntls)]
2912 pub fn enable_ntls(&mut self) {
2913 unsafe { ffi::SSL_enable_ntls(self.as_ptr()) }
2914 }
2915
2916 #[cfg(tongsuo)]
2917 #[corresponds(SSL_disable_ntls)]
2918 pub fn disable_ntls(&mut self) {
2919 unsafe { ffi::SSL_disable_ntls(self.as_ptr()) }
2920 }
2921
2922 #[cfg(all(tongsuo, ossl300))]
2923 #[corresponds(SSL_enable_force_ntls)]
2924 pub fn enable_force_ntls(&mut self) {
2925 unsafe { ffi::SSL_enable_force_ntls(self.as_ptr()) }
2926 }
2927
2928 #[cfg(all(tongsuo, ossl300))]
2929 #[corresponds(SSL_disable_force_ntls)]
2930 pub fn disable_force_ntls(&mut self) {
2931 unsafe { ffi::SSL_disable_force_ntls(self.as_ptr()) }
2932 }
2933
2934 #[cfg(tongsuo)]
2935 #[corresponds(SSL_enable_sm_tls13_strict)]
2936 pub fn enable_sm_tls13_strict(&mut self) {
2937 unsafe { ffi::SSL_enable_sm_tls13_strict(self.as_ptr()) }
2938 }
2939
2940 #[cfg(tongsuo)]
2941 #[corresponds(SSL_disable_sm_tls13_strict)]
2942 pub fn disable_sm_tls13_strict(&mut self) {
2943 unsafe { ffi::SSL_disable_sm_tls13_strict(self.as_ptr()) }
2944 }
2945
2946 #[corresponds(SSL_set_verify)]
2950 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2951 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2952 }
2953
2954 #[corresponds(SSL_set_verify_mode)]
2956 pub fn verify_mode(&self) -> SslVerifyMode {
2957 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2958 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2959 }
2960
2961 #[corresponds(SSL_set_verify)]
2965 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2966 where
2967 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2968 {
2969 unsafe {
2970 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2972 ffi::SSL_set_verify(
2973 self.as_ptr(),
2974 mode.bits() as c_int,
2975 Some(ssl_raw_verify::<F>),
2976 );
2977 }
2978 }
2979
2980 #[corresponds(SSL_set_info_callback)]
2983 pub fn set_info_callback<F>(&mut self, callback: F)
2984 where
2985 F: Fn(&SslRef, i32, i32) + 'static + Sync + Send,
2986 {
2987 unsafe {
2988 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2990 ffi::SSL_set_info_callback(self.as_ptr(), Some(callbacks::ssl_raw_info::<F>));
2991 }
2992 }
2993
2994 #[corresponds(SSL_set_dh_auto)]
2998 #[cfg(ossl300)]
2999 pub fn set_dh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3000 unsafe { cvt(ffi::SSL_set_dh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3001 }
3002
3003 #[corresponds(SSL_set_tmp_dh)]
3007 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
3008 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
3009 }
3010
3011 #[corresponds(SSL_set_tmp_dh_callback)]
3015 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
3016 where
3017 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
3018 {
3019 unsafe {
3020 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
3022 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
3023 }
3024 }
3025
3026 #[corresponds(SSL_set_tmp_ecdh)]
3030 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
3031 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
3032 }
3033
3034 #[corresponds(SSL_set_ecdh_auto)]
3040 #[cfg(libressl)]
3041 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
3042 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int) as c_int).map(|_| ()) }
3043 }
3044
3045 #[corresponds(SSL_set_alpn_protos)]
3051 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
3052 unsafe {
3053 assert!(protocols.len() <= c_uint::MAX as usize);
3054 let r =
3055 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
3056 if r == 0 {
3058 Ok(())
3059 } else {
3060 Err(ErrorStack::get())
3061 }
3062 }
3063 }
3064
3065 #[corresponds(SSL_get_current_cipher)]
3067 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
3068 unsafe {
3069 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
3070
3071 SslCipherRef::from_const_ptr_opt(ptr)
3072 }
3073 }
3074
3075 #[corresponds(SSL_state_string)]
3077 pub fn state_string(&self) -> &'static str {
3078 let state = unsafe {
3079 let ptr = ffi::SSL_state_string(self.as_ptr());
3080 CStr::from_ptr(ptr as *const _)
3081 };
3082
3083 str::from_utf8(state.to_bytes()).unwrap()
3084 }
3085
3086 #[corresponds(SSL_state_string_long)]
3088 pub fn state_string_long(&self) -> &'static str {
3089 let state = unsafe {
3090 let ptr = ffi::SSL_state_string_long(self.as_ptr());
3091 CStr::from_ptr(ptr as *const _)
3092 };
3093
3094 str::from_utf8(state.to_bytes()).unwrap()
3095 }
3096
3097 #[corresponds(SSL_set_tlsext_host_name)]
3101 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
3102 let cstr = CString::new(hostname).unwrap();
3103 unsafe {
3104 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
3105 .map(|_| ())
3106 }
3107 }
3108
3109 #[corresponds(SSL_get_peer_certificate)]
3111 pub fn peer_certificate(&self) -> Option<X509> {
3112 unsafe {
3113 let ptr = SSL_get1_peer_certificate(self.as_ptr());
3114 X509::from_ptr_opt(ptr)
3115 }
3116 }
3117
3118 #[corresponds(SSL_get_peer_cert_chain)]
3123 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
3124 unsafe {
3125 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
3126 StackRef::from_const_ptr_opt(ptr)
3127 }
3128 }
3129
3130 #[corresponds(SSL_get0_verified_chain)]
3140 #[cfg(ossl110)]
3141 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
3142 unsafe {
3143 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
3144 StackRef::from_const_ptr_opt(ptr)
3145 }
3146 }
3147
3148 #[corresponds(SSL_get_certificate)]
3150 pub fn certificate(&self) -> Option<&X509Ref> {
3151 unsafe {
3152 let ptr = ffi::SSL_get_certificate(self.as_ptr());
3153 X509Ref::from_const_ptr_opt(ptr)
3154 }
3155 }
3156
3157 #[corresponds(SSL_get_privatekey)]
3161 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
3162 unsafe {
3163 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
3164 PKeyRef::from_const_ptr_opt(ptr)
3165 }
3166 }
3167
3168 #[corresponds(SSL_version)]
3170 pub fn version2(&self) -> Option<SslVersion> {
3171 unsafe {
3172 let r = ffi::SSL_version(self.as_ptr());
3173 if r == 0 {
3174 None
3175 } else {
3176 Some(SslVersion(r))
3177 }
3178 }
3179 }
3180
3181 #[corresponds(SSL_get_version)]
3183 pub fn version_str(&self) -> &'static str {
3184 let version = unsafe {
3185 let ptr = ffi::SSL_get_version(self.as_ptr());
3186 CStr::from_ptr(ptr as *const _)
3187 };
3188
3189 str::from_utf8(version.to_bytes()).unwrap()
3190 }
3191
3192 #[corresponds(SSL_get0_alpn_selected)]
3199 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
3200 unsafe {
3201 let mut data: *const c_uchar = ptr::null();
3202 let mut len: c_uint = 0;
3203 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
3206
3207 if data.is_null() {
3208 None
3209 } else {
3210 Some(util::from_raw_parts(data, len as usize))
3211 }
3212 }
3213 }
3214
3215 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3217 #[corresponds(SSL_set_tlsext_use_srtp)]
3218 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
3219 unsafe {
3220 let cstr = CString::new(protocols).unwrap();
3221
3222 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
3223 if r == 0 {
3225 Ok(())
3226 } else {
3227 Err(ErrorStack::get())
3228 }
3229 }
3230 }
3231
3232 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3236 #[corresponds(SSL_get_srtp_profiles)]
3237 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
3238 unsafe {
3239 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
3240
3241 StackRef::from_const_ptr_opt(chain)
3242 }
3243 }
3244
3245 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
3249 #[corresponds(SSL_get_selected_srtp_profile)]
3250 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
3251 unsafe {
3252 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
3253
3254 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
3255 }
3256 }
3257
3258 #[corresponds(SSL_pending)]
3263 pub fn pending(&self) -> usize {
3264 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
3265 }
3266
3267 #[corresponds(SSL_get_servername)]
3280 pub fn servername(&self, type_: NameType) -> Option<&str> {
3282 self.servername_raw(type_)
3283 .and_then(|b| str::from_utf8(b).ok())
3284 }
3285
3286 #[corresponds(SSL_get_servername)]
3294 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
3295 unsafe {
3296 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
3297 if name.is_null() {
3298 None
3299 } else {
3300 Some(CStr::from_ptr(name as *const _).to_bytes())
3301 }
3302 }
3303 }
3304
3305 #[corresponds(SSL_set_SSL_CTX)]
3309 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
3310 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
3311 }
3312
3313 #[corresponds(SSL_get_SSL_CTX)]
3315 pub fn ssl_context(&self) -> &SslContextRef {
3316 unsafe {
3317 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
3318 SslContextRef::from_ptr(ssl_ctx)
3319 }
3320 }
3321
3322 #[corresponds(SSL_get0_param)]
3326 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
3327 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
3328 }
3329
3330 #[corresponds(SSL_get_verify_result)]
3332 pub fn verify_result(&self) -> X509VerifyResult {
3333 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
3334 }
3335
3336 #[corresponds(SSL_get_session)]
3338 pub fn session(&self) -> Option<&SslSessionRef> {
3339 unsafe {
3340 let p = ffi::SSL_get_session(self.as_ptr());
3341 SslSessionRef::from_const_ptr_opt(p)
3342 }
3343 }
3344
3345 #[corresponds(SSL_get_client_random)]
3352 #[cfg(any(ossl110, libressl))]
3353 pub fn client_random(&self, buf: &mut [u8]) -> usize {
3354 unsafe {
3355 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3356 }
3357 }
3358
3359 #[corresponds(SSL_get_server_random)]
3366 #[cfg(any(ossl110, libressl))]
3367 pub fn server_random(&self, buf: &mut [u8]) -> usize {
3368 unsafe {
3369 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
3370 }
3371 }
3372
3373 #[corresponds(SSL_export_keying_material)]
3375 pub fn export_keying_material(
3376 &self,
3377 out: &mut [u8],
3378 label: &str,
3379 context: Option<&[u8]>,
3380 ) -> Result<(), ErrorStack> {
3381 unsafe {
3382 let (context, contextlen, use_context) = match context {
3383 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
3384 None => (ptr::null(), 0, 0),
3385 };
3386 cvt(ffi::SSL_export_keying_material(
3387 self.as_ptr(),
3388 out.as_mut_ptr() as *mut c_uchar,
3389 out.len(),
3390 label.as_ptr() as *const c_char,
3391 label.len(),
3392 context,
3393 contextlen,
3394 use_context,
3395 ))
3396 .map(|_| ())
3397 }
3398 }
3399
3400 #[corresponds(SSL_export_keying_material_early)]
3407 #[cfg(ossl111)]
3408 pub fn export_keying_material_early(
3409 &self,
3410 out: &mut [u8],
3411 label: &str,
3412 context: &[u8],
3413 ) -> Result<(), ErrorStack> {
3414 unsafe {
3415 cvt(ffi::SSL_export_keying_material_early(
3416 self.as_ptr(),
3417 out.as_mut_ptr() as *mut c_uchar,
3418 out.len(),
3419 label.as_ptr() as *const c_char,
3420 label.len(),
3421 context.as_ptr() as *const c_uchar,
3422 context.len(),
3423 ))
3424 .map(|_| ())
3425 }
3426 }
3427
3428 #[corresponds(SSL_set_session)]
3439 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
3440 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
3441 }
3442
3443 #[corresponds(SSL_session_reused)]
3445 pub fn session_reused(&self) -> bool {
3446 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
3447 }
3448
3449 #[cfg(any(boringssl, awslc))]
3457 pub fn enable_ocsp_stapling(&mut self) {
3458 unsafe { ffi::SSL_enable_ocsp_stapling(self.as_ptr()) }
3459 }
3460
3461 #[cfg(any(boringssl, awslc))]
3469 pub fn enable_signed_cert_timestamps(&mut self) {
3470 unsafe { ffi::SSL_enable_signed_cert_timestamps(self.as_ptr()) }
3471 }
3472
3473 #[cfg(any(boringssl, awslc))]
3481 pub fn set_permute_extensions(&mut self, enabled: bool) {
3482 unsafe { ffi::SSL_set_permute_extensions(self.as_ptr(), enabled as c_int) }
3483 }
3484
3485 #[corresponds(SSL_enable_ct)]
3487 #[cfg(ossl111)]
3488 pub fn enable_ct(&mut self, validation_mode: SslCtValidationMode) -> Result<(), ErrorStack> {
3489 unsafe { cvt(ffi::SSL_enable_ct(self.as_ptr(), validation_mode.0)).map(|_| ()) }
3490 }
3491
3492 #[corresponds(SSL_ct_is_enabled)]
3494 #[cfg(ossl111)]
3495 pub fn ct_is_enabled(&self) -> bool {
3496 unsafe { ffi::SSL_ct_is_enabled(self.as_ptr()) == 1 }
3497 }
3498
3499 #[corresponds(SSL_set_tlsext_status_type)]
3501 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
3502 unsafe {
3503 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
3504 }
3505 }
3506
3507 #[corresponds(SSL_get_extms_support)]
3511 #[cfg(ossl110)]
3512 pub fn extms_support(&self) -> Option<bool> {
3513 unsafe {
3514 match ffi::SSL_get_extms_support(self.as_ptr()) {
3515 -1 => None,
3516 ret => Some(ret != 0),
3517 }
3518 }
3519 }
3520
3521 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
3523 #[cfg(not(any(boringssl, awslc)))]
3524 pub fn ocsp_status(&self) -> Option<&[u8]> {
3525 unsafe {
3526 let mut p = ptr::null_mut();
3527 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
3528
3529 if len < 0 {
3530 None
3531 } else {
3532 Some(util::from_raw_parts(p as *const u8, len as usize))
3533 }
3534 }
3535 }
3536
3537 #[corresponds(SSL_get0_ocsp_response)]
3539 #[cfg(any(boringssl, awslc))]
3540 pub fn ocsp_status(&self) -> Option<&[u8]> {
3541 unsafe {
3542 let mut p = ptr::null();
3543 let mut len: usize = 0;
3544 ffi::SSL_get0_ocsp_response(self.as_ptr(), &mut p, &mut len);
3545
3546 if len == 0 {
3547 None
3548 } else {
3549 Some(util::from_raw_parts(p as *const u8, len))
3550 }
3551 }
3552 }
3553
3554 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
3556 #[cfg(not(any(boringssl, awslc)))]
3557 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3558 unsafe {
3559 assert!(response.len() <= c_int::MAX as usize);
3560 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
3561 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
3562 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
3563 self.as_ptr(),
3564 p as *mut c_uchar,
3565 response.len() as c_long,
3566 ) as c_int)
3567 .map(|_| ())
3568 .map_err(|e| {
3569 ffi::OPENSSL_free(p);
3570 e
3571 })
3572 }
3573 }
3574
3575 #[corresponds(SSL_set_ocsp_response)]
3577 #[cfg(any(boringssl, awslc))]
3578 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
3579 unsafe {
3580 cvt(ffi::SSL_set_ocsp_response(
3581 self.as_ptr(),
3582 response.as_ptr(),
3583 response.len(),
3584 ))
3585 .map(|_| ())
3586 }
3587 }
3588
3589 #[corresponds(SSL_is_server)]
3591 pub fn is_server(&self) -> bool {
3592 unsafe { SSL_is_server(self.as_ptr()) != 0 }
3593 }
3594
3595 #[corresponds(SSL_set_ex_data)]
3601 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
3602 match self.ex_data_mut(index) {
3603 Some(v) => *v = data,
3604 None => unsafe {
3605 let data = Box::new(data);
3606 ffi::SSL_set_ex_data(
3607 self.as_ptr(),
3608 index.as_raw(),
3609 Box::into_raw(data) as *mut c_void,
3610 );
3611 },
3612 }
3613 }
3614
3615 #[corresponds(SSL_get_ex_data)]
3617 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
3618 unsafe {
3619 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3620 if data.is_null() {
3621 None
3622 } else {
3623 Some(&*(data as *const T))
3624 }
3625 }
3626 }
3627
3628 #[corresponds(SSL_get_ex_data)]
3630 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3631 unsafe {
3632 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3633 if data.is_null() {
3634 None
3635 } else {
3636 Some(&mut *(data as *mut T))
3637 }
3638 }
3639 }
3640
3641 #[corresponds(SSL_set_max_early_data)]
3645 #[cfg(any(ossl111, libressl))]
3646 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3647 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3648 Ok(())
3649 } else {
3650 Err(ErrorStack::get())
3651 }
3652 }
3653
3654 #[corresponds(SSL_get_max_early_data)]
3658 #[cfg(any(ossl111, libressl))]
3659 pub fn max_early_data(&self) -> u32 {
3660 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3661 }
3662
3663 #[corresponds(SSL_get_finished)]
3668 pub fn finished(&self, buf: &mut [u8]) -> usize {
3669 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3670 }
3671
3672 #[corresponds(SSL_get_peer_finished)]
3678 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3679 unsafe {
3680 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3681 }
3682 }
3683
3684 #[corresponds(SSL_is_init_finished)]
3686 #[cfg(ossl110)]
3687 pub fn is_init_finished(&self) -> bool {
3688 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3689 }
3690
3691 #[corresponds(SSL_client_hello_isv2)]
3697 #[cfg(ossl111)]
3698 pub fn client_hello_isv2(&self) -> bool {
3699 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3700 }
3701
3702 #[corresponds(SSL_client_hello_get0_legacy_version)]
3708 #[cfg(ossl111)]
3709 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3710 unsafe {
3711 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3712 if version == 0 {
3713 None
3714 } else {
3715 Some(SslVersion(version as c_int))
3716 }
3717 }
3718 }
3719
3720 #[corresponds(SSL_client_hello_get0_random)]
3726 #[cfg(ossl111)]
3727 pub fn client_hello_random(&self) -> Option<&[u8]> {
3728 unsafe {
3729 let mut ptr = ptr::null();
3730 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3731 if len == 0 {
3732 None
3733 } else {
3734 Some(util::from_raw_parts(ptr, len))
3735 }
3736 }
3737 }
3738
3739 #[corresponds(SSL_client_hello_get0_session_id)]
3745 #[cfg(ossl111)]
3746 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3747 unsafe {
3748 let mut ptr = ptr::null();
3749 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3750 if len == 0 {
3751 None
3752 } else {
3753 Some(util::from_raw_parts(ptr, len))
3754 }
3755 }
3756 }
3757
3758 #[corresponds(SSL_client_hello_get0_ciphers)]
3764 #[cfg(ossl111)]
3765 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3766 unsafe {
3767 let mut ptr = ptr::null();
3768 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3769 if len == 0 {
3770 None
3771 } else {
3772 Some(util::from_raw_parts(ptr, len))
3773 }
3774 }
3775 }
3776
3777 #[cfg(ossl111)]
3783 pub fn client_hello_ext(&self, ext_type: TlsExtType) -> Option<&[u8]> {
3784 unsafe {
3785 let mut ptr = ptr::null();
3786 let mut len = 0usize;
3787 let r = ffi::SSL_client_hello_get0_ext(
3788 self.as_ptr(),
3789 ext_type.as_raw() as _,
3790 &mut ptr,
3791 &mut len,
3792 );
3793 if r == 0 {
3794 None
3795 } else {
3796 Some(util::from_raw_parts(ptr, len))
3797 }
3798 }
3799 }
3800
3801 #[corresponds(SSL_bytes_to_cipher_list)]
3806 #[cfg(ossl111)]
3807 pub fn bytes_to_cipher_list(
3808 &self,
3809 bytes: &[u8],
3810 isv2format: bool,
3811 ) -> Result<CipherLists, ErrorStack> {
3812 unsafe {
3813 let ptr = bytes.as_ptr();
3814 let len = bytes.len();
3815 let mut sk = ptr::null_mut();
3816 let mut scsvs = ptr::null_mut();
3817 let res = ffi::SSL_bytes_to_cipher_list(
3818 self.as_ptr(),
3819 ptr,
3820 len,
3821 isv2format as c_int,
3822 &mut sk,
3823 &mut scsvs,
3824 );
3825 if res == 1 {
3826 Ok(CipherLists {
3827 suites: Stack::from_ptr(sk),
3828 signalling_suites: Stack::from_ptr(scsvs),
3829 })
3830 } else {
3831 Err(ErrorStack::get())
3832 }
3833 }
3834 }
3835
3836 #[corresponds(SSL_client_hello_get0_compression_methods)]
3842 #[cfg(ossl111)]
3843 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3844 unsafe {
3845 let mut ptr = ptr::null();
3846 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3847 if len == 0 {
3848 None
3849 } else {
3850 Some(util::from_raw_parts(ptr, len))
3851 }
3852 }
3853 }
3854
3855 #[corresponds(SSL_set_mtu)]
3857 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3858 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3859 }
3860
3861 #[corresponds(SSL_get_psk_identity_hint)]
3865 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3866 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3867 unsafe {
3868 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3869 if ptr.is_null() {
3870 None
3871 } else {
3872 Some(CStr::from_ptr(ptr).to_bytes())
3873 }
3874 }
3875 }
3876
3877 #[corresponds(SSL_get_psk_identity)]
3879 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3880 pub fn psk_identity(&self) -> Option<&[u8]> {
3881 unsafe {
3882 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3883 if ptr.is_null() {
3884 None
3885 } else {
3886 Some(CStr::from_ptr(ptr).to_bytes())
3887 }
3888 }
3889 }
3890
3891 #[corresponds(SSL_add0_chain_cert)]
3892 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3893 unsafe {
3894 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3895 mem::forget(chain);
3896 }
3897 Ok(())
3898 }
3899
3900 #[cfg(not(any(boringssl, awslc)))]
3902 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3903 unsafe {
3904 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3905 };
3906 Ok(())
3907 }
3908
3909 #[corresponds(SSL_use_Private_Key_file)]
3911 pub fn set_private_key_file<P: AsRef<Path>>(
3912 &mut self,
3913 path: P,
3914 ssl_file_type: SslFiletype,
3915 ) -> Result<(), ErrorStack> {
3916 let p = path.as_ref().as_os_str().to_str().unwrap();
3917 let key_file = CString::new(p).unwrap();
3918 unsafe {
3919 cvt(ffi::SSL_use_PrivateKey_file(
3920 self.as_ptr(),
3921 key_file.as_ptr(),
3922 ssl_file_type.as_raw(),
3923 ))?;
3924 };
3925 Ok(())
3926 }
3927
3928 #[corresponds(SSL_use_PrivateKey)]
3930 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3931 unsafe {
3932 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3933 };
3934 Ok(())
3935 }
3936
3937 #[cfg(tongsuo)]
3938 #[corresponds(SSL_use_enc_Private_Key_file)]
3939 pub fn set_enc_private_key_file<P: AsRef<Path>>(
3940 &mut self,
3941 path: P,
3942 ssl_file_type: SslFiletype,
3943 ) -> Result<(), ErrorStack> {
3944 let p = path.as_ref().as_os_str().to_str().unwrap();
3945 let key_file = CString::new(p).unwrap();
3946 unsafe {
3947 cvt(ffi::SSL_use_enc_PrivateKey_file(
3948 self.as_ptr(),
3949 key_file.as_ptr(),
3950 ssl_file_type.as_raw(),
3951 ))?;
3952 };
3953 Ok(())
3954 }
3955
3956 #[cfg(tongsuo)]
3957 #[corresponds(SSL_use_enc_PrivateKey)]
3958 pub fn set_enc_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3959 unsafe {
3960 cvt(ffi::SSL_use_enc_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3961 };
3962 Ok(())
3963 }
3964
3965 #[cfg(tongsuo)]
3966 #[corresponds(SSL_use_sign_Private_Key_file)]
3967 pub fn set_sign_private_key_file<P: AsRef<Path>>(
3968 &mut self,
3969 path: P,
3970 ssl_file_type: SslFiletype,
3971 ) -> Result<(), ErrorStack> {
3972 let p = path.as_ref().as_os_str().to_str().unwrap();
3973 let key_file = CString::new(p).unwrap();
3974 unsafe {
3975 cvt(ffi::SSL_use_sign_PrivateKey_file(
3976 self.as_ptr(),
3977 key_file.as_ptr(),
3978 ssl_file_type.as_raw(),
3979 ))?;
3980 };
3981 Ok(())
3982 }
3983
3984 #[cfg(tongsuo)]
3985 #[corresponds(SSL_use_sign_PrivateKey)]
3986 pub fn set_sign_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3987 unsafe {
3988 cvt(ffi::SSL_use_sign_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3989 };
3990 Ok(())
3991 }
3992
3993 #[corresponds(SSL_use_certificate)]
3995 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3996 unsafe {
3997 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3998 };
3999 Ok(())
4000 }
4001
4002 #[cfg(tongsuo)]
4003 #[corresponds(SSL_use_enc_certificate)]
4004 pub fn set_enc_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4005 unsafe {
4006 cvt(ffi::SSL_use_enc_certificate(self.as_ptr(), cert.as_ptr()))?;
4007 };
4008 Ok(())
4009 }
4010
4011 #[cfg(tongsuo)]
4012 #[corresponds(SSL_use_sign_certificate)]
4013 pub fn set_sign_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
4014 unsafe {
4015 cvt(ffi::SSL_use_sign_certificate(self.as_ptr(), cert.as_ptr()))?;
4016 };
4017 Ok(())
4018 }
4019
4020 #[corresponds(SSL_use_certificate_chain_file)]
4026 #[cfg(any(ossl110, libressl))]
4027 pub fn set_certificate_chain_file<P: AsRef<Path>>(
4028 &mut self,
4029 path: P,
4030 ) -> Result<(), ErrorStack> {
4031 let p = path.as_ref().as_os_str().to_str().unwrap();
4032 let cert_file = CString::new(p).unwrap();
4033 unsafe {
4034 cvt(ffi::SSL_use_certificate_chain_file(
4035 self.as_ptr(),
4036 cert_file.as_ptr(),
4037 ))?;
4038 };
4039 Ok(())
4040 }
4041
4042 #[corresponds(SSL_add_client_CA)]
4044 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
4045 unsafe {
4046 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
4047 };
4048 Ok(())
4049 }
4050
4051 #[corresponds(SSL_set_client_CA_list)]
4053 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
4054 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
4055 mem::forget(list);
4056 }
4057
4058 #[corresponds(SSL_set_min_proto_version)]
4063 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4064 unsafe {
4065 cvt(ffi::SSL_set_min_proto_version(
4066 self.as_ptr(),
4067 version.map_or(0, |v| v.0 as _),
4068 ))
4069 .map(|_| ())
4070 }
4071 }
4072
4073 #[corresponds(SSL_set_max_proto_version)]
4078 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
4079 unsafe {
4080 cvt(ffi::SSL_set_max_proto_version(
4081 self.as_ptr(),
4082 version.map_or(0, |v| v.0 as _),
4083 ))
4084 .map(|_| ())
4085 }
4086 }
4087
4088 #[corresponds(SSL_set_ciphersuites)]
4097 #[cfg(any(ossl111, libressl))]
4098 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4099 let cipher_list = CString::new(cipher_list).unwrap();
4100 unsafe {
4101 cvt(ffi::SSL_set_ciphersuites(
4102 self.as_ptr(),
4103 cipher_list.as_ptr() as *const _,
4104 ))
4105 .map(|_| ())
4106 }
4107 }
4108
4109 #[corresponds(SSL_set_cipher_list)]
4117 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
4118 let cipher_list = CString::new(cipher_list).unwrap();
4119 unsafe {
4120 cvt(ffi::SSL_set_cipher_list(
4121 self.as_ptr(),
4122 cipher_list.as_ptr() as *const _,
4123 ))
4124 .map(|_| ())
4125 }
4126 }
4127
4128 #[corresponds(SSL_set_cert_store)]
4130 #[cfg(any(ossl110, boringssl, awslc))]
4131 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
4132 unsafe {
4133 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
4134 mem::forget(cert_store);
4135 Ok(())
4136 }
4137 }
4138
4139 #[corresponds(SSL_set_num_tickets)]
4144 #[cfg(ossl111)]
4145 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
4146 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
4147 }
4148
4149 #[corresponds(SSL_get_num_tickets)]
4154 #[cfg(ossl111)]
4155 pub fn num_tickets(&self) -> usize {
4156 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
4157 }
4158
4159 #[corresponds(SSL_set_security_level)]
4164 #[cfg(any(ossl110, libressl360))]
4165 pub fn set_security_level(&mut self, level: u32) {
4166 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
4167 }
4168
4169 #[corresponds(SSL_get_security_level)]
4174 #[cfg(any(ossl110, libressl360))]
4175 pub fn security_level(&self) -> u32 {
4176 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
4177 }
4178
4179 #[corresponds(SSL_get_peer_tmp_key)]
4184 #[cfg(ossl300)]
4185 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
4186 unsafe {
4187 let mut key = ptr::null_mut();
4188 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
4189 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
4190 Err(e) => Err(e),
4191 }
4192 }
4193 }
4194
4195 #[corresponds(SSL_get_tmp_key)]
4200 #[cfg(ossl300)]
4201 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
4202 unsafe {
4203 let mut key = ptr::null_mut();
4204 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
4205 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
4206 Err(e) => Err(e),
4207 }
4208 }
4209 }
4210}
4211
4212#[derive(Debug)]
4214pub struct MidHandshakeSslStream<S> {
4215 stream: SslStream<S>,
4216 error: Error,
4217}
4218
4219impl<S> MidHandshakeSslStream<S> {
4220 pub fn get_ref(&self) -> &S {
4222 self.stream.get_ref()
4223 }
4224
4225 pub fn get_mut(&mut self) -> &mut S {
4227 self.stream.get_mut()
4228 }
4229
4230 pub fn ssl(&self) -> &SslRef {
4232 self.stream.ssl()
4233 }
4234
4235 pub fn ssl_mut(&mut self) -> &mut SslRef {
4237 self.stream.ssl_mut()
4238 }
4239
4240 pub fn error(&self) -> &Error {
4242 &self.error
4243 }
4244
4245 pub fn into_error(self) -> Error {
4247 self.error
4248 }
4249}
4250
4251impl<S> MidHandshakeSslStream<S>
4252where
4253 S: Read + Write,
4254{
4255 #[corresponds(SSL_do_handshake)]
4258 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4259 match self.stream.do_handshake() {
4260 Ok(()) => Ok(self.stream),
4261 Err(error) => {
4262 self.error = error;
4263 match self.error.code() {
4264 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4265 Err(HandshakeError::WouldBlock(self))
4266 }
4267 _ => Err(HandshakeError::Failure(self)),
4268 }
4269 }
4270 }
4271 }
4272}
4273
4274pub struct SslStream<S> {
4276 ssl: ManuallyDrop<Ssl>,
4277 method: ManuallyDrop<BioMethod>,
4278 _p: PhantomData<S>,
4279}
4280
4281impl<S> Drop for SslStream<S> {
4282 fn drop(&mut self) {
4283 unsafe {
4285 ManuallyDrop::drop(&mut self.ssl);
4286 ManuallyDrop::drop(&mut self.method);
4287 }
4288 }
4289}
4290
4291impl<S> fmt::Debug for SslStream<S>
4292where
4293 S: fmt::Debug,
4294{
4295 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
4296 fmt.debug_struct("SslStream")
4297 .field("stream", &self.get_ref())
4298 .field("ssl", &self.ssl())
4299 .finish()
4300 }
4301}
4302
4303impl<S: Read + Write> SslStream<S> {
4304 #[corresponds(SSL_set_bio)]
4312 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
4313 let (bio, method) = bio::new(stream)?;
4314 unsafe {
4315 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
4316 }
4317
4318 Ok(SslStream {
4319 ssl: ManuallyDrop::new(ssl),
4320 method: ManuallyDrop::new(method),
4321 _p: PhantomData,
4322 })
4323 }
4324
4325 #[corresponds(SSL_read_early_data)]
4334 #[cfg(any(ossl111, libressl))]
4335 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4336 let mut read = 0;
4337 let ret = unsafe {
4338 ffi::SSL_read_early_data(
4339 self.ssl.as_ptr(),
4340 buf.as_ptr() as *mut c_void,
4341 buf.len(),
4342 &mut read,
4343 )
4344 };
4345 match ret {
4346 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
4347 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
4348 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
4349 _ => unreachable!(),
4350 }
4351 }
4352
4353 #[corresponds(SSL_write_early_data)]
4360 #[cfg(any(ossl111, libressl))]
4361 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4362 let mut written = 0;
4363 let ret = unsafe {
4364 ffi::SSL_write_early_data(
4365 self.ssl.as_ptr(),
4366 buf.as_ptr() as *const c_void,
4367 buf.len(),
4368 &mut written,
4369 )
4370 };
4371 if ret > 0 {
4372 Ok(written)
4373 } else {
4374 Err(self.make_error(ret))
4375 }
4376 }
4377
4378 #[corresponds(SSL_connect)]
4385 pub fn connect(&mut self) -> Result<(), Error> {
4386 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
4387 if ret > 0 {
4388 Ok(())
4389 } else {
4390 Err(self.make_error(ret))
4391 }
4392 }
4393
4394 #[corresponds(SSL_accept)]
4401 pub fn accept(&mut self) -> Result<(), Error> {
4402 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
4403 if ret > 0 {
4404 Ok(())
4405 } else {
4406 Err(self.make_error(ret))
4407 }
4408 }
4409
4410 #[corresponds(SSL_do_handshake)]
4414 pub fn do_handshake(&mut self) -> Result<(), Error> {
4415 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
4416 if ret > 0 {
4417 Ok(())
4418 } else {
4419 Err(self.make_error(ret))
4420 }
4421 }
4422
4423 #[corresponds(SSL_stateless)]
4434 #[cfg(ossl111)]
4435 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4436 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
4437 1 => Ok(true),
4438 0 => Ok(false),
4439 -1 => Err(ErrorStack::get()),
4440 _ => unreachable!(),
4441 }
4442 }
4443
4444 #[corresponds(SSL_read_ex)]
4451 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
4452 loop {
4453 match self.ssl_read_uninit(buf) {
4454 Ok(n) => return Ok(n),
4455 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
4456 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
4457 return Ok(0);
4458 }
4459 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4460 Err(e) => {
4461 return Err(e
4462 .into_io_error()
4463 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4464 }
4465 }
4466 }
4467 }
4468
4469 #[corresponds(SSL_read_ex)]
4474 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4475 unsafe {
4477 self.ssl_read_uninit(util::from_raw_parts_mut(
4478 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4479 buf.len(),
4480 ))
4481 }
4482 }
4483
4484 #[corresponds(SSL_read_ex)]
4491 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4492 cfg_if! {
4493 if #[cfg(any(ossl111, libressl))] {
4494 let mut readbytes = 0;
4495 let ret = unsafe {
4496 ffi::SSL_read_ex(
4497 self.ssl().as_ptr(),
4498 buf.as_mut_ptr().cast(),
4499 buf.len(),
4500 &mut readbytes,
4501 )
4502 };
4503
4504 if ret > 0 {
4505 Ok(readbytes)
4506 } else {
4507 Err(self.make_error(ret))
4508 }
4509 } else {
4510 if buf.is_empty() {
4511 return Ok(0);
4512 }
4513
4514 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4515 let ret = unsafe {
4516 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4517 };
4518 if ret > 0 {
4519 Ok(ret as usize)
4520 } else {
4521 Err(self.make_error(ret))
4522 }
4523 }
4524 }
4525 }
4526
4527 #[corresponds(SSL_write_ex)]
4532 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
4533 cfg_if! {
4534 if #[cfg(any(ossl111, libressl))] {
4535 let mut written = 0;
4536 let ret = unsafe {
4537 ffi::SSL_write_ex(
4538 self.ssl().as_ptr(),
4539 buf.as_ptr().cast(),
4540 buf.len(),
4541 &mut written,
4542 )
4543 };
4544
4545 if ret > 0 {
4546 Ok(written)
4547 } else {
4548 Err(self.make_error(ret))
4549 }
4550 } else {
4551 if buf.is_empty() {
4552 return Ok(0);
4553 }
4554
4555 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4556 let ret = unsafe {
4557 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
4558 };
4559 if ret > 0 {
4560 Ok(ret as usize)
4561 } else {
4562 Err(self.make_error(ret))
4563 }
4564 }
4565 }
4566 }
4567
4568 #[corresponds(SSL_peek_ex)]
4570 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4571 unsafe {
4573 self.ssl_peek_uninit(util::from_raw_parts_mut(
4574 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4575 buf.len(),
4576 ))
4577 }
4578 }
4579
4580 #[corresponds(SSL_peek_ex)]
4587 pub fn ssl_peek_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
4588 cfg_if! {
4589 if #[cfg(any(ossl111, libressl))] {
4590 let mut readbytes = 0;
4591 let ret = unsafe {
4592 ffi::SSL_peek_ex(
4593 self.ssl().as_ptr(),
4594 buf.as_mut_ptr().cast(),
4595 buf.len(),
4596 &mut readbytes,
4597 )
4598 };
4599
4600 if ret > 0 {
4601 Ok(readbytes)
4602 } else {
4603 Err(self.make_error(ret))
4604 }
4605 } else {
4606 if buf.is_empty() {
4607 return Ok(0);
4608 }
4609
4610 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
4611 let ret = unsafe {
4612 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
4613 };
4614 if ret > 0 {
4615 Ok(ret as usize)
4616 } else {
4617 Err(self.make_error(ret))
4618 }
4619 }
4620 }
4621 }
4622
4623 #[corresponds(SSL_shutdown)]
4633 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
4634 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
4635 0 => Ok(ShutdownResult::Sent),
4636 1 => Ok(ShutdownResult::Received),
4637 n => Err(self.make_error(n)),
4638 }
4639 }
4640
4641 #[corresponds(SSL_get_shutdown)]
4643 pub fn get_shutdown(&mut self) -> ShutdownState {
4644 unsafe {
4645 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
4646 ShutdownState::from_bits_retain(bits)
4647 }
4648 }
4649
4650 #[corresponds(SSL_set_shutdown)]
4655 pub fn set_shutdown(&mut self, state: ShutdownState) {
4656 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
4657 }
4658}
4659
4660impl<S> SslStream<S> {
4661 fn make_error(&mut self, ret: c_int) -> Error {
4662 self.check_panic();
4663
4664 let code = self.ssl.get_error(ret);
4665
4666 let cause = match code {
4667 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
4668 ErrorCode::SYSCALL => {
4669 let errs = ErrorStack::get();
4670 if errs.errors().is_empty() {
4671 self.get_bio_error().map(InnerError::Io)
4672 } else {
4673 Some(InnerError::Ssl(errs))
4674 }
4675 }
4676 ErrorCode::ZERO_RETURN => None,
4677 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4678 self.get_bio_error().map(InnerError::Io)
4679 }
4680 _ => None,
4681 };
4682
4683 Error { code, cause }
4684 }
4685
4686 fn check_panic(&mut self) {
4687 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
4688 resume_unwind(err)
4689 }
4690 }
4691
4692 fn get_bio_error(&mut self) -> Option<io::Error> {
4693 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
4694 }
4695
4696 pub fn get_ref(&self) -> &S {
4698 unsafe {
4699 let bio = self.ssl.get_raw_rbio();
4700 bio::get_ref(bio)
4701 }
4702 }
4703
4704 pub fn get_mut(&mut self) -> &mut S {
4711 unsafe {
4712 let bio = self.ssl.get_raw_rbio();
4713 bio::get_mut(bio)
4714 }
4715 }
4716
4717 pub fn ssl(&self) -> &SslRef {
4719 &self.ssl
4720 }
4721
4722 pub fn ssl_mut(&mut self) -> &mut SslRef {
4724 &mut self.ssl
4725 }
4726}
4727
4728impl<S: Read + Write> Read for SslStream<S> {
4729 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4730 unsafe {
4732 self.read_uninit(util::from_raw_parts_mut(
4733 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4734 buf.len(),
4735 ))
4736 }
4737 }
4738}
4739
4740impl<S: Read + Write> Write for SslStream<S> {
4741 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4742 loop {
4743 match self.ssl_write(buf) {
4744 Ok(n) => return Ok(n),
4745 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4746 Err(e) => {
4747 return Err(e
4748 .into_io_error()
4749 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4750 }
4751 }
4752 }
4753 }
4754
4755 fn flush(&mut self) -> io::Result<()> {
4756 self.get_mut().flush()
4757 }
4758}
4759
4760#[deprecated(
4762 since = "0.10.32",
4763 note = "use the methods directly on Ssl/SslStream instead"
4764)]
4765pub struct SslStreamBuilder<S> {
4766 inner: SslStream<S>,
4767}
4768
4769#[allow(deprecated)]
4770impl<S> SslStreamBuilder<S>
4771where
4772 S: Read + Write,
4773{
4774 pub fn new(ssl: Ssl, stream: S) -> Self {
4776 Self {
4777 inner: SslStream::new(ssl, stream).unwrap(),
4778 }
4779 }
4780
4781 #[corresponds(SSL_stateless)]
4792 #[cfg(ossl111)]
4793 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4794 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4795 1 => Ok(true),
4796 0 => Ok(false),
4797 -1 => Err(ErrorStack::get()),
4798 _ => unreachable!(),
4799 }
4800 }
4801
4802 #[corresponds(SSL_set_connect_state)]
4804 pub fn set_connect_state(&mut self) {
4805 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4806 }
4807
4808 #[corresponds(SSL_set_accept_state)]
4810 pub fn set_accept_state(&mut self) {
4811 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4812 }
4813
4814 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4816 match self.inner.connect() {
4817 Ok(()) => Ok(self.inner),
4818 Err(error) => match error.code() {
4819 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4820 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4821 stream: self.inner,
4822 error,
4823 }))
4824 }
4825 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4826 stream: self.inner,
4827 error,
4828 })),
4829 },
4830 }
4831 }
4832
4833 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4835 match self.inner.accept() {
4836 Ok(()) => Ok(self.inner),
4837 Err(error) => match error.code() {
4838 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4839 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4840 stream: self.inner,
4841 error,
4842 }))
4843 }
4844 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4845 stream: self.inner,
4846 error,
4847 })),
4848 },
4849 }
4850 }
4851
4852 #[corresponds(SSL_do_handshake)]
4856 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4857 match self.inner.do_handshake() {
4858 Ok(()) => Ok(self.inner),
4859 Err(error) => match error.code() {
4860 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4861 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4862 stream: self.inner,
4863 error,
4864 }))
4865 }
4866 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4867 stream: self.inner,
4868 error,
4869 })),
4870 },
4871 }
4872 }
4873
4874 #[corresponds(SSL_read_early_data)]
4884 #[cfg(any(ossl111, libressl))]
4885 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4886 self.inner.read_early_data(buf)
4887 }
4888
4889 #[corresponds(SSL_write_early_data)]
4896 #[cfg(any(ossl111, libressl))]
4897 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4898 self.inner.write_early_data(buf)
4899 }
4900}
4901
4902#[allow(deprecated)]
4903impl<S> SslStreamBuilder<S> {
4904 pub fn get_ref(&self) -> &S {
4906 unsafe {
4907 let bio = self.inner.ssl.get_raw_rbio();
4908 bio::get_ref(bio)
4909 }
4910 }
4911
4912 pub fn get_mut(&mut self) -> &mut S {
4919 unsafe {
4920 let bio = self.inner.ssl.get_raw_rbio();
4921 bio::get_mut(bio)
4922 }
4923 }
4924
4925 pub fn ssl(&self) -> &SslRef {
4927 &self.inner.ssl
4928 }
4929
4930 pub fn ssl_mut(&mut self) -> &mut SslRef {
4932 &mut self.inner.ssl
4933 }
4934}
4935
4936#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4938pub enum ShutdownResult {
4939 Sent,
4941
4942 Received,
4944}
4945
4946bitflags! {
4947 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4949 #[repr(transparent)]
4950 pub struct ShutdownState: c_int {
4951 const SENT = ffi::SSL_SENT_SHUTDOWN;
4953 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4955 }
4956}
4957
4958use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4959cfg_if! {
4960 if #[cfg(ossl300)] {
4961 use ffi::SSL_get1_peer_certificate;
4962 } else {
4963 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4964 }
4965}
4966use ffi::{
4967 DTLS_client_method, DTLS_method, DTLS_server_method, TLS_client_method, TLS_method,
4968 TLS_server_method,
4969};
4970cfg_if! {
4971 if #[cfg(ossl110)] {
4972 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4973 ffi::CRYPTO_get_ex_new_index(
4974 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4975 0,
4976 ptr::null_mut(),
4977 None,
4978 None,
4979 f,
4980 )
4981 }
4982
4983 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4984 ffi::CRYPTO_get_ex_new_index(
4985 ffi::CRYPTO_EX_INDEX_SSL,
4986 0,
4987 ptr::null_mut(),
4988 None,
4989 None,
4990 f,
4991 )
4992 }
4993 } else {
4994 use std::sync::Once;
4995
4996 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4997 static ONCE: Once = Once::new();
4999 ONCE.call_once(|| {
5000 cfg_if! {
5001 if #[cfg(not(any(boringssl, awslc)))] {
5002 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5003 } else {
5004 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5005 }
5006 }
5007 });
5008
5009 cfg_if! {
5010 if #[cfg(not(any(boringssl, awslc)))] {
5011 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, f)
5012 } else {
5013 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
5014 }
5015 }
5016 }
5017
5018 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
5019 static ONCE: Once = Once::new();
5021 ONCE.call_once(|| {
5022 #[cfg(not(any(boringssl, awslc)))]
5023 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
5024 #[cfg(any(boringssl, awslc))]
5025 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
5026 });
5027
5028 #[cfg(not(any(boringssl, awslc)))]
5029 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, f);
5030 #[cfg(any(boringssl, awslc))]
5031 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
5032 }
5033 }
5034}