1#[cfg(ossl300)]
61use crate::cvt_long;
62use crate::dh::{Dh, DhRef};
63#[cfg(all(ossl101, not(ossl110)))]
64use crate::ec::EcKey;
65use crate::ec::EcKeyRef;
66use crate::error::ErrorStack;
67use crate::ex_data::Index;
68#[cfg(ossl111)]
69use crate::hash::MessageDigest;
70#[cfg(any(ossl110, libressl270))]
71use crate::nid::Nid;
72use crate::pkey::{HasPrivate, PKeyRef, Params, Private};
73#[cfg(ossl300)]
74use crate::pkey::{PKey, Public};
75use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
76use crate::ssl::bio::BioMethod;
77use crate::ssl::callbacks::*;
78use crate::ssl::error::InnerError;
79use crate::stack::{Stack, StackRef, Stackable};
80use crate::util;
81use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
82use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
83#[cfg(any(ossl102, boringssl, libressl261, awslc))]
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, libressl340, awslc))]
226 const NO_TLSV1_3 = ffi::SSL_OP_NO_TLSv1_3 as SslOptionsRepr;
227
228 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
232 const NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1 as SslOptionsRepr;
233
234 #[cfg(any(boringssl, ossl102, ossl110, libressl332, awslc))]
238 const NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2 as SslOptionsRepr;
239
240 #[cfg(any(ossl102, ossl110))]
256 const NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK as SslOptionsRepr;
257
258 #[cfg(any(boringssl, ossl110h, awslc))]
262 const NO_RENEGOTIATION = ffi::SSL_OP_NO_RENEGOTIATION as SslOptionsRepr;
263
264 #[cfg(ossl111)]
269 const ENABLE_MIDDLEBOX_COMPAT = ffi::SSL_OP_ENABLE_MIDDLEBOX_COMPAT as SslOptionsRepr;
270
271 #[cfg(ossl111)]
283 const PRIORITIZE_CHACHA = ffi::SSL_OP_PRIORITIZE_CHACHA as SslOptionsRepr;
284 }
285}
286
287bitflags! {
288 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
290 #[repr(transparent)]
291 pub struct SslMode: SslBitType {
292 const ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE;
298
299 const ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
302
303 const AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY;
313
314 const NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN;
320
321 const RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS;
325
326 #[cfg(not(libressl))]
334 const SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV;
335 }
336}
337
338#[derive(Copy, Clone)]
340pub struct SslMethod(*const ffi::SSL_METHOD);
341
342impl SslMethod {
343 #[corresponds(TLS_method)]
345 pub fn tls() -> SslMethod {
346 unsafe { SslMethod(TLS_method()) }
347 }
348
349 #[corresponds(DTLS_method)]
351 pub fn dtls() -> SslMethod {
352 unsafe { SslMethod(DTLS_method()) }
353 }
354
355 #[corresponds(TLS_client_method)]
357 pub fn tls_client() -> SslMethod {
358 unsafe { SslMethod(TLS_client_method()) }
359 }
360
361 #[corresponds(TLS_server_method)]
363 pub fn tls_server() -> SslMethod {
364 unsafe { SslMethod(TLS_server_method()) }
365 }
366
367 #[corresponds(DTLS_client_method)]
369 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
370 pub fn dtls_client() -> SslMethod {
371 unsafe { SslMethod(DTLS_client_method()) }
372 }
373
374 #[corresponds(DTLS_server_method)]
376 #[cfg(any(boringssl, ossl110, libressl291, awslc))]
377 pub fn dtls_server() -> SslMethod {
378 unsafe { SslMethod(DTLS_server_method()) }
379 }
380
381 pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod {
387 SslMethod(ptr)
388 }
389
390 #[allow(clippy::trivially_copy_pass_by_ref)]
392 pub fn as_ptr(&self) -> *const ffi::SSL_METHOD {
393 self.0
394 }
395}
396
397unsafe impl Sync for SslMethod {}
398unsafe impl Send for SslMethod {}
399
400bitflags! {
401 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
403 #[repr(transparent)]
404 pub struct SslVerifyMode: i32 {
405 const PEER = ffi::SSL_VERIFY_PEER;
409
410 const NONE = ffi::SSL_VERIFY_NONE;
416
417 const FAIL_IF_NO_PEER_CERT = ffi::SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
421 }
422}
423
424#[cfg(any(boringssl, awslc))]
425type SslBitType = c_int;
426#[cfg(not(any(boringssl, awslc)))]
427type SslBitType = c_long;
428
429#[cfg(any(boringssl, awslc))]
430type SslTimeTy = u64;
431#[cfg(not(any(boringssl, awslc)))]
432type SslTimeTy = c_long;
433
434bitflags! {
435 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
437 #[repr(transparent)]
438 pub struct SslSessionCacheMode: SslBitType {
439 const OFF = ffi::SSL_SESS_CACHE_OFF;
441
442 const CLIENT = ffi::SSL_SESS_CACHE_CLIENT;
449
450 const SERVER = ffi::SSL_SESS_CACHE_SERVER;
454
455 const BOTH = ffi::SSL_SESS_CACHE_BOTH;
457
458 const NO_AUTO_CLEAR = ffi::SSL_SESS_CACHE_NO_AUTO_CLEAR;
460
461 const NO_INTERNAL_LOOKUP = ffi::SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
463
464 const NO_INTERNAL_STORE = ffi::SSL_SESS_CACHE_NO_INTERNAL_STORE;
466
467 const NO_INTERNAL = ffi::SSL_SESS_CACHE_NO_INTERNAL;
469 }
470}
471
472#[cfg(ossl111)]
473bitflags! {
474 #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
476 #[repr(transparent)]
477 pub struct ExtensionContext: c_uint {
478 const TLS_ONLY = ffi::SSL_EXT_TLS_ONLY;
480 const DTLS_ONLY = ffi::SSL_EXT_DTLS_ONLY;
482 const TLS_IMPLEMENTATION_ONLY = ffi::SSL_EXT_TLS_IMPLEMENTATION_ONLY;
484 const SSL3_ALLOWED = ffi::SSL_EXT_SSL3_ALLOWED;
486 const TLS1_2_AND_BELOW_ONLY = ffi::SSL_EXT_TLS1_2_AND_BELOW_ONLY;
488 const TLS1_3_ONLY = ffi::SSL_EXT_TLS1_3_ONLY;
490 const IGNORE_ON_RESUMPTION = ffi::SSL_EXT_IGNORE_ON_RESUMPTION;
492 const CLIENT_HELLO = ffi::SSL_EXT_CLIENT_HELLO;
493 const TLS1_2_SERVER_HELLO = ffi::SSL_EXT_TLS1_2_SERVER_HELLO;
495 const TLS1_3_SERVER_HELLO = ffi::SSL_EXT_TLS1_3_SERVER_HELLO;
496 const TLS1_3_ENCRYPTED_EXTENSIONS = ffi::SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS;
497 const TLS1_3_HELLO_RETRY_REQUEST = ffi::SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST;
498 const TLS1_3_CERTIFICATE = ffi::SSL_EXT_TLS1_3_CERTIFICATE;
499 const TLS1_3_NEW_SESSION_TICKET = ffi::SSL_EXT_TLS1_3_NEW_SESSION_TICKET;
500 const TLS1_3_CERTIFICATE_REQUEST = ffi::SSL_EXT_TLS1_3_CERTIFICATE_REQUEST;
501 }
502}
503
504#[derive(Copy, Clone)]
506pub struct SslFiletype(c_int);
507
508impl SslFiletype {
509 pub const PEM: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_PEM);
513
514 pub const ASN1: SslFiletype = SslFiletype(ffi::SSL_FILETYPE_ASN1);
518
519 pub fn from_raw(raw: c_int) -> SslFiletype {
521 SslFiletype(raw)
522 }
523
524 #[allow(clippy::trivially_copy_pass_by_ref)]
526 pub fn as_raw(&self) -> c_int {
527 self.0
528 }
529}
530
531#[derive(Copy, Clone)]
533pub struct StatusType(c_int);
534
535impl StatusType {
536 pub const OCSP: StatusType = StatusType(ffi::TLSEXT_STATUSTYPE_ocsp);
538
539 pub fn from_raw(raw: c_int) -> StatusType {
541 StatusType(raw)
542 }
543
544 #[allow(clippy::trivially_copy_pass_by_ref)]
546 pub fn as_raw(&self) -> c_int {
547 self.0
548 }
549}
550
551#[derive(Copy, Clone)]
553pub struct NameType(c_int);
554
555impl NameType {
556 pub const HOST_NAME: NameType = NameType(ffi::TLSEXT_NAMETYPE_host_name);
558
559 pub fn from_raw(raw: c_int) -> StatusType {
561 StatusType(raw)
562 }
563
564 #[allow(clippy::trivially_copy_pass_by_ref)]
566 pub fn as_raw(&self) -> c_int {
567 self.0
568 }
569}
570
571static INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
572static SSL_INDEXES: Lazy<Mutex<HashMap<TypeId, c_int>>> = Lazy::new(|| Mutex::new(HashMap::new()));
573static SESSION_CTX_INDEX: OnceCell<Index<Ssl, SslContext>> = OnceCell::new();
574
575fn try_get_session_ctx_index() -> Result<&'static Index<Ssl, SslContext>, ErrorStack> {
576 SESSION_CTX_INDEX.get_or_try_init(Ssl::new_ex_index)
577}
578
579unsafe extern "C" fn free_data_box<T>(
580 _parent: *mut c_void,
581 ptr: *mut c_void,
582 _ad: *mut ffi::CRYPTO_EX_DATA,
583 _idx: c_int,
584 _argl: c_long,
585 _argp: *mut c_void,
586) {
587 if !ptr.is_null() {
588 let _ = Box::<T>::from_raw(ptr as *mut T);
589 }
590}
591
592#[derive(Debug, Copy, Clone, PartialEq, Eq)]
594pub struct SniError(c_int);
595
596impl SniError {
597 pub const ALERT_FATAL: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
599
600 pub const ALERT_WARNING: SniError = SniError(ffi::SSL_TLSEXT_ERR_ALERT_WARNING);
602
603 pub const NOACK: SniError = SniError(ffi::SSL_TLSEXT_ERR_NOACK);
604}
605
606#[derive(Debug, Copy, Clone, PartialEq, Eq)]
608pub struct SslAlert(c_int);
609
610impl SslAlert {
611 pub const UNRECOGNIZED_NAME: SslAlert = SslAlert(ffi::SSL_AD_UNRECOGNIZED_NAME);
613 pub const ILLEGAL_PARAMETER: SslAlert = SslAlert(ffi::SSL_AD_ILLEGAL_PARAMETER);
614 pub const DECODE_ERROR: SslAlert = SslAlert(ffi::SSL_AD_DECODE_ERROR);
615}
616
617#[cfg(any(ossl102, libressl261, boringssl, awslc))]
621#[derive(Debug, Copy, Clone, PartialEq, Eq)]
622pub struct AlpnError(c_int);
623
624#[cfg(any(ossl102, libressl261, boringssl, awslc))]
625impl AlpnError {
626 #[cfg(any(ossl110, boringssl, awslc))]
630 pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
631
632 pub const NOACK: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_NOACK);
634}
635
636#[cfg(ossl111)]
640#[derive(Debug, Copy, Clone, PartialEq, Eq)]
641pub struct ClientHelloResponse(c_int);
642
643#[cfg(ossl111)]
644impl ClientHelloResponse {
645 pub const SUCCESS: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_SUCCESS);
647
648 pub const RETRY: ClientHelloResponse = ClientHelloResponse(ffi::SSL_CLIENT_HELLO_RETRY);
650}
651
652#[derive(Debug, Copy, Clone, PartialEq, Eq)]
654pub struct SslVersion(c_int);
655
656impl SslVersion {
657 pub const SSL3: SslVersion = SslVersion(ffi::SSL3_VERSION);
659
660 pub const TLS1: SslVersion = SslVersion(ffi::TLS1_VERSION);
662
663 pub const TLS1_1: SslVersion = SslVersion(ffi::TLS1_1_VERSION);
665
666 pub const TLS1_2: SslVersion = SslVersion(ffi::TLS1_2_VERSION);
668
669 #[cfg(any(ossl111, libressl340, boringssl, awslc))]
673 pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
674
675 pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
679
680 #[cfg(any(ossl102, libressl332, boringssl, awslc))]
684 pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
685}
686
687cfg_if! {
688 if #[cfg(any(boringssl, awslc))] {
689 type SslCacheTy = i64;
690 type SslCacheSize = libc::c_ulong;
691 type MtuTy = u32;
692 type SizeTy = usize;
693 } else {
694 type SslCacheTy = i64;
695 type SslCacheSize = c_long;
696 type MtuTy = c_long;
697 type SizeTy = u32;
698 }
699}
700
701#[corresponds(SSL_select_next_proto)]
712pub fn select_next_proto<'a>(server: &'a [u8], client: &'a [u8]) -> Option<&'a [u8]> {
713 unsafe {
714 let mut out = ptr::null_mut();
715 let mut outlen = 0;
716 let r = ffi::SSL_select_next_proto(
717 &mut out,
718 &mut outlen,
719 server.as_ptr(),
720 server.len() as c_uint,
721 client.as_ptr(),
722 client.len() as c_uint,
723 );
724 if r == ffi::OPENSSL_NPN_NEGOTIATED {
725 Some(util::from_raw_parts(out as *const u8, outlen as usize))
726 } else {
727 None
728 }
729 }
730}
731
732pub struct SslContextBuilder(SslContext);
734
735impl SslContextBuilder {
736 #[corresponds(SSL_CTX_new)]
738 pub fn new(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
739 unsafe {
740 init();
741 let ctx = cvt_p(ffi::SSL_CTX_new(method.as_ptr()))?;
742
743 Ok(SslContextBuilder::from_ptr(ctx))
744 }
745 }
746
747 pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder {
753 SslContextBuilder(SslContext::from_ptr(ctx))
754 }
755
756 pub fn as_ptr(&self) -> *mut ffi::SSL_CTX {
758 self.0.as_ptr()
759 }
760
761 #[corresponds(SSL_CTX_set_verify)]
763 pub fn set_verify(&mut self, mode: SslVerifyMode) {
764 unsafe {
765 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, None);
766 }
767 }
768
769 #[corresponds(SSL_CTX_set_verify)]
776 pub fn set_verify_callback<F>(&mut self, mode: SslVerifyMode, verify: F)
777 where
778 F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
779 {
780 unsafe {
781 self.set_ex_data(SslContext::cached_ex_index::<F>(), verify);
782 ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits() as c_int, Some(raw_verify::<F>));
783 }
784 }
785
786 #[corresponds(SSL_CTX_set_tlsext_servername_callback)]
794 pub fn set_servername_callback<F>(&mut self, callback: F)
796 where
797 F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
798 {
799 unsafe {
800 let arg = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
806 ffi::SSL_CTX_set_tlsext_servername_arg(self.as_ptr(), arg);
807 #[cfg(any(boringssl, awslc))]
808 ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(raw_sni::<F>));
809 #[cfg(not(any(boringssl, awslc)))]
810 ffi::SSL_CTX_set_tlsext_servername_callback__fixed_rust(
811 self.as_ptr(),
812 Some(raw_sni::<F>),
813 );
814 }
815 }
816
817 #[corresponds(SSL_CTX_set_verify_depth)]
821 pub fn set_verify_depth(&mut self, depth: u32) {
822 unsafe {
823 ffi::SSL_CTX_set_verify_depth(self.as_ptr(), depth as c_int);
824 }
825 }
826
827 #[corresponds(SSL_CTX_set0_verify_cert_store)]
831 #[cfg(ossl102)]
832 pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> {
833 unsafe {
834 let ptr = cert_store.as_ptr();
835 cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as c_int)?;
836 mem::forget(cert_store);
837
838 Ok(())
839 }
840 }
841
842 #[corresponds(SSL_CTX_set_cert_store)]
844 pub fn set_cert_store(&mut self, cert_store: X509Store) {
845 unsafe {
846 ffi::SSL_CTX_set_cert_store(self.as_ptr(), cert_store.as_ptr());
847 mem::forget(cert_store);
848 }
849 }
850
851 #[corresponds(SSL_CTX_set_read_ahead)]
858 pub fn set_read_ahead(&mut self, read_ahead: bool) {
859 unsafe {
860 ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as SslBitType);
861 }
862 }
863
864 #[corresponds(SSL_CTX_set_mode)]
866 pub fn set_mode(&mut self, mode: SslMode) -> SslMode {
867 unsafe {
868 let bits = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits() as MtuTy) as SslBitType;
869 SslMode::from_bits_retain(bits)
870 }
871 }
872
873 #[corresponds(SSL_CTX_set_tmp_dh)]
875 pub fn set_tmp_dh(&mut self, dh: &DhRef<Params>) -> Result<(), ErrorStack> {
876 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
877 }
878
879 #[corresponds(SSL_CTX_set_tmp_dh_callback)]
886 pub fn set_tmp_dh_callback<F>(&mut self, callback: F)
887 where
888 F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
889 {
890 unsafe {
891 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
892
893 #[cfg(not(any(boringssl, awslc)))]
894 ffi::SSL_CTX_set_tmp_dh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_dh::<F>));
895 #[cfg(any(boringssl, awslc))]
896 ffi::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), Some(raw_tmp_dh::<F>));
897 }
898 }
899
900 #[corresponds(SSL_CTX_set_tmp_ecdh)]
902 pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef<Params>) -> Result<(), ErrorStack> {
903 unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
904 }
905
906 #[corresponds(SSL_CTX_set_tmp_ecdh_callback)]
915 #[cfg(all(ossl101, not(ossl110)))]
916 #[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
917 pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
918 where
919 F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
920 {
921 unsafe {
922 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
923 ffi::SSL_CTX_set_tmp_ecdh_callback__fixed_rust(self.as_ptr(), Some(raw_tmp_ecdh::<F>));
924 }
925 }
926
927 #[corresponds(SSL_CTX_set_default_verify_paths)]
932 pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> {
933 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
934 }
935
936 #[corresponds(SSL_CTX_load_verify_locations)]
940 pub fn set_ca_file<P: AsRef<Path>>(&mut self, file: P) -> Result<(), ErrorStack> {
941 self.load_verify_locations(Some(file.as_ref()), None)
942 }
943
944 #[corresponds(SSL_CTX_load_verify_locations)]
946 pub fn load_verify_locations(
947 &mut self,
948 ca_file: Option<&Path>,
949 ca_path: Option<&Path>,
950 ) -> Result<(), ErrorStack> {
951 let ca_file = ca_file.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
952 let ca_path = ca_path.map(|p| CString::new(p.as_os_str().to_str().unwrap()).unwrap());
953 unsafe {
954 cvt(ffi::SSL_CTX_load_verify_locations(
955 self.as_ptr(),
956 ca_file.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
957 ca_path.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
958 ))
959 .map(|_| ())
960 }
961 }
962
963 #[corresponds(SSL_CTX_set_client_CA_list)]
968 pub fn set_client_ca_list(&mut self, list: Stack<X509Name>) {
969 unsafe {
970 ffi::SSL_CTX_set_client_CA_list(self.as_ptr(), list.as_ptr());
971 mem::forget(list);
972 }
973 }
974
975 #[corresponds(SSL_CTX_add_client_CA)]
978 pub fn add_client_ca(&mut self, cacert: &X509Ref) -> Result<(), ErrorStack> {
979 unsafe { cvt(ffi::SSL_CTX_add_client_CA(self.as_ptr(), cacert.as_ptr())).map(|_| ()) }
980 }
981
982 #[corresponds(SSL_CTX_set_session_id_context)]
991 pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> {
992 unsafe {
993 assert!(sid_ctx.len() <= c_uint::MAX as usize);
994 cvt(ffi::SSL_CTX_set_session_id_context(
995 self.as_ptr(),
996 sid_ctx.as_ptr(),
997 sid_ctx.len() as SizeTy,
998 ))
999 .map(|_| ())
1000 }
1001 }
1002
1003 #[corresponds(SSL_CTX_use_certificate_file)]
1009 pub fn set_certificate_file<P: AsRef<Path>>(
1010 &mut self,
1011 file: P,
1012 file_type: SslFiletype,
1013 ) -> Result<(), ErrorStack> {
1014 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1015 unsafe {
1016 cvt(ffi::SSL_CTX_use_certificate_file(
1017 self.as_ptr(),
1018 file.as_ptr() as *const _,
1019 file_type.as_raw(),
1020 ))
1021 .map(|_| ())
1022 }
1023 }
1024
1025 #[corresponds(SSL_CTX_use_certificate_chain_file)]
1031 pub fn set_certificate_chain_file<P: AsRef<Path>>(
1032 &mut self,
1033 file: P,
1034 ) -> Result<(), ErrorStack> {
1035 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1036 unsafe {
1037 cvt(ffi::SSL_CTX_use_certificate_chain_file(
1038 self.as_ptr(),
1039 file.as_ptr() as *const _,
1040 ))
1041 .map(|_| ())
1042 }
1043 }
1044
1045 #[corresponds(SSL_CTX_use_certificate)]
1049 pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> {
1050 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
1051 }
1052
1053 #[corresponds(SSL_CTX_add_extra_chain_cert)]
1058 pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
1059 unsafe {
1060 cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?;
1061 mem::forget(cert);
1062 Ok(())
1063 }
1064 }
1065
1066 #[corresponds(SSL_CTX_use_PrivateKey_file)]
1068 pub fn set_private_key_file<P: AsRef<Path>>(
1069 &mut self,
1070 file: P,
1071 file_type: SslFiletype,
1072 ) -> Result<(), ErrorStack> {
1073 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
1074 unsafe {
1075 cvt(ffi::SSL_CTX_use_PrivateKey_file(
1076 self.as_ptr(),
1077 file.as_ptr() as *const _,
1078 file_type.as_raw(),
1079 ))
1080 .map(|_| ())
1081 }
1082 }
1083
1084 #[corresponds(SSL_CTX_use_PrivateKey)]
1086 pub fn set_private_key<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack>
1087 where
1088 T: HasPrivate,
1089 {
1090 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
1091 }
1092
1093 #[corresponds(SSL_CTX_set_cipher_list)]
1101 pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1102 let cipher_list = CString::new(cipher_list).unwrap();
1103 unsafe {
1104 cvt(ffi::SSL_CTX_set_cipher_list(
1105 self.as_ptr(),
1106 cipher_list.as_ptr() as *const _,
1107 ))
1108 .map(|_| ())
1109 }
1110 }
1111
1112 #[corresponds(SSL_CTX_set_ciphersuites)]
1121 #[cfg(any(ossl111, libressl340))]
1122 pub fn set_ciphersuites(&mut self, cipher_list: &str) -> Result<(), ErrorStack> {
1123 let cipher_list = CString::new(cipher_list).unwrap();
1124 unsafe {
1125 cvt(ffi::SSL_CTX_set_ciphersuites(
1126 self.as_ptr(),
1127 cipher_list.as_ptr() as *const _,
1128 ))
1129 .map(|_| ())
1130 }
1131 }
1132
1133 #[corresponds(SSL_CTX_set_ecdh_auto)]
1137 #[cfg(any(libressl, all(ossl102, not(ossl110))))]
1138 pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
1139 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1140 }
1141
1142 #[corresponds(SSL_CTX_set_options)]
1149 pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
1150 let bits =
1151 unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1152 SslOptions::from_bits_retain(bits)
1153 }
1154
1155 #[corresponds(SSL_CTX_get_options)]
1157 pub fn options(&self) -> SslOptions {
1158 let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) } as SslOptionsRepr;
1159 SslOptions::from_bits_retain(bits)
1160 }
1161
1162 #[corresponds(SSL_CTX_clear_options)]
1164 pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
1165 let bits =
1166 unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) } as SslOptionsRepr;
1167 SslOptions::from_bits_retain(bits)
1168 }
1169
1170 #[corresponds(SSL_CTX_set_min_proto_version)]
1177 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1178 pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1179 unsafe {
1180 cvt(ffi::SSL_CTX_set_min_proto_version(
1181 self.as_ptr(),
1182 version.map_or(0, |v| v.0 as _),
1183 ))
1184 .map(|_| ())
1185 }
1186 }
1187
1188 #[corresponds(SSL_CTX_set_max_proto_version)]
1195 #[cfg(any(ossl110, libressl261, boringssl, awslc))]
1196 pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
1197 unsafe {
1198 cvt(ffi::SSL_CTX_set_max_proto_version(
1199 self.as_ptr(),
1200 version.map_or(0, |v| v.0 as _),
1201 ))
1202 .map(|_| ())
1203 }
1204 }
1205
1206 #[corresponds(SSL_CTX_get_min_proto_version)]
1213 #[cfg(any(ossl110g, libressl270))]
1214 pub fn min_proto_version(&mut self) -> Option<SslVersion> {
1215 unsafe {
1216 let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
1217 if r == 0 {
1218 None
1219 } else {
1220 Some(SslVersion(r))
1221 }
1222 }
1223 }
1224
1225 #[corresponds(SSL_CTX_get_max_proto_version)]
1232 #[cfg(any(ossl110g, libressl270))]
1233 pub fn max_proto_version(&mut self) -> Option<SslVersion> {
1234 unsafe {
1235 let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
1236 if r == 0 {
1237 None
1238 } else {
1239 Some(SslVersion(r))
1240 }
1241 }
1242 }
1243
1244 #[corresponds(SSL_CTX_set_alpn_protos)]
1253 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1254 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
1255 unsafe {
1256 assert!(protocols.len() <= c_uint::MAX as usize);
1257 let r = ffi::SSL_CTX_set_alpn_protos(
1258 self.as_ptr(),
1259 protocols.as_ptr(),
1260 protocols.len() as _,
1261 );
1262 if r == 0 {
1264 Ok(())
1265 } else {
1266 Err(ErrorStack::get())
1267 }
1268 }
1269 }
1270
1271 #[corresponds(SSL_CTX_set_tlsext_use_srtp)]
1273 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
1274 unsafe {
1275 let cstr = CString::new(protocols).unwrap();
1276
1277 let r = ffi::SSL_CTX_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
1278 if r == 0 {
1280 Ok(())
1281 } else {
1282 Err(ErrorStack::get())
1283 }
1284 }
1285 }
1286
1287 #[corresponds(SSL_CTX_set_alpn_select_cb)]
1300 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
1301 pub fn set_alpn_select_callback<F>(&mut self, callback: F)
1302 where
1303 F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
1304 {
1305 unsafe {
1306 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1307 #[cfg(not(any(boringssl, awslc)))]
1308 ffi::SSL_CTX_set_alpn_select_cb__fixed_rust(
1309 self.as_ptr(),
1310 Some(callbacks::raw_alpn_select::<F>),
1311 ptr::null_mut(),
1312 );
1313 #[cfg(any(boringssl, awslc))]
1314 ffi::SSL_CTX_set_alpn_select_cb(
1315 self.as_ptr(),
1316 Some(callbacks::raw_alpn_select::<F>),
1317 ptr::null_mut(),
1318 );
1319 }
1320 }
1321
1322 #[corresponds(SSL_CTX_check_private_key)]
1324 pub fn check_private_key(&self) -> Result<(), ErrorStack> {
1325 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
1326 }
1327
1328 #[corresponds(SSL_CTX_get_cert_store)]
1330 pub fn cert_store(&self) -> &X509StoreBuilderRef {
1331 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1332 }
1333
1334 #[corresponds(SSL_CTX_get_cert_store)]
1336 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef {
1337 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1338 }
1339
1340 #[corresponds(SSL_CTX_get0_param)]
1344 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1345 pub fn verify_param(&self) -> &X509VerifyParamRef {
1346 unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1347 }
1348
1349 #[corresponds(SSL_CTX_get0_param)]
1353 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
1354 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
1355 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) }
1356 }
1357
1358 #[corresponds(SSL_CTX_set_tlsext_status_cb)]
1371 pub fn set_status_callback<F>(&mut self, callback: F) -> Result<(), ErrorStack>
1372 where
1373 F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
1374 {
1375 unsafe {
1376 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1377 cvt(
1378 ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(raw_tlsext_status::<F>))
1379 as c_int,
1380 )
1381 .map(|_| ())
1382 }
1383 }
1384
1385 #[corresponds(SSL_CTX_set_psk_client_callback)]
1391 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1392 pub fn set_psk_client_callback<F>(&mut self, callback: F)
1393 where
1394 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1395 + 'static
1396 + Sync
1397 + Send,
1398 {
1399 unsafe {
1400 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1401 ffi::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_client_psk::<F>));
1402 }
1403 }
1404
1405 #[deprecated(since = "0.10.10", note = "renamed to `set_psk_client_callback`")]
1406 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1407 pub fn set_psk_callback<F>(&mut self, callback: F)
1408 where
1409 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
1410 + 'static
1411 + Sync
1412 + Send,
1413 {
1414 self.set_psk_client_callback(callback)
1415 }
1416
1417 #[corresponds(SSL_CTX_set_psk_server_callback)]
1423 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
1424 pub fn set_psk_server_callback<F>(&mut self, callback: F)
1425 where
1426 F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
1427 + 'static
1428 + Sync
1429 + Send,
1430 {
1431 unsafe {
1432 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1433 ffi::SSL_CTX_set_psk_server_callback(self.as_ptr(), Some(raw_server_psk::<F>));
1434 }
1435 }
1436
1437 #[corresponds(SSL_CTX_sess_set_new_cb)]
1451 pub fn set_new_session_callback<F>(&mut self, callback: F)
1452 where
1453 F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
1454 {
1455 unsafe {
1456 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1457 ffi::SSL_CTX_sess_set_new_cb(self.as_ptr(), Some(callbacks::raw_new_session::<F>));
1458 }
1459 }
1460
1461 #[corresponds(SSL_CTX_sess_set_remove_cb)]
1465 pub fn set_remove_session_callback<F>(&mut self, callback: F)
1466 where
1467 F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
1468 {
1469 unsafe {
1470 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1471 ffi::SSL_CTX_sess_set_remove_cb(
1472 self.as_ptr(),
1473 Some(callbacks::raw_remove_session::<F>),
1474 );
1475 }
1476 }
1477
1478 #[corresponds(SSL_CTX_sess_set_get_cb)]
1489 pub unsafe fn set_get_session_callback<F>(&mut self, callback: F)
1490 where
1491 F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
1492 {
1493 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1494 ffi::SSL_CTX_sess_set_get_cb(self.as_ptr(), Some(callbacks::raw_get_session::<F>));
1495 }
1496
1497 #[corresponds(SSL_CTX_set_keylog_callback)]
1505 #[cfg(any(ossl111, boringssl, awslc))]
1506 pub fn set_keylog_callback<F>(&mut self, callback: F)
1507 where
1508 F: Fn(&SslRef, &str) + 'static + Sync + Send,
1509 {
1510 unsafe {
1511 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1512 ffi::SSL_CTX_set_keylog_callback(self.as_ptr(), Some(callbacks::raw_keylog::<F>));
1513 }
1514 }
1515
1516 #[corresponds(SSL_CTX_set_session_cache_mode)]
1520 pub fn set_session_cache_mode(&mut self, mode: SslSessionCacheMode) -> SslSessionCacheMode {
1521 unsafe {
1522 let bits = ffi::SSL_CTX_set_session_cache_mode(self.as_ptr(), mode.bits());
1523 SslSessionCacheMode::from_bits_retain(bits)
1524 }
1525 }
1526
1527 #[corresponds(SSL_CTX_set_stateless_cookie_generate_cb)]
1533 #[cfg(ossl111)]
1534 pub fn set_stateless_cookie_generate_cb<F>(&mut self, callback: F)
1535 where
1536 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1537 {
1538 unsafe {
1539 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1540 ffi::SSL_CTX_set_stateless_cookie_generate_cb(
1541 self.as_ptr(),
1542 Some(raw_stateless_cookie_generate::<F>),
1543 );
1544 }
1545 }
1546
1547 #[corresponds(SSL_CTX_set_stateless_cookie_verify_cb)]
1556 #[cfg(ossl111)]
1557 pub fn set_stateless_cookie_verify_cb<F>(&mut self, callback: F)
1558 where
1559 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1560 {
1561 unsafe {
1562 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1563 ffi::SSL_CTX_set_stateless_cookie_verify_cb(
1564 self.as_ptr(),
1565 Some(raw_stateless_cookie_verify::<F>),
1566 )
1567 }
1568 }
1569
1570 #[corresponds(SSL_CTX_set_cookie_generate_cb)]
1575 #[cfg(not(any(boringssl, awslc)))]
1576 pub fn set_cookie_generate_cb<F>(&mut self, callback: F)
1577 where
1578 F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
1579 {
1580 unsafe {
1581 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1582 ffi::SSL_CTX_set_cookie_generate_cb(self.as_ptr(), Some(raw_cookie_generate::<F>));
1583 }
1584 }
1585
1586 #[corresponds(SSL_CTX_set_cookie_verify_cb)]
1591 #[cfg(not(any(boringssl, awslc)))]
1592 pub fn set_cookie_verify_cb<F>(&mut self, callback: F)
1593 where
1594 F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
1595 {
1596 unsafe {
1597 self.set_ex_data(SslContext::cached_ex_index::<F>(), callback);
1598 ffi::SSL_CTX_set_cookie_verify_cb(self.as_ptr(), Some(raw_cookie_verify::<F>));
1599 }
1600 }
1601
1602 #[corresponds(SSL_CTX_set_ex_data)]
1608 pub fn set_ex_data<T>(&mut self, index: Index<SslContext, T>, data: T) {
1609 self.set_ex_data_inner(index, data);
1610 }
1611
1612 fn set_ex_data_inner<T>(&mut self, index: Index<SslContext, T>, data: T) -> *mut c_void {
1613 match self.ex_data_mut(index) {
1614 Some(v) => {
1615 *v = data;
1616 (v as *mut T).cast()
1617 }
1618 _ => unsafe {
1619 let data = Box::into_raw(Box::new(data)) as *mut c_void;
1620 ffi::SSL_CTX_set_ex_data(self.as_ptr(), index.as_raw(), data);
1621 data
1622 },
1623 }
1624 }
1625
1626 fn ex_data_mut<T>(&mut self, index: Index<SslContext, T>) -> Option<&mut T> {
1627 unsafe {
1628 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1629 if data.is_null() {
1630 None
1631 } else {
1632 Some(&mut *data.cast())
1633 }
1634 }
1635 }
1636
1637 #[corresponds(SSL_CTX_add_custom_ext)]
1641 #[cfg(ossl111)]
1642 pub fn add_custom_ext<AddFn, ParseFn, T>(
1643 &mut self,
1644 ext_type: u16,
1645 context: ExtensionContext,
1646 add_cb: AddFn,
1647 parse_cb: ParseFn,
1648 ) -> Result<(), ErrorStack>
1649 where
1650 AddFn: Fn(
1651 &mut SslRef,
1652 ExtensionContext,
1653 Option<(usize, &X509Ref)>,
1654 ) -> Result<Option<T>, SslAlert>
1655 + 'static
1656 + Sync
1657 + Send,
1658 T: AsRef<[u8]> + 'static + Sync + Send,
1659 ParseFn: Fn(
1660 &mut SslRef,
1661 ExtensionContext,
1662 &[u8],
1663 Option<(usize, &X509Ref)>,
1664 ) -> Result<(), SslAlert>
1665 + 'static
1666 + Sync
1667 + Send,
1668 {
1669 let ret = unsafe {
1670 self.set_ex_data(SslContext::cached_ex_index::<AddFn>(), add_cb);
1671 self.set_ex_data(SslContext::cached_ex_index::<ParseFn>(), parse_cb);
1672
1673 ffi::SSL_CTX_add_custom_ext(
1674 self.as_ptr(),
1675 ext_type as c_uint,
1676 context.bits(),
1677 Some(raw_custom_ext_add::<AddFn, T>),
1678 Some(raw_custom_ext_free::<T>),
1679 ptr::null_mut(),
1680 Some(raw_custom_ext_parse::<ParseFn>),
1681 ptr::null_mut(),
1682 )
1683 };
1684 if ret == 1 {
1685 Ok(())
1686 } else {
1687 Err(ErrorStack::get())
1688 }
1689 }
1690
1691 #[corresponds(SSL_CTX_set_max_early_data)]
1697 #[cfg(any(ossl111, libressl340))]
1698 pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
1699 if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
1700 Ok(())
1701 } else {
1702 Err(ErrorStack::get())
1703 }
1704 }
1705
1706 #[corresponds(SSL_CTX_set_client_hello_cb)]
1710 #[cfg(ossl111)]
1711 pub fn set_client_hello_callback<F>(&mut self, callback: F)
1712 where
1713 F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
1714 + 'static
1715 + Sync
1716 + Send,
1717 {
1718 unsafe {
1719 let ptr = self.set_ex_data_inner(SslContext::cached_ex_index::<F>(), callback);
1720 ffi::SSL_CTX_set_client_hello_cb(
1721 self.as_ptr(),
1722 Some(callbacks::raw_client_hello::<F>),
1723 ptr,
1724 );
1725 }
1726 }
1727
1728 #[corresponds(SSL_CTX_sess_set_cache_size)]
1732 #[allow(clippy::useless_conversion)]
1733 pub fn set_session_cache_size(&mut self, size: i32) -> i64 {
1734 unsafe {
1735 ffi::SSL_CTX_sess_set_cache_size(self.as_ptr(), size as SslCacheSize) as SslCacheTy
1736 }
1737 }
1738
1739 #[corresponds(SSL_CTX_set1_sigalgs_list)]
1743 #[cfg(ossl102)]
1744 pub fn set_sigalgs_list(&mut self, sigalgs: &str) -> Result<(), ErrorStack> {
1745 let sigalgs = CString::new(sigalgs).unwrap();
1746 unsafe {
1747 cvt(ffi::SSL_CTX_set1_sigalgs_list(self.as_ptr(), sigalgs.as_ptr()) as c_int)
1748 .map(|_| ())
1749 }
1750 }
1751
1752 #[corresponds(SSL_CTX_set1_groups_list)]
1756 #[cfg(any(ossl111, boringssl, libressl251, awslc))]
1757 pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> {
1758 let groups = CString::new(groups).unwrap();
1759 unsafe {
1760 cvt(ffi::SSL_CTX_set1_groups_list(self.as_ptr(), groups.as_ptr()) as c_int).map(|_| ())
1761 }
1762 }
1763
1764 #[corresponds(SSL_CTX_set_num_tickets)]
1769 #[cfg(ossl111)]
1770 pub fn set_num_tickets(&mut self, num_tickets: usize) -> Result<(), ErrorStack> {
1771 unsafe { cvt(ffi::SSL_CTX_set_num_tickets(self.as_ptr(), num_tickets)).map(|_| ()) }
1772 }
1773
1774 #[corresponds(SSL_CTX_set_security_level)]
1779 #[cfg(any(ossl110, libressl360))]
1780 pub fn set_security_level(&mut self, level: u32) {
1781 unsafe { ffi::SSL_CTX_set_security_level(self.as_ptr(), level as c_int) }
1782 }
1783
1784 pub fn build(self) -> SslContext {
1786 self.0
1787 }
1788}
1789
1790foreign_type_and_impl_send_sync! {
1791 type CType = ffi::SSL_CTX;
1792 fn drop = ffi::SSL_CTX_free;
1793
1794 pub struct SslContext;
1799
1800 pub struct SslContextRef;
1804}
1805
1806impl Clone for SslContext {
1807 fn clone(&self) -> Self {
1808 (**self).to_owned()
1809 }
1810}
1811
1812impl ToOwned for SslContextRef {
1813 type Owned = SslContext;
1814
1815 fn to_owned(&self) -> Self::Owned {
1816 unsafe {
1817 SSL_CTX_up_ref(self.as_ptr());
1818 SslContext::from_ptr(self.as_ptr())
1819 }
1820 }
1821}
1822
1823impl fmt::Debug for SslContext {
1825 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1826 write!(fmt, "SslContext")
1827 }
1828}
1829
1830impl SslContext {
1831 pub fn builder(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
1833 SslContextBuilder::new(method)
1834 }
1835
1836 #[corresponds(SSL_CTX_get_ex_new_index)]
1841 pub fn new_ex_index<T>() -> Result<Index<SslContext, T>, ErrorStack>
1842 where
1843 T: 'static + Sync + Send,
1844 {
1845 unsafe {
1846 ffi::init();
1847 #[cfg(any(boringssl, awslc))]
1848 let idx = cvt_n(get_new_idx(Some(free_data_box::<T>)))?;
1849 #[cfg(not(any(boringssl, awslc)))]
1850 let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
1851 Ok(Index::from_raw(idx))
1852 }
1853 }
1854
1855 fn cached_ex_index<T>() -> Index<SslContext, T>
1857 where
1858 T: 'static + Sync + Send,
1859 {
1860 unsafe {
1861 let idx = *INDEXES
1862 .lock()
1863 .unwrap_or_else(|e| e.into_inner())
1864 .entry(TypeId::of::<T>())
1865 .or_insert_with(|| SslContext::new_ex_index::<T>().unwrap().as_raw());
1866 Index::from_raw(idx)
1867 }
1868 }
1869}
1870
1871impl SslContextRef {
1872 #[corresponds(SSL_CTX_get0_certificate)]
1876 #[cfg(any(ossl102, libressl270))]
1877 pub fn certificate(&self) -> Option<&X509Ref> {
1878 unsafe {
1879 let ptr = ffi::SSL_CTX_get0_certificate(self.as_ptr());
1880 X509Ref::from_const_ptr_opt(ptr)
1881 }
1882 }
1883
1884 #[corresponds(SSL_CTX_get0_privatekey)]
1888 #[cfg(any(ossl102, libressl340))]
1889 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
1890 unsafe {
1891 let ptr = ffi::SSL_CTX_get0_privatekey(self.as_ptr());
1892 PKeyRef::from_const_ptr_opt(ptr)
1893 }
1894 }
1895
1896 #[corresponds(SSL_CTX_get_cert_store)]
1898 pub fn cert_store(&self) -> &X509StoreRef {
1899 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
1900 }
1901
1902 #[corresponds(SSL_CTX_get_extra_chain_certs)]
1904 pub fn extra_chain_certs(&self) -> &StackRef<X509> {
1905 unsafe {
1906 let mut chain = ptr::null_mut();
1907 ffi::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain);
1908 StackRef::from_const_ptr_opt(chain).expect("extra chain certs must not be null")
1909 }
1910 }
1911
1912 #[corresponds(SSL_CTX_get_ex_data)]
1914 pub fn ex_data<T>(&self, index: Index<SslContext, T>) -> Option<&T> {
1915 unsafe {
1916 let data = ffi::SSL_CTX_get_ex_data(self.as_ptr(), index.as_raw());
1917 if data.is_null() {
1918 None
1919 } else {
1920 Some(&*(data as *const T))
1921 }
1922 }
1923 }
1924
1925 #[corresponds(SSL_CTX_get_max_early_data)]
1929 #[cfg(any(ossl111, libressl340))]
1930 pub fn max_early_data(&self) -> u32 {
1931 unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
1932 }
1933
1934 #[corresponds(SSL_CTX_add_session)]
1943 pub unsafe fn add_session(&self, session: &SslSessionRef) -> bool {
1944 ffi::SSL_CTX_add_session(self.as_ptr(), session.as_ptr()) != 0
1945 }
1946
1947 #[corresponds(SSL_CTX_remove_session)]
1956 pub unsafe fn remove_session(&self, session: &SslSessionRef) -> bool {
1957 ffi::SSL_CTX_remove_session(self.as_ptr(), session.as_ptr()) != 0
1958 }
1959
1960 #[corresponds(SSL_CTX_sess_get_cache_size)]
1964 #[allow(clippy::unnecessary_cast)]
1965 pub fn session_cache_size(&self) -> i64 {
1966 unsafe { ffi::SSL_CTX_sess_get_cache_size(self.as_ptr()) as i64 }
1967 }
1968
1969 #[corresponds(SSL_CTX_get_verify_mode)]
1973 pub fn verify_mode(&self) -> SslVerifyMode {
1974 let mode = unsafe { ffi::SSL_CTX_get_verify_mode(self.as_ptr()) };
1975 SslVerifyMode::from_bits(mode).expect("SSL_CTX_get_verify_mode returned invalid mode")
1976 }
1977
1978 #[corresponds(SSL_CTX_get_num_tickets)]
1983 #[cfg(ossl111)]
1984 pub fn num_tickets(&self) -> usize {
1985 unsafe { ffi::SSL_CTX_get_num_tickets(self.as_ptr()) }
1986 }
1987
1988 #[corresponds(SSL_CTX_get_security_level)]
1993 #[cfg(any(ossl110, libressl360))]
1994 pub fn security_level(&self) -> u32 {
1995 unsafe { ffi::SSL_CTX_get_security_level(self.as_ptr()) as u32 }
1996 }
1997}
1998
1999pub struct CipherBits {
2001 pub secret: i32,
2003
2004 pub algorithm: i32,
2006}
2007
2008pub struct SslCipher(*mut ffi::SSL_CIPHER);
2010
2011impl ForeignType for SslCipher {
2012 type CType = ffi::SSL_CIPHER;
2013 type Ref = SslCipherRef;
2014
2015 #[inline]
2016 unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher {
2017 SslCipher(ptr)
2018 }
2019
2020 #[inline]
2021 fn as_ptr(&self) -> *mut ffi::SSL_CIPHER {
2022 self.0
2023 }
2024}
2025
2026impl Stackable for SslCipher {
2027 type StackType = ffi::stack_st_SSL_CIPHER;
2028}
2029
2030impl Deref for SslCipher {
2031 type Target = SslCipherRef;
2032
2033 fn deref(&self) -> &SslCipherRef {
2034 unsafe { SslCipherRef::from_ptr(self.0) }
2035 }
2036}
2037
2038impl DerefMut for SslCipher {
2039 fn deref_mut(&mut self) -> &mut SslCipherRef {
2040 unsafe { SslCipherRef::from_ptr_mut(self.0) }
2041 }
2042}
2043
2044pub struct SslCipherRef(Opaque);
2048
2049impl ForeignTypeRef for SslCipherRef {
2050 type CType = ffi::SSL_CIPHER;
2051}
2052
2053impl SslCipherRef {
2054 #[corresponds(SSL_CIPHER_get_name)]
2056 pub fn name(&self) -> &'static str {
2057 unsafe {
2058 let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr());
2059 CStr::from_ptr(ptr).to_str().unwrap()
2060 }
2061 }
2062
2063 #[corresponds(SSL_CIPHER_standard_name)]
2067 #[cfg(ossl111)]
2068 pub fn standard_name(&self) -> Option<&'static str> {
2069 unsafe {
2070 let ptr = ffi::SSL_CIPHER_standard_name(self.as_ptr());
2071 if ptr.is_null() {
2072 None
2073 } else {
2074 Some(CStr::from_ptr(ptr).to_str().unwrap())
2075 }
2076 }
2077 }
2078
2079 #[corresponds(SSL_CIPHER_get_version)]
2081 pub fn version(&self) -> &'static str {
2082 let version = unsafe {
2083 let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr());
2084 CStr::from_ptr(ptr as *const _)
2085 };
2086
2087 str::from_utf8(version.to_bytes()).unwrap()
2088 }
2089
2090 #[corresponds(SSL_CIPHER_get_bits)]
2092 #[allow(clippy::useless_conversion)]
2093 pub fn bits(&self) -> CipherBits {
2094 unsafe {
2095 let mut algo_bits = 0;
2096 let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits);
2097 CipherBits {
2098 secret: secret_bits.into(),
2099 algorithm: algo_bits.into(),
2100 }
2101 }
2102 }
2103
2104 #[corresponds(SSL_CIPHER_description)]
2106 pub fn description(&self) -> String {
2107 unsafe {
2108 let mut buf = [0; 128];
2110 let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128);
2111 String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap()
2112 }
2113 }
2114
2115 #[corresponds(SSL_CIPHER_get_handshake_digest)]
2119 #[cfg(ossl111)]
2120 pub fn handshake_digest(&self) -> Option<MessageDigest> {
2121 unsafe {
2122 let ptr = ffi::SSL_CIPHER_get_handshake_digest(self.as_ptr());
2123 if ptr.is_null() {
2124 None
2125 } else {
2126 Some(MessageDigest::from_ptr(ptr))
2127 }
2128 }
2129 }
2130
2131 #[corresponds(SSL_CIPHER_get_cipher_nid)]
2135 #[cfg(any(ossl110, libressl270))]
2136 pub fn cipher_nid(&self) -> Option<Nid> {
2137 let n = unsafe { ffi::SSL_CIPHER_get_cipher_nid(self.as_ptr()) };
2138 if n == 0 {
2139 None
2140 } else {
2141 Some(Nid::from_raw(n))
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, libressl340))]
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, libressl270))]
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(ossl101, 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 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
2507 pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
2508 unsafe {
2509 assert!(protocols.len() <= c_uint::MAX as usize);
2510 let r =
2511 ffi::SSL_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as _);
2512 if r == 0 {
2514 Ok(())
2515 } else {
2516 Err(ErrorStack::get())
2517 }
2518 }
2519 }
2520
2521 #[corresponds(SSL_get_current_cipher)]
2523 pub fn current_cipher(&self) -> Option<&SslCipherRef> {
2524 unsafe {
2525 let ptr = ffi::SSL_get_current_cipher(self.as_ptr());
2526
2527 SslCipherRef::from_const_ptr_opt(ptr)
2528 }
2529 }
2530
2531 #[corresponds(SSL_state_string)]
2533 pub fn state_string(&self) -> &'static str {
2534 let state = unsafe {
2535 let ptr = ffi::SSL_state_string(self.as_ptr());
2536 CStr::from_ptr(ptr as *const _)
2537 };
2538
2539 str::from_utf8(state.to_bytes()).unwrap()
2540 }
2541
2542 #[corresponds(SSL_state_string_long)]
2544 pub fn state_string_long(&self) -> &'static str {
2545 let state = unsafe {
2546 let ptr = ffi::SSL_state_string_long(self.as_ptr());
2547 CStr::from_ptr(ptr as *const _)
2548 };
2549
2550 str::from_utf8(state.to_bytes()).unwrap()
2551 }
2552
2553 #[corresponds(SSL_set_tlsext_host_name)]
2557 pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> {
2558 let cstr = CString::new(hostname).unwrap();
2559 unsafe {
2560 cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int)
2561 .map(|_| ())
2562 }
2563 }
2564
2565 #[corresponds(SSL_get_peer_certificate)]
2567 pub fn peer_certificate(&self) -> Option<X509> {
2568 unsafe {
2569 let ptr = SSL_get1_peer_certificate(self.as_ptr());
2570 X509::from_ptr_opt(ptr)
2571 }
2572 }
2573
2574 #[corresponds(SSL_get_peer_cert_chain)]
2579 pub fn peer_cert_chain(&self) -> Option<&StackRef<X509>> {
2580 unsafe {
2581 let ptr = ffi::SSL_get_peer_cert_chain(self.as_ptr());
2582 StackRef::from_const_ptr_opt(ptr)
2583 }
2584 }
2585
2586 #[corresponds(SSL_get0_verified_chain)]
2596 #[cfg(ossl110)]
2597 pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
2598 unsafe {
2599 let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
2600 StackRef::from_const_ptr_opt(ptr)
2601 }
2602 }
2603
2604 #[corresponds(SSL_get_certificate)]
2606 pub fn certificate(&self) -> Option<&X509Ref> {
2607 unsafe {
2608 let ptr = ffi::SSL_get_certificate(self.as_ptr());
2609 X509Ref::from_const_ptr_opt(ptr)
2610 }
2611 }
2612
2613 #[corresponds(SSL_get_privatekey)]
2617 pub fn private_key(&self) -> Option<&PKeyRef<Private>> {
2618 unsafe {
2619 let ptr = ffi::SSL_get_privatekey(self.as_ptr());
2620 PKeyRef::from_const_ptr_opt(ptr)
2621 }
2622 }
2623
2624 #[deprecated(since = "0.10.5", note = "renamed to `version_str`")]
2625 pub fn version(&self) -> &str {
2626 self.version_str()
2627 }
2628
2629 #[corresponds(SSL_version)]
2631 pub fn version2(&self) -> Option<SslVersion> {
2632 unsafe {
2633 let r = ffi::SSL_version(self.as_ptr());
2634 if r == 0 {
2635 None
2636 } else {
2637 Some(SslVersion(r))
2638 }
2639 }
2640 }
2641
2642 #[corresponds(SSL_get_version)]
2644 pub fn version_str(&self) -> &'static str {
2645 let version = unsafe {
2646 let ptr = ffi::SSL_get_version(self.as_ptr());
2647 CStr::from_ptr(ptr as *const _)
2648 };
2649
2650 str::from_utf8(version.to_bytes()).unwrap()
2651 }
2652
2653 #[corresponds(SSL_get0_alpn_selected)]
2660 #[cfg(any(ossl102, libressl261, boringssl, awslc))]
2661 pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
2662 unsafe {
2663 let mut data: *const c_uchar = ptr::null();
2664 let mut len: c_uint = 0;
2665 ffi::SSL_get0_alpn_selected(self.as_ptr(), &mut data, &mut len);
2668
2669 if data.is_null() {
2670 None
2671 } else {
2672 Some(util::from_raw_parts(data, len as usize))
2673 }
2674 }
2675 }
2676
2677 #[corresponds(SSL_set_tlsext_use_srtp)]
2679 pub fn set_tlsext_use_srtp(&mut self, protocols: &str) -> Result<(), ErrorStack> {
2680 unsafe {
2681 let cstr = CString::new(protocols).unwrap();
2682
2683 let r = ffi::SSL_set_tlsext_use_srtp(self.as_ptr(), cstr.as_ptr());
2684 if r == 0 {
2686 Ok(())
2687 } else {
2688 Err(ErrorStack::get())
2689 }
2690 }
2691 }
2692
2693 #[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 #[corresponds(SSL_get_selected_srtp_profile)]
2709 pub fn selected_srtp_profile(&self) -> Option<&SrtpProtectionProfileRef> {
2710 unsafe {
2711 let profile = ffi::SSL_get_selected_srtp_profile(self.as_ptr());
2712
2713 SrtpProtectionProfileRef::from_const_ptr_opt(profile)
2714 }
2715 }
2716
2717 #[corresponds(SSL_pending)]
2722 pub fn pending(&self) -> usize {
2723 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
2724 }
2725
2726 #[corresponds(SSL_get_servername)]
2739 pub fn servername(&self, type_: NameType) -> Option<&str> {
2741 self.servername_raw(type_)
2742 .and_then(|b| str::from_utf8(b).ok())
2743 }
2744
2745 #[corresponds(SSL_get_servername)]
2753 pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
2754 unsafe {
2755 let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
2756 if name.is_null() {
2757 None
2758 } else {
2759 Some(CStr::from_ptr(name as *const _).to_bytes())
2760 }
2761 }
2762 }
2763
2764 #[corresponds(SSL_set_SSL_CTX)]
2768 pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> {
2769 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
2770 }
2771
2772 #[corresponds(SSL_get_SSL_CTX)]
2774 pub fn ssl_context(&self) -> &SslContextRef {
2775 unsafe {
2776 let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr());
2777 SslContextRef::from_ptr(ssl_ctx)
2778 }
2779 }
2780
2781 #[corresponds(SSL_get0_param)]
2785 #[cfg(any(ossl102, boringssl, libressl261, awslc))]
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, libressl270))]
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, libressl270))]
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, libressl340))]
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, libressl340))]
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, libressl332))]
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, libressl261, 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, libressl261, 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, libressl340))]
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, libressl340))]
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, libressl340))]
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, libressl350))] {
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, libressl350))] {
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, libressl350))] {
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, libressl340))]
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, libressl340))]
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, libressl273, 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, libressl291, 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}