1#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63#[cfg(all(ossl101, not(ossl110)))]
64use crate::ec::EcKey;
65use crate::ec::EcKeyRef;
66use crate::error::ErrorStack;
67use crate::ex_data::Index;
68#[cfg(ossl111)]
69use crate::hash::MessageDigest;
70#[cfg(any(ossl110, libressl270))]
71use crate::nid::Nid;
72use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
73#[cfg(ossl300)]
74use crate::pkey::{PKey, Public};
75use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
76use crate::ssl::bio::BioMethod;
77use crate::ssl::callbacks::*;
78use crate::ssl::error::InnerError;
79use crate::stack::{Stack, StackRef, Stackable};
80use crate::util;
81use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
82use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
83#[cfg(any(ossl102, boringssl, libressl261))]
84use crate::x509::verify::X509VerifyParamRef;
85use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509};
86use crate::{cvt, cvt_n, cvt_p, init};
87use bitflags::bitflags;
88use cfg_if::cfg_if;
89use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
90use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_void};
91use once_cell::sync::{Lazy, OnceCell};
92use openssl_macros::corresponds;
93use std::any::TypeId;
94use std::collections::HashMap;
95use std::ffi::{CStr, CString};
96use std::fmt;
97use std::io;
98use std::io::prelude::*;
99use std::marker::PhantomData;
100use std::mem::{self, ManuallyDrop, MaybeUninit};
101use std::ops::{Deref, DerefMut};
102use std::panic::resume_unwind;
103use std::path::Path;
104use std::ptr;
105use std::str;
106use std::sync::{Arc, Mutex};
107
108pub use crate::ssl::connector::{
109 ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, SslConnectorBuilder,
110};
111pub use crate::ssl::error::{Error, ErrorCode, HandshakeError};
112
113mod bio;
114mod callbacks;
115mod connector;
116mod error;
117#[cfg(test)]
118mod test;
119
120#[corresponds(OPENSSL_cipher_name)]
126#[cfg(ossl111)]
127pub fn cipher_name(std_name: &str) -> &'static str {
128 unsafe {
129 ffi::init();
130
131 let s = CString::new(std_name).unwrap();
132 let ptr = ffi::OPENSSL_cipher_name(s.as_ptr());
133 CStr::from_ptr(ptr).to_str().unwrap()
134 }
135}
136
137cfg_if! {
138 if #[cfg(ossl300)] {
139 type SslOptionsRepr = u64;
140 } else if #[cfg(boringssl)] {
141 type SslOptionsRepr = u32;
142 } else {
143 type SslOptionsRepr = libc::c_ulong;
144 }
145}
146
147bitflags! {
148 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
150 #[repr(transparent)]
151 pub struct SslOptions: SslOptionsRepr {
152 const DONT_INSERT_EMPTY_FRAGMENTS = ffi::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS as SslOptionsRepr;
154
155 #[cfg(not(boringssl))]
157 const ALL = ffi::SSL_OP_ALL as SslOptionsRepr;
158
159 const NO_QUERY_MTU = ffi::SSL_OP_NO_QUERY_MTU as SslOptionsRepr;
163
164 #[cfg(not(boringssl))]
170 const COOKIE_EXCHANGE = ffi::SSL_OP_COOKIE_EXCHANGE as SslOptionsRepr;
171
172 const NO_TICKET = ffi::SSL_OP_NO_TICKET as SslOptionsRepr;
174
175 #[cfg(not(boringssl))]
177 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
178 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
179
180 #[cfg(not(boringssl))]
182 const NO_COMPRESSION = ffi::SSL_OP_NO_COMPRESSION as SslOptionsRepr;
183
184 const ALLOW_UNSAFE_LEGACY_RENEGOTIATION =
187 ffi::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION as SslOptionsRepr;
188
189 const SINGLE_ECDH_USE = ffi::SSL_OP_SINGLE_ECDH_USE as SslOptionsRepr;
193
194 const SINGLE_DH_USE = ffi::SSL_OP_SINGLE_DH_USE as SslOptionsRepr;
198
199 const CIPHER_SERVER_PREFERENCE = ffi::SSL_OP_CIPHER_SERVER_PREFERENCE as SslOptionsRepr;
203
204 const TLS_ROLLBACK_BUG = ffi::SSL_OP_TLS_ROLLBACK_BUG as SslOptionsRepr;
206
207 const NO_SSLV2 = ffi::SSL_OP_NO_SSLv2 as SslOptionsRepr;
209
210 const NO_SSLV3 = ffi::SSL_OP_NO_SSLv3 as SslOptionsRepr;
212
213 const NO_TLSV1 = ffi::SSL_OP_NO_TLSv1 as SslOptionsRepr;
215
216 const NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1 as SslOptionsRepr;
218
219 const NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2 as SslOptionsRepr;
221
222 #[cfg(any(boringssl, ossl111, libressl340))]
226 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
227
228 #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
232 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
233
234 #[cfg(any(boringssl, ossl102, ossl110, libressl332))]
238 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
239
240 #[cfg(any(ossl102, ossl110))]
256 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
257
258 #[cfg(any(boringssl, ossl110h))]
262 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
263
264 #[cfg(ossl111)]
269 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
270
271 #[cfg(ossl111)]
283 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
284 }
285}
286
287bitflags! {
288 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
290 #[repr(transparent)]
291 pub struct SslMode: SslBitType {
292 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
298
299 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
302
303 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
313
314 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
320
321 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
325
326 #[cfg(not(libressl))]
334 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
335 }
336}
337
338#[derive(Copy, Clone)]
340pub struct SslMethod(*const ffi::SSL_METHOD);
341
342impl SslMethod {
343 #[corresponds(TLS_method)]
345 pub fn tls() -> SslMethod {
346 unsafe { SslMethod(TLS_method()) }
347 }
348
349 #[corresponds(DTLS_method)]
351 pub fn dtls() -> SslMethod {
352 unsafe { SslMethod(DTLS_method()) }
353 }
354
355 #[corresponds(TLS_client_method)]
357 pub fn tls_client() -> SslMethod {
358 unsafe { SslMethod(TLS_client_method()) }
359 }
360
361 #[corresponds(TLS_server_method)]
363 pub fn tls_server() -> SslMethod {
364 unsafe { SslMethod(TLS_server_method()) }
365 }
366
367 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
373 SslMethod(ptr)
374 }
375
376 #[allow(clippy::trivially_copy_pass_by_ref)]
378 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
379 self.0
380 }
381}
382
383unsafe impl Sync for SslMethod {}
384unsafe impl Send for SslMethod {}
385
386bitflags! {
387 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
389 #[repr(transparent)]
390 pub struct SslVerifyMode: i32 {
391 const PEER = ffi::SSL_VERIFY_PEER;
395
396 const NONE = ffi::SSL_VERIFY_NONE;
402
403 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
407 }
408}
409
410#[cfg(boringssl)]
411type SslBitType = c_int;
412#[cfg(not(boringssl))]
413type SslBitType = c_long;
414
415#[cfg(boringssl)]
416type SslTimeTy = u64;
417#[cfg(not(boringssl))]
418type SslTimeTy = c_long;
419
420bitflags! {
421 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
423 #[repr(transparent)]
424 pub struct SslSessionCacheMode: SslBitType {
425 const OFF = ffi::SSL_SESS_CACHE_OFF;
427
428 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
435
436 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
440
441 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
443
444 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
446
447 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
449
450 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
452
453 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
455 }
456}
457
458#[cfg(ossl111)]
459bitflags! {
460 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
462 #[repr(transparent)]
463 pub struct ExtensionContext: c_uint {
464 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
466 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
468 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
470 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
472 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
474 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
476 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
478 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
479 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
481 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
482 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
483 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
484 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
485 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
486 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
487 }
488}
489
490#[derive(Copy, Clone)]
492pub struct SslFiletype(c_int);
493
494impl SslFiletype {
495 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
499
500 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
504
505 pub fn from_raw(raw: c_int) -> SslFiletype {
507 SslFiletype(raw)
508 }
509
510 #[allow(clippy::trivially_copy_pass_by_ref)]
512 pub fn as_raw(&self) -> c_int {
513 self.0
514 }
515}
516
517#[derive(Copy, Clone)]
519pub struct StatusType(c_int);
520
521impl StatusType {
522 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
524
525 pub fn from_raw(raw: c_int) -> StatusType {
527 StatusType(raw)
528 }
529
530 #[allow(clippy::trivially_copy_pass_by_ref)]
532 pub fn as_raw(&self) -> c_int {
533 self.0
534 }
535}
536
537#[derive(Copy, Clone)]
539pub struct NameType(c_int);
540
541impl NameType {
542 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
544
545 pub fn from_raw(raw: c_int) -> StatusType {
547 StatusType(raw)
548 }
549
550 #[allow(clippy::trivially_copy_pass_by_ref)]
552 pub fn as_raw(&self) -> c_int {
553 self.0
554 }
555}
556
557static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
558static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
559static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
560
561fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
562 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
563}
564
565unsafe extern "C" fn free_data_box<T>(
566 _parent: *mut c_void,
567 ptr: *mut c_void,
568 _ad: *mut ffi::CRYPTO_EX_DATA,
569 _idx: c_int,
570 _argl: c_long,
571 _argp: *mut c_void,
572) {
573 if !ptr.is_null() {
574 let _ = Box::<T>::from_raw(ptr as *mut T);
575 }
576}
577
578#[derive(Debug, Copy, Clone, PartialEq, Eq)]
580pub struct SniError(c_int);
581
582impl SniError {
583 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
585
586 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
588
589 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
590}
591
592#[derive(Debug, Copy, Clone, PartialEq, Eq)]
594pub struct SslAlert(c_int);
595
596impl SslAlert {
597 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
599 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
600 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
601}
602
603#[cfg(any(ossl102, libressl261))]
607#[derive(Debug, Copy, Clone, PartialEq, Eq)]
608pub struct AlpnError(c_int);
609
610#[cfg(any(ossl102, libressl261))]
611impl AlpnError {
612 #[cfg(ossl110)]
616 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
617
618 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
620}
621
622#[cfg(ossl111)]
626#[derive(Debug, Copy, Clone, PartialEq, Eq)]
627pub struct ClientHelloResponse(c_int);
628
629#[cfg(ossl111)]
630impl ClientHelloResponse {
631 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
633
634 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
636}
637
638#[derive(Debug, Copy, Clone, PartialEq, Eq)]
640pub struct SslVersion(c_int);
641
642impl SslVersion {
643 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
645
646 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
648
649 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
651
652 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
654
655 #[cfg(any(ossl111, libressl340, boringssl))]
659 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
660
661 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
665
666 #[cfg(any(ossl102, libressl332, boringssl))]
670 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
671}
672
673cfg_if! {
674 if #[cfg(boringssl)] {
675 type SslCacheTy = i64;
676 type SslCacheSize = libc::c_ulong;
677 type MtuTy = u32;
678 type SizeTy = usize;
679 } else {
680 type SslCacheTy = i64;
681 type SslCacheSize = c_long;
682 type MtuTy = c_long;
683 type SizeTy = u32;
684 }
685}
686
687#[corresponds(SSL_select_next_proto)]
698pub fn select_next_proto<'a>(server: &[u8], client: &'a [u8]) -> Option<&'a [u8]> {
699 unsafe {
700 let mut out = ptr::null_mut();
701 let mut outlen = 0;
702 let r = ffi::SSL_select_next_proto(
703 &mut out,
704 &mut outlen,
705 server.as_ptr(),
706 server.len() as c_uint,
707 client.as_ptr(),
708 client.len() as c_uint,
709 );
710 if r == ffi::OPENSSL_NPN_NEGOTIATED {
711 Some(util::from_raw_parts(out as *const u8, outlen as usize))
712 } else {
713 None
714 }
715 }
716}
717
718pub struct SslContextBuilder(SslContext);
720
721impl SslContextBuilder {
722 #[corresponds(SSL_CTX_new)]
724 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
725 unsafe {
726 init();
727 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
728
729 Ok(SslContextBuilder::from_ptr(ctx))
730 }
731 }
732
733 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
739 SslContextBuilder(SslContext::from_ptr(ctx))
740 }
741
742 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
744 self.0.as_ptr()
745 }
746
747 #[corresponds(SSL_CTX_set_verify)]
749 pub fn set_verify(&mut self, mode: SslVerifyMode) {
750 unsafe {
751 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
752 }
753 }
754
755 #[corresponds(SSL_CTX_set_verify)]
762 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
763 where
764 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
765 {
766 unsafe {
767 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
768 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
769 }
770 }
771
772 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
780 pub fn set_servername_callback<F>(&mut self, callback: F)
782 where
783 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
784 {
785 unsafe {
786 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
792 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
793 #[cfg(boringssl)]
794 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
795 #[cfg(not(boringssl))]
796 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
797 self.as_ptr(),
798 Some(raw_sni::<F>),
799 );
800 }
801 }
802
803 #[corresponds(SSL_CTX_set_verify_depth)]
807 pub fn set_verify_depth(&mut self, depth: u32) {
808 unsafe {
809 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
810 }
811 }
812
813 #[corresponds(SSL_CTX_set0_verify_cert_store)]
817 #[cfg(ossl102)]
818 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
819 unsafe {
820 let ptr = cert_store.as_ptr();
821 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
822 mem::forget(cert_store);
823
824 Ok(())
825 }
826 }
827
828 #[corresponds(SSL_CTX_set_cert_store)]
830 pub fn set_cert_store(&mut self, cert_store: X509Store) {
831 unsafe {
832 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
833 mem::forget(cert_store);
834 }
835 }
836
837 #[corresponds(SSL_CTX_set_read_ahead)]
844 pub fn set_read_ahead(&mut self, read_ahead: bool) {
845 unsafe {
846 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
847 }
848 }
849
850 #[corresponds(SSL_CTX_set_mode)]
852 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
853 unsafe {
854 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
855 SslMode::from_bits_retain(bits)
856 }
857 }
858
859 #[corresponds(SSL_CTX_set_tmp_dh)]
861 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
862 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
863 }
864
865 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
872 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
873 where
874 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
875 {
876 unsafe {
877 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
878
879 #[cfg(not(boringssl))]
880 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
881 #[cfg(boringssl)]
882 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
883 }
884 }
885
886 #[corresponds(SSL_CTX_set_tmp_ecdh)]
888 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
889 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
890 }
891
892 #[corresponds(SSL_CTX_set_tmp_ecdh_callback)]
901 #[cfg(all(ossl101, not(ossl110)))]
902 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
903 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
904 where
905 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
906 {
907 unsafe {
908 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
909 ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>));
910 }
911 }
912
913 #[corresponds(SSL_CTX_set_default_verify_paths)]
918 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
919 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
920 }
921
922 #[corresponds(SSL_CTX_load_verify_locations)]
926 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
927 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
928 unsafe {
929 cvt(ffi::SSL_CTX_load_verify_locations(
930 self.as_ptr(),
931 file.as_ptr() as *const _,
932 ptr::null(),
933 ))
934 .map(|_| ())
935 }
936 }
937
938 #[corresponds(SSL_CTX_set_client_CA_list)]
943 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
944 unsafe {
945 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
946 mem::forget(list);
947 }
948 }
949
950 #[corresponds(SSL_CTX_add_client_CA)]
953 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
954 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
955 }
956
957 #[corresponds(SSL_CTX_set_session_id_context)]
966 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
967 unsafe {
968 assert!(sid_ctx.len() <= c_uint::MAX as usize);
969 cvt(ffi::SSL_CTX_set_session_id_context(
970 self.as_ptr(),
971 sid_ctx.as_ptr(),
972 sid_ctx.len() as SizeTy,
973 ))
974 .map(|_| ())
975 }
976 }
977
978 #[corresponds(SSL_CTX_use_certificate_file)]
984 pub fn set_certificate_file<P: AsRef<Path>>(
985 &mut self,
986 file: P,
987 file_type: SslFiletype,
988 ) -> Result<(), ErrorStack> {
989 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
990 unsafe {
991 cvt(ffi::SSL_CTX_use_certificate_file(
992 self.as_ptr(),
993 file.as_ptr() as *const _,
994 file_type.as_raw(),
995 ))
996 .map(|_| ())
997 }
998 }
999
1000 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1006 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1007 &mut self,
1008 file: P,
1009 ) -> Result<(), ErrorStack> {
1010 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1011 unsafe {
1012 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1013 self.as_ptr(),
1014 file.as_ptr() as *const _,
1015 ))
1016 .map(|_| ())
1017 }
1018 }
1019
1020 #[corresponds(SSL_CTX_use_certificate)]
1024 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1025 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1026 }
1027
1028 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1033 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1034 unsafe {
1035 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1036 mem::forget(cert);
1037 Ok(())
1038 }
1039 }
1040
1041 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1043 pub fn set_private_key_file<P: AsRef<Path>>(
1044 &mut self,
1045 file: P,
1046 file_type: SslFiletype,
1047 ) -> Result<(), ErrorStack> {
1048 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1049 unsafe {
1050 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1051 self.as_ptr(),
1052 file.as_ptr() as *const _,
1053 file_type.as_raw(),
1054 ))
1055 .map(|_| ())
1056 }
1057 }
1058
1059 #[corresponds(SSL_CTX_use_PrivateKey)]
1061 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1062 where
1063 T: HasPrivate,
1064 {
1065 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1066 }
1067
1068 #[corresponds(SSL_CTX_set_cipher_list)]
1076 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1077 let cipher_list = CString::new(cipher_list).unwrap();
1078 unsafe {
1079 cvt(ffi::SSL_CTX_set_cipher_list(
1080 self.as_ptr(),
1081 cipher_list.as_ptr() as *const _,
1082 ))
1083 .map(|_| ())
1084 }
1085 }
1086
1087 #[corresponds(SSL_CTX_set_ciphersuites)]
1096 #[cfg(any(ossl111, libressl340))]
1097 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1098 let cipher_list = CString::new(cipher_list).unwrap();
1099 unsafe {
1100 cvt(ffi::SSL_CTX_set_ciphersuites(
1101 self.as_ptr(),
1102 cipher_list.as_ptr() as *const _,
1103 ))
1104 .map(|_| ())
1105 }
1106 }
1107
1108 #[corresponds(SSL_CTX_set_ecdh_auto)]
1112 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1113 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1114 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1115 }
1116
1117 #[corresponds(SSL_CTX_set_options)]
1124 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1125 let bits =
1126 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1127 SslOptions::from_bits_retain(bits)
1128 }
1129
1130 #[corresponds(SSL_CTX_get_options)]
1132 pub fn options(&self) -> SslOptions {
1133 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1134 SslOptions::from_bits_retain(bits)
1135 }
1136
1137 #[corresponds(SSL_CTX_clear_options)]
1139 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1140 let bits =
1141 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1142 SslOptions::from_bits_retain(bits)
1143 }
1144
1145 #[corresponds(SSL_CTX_set_min_proto_version)]
1152 #[cfg(any(ossl110, libressl261, boringssl))]
1153 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1154 unsafe {
1155 cvt(ffi::SSL_CTX_set_min_proto_version(
1156 self.as_ptr(),
1157 version.map_or(0, |v| v.0 as _),
1158 ))
1159 .map(|_| ())
1160 }
1161 }
1162
1163 #[corresponds(SSL_CTX_set_max_proto_version)]
1170 #[cfg(any(ossl110, libressl261, boringssl))]
1171 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1172 unsafe {
1173 cvt(ffi::SSL_CTX_set_max_proto_version(
1174 self.as_ptr(),
1175 version.map_or(0, |v| v.0 as _),
1176 ))
1177 .map(|_| ())
1178 }
1179 }
1180
1181 #[corresponds(SSL_CTX_get_min_proto_version)]
1188 #[cfg(any(ossl110g, libressl270))]
1189 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1190 unsafe {
1191 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1192 if r == 0 {
1193 None
1194 } else {
1195 Some(SslVersion(r))
1196 }
1197 }
1198 }
1199
1200 #[corresponds(SSL_CTX_get_max_proto_version)]
1207 #[cfg(any(ossl110g, libressl270))]
1208 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1209 unsafe {
1210 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1211 if r == 0 {
1212 None
1213 } else {
1214 Some(SslVersion(r))
1215 }
1216 }
1217 }
1218
1219 #[corresponds(SSL_CTX_set_alpn_protos)]
1228 #[cfg(any(ossl102, libressl261, boringssl))]
1229 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1230 unsafe {
1231 assert!(protocols.len() <= c_uint::MAX as usize);
1232 let r = ffi::SSL_CTX_set_alpn_protos(
1233 self.as_ptr(),
1234 protocols.as_ptr(),
1235 protocols.len() as _,
1236 );
1237 if r == 0 {
1239 Ok(())
1240 } else {
1241 Err(ErrorStack::get())
1242 }
1243 }
1244 }
1245
1246 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1248 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1249 unsafe {
1250 let cstr = CString::new(protocols).unwrap();
1251
1252 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1253 if r == 0 {
1255 Ok(())
1256 } else {
1257 Err(ErrorStack::get())
1258 }
1259 }
1260 }
1261
1262 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1275 #[cfg(any(ossl102, libressl261))]
1276 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1277 where
1278 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1279 {
1280 unsafe {
1281 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1282 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1283 self.as_ptr(),
1284 Some(callbacks::raw_alpn_select::<F>),
1285 ptr::null_mut(),
1286 );
1287 }
1288 }
1289
1290 #[corresponds(SSL_CTX_check_private_key)]
1292 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1293 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1294 }
1295
1296 #[corresponds(SSL_CTX_get_cert_store)]
1298 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1299 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1300 }
1301
1302 #[corresponds(SSL_CTX_get_cert_store)]
1304 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1305 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1306 }
1307
1308 #[corresponds(SSL_CTX_get0_param)]
1312 #[cfg(any(ossl102, boringssl, libressl261))]
1313 pub fn verify_param(&self) -> &X509VerifyParamRef {
1314 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1315 }
1316
1317 #[corresponds(SSL_CTX_get0_param)]
1321 #[cfg(any(ossl102, boringssl, libressl261))]
1322 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1323 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1324 }
1325
1326 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1339 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1340 where
1341 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1342 {
1343 unsafe {
1344 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1345 cvt(
1346 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1347 as c_int,
1348 )
1349 .map(|_| ())
1350 }
1351 }
1352
1353 #[corresponds(SSL_CTX_set_psk_client_callback)]
1359 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1360 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1361 where
1362 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1363 + 'static
1364 + Sync
1365 + Send,
1366 {
1367 unsafe {
1368 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1369 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1370 }
1371 }
1372
1373 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1374 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1375 pub fn set_psk_callback<F>(&mut self, callback: F)
1376 where
1377 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1378 + 'static
1379 + Sync
1380 + Send,
1381 {
1382 self.set_psk_client_callback(callback)
1383 }
1384
1385 #[corresponds(SSL_CTX_set_psk_server_callback)]
1391 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1392 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1393 where
1394 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1395 + 'static
1396 + Sync
1397 + Send,
1398 {
1399 unsafe {
1400 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1401 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1402 }
1403 }
1404
1405 #[corresponds(SSL_CTX_sess_set_new_cb)]
1419 pub fn set_new_session_callback<F>(&mut self, callback: F)
1420 where
1421 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1422 {
1423 unsafe {
1424 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1425 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1426 }
1427 }
1428
1429 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1433 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1434 where
1435 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1436 {
1437 unsafe {
1438 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1439 ffi::SSL_CTX_sess_set_remove_cb(
1440 self.as_ptr(),
1441 Some(callbacks::raw_remove_session::<F>),
1442 );
1443 }
1444 }
1445
1446 #[corresponds(SSL_CTX_sess_set_get_cb)]
1457 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1458 where
1459 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1460 {
1461 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1462 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1463 }
1464
1465 #[corresponds(SSL_CTX_set_keylog_callback)]
1473 #[cfg(any(ossl111, boringssl))]
1474 pub fn set_keylog_callback<F>(&mut self, callback: F)
1475 where
1476 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1477 {
1478 unsafe {
1479 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1480 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1481 }
1482 }
1483
1484 #[corresponds(SSL_CTX_set_session_cache_mode)]
1488 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1489 unsafe {
1490 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1491 SslSessionCacheMode::from_bits_retain(bits)
1492 }
1493 }
1494
1495 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1501 #[cfg(ossl111)]
1502 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1503 where
1504 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1505 {
1506 unsafe {
1507 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1508 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1509 self.as_ptr(),
1510 Some(raw_stateless_cookie_generate::<F>),
1511 );
1512 }
1513 }
1514
1515 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1524 #[cfg(ossl111)]
1525 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1526 where
1527 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1528 {
1529 unsafe {
1530 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1531 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1532 self.as_ptr(),
1533 Some(raw_stateless_cookie_verify::<F>),
1534 )
1535 }
1536 }
1537
1538 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1543 #[cfg(not(boringssl))]
1544 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1545 where
1546 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1547 {
1548 unsafe {
1549 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1550 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1551 }
1552 }
1553
1554 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1559 #[cfg(not(boringssl))]
1560 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1561 where
1562 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1563 {
1564 unsafe {
1565 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1566 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1567 }
1568 }
1569
1570 #[corresponds(SSL_CTX_set_ex_data)]
1576 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1577 self.set_ex_data_inner(index, data);
1578 }
1579
1580 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1581 match self.ex_data_mut(index) {
1582 Some(v) => {
1583 *v = data;
1584 (v as *mut T).cast()
1585 }
1586 _ => unsafe {
1587 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1588 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1589 data
1590 },
1591 }
1592 }
1593
1594 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1595 unsafe {
1596 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1597 if data.is_null() {
1598 None
1599 } else {
1600 Some(&mut *data.cast())
1601 }
1602 }
1603 }
1604
1605 #[corresponds(SSL_CTX_add_custom_ext)]
1609 #[cfg(ossl111)]
1610 pub fn add_custom_ext<AddFn, ParseFn, T>(
1611 &mut self,
1612 ext_type: u16,
1613 context: ExtensionContext,
1614 add_cb: AddFn,
1615 parse_cb: ParseFn,
1616 ) -> Result<(), ErrorStack>
1617 where
1618 AddFn: Fn(
1619 &mut SslRef,
1620 ExtensionContext,
1621 Option<(usize, &X509Ref)>,
1622 ) -> Result<Option<T>, SslAlert>
1623 + 'static
1624 + Sync
1625 + Send,
1626 T: AsRef<[u8]> + 'static + Sync + Send,
1627 ParseFn: Fn(
1628 &mut SslRef,
1629 ExtensionContext,
1630 &[u8],
1631 Option<(usize, &X509Ref)>,
1632 ) -> Result<(), SslAlert>
1633 + 'static
1634 + Sync
1635 + Send,
1636 {
1637 let ret = unsafe {
1638 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1639 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1640
1641 ffi::SSL_CTX_add_custom_ext(
1642 self.as_ptr(),
1643 ext_type as c_uint,
1644 context.bits(),
1645 Some(raw_custom_ext_add::<AddFn, T>),
1646 Some(raw_custom_ext_free::<T>),
1647 ptr::null_mut(),
1648 Some(raw_custom_ext_parse::<ParseFn>),
1649 ptr::null_mut(),
1650 )
1651 };
1652 if ret == 1 {
1653 Ok(())
1654 } else {
1655 Err(ErrorStack::get())
1656 }
1657 }
1658
1659 #[corresponds(SSL_CTX_set_max_early_data)]
1665 #[cfg(any(ossl111, libressl340))]
1666 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1667 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1668 Ok(())
1669 } else {
1670 Err(ErrorStack::get())
1671 }
1672 }
1673
1674 #[corresponds(SSL_CTX_set_client_hello_cb)]
1678 #[cfg(ossl111)]
1679 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1680 where
1681 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1682 + 'static
1683 + Sync
1684 + Send,
1685 {
1686 unsafe {
1687 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1688 ffi::SSL_CTX_set_client_hello_cb(
1689 self.as_ptr(),
1690 Some(callbacks::raw_client_hello::<F>),
1691 ptr,
1692 );
1693 }
1694 }
1695
1696 #[corresponds(SSL_CTX_sess_set_cache_size)]
1700 #[allow(clippy::useless_conversion)]
1701 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1702 unsafe {
1703 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1704 }
1705 }
1706
1707 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1711 #[cfg(ossl102)]
1712 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1713 let sigalgs = CString::new(sigalgs).unwrap();
1714 unsafe {
1715 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1716 .map(|_| ())
1717 }
1718 }
1719
1720 #[corresponds(SSL_CTX_set1_groups_list)]
1724 #[cfg(any(ossl111, boringssl, libressl251))]
1725 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1726 let groups = CString::new(groups).unwrap();
1727 unsafe {
1728 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1729 }
1730 }
1731
1732 #[corresponds(SSL_CTX_set_num_tickets)]
1737 #[cfg(ossl111)]
1738 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1739 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1740 }
1741
1742 #[corresponds(SSL_CTX_set_security_level)]
1747 #[cfg(any(ossl110, libressl360))]
1748 pub fn set_security_level(&mut self, level: u32) {
1749 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1750 }
1751
1752 pub fn build(self) -> SslContext {
1754 self.0
1755 }
1756}
1757
1758foreign_type_and_impl_send_sync! {
1759 type CType = ffi::SSL_CTX;
1760 fn drop = ffi::SSL_CTX_free;
1761
1762 pub struct SslContext;
1767
1768 pub struct SslContextRef;
1772}
1773
1774impl Clone for SslContext {
1775 fn clone(&self) -> Self {
1776 (**self).to_owned()
1777 }
1778}
1779
1780impl ToOwned for SslContextRef {
1781 type Owned = SslContext;
1782
1783 fn to_owned(&self) -> Self::Owned {
1784 unsafe {
1785 SSL_CTX_up_ref(self.as_ptr());
1786 SslContext::from_ptr(self.as_ptr())
1787 }
1788 }
1789}
1790
1791impl fmt::Debug for SslContext {
1793 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1794 write!(fmt, "SslContext")
1795 }
1796}
1797
1798impl SslContext {
1799 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1801 SslContextBuilder::new(method)
1802 }
1803
1804 #[corresponds(SSL_CTX_get_ex_new_index)]
1809 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1810 where
1811 T: 'static + Sync + Send,
1812 {
1813 unsafe {
1814 ffi::init();
1815 #[cfg(boringssl)]
1816 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1817 #[cfg(not(boringssl))]
1818 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1819 Ok(Index::from_raw(idx))
1820 }
1821 }
1822
1823 fn cached_ex_index<T>() -> Index<SslContext, T>
1825 where
1826 T: 'static + Sync + Send,
1827 {
1828 unsafe {
1829 let idx = *INDEXES
1830 .lock()
1831 .unwrap_or_else(|e| e.into_inner())
1832 .entry(TypeId::of::<T>())
1833 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1834 Index::from_raw(idx)
1835 }
1836 }
1837}
1838
1839impl SslContextRef {
1840 #[corresponds(SSL_CTX_get0_certificate)]
1844 #[cfg(any(ossl102, libressl270))]
1845 pub fn certificate(&self) -> Option<&X509Ref> {
1846 unsafe {
1847 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1848 X509Ref::from_const_ptr_opt(ptr)
1849 }
1850 }
1851
1852 #[corresponds(SSL_CTX_get0_privatekey)]
1856 #[cfg(any(ossl102, libressl340))]
1857 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1858 unsafe {
1859 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1860 PKeyRef::from_const_ptr_opt(ptr)
1861 }
1862 }
1863
1864 #[corresponds(SSL_CTX_get_cert_store)]
1866 pub fn cert_store(&self) -> &X509StoreRef {
1867 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1868 }
1869
1870 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1872 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1873 unsafe {
1874 let mut chain = ptr::null_mut();
1875 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1876 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1877 }
1878 }
1879
1880 #[corresponds(SSL_CTX_get_ex_data)]
1882 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1883 unsafe {
1884 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1885 if data.is_null() {
1886 None
1887 } else {
1888 Some(&*(data as *const T))
1889 }
1890 }
1891 }
1892
1893 #[corresponds(SSL_CTX_get_max_early_data)]
1897 #[cfg(any(ossl111, libressl340))]
1898 pub fn max_early_data(&self) -> u32 {
1899 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1900 }
1901
1902 #[corresponds(SSL_CTX_add_session)]
1911 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1912 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1913 }
1914
1915 #[corresponds(SSL_CTX_remove_session)]
1924 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1925 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1926 }
1927
1928 #[corresponds(SSL_CTX_sess_get_cache_size)]
1932 #[allow(clippy::unnecessary_cast)]
1933 pub fn session_cache_size(&self) -> i64 {
1934 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1935 }
1936
1937 #[corresponds(SSL_CTX_get_verify_mode)]
1941 pub fn verify_mode(&self) -> SslVerifyMode {
1942 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1943 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1944 }
1945
1946 #[corresponds(SSL_CTX_get_num_tickets)]
1951 #[cfg(ossl111)]
1952 pub fn num_tickets(&self) -> usize {
1953 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1954 }
1955
1956 #[corresponds(SSL_CTX_get_security_level)]
1961 #[cfg(any(ossl110, libressl360))]
1962 pub fn security_level(&self) -> u32 {
1963 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1964 }
1965}
1966
1967pub struct CipherBits {
1969 pub secret: i32,
1971
1972 pub algorithm: i32,
1974}
1975
1976pub struct SslCipher(*mut ffi::SSL_CIPHER);
1978
1979impl ForeignType for SslCipher {
1980 type CType = ffi::SSL_CIPHER;
1981 type Ref = SslCipherRef;
1982
1983 #[inline]
1984 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
1985 SslCipher(ptr)
1986 }
1987
1988 #[inline]
1989 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
1990 self.0
1991 }
1992}
1993
1994impl Stackable for SslCipher {
1995 type StackType = ffi::stack_st_SSL_CIPHER;
1996}
1997
1998impl Deref for SslCipher {
1999 type Target = SslCipherRef;
2000
2001 fn deref(&self) -> &SslCipherRef {
2002 unsafe { SslCipherRef::from_ptr(self.0) }
2003 }
2004}
2005
2006impl DerefMut for SslCipher {
2007 fn deref_mut(&mut self) -> &mut SslCipherRef {
2008 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2009 }
2010}
2011
2012pub struct SslCipherRef(Opaque);
2016
2017impl ForeignTypeRef for SslCipherRef {
2018 type CType = ffi::SSL_CIPHER;
2019}
2020
2021impl SslCipherRef {
2022 #[corresponds(SSL_CIPHER_get_name)]
2024 pub fn name(&self) -> &'static str {
2025 unsafe {
2026 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2027 CStr::from_ptr(ptr).to_str().unwrap()
2028 }
2029 }
2030
2031 #[corresponds(SSL_CIPHER_standard_name)]
2035 #[cfg(ossl111)]
2036 pub fn standard_name(&self) -> Option<&'static str> {
2037 unsafe {
2038 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2039 if ptr.is_null() {
2040 None
2041 } else {
2042 Some(CStr::from_ptr(ptr).to_str().unwrap())
2043 }
2044 }
2045 }
2046
2047 #[corresponds(SSL_CIPHER_get_version)]
2049 pub fn version(&self) -> &'static str {
2050 let version = unsafe {
2051 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2052 CStr::from_ptr(ptr as *const _)
2053 };
2054
2055 str::from_utf8(version.to_bytes()).unwrap()
2056 }
2057
2058 #[corresponds(SSL_CIPHER_get_bits)]
2060 #[allow(clippy::useless_conversion)]
2061 pub fn bits(&self) -> CipherBits {
2062 unsafe {
2063 let mut algo_bits = 0;
2064 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2065 CipherBits {
2066 secret: secret_bits.into(),
2067 algorithm: algo_bits.into(),
2068 }
2069 }
2070 }
2071
2072 #[corresponds(SSL_CIPHER_description)]
2074 pub fn description(&self) -> String {
2075 unsafe {
2076 let mut buf = [0; 128];
2078 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2079 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2080 }
2081 }
2082
2083 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2087 #[cfg(ossl111)]
2088 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2089 unsafe {
2090 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2091 if ptr.is_null() {
2092 None
2093 } else {
2094 Some(MessageDigest::from_ptr(ptr))
2095 }
2096 }
2097 }
2098
2099 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2103 #[cfg(any(ossl110, libressl270))]
2104 pub fn cipher_nid(&self) -> Option<Nid> {
2105 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2106 if n == 0 {
2107 None
2108 } else {
2109 Some(Nid::from_raw(n))
2110 }
2111 }
2112}
2113
2114impl fmt::Debug for SslCipherRef {
2115 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2116 write!(fmt, "{}", self.name())
2117 }
2118}
2119
2120#[derive(Debug)]
2122pub struct CipherLists {
2123 pub suites: Stack<SslCipher>,
2124 pub signalling_suites: Stack<SslCipher>,
2125}
2126
2127foreign_type_and_impl_send_sync! {
2128 type CType = ffi::SSL_SESSION;
2129 fn drop = ffi::SSL_SESSION_free;
2130
2131 pub struct SslSession;
2135
2136 pub struct SslSessionRef;
2140}
2141
2142impl Clone for SslSession {
2143 fn clone(&self) -> SslSession {
2144 SslSessionRef::to_owned(self)
2145 }
2146}
2147
2148impl SslSession {
2149 from_der! {
2150 #[corresponds(d2i_SSL_SESSION)]
2152 from_der,
2153 SslSession,
2154 ffi::d2i_SSL_SESSION
2155 }
2156}
2157
2158impl ToOwned for SslSessionRef {
2159 type Owned = SslSession;
2160
2161 fn to_owned(&self) -> SslSession {
2162 unsafe {
2163 SSL_SESSION_up_ref(self.as_ptr());
2164 SslSession(self.as_ptr())
2165 }
2166 }
2167}
2168
2169impl SslSessionRef {
2170 #[corresponds(SSL_SESSION_get_id)]
2172 pub fn id(&self) -> &[u8] {
2173 unsafe {
2174 let mut len = 0;
2175 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2176 #[allow(clippy::unnecessary_cast)]
2177 util::from_raw_parts(p as *const u8, len as usize)
2178 }
2179 }
2180
2181 #[corresponds(SSL_SESSION_get_master_key)]
2183 pub fn master_key_len(&self) -> usize {
2184 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2185 }
2186
2187 #[corresponds(SSL_SESSION_get_master_key)]
2191 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2192 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2193 }
2194
2195 #[corresponds(SSL_SESSION_get_max_early_data)]
2199 #[cfg(any(ossl111, libressl340))]
2200 pub fn max_early_data(&self) -> u32 {
2201 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2202 }
2203
2204 #[corresponds(SSL_SESSION_get_time)]
2206 #[allow(clippy::useless_conversion)]
2207 pub fn time(&self) -> SslTimeTy {
2208 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2209 }
2210
2211 #[corresponds(SSL_SESSION_get_timeout)]
2215 #[allow(clippy::useless_conversion)]
2216 pub fn timeout(&self) -> i64 {
2217 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2218 }
2219
2220 #[corresponds(SSL_SESSION_get_protocol_version)]
2224 #[cfg(any(ossl110, libressl270))]
2225 pub fn protocol_version(&self) -> SslVersion {
2226 unsafe {
2227 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2228 SslVersion(version)
2229 }
2230 }
2231
2232 to_der! {
2233 #[corresponds(i2d_SSL_SESSION)]
2235 to_der,
2236 ffi::i2d_SSL_SESSION
2237 }
2238}
2239
2240foreign_type_and_impl_send_sync! {
2241 type CType = ffi::SSL;
2242 fn drop = ffi::SSL_free;
2243
2244 pub struct Ssl;
2251
2252 pub struct SslRef;
2256}
2257
2258impl fmt::Debug for Ssl {
2259 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2260 fmt::Debug::fmt(&**self, fmt)
2261 }
2262}
2263
2264impl Ssl {
2265 #[corresponds(SSL_get_ex_new_index)]
2270 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2271 where
2272 T: 'static + Sync + Send,
2273 {
2274 unsafe {
2275 ffi::init();
2276 #[cfg(boringssl)]
2277 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2278 #[cfg(not(boringssl))]
2279 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2280 Ok(Index::from_raw(idx))
2281 }
2282 }
2283
2284 fn cached_ex_index<T>() -> Index<Ssl, T>
2286 where
2287 T: 'static + Sync + Send,
2288 {
2289 unsafe {
2290 let idx = *SSL_INDEXES
2291 .lock()
2292 .unwrap_or_else(|e| e.into_inner())
2293 .entry(TypeId::of::<T>())
2294 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2295 Index::from_raw(idx)
2296 }
2297 }
2298
2299 #[corresponds(SSL_new)]
2301 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2302 let session_ctx_index = try_get_session_ctx_index()?;
2303 unsafe {
2304 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2305 let mut ssl = Ssl::from_ptr(ptr);
2306 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2307
2308 Ok(ssl)
2309 }
2310 }
2311
2312 #[corresponds(SSL_connect)]
2318 #[allow(deprecated)]
2319 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2320 where
2321 S: Read + Write,
2322 {
2323 SslStreamBuilder::new(self, stream).connect()
2324 }
2325
2326 #[corresponds(SSL_accept)]
2333 #[allow(deprecated)]
2334 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2335 where
2336 S: Read + Write,
2337 {
2338 SslStreamBuilder::new(self, stream).accept()
2339 }
2340}
2341
2342impl fmt::Debug for SslRef {
2343 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2344 fmt.debug_struct("Ssl")
2345 .field("state", &self.state_string_long())
2346 .field("verify_result", &self.verify_result())
2347 .finish()
2348 }
2349}
2350
2351impl SslRef {
2352 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2353 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2354 }
2355
2356 fn get_error(&self, ret: c_int) -> ErrorCode {
2357 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2358 }
2359
2360 #[corresponds(SSL_set_connect_state)]
2362 pub fn set_connect_state(&mut self) {
2363 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2364 }
2365
2366 #[corresponds(SSL_set_accept_state)]
2368 pub fn set_accept_state(&mut self) {
2369 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2370 }
2371
2372 #[corresponds(SSL_set_verify)]
2376 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2377 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2378 }
2379
2380 #[corresponds(SSL_set_verify_mode)]
2382 pub fn verify_mode(&self) -> SslVerifyMode {
2383 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2384 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2385 }
2386
2387 #[corresponds(SSL_set_verify)]
2391 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2392 where
2393 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2394 {
2395 unsafe {
2396 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2398 ffi::SSL_set_verify(
2399 self.as_ptr(),
2400 mode.bits() as c_int,
2401 Some(ssl_raw_verify::<F>),
2402 );
2403 }
2404 }
2405
2406 #[corresponds(SSL_set_tmp_dh)]
2410 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2411 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2412 }
2413
2414 #[corresponds(SSL_set_tmp_dh_callback)]
2418 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2419 where
2420 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2421 {
2422 unsafe {
2423 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2425 #[cfg(boringssl)]
2426 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2427 #[cfg(not(boringssl))]
2428 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2429 }
2430 }
2431
2432 #[corresponds(SSL_set_tmp_ecdh)]
2436 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2437 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2438 }
2439
2440 #[corresponds(SSL_set_tmp_ecdh_callback)]
2444 #[cfg(all(ossl101, not(ossl110)))]
2445 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
2446 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
2447 where
2448 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
2449 {
2450 unsafe {
2451 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2453 ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::<F>));
2454 }
2455 }
2456
2457 #[corresponds(SSL_set_ecdh_auto)]
2463 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
2464 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2465 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2466 }
2467
2468 #[corresponds(SSL_set_alpn_protos)]
2474 #[cfg(any(ossl102, libressl261, boringssl))]
2475 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2476 unsafe {
2477 assert!(protocols.len() <= c_uint::MAX as usize);
2478 let r =
2479 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2480 if r == 0 {
2482 Ok(())
2483 } else {
2484 Err(ErrorStack::get())
2485 }
2486 }
2487 }
2488
2489 #[corresponds(SSL_get_current_cipher)]
2491 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2492 unsafe {
2493 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2494
2495 SslCipherRef::from_const_ptr_opt(ptr)
2496 }
2497 }
2498
2499 #[corresponds(SSL_state_string)]
2501 pub fn state_string(&self) -> &'static str {
2502 let state = unsafe {
2503 let ptr = ffi::SSL_state_string(self.as_ptr());
2504 CStr::from_ptr(ptr as *const _)
2505 };
2506
2507 str::from_utf8(state.to_bytes()).unwrap()
2508 }
2509
2510 #[corresponds(SSL_state_string_long)]
2512 pub fn state_string_long(&self) -> &'static str {
2513 let state = unsafe {
2514 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2515 CStr::from_ptr(ptr as *const _)
2516 };
2517
2518 str::from_utf8(state.to_bytes()).unwrap()
2519 }
2520
2521 #[corresponds(SSL_set_tlsext_host_name)]
2525 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2526 let cstr = CString::new(hostname).unwrap();
2527 unsafe {
2528 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2529 .map(|_| ())
2530 }
2531 }
2532
2533 #[corresponds(SSL_get_peer_certificate)]
2535 pub fn peer_certificate(&self) -> Option<X509> {
2536 unsafe {
2537 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2538 X509::from_ptr_opt(ptr)
2539 }
2540 }
2541
2542 #[corresponds(SSL_get_peer_cert_chain)]
2547 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2548 unsafe {
2549 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2550 StackRef::from_const_ptr_opt(ptr)
2551 }
2552 }
2553
2554 #[corresponds(SSL_get0_verified_chain)]
2564 #[cfg(ossl110)]
2565 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2566 unsafe {
2567 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2568 StackRef::from_const_ptr_opt(ptr)
2569 }
2570 }
2571
2572 #[corresponds(SSL_get_certificate)]
2574 pub fn certificate(&self) -> Option<&X509Ref> {
2575 unsafe {
2576 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2577 X509Ref::from_const_ptr_opt(ptr)
2578 }
2579 }
2580
2581 #[corresponds(SSL_get_privatekey)]
2585 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2586 unsafe {
2587 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2588 PKeyRef::from_const_ptr_opt(ptr)
2589 }
2590 }
2591
2592 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2593 pub fn version(&self) -> &str {
2594 self.version_str()
2595 }
2596
2597 #[corresponds(SSL_version)]
2599 pub fn version2(&self) -> Option<SslVersion> {
2600 unsafe {
2601 let r = ffi::SSL_version(self.as_ptr());
2602 if r == 0 {
2603 None
2604 } else {
2605 Some(SslVersion(r))
2606 }
2607 }
2608 }
2609
2610 #[corresponds(SSL_get_version)]
2612 pub fn version_str(&self) -> &'static str {
2613 let version = unsafe {
2614 let ptr = ffi::SSL_get_version(self.as_ptr());
2615 CStr::from_ptr(ptr as *const _)
2616 };
2617
2618 str::from_utf8(version.to_bytes()).unwrap()
2619 }
2620
2621 #[corresponds(SSL_get0_alpn_selected)]
2628 #[cfg(any(ossl102, libressl261, boringssl))]
2629 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2630 unsafe {
2631 let mut data: *const c_uchar = ptr::null();
2632 let mut len: c_uint = 0;
2633 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2636
2637 if data.is_null() {
2638 None
2639 } else {
2640 Some(util::from_raw_parts(data, len as usize))
2641 }
2642 }
2643 }
2644
2645 #[corresponds(SSL_set_tlsext_use_srtp)]
2647 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2648 unsafe {
2649 let cstr = CString::new(protocols).unwrap();
2650
2651 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2652 if r == 0 {
2654 Ok(())
2655 } else {
2656 Err(ErrorStack::get())
2657 }
2658 }
2659 }
2660
2661 #[corresponds(SSL_get_srtp_profiles)]
2665 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2666 unsafe {
2667 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2668
2669 StackRef::from_const_ptr_opt(chain)
2670 }
2671 }
2672
2673 #[corresponds(SSL_get_selected_srtp_profile)]
2677 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2678 unsafe {
2679 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2680
2681 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2682 }
2683 }
2684
2685 #[corresponds(SSL_pending)]
2690 pub fn pending(&self) -> usize {
2691 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2692 }
2693
2694 #[corresponds(SSL_get_servername)]
2707 pub fn servername(&self, type_: NameType) -> Option<&str> {
2709 self.servername_raw(type_)
2710 .and_then(|b| str::from_utf8(b).ok())
2711 }
2712
2713 #[corresponds(SSL_get_servername)]
2721 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2722 unsafe {
2723 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2724 if name.is_null() {
2725 None
2726 } else {
2727 Some(CStr::from_ptr(name as *const _).to_bytes())
2728 }
2729 }
2730 }
2731
2732 #[corresponds(SSL_set_SSL_CTX)]
2736 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2737 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2738 }
2739
2740 #[corresponds(SSL_get_SSL_CTX)]
2742 pub fn ssl_context(&self) -> &SslContextRef {
2743 unsafe {
2744 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2745 SslContextRef::from_ptr(ssl_ctx)
2746 }
2747 }
2748
2749 #[corresponds(SSL_get0_param)]
2753 #[cfg(any(ossl102, boringssl, libressl261))]
2754 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2755 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2756 }
2757
2758 #[corresponds(SSL_get_verify_result)]
2760 pub fn verify_result(&self) -> X509VerifyResult {
2761 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2762 }
2763
2764 #[corresponds(SSL_get_session)]
2766 pub fn session(&self) -> Option<&SslSessionRef> {
2767 unsafe {
2768 let p = ffi::SSL_get_session(self.as_ptr());
2769 SslSessionRef::from_const_ptr_opt(p)
2770 }
2771 }
2772
2773 #[corresponds(SSL_get_client_random)]
2780 #[cfg(any(ossl110, libressl270))]
2781 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2782 unsafe {
2783 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2784 }
2785 }
2786
2787 #[corresponds(SSL_get_server_random)]
2794 #[cfg(any(ossl110, libressl270))]
2795 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2796 unsafe {
2797 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2798 }
2799 }
2800
2801 #[corresponds(SSL_export_keying_material)]
2803 pub fn export_keying_material(
2804 &self,
2805 out: &mut [u8],
2806 label: &str,
2807 context: Option<&[u8]>,
2808 ) -> Result<(), ErrorStack> {
2809 unsafe {
2810 let (context, contextlen, use_context) = match context {
2811 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2812 None => (ptr::null(), 0, 0),
2813 };
2814 cvt(ffi::SSL_export_keying_material(
2815 self.as_ptr(),
2816 out.as_mut_ptr() as *mut c_uchar,
2817 out.len(),
2818 label.as_ptr() as *const c_char,
2819 label.len(),
2820 context,
2821 contextlen,
2822 use_context,
2823 ))
2824 .map(|_| ())
2825 }
2826 }
2827
2828 #[corresponds(SSL_export_keying_material_early)]
2835 #[cfg(ossl111)]
2836 pub fn export_keying_material_early(
2837 &self,
2838 out: &mut [u8],
2839 label: &str,
2840 context: &[u8],
2841 ) -> Result<(), ErrorStack> {
2842 unsafe {
2843 cvt(ffi::SSL_export_keying_material_early(
2844 self.as_ptr(),
2845 out.as_mut_ptr() as *mut c_uchar,
2846 out.len(),
2847 label.as_ptr() as *const c_char,
2848 label.len(),
2849 context.as_ptr() as *const c_uchar,
2850 context.len(),
2851 ))
2852 .map(|_| ())
2853 }
2854 }
2855
2856 #[corresponds(SSL_set_session)]
2867 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2868 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2869 }
2870
2871 #[corresponds(SSL_session_reused)]
2873 pub fn session_reused(&self) -> bool {
2874 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2875 }
2876
2877 #[corresponds(SSL_set_tlsext_status_type)]
2879 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2880 unsafe {
2881 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2882 }
2883 }
2884
2885 #[corresponds(SSL_get_extms_support)]
2889 #[cfg(ossl110)]
2890 pub fn extms_support(&self) -> Option<bool> {
2891 unsafe {
2892 match ffi::SSL_get_extms_support(self.as_ptr()) {
2893 -1 => None,
2894 ret => Some(ret != 0),
2895 }
2896 }
2897 }
2898
2899 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2901 #[cfg(not(boringssl))]
2902 pub fn ocsp_status(&self) -> Option<&[u8]> {
2903 unsafe {
2904 let mut p = ptr::null_mut();
2905 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2906
2907 if len < 0 {
2908 None
2909 } else {
2910 Some(util::from_raw_parts(p as *const u8, len as usize))
2911 }
2912 }
2913 }
2914
2915 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2917 #[cfg(not(boringssl))]
2918 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2919 unsafe {
2920 assert!(response.len() <= c_int::MAX as usize);
2921 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2922 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2923 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2924 self.as_ptr(),
2925 p as *mut c_uchar,
2926 response.len() as c_long,
2927 ) as c_int)
2928 .map(|_| ())
2929 .map_err(|e| {
2930 ffi::OPENSSL_free(p);
2931 e
2932 })
2933 }
2934 }
2935
2936 #[corresponds(SSL_is_server)]
2938 pub fn is_server(&self) -> bool {
2939 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2940 }
2941
2942 #[corresponds(SSL_set_ex_data)]
2948 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2949 match self.ex_data_mut(index) {
2950 Some(v) => *v = data,
2951 None => unsafe {
2952 let data = Box::new(data);
2953 ffi::SSL_set_ex_data(
2954 self.as_ptr(),
2955 index.as_raw(),
2956 Box::into_raw(data) as *mut c_void,
2957 );
2958 },
2959 }
2960 }
2961
2962 #[corresponds(SSL_get_ex_data)]
2964 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2965 unsafe {
2966 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2967 if data.is_null() {
2968 None
2969 } else {
2970 Some(&*(data as *const T))
2971 }
2972 }
2973 }
2974
2975 #[corresponds(SSL_get_ex_data)]
2977 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
2978 unsafe {
2979 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2980 if data.is_null() {
2981 None
2982 } else {
2983 Some(&mut *(data as *mut T))
2984 }
2985 }
2986 }
2987
2988 #[corresponds(SSL_set_max_early_data)]
2992 #[cfg(any(ossl111, libressl340))]
2993 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
2994 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
2995 Ok(())
2996 } else {
2997 Err(ErrorStack::get())
2998 }
2999 }
3000
3001 #[corresponds(SSL_get_max_early_data)]
3005 #[cfg(any(ossl111, libressl340))]
3006 pub fn max_early_data(&self) -> u32 {
3007 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3008 }
3009
3010 #[corresponds(SSL_get_finished)]
3015 pub fn finished(&self, buf: &mut [u8]) -> usize {
3016 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3017 }
3018
3019 #[corresponds(SSL_get_peer_finished)]
3025 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3026 unsafe {
3027 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3028 }
3029 }
3030
3031 #[corresponds(SSL_is_init_finished)]
3033 #[cfg(ossl110)]
3034 pub fn is_init_finished(&self) -> bool {
3035 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3036 }
3037
3038 #[corresponds(SSL_client_hello_isv2)]
3044 #[cfg(ossl111)]
3045 pub fn client_hello_isv2(&self) -> bool {
3046 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3047 }
3048
3049 #[corresponds(SSL_client_hello_get0_legacy_version)]
3055 #[cfg(ossl111)]
3056 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3057 unsafe {
3058 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3059 if version == 0 {
3060 None
3061 } else {
3062 Some(SslVersion(version as c_int))
3063 }
3064 }
3065 }
3066
3067 #[corresponds(SSL_client_hello_get0_random)]
3073 #[cfg(ossl111)]
3074 pub fn client_hello_random(&self) -> Option<&[u8]> {
3075 unsafe {
3076 let mut ptr = ptr::null();
3077 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3078 if len == 0 {
3079 None
3080 } else {
3081 Some(util::from_raw_parts(ptr, len))
3082 }
3083 }
3084 }
3085
3086 #[corresponds(SSL_client_hello_get0_session_id)]
3092 #[cfg(ossl111)]
3093 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3094 unsafe {
3095 let mut ptr = ptr::null();
3096 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3097 if len == 0 {
3098 None
3099 } else {
3100 Some(util::from_raw_parts(ptr, len))
3101 }
3102 }
3103 }
3104
3105 #[corresponds(SSL_client_hello_get0_ciphers)]
3111 #[cfg(ossl111)]
3112 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3113 unsafe {
3114 let mut ptr = ptr::null();
3115 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3116 if len == 0 {
3117 None
3118 } else {
3119 Some(util::from_raw_parts(ptr, len))
3120 }
3121 }
3122 }
3123
3124 #[corresponds(SSL_bytes_to_cipher_list)]
3129 #[cfg(ossl111)]
3130 pub fn bytes_to_cipher_list(
3131 &self,
3132 bytes: &[u8],
3133 isv2format: bool,
3134 ) -> Result<CipherLists, ErrorStack> {
3135 unsafe {
3136 let ptr = bytes.as_ptr();
3137 let len = bytes.len();
3138 let mut sk = ptr::null_mut();
3139 let mut scsvs = ptr::null_mut();
3140 let res = ffi::SSL_bytes_to_cipher_list(
3141 self.as_ptr(),
3142 ptr,
3143 len,
3144 isv2format as c_int,
3145 &mut sk,
3146 &mut scsvs,
3147 );
3148 if res == 1 {
3149 Ok(CipherLists {
3150 suites: Stack::from_ptr(sk),
3151 signalling_suites: Stack::from_ptr(scsvs),
3152 })
3153 } else {
3154 Err(ErrorStack::get())
3155 }
3156 }
3157 }
3158
3159 #[corresponds(SSL_client_hello_get0_compression_methods)]
3165 #[cfg(ossl111)]
3166 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3167 unsafe {
3168 let mut ptr = ptr::null();
3169 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3170 if len == 0 {
3171 None
3172 } else {
3173 Some(util::from_raw_parts(ptr, len))
3174 }
3175 }
3176 }
3177
3178 #[corresponds(SSL_set_mtu)]
3180 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3181 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3182 }
3183
3184 #[corresponds(SSL_get_psk_identity_hint)]
3188 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3189 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3190 unsafe {
3191 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3192 if ptr.is_null() {
3193 None
3194 } else {
3195 Some(CStr::from_ptr(ptr).to_bytes())
3196 }
3197 }
3198 }
3199
3200 #[corresponds(SSL_get_psk_identity)]
3202 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3203 pub fn psk_identity(&self) -> Option<&[u8]> {
3204 unsafe {
3205 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3206 if ptr.is_null() {
3207 None
3208 } else {
3209 Some(CStr::from_ptr(ptr).to_bytes())
3210 }
3211 }
3212 }
3213
3214 #[corresponds(SSL_add0_chain_cert)]
3215 #[cfg(ossl102)]
3216 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3217 unsafe {
3218 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3219 mem::forget(chain);
3220 }
3221 Ok(())
3222 }
3223
3224 #[cfg(not(boringssl))]
3226 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3227 unsafe {
3228 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3229 };
3230 Ok(())
3231 }
3232
3233 #[corresponds(SSL_use_Private_Key_file)]
3235 pub fn set_private_key_file<P: AsRef<Path>>(
3236 &mut self,
3237 path: P,
3238 ssl_file_type: SslFiletype,
3239 ) -> Result<(), ErrorStack> {
3240 let p = path.as_ref().as_os_str().to_str().unwrap();
3241 let key_file = CString::new(p).unwrap();
3242 unsafe {
3243 cvt(ffi::SSL_use_PrivateKey_file(
3244 self.as_ptr(),
3245 key_file.as_ptr(),
3246 ssl_file_type.as_raw(),
3247 ))?;
3248 };
3249 Ok(())
3250 }
3251
3252 #[corresponds(SSL_use_PrivateKey)]
3254 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3255 unsafe {
3256 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3257 };
3258 Ok(())
3259 }
3260
3261 #[corresponds(SSL_use_certificate)]
3263 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3264 unsafe {
3265 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3266 };
3267 Ok(())
3268 }
3269
3270 #[corresponds(SSL_use_certificate_chain_file)]
3276 #[cfg(any(ossl110, libressl332))]
3277 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3278 &mut self,
3279 path: P,
3280 ) -> Result<(), ErrorStack> {
3281 let p = path.as_ref().as_os_str().to_str().unwrap();
3282 let cert_file = CString::new(p).unwrap();
3283 unsafe {
3284 cvt(ffi::SSL_use_certificate_chain_file(
3285 self.as_ptr(),
3286 cert_file.as_ptr(),
3287 ))?;
3288 };
3289 Ok(())
3290 }
3291
3292 #[corresponds(SSL_add_client_CA)]
3294 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3295 unsafe {
3296 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3297 };
3298 Ok(())
3299 }
3300
3301 #[corresponds(SSL_set_client_CA_list)]
3303 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3304 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3305 mem::forget(list);
3306 }
3307
3308 #[corresponds(SSL_set_min_proto_version)]
3315 #[cfg(any(ossl110, libressl261, boringssl))]
3316 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3317 unsafe {
3318 cvt(ffi::SSL_set_min_proto_version(
3319 self.as_ptr(),
3320 version.map_or(0, |v| v.0 as _),
3321 ))
3322 .map(|_| ())
3323 }
3324 }
3325
3326 #[corresponds(SSL_set_max_proto_version)]
3333 #[cfg(any(ossl110, libressl261, boringssl))]
3334 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3335 unsafe {
3336 cvt(ffi::SSL_set_max_proto_version(
3337 self.as_ptr(),
3338 version.map_or(0, |v| v.0 as _),
3339 ))
3340 .map(|_| ())
3341 }
3342 }
3343
3344 #[corresponds(SSL_set_ciphersuites)]
3353 #[cfg(any(ossl111, libressl340))]
3354 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3355 let cipher_list = CString::new(cipher_list).unwrap();
3356 unsafe {
3357 cvt(ffi::SSL_set_ciphersuites(
3358 self.as_ptr(),
3359 cipher_list.as_ptr() as *const _,
3360 ))
3361 .map(|_| ())
3362 }
3363 }
3364
3365 #[corresponds(SSL_set_cipher_list)]
3373 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3374 let cipher_list = CString::new(cipher_list).unwrap();
3375 unsafe {
3376 cvt(ffi::SSL_set_cipher_list(
3377 self.as_ptr(),
3378 cipher_list.as_ptr() as *const _,
3379 ))
3380 .map(|_| ())
3381 }
3382 }
3383
3384 #[corresponds(SSL_set_cert_store)]
3386 #[cfg(ossl102)]
3387 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3388 unsafe {
3389 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3390 mem::forget(cert_store);
3391 Ok(())
3392 }
3393 }
3394
3395 #[corresponds(SSL_set_num_tickets)]
3400 #[cfg(ossl111)]
3401 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3402 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3403 }
3404
3405 #[corresponds(SSL_get_num_tickets)]
3410 #[cfg(ossl111)]
3411 pub fn num_tickets(&self) -> usize {
3412 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3413 }
3414
3415 #[corresponds(SSL_set_security_level)]
3420 #[cfg(any(ossl110, libressl360))]
3421 pub fn set_security_level(&mut self, level: u32) {
3422 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3423 }
3424
3425 #[corresponds(SSL_get_security_level)]
3430 #[cfg(any(ossl110, libressl360))]
3431 pub fn security_level(&self) -> u32 {
3432 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3433 }
3434
3435 #[corresponds(SSL_get_peer_tmp_key)]
3440 #[cfg(ossl300)]
3441 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3442 unsafe {
3443 let mut key = ptr::null_mut();
3444 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3445 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3446 Err(e) => Err(e),
3447 }
3448 }
3449 }
3450
3451 #[corresponds(SSL_get_tmp_key)]
3456 #[cfg(ossl300)]
3457 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3458 unsafe {
3459 let mut key = ptr::null_mut();
3460 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3461 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3462 Err(e) => Err(e),
3463 }
3464 }
3465 }
3466}
3467
3468#[derive(Debug)]
3470pub struct MidHandshakeSslStream<S> {
3471 stream: SslStream<S>,
3472 error: Error,
3473}
3474
3475impl<S> MidHandshakeSslStream<S> {
3476 pub fn get_ref(&self) -> &S {
3478 self.stream.get_ref()
3479 }
3480
3481 pub fn get_mut(&mut self) -> &mut S {
3483 self.stream.get_mut()
3484 }
3485
3486 pub fn ssl(&self) -> &SslRef {
3488 self.stream.ssl()
3489 }
3490
3491 pub fn error(&self) -> &Error {
3493 &self.error
3494 }
3495
3496 pub fn into_error(self) -> Error {
3498 self.error
3499 }
3500}
3501
3502impl<S> MidHandshakeSslStream<S>
3503where
3504 S: Read + Write,
3505{
3506 #[corresponds(SSL_do_handshake)]
3509 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3510 match self.stream.do_handshake() {
3511 Ok(()) => Ok(self.stream),
3512 Err(error) => {
3513 self.error = error;
3514 match self.error.code() {
3515 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3516 Err(HandshakeError::WouldBlock(self))
3517 }
3518 _ => Err(HandshakeError::Failure(self)),
3519 }
3520 }
3521 }
3522 }
3523}
3524
3525pub struct SslStream<S> {
3527 ssl: ManuallyDrop<Ssl>,
3528 method: ManuallyDrop<BioMethod>,
3529 _p: PhantomData<S>,
3530}
3531
3532impl<S> Drop for SslStream<S> {
3533 fn drop(&mut self) {
3534 unsafe {
3536 ManuallyDrop::drop(&mut self.ssl);
3537 ManuallyDrop::drop(&mut self.method);
3538 }
3539 }
3540}
3541
3542impl<S> fmt::Debug for SslStream<S>
3543where
3544 S: fmt::Debug,
3545{
3546 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3547 fmt.debug_struct("SslStream")
3548 .field("stream", &self.get_ref())
3549 .field("ssl", &self.ssl())
3550 .finish()
3551 }
3552}
3553
3554impl<S: Read + Write> SslStream<S> {
3555 #[corresponds(SSL_set_bio)]
3563 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3564 let (bio, method) = bio::new(stream)?;
3565 unsafe {
3566 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3567 }
3568
3569 Ok(SslStream {
3570 ssl: ManuallyDrop::new(ssl),
3571 method: ManuallyDrop::new(method),
3572 _p: PhantomData,
3573 })
3574 }
3575
3576 #[deprecated(
3584 since = "0.10.32",
3585 note = "use Ssl::from_ptr and SslStream::new instead"
3586 )]
3587 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3588 let ssl = Ssl::from_ptr(ssl);
3589 Self::new(ssl, stream).unwrap()
3590 }
3591
3592 #[corresponds(SSL_read_early_data)]
3601 #[cfg(any(ossl111, libressl340))]
3602 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3603 let mut read = 0;
3604 let ret = unsafe {
3605 ffi::SSL_read_early_data(
3606 self.ssl.as_ptr(),
3607 buf.as_ptr() as *mut c_void,
3608 buf.len(),
3609 &mut read,
3610 )
3611 };
3612 match ret {
3613 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3614 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3615 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3616 _ => unreachable!(),
3617 }
3618 }
3619
3620 #[corresponds(SSL_write_early_data)]
3627 #[cfg(any(ossl111, libressl340))]
3628 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3629 let mut written = 0;
3630 let ret = unsafe {
3631 ffi::SSL_write_early_data(
3632 self.ssl.as_ptr(),
3633 buf.as_ptr() as *const c_void,
3634 buf.len(),
3635 &mut written,
3636 )
3637 };
3638 if ret > 0 {
3639 Ok(written)
3640 } else {
3641 Err(self.make_error(ret))
3642 }
3643 }
3644
3645 #[corresponds(SSL_connect)]
3652 pub fn connect(&mut self) -> Result<(), Error> {
3653 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3654 if ret > 0 {
3655 Ok(())
3656 } else {
3657 Err(self.make_error(ret))
3658 }
3659 }
3660
3661 #[corresponds(SSL_accept)]
3668 pub fn accept(&mut self) -> Result<(), Error> {
3669 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3670 if ret > 0 {
3671 Ok(())
3672 } else {
3673 Err(self.make_error(ret))
3674 }
3675 }
3676
3677 #[corresponds(SSL_do_handshake)]
3681 pub fn do_handshake(&mut self) -> Result<(), Error> {
3682 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3683 if ret > 0 {
3684 Ok(())
3685 } else {
3686 Err(self.make_error(ret))
3687 }
3688 }
3689
3690 #[corresponds(SSL_stateless)]
3701 #[cfg(ossl111)]
3702 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3703 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3704 1 => Ok(true),
3705 0 => Ok(false),
3706 -1 => Err(ErrorStack::get()),
3707 _ => unreachable!(),
3708 }
3709 }
3710
3711 #[corresponds(SSL_read_ex)]
3718 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3719 loop {
3720 match self.ssl_read_uninit(buf) {
3721 Ok(n) => return Ok(n),
3722 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3723 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3724 return Ok(0);
3725 }
3726 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3727 Err(e) => {
3728 return Err(e
3729 .into_io_error()
3730 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3731 }
3732 }
3733 }
3734 }
3735
3736 #[corresponds(SSL_read_ex)]
3741 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3742 unsafe {
3744 self.ssl_read_uninit(util::from_raw_parts_mut(
3745 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3746 buf.len(),
3747 ))
3748 }
3749 }
3750
3751 #[corresponds(SSL_read_ex)]
3758 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3759 cfg_if! {
3760 if #[cfg(any(ossl111, libressl350))] {
3761 let mut readbytes = 0;
3762 let ret = unsafe {
3763 ffi::SSL_read_ex(
3764 self.ssl().as_ptr(),
3765 buf.as_mut_ptr().cast(),
3766 buf.len(),
3767 &mut readbytes,
3768 )
3769 };
3770
3771 if ret > 0 {
3772 Ok(readbytes)
3773 } else {
3774 Err(self.make_error(ret))
3775 }
3776 } else {
3777 if buf.is_empty() {
3778 return Ok(0);
3779 }
3780
3781 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3782 let ret = unsafe {
3783 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3784 };
3785 if ret > 0 {
3786 Ok(ret as usize)
3787 } else {
3788 Err(self.make_error(ret))
3789 }
3790 }
3791 }
3792 }
3793
3794 #[corresponds(SSL_write_ex)]
3799 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3800 cfg_if! {
3801 if #[cfg(any(ossl111, libressl350))] {
3802 let mut written = 0;
3803 let ret = unsafe {
3804 ffi::SSL_write_ex(
3805 self.ssl().as_ptr(),
3806 buf.as_ptr().cast(),
3807 buf.len(),
3808 &mut written,
3809 )
3810 };
3811
3812 if ret > 0 {
3813 Ok(written)
3814 } else {
3815 Err(self.make_error(ret))
3816 }
3817 } else {
3818 if buf.is_empty() {
3819 return Ok(0);
3820 }
3821
3822 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3823 let ret = unsafe {
3824 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3825 };
3826 if ret > 0 {
3827 Ok(ret as usize)
3828 } else {
3829 Err(self.make_error(ret))
3830 }
3831 }
3832 }
3833 }
3834
3835 #[corresponds(SSL_peek_ex)]
3837 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3838 cfg_if! {
3839 if #[cfg(any(ossl111, libressl350))] {
3840 let mut readbytes = 0;
3841 let ret = unsafe {
3842 ffi::SSL_peek_ex(
3843 self.ssl().as_ptr(),
3844 buf.as_mut_ptr().cast(),
3845 buf.len(),
3846 &mut readbytes,
3847 )
3848 };
3849
3850 if ret > 0 {
3851 Ok(readbytes)
3852 } else {
3853 Err(self.make_error(ret))
3854 }
3855 } else {
3856 if buf.is_empty() {
3857 return Ok(0);
3858 }
3859
3860 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3861 let ret = unsafe {
3862 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3863 };
3864 if ret > 0 {
3865 Ok(ret as usize)
3866 } else {
3867 Err(self.make_error(ret))
3868 }
3869 }
3870 }
3871 }
3872
3873 #[corresponds(SSL_shutdown)]
3883 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3884 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3885 0 => Ok(ShutdownResult::Sent),
3886 1 => Ok(ShutdownResult::Received),
3887 n => Err(self.make_error(n)),
3888 }
3889 }
3890
3891 #[corresponds(SSL_get_shutdown)]
3893 pub fn get_shutdown(&mut self) -> ShutdownState {
3894 unsafe {
3895 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3896 ShutdownState::from_bits_retain(bits)
3897 }
3898 }
3899
3900 #[corresponds(SSL_set_shutdown)]
3905 pub fn set_shutdown(&mut self, state: ShutdownState) {
3906 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3907 }
3908}
3909
3910impl<S> SslStream<S> {
3911 fn make_error(&mut self, ret: c_int) -> Error {
3912 self.check_panic();
3913
3914 let code = self.ssl.get_error(ret);
3915
3916 let cause = match code {
3917 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3918 ErrorCode::SYSCALL => {
3919 let errs = ErrorStack::get();
3920 if errs.errors().is_empty() {
3921 self.get_bio_error().map(InnerError::Io)
3922 } else {
3923 Some(InnerError::Ssl(errs))
3924 }
3925 }
3926 ErrorCode::ZERO_RETURN => None,
3927 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3928 self.get_bio_error().map(InnerError::Io)
3929 }
3930 _ => None,
3931 };
3932
3933 Error { code, cause }
3934 }
3935
3936 fn check_panic(&mut self) {
3937 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3938 resume_unwind(err)
3939 }
3940 }
3941
3942 fn get_bio_error(&mut self) -> Option<io::Error> {
3943 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3944 }
3945
3946 pub fn get_ref(&self) -> &S {
3948 unsafe {
3949 let bio = self.ssl.get_raw_rbio();
3950 bio::get_ref(bio)
3951 }
3952 }
3953
3954 pub fn get_mut(&mut self) -> &mut S {
3961 unsafe {
3962 let bio = self.ssl.get_raw_rbio();
3963 bio::get_mut(bio)
3964 }
3965 }
3966
3967 pub fn ssl(&self) -> &SslRef {
3969 &self.ssl
3970 }
3971}
3972
3973impl<S: Read + Write> Read for SslStream<S> {
3974 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
3975 unsafe {
3977 self.read_uninit(util::from_raw_parts_mut(
3978 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3979 buf.len(),
3980 ))
3981 }
3982 }
3983}
3984
3985impl<S: Read + Write> Write for SslStream<S> {
3986 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
3987 loop {
3988 match self.ssl_write(buf) {
3989 Ok(n) => return Ok(n),
3990 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3991 Err(e) => {
3992 return Err(e
3993 .into_io_error()
3994 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3995 }
3996 }
3997 }
3998 }
3999
4000 fn flush(&mut self) -> io::Result<()> {
4001 self.get_mut().flush()
4002 }
4003}
4004
4005#[deprecated(
4007 since = "0.10.32",
4008 note = "use the methods directly on Ssl/SslStream instead"
4009)]
4010pub struct SslStreamBuilder<S> {
4011 inner: SslStream<S>,
4012}
4013
4014#[allow(deprecated)]
4015impl<S> SslStreamBuilder<S>
4016where
4017 S: Read + Write,
4018{
4019 pub fn new(ssl: Ssl, stream: S) -> Self {
4021 Self {
4022 inner: SslStream::new(ssl, stream).unwrap(),
4023 }
4024 }
4025
4026 #[corresponds(SSL_stateless)]
4037 #[cfg(ossl111)]
4038 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4039 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4040 1 => Ok(true),
4041 0 => Ok(false),
4042 -1 => Err(ErrorStack::get()),
4043 _ => unreachable!(),
4044 }
4045 }
4046
4047 #[corresponds(SSL_set_connect_state)]
4049 pub fn set_connect_state(&mut self) {
4050 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4051 }
4052
4053 #[corresponds(SSL_set_accept_state)]
4055 pub fn set_accept_state(&mut self) {
4056 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4057 }
4058
4059 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4061 match self.inner.connect() {
4062 Ok(()) => Ok(self.inner),
4063 Err(error) => match error.code() {
4064 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4065 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4066 stream: self.inner,
4067 error,
4068 }))
4069 }
4070 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4071 stream: self.inner,
4072 error,
4073 })),
4074 },
4075 }
4076 }
4077
4078 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4080 match self.inner.accept() {
4081 Ok(()) => Ok(self.inner),
4082 Err(error) => match error.code() {
4083 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4084 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4085 stream: self.inner,
4086 error,
4087 }))
4088 }
4089 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4090 stream: self.inner,
4091 error,
4092 })),
4093 },
4094 }
4095 }
4096
4097 #[corresponds(SSL_do_handshake)]
4101 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4102 match self.inner.do_handshake() {
4103 Ok(()) => Ok(self.inner),
4104 Err(error) => match error.code() {
4105 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4106 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4107 stream: self.inner,
4108 error,
4109 }))
4110 }
4111 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4112 stream: self.inner,
4113 error,
4114 })),
4115 },
4116 }
4117 }
4118
4119 #[corresponds(SSL_read_early_data)]
4129 #[cfg(any(ossl111, libressl340))]
4130 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4131 self.inner.read_early_data(buf)
4132 }
4133
4134 #[corresponds(SSL_write_early_data)]
4141 #[cfg(any(ossl111, libressl340))]
4142 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4143 self.inner.write_early_data(buf)
4144 }
4145}
4146
4147#[allow(deprecated)]
4148impl<S> SslStreamBuilder<S> {
4149 pub fn get_ref(&self) -> &S {
4151 unsafe {
4152 let bio = self.inner.ssl.get_raw_rbio();
4153 bio::get_ref(bio)
4154 }
4155 }
4156
4157 pub fn get_mut(&mut self) -> &mut S {
4164 unsafe {
4165 let bio = self.inner.ssl.get_raw_rbio();
4166 bio::get_mut(bio)
4167 }
4168 }
4169
4170 pub fn ssl(&self) -> &SslRef {
4172 &self.inner.ssl
4173 }
4174
4175 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4183 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4184 unsafe {
4185 let bio = self.inner.ssl.get_raw_rbio();
4186 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4187 }
4188 }
4189}
4190
4191#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4193pub enum ShutdownResult {
4194 Sent,
4196
4197 Received,
4199}
4200
4201bitflags! {
4202 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4204 #[repr(transparent)]
4205 pub struct ShutdownState: c_int {
4206 const SENT = ffi::SSL_SENT_SHUTDOWN;
4208 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4210 }
4211}
4212
4213cfg_if! {
4214 if #[cfg(any(boringssl, ossl110, libressl273))] {
4215 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4216 } else {
4217 #[allow(bad_style)]
4218 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4219 ffi::CRYPTO_add_lock(
4220 &mut (*ssl).references,
4221 1,
4222 ffi::CRYPTO_LOCK_SSL_CTX,
4223 "mod.rs\0".as_ptr() as *const _,
4224 line!() as c_int,
4225 );
4226 0
4227 }
4228
4229 #[allow(bad_style)]
4230 pub unsafe fn SSL_SESSION_get_master_key(
4231 session: *const ffi::SSL_SESSION,
4232 out: *mut c_uchar,
4233 mut outlen: usize,
4234 ) -> usize {
4235 if outlen == 0 {
4236 return (*session).master_key_length as usize;
4237 }
4238 if outlen > (*session).master_key_length as usize {
4239 outlen = (*session).master_key_length as usize;
4240 }
4241 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4242 outlen
4243 }
4244
4245 #[allow(bad_style)]
4246 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4247 (*s).server
4248 }
4249
4250 #[allow(bad_style)]
4251 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4252 ffi::CRYPTO_add_lock(
4253 &mut (*ses).references,
4254 1,
4255 ffi::CRYPTO_LOCK_SSL_CTX,
4256 "mod.rs\0".as_ptr() as *const _,
4257 line!() as c_int,
4258 );
4259 0
4260 }
4261 }
4262}
4263
4264cfg_if! {
4265 if #[cfg(ossl300)] {
4266 use ffi::SSL_get1_peer_certificate;
4267 } else {
4268 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4269 }
4270}
4271cfg_if! {
4272 if #[cfg(any(boringssl, ossl110, libressl291))] {
4273 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method};
4274 } else {
4275 use ffi::{
4276 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
4277 SSLv23_server_method as TLS_server_method,
4278 };
4279 }
4280}
4281cfg_if! {
4282 if #[cfg(ossl110)] {
4283 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4284 ffi::CRYPTO_get_ex_new_index(
4285 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4286 0,
4287 ptr::null_mut(),
4288 None,
4289 None,
4290 Some(f),
4291 )
4292 }
4293
4294 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4295 ffi::CRYPTO_get_ex_new_index(
4296 ffi::CRYPTO_EX_INDEX_SSL,
4297 0,
4298 ptr::null_mut(),
4299 None,
4300 None,
4301 Some(f),
4302 )
4303 }
4304 } else {
4305 use std::sync::Once;
4306
4307 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4308 static ONCE: Once = Once::new();
4310 ONCE.call_once(|| {
4311 cfg_if! {
4312 if #[cfg(not(boringssl))] {
4313 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4314 } else {
4315 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4316 }
4317 }
4318 });
4319
4320 cfg_if! {
4321 if #[cfg(not(boringssl))] {
4322 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4323 } else {
4324 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4325 }
4326 }
4327 }
4328
4329 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4330 static ONCE: Once = Once::new();
4332 ONCE.call_once(|| {
4333 #[cfg(not(boringssl))]
4334 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4335 #[cfg(boringssl)]
4336 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4337 });
4338
4339 #[cfg(not(boringssl))]
4340 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4341 #[cfg(boringssl)]
4342 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4343 }
4344 }
4345}