1#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63#[cfg(all(ossl102, 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, libressl))]
71use crate::nid::Nid;
72use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
73#[cfg(ossl300)]
74use crate::pkey::{PKey, Public};
75#[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
76use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
77use crate::ssl::bio::BioMethod;
78use crate::ssl::callbacks::*;
79use crate::ssl::error::InnerError;
80use crate::stack::{Stack, StackRef, Stackable};
81use crate::util;
82use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
83use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
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(any(boringssl, awslc))] {
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(any(boringssl, awslc)))]
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(any(boringssl, awslc)))]
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(any(boringssl, awslc)))]
177 const NO_SESSION_RESUMPTION_ON_RENEGOTIATION =
178 ffi::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION as SslOptionsRepr;
179
180 #[cfg(not(any(boringssl, awslc)))]
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, libressl, awslc))]
226 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
227
228 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
230
231 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
233
234 #[cfg(ossl102)]
250 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
251
252 #[cfg(any(boringssl, ossl110h, awslc))]
256 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
257
258 #[cfg(ossl111)]
263 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
264
265 #[cfg(ossl111)]
277 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
278 }
279}
280
281bitflags! {
282 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
284 #[repr(transparent)]
285 pub struct SslMode: SslBitType {
286 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
292
293 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
296
297 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
307
308 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
314
315 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
319
320 #[cfg(not(libressl))]
328 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
329 }
330}
331
332#[derive(Copy, Clone)]
334pub struct SslMethod(*const ffi::SSL_METHOD);
335
336impl SslMethod {
337 #[corresponds(TLS_method)]
339 pub fn tls() -> SslMethod {
340 unsafe { SslMethod(TLS_method()) }
341 }
342
343 #[corresponds(DTLS_method)]
345 pub fn dtls() -> SslMethod {
346 unsafe { SslMethod(DTLS_method()) }
347 }
348
349 #[corresponds(TLS_client_method)]
351 pub fn tls_client() -> SslMethod {
352 unsafe { SslMethod(TLS_client_method()) }
353 }
354
355 #[corresponds(TLS_server_method)]
357 pub fn tls_server() -> SslMethod {
358 unsafe { SslMethod(TLS_server_method()) }
359 }
360
361 #[corresponds(DTLS_client_method)]
363 #[cfg(any(boringssl, ossl110, libressl, awslc))]
364 pub fn dtls_client() -> SslMethod {
365 unsafe { SslMethod(DTLS_client_method()) }
366 }
367
368 #[corresponds(DTLS_server_method)]
370 #[cfg(any(boringssl, ossl110, libressl, awslc))]
371 pub fn dtls_server() -> SslMethod {
372 unsafe { SslMethod(DTLS_server_method()) }
373 }
374
375 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
381 SslMethod(ptr)
382 }
383
384 #[allow(clippy::trivially_copy_pass_by_ref)]
386 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
387 self.0
388 }
389}
390
391unsafe impl Sync for SslMethod {}
392unsafe impl Send for SslMethod {}
393
394bitflags! {
395 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
397 #[repr(transparent)]
398 pub struct SslVerifyMode: i32 {
399 const PEER = ffi::SSL_VERIFY_PEER;
403
404 const NONE = ffi::SSL_VERIFY_NONE;
410
411 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
415 }
416}
417
418#[cfg(any(boringssl, awslc))]
419type SslBitType = c_int;
420#[cfg(not(any(boringssl, awslc)))]
421type SslBitType = c_long;
422
423#[cfg(any(boringssl, awslc))]
424type SslTimeTy = u64;
425#[cfg(not(any(boringssl, awslc)))]
426type SslTimeTy = c_long;
427
428bitflags! {
429 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
431 #[repr(transparent)]
432 pub struct SslSessionCacheMode: SslBitType {
433 const OFF = ffi::SSL_SESS_CACHE_OFF;
435
436 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
443
444 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
448
449 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
451
452 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
454
455 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
457
458 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
460
461 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
463 }
464}
465
466#[cfg(ossl111)]
467bitflags! {
468 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
470 #[repr(transparent)]
471 pub struct ExtensionContext: c_uint {
472 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
474 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
476 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
478 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
480 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
482 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
484 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
486 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
487 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
489 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
490 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
491 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
492 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
493 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
494 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
495 }
496}
497
498#[derive(Copy, Clone)]
500pub struct SslFiletype(c_int);
501
502impl SslFiletype {
503 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
507
508 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
512
513 pub fn from_raw(raw: c_int) -> SslFiletype {
515 SslFiletype(raw)
516 }
517
518 #[allow(clippy::trivially_copy_pass_by_ref)]
520 pub fn as_raw(&self) -> c_int {
521 self.0
522 }
523}
524
525#[derive(Copy, Clone)]
527pub struct StatusType(c_int);
528
529impl StatusType {
530 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
532
533 pub fn from_raw(raw: c_int) -> StatusType {
535 StatusType(raw)
536 }
537
538 #[allow(clippy::trivially_copy_pass_by_ref)]
540 pub fn as_raw(&self) -> c_int {
541 self.0
542 }
543}
544
545#[derive(Copy, Clone)]
547pub struct NameType(c_int);
548
549impl NameType {
550 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
552
553 pub fn from_raw(raw: c_int) -> StatusType {
555 StatusType(raw)
556 }
557
558 #[allow(clippy::trivially_copy_pass_by_ref)]
560 pub fn as_raw(&self) -> c_int {
561 self.0
562 }
563}
564
565static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
566static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
567static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
568
569fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
570 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
571}
572
573unsafe extern "C" fn free_data_box<T>(
574 _parent: *mut c_void,
575 ptr: *mut c_void,
576 _ad: *mut ffi::CRYPTO_EX_DATA,
577 _idx: c_int,
578 _argl: c_long,
579 _argp: *mut c_void,
580) {
581 if !ptr.is_null() {
582 let _ = Box::<T>::from_raw(ptr as *mut T);
583 }
584}
585
586#[derive(Debug, Copy, Clone, PartialEq, Eq)]
588pub struct SniError(c_int);
589
590impl SniError {
591 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
593
594 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
596
597 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
598}
599
600#[derive(Debug, Copy, Clone, PartialEq, Eq)]
602pub struct SslAlert(c_int);
603
604impl SslAlert {
605 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
607 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
608 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
609}
610
611#[derive(Debug, Copy, Clone, PartialEq, Eq)]
615pub struct AlpnError(c_int);
616
617impl AlpnError {
618 #[cfg(any(ossl110, libressl, boringssl, awslc))]
622 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
623
624 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
626}
627
628#[cfg(ossl111)]
632#[derive(Debug, Copy, Clone, PartialEq, Eq)]
633pub struct ClientHelloResponse(c_int);
634
635#[cfg(ossl111)]
636impl ClientHelloResponse {
637 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
639
640 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
642}
643
644#[derive(Debug, Copy, Clone, PartialEq, Eq)]
646pub struct SslVersion(c_int);
647
648impl SslVersion {
649 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
651
652 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
654
655 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
657
658 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
660
661 #[cfg(any(ossl111, libressl, boringssl, awslc))]
665 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
666
667 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
671
672 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
676}
677
678cfg_if! {
679 if #[cfg(any(boringssl, awslc))] {
680 type SslCacheTy = i64;
681 type SslCacheSize = libc::c_ulong;
682 type MtuTy = u32;
683 type SizeTy = usize;
684 } else {
685 type SslCacheTy = i64;
686 type SslCacheSize = c_long;
687 type MtuTy = c_long;
688 type SizeTy = u32;
689 }
690}
691
692#[corresponds(SSL_select_next_proto)]
703pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
704 unsafe {
705 let mut out = ptr::null_mut();
706 let mut outlen = 0;
707 let r = ffi::SSL_select_next_proto(
708 &mut out,
709 &mut outlen,
710 server.as_ptr(),
711 server.len() as c_uint,
712 client.as_ptr(),
713 client.len() as c_uint,
714 );
715 if r == ffi::OPENSSL_NPN_NEGOTIATED {
716 Some(util::from_raw_parts(out as *const u8, outlen as usize))
717 } else {
718 None
719 }
720 }
721}
722
723pub struct SslContextBuilder(SslContext);
725
726impl SslContextBuilder {
727 #[corresponds(SSL_CTX_new)]
729 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
730 unsafe {
731 init();
732 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
733
734 Ok(SslContextBuilder::from_ptr(ctx))
735 }
736 }
737
738 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
744 SslContextBuilder(SslContext::from_ptr(ctx))
745 }
746
747 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
749 self.0.as_ptr()
750 }
751
752 #[corresponds(SSL_CTX_set_verify)]
754 pub fn set_verify(&mut self, mode: SslVerifyMode) {
755 unsafe {
756 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
757 }
758 }
759
760 #[corresponds(SSL_CTX_set_verify)]
767 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
768 where
769 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
770 {
771 unsafe {
772 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
773 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
774 }
775 }
776
777 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
785 pub fn set_servername_callback<F>(&mut self, callback: F)
787 where
788 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
789 {
790 unsafe {
791 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
797 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
798 #[cfg(any(boringssl, awslc))]
799 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
800 #[cfg(not(any(boringssl, awslc)))]
801 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
802 self.as_ptr(),
803 Some(raw_sni::<F>),
804 );
805 }
806 }
807
808 #[corresponds(SSL_CTX_set_verify_depth)]
812 pub fn set_verify_depth(&mut self, depth: u32) {
813 unsafe {
814 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
815 }
816 }
817
818 #[corresponds(SSL_CTX_set0_verify_cert_store)]
822 #[cfg(ossl102)]
823 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
824 unsafe {
825 let ptr = cert_store.as_ptr();
826 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
827 mem::forget(cert_store);
828
829 Ok(())
830 }
831 }
832
833 #[corresponds(SSL_CTX_set_cert_store)]
835 pub fn set_cert_store(&mut self, cert_store: X509Store) {
836 unsafe {
837 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
838 mem::forget(cert_store);
839 }
840 }
841
842 #[corresponds(SSL_CTX_set_read_ahead)]
849 pub fn set_read_ahead(&mut self, read_ahead: bool) {
850 unsafe {
851 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
852 }
853 }
854
855 #[corresponds(SSL_CTX_set_mode)]
857 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
858 unsafe {
859 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
860 SslMode::from_bits_retain(bits)
861 }
862 }
863
864 #[corresponds(SSL_CTX_set_tmp_dh)]
866 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
867 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
868 }
869
870 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
877 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
878 where
879 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
880 {
881 unsafe {
882 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
883
884 #[cfg(not(any(boringssl, awslc)))]
885 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
886 #[cfg(any(boringssl, awslc))]
887 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
888 }
889 }
890
891 #[corresponds(SSL_CTX_set_tmp_ecdh)]
893 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
894 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
895 }
896
897 #[corresponds(SSL_CTX_set_tmp_ecdh_callback)]
906 #[cfg(all(ossl102, not(ossl110)))]
907 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
908 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
909 where
910 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
911 {
912 unsafe {
913 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
914 ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>));
915 }
916 }
917
918 #[corresponds(SSL_CTX_set_default_verify_paths)]
923 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
924 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
925 }
926
927 #[corresponds(SSL_CTX_load_verify_locations)]
931 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
932 self.load_verify_locations(Some(file.as_ref()), None)
933 }
934
935 #[corresponds(SSL_CTX_load_verify_locations)]
937 pub fn load_verify_locations(
938 &mut self,
939 ca_file: Option<&Path>,
940 ca_path: Option<&Path>,
941 ) -> Result<(), ErrorStack> {
942 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
943 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
944 unsafe {
945 cvt(ffi::SSL_CTX_load_verify_locations(
946 self.as_ptr(),
947 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
948 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
949 ))
950 .map(|_| ())
951 }
952 }
953
954 #[corresponds(SSL_CTX_set_client_CA_list)]
959 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
960 unsafe {
961 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
962 mem::forget(list);
963 }
964 }
965
966 #[corresponds(SSL_CTX_add_client_CA)]
969 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
970 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
971 }
972
973 #[corresponds(SSL_CTX_set_session_id_context)]
982 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
983 unsafe {
984 assert!(sid_ctx.len() <= c_uint::MAX as usize);
985 cvt(ffi::SSL_CTX_set_session_id_context(
986 self.as_ptr(),
987 sid_ctx.as_ptr(),
988 sid_ctx.len() as SizeTy,
989 ))
990 .map(|_| ())
991 }
992 }
993
994 #[corresponds(SSL_CTX_use_certificate_file)]
1000 pub fn set_certificate_file<P: AsRef<Path>>(
1001 &mut self,
1002 file: P,
1003 file_type: SslFiletype,
1004 ) -> Result<(), ErrorStack> {
1005 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1006 unsafe {
1007 cvt(ffi::SSL_CTX_use_certificate_file(
1008 self.as_ptr(),
1009 file.as_ptr() as *const _,
1010 file_type.as_raw(),
1011 ))
1012 .map(|_| ())
1013 }
1014 }
1015
1016 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1022 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1023 &mut self,
1024 file: P,
1025 ) -> Result<(), ErrorStack> {
1026 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1027 unsafe {
1028 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1029 self.as_ptr(),
1030 file.as_ptr() as *const _,
1031 ))
1032 .map(|_| ())
1033 }
1034 }
1035
1036 #[corresponds(SSL_CTX_use_certificate)]
1040 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1041 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1042 }
1043
1044 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1049 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1050 unsafe {
1051 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1052 mem::forget(cert);
1053 Ok(())
1054 }
1055 }
1056
1057 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1059 pub fn set_private_key_file<P: AsRef<Path>>(
1060 &mut self,
1061 file: P,
1062 file_type: SslFiletype,
1063 ) -> Result<(), ErrorStack> {
1064 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1065 unsafe {
1066 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1067 self.as_ptr(),
1068 file.as_ptr() as *const _,
1069 file_type.as_raw(),
1070 ))
1071 .map(|_| ())
1072 }
1073 }
1074
1075 #[corresponds(SSL_CTX_use_PrivateKey)]
1077 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1078 where
1079 T: HasPrivate,
1080 {
1081 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1082 }
1083
1084 #[corresponds(SSL_CTX_set_cipher_list)]
1092 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1093 let cipher_list = CString::new(cipher_list).unwrap();
1094 unsafe {
1095 cvt(ffi::SSL_CTX_set_cipher_list(
1096 self.as_ptr(),
1097 cipher_list.as_ptr() as *const _,
1098 ))
1099 .map(|_| ())
1100 }
1101 }
1102
1103 #[corresponds(SSL_CTX_set_ciphersuites)]
1112 #[cfg(any(ossl111, libressl))]
1113 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1114 let cipher_list = CString::new(cipher_list).unwrap();
1115 unsafe {
1116 cvt(ffi::SSL_CTX_set_ciphersuites(
1117 self.as_ptr(),
1118 cipher_list.as_ptr() as *const _,
1119 ))
1120 .map(|_| ())
1121 }
1122 }
1123
1124 #[corresponds(SSL_CTX_set_ecdh_auto)]
1128 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1129 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1130 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1131 }
1132
1133 #[corresponds(SSL_CTX_set_options)]
1140 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1141 let bits =
1142 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1143 SslOptions::from_bits_retain(bits)
1144 }
1145
1146 #[corresponds(SSL_CTX_get_options)]
1148 pub fn options(&self) -> SslOptions {
1149 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1150 SslOptions::from_bits_retain(bits)
1151 }
1152
1153 #[corresponds(SSL_CTX_clear_options)]
1155 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1156 let bits =
1157 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1158 SslOptions::from_bits_retain(bits)
1159 }
1160
1161 #[corresponds(SSL_CTX_set_min_proto_version)]
1168 #[cfg(any(ossl110, libressl, boringssl, awslc))]
1169 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1170 unsafe {
1171 cvt(ffi::SSL_CTX_set_min_proto_version(
1172 self.as_ptr(),
1173 version.map_or(0, |v| v.0 as _),
1174 ))
1175 .map(|_| ())
1176 }
1177 }
1178
1179 #[corresponds(SSL_CTX_set_max_proto_version)]
1186 #[cfg(any(ossl110, libressl, boringssl, awslc))]
1187 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1188 unsafe {
1189 cvt(ffi::SSL_CTX_set_max_proto_version(
1190 self.as_ptr(),
1191 version.map_or(0, |v| v.0 as _),
1192 ))
1193 .map(|_| ())
1194 }
1195 }
1196
1197 #[corresponds(SSL_CTX_get_min_proto_version)]
1204 #[cfg(any(ossl110g, libressl))]
1205 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1206 unsafe {
1207 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1208 if r == 0 {
1209 None
1210 } else {
1211 Some(SslVersion(r))
1212 }
1213 }
1214 }
1215
1216 #[corresponds(SSL_CTX_get_max_proto_version)]
1223 #[cfg(any(ossl110g, libressl))]
1224 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1225 unsafe {
1226 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1227 if r == 0 {
1228 None
1229 } else {
1230 Some(SslVersion(r))
1231 }
1232 }
1233 }
1234
1235 #[corresponds(SSL_CTX_set_alpn_protos)]
1244 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1245 unsafe {
1246 assert!(protocols.len() <= c_uint::MAX as usize);
1247 let r = ffi::SSL_CTX_set_alpn_protos(
1248 self.as_ptr(),
1249 protocols.as_ptr(),
1250 protocols.len() as _,
1251 );
1252 if r == 0 {
1254 Ok(())
1255 } else {
1256 Err(ErrorStack::get())
1257 }
1258 }
1259 }
1260
1261 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
1263 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1264 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1265 unsafe {
1266 let cstr = CString::new(protocols).unwrap();
1267
1268 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1269 if r == 0 {
1271 Ok(())
1272 } else {
1273 Err(ErrorStack::get())
1274 }
1275 }
1276 }
1277
1278 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1291 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1292 where
1293 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1294 {
1295 unsafe {
1296 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1297 #[cfg(not(any(boringssl, awslc)))]
1298 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1299 self.as_ptr(),
1300 Some(callbacks::raw_alpn_select::<F>),
1301 ptr::null_mut(),
1302 );
1303 #[cfg(any(boringssl, awslc))]
1304 ffi::SSL_CTX_set_alpn_select_cb(
1305 self.as_ptr(),
1306 Some(callbacks::raw_alpn_select::<F>),
1307 ptr::null_mut(),
1308 );
1309 }
1310 }
1311
1312 #[corresponds(SSL_CTX_check_private_key)]
1314 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1315 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1316 }
1317
1318 #[corresponds(SSL_CTX_get_cert_store)]
1320 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1321 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1322 }
1323
1324 #[corresponds(SSL_CTX_get_cert_store)]
1326 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1327 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1328 }
1329
1330 #[corresponds(SSL_CTX_get0_param)]
1334 pub fn verify_param(&self) -> &X509VerifyParamRef {
1335 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1336 }
1337
1338 #[corresponds(SSL_CTX_get0_param)]
1342 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1343 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1344 }
1345
1346 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1359 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1360 where
1361 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1362 {
1363 unsafe {
1364 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1365 cvt(
1366 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1367 as c_int,
1368 )
1369 .map(|_| ())
1370 }
1371 }
1372
1373 #[corresponds(SSL_CTX_set_psk_client_callback)]
1379 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1380 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1381 where
1382 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1383 + 'static
1384 + Sync
1385 + Send,
1386 {
1387 unsafe {
1388 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1389 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1390 }
1391 }
1392
1393 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1394 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1395 pub fn set_psk_callback<F>(&mut self, callback: F)
1396 where
1397 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1398 + 'static
1399 + Sync
1400 + Send,
1401 {
1402 self.set_psk_client_callback(callback)
1403 }
1404
1405 #[corresponds(SSL_CTX_set_psk_server_callback)]
1411 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1412 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1413 where
1414 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1415 + 'static
1416 + Sync
1417 + Send,
1418 {
1419 unsafe {
1420 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1421 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1422 }
1423 }
1424
1425 #[corresponds(SSL_CTX_sess_set_new_cb)]
1439 pub fn set_new_session_callback<F>(&mut self, callback: F)
1440 where
1441 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1442 {
1443 unsafe {
1444 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1445 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1446 }
1447 }
1448
1449 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1453 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1454 where
1455 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1456 {
1457 unsafe {
1458 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1459 ffi::SSL_CTX_sess_set_remove_cb(
1460 self.as_ptr(),
1461 Some(callbacks::raw_remove_session::<F>),
1462 );
1463 }
1464 }
1465
1466 #[corresponds(SSL_CTX_sess_set_get_cb)]
1477 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1478 where
1479 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1480 {
1481 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1482 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1483 }
1484
1485 #[corresponds(SSL_CTX_set_keylog_callback)]
1493 #[cfg(any(ossl111, boringssl, awslc))]
1494 pub fn set_keylog_callback<F>(&mut self, callback: F)
1495 where
1496 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1497 {
1498 unsafe {
1499 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1500 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1501 }
1502 }
1503
1504 #[corresponds(SSL_CTX_set_session_cache_mode)]
1508 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1509 unsafe {
1510 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1511 SslSessionCacheMode::from_bits_retain(bits)
1512 }
1513 }
1514
1515 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1521 #[cfg(ossl111)]
1522 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1523 where
1524 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1525 {
1526 unsafe {
1527 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1528 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1529 self.as_ptr(),
1530 Some(raw_stateless_cookie_generate::<F>),
1531 );
1532 }
1533 }
1534
1535 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1544 #[cfg(ossl111)]
1545 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1546 where
1547 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1548 {
1549 unsafe {
1550 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1551 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1552 self.as_ptr(),
1553 Some(raw_stateless_cookie_verify::<F>),
1554 )
1555 }
1556 }
1557
1558 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1563 #[cfg(not(any(boringssl, awslc)))]
1564 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1565 where
1566 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1567 {
1568 unsafe {
1569 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1570 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1571 }
1572 }
1573
1574 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1579 #[cfg(not(any(boringssl, awslc)))]
1580 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1581 where
1582 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1583 {
1584 unsafe {
1585 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1586 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1587 }
1588 }
1589
1590 #[corresponds(SSL_CTX_set_ex_data)]
1596 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1597 self.set_ex_data_inner(index, data);
1598 }
1599
1600 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1601 match self.ex_data_mut(index) {
1602 Some(v) => {
1603 *v = data;
1604 (v as *mut T).cast()
1605 }
1606 _ => unsafe {
1607 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1608 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1609 data
1610 },
1611 }
1612 }
1613
1614 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1615 unsafe {
1616 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1617 if data.is_null() {
1618 None
1619 } else {
1620 Some(&mut *data.cast())
1621 }
1622 }
1623 }
1624
1625 #[corresponds(SSL_CTX_add_custom_ext)]
1629 #[cfg(ossl111)]
1630 pub fn add_custom_ext<AddFn, ParseFn, T>(
1631 &mut self,
1632 ext_type: u16,
1633 context: ExtensionContext,
1634 add_cb: AddFn,
1635 parse_cb: ParseFn,
1636 ) -> Result<(), ErrorStack>
1637 where
1638 AddFn: Fn(
1639 &mut SslRef,
1640 ExtensionContext,
1641 Option<(usize, &X509Ref)>,
1642 ) -> Result<Option<T>, SslAlert>
1643 + 'static
1644 + Sync
1645 + Send,
1646 T: AsRef<[u8]> + 'static + Sync + Send,
1647 ParseFn: Fn(
1648 &mut SslRef,
1649 ExtensionContext,
1650 &[u8],
1651 Option<(usize, &X509Ref)>,
1652 ) -> Result<(), SslAlert>
1653 + 'static
1654 + Sync
1655 + Send,
1656 {
1657 let ret = unsafe {
1658 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1659 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1660
1661 ffi::SSL_CTX_add_custom_ext(
1662 self.as_ptr(),
1663 ext_type as c_uint,
1664 context.bits(),
1665 Some(raw_custom_ext_add::<AddFn, T>),
1666 Some(raw_custom_ext_free::<T>),
1667 ptr::null_mut(),
1668 Some(raw_custom_ext_parse::<ParseFn>),
1669 ptr::null_mut(),
1670 )
1671 };
1672 if ret == 1 {
1673 Ok(())
1674 } else {
1675 Err(ErrorStack::get())
1676 }
1677 }
1678
1679 #[corresponds(SSL_CTX_set_max_early_data)]
1685 #[cfg(any(ossl111, libressl))]
1686 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1687 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1688 Ok(())
1689 } else {
1690 Err(ErrorStack::get())
1691 }
1692 }
1693
1694 #[corresponds(SSL_CTX_set_client_hello_cb)]
1698 #[cfg(ossl111)]
1699 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1700 where
1701 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1702 + 'static
1703 + Sync
1704 + Send,
1705 {
1706 unsafe {
1707 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1708 ffi::SSL_CTX_set_client_hello_cb(
1709 self.as_ptr(),
1710 Some(callbacks::raw_client_hello::<F>),
1711 ptr,
1712 );
1713 }
1714 }
1715
1716 #[corresponds(SSL_CTX_sess_set_cache_size)]
1720 #[allow(clippy::useless_conversion)]
1721 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1722 unsafe {
1723 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1724 }
1725 }
1726
1727 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1731 #[cfg(ossl102)]
1732 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1733 let sigalgs = CString::new(sigalgs).unwrap();
1734 unsafe {
1735 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1736 .map(|_| ())
1737 }
1738 }
1739
1740 #[corresponds(SSL_CTX_set1_groups_list)]
1744 #[cfg(any(ossl111, boringssl, libressl, awslc))]
1745 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1746 let groups = CString::new(groups).unwrap();
1747 unsafe {
1748 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1749 }
1750 }
1751
1752 #[corresponds(SSL_CTX_set_num_tickets)]
1757 #[cfg(ossl111)]
1758 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1759 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1760 }
1761
1762 #[corresponds(SSL_CTX_set_security_level)]
1767 #[cfg(any(ossl110, libressl360))]
1768 pub fn set_security_level(&mut self, level: u32) {
1769 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1770 }
1771
1772 pub fn build(self) -> SslContext {
1774 self.0
1775 }
1776}
1777
1778foreign_type_and_impl_send_sync! {
1779 type CType = ffi::SSL_CTX;
1780 fn drop = ffi::SSL_CTX_free;
1781
1782 pub struct SslContext;
1787
1788 pub struct SslContextRef;
1792}
1793
1794impl Clone for SslContext {
1795 fn clone(&self) -> Self {
1796 (**self).to_owned()
1797 }
1798}
1799
1800impl ToOwned for SslContextRef {
1801 type Owned = SslContext;
1802
1803 fn to_owned(&self) -> Self::Owned {
1804 unsafe {
1805 SSL_CTX_up_ref(self.as_ptr());
1806 SslContext::from_ptr(self.as_ptr())
1807 }
1808 }
1809}
1810
1811impl fmt::Debug for SslContext {
1813 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1814 write!(fmt, "SslContext")
1815 }
1816}
1817
1818impl SslContext {
1819 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1821 SslContextBuilder::new(method)
1822 }
1823
1824 #[corresponds(SSL_CTX_get_ex_new_index)]
1829 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1830 where
1831 T: 'static + Sync + Send,
1832 {
1833 unsafe {
1834 ffi::init();
1835 #[cfg(any(boringssl, awslc))]
1836 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1837 #[cfg(not(any(boringssl, awslc)))]
1838 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1839 Ok(Index::from_raw(idx))
1840 }
1841 }
1842
1843 fn cached_ex_index<T>() -> Index<SslContext, T>
1845 where
1846 T: 'static + Sync + Send,
1847 {
1848 unsafe {
1849 let idx = *INDEXES
1850 .lock()
1851 .unwrap_or_else(|e| e.into_inner())
1852 .entry(TypeId::of::<T>())
1853 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1854 Index::from_raw(idx)
1855 }
1856 }
1857}
1858
1859impl SslContextRef {
1860 #[corresponds(SSL_CTX_get0_certificate)]
1864 #[cfg(any(ossl102, libressl))]
1865 pub fn certificate(&self) -> Option<&X509Ref> {
1866 unsafe {
1867 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1868 X509Ref::from_const_ptr_opt(ptr)
1869 }
1870 }
1871
1872 #[corresponds(SSL_CTX_get0_privatekey)]
1876 #[cfg(any(ossl102, libressl))]
1877 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1878 unsafe {
1879 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1880 PKeyRef::from_const_ptr_opt(ptr)
1881 }
1882 }
1883
1884 #[corresponds(SSL_CTX_get_cert_store)]
1886 pub fn cert_store(&self) -> &X509StoreRef {
1887 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1888 }
1889
1890 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1892 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1893 unsafe {
1894 let mut chain = ptr::null_mut();
1895 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1896 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1897 }
1898 }
1899
1900 #[corresponds(SSL_CTX_get_ex_data)]
1902 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1903 unsafe {
1904 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1905 if data.is_null() {
1906 None
1907 } else {
1908 Some(&*(data as *const T))
1909 }
1910 }
1911 }
1912
1913 #[corresponds(SSL_CTX_get_max_early_data)]
1917 #[cfg(any(ossl111, libressl))]
1918 pub fn max_early_data(&self) -> u32 {
1919 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1920 }
1921
1922 #[corresponds(SSL_CTX_add_session)]
1931 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1932 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1933 }
1934
1935 #[corresponds(SSL_CTX_remove_session)]
1944 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1945 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1946 }
1947
1948 #[corresponds(SSL_CTX_sess_get_cache_size)]
1952 #[allow(clippy::unnecessary_cast)]
1953 pub fn session_cache_size(&self) -> i64 {
1954 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1955 }
1956
1957 #[corresponds(SSL_CTX_get_verify_mode)]
1961 pub fn verify_mode(&self) -> SslVerifyMode {
1962 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1963 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1964 }
1965
1966 #[corresponds(SSL_CTX_get_num_tickets)]
1971 #[cfg(ossl111)]
1972 pub fn num_tickets(&self) -> usize {
1973 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1974 }
1975
1976 #[corresponds(SSL_CTX_get_security_level)]
1981 #[cfg(any(ossl110, libressl360))]
1982 pub fn security_level(&self) -> u32 {
1983 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1984 }
1985}
1986
1987pub struct CipherBits {
1989 pub secret: i32,
1991
1992 pub algorithm: i32,
1994}
1995
1996pub struct SslCipher(*mut ffi::SSL_CIPHER);
1998
1999impl ForeignType for SslCipher {
2000 type CType = ffi::SSL_CIPHER;
2001 type Ref = SslCipherRef;
2002
2003 #[inline]
2004 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2005 SslCipher(ptr)
2006 }
2007
2008 #[inline]
2009 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2010 self.0
2011 }
2012}
2013
2014impl Stackable for SslCipher {
2015 type StackType = ffi::stack_st_SSL_CIPHER;
2016}
2017
2018impl Deref for SslCipher {
2019 type Target = SslCipherRef;
2020
2021 fn deref(&self) -> &SslCipherRef {
2022 unsafe { SslCipherRef::from_ptr(self.0) }
2023 }
2024}
2025
2026impl DerefMut for SslCipher {
2027 fn deref_mut(&mut self) -> &mut SslCipherRef {
2028 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2029 }
2030}
2031
2032pub struct SslCipherRef(Opaque);
2036
2037impl ForeignTypeRef for SslCipherRef {
2038 type CType = ffi::SSL_CIPHER;
2039}
2040
2041impl SslCipherRef {
2042 #[corresponds(SSL_CIPHER_get_name)]
2044 pub fn name(&self) -> &'static str {
2045 unsafe {
2046 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2047 CStr::from_ptr(ptr).to_str().unwrap()
2048 }
2049 }
2050
2051 #[corresponds(SSL_CIPHER_standard_name)]
2055 #[cfg(ossl111)]
2056 pub fn standard_name(&self) -> Option<&'static str> {
2057 unsafe {
2058 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2059 if ptr.is_null() {
2060 None
2061 } else {
2062 Some(CStr::from_ptr(ptr).to_str().unwrap())
2063 }
2064 }
2065 }
2066
2067 #[corresponds(SSL_CIPHER_get_version)]
2069 pub fn version(&self) -> &'static str {
2070 let version = unsafe {
2071 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2072 CStr::from_ptr(ptr as *const _)
2073 };
2074
2075 str::from_utf8(version.to_bytes()).unwrap()
2076 }
2077
2078 #[corresponds(SSL_CIPHER_get_bits)]
2080 #[allow(clippy::useless_conversion)]
2081 pub fn bits(&self) -> CipherBits {
2082 unsafe {
2083 let mut algo_bits = 0;
2084 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2085 CipherBits {
2086 secret: secret_bits.into(),
2087 algorithm: algo_bits.into(),
2088 }
2089 }
2090 }
2091
2092 #[corresponds(SSL_CIPHER_description)]
2094 pub fn description(&self) -> String {
2095 unsafe {
2096 let mut buf = [0; 128];
2098 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2099 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2100 }
2101 }
2102
2103 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2107 #[cfg(ossl111)]
2108 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2109 unsafe {
2110 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2111 if ptr.is_null() {
2112 None
2113 } else {
2114 Some(MessageDigest::from_ptr(ptr))
2115 }
2116 }
2117 }
2118
2119 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2123 #[cfg(any(ossl110, libressl))]
2124 pub fn cipher_nid(&self) -> Option<Nid> {
2125 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2126 if n == 0 {
2127 None
2128 } else {
2129 Some(Nid::from_raw(n))
2130 }
2131 }
2132
2133 #[corresponds(SSL_CIPHER_get_protocol_id)]
2137 #[cfg(ossl111)]
2138 pub fn protocol_id(&self) -> [u8; 2] {
2139 unsafe {
2140 let id = ffi::SSL_CIPHER_get_protocol_id(self.as_ptr());
2141 id.to_be_bytes()
2142 }
2143 }
2144}
2145
2146impl fmt::Debug for SslCipherRef {
2147 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2148 write!(fmt, "{}", self.name())
2149 }
2150}
2151
2152#[derive(Debug)]
2154pub struct CipherLists {
2155 pub suites: Stack<SslCipher>,
2156 pub signalling_suites: Stack<SslCipher>,
2157}
2158
2159foreign_type_and_impl_send_sync! {
2160 type CType = ffi::SSL_SESSION;
2161 fn drop = ffi::SSL_SESSION_free;
2162
2163 pub struct SslSession;
2167
2168 pub struct SslSessionRef;
2172}
2173
2174impl Clone for SslSession {
2175 fn clone(&self) -> SslSession {
2176 SslSessionRef::to_owned(self)
2177 }
2178}
2179
2180impl SslSession {
2181 from_der! {
2182 #[corresponds(d2i_SSL_SESSION)]
2184 from_der,
2185 SslSession,
2186 ffi::d2i_SSL_SESSION
2187 }
2188}
2189
2190impl ToOwned for SslSessionRef {
2191 type Owned = SslSession;
2192
2193 fn to_owned(&self) -> SslSession {
2194 unsafe {
2195 SSL_SESSION_up_ref(self.as_ptr());
2196 SslSession(self.as_ptr())
2197 }
2198 }
2199}
2200
2201impl SslSessionRef {
2202 #[corresponds(SSL_SESSION_get_id)]
2204 pub fn id(&self) -> &[u8] {
2205 unsafe {
2206 let mut len = 0;
2207 let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len);
2208 #[allow(clippy::unnecessary_cast)]
2209 util::from_raw_parts(p as *const u8, len as usize)
2210 }
2211 }
2212
2213 #[corresponds(SSL_SESSION_get_master_key)]
2215 pub fn master_key_len(&self) -> usize {
2216 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
2217 }
2218
2219 #[corresponds(SSL_SESSION_get_master_key)]
2223 pub fn master_key(&self, buf: &mut [u8]) -> usize {
2224 unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
2225 }
2226
2227 #[corresponds(SSL_SESSION_get_max_early_data)]
2231 #[cfg(any(ossl111, libressl))]
2232 pub fn max_early_data(&self) -> u32 {
2233 unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
2234 }
2235
2236 #[corresponds(SSL_SESSION_get_time)]
2238 #[allow(clippy::useless_conversion)]
2239 pub fn time(&self) -> SslTimeTy {
2240 unsafe { ffi::SSL_SESSION_get_time(self.as_ptr()) }
2241 }
2242
2243 #[corresponds(SSL_SESSION_get_timeout)]
2247 #[allow(clippy::useless_conversion)]
2248 pub fn timeout(&self) -> i64 {
2249 unsafe { ffi::SSL_SESSION_get_timeout(self.as_ptr()).into() }
2250 }
2251
2252 #[corresponds(SSL_SESSION_get_protocol_version)]
2256 #[cfg(any(ossl110, libressl))]
2257 pub fn protocol_version(&self) -> SslVersion {
2258 unsafe {
2259 let version = ffi::SSL_SESSION_get_protocol_version(self.as_ptr());
2260 SslVersion(version)
2261 }
2262 }
2263
2264 to_der! {
2265 #[corresponds(i2d_SSL_SESSION)]
2267 to_der,
2268 ffi::i2d_SSL_SESSION
2269 }
2270}
2271
2272foreign_type_and_impl_send_sync! {
2273 type CType = ffi::SSL;
2274 fn drop = ffi::SSL_free;
2275
2276 pub struct Ssl;
2283
2284 pub struct SslRef;
2288}
2289
2290impl fmt::Debug for Ssl {
2291 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2292 fmt::Debug::fmt(&**self, fmt)
2293 }
2294}
2295
2296impl Ssl {
2297 #[corresponds(SSL_get_ex_new_index)]
2302 pub fn new_ex_index<T>() -> Result<Index<Ssl, T>, ErrorStack>
2303 where
2304 T: 'static + Sync + Send,
2305 {
2306 unsafe {
2307 ffi::init();
2308 #[cfg(any(boringssl, awslc))]
2309 let idx = cvt_n(get_new_ssl_idx(Some(free_data_box::<T>)))?;
2310 #[cfg(not(any(boringssl, awslc)))]
2311 let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
2312 Ok(Index::from_raw(idx))
2313 }
2314 }
2315
2316 fn cached_ex_index<T>() -> Index<Ssl, T>
2318 where
2319 T: 'static + Sync + Send,
2320 {
2321 unsafe {
2322 let idx = *SSL_INDEXES
2323 .lock()
2324 .unwrap_or_else(|e| e.into_inner())
2325 .entry(TypeId::of::<T>())
2326 .or_insert_with(|| Ssl::new_ex_index::<T>().unwrap().as_raw());
2327 Index::from_raw(idx)
2328 }
2329 }
2330
2331 #[corresponds(SSL_new)]
2333 pub fn new(ctx: &SslContextRef) -> Result<Ssl, ErrorStack> {
2334 let session_ctx_index = try_get_session_ctx_index()?;
2335 unsafe {
2336 let ptr = cvt_p(ffi::SSL_new(ctx.as_ptr()))?;
2337 let mut ssl = Ssl::from_ptr(ptr);
2338 ssl.set_ex_data(*session_ctx_index, ctx.to_owned());
2339
2340 Ok(ssl)
2341 }
2342 }
2343
2344 #[corresponds(SSL_connect)]
2350 #[allow(deprecated)]
2351 pub fn connect<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2352 where
2353 S: Read + Write,
2354 {
2355 SslStreamBuilder::new(self, stream).connect()
2356 }
2357
2358 #[corresponds(SSL_accept)]
2365 #[allow(deprecated)]
2366 pub fn accept<S>(self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
2367 where
2368 S: Read + Write,
2369 {
2370 SslStreamBuilder::new(self, stream).accept()
2371 }
2372}
2373
2374impl fmt::Debug for SslRef {
2375 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
2376 fmt.debug_struct("Ssl")
2377 .field("state", &self.state_string_long())
2378 .field("verify_result", &self.verify_result())
2379 .finish()
2380 }
2381}
2382
2383impl SslRef {
2384 fn get_raw_rbio(&self) -> *mut ffi::BIO {
2385 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
2386 }
2387
2388 fn get_error(&self, ret: c_int) -> ErrorCode {
2389 unsafe { ErrorCode::from_raw(ffi::SSL_get_error(self.as_ptr(), ret)) }
2390 }
2391
2392 #[corresponds(SSL_set_connect_state)]
2394 pub fn set_connect_state(&mut self) {
2395 unsafe { ffi::SSL_set_connect_state(self.as_ptr()) }
2396 }
2397
2398 #[corresponds(SSL_set_accept_state)]
2400 pub fn set_accept_state(&mut self) {
2401 unsafe { ffi::SSL_set_accept_state(self.as_ptr()) }
2402 }
2403
2404 #[corresponds(SSL_set_verify)]
2408 pub fn set_verify(&mut self, mode: SslVerifyMode) {
2409 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits() as c_int, None) }
2410 }
2411
2412 #[corresponds(SSL_set_verify_mode)]
2414 pub fn verify_mode(&self) -> SslVerifyMode {
2415 let mode = unsafe { ffi::SSL_get_verify_mode(self.as_ptr()) };
2416 SslVerifyMode::from_bits(mode).expect("SSL_get_verify_mode returned invalid mode")
2417 }
2418
2419 #[corresponds(SSL_set_verify)]
2423 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
2424 where
2425 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
2426 {
2427 unsafe {
2428 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(verify));
2430 ffi::SSL_set_verify(
2431 self.as_ptr(),
2432 mode.bits() as c_int,
2433 Some(ssl_raw_verify::<F>),
2434 );
2435 }
2436 }
2437
2438 #[corresponds(SSL_set_tmp_dh)]
2442 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
2443 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
2444 }
2445
2446 #[corresponds(SSL_set_tmp_dh_callback)]
2450 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
2451 where
2452 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
2453 {
2454 unsafe {
2455 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2457 #[cfg(any(boringssl, awslc))]
2458 ffi::SSL_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2459 #[cfg(not(any(boringssl, awslc)))]
2460 ffi::SSL_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh_ssl::<F>));
2461 }
2462 }
2463
2464 #[corresponds(SSL_set_tmp_ecdh)]
2468 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
2469 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
2470 }
2471
2472 #[corresponds(SSL_set_tmp_ecdh_callback)]
2476 #[cfg(all(ossl102, not(ossl110)))]
2477 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
2478 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
2479 where
2480 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
2481 {
2482 unsafe {
2483 self.set_ex_data(Ssl::cached_ex_index(), Arc::new(callback));
2485 ffi::SSL_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh_ssl::<F>));
2486 }
2487 }
2488
2489 #[corresponds(SSL_set_ecdh_auto)]
2495 #[cfg(any(all(ossl102, not(ossl110)), libressl))]
2496 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
2497 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
2498 }
2499
2500 #[corresponds(SSL_set_alpn_protos)]
2506 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2507 unsafe {
2508 assert!(protocols.len() <= c_uint::MAX as usize);
2509 let r =
2510 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2511 if r == 0 {
2513 Ok(())
2514 } else {
2515 Err(ErrorStack::get())
2516 }
2517 }
2518 }
2519
2520 #[corresponds(SSL_get_current_cipher)]
2522 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2523 unsafe {
2524 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2525
2526 SslCipherRef::from_const_ptr_opt(ptr)
2527 }
2528 }
2529
2530 #[corresponds(SSL_state_string)]
2532 pub fn state_string(&self) -> &'static str {
2533 let state = unsafe {
2534 let ptr = ffi::SSL_state_string(self.as_ptr());
2535 CStr::from_ptr(ptr as *const _)
2536 };
2537
2538 str::from_utf8(state.to_bytes()).unwrap()
2539 }
2540
2541 #[corresponds(SSL_state_string_long)]
2543 pub fn state_string_long(&self) -> &'static str {
2544 let state = unsafe {
2545 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2546 CStr::from_ptr(ptr as *const _)
2547 };
2548
2549 str::from_utf8(state.to_bytes()).unwrap()
2550 }
2551
2552 #[corresponds(SSL_set_tlsext_host_name)]
2556 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2557 let cstr = CString::new(hostname).unwrap();
2558 unsafe {
2559 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2560 .map(|_| ())
2561 }
2562 }
2563
2564 #[corresponds(SSL_get_peer_certificate)]
2566 pub fn peer_certificate(&self) -> Option<X509> {
2567 unsafe {
2568 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2569 X509::from_ptr_opt(ptr)
2570 }
2571 }
2572
2573 #[corresponds(SSL_get_peer_cert_chain)]
2578 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2579 unsafe {
2580 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2581 StackRef::from_const_ptr_opt(ptr)
2582 }
2583 }
2584
2585 #[corresponds(SSL_get0_verified_chain)]
2595 #[cfg(ossl110)]
2596 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2597 unsafe {
2598 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2599 StackRef::from_const_ptr_opt(ptr)
2600 }
2601 }
2602
2603 #[corresponds(SSL_get_certificate)]
2605 pub fn certificate(&self) -> Option<&X509Ref> {
2606 unsafe {
2607 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2608 X509Ref::from_const_ptr_opt(ptr)
2609 }
2610 }
2611
2612 #[corresponds(SSL_get_privatekey)]
2616 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2617 unsafe {
2618 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2619 PKeyRef::from_const_ptr_opt(ptr)
2620 }
2621 }
2622
2623 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2624 pub fn version(&self) -> &str {
2625 self.version_str()
2626 }
2627
2628 #[corresponds(SSL_version)]
2630 pub fn version2(&self) -> Option<SslVersion> {
2631 unsafe {
2632 let r = ffi::SSL_version(self.as_ptr());
2633 if r == 0 {
2634 None
2635 } else {
2636 Some(SslVersion(r))
2637 }
2638 }
2639 }
2640
2641 #[corresponds(SSL_get_version)]
2643 pub fn version_str(&self) -> &'static str {
2644 let version = unsafe {
2645 let ptr = ffi::SSL_get_version(self.as_ptr());
2646 CStr::from_ptr(ptr as *const _)
2647 };
2648
2649 str::from_utf8(version.to_bytes()).unwrap()
2650 }
2651
2652 #[corresponds(SSL_get0_alpn_selected)]
2659 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2660 unsafe {
2661 let mut data: *const c_uchar = ptr::null();
2662 let mut len: c_uint = 0;
2663 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2666
2667 if data.is_null() {
2668 None
2669 } else {
2670 Some(util::from_raw_parts(data, len as usize))
2671 }
2672 }
2673 }
2674
2675 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2677 #[corresponds(SSL_set_tlsext_use_srtp)]
2678 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2679 unsafe {
2680 let cstr = CString::new(protocols).unwrap();
2681
2682 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2683 if r == 0 {
2685 Ok(())
2686 } else {
2687 Err(ErrorStack::get())
2688 }
2689 }
2690 }
2691
2692 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2696 #[corresponds(SSL_get_srtp_profiles)]
2697 pub fn srtp_profiles(&self) -> Option<&StackRef<SrtpProtectionProfile>> {
2698 unsafe {
2699 let chain = ffi::SSL_get_srtp_profiles(self.as_ptr());
2700
2701 StackRef::from_const_ptr_opt(chain)
2702 }
2703 }
2704
2705 #[cfg(not(osslconf = "OPENSSL_NO_SRTP"))]
2709 #[corresponds(SSL_get_selected_srtp_profile)]
2710 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2711 unsafe {
2712 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2713
2714 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2715 }
2716 }
2717
2718 #[corresponds(SSL_pending)]
2723 pub fn pending(&self) -> usize {
2724 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2725 }
2726
2727 #[corresponds(SSL_get_servername)]
2740 pub fn servername(&self, type_: NameType) -> Option<&str> {
2742 self.servername_raw(type_)
2743 .and_then(|b| str::from_utf8(b).ok())
2744 }
2745
2746 #[corresponds(SSL_get_servername)]
2754 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2755 unsafe {
2756 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2757 if name.is_null() {
2758 None
2759 } else {
2760 Some(CStr::from_ptr(name as *const _).to_bytes())
2761 }
2762 }
2763 }
2764
2765 #[corresponds(SSL_set_SSL_CTX)]
2769 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2770 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2771 }
2772
2773 #[corresponds(SSL_get_SSL_CTX)]
2775 pub fn ssl_context(&self) -> &SslContextRef {
2776 unsafe {
2777 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2778 SslContextRef::from_ptr(ssl_ctx)
2779 }
2780 }
2781
2782 #[corresponds(SSL_get0_param)]
2786 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
2787 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
2788 }
2789
2790 #[corresponds(SSL_get_verify_result)]
2792 pub fn verify_result(&self) -> X509VerifyResult {
2793 unsafe { X509VerifyResult::from_raw(ffi::SSL_get_verify_result(self.as_ptr()) as c_int) }
2794 }
2795
2796 #[corresponds(SSL_get_session)]
2798 pub fn session(&self) -> Option<&SslSessionRef> {
2799 unsafe {
2800 let p = ffi::SSL_get_session(self.as_ptr());
2801 SslSessionRef::from_const_ptr_opt(p)
2802 }
2803 }
2804
2805 #[corresponds(SSL_get_client_random)]
2812 #[cfg(any(ossl110, libressl))]
2813 pub fn client_random(&self, buf: &mut [u8]) -> usize {
2814 unsafe {
2815 ffi::SSL_get_client_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2816 }
2817 }
2818
2819 #[corresponds(SSL_get_server_random)]
2826 #[cfg(any(ossl110, libressl))]
2827 pub fn server_random(&self, buf: &mut [u8]) -> usize {
2828 unsafe {
2829 ffi::SSL_get_server_random(self.as_ptr(), buf.as_mut_ptr() as *mut c_uchar, buf.len())
2830 }
2831 }
2832
2833 #[corresponds(SSL_export_keying_material)]
2835 pub fn export_keying_material(
2836 &self,
2837 out: &mut [u8],
2838 label: &str,
2839 context: Option<&[u8]>,
2840 ) -> Result<(), ErrorStack> {
2841 unsafe {
2842 let (context, contextlen, use_context) = match context {
2843 Some(context) => (context.as_ptr() as *const c_uchar, context.len(), 1),
2844 None => (ptr::null(), 0, 0),
2845 };
2846 cvt(ffi::SSL_export_keying_material(
2847 self.as_ptr(),
2848 out.as_mut_ptr() as *mut c_uchar,
2849 out.len(),
2850 label.as_ptr() as *const c_char,
2851 label.len(),
2852 context,
2853 contextlen,
2854 use_context,
2855 ))
2856 .map(|_| ())
2857 }
2858 }
2859
2860 #[corresponds(SSL_export_keying_material_early)]
2867 #[cfg(ossl111)]
2868 pub fn export_keying_material_early(
2869 &self,
2870 out: &mut [u8],
2871 label: &str,
2872 context: &[u8],
2873 ) -> Result<(), ErrorStack> {
2874 unsafe {
2875 cvt(ffi::SSL_export_keying_material_early(
2876 self.as_ptr(),
2877 out.as_mut_ptr() as *mut c_uchar,
2878 out.len(),
2879 label.as_ptr() as *const c_char,
2880 label.len(),
2881 context.as_ptr() as *const c_uchar,
2882 context.len(),
2883 ))
2884 .map(|_| ())
2885 }
2886 }
2887
2888 #[corresponds(SSL_set_session)]
2899 pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
2900 cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
2901 }
2902
2903 #[corresponds(SSL_session_reused)]
2905 pub fn session_reused(&self) -> bool {
2906 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
2907 }
2908
2909 #[corresponds(SSL_set_tlsext_status_type)]
2911 pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
2912 unsafe {
2913 cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ())
2914 }
2915 }
2916
2917 #[corresponds(SSL_get_extms_support)]
2921 #[cfg(ossl110)]
2922 pub fn extms_support(&self) -> Option<bool> {
2923 unsafe {
2924 match ffi::SSL_get_extms_support(self.as_ptr()) {
2925 -1 => None,
2926 ret => Some(ret != 0),
2927 }
2928 }
2929 }
2930
2931 #[corresponds(SSL_get_tlsext_status_ocsp_resp)]
2933 #[cfg(not(any(boringssl, awslc)))]
2934 pub fn ocsp_status(&self) -> Option<&[u8]> {
2935 unsafe {
2936 let mut p = ptr::null_mut();
2937 let len = ffi::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p);
2938
2939 if len < 0 {
2940 None
2941 } else {
2942 Some(util::from_raw_parts(p as *const u8, len as usize))
2943 }
2944 }
2945 }
2946
2947 #[corresponds(SSL_set_tlsext_status_oscp_resp)]
2949 #[cfg(not(any(boringssl, awslc)))]
2950 pub fn set_ocsp_status(&mut self, response: &[u8]) -> Result<(), ErrorStack> {
2951 unsafe {
2952 assert!(response.len() <= c_int::MAX as usize);
2953 let p = cvt_p(ffi::OPENSSL_malloc(response.len() as _))?;
2954 ptr::copy_nonoverlapping(response.as_ptr(), p as *mut u8, response.len());
2955 cvt(ffi::SSL_set_tlsext_status_ocsp_resp(
2956 self.as_ptr(),
2957 p as *mut c_uchar,
2958 response.len() as c_long,
2959 ) as c_int)
2960 .map(|_| ())
2961 .map_err(|e| {
2962 ffi::OPENSSL_free(p);
2963 e
2964 })
2965 }
2966 }
2967
2968 #[corresponds(SSL_is_server)]
2970 pub fn is_server(&self) -> bool {
2971 unsafe { SSL_is_server(self.as_ptr()) != 0 }
2972 }
2973
2974 #[corresponds(SSL_set_ex_data)]
2980 pub fn set_ex_data<T>(&mut self, index: Index<Ssl, T>, data: T) {
2981 match self.ex_data_mut(index) {
2982 Some(v) => *v = data,
2983 None => unsafe {
2984 let data = Box::new(data);
2985 ffi::SSL_set_ex_data(
2986 self.as_ptr(),
2987 index.as_raw(),
2988 Box::into_raw(data) as *mut c_void,
2989 );
2990 },
2991 }
2992 }
2993
2994 #[corresponds(SSL_get_ex_data)]
2996 pub fn ex_data<T>(&self, index: Index<Ssl, T>) -> Option<&T> {
2997 unsafe {
2998 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
2999 if data.is_null() {
3000 None
3001 } else {
3002 Some(&*(data as *const T))
3003 }
3004 }
3005 }
3006
3007 #[corresponds(SSL_get_ex_data)]
3009 pub fn ex_data_mut<T>(&mut self, index: Index<Ssl, T>) -> Option<&mut T> {
3010 unsafe {
3011 let data = ffi::SSL_get_ex_data(self.as_ptr(), index.as_raw());
3012 if data.is_null() {
3013 None
3014 } else {
3015 Some(&mut *(data as *mut T))
3016 }
3017 }
3018 }
3019
3020 #[corresponds(SSL_set_max_early_data)]
3024 #[cfg(any(ossl111, libressl))]
3025 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
3026 if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
3027 Ok(())
3028 } else {
3029 Err(ErrorStack::get())
3030 }
3031 }
3032
3033 #[corresponds(SSL_get_max_early_data)]
3037 #[cfg(any(ossl111, libressl))]
3038 pub fn max_early_data(&self) -> u32 {
3039 unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
3040 }
3041
3042 #[corresponds(SSL_get_finished)]
3047 pub fn finished(&self, buf: &mut [u8]) -> usize {
3048 unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
3049 }
3050
3051 #[corresponds(SSL_get_peer_finished)]
3057 pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
3058 unsafe {
3059 ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
3060 }
3061 }
3062
3063 #[corresponds(SSL_is_init_finished)]
3065 #[cfg(ossl110)]
3066 pub fn is_init_finished(&self) -> bool {
3067 unsafe { ffi::SSL_is_init_finished(self.as_ptr()) != 0 }
3068 }
3069
3070 #[corresponds(SSL_client_hello_isv2)]
3076 #[cfg(ossl111)]
3077 pub fn client_hello_isv2(&self) -> bool {
3078 unsafe { ffi::SSL_client_hello_isv2(self.as_ptr()) != 0 }
3079 }
3080
3081 #[corresponds(SSL_client_hello_get0_legacy_version)]
3087 #[cfg(ossl111)]
3088 pub fn client_hello_legacy_version(&self) -> Option<SslVersion> {
3089 unsafe {
3090 let version = ffi::SSL_client_hello_get0_legacy_version(self.as_ptr());
3091 if version == 0 {
3092 None
3093 } else {
3094 Some(SslVersion(version as c_int))
3095 }
3096 }
3097 }
3098
3099 #[corresponds(SSL_client_hello_get0_random)]
3105 #[cfg(ossl111)]
3106 pub fn client_hello_random(&self) -> Option<&[u8]> {
3107 unsafe {
3108 let mut ptr = ptr::null();
3109 let len = ffi::SSL_client_hello_get0_random(self.as_ptr(), &mut ptr);
3110 if len == 0 {
3111 None
3112 } else {
3113 Some(util::from_raw_parts(ptr, len))
3114 }
3115 }
3116 }
3117
3118 #[corresponds(SSL_client_hello_get0_session_id)]
3124 #[cfg(ossl111)]
3125 pub fn client_hello_session_id(&self) -> Option<&[u8]> {
3126 unsafe {
3127 let mut ptr = ptr::null();
3128 let len = ffi::SSL_client_hello_get0_session_id(self.as_ptr(), &mut ptr);
3129 if len == 0 {
3130 None
3131 } else {
3132 Some(util::from_raw_parts(ptr, len))
3133 }
3134 }
3135 }
3136
3137 #[corresponds(SSL_client_hello_get0_ciphers)]
3143 #[cfg(ossl111)]
3144 pub fn client_hello_ciphers(&self) -> Option<&[u8]> {
3145 unsafe {
3146 let mut ptr = ptr::null();
3147 let len = ffi::SSL_client_hello_get0_ciphers(self.as_ptr(), &mut ptr);
3148 if len == 0 {
3149 None
3150 } else {
3151 Some(util::from_raw_parts(ptr, len))
3152 }
3153 }
3154 }
3155
3156 #[corresponds(SSL_bytes_to_cipher_list)]
3161 #[cfg(ossl111)]
3162 pub fn bytes_to_cipher_list(
3163 &self,
3164 bytes: &[u8],
3165 isv2format: bool,
3166 ) -> Result<CipherLists, ErrorStack> {
3167 unsafe {
3168 let ptr = bytes.as_ptr();
3169 let len = bytes.len();
3170 let mut sk = ptr::null_mut();
3171 let mut scsvs = ptr::null_mut();
3172 let res = ffi::SSL_bytes_to_cipher_list(
3173 self.as_ptr(),
3174 ptr,
3175 len,
3176 isv2format as c_int,
3177 &mut sk,
3178 &mut scsvs,
3179 );
3180 if res == 1 {
3181 Ok(CipherLists {
3182 suites: Stack::from_ptr(sk),
3183 signalling_suites: Stack::from_ptr(scsvs),
3184 })
3185 } else {
3186 Err(ErrorStack::get())
3187 }
3188 }
3189 }
3190
3191 #[corresponds(SSL_client_hello_get0_compression_methods)]
3197 #[cfg(ossl111)]
3198 pub fn client_hello_compression_methods(&self) -> Option<&[u8]> {
3199 unsafe {
3200 let mut ptr = ptr::null();
3201 let len = ffi::SSL_client_hello_get0_compression_methods(self.as_ptr(), &mut ptr);
3202 if len == 0 {
3203 None
3204 } else {
3205 Some(util::from_raw_parts(ptr, len))
3206 }
3207 }
3208 }
3209
3210 #[corresponds(SSL_set_mtu)]
3212 pub fn set_mtu(&mut self, mtu: u32) -> Result<(), ErrorStack> {
3213 unsafe { cvt(ffi::SSL_set_mtu(self.as_ptr(), mtu as MtuTy) as c_int).map(|_| ()) }
3214 }
3215
3216 #[corresponds(SSL_get_psk_identity_hint)]
3220 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3221 pub fn psk_identity_hint(&self) -> Option<&[u8]> {
3222 unsafe {
3223 let ptr = ffi::SSL_get_psk_identity_hint(self.as_ptr());
3224 if ptr.is_null() {
3225 None
3226 } else {
3227 Some(CStr::from_ptr(ptr).to_bytes())
3228 }
3229 }
3230 }
3231
3232 #[corresponds(SSL_get_psk_identity)]
3234 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
3235 pub fn psk_identity(&self) -> Option<&[u8]> {
3236 unsafe {
3237 let ptr = ffi::SSL_get_psk_identity(self.as_ptr());
3238 if ptr.is_null() {
3239 None
3240 } else {
3241 Some(CStr::from_ptr(ptr).to_bytes())
3242 }
3243 }
3244 }
3245
3246 #[corresponds(SSL_add0_chain_cert)]
3247 #[cfg(ossl102)]
3248 pub fn add_chain_cert(&mut self, chain: X509) -> Result<(), ErrorStack> {
3249 unsafe {
3250 cvt(ffi::SSL_add0_chain_cert(self.as_ptr(), chain.as_ptr()) as c_int).map(|_| ())?;
3251 mem::forget(chain);
3252 }
3253 Ok(())
3254 }
3255
3256 #[cfg(not(any(boringssl, awslc)))]
3258 pub fn set_method(&mut self, method: SslMethod) -> Result<(), ErrorStack> {
3259 unsafe {
3260 cvt(ffi::SSL_set_ssl_method(self.as_ptr(), method.as_ptr()))?;
3261 };
3262 Ok(())
3263 }
3264
3265 #[corresponds(SSL_use_Private_Key_file)]
3267 pub fn set_private_key_file<P: AsRef<Path>>(
3268 &mut self,
3269 path: P,
3270 ssl_file_type: SslFiletype,
3271 ) -> Result<(), ErrorStack> {
3272 let p = path.as_ref().as_os_str().to_str().unwrap();
3273 let key_file = CString::new(p).unwrap();
3274 unsafe {
3275 cvt(ffi::SSL_use_PrivateKey_file(
3276 self.as_ptr(),
3277 key_file.as_ptr(),
3278 ssl_file_type.as_raw(),
3279 ))?;
3280 };
3281 Ok(())
3282 }
3283
3284 #[corresponds(SSL_use_PrivateKey)]
3286 pub fn set_private_key(&mut self, pkey: &PKeyRef<Private>) -> Result<(), ErrorStack> {
3287 unsafe {
3288 cvt(ffi::SSL_use_PrivateKey(self.as_ptr(), pkey.as_ptr()))?;
3289 };
3290 Ok(())
3291 }
3292
3293 #[corresponds(SSL_use_certificate)]
3295 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
3296 unsafe {
3297 cvt(ffi::SSL_use_certificate(self.as_ptr(), cert.as_ptr()))?;
3298 };
3299 Ok(())
3300 }
3301
3302 #[corresponds(SSL_use_certificate_chain_file)]
3308 #[cfg(any(ossl110, libressl))]
3309 pub fn set_certificate_chain_file<P: AsRef<Path>>(
3310 &mut self,
3311 path: P,
3312 ) -> Result<(), ErrorStack> {
3313 let p = path.as_ref().as_os_str().to_str().unwrap();
3314 let cert_file = CString::new(p).unwrap();
3315 unsafe {
3316 cvt(ffi::SSL_use_certificate_chain_file(
3317 self.as_ptr(),
3318 cert_file.as_ptr(),
3319 ))?;
3320 };
3321 Ok(())
3322 }
3323
3324 #[corresponds(SSL_add_client_CA)]
3326 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
3327 unsafe {
3328 cvt(ffi::SSL_add_client_CA(self.as_ptr(), cacert.as_ptr()))?;
3329 };
3330 Ok(())
3331 }
3332
3333 #[corresponds(SSL_set_client_CA_list)]
3335 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
3336 unsafe { ffi::SSL_set_client_CA_list(self.as_ptr(), list.as_ptr()) }
3337 mem::forget(list);
3338 }
3339
3340 #[corresponds(SSL_set_min_proto_version)]
3347 #[cfg(any(ossl110, libressl, boringssl, awslc))]
3348 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3349 unsafe {
3350 cvt(ffi::SSL_set_min_proto_version(
3351 self.as_ptr(),
3352 version.map_or(0, |v| v.0 as _),
3353 ))
3354 .map(|_| ())
3355 }
3356 }
3357
3358 #[corresponds(SSL_set_max_proto_version)]
3365 #[cfg(any(ossl110, libressl, boringssl, awslc))]
3366 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
3367 unsafe {
3368 cvt(ffi::SSL_set_max_proto_version(
3369 self.as_ptr(),
3370 version.map_or(0, |v| v.0 as _),
3371 ))
3372 .map(|_| ())
3373 }
3374 }
3375
3376 #[corresponds(SSL_set_ciphersuites)]
3385 #[cfg(any(ossl111, libressl))]
3386 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3387 let cipher_list = CString::new(cipher_list).unwrap();
3388 unsafe {
3389 cvt(ffi::SSL_set_ciphersuites(
3390 self.as_ptr(),
3391 cipher_list.as_ptr() as *const _,
3392 ))
3393 .map(|_| ())
3394 }
3395 }
3396
3397 #[corresponds(SSL_set_cipher_list)]
3405 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
3406 let cipher_list = CString::new(cipher_list).unwrap();
3407 unsafe {
3408 cvt(ffi::SSL_set_cipher_list(
3409 self.as_ptr(),
3410 cipher_list.as_ptr() as *const _,
3411 ))
3412 .map(|_| ())
3413 }
3414 }
3415
3416 #[corresponds(SSL_set_cert_store)]
3418 #[cfg(ossl102)]
3419 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
3420 unsafe {
3421 cvt(ffi::SSL_set0_verify_cert_store(self.as_ptr(), cert_store.as_ptr()) as c_int)?;
3422 mem::forget(cert_store);
3423 Ok(())
3424 }
3425 }
3426
3427 #[corresponds(SSL_set_num_tickets)]
3432 #[cfg(ossl111)]
3433 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
3434 unsafe { cvt(ffi::SSL_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
3435 }
3436
3437 #[corresponds(SSL_get_num_tickets)]
3442 #[cfg(ossl111)]
3443 pub fn num_tickets(&self) -> usize {
3444 unsafe { ffi::SSL_get_num_tickets(self.as_ptr()) }
3445 }
3446
3447 #[corresponds(SSL_set_security_level)]
3452 #[cfg(any(ossl110, libressl360))]
3453 pub fn set_security_level(&mut self, level: u32) {
3454 unsafe { ffi::SSL_set_security_level(self.as_ptr(), level as c_int) }
3455 }
3456
3457 #[corresponds(SSL_get_security_level)]
3462 #[cfg(any(ossl110, libressl360))]
3463 pub fn security_level(&self) -> u32 {
3464 unsafe { ffi::SSL_get_security_level(self.as_ptr()) as u32 }
3465 }
3466
3467 #[corresponds(SSL_get_peer_tmp_key)]
3472 #[cfg(ossl300)]
3473 pub fn peer_tmp_key(&self) -> Result<PKey<Public>, ErrorStack> {
3474 unsafe {
3475 let mut key = ptr::null_mut();
3476 match cvt_long(ffi::SSL_get_peer_tmp_key(self.as_ptr(), &mut key)) {
3477 Ok(_) => Ok(PKey::<Public>::from_ptr(key)),
3478 Err(e) => Err(e),
3479 }
3480 }
3481 }
3482
3483 #[corresponds(SSL_get_tmp_key)]
3488 #[cfg(ossl300)]
3489 pub fn tmp_key(&self) -> Result<PKey<Private>, ErrorStack> {
3490 unsafe {
3491 let mut key = ptr::null_mut();
3492 match cvt_long(ffi::SSL_get_tmp_key(self.as_ptr(), &mut key)) {
3493 Ok(_) => Ok(PKey::<Private>::from_ptr(key)),
3494 Err(e) => Err(e),
3495 }
3496 }
3497 }
3498}
3499
3500#[derive(Debug)]
3502pub struct MidHandshakeSslStream<S> {
3503 stream: SslStream<S>,
3504 error: Error,
3505}
3506
3507impl<S> MidHandshakeSslStream<S> {
3508 pub fn get_ref(&self) -> &S {
3510 self.stream.get_ref()
3511 }
3512
3513 pub fn get_mut(&mut self) -> &mut S {
3515 self.stream.get_mut()
3516 }
3517
3518 pub fn ssl(&self) -> &SslRef {
3520 self.stream.ssl()
3521 }
3522
3523 pub fn error(&self) -> &Error {
3525 &self.error
3526 }
3527
3528 pub fn into_error(self) -> Error {
3530 self.error
3531 }
3532}
3533
3534impl<S> MidHandshakeSslStream<S>
3535where
3536 S: Read + Write,
3537{
3538 #[corresponds(SSL_do_handshake)]
3541 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
3542 match self.stream.do_handshake() {
3543 Ok(()) => Ok(self.stream),
3544 Err(error) => {
3545 self.error = error;
3546 match self.error.code() {
3547 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3548 Err(HandshakeError::WouldBlock(self))
3549 }
3550 _ => Err(HandshakeError::Failure(self)),
3551 }
3552 }
3553 }
3554 }
3555}
3556
3557pub struct SslStream<S> {
3559 ssl: ManuallyDrop<Ssl>,
3560 method: ManuallyDrop<BioMethod>,
3561 _p: PhantomData<S>,
3562}
3563
3564impl<S> Drop for SslStream<S> {
3565 fn drop(&mut self) {
3566 unsafe {
3568 ManuallyDrop::drop(&mut self.ssl);
3569 ManuallyDrop::drop(&mut self.method);
3570 }
3571 }
3572}
3573
3574impl<S> fmt::Debug for SslStream<S>
3575where
3576 S: fmt::Debug,
3577{
3578 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
3579 fmt.debug_struct("SslStream")
3580 .field("stream", &self.get_ref())
3581 .field("ssl", &self.ssl())
3582 .finish()
3583 }
3584}
3585
3586impl<S: Read + Write> SslStream<S> {
3587 #[corresponds(SSL_set_bio)]
3595 pub fn new(ssl: Ssl, stream: S) -> Result<Self, ErrorStack> {
3596 let (bio, method) = bio::new(stream)?;
3597 unsafe {
3598 ffi::SSL_set_bio(ssl.as_ptr(), bio, bio);
3599 }
3600
3601 Ok(SslStream {
3602 ssl: ManuallyDrop::new(ssl),
3603 method: ManuallyDrop::new(method),
3604 _p: PhantomData,
3605 })
3606 }
3607
3608 #[deprecated(
3616 since = "0.10.32",
3617 note = "use Ssl::from_ptr and SslStream::new instead"
3618 )]
3619 pub unsafe fn from_raw_parts(ssl: *mut ffi::SSL, stream: S) -> Self {
3620 let ssl = Ssl::from_ptr(ssl);
3621 Self::new(ssl, stream).unwrap()
3622 }
3623
3624 #[corresponds(SSL_read_early_data)]
3633 #[cfg(any(ossl111, libressl))]
3634 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3635 let mut read = 0;
3636 let ret = unsafe {
3637 ffi::SSL_read_early_data(
3638 self.ssl.as_ptr(),
3639 buf.as_ptr() as *mut c_void,
3640 buf.len(),
3641 &mut read,
3642 )
3643 };
3644 match ret {
3645 ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.make_error(ret)),
3646 ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
3647 ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
3648 _ => unreachable!(),
3649 }
3650 }
3651
3652 #[corresponds(SSL_write_early_data)]
3659 #[cfg(any(ossl111, libressl))]
3660 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
3661 let mut written = 0;
3662 let ret = unsafe {
3663 ffi::SSL_write_early_data(
3664 self.ssl.as_ptr(),
3665 buf.as_ptr() as *const c_void,
3666 buf.len(),
3667 &mut written,
3668 )
3669 };
3670 if ret > 0 {
3671 Ok(written)
3672 } else {
3673 Err(self.make_error(ret))
3674 }
3675 }
3676
3677 #[corresponds(SSL_connect)]
3684 pub fn connect(&mut self) -> Result<(), Error> {
3685 let ret = unsafe { ffi::SSL_connect(self.ssl.as_ptr()) };
3686 if ret > 0 {
3687 Ok(())
3688 } else {
3689 Err(self.make_error(ret))
3690 }
3691 }
3692
3693 #[corresponds(SSL_accept)]
3700 pub fn accept(&mut self) -> Result<(), Error> {
3701 let ret = unsafe { ffi::SSL_accept(self.ssl.as_ptr()) };
3702 if ret > 0 {
3703 Ok(())
3704 } else {
3705 Err(self.make_error(ret))
3706 }
3707 }
3708
3709 #[corresponds(SSL_do_handshake)]
3713 pub fn do_handshake(&mut self) -> Result<(), Error> {
3714 let ret = unsafe { ffi::SSL_do_handshake(self.ssl.as_ptr()) };
3715 if ret > 0 {
3716 Ok(())
3717 } else {
3718 Err(self.make_error(ret))
3719 }
3720 }
3721
3722 #[corresponds(SSL_stateless)]
3733 #[cfg(ossl111)]
3734 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
3735 match unsafe { ffi::SSL_stateless(self.ssl.as_ptr()) } {
3736 1 => Ok(true),
3737 0 => Ok(false),
3738 -1 => Err(ErrorStack::get()),
3739 _ => unreachable!(),
3740 }
3741 }
3742
3743 #[corresponds(SSL_read_ex)]
3750 pub fn read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> io::Result<usize> {
3751 loop {
3752 match self.ssl_read_uninit(buf) {
3753 Ok(n) => return Ok(n),
3754 Err(ref e) if e.code() == ErrorCode::ZERO_RETURN => return Ok(0),
3755 Err(ref e) if e.code() == ErrorCode::SYSCALL && e.io_error().is_none() => {
3756 return Ok(0);
3757 }
3758 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
3759 Err(e) => {
3760 return Err(e
3761 .into_io_error()
3762 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
3763 }
3764 }
3765 }
3766 }
3767
3768 #[corresponds(SSL_read_ex)]
3773 pub fn ssl_read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3774 unsafe {
3776 self.ssl_read_uninit(util::from_raw_parts_mut(
3777 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
3778 buf.len(),
3779 ))
3780 }
3781 }
3782
3783 #[corresponds(SSL_read_ex)]
3790 pub fn ssl_read_uninit(&mut self, buf: &mut [MaybeUninit<u8>]) -> Result<usize, Error> {
3791 cfg_if! {
3792 if #[cfg(any(ossl111, libressl))] {
3793 let mut readbytes = 0;
3794 let ret = unsafe {
3795 ffi::SSL_read_ex(
3796 self.ssl().as_ptr(),
3797 buf.as_mut_ptr().cast(),
3798 buf.len(),
3799 &mut readbytes,
3800 )
3801 };
3802
3803 if ret > 0 {
3804 Ok(readbytes)
3805 } else {
3806 Err(self.make_error(ret))
3807 }
3808 } else {
3809 if buf.is_empty() {
3810 return Ok(0);
3811 }
3812
3813 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3814 let ret = unsafe {
3815 ffi::SSL_read(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3816 };
3817 if ret > 0 {
3818 Ok(ret as usize)
3819 } else {
3820 Err(self.make_error(ret))
3821 }
3822 }
3823 }
3824 }
3825
3826 #[corresponds(SSL_write_ex)]
3831 pub fn ssl_write(&mut self, buf: &[u8]) -> Result<usize, Error> {
3832 cfg_if! {
3833 if #[cfg(any(ossl111, libressl))] {
3834 let mut written = 0;
3835 let ret = unsafe {
3836 ffi::SSL_write_ex(
3837 self.ssl().as_ptr(),
3838 buf.as_ptr().cast(),
3839 buf.len(),
3840 &mut written,
3841 )
3842 };
3843
3844 if ret > 0 {
3845 Ok(written)
3846 } else {
3847 Err(self.make_error(ret))
3848 }
3849 } else {
3850 if buf.is_empty() {
3851 return Ok(0);
3852 }
3853
3854 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3855 let ret = unsafe {
3856 ffi::SSL_write(self.ssl().as_ptr(), buf.as_ptr().cast(), len)
3857 };
3858 if ret > 0 {
3859 Ok(ret as usize)
3860 } else {
3861 Err(self.make_error(ret))
3862 }
3863 }
3864 }
3865 }
3866
3867 #[corresponds(SSL_peek_ex)]
3869 pub fn ssl_peek(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
3870 cfg_if! {
3871 if #[cfg(any(ossl111, libressl))] {
3872 let mut readbytes = 0;
3873 let ret = unsafe {
3874 ffi::SSL_peek_ex(
3875 self.ssl().as_ptr(),
3876 buf.as_mut_ptr().cast(),
3877 buf.len(),
3878 &mut readbytes,
3879 )
3880 };
3881
3882 if ret > 0 {
3883 Ok(readbytes)
3884 } else {
3885 Err(self.make_error(ret))
3886 }
3887 } else {
3888 if buf.is_empty() {
3889 return Ok(0);
3890 }
3891
3892 let len = usize::min(c_int::MAX as usize, buf.len()) as c_int;
3893 let ret = unsafe {
3894 ffi::SSL_peek(self.ssl().as_ptr(), buf.as_mut_ptr().cast(), len)
3895 };
3896 if ret > 0 {
3897 Ok(ret as usize)
3898 } else {
3899 Err(self.make_error(ret))
3900 }
3901 }
3902 }
3903 }
3904
3905 #[corresponds(SSL_shutdown)]
3915 pub fn shutdown(&mut self) -> Result<ShutdownResult, Error> {
3916 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } {
3917 0 => Ok(ShutdownResult::Sent),
3918 1 => Ok(ShutdownResult::Received),
3919 n => Err(self.make_error(n)),
3920 }
3921 }
3922
3923 #[corresponds(SSL_get_shutdown)]
3925 pub fn get_shutdown(&mut self) -> ShutdownState {
3926 unsafe {
3927 let bits = ffi::SSL_get_shutdown(self.ssl.as_ptr());
3928 ShutdownState::from_bits_retain(bits)
3929 }
3930 }
3931
3932 #[corresponds(SSL_set_shutdown)]
3937 pub fn set_shutdown(&mut self, state: ShutdownState) {
3938 unsafe { ffi::SSL_set_shutdown(self.ssl.as_ptr(), state.bits()) }
3939 }
3940}
3941
3942impl<S> SslStream<S> {
3943 fn make_error(&mut self, ret: c_int) -> Error {
3944 self.check_panic();
3945
3946 let code = self.ssl.get_error(ret);
3947
3948 let cause = match code {
3949 ErrorCode::SSL => Some(InnerError::Ssl(ErrorStack::get())),
3950 ErrorCode::SYSCALL => {
3951 let errs = ErrorStack::get();
3952 if errs.errors().is_empty() {
3953 self.get_bio_error().map(InnerError::Io)
3954 } else {
3955 Some(InnerError::Ssl(errs))
3956 }
3957 }
3958 ErrorCode::ZERO_RETURN => None,
3959 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
3960 self.get_bio_error().map(InnerError::Io)
3961 }
3962 _ => None,
3963 };
3964
3965 Error { code, cause }
3966 }
3967
3968 fn check_panic(&mut self) {
3969 if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
3970 resume_unwind(err)
3971 }
3972 }
3973
3974 fn get_bio_error(&mut self) -> Option<io::Error> {
3975 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
3976 }
3977
3978 pub fn get_ref(&self) -> &S {
3980 unsafe {
3981 let bio = self.ssl.get_raw_rbio();
3982 bio::get_ref(bio)
3983 }
3984 }
3985
3986 pub fn get_mut(&mut self) -> &mut S {
3993 unsafe {
3994 let bio = self.ssl.get_raw_rbio();
3995 bio::get_mut(bio)
3996 }
3997 }
3998
3999 pub fn ssl(&self) -> &SslRef {
4001 &self.ssl
4002 }
4003}
4004
4005impl<S: Read + Write> Read for SslStream<S> {
4006 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
4007 unsafe {
4009 self.read_uninit(util::from_raw_parts_mut(
4010 buf.as_mut_ptr().cast::<MaybeUninit<u8>>(),
4011 buf.len(),
4012 ))
4013 }
4014 }
4015}
4016
4017impl<S: Read + Write> Write for SslStream<S> {
4018 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
4019 loop {
4020 match self.ssl_write(buf) {
4021 Ok(n) => return Ok(n),
4022 Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
4023 Err(e) => {
4024 return Err(e
4025 .into_io_error()
4026 .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)));
4027 }
4028 }
4029 }
4030 }
4031
4032 fn flush(&mut self) -> io::Result<()> {
4033 self.get_mut().flush()
4034 }
4035}
4036
4037#[deprecated(
4039 since = "0.10.32",
4040 note = "use the methods directly on Ssl/SslStream instead"
4041)]
4042pub struct SslStreamBuilder<S> {
4043 inner: SslStream<S>,
4044}
4045
4046#[allow(deprecated)]
4047impl<S> SslStreamBuilder<S>
4048where
4049 S: Read + Write,
4050{
4051 pub fn new(ssl: Ssl, stream: S) -> Self {
4053 Self {
4054 inner: SslStream::new(ssl, stream).unwrap(),
4055 }
4056 }
4057
4058 #[corresponds(SSL_stateless)]
4069 #[cfg(ossl111)]
4070 pub fn stateless(&mut self) -> Result<bool, ErrorStack> {
4071 match unsafe { ffi::SSL_stateless(self.inner.ssl.as_ptr()) } {
4072 1 => Ok(true),
4073 0 => Ok(false),
4074 -1 => Err(ErrorStack::get()),
4075 _ => unreachable!(),
4076 }
4077 }
4078
4079 #[corresponds(SSL_set_connect_state)]
4081 pub fn set_connect_state(&mut self) {
4082 unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
4083 }
4084
4085 #[corresponds(SSL_set_accept_state)]
4087 pub fn set_accept_state(&mut self) {
4088 unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
4089 }
4090
4091 pub fn connect(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4093 match self.inner.connect() {
4094 Ok(()) => Ok(self.inner),
4095 Err(error) => match error.code() {
4096 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4097 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4098 stream: self.inner,
4099 error,
4100 }))
4101 }
4102 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4103 stream: self.inner,
4104 error,
4105 })),
4106 },
4107 }
4108 }
4109
4110 pub fn accept(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4112 match self.inner.accept() {
4113 Ok(()) => Ok(self.inner),
4114 Err(error) => match error.code() {
4115 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4116 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4117 stream: self.inner,
4118 error,
4119 }))
4120 }
4121 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4122 stream: self.inner,
4123 error,
4124 })),
4125 },
4126 }
4127 }
4128
4129 #[corresponds(SSL_do_handshake)]
4133 pub fn handshake(mut self) -> Result<SslStream<S>, HandshakeError<S>> {
4134 match self.inner.do_handshake() {
4135 Ok(()) => Ok(self.inner),
4136 Err(error) => match error.code() {
4137 ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => {
4138 Err(HandshakeError::WouldBlock(MidHandshakeSslStream {
4139 stream: self.inner,
4140 error,
4141 }))
4142 }
4143 _ => Err(HandshakeError::Failure(MidHandshakeSslStream {
4144 stream: self.inner,
4145 error,
4146 })),
4147 },
4148 }
4149 }
4150
4151 #[corresponds(SSL_read_early_data)]
4161 #[cfg(any(ossl111, libressl))]
4162 pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
4163 self.inner.read_early_data(buf)
4164 }
4165
4166 #[corresponds(SSL_write_early_data)]
4173 #[cfg(any(ossl111, libressl))]
4174 pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
4175 self.inner.write_early_data(buf)
4176 }
4177}
4178
4179#[allow(deprecated)]
4180impl<S> SslStreamBuilder<S> {
4181 pub fn get_ref(&self) -> &S {
4183 unsafe {
4184 let bio = self.inner.ssl.get_raw_rbio();
4185 bio::get_ref(bio)
4186 }
4187 }
4188
4189 pub fn get_mut(&mut self) -> &mut S {
4196 unsafe {
4197 let bio = self.inner.ssl.get_raw_rbio();
4198 bio::get_mut(bio)
4199 }
4200 }
4201
4202 pub fn ssl(&self) -> &SslRef {
4204 &self.inner.ssl
4205 }
4206
4207 #[deprecated(note = "Use SslRef::set_mtu instead", since = "0.10.30")]
4215 pub fn set_dtls_mtu_size(&mut self, mtu_size: usize) {
4216 unsafe {
4217 let bio = self.inner.ssl.get_raw_rbio();
4218 bio::set_dtls_mtu_size::<S>(bio, mtu_size);
4219 }
4220 }
4221}
4222
4223#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4225pub enum ShutdownResult {
4226 Sent,
4228
4229 Received,
4231}
4232
4233bitflags! {
4234 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
4236 #[repr(transparent)]
4237 pub struct ShutdownState: c_int {
4238 const SENT = ffi::SSL_SENT_SHUTDOWN;
4240 const RECEIVED = ffi::SSL_RECEIVED_SHUTDOWN;
4242 }
4243}
4244
4245cfg_if! {
4246 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
4247 use ffi::{SSL_CTX_up_ref, SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server};
4248 } else {
4249 #[allow(bad_style)]
4250 pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
4251 ffi::CRYPTO_add_lock(
4252 &mut (*ssl).references,
4253 1,
4254 ffi::CRYPTO_LOCK_SSL_CTX,
4255 "mod.rs\0".as_ptr() as *const _,
4256 line!() as c_int,
4257 );
4258 0
4259 }
4260
4261 #[allow(bad_style)]
4262 pub unsafe fn SSL_SESSION_get_master_key(
4263 session: *const ffi::SSL_SESSION,
4264 out: *mut c_uchar,
4265 mut outlen: usize,
4266 ) -> usize {
4267 if outlen == 0 {
4268 return (*session).master_key_length as usize;
4269 }
4270 if outlen > (*session).master_key_length as usize {
4271 outlen = (*session).master_key_length as usize;
4272 }
4273 ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
4274 outlen
4275 }
4276
4277 #[allow(bad_style)]
4278 pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
4279 (*s).server
4280 }
4281
4282 #[allow(bad_style)]
4283 pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
4284 ffi::CRYPTO_add_lock(
4285 &mut (*ses).references,
4286 1,
4287 ffi::CRYPTO_LOCK_SSL_CTX,
4288 "mod.rs\0".as_ptr() as *const _,
4289 line!() as c_int,
4290 );
4291 0
4292 }
4293 }
4294}
4295
4296cfg_if! {
4297 if #[cfg(ossl300)] {
4298 use ffi::SSL_get1_peer_certificate;
4299 } else {
4300 use ffi::SSL_get_peer_certificate as SSL_get1_peer_certificate;
4301 }
4302}
4303cfg_if! {
4304 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
4305 use ffi::{TLS_method, DTLS_method, TLS_client_method, TLS_server_method, DTLS_server_method, DTLS_client_method};
4306 } else {
4307 use ffi::{
4308 SSLv23_method as TLS_method, DTLSv1_method as DTLS_method, SSLv23_client_method as TLS_client_method,
4309 SSLv23_server_method as TLS_server_method,
4310 };
4311 }
4312}
4313cfg_if! {
4314 if #[cfg(ossl110)] {
4315 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4316 ffi::CRYPTO_get_ex_new_index(
4317 ffi::CRYPTO_EX_INDEX_SSL_CTX,
4318 0,
4319 ptr::null_mut(),
4320 None,
4321 None,
4322 Some(f),
4323 )
4324 }
4325
4326 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4327 ffi::CRYPTO_get_ex_new_index(
4328 ffi::CRYPTO_EX_INDEX_SSL,
4329 0,
4330 ptr::null_mut(),
4331 None,
4332 None,
4333 Some(f),
4334 )
4335 }
4336 } else {
4337 use std::sync::Once;
4338
4339 unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4340 static ONCE: Once = Once::new();
4342 ONCE.call_once(|| {
4343 cfg_if! {
4344 if #[cfg(not(any(boringssl, awslc)))] {
4345 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4346 } else {
4347 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4348 }
4349 }
4350 });
4351
4352 cfg_if! {
4353 if #[cfg(not(any(boringssl, awslc)))] {
4354 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
4355 } else {
4356 ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f)
4357 }
4358 }
4359 }
4360
4361 unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
4362 static ONCE: Once = Once::new();
4364 ONCE.call_once(|| {
4365 #[cfg(not(any(boringssl, awslc)))]
4366 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, None);
4367 #[cfg(any(boringssl, awslc))]
4368 ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, None);
4369 });
4370
4371 #[cfg(not(any(boringssl, awslc)))]
4372 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f));
4373 #[cfg(any(boringssl, awslc))]
4374 return ffi::SSL_get_ex_new_index(0, ptr::null_mut(), ptr::null_mut(), None, f);
4375 }
4376 }
4377}