3 //! `SslConnector` and `SslAcceptor` should be used in most cases - they handle
4 //! configuration of the OpenSSL primitives for you.
8 //! To connect as a client to a remote server:
11 //! use openssl::ssl::{SslMethod, SslConnectorBuilder};
12 //! use std::io::{Read, Write};
13 //! use std::net::TcpStream;
15 //! let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build();
17 //! let stream = TcpStream::connect("google.com:443").unwrap();
18 //! let mut stream = connector.connect("google.com", stream).unwrap();
20 //! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap();
21 //! let mut res = vec![];
22 //! stream.read_to_end(&mut res).unwrap();
23 //! println!("{}", String::from_utf8_lossy(&res));
26 //! To accept connections as a server from remote clients:
29 //! use openssl::pkcs12::Pkcs12;
30 //! use openssl::ssl::{SslMethod, SslAcceptorBuilder, SslStream};
31 //! use std::fs::File;
32 //! use std::io::{Read, Write};
33 //! use std::net::{TcpListener, TcpStream};
34 //! use std::sync::Arc;
37 //! // In this example we retrieve our keypair and certificate chain from a PKCS #12 archive,
38 //! // but but they can also be retrieved from, for example, individual PEM- or DER-formatted
39 //! // files. See the documentation for the `PKey` and `X509` types for more details.
40 //! let mut file = File::open("identity.pfx").unwrap();
41 //! let mut pkcs12 = vec![];
42 //! file.read_to_end(&mut pkcs12).unwrap();
43 //! let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap();
44 //! let identity = pkcs12.parse("password123").unwrap();
46 //! let acceptor = SslAcceptorBuilder::mozilla_intermediate(SslMethod::tls(),
52 //! let acceptor = Arc::new(acceptor);
54 //! let listener = TcpListener::bind("0.0.0.0:8443").unwrap();
56 //! fn handle_client(stream: SslStream<TcpStream>) {
60 //! for stream in listener.incoming() {
63 //! let acceptor = acceptor.clone();
64 //! thread::spawn(move || {
65 //! let stream = acceptor.accept(stream).unwrap();
66 //! handle_client(stream);
69 //! Err(e) => { /* connection failed */ }
74 use foreign_types
::{ForeignType, ForeignTypeRef, Opaque}
;
75 use libc
::{c_int, c_void, c_long, c_ulong}
;
76 use libc
::{c_uchar, c_uint}
;
79 use std
::borrow
::Borrow
;
81 use std
::collections
::HashMap
;
82 use std
::ffi
::{CStr, CString}
;
85 use std
::io
::prelude
::*;
86 use std
::marker
::PhantomData
;
88 use std
::ops
::{Deref, DerefMut}
;
89 use std
::panic
::resume_unwind
;
96 use {init, cvt, cvt_p, cvt_n}
;
99 #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
101 use x509
::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError, X509Name}
;
102 use x509
::store
::{X509StoreBuilderRef, X509StoreRef}
;
103 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
104 use x509
::store
::X509Store
;
105 #[cfg(any(ossl102, ossl110))]
106 use verify
::X509VerifyParamRef
;
108 use error
::ErrorStack
;
110 use stack
::{Stack, StackRef}
;
111 use ssl
::bio
::BioMethod
;
112 use ssl
::callbacks
::*;
114 pub use ssl
::connector
::{SslConnectorBuilder
, SslConnector
, SslAcceptorBuilder
, SslAcceptor
,
115 ConnectConfiguration
};
116 pub use ssl
::error
::{Error, HandshakeError}
;
125 // FIXME drop SSL_ prefix
126 // FIXME remvove flags not used in OpenSSL 1.1
128 pub struct SslOption
: c_ulong
{
129 const SSL_OP_MICROSOFT_SESS_ID_BUG
= ffi
::SSL_OP_MICROSOFT_SESS_ID_BUG
;
130 const SSL_OP_NETSCAPE_CHALLENGE_BUG
= ffi
::SSL_OP_NETSCAPE_CHALLENGE_BUG
;
131 const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
=
132 ffi
::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
;
133 const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
= ffi
::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
;
134 const SSL_OP_SSLEAY_080_CLIENT_DH_BUG
= ffi
::SSL_OP_SSLEAY_080_CLIENT_DH_BUG
;
135 const SSL_OP_TLS_D5_BUG
= ffi
::SSL_OP_TLS_D5_BUG
;
136 const SSL_OP_TLS_BLOCK_PADDING_BUG
= ffi
::SSL_OP_TLS_BLOCK_PADDING_BUG
;
137 const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
= ffi
::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
;
138 const SSL_OP_ALL
= ffi
::SSL_OP_ALL
;
139 const SSL_OP_NO_QUERY_MTU
= ffi
::SSL_OP_NO_QUERY_MTU
;
140 const SSL_OP_COOKIE_EXCHANGE
= ffi
::SSL_OP_COOKIE_EXCHANGE
;
141 const SSL_OP_NO_TICKET
= ffi
::SSL_OP_NO_TICKET
;
142 const SSL_OP_CISCO_ANYCONNECT
= ffi
::SSL_OP_CISCO_ANYCONNECT
;
143 const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
=
144 ffi
::SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
;
145 const SSL_OP_NO_COMPRESSION
= ffi
::SSL_OP_NO_COMPRESSION
;
146 const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
=
147 ffi
::SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
;
148 const SSL_OP_SINGLE_ECDH_USE
= ffi
::SSL_OP_SINGLE_ECDH_USE
;
149 const SSL_OP_SINGLE_DH_USE
= ffi
::SSL_OP_SINGLE_DH_USE
;
150 const SSL_OP_CIPHER_SERVER_PREFERENCE
= ffi
::SSL_OP_CIPHER_SERVER_PREFERENCE
;
151 const SSL_OP_TLS_ROLLBACK_BUG
= ffi
::SSL_OP_TLS_ROLLBACK_BUG
;
152 const SSL_OP_NO_SSLV2
= ffi
::SSL_OP_NO_SSLv2
;
153 const SSL_OP_NO_SSLV3
= ffi
::SSL_OP_NO_SSLv3
;
154 const SSL_OP_NO_TLSV1
= ffi
::SSL_OP_NO_TLSv1
;
155 const SSL_OP_NO_TLSV1_2
= ffi
::SSL_OP_NO_TLSv1_2
;
156 const SSL_OP_NO_TLSV1_1
= ffi
::SSL_OP_NO_TLSv1_1
;
157 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
158 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
159 const SSL_OP_NO_DTLSV1
= ffi
::SSL_OP_NO_DTLSv1
;
160 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
161 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
162 const SSL_OP_NO_DTLSV1_2
= ffi
::SSL_OP_NO_DTLSv1_2
;
163 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
164 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
165 const SSL_OP_NO_SSL_MASK
= ffi
::SSL_OP_NO_SSL_MASK
;
170 pub struct SslMode
: c_long
{
171 const SSL_MODE_ENABLE_PARTIAL_WRITE
= ffi
::SSL_MODE_ENABLE_PARTIAL_WRITE
;
172 const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
= ffi
::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER
;
173 const SSL_MODE_AUTO_RETRY
= ffi
::SSL_MODE_AUTO_RETRY
;
174 const SSL_MODE_NO_AUTO_CHAIN
= ffi
::SSL_MODE_NO_AUTO_CHAIN
;
175 const SSL_MODE_RELEASE_BUFFERS
= ffi
::SSL_MODE_RELEASE_BUFFERS
;
176 #[cfg(not(libressl))]
177 const SSL_MODE_SEND_CLIENTHELLO_TIME
= ffi
::SSL_MODE_SEND_CLIENTHELLO_TIME
;
178 #[cfg(not(libressl))]
179 const SSL_MODE_SEND_SERVERHELLO_TIME
= ffi
::SSL_MODE_SEND_SERVERHELLO_TIME
;
180 #[cfg(not(libressl))]
181 const SSL_MODE_SEND_FALLBACK_SCSV
= ffi
::SSL_MODE_SEND_FALLBACK_SCSV
;
185 #[derive(Copy, Clone)]
186 pub struct SslMethod(*const ffi
::SSL_METHOD
);
189 /// Support all versions of the TLS protocol.
191 /// This corresponds to `TLS_method` on OpenSSL 1.1.0 and `SSLv23_method`
192 /// on OpenSSL 1.0.x.
193 pub fn tls() -> SslMethod
{
194 SslMethod(compat
::tls_method())
197 /// Support all versions of the DTLS protocol.
199 /// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method`
200 /// on OpenSSL 1.0.x.
201 pub fn dtls() -> SslMethod
{
202 SslMethod(compat
::dtls_method())
205 pub unsafe fn from_ptr(ptr
: *const ffi
::SSL_METHOD
) -> SslMethod
{
209 pub fn as_ptr(&self) -> *const ffi
::SSL_METHOD
{
214 /// Determines the type of certificate verification used
216 pub struct SslVerifyMode
: i32 {
217 /// Verify that the server's certificate is trusted
218 const SSL_VERIFY_PEER
= ::ffi
::SSL_VERIFY_PEER
;
219 /// Do not verify the server's certificate
220 const SSL_VERIFY_NONE
= ::ffi
::SSL_VERIFY_NONE
;
221 /// Terminate handshake if client did not return a certificate.
222 /// Use together with SSL_VERIFY_PEER.
223 const SSL_VERIFY_FAIL_IF_NO_PEER_CERT
= ::ffi
::SSL_VERIFY_FAIL_IF_NO_PEER_CERT
;
227 #[derive(Copy, Clone)]
228 pub struct StatusType(c_int
);
231 pub fn from_raw(raw
: c_int
) -> StatusType
{
235 pub fn as_raw(&self) -> c_int
{
241 pub const STATUS_TYPE_OCSP
: StatusType
= StatusType(ffi
::TLSEXT_STATUSTYPE_ocsp
);
244 static ref INDEXES
: Mutex
<HashMap
<TypeId
, c_int
>> = Mutex
::new(HashMap
::new());
245 static ref SSL_INDEXES
: Mutex
<HashMap
<TypeId
, c_int
>> = Mutex
::new(HashMap
::new());
248 // Creates a static index for user data of type T
249 // Registers a destructor for the data which will be called
250 // when context is freed
251 fn get_callback_idx
<T
: Any
+ '
static>() -> c_int
{
255 .entry(TypeId
::of
::<T
>())
256 .or_insert_with(|| get_new_idx
::<T
>())
259 fn get_ssl_callback_idx
<T
: Any
+ '
static>() -> c_int
{
263 .entry(TypeId
::of
::<T
>())
264 .or_insert_with(|| get_new_ssl_idx
::<T
>())
268 static ref NPN_PROTOS_IDX
: c_int
= get_new_idx
::<Vec
<u8>>();
271 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
273 static ref ALPN_PROTOS_IDX
: c_int
= get_new_idx
::<Vec
<u8>>();
276 unsafe extern "C" fn free_data_box
<T
>(
277 _parent
: *mut c_void
,
279 _ad
: *mut ffi
::CRYPTO_EX_DATA
,
285 Box
::<T
>::from_raw(ptr
as *mut T
);
289 /// Determine a new index to use for SSL CTX ex data.
290 /// Registers a destruct for the data which will be called by openssl when the context is freed.
291 fn get_new_idx
<T
>() -> c_int
{
293 let idx
= compat
::get_new_idx(free_data_box
::<T
>);
299 fn get_new_ssl_idx
<T
>() -> c_int
{
301 let idx
= compat
::get_new_ssl_idx(free_data_box
::<T
>);
307 /// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte
308 /// containing the length followed by the string.
309 fn ssl_encode_byte_strings(strings
: &[&[u8]]) -> Vec
<u8> {
310 let mut enc
= Vec
::new();
311 for string
in strings
{
312 let len
= string
.len() as u8;
313 if len
as usize != string
.len() {
314 // If the item does not fit, discard it
318 enc
.extend(string
[..len
as usize].to_vec());
323 /// An error returned from an SNI callback.
330 /// A builder for `SslContext`s.
331 pub struct SslContextBuilder(*mut ffi
::SSL_CTX
);
333 unsafe impl Sync
for SslContextBuilder {}
334 unsafe impl Send
for SslContextBuilder {}
336 impl Drop
for SslContextBuilder
{
338 unsafe { ffi::SSL_CTX_free(self.as_ptr()) }
342 impl SslContextBuilder
{
343 pub fn new(method
: SslMethod
) -> Result
<SslContextBuilder
, ErrorStack
> {
346 let ctx
= try
!(cvt_p(ffi
::SSL_CTX_new(method
.as_ptr())));
348 Ok(SslContextBuilder
::from_ptr(ctx
))
352 pub unsafe fn from_ptr(ctx
: *mut ffi
::SSL_CTX
) -> SslContextBuilder
{
353 SslContextBuilder(ctx
)
356 pub fn as_ptr(&self) -> *mut ffi
::SSL_CTX
{
360 /// Configures the certificate verification method for new connections.
361 pub fn set_verify(&mut self, mode
: SslVerifyMode
) {
363 ffi
::SSL_CTX_set_verify(self.as_ptr(), mode
.bits
as c_int
, None
);
367 /// Configures the certificate verification method for new connections and
368 /// registers a verification callback.
369 pub fn set_verify_callback
<F
>(&mut self, mode
: SslVerifyMode
, verify
: F
)
371 F
: Fn(bool
, &X509StoreContextRef
) -> bool
+ Any
+ '
static + Sync
+ Send
,
374 let verify
= Box
::new(verify
);
375 ffi
::SSL_CTX_set_ex_data(
377 get_callback_idx
::<F
>(),
378 mem
::transmute(verify
),
380 ffi
::SSL_CTX_set_verify(self.as_ptr(), mode
.bits
as c_int
, Some(raw_verify
::<F
>));
384 /// Configures the server name indication (SNI) callback for new connections
386 /// Obtain the server name with `servername` then set the corresponding context
387 /// with `set_ssl_context`
388 pub fn set_servername_callback
<F
>(&mut self, callback
: F
)
390 F
: Fn(&mut SslRef
) -> Result
<(), SniError
> + Any
+ '
static + Sync
+ Send
,
393 let callback
= Box
::new(callback
);
394 ffi
::SSL_CTX_set_ex_data(
396 get_callback_idx
::<F
>(),
397 mem
::transmute(callback
),
399 let f
: extern "C" fn(_
, _
, _
) -> _
= raw_sni
::<F
>;
400 let f
: extern "C" fn() = mem
::transmute(f
);
401 ffi
::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f
));
405 /// Sets verification depth
406 pub fn set_verify_depth(&mut self, depth
: u32) {
408 ffi
::SSL_CTX_set_verify_depth(self.as_ptr(), depth
as c_int
);
412 /// Sets a custom X509Store for verifying peer certificates.
414 /// Requires the `v102` feature and OpenSSL 1.0.2, or the `v110` feature and OpenSSL 1.1.0.
415 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
416 pub fn set_verify_cert_store(&mut self, cert_store
: X509Store
) -> Result
<(), ErrorStack
> {
418 let ptr
= cert_store
.as_ptr();
420 ffi
::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr
) as
423 mem
::forget(cert_store
);
429 pub fn set_read_ahead(&mut self, read_ahead
: bool
) {
431 ffi
::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead
as c_long
);
435 pub fn set_mode(&mut self, mode
: SslMode
) -> SslMode
{
437 let mode
= ffi
::SSL_CTX_set_mode(self.as_ptr(), mode
.bits());
438 SslMode
::from_bits(mode
).unwrap()
442 pub fn set_tmp_dh(&mut self, dh
: &DhRef
) -> Result
<(), ErrorStack
> {
443 unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
446 pub fn set_tmp_dh_callback
<F
>(&mut self, callback
: F
)
448 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<Dh
, ErrorStack
> + Any
+ '
static + Sync
+ Send
,
451 let callback
= Box
::new(callback
);
452 ffi
::SSL_CTX_set_ex_data(
454 get_callback_idx
::<F
>(),
455 Box
::into_raw(callback
) as *mut c_void
,
457 let f
: unsafe extern "C" fn(_
, _
, _
) -> _
= raw_tmp_dh
::<F
>;
458 ffi
::SSL_CTX_set_tmp_dh_callback(self.as_ptr(), f
);
462 pub fn set_tmp_ecdh(&mut self, key
: &EcKeyRef
) -> Result
<(), ErrorStack
> {
464 cvt(ffi
::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key
.as_ptr()) as
469 /// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2.
470 #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
471 pub fn set_tmp_ecdh_callback
<F
>(&mut self, callback
: F
)
473 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<EcKey
, ErrorStack
> + Any
+ '
static + Sync
+ Send
,
476 let callback
= Box
::new(callback
);
477 ffi
::SSL_CTX_set_ex_data(
479 get_callback_idx
::<F
>(),
480 Box
::into_raw(callback
) as *mut c_void
,
482 let f
: unsafe extern "C" fn(_
, _
, _
) -> _
= raw_tmp_ecdh
::<F
>;
483 ffi
::SSL_CTX_set_tmp_ecdh_callback(self.as_ptr(), f
);
487 /// Use the default locations of trusted certificates for verification.
489 /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`
490 /// environment variables if present, or defaults specified at OpenSSL
491 /// build time otherwise.
492 pub fn set_default_verify_paths(&mut self) -> Result
<(), ErrorStack
> {
493 unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) }
496 /// Specifies the file that contains trusted CA certificates.
497 pub fn set_ca_file
<P
: AsRef
<Path
>>(&mut self, file
: P
) -> Result
<(), ErrorStack
> {
498 let file
= CString
::new(file
.as_ref().as_os_str().to_str().unwrap()).unwrap();
500 cvt(ffi
::SSL_CTX_load_verify_locations(
502 file
.as_ptr() as *const _
,
508 /// Sets the list of CAs sent to the client.
510 /// The CA certificates must still be added to the trust root.
511 pub fn set_client_ca_list(&mut self, list
: Stack
<X509Name
>) {
513 ffi
::SSL_CTX_set_client_CA_list(self.as_ptr(), list
.as_ptr());
518 /// Set the context identifier for sessions
520 /// This value identifies the server's session cache to clients, telling them when they're
521 /// able to reuse sessions. Should be set to a unique value per server, unless multiple servers
522 /// share a session cache.
524 /// This value should be set when using client certificates, or each request will fail
525 /// handshake and need to be restarted.
526 pub fn set_session_id_context(&mut self, sid_ctx
: &[u8]) -> Result
<(), ErrorStack
> {
528 assert
!(sid_ctx
.len() <= c_uint
::max_value() as usize);
529 cvt(ffi
::SSL_CTX_set_session_id_context(
532 sid_ctx
.len() as c_uint
,
537 /// Loads a certificate from a file.
538 pub fn set_certificate_file
<P
: AsRef
<Path
>>(
541 file_type
: X509FileType
,
542 ) -> Result
<(), ErrorStack
> {
543 let file
= CString
::new(file
.as_ref().as_os_str().to_str().unwrap()).unwrap();
545 cvt(ffi
::SSL_CTX_use_certificate_file(
547 file
.as_ptr() as *const _
,
553 /// Loads a certificate chain from a file.
555 /// The file should contain a sequence of PEM-formatted certificates, the first being the leaf
556 /// certificate, and the remainder forming the chain of certificates up to and including the
557 /// trusted root certificate.
558 pub fn set_certificate_chain_file
<P
: AsRef
<Path
>>(
561 ) -> Result
<(), ErrorStack
> {
562 let file
= CString
::new(file
.as_ref().as_os_str().to_str().unwrap()).unwrap();
564 cvt(ffi
::SSL_CTX_use_certificate_chain_file(
566 file
.as_ptr() as *const _
,
571 /// Sets the certificate.
572 pub fn set_certificate(&mut self, cert
: &X509Ref
) -> Result
<(), ErrorStack
> {
573 unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
576 /// Appends a certificate to the certificate chain.
578 /// This chain should contain all certificates necessary to go from the certificate specified by
579 /// `set_certificate` to a trusted root.
580 pub fn add_extra_chain_cert(&mut self, cert
: X509
) -> Result
<(), ErrorStack
> {
582 try
!(cvt(ffi
::SSL_CTX_add_extra_chain_cert(
591 /// Loads the private key from a file.
592 pub fn set_private_key_file
<P
: AsRef
<Path
>>(
595 file_type
: X509FileType
,
596 ) -> Result
<(), ErrorStack
> {
597 let file
= CString
::new(file
.as_ref().as_os_str().to_str().unwrap()).unwrap();
599 cvt(ffi
::SSL_CTX_use_PrivateKey_file(
601 file
.as_ptr() as *const _
,
607 /// Sets the private key.
608 pub fn set_private_key(&mut self, key
: &PKeyRef
) -> Result
<(), ErrorStack
> {
609 unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) }
612 /// Sets the cipher configuration.
614 /// See `man 1 ciphers` for details on the format.
615 pub fn set_cipher_list(&mut self, cipher_list
: &str) -> Result
<(), ErrorStack
> {
616 let cipher_list
= CString
::new(cipher_list
).unwrap();
618 cvt(ffi
::SSL_CTX_set_cipher_list(
620 cipher_list
.as_ptr() as *const _
,
625 /// Enables ECDHE key exchange with an automatically chosen curve list.
627 /// Requires the `v102` feature and OpenSSL 1.0.2.
628 #[cfg(all(feature = "v102", any(ossl102, libressl)))]
629 pub fn set_ecdh_auto(&mut self, onoff
: bool
) -> Result
<(), ErrorStack
> {
630 self._set_ecdh_auto(onoff
)
633 #[cfg(any(ossl102, libressl))]
634 fn _set_ecdh_auto(&mut self, onoff
: bool
) -> Result
<(), ErrorStack
> {
635 unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
638 pub fn set_options(&mut self, option
: SslOption
) -> SslOption
{
639 let ret
= unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) }
;
640 SslOption
::from_bits(ret
).unwrap()
643 pub fn options(&self) -> SslOption
{
644 let ret
= unsafe { compat::SSL_CTX_get_options(self.as_ptr()) }
;
645 SslOption
::from_bits(ret
).unwrap()
648 pub fn clear_options(&mut self, option
: SslOption
) -> SslOption
{
649 let ret
= unsafe { compat::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }
;
650 SslOption
::from_bits(ret
).unwrap()
653 /// Set the protocols to be used during Next Protocol Negotiation (the protocols
654 /// supported by the application).
655 #[cfg(not(libressl261))]
656 pub fn set_npn_protocols(&mut self, protocols
: &[&[u8]]) -> Result
<(), ErrorStack
> {
657 // Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL
658 // APIs -- a list of length-prefixed strings.
659 let protocols
: Box
<Vec
<u8>> = Box
::new(ssl_encode_byte_strings(protocols
));
662 // Attach the protocol list to the OpenSSL context structure,
663 // so that we can refer to it within the callback.
664 try
!(cvt(ffi
::SSL_CTX_set_ex_data(
667 Box
::into_raw(protocols
) as *mut c_void
,
669 // Now register the callback that performs the default protocol
670 // matching based on the client-supported list of protocols that
672 ffi
::SSL_CTX_set_next_proto_select_cb(
674 raw_next_proto_select_cb
,
677 // Also register the callback to advertise these protocols, if a server socket is
678 // created with the context.
679 ffi
::SSL_CTX_set_next_protos_advertised_cb(
681 raw_next_protos_advertise_cb
,
688 /// Set the protocols to be used during ALPN (application layer protocol negotiation).
689 /// If this is a server, these are the protocols we report to the client.
690 /// If this is a client, these are the protocols we try to match with those reported by the
693 /// Note that ordering of the protocols controls the priority with which they are chosen.
695 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
696 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
697 pub fn set_alpn_protocols(&mut self, protocols
: &[&[u8]]) -> Result
<(), ErrorStack
> {
698 let protocols
: Box
<Vec
<u8>> = Box
::new(ssl_encode_byte_strings(protocols
));
700 // Set the context's internal protocol list for use if we are a server
701 let r
= ffi
::SSL_CTX_set_alpn_protos(
704 protocols
.len() as c_uint
,
706 // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D:
708 return Err(ErrorStack
::get());
711 // Rather than use the argument to the callback to contain our data, store it in the
712 // ssl ctx's ex_data so that we can configure a function to free it later. In the
713 // future, it might make sense to pull this into our internal struct Ssl instead of
714 // leaning on openssl and using function pointers.
715 try
!(cvt(ffi
::SSL_CTX_set_ex_data(
718 Box
::into_raw(protocols
) as *mut c_void
,
721 // Now register the callback that performs the default protocol
722 // matching based on the client-supported list of protocols that
724 ffi
::SSL_CTX_set_alpn_select_cb(self.as_ptr(), raw_alpn_select_cb
, ptr
::null_mut());
730 /// Checks consistency between the private key and certificate.
731 pub fn check_private_key(&self) -> Result
<(), ErrorStack
> {
732 unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) }
735 /// Returns a shared reference to the context's certificate store.
736 pub fn cert_store(&self) -> &X509StoreBuilderRef
{
737 unsafe { X509StoreBuilderRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
740 /// Returns a mutable reference to the context's certificate store.
741 pub fn cert_store_mut(&mut self) -> &mut X509StoreBuilderRef
{
742 unsafe { X509StoreBuilderRef::from_ptr_mut(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
745 /// Sets the callback dealing with OCSP stapling.
747 /// On the client side, this callback is responsible for validating the OCSP status response
748 /// returned by the server. The status may be retrieved with the `SslRef::ocsp_status` method.
749 /// A response of `Ok(true)` indicates that the OCSP status is valid, and a response of
750 /// `Ok(false)` indicates that the OCSP status is invalid and the handshake should be
753 /// On the server side, this callback is resopnsible for setting the OCSP status response to be
754 /// returned to clients. The status may be set with the `SslRef::set_ocsp_status` method. A
755 /// response of `Ok(true)` indicates that the OCSP status should be returned to the client, and
756 /// `Ok(false)` indicates that the status should not be returned to the client.
757 pub fn set_status_callback
<F
>(&mut self, callback
: F
) -> Result
<(), ErrorStack
>
759 F
: Fn(&mut SslRef
) -> Result
<bool
, ErrorStack
> + Any
+ '
static + Sync
+ Send
,
762 let callback
= Box
::new(callback
);
763 ffi
::SSL_CTX_set_ex_data(
765 get_callback_idx
::<F
>(),
766 Box
::into_raw(callback
) as *mut c_void
,
768 let f
: unsafe extern "C" fn(_
, _
) -> _
= raw_tlsext_status
::<F
>;
769 cvt(ffi
::SSL_CTX_set_tlsext_status_cb(
772 ) as c_int
).map(|_
| ())
776 /// Sets the callback for providing an identity and pre-shared key for a TLS-PSK client.
778 /// The callback will be called with the SSL context, an identity hint if one was provided
779 /// by the server, a mut slice for each of the identity and pre-shared key bytes. The identity
780 /// must be written as a null-terminated C string.
781 #[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
782 pub fn set_psk_callback
<F
>(&mut self, callback
: F
)
784 F
: Fn(&mut SslRef
, Option
<&[u8]>, &mut [u8], &mut [u8]) -> Result
<usize, ErrorStack
>
791 let callback
= Box
::new(callback
);
792 ffi
::SSL_CTX_set_ex_data(
794 get_callback_idx
::<F
>(),
795 mem
::transmute(callback
),
797 ffi
::SSL_CTX_set_psk_client_callback(self.as_ptr(), Some(raw_psk
::<F
>))
801 /// Sets the extra data at the specified index.
802 pub fn set_ex_data
<T
>(&mut self, index
: Index
<SslContext
, T
>, data
: T
) {
804 let data
= Box
::new(data
);
805 ffi
::SSL_CTX_set_ex_data(
808 Box
::into_raw(data
) as *mut c_void
,
813 pub fn build(self) -> SslContext
{
814 let ctx
= SslContext(self.0);
821 type CType
= ffi
::SSL_CTX
;
822 fn drop
= ffi
::SSL_CTX_free
;
824 pub struct SslContext
;
825 pub struct SslContextRef
;
828 unsafe impl Send
for SslContext {}
829 unsafe impl Sync
for SslContext {}
831 impl Clone
for SslContext
{
832 fn clone(&self) -> Self {
834 compat
::SSL_CTX_up_ref(self.as_ptr());
835 SslContext
::from_ptr(self.as_ptr())
840 // TODO: add useful info here
841 impl fmt
::Debug
for SslContext
{
842 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
843 write
!(fmt
, "SslContext")
848 pub fn builder(method
: SslMethod
) -> Result
<SslContextBuilder
, ErrorStack
> {
849 SslContextBuilder
::new(method
)
852 /// Returns a new extra data index.
854 /// Each invocation of this function is guaranteed to return a distinct
856 pub fn new_ex_index
<T
>() -> Result
<Index
<SslContext
, T
>, ErrorStack
>
858 T
: '
static + Sync
+ Send
,
862 let idx
= try
!(cvt_n(compat
::get_new_idx(free_data_box
::<T
>)));
863 Ok(Index
::from_raw(idx
))
869 /// Returns the certificate associated with this `SslContext`, if present.
871 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
872 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
873 pub fn certificate(&self) -> Option
<&X509Ref
> {
875 let ptr
= ffi
::SSL_CTX_get0_certificate(self.as_ptr());
879 Some(X509Ref
::from_ptr(ptr
))
884 /// Returns the private key associated with this `SslContext`, if present.
886 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
887 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
888 pub fn private_key(&self) -> Option
<&PKeyRef
> {
890 let ptr
= ffi
::SSL_CTX_get0_privatekey(self.as_ptr());
894 Some(PKeyRef
::from_ptr(ptr
))
899 /// Returns the certificate store used for verification.
900 pub fn cert_store(&self) -> &X509StoreRef
{
901 unsafe { X509StoreRef::from_ptr(ffi::SSL_CTX_get_cert_store(self.as_ptr())) }
904 pub fn extra_chain_certs(&self) -> &StackRef
<X509
> {
906 let mut chain
= ptr
::null_mut();
907 ffi
::SSL_CTX_get_extra_chain_certs(self.as_ptr(), &mut chain
);
908 assert
!(!chain
.is_null());
909 StackRef
::from_ptr(chain
)
913 /// Returns a reference to the extra data at the specified index.
914 pub fn ex_data
<T
>(&self, index
: Index
<SslContext
, T
>) -> Option
<&T
> {
916 let data
= ffi
::SSL_CTX_get_ex_data(self.as_ptr(), index
.as_raw());
920 Some(&*(data
as *const T
))
926 pub struct CipherBits
{
927 /// The number of secret bits used for the cipher.
930 /// The number of bits processed by the chosen algorithm.
934 pub struct SslCipher(*mut ffi
::SSL_CIPHER
);
936 impl ForeignType
for SslCipher
{
937 type CType
= ffi
::SSL_CIPHER
;
938 type Ref
= SslCipherRef
;
941 unsafe fn from_ptr(ptr
: *mut ffi
::SSL_CIPHER
) -> SslCipher
{
946 fn as_ptr(&self) -> *mut ffi
::SSL_CIPHER
{
951 impl Deref
for SslCipher
{
952 type Target
= SslCipherRef
;
954 fn deref(&self) -> &SslCipherRef
{
955 unsafe { SslCipherRef::from_ptr(self.0) }
959 impl DerefMut
for SslCipher
{
960 fn deref_mut(&mut self) -> &mut SslCipherRef
{
961 unsafe { SslCipherRef::from_ptr_mut(self.0) }
965 pub struct SslCipherRef(Opaque
);
967 impl ForeignTypeRef
for SslCipherRef
{
968 type CType
= ffi
::SSL_CIPHER
;
972 /// Returns the name of cipher.
973 pub fn name(&self) -> &str {
975 let ptr
= ffi
::SSL_CIPHER_get_name(self.as_ptr());
976 CStr
::from_ptr(ptr
as *const _
)
979 str::from_utf8(name
.to_bytes()).unwrap()
982 /// Returns the SSL/TLS protocol version that first defined the cipher.
983 pub fn version(&self) -> &str {
984 let version
= unsafe {
985 let ptr
= ffi
::SSL_CIPHER_get_version(self.as_ptr());
986 CStr
::from_ptr(ptr
as *const _
)
989 str::from_utf8(version
.to_bytes()).unwrap()
992 /// Returns the number of bits used for the cipher.
993 pub fn bits(&self) -> CipherBits
{
995 let mut algo_bits
= 0;
996 let secret_bits
= ffi
::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits
);
998 secret
: secret_bits
.into(),
999 algorithm
: algo_bits
.into(),
1004 /// Returns a textual description of the cipher used
1005 pub fn description(&self) -> String
{
1007 // SSL_CIPHER_description requires a buffer of at least 128 bytes.
1008 let mut buf
= [0; 128];
1009 let ptr
= ffi
::SSL_CIPHER_description(self.as_ptr(), buf
.as_mut_ptr(), 128);
1010 String
::from_utf8(CStr
::from_ptr(ptr
as *const _
).to_bytes().to_vec()).unwrap()
1016 type CType
= ffi
::SSL_SESSION
;
1017 fn drop
= ffi
::SSL_SESSION_free
;
1019 pub struct SslSession
;
1020 pub struct SslSessionRef
;
1023 unsafe impl Sync
for SslSession {}
1024 unsafe impl Send
for SslSession {}
1026 impl Clone
for SslSession
{
1027 fn clone(&self) -> SslSession
{
1032 impl Borrow
<SslSessionRef
> for SslSession
{
1033 fn borrow(&self) -> &SslSessionRef
{
1038 impl ToOwned
for SslSessionRef
{
1039 type Owned
= SslSession
;
1041 fn to_owned(&self) -> SslSession
{
1043 compat
::SSL_SESSION_up_ref(self.as_ptr());
1044 SslSession(self.as_ptr())
1049 impl SslSessionRef
{
1050 /// Returns the SSL session ID.
1051 pub fn id(&self) -> &[u8] {
1054 let p
= ffi
::SSL_SESSION_get_id(self.as_ptr(), &mut len
);
1055 slice
::from_raw_parts(p
as *const u8, len
as usize)
1059 /// Returns the length of the master key.
1060 pub fn master_key_len(&self) -> usize {
1061 unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
1064 /// Copies the master key into the provided buffer.
1066 /// Returns the number of bytes written.
1067 pub fn master_key(&self, buf
: &mut [u8]) -> usize {
1068 unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
1073 type CType
= ffi
::SSL
;
1074 fn drop
= ffi
::SSL_free
;
1081 /// Returns a new extra data index.
1083 /// Each invocation of this function is guaranteed to return a distinct
1085 pub fn new_ex_index
<T
>() -> Result
<Index
<Ssl
, T
>, ErrorStack
>
1087 T
: '
static + Sync
+ Send
,
1091 let idx
= try
!(cvt_n(compat
::get_new_ssl_idx(free_data_box
::<T
>)));
1092 Ok(Index
::from_raw(idx
))
1097 impl fmt
::Debug
for SslRef
{
1098 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
1099 let mut builder
= fmt
.debug_struct("Ssl");
1100 builder
.field("state", &self.state_string_long());
1101 if let Some(err
) = self.verify_result() {
1102 builder
.field("verify_result", &err
);
1109 fn get_raw_rbio(&self) -> *mut ffi
::BIO
{
1110 unsafe { ffi::SSL_get_rbio(self.as_ptr()) }
1113 fn read(&mut self, buf
: &mut [u8]) -> c_int
{
1114 let len
= cmp
::min(c_int
::max_value() as usize, buf
.len()) as c_int
;
1115 unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) }
1118 fn write(&mut self, buf
: &[u8]) -> c_int
{
1119 let len
= cmp
::min(c_int
::max_value() as usize, buf
.len()) as c_int
;
1120 unsafe { ffi::SSL_write(self.as_ptr(), buf.as_ptr() as *const c_void, len) }
1123 fn get_error(&self, ret
: c_int
) -> c_int
{
1124 unsafe { ffi::SSL_get_error(self.as_ptr(), ret) }
1127 /// Sets the verification mode to be used during the handshake process.
1129 /// Use `set_verify_callback` to additionally add a callback.
1130 pub fn set_verify(&mut self, mode
: SslVerifyMode
) {
1131 unsafe { ffi::SSL_set_verify(self.as_ptr(), mode.bits as c_int, None) }
1134 /// Sets the certificate verification callback to be used during the
1135 /// handshake process.
1137 /// The callback is provided with a boolean indicating if the
1138 /// preveification process was successful, and an object providing access
1139 /// to the certificate chain. It should return `true` if the certificate
1140 /// chain is valid and `false` otherwise.
1141 pub fn set_verify_callback
<F
>(&mut self, mode
: SslVerifyMode
, verify
: F
)
1143 F
: Fn(bool
, &X509StoreContextRef
) -> bool
+ Any
+ '
static + Sync
+ Send
,
1146 let verify
= Box
::new(verify
);
1147 ffi
::SSL_set_ex_data(
1149 get_ssl_callback_idx
::<F
>(),
1150 mem
::transmute(verify
),
1152 ffi
::SSL_set_verify(self.as_ptr(), mode
.bits
as c_int
, Some(ssl_raw_verify
::<F
>));
1156 pub fn set_tmp_dh(&mut self, dh
: &DhRef
) -> Result
<(), ErrorStack
> {
1157 unsafe { cvt(ffi::SSL_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) }
1160 pub fn set_tmp_dh_callback
<F
>(&mut self, callback
: F
)
1162 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<Dh
, ErrorStack
> + Any
+ '
static + Sync
+ Send
,
1165 let callback
= Box
::new(callback
);
1166 ffi
::SSL_set_ex_data(
1168 get_ssl_callback_idx
::<F
>(),
1169 Box
::into_raw(callback
) as *mut c_void
,
1171 let f
: unsafe extern "C" fn(_
, _
, _
) -> _
= raw_tmp_dh_ssl
::<F
>;
1172 ffi
::SSL_set_tmp_dh_callback(self.as_ptr(), f
);
1176 pub fn set_tmp_ecdh(&mut self, key
: &EcKeyRef
) -> Result
<(), ErrorStack
> {
1177 unsafe { cvt(ffi::SSL_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) }
1180 /// Requires the `v101` feature and OpenSSL 1.0.1, or the `v102` feature and OpenSSL 1.0.2.
1181 #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))]
1182 pub fn set_tmp_ecdh_callback
<F
>(&mut self, callback
: F
)
1184 F
: Fn(&mut SslRef
, bool
, u32) -> Result
<EcKey
, ErrorStack
> + Any
+ '
static + Sync
+ Send
,
1187 let callback
= Box
::new(callback
);
1188 ffi
::SSL_set_ex_data(
1190 get_ssl_callback_idx
::<F
>(),
1191 Box
::into_raw(callback
) as *mut c_void
,
1193 let f
: unsafe extern "C" fn(_
, _
, _
) -> _
= raw_tmp_ecdh_ssl
::<F
>;
1194 ffi
::SSL_set_tmp_ecdh_callback(self.as_ptr(), f
);
1198 /// If `onoff` is set to `true`, enable ECDHE for key exchange with
1199 /// compatible clients, and automatically select an appropriate elliptic
1202 /// Requires the `v102` feature and OpenSSL 1.0.2.
1203 #[cfg(all(feature = "v102", ossl102))]
1204 pub fn set_ecdh_auto(&mut self, onoff
: bool
) -> Result
<(), ErrorStack
> {
1205 unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
1208 pub fn current_cipher(&self) -> Option
<&SslCipherRef
> {
1210 let ptr
= ffi
::SSL_get_current_cipher(self.as_ptr());
1215 Some(SslCipherRef
::from_ptr(ptr
as *mut _
))
1220 pub fn state_string(&self) -> &'
static str {
1221 let state
= unsafe {
1222 let ptr
= ffi
::SSL_state_string(self.as_ptr());
1223 CStr
::from_ptr(ptr
as *const _
)
1226 str::from_utf8(state
.to_bytes()).unwrap()
1229 pub fn state_string_long(&self) -> &'
static str {
1230 let state
= unsafe {
1231 let ptr
= ffi
::SSL_state_string_long(self.as_ptr());
1232 CStr
::from_ptr(ptr
as *const _
)
1235 str::from_utf8(state
.to_bytes()).unwrap()
1238 /// Sets the host name to be used with SNI (Server Name Indication).
1239 pub fn set_hostname(&mut self, hostname
: &str) -> Result
<(), ErrorStack
> {
1240 let cstr
= CString
::new(hostname
).unwrap();
1242 cvt(ffi
::SSL_set_tlsext_host_name(
1244 cstr
.as_ptr() as *mut _
,
1245 ) as c_int
).map(|_
| ())
1249 /// Returns the certificate of the peer, if present.
1250 pub fn peer_certificate(&self) -> Option
<X509
> {
1252 let ptr
= ffi
::SSL_get_peer_certificate(self.as_ptr());
1256 Some(X509
::from_ptr(ptr
))
1261 /// Returns the certificate chain of the peer, if present.
1263 /// On the client side, the chain includes the leaf certificate, but on the server side it does
1265 pub fn peer_cert_chain(&self) -> Option
<&StackRef
<X509
>> {
1267 let ptr
= ffi
::SSL_get_peer_cert_chain(self.as_ptr());
1271 Some(StackRef
::from_ptr(ptr
))
1276 /// Returns the certificate associated with this `Ssl`, if present.
1277 pub fn certificate(&self) -> Option
<&X509Ref
> {
1279 let ptr
= ffi
::SSL_get_certificate(self.as_ptr());
1283 Some(X509Ref
::from_ptr(ptr
))
1288 /// Returns the private key associated with this `Ssl`, if present.
1289 pub fn private_key(&self) -> Option
<&PKeyRef
> {
1291 let ptr
= ffi
::SSL_get_privatekey(self.as_ptr());
1295 Some(PKeyRef
::from_ptr(ptr
))
1300 /// Returns the name of the protocol used for the connection, e.g. "TLSv1.2", "SSLv3", etc.
1301 pub fn version(&self) -> &'
static str {
1302 let version
= unsafe {
1303 let ptr
= ffi
::SSL_get_version(self.as_ptr());
1304 CStr
::from_ptr(ptr
as *const _
)
1307 str::from_utf8(version
.to_bytes()).unwrap()
1310 /// Returns the protocol selected by performing Next Protocol Negotiation, if any.
1312 /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
1313 /// to interpret it.
1314 #[cfg(not(libressl261))]
1315 pub fn selected_npn_protocol(&self) -> Option
<&[u8]> {
1317 let mut data
: *const c_uchar
= ptr
::null();
1318 let mut len
: c_uint
= 0;
1319 // Get the negotiated protocol from the SSL instance.
1320 // `data` will point at a `c_uchar` array; `len` will contain the length of this array.
1321 ffi
::SSL_get0_next_proto_negotiated(self.as_ptr(), &mut data
, &mut len
);
1326 Some(slice
::from_raw_parts(data
, len
as usize))
1331 /// Returns the protocol selected by performing ALPN, if any.
1333 /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
1334 /// to interpret it.
1336 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0.
1337 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
1338 pub fn selected_alpn_protocol(&self) -> Option
<&[u8]> {
1340 let mut data
: *const c_uchar
= ptr
::null();
1341 let mut len
: c_uint
= 0;
1342 // Get the negotiated protocol from the SSL instance.
1343 // `data` will point at a `c_uchar` array; `len` will contain the length of this array.
1344 ffi
::SSL_get0_alpn_selected(self.as_ptr(), &mut data
, &mut len
);
1349 Some(slice
::from_raw_parts(data
, len
as usize))
1354 /// Returns the number of bytes remaining in the currently processed TLS
1356 pub fn pending(&self) -> usize {
1357 unsafe { ffi::SSL_pending(self.as_ptr()) as usize }
1360 /// Returns the compression currently in use.
1362 /// The result will be either None, indicating no compression is in use, or
1363 /// a string with the compression name.
1364 pub fn compression(&self) -> Option
<&str> {
1368 #[cfg(not(osslconf = "OPENSSL_NO_COMP"))]
1369 fn _compression(&self) -> Option
<&str> {
1371 let ptr
= ffi
::SSL_get_current_compression(self.as_ptr());
1372 if ptr
== ptr
::null() {
1375 let meth
= ffi
::SSL_COMP_get_name(ptr
);
1377 str::from_utf8(CStr
::from_ptr(meth
as *const _
).to_bytes()).unwrap(),
1382 #[cfg(osslconf = "OPENSSL_NO_COMP")]
1383 fn _compression(&self) -> Option
<&str> {
1387 /// Returns the server's name for the current connection
1388 pub fn servername(&self) -> Option
<&str> {
1390 let name
= ffi
::SSL_get_servername(self.as_ptr(), ffi
::TLSEXT_NAMETYPE_host_name
);
1391 if name
== ptr
::null() {
1396 str::from_utf8(CStr
::from_ptr(name
as *const _
).to_bytes()).unwrap(),
1401 /// Changes the context corresponding to the current connection.
1402 pub fn set_ssl_context(&mut self, ctx
: &SslContextRef
) -> Result
<(), ErrorStack
> {
1403 unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) }
1406 /// Returns the context corresponding to the current connection
1407 pub fn ssl_context(&self) -> &SslContextRef
{
1409 let ssl_ctx
= ffi
::SSL_get_SSL_CTX(self.as_ptr());
1410 SslContextRef
::from_ptr(ssl_ctx
)
1414 /// Returns the X509 verification configuration.
1416 /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0.
1417 #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))]
1418 pub fn param_mut(&mut self) -> &mut X509VerifyParamRef
{
1422 #[cfg(any(ossl102, ossl110))]
1423 fn _param_mut(&mut self) -> &mut X509VerifyParamRef
{
1424 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
1427 /// Returns the result of X509 certificate verification.
1428 pub fn verify_result(&self) -> Option
<X509VerifyError
> {
1429 unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr())) }
1432 /// Returns the SSL session.
1433 pub fn session(&self) -> Option
<&SslSessionRef
> {
1435 let p
= ffi
::SSL_get_session(self.as_ptr());
1439 Some(SslSessionRef
::from_ptr(p
))
1444 /// Sets the session to be used.
1448 /// The caller of this method is responsible for ensuring that the session is associated
1449 /// with the same `SslContext` as this `Ssl`.
1450 pub unsafe fn set_session(&mut self, session
: &SslSessionRef
) -> Result
<(), ErrorStack
> {
1451 cvt(ffi
::SSL_set_session(self.as_ptr(), session
.as_ptr())).map(|_
| ())
1454 /// Determines if the session provided to `set_session` was successfully reused.
1455 pub fn session_reused(&self) -> bool
{
1456 unsafe { ffi::SSL_session_reused(self.as_ptr()) != 0 }
1459 /// Sets the status response a client wishes the server to reply with.
1460 pub fn set_status_type(&mut self, type_
: StatusType
) -> Result
<(), ErrorStack
> {
1462 cvt(ffi
::SSL_set_tlsext_status_type(
1465 ) as c_int
).map(|_
| ())
1469 /// Returns the server's OCSP response, if present.
1470 pub fn ocsp_status(&self) -> Option
<&[u8]> {
1472 let mut p
= ptr
::null_mut();
1473 let len
= ffi
::SSL_get_tlsext_status_ocsp_resp(self.as_ptr(), &mut p
);
1478 Some(slice
::from_raw_parts(p
as *const u8, len
as usize))
1483 /// Sets the OCSP response to be returned to the client.
1484 pub fn set_ocsp_status(&mut self, response
: &[u8]) -> Result
<(), ErrorStack
> {
1486 assert
!(response
.len() <= c_int
::max_value() as usize);
1487 let p
= try
!(cvt_p(ffi
::CRYPTO_malloc(
1488 response
.len() as _
,
1489 concat
!(file
!(), "\0").as_ptr() as *const _
,
1492 ptr
::copy_nonoverlapping(response
.as_ptr(), p
as *mut u8, response
.len());
1493 cvt(ffi
::SSL_set_tlsext_status_ocsp_resp(
1496 response
.len() as c_long
,
1497 ) as c_int
).map(|_
| ())
1501 /// Determines if this `Ssl` is configured for server-side or client-side use.
1502 pub fn is_server(&self) -> bool
{
1503 unsafe { compat::SSL_is_server(self.as_ptr()) != 0 }
1506 /// Sets the extra data at the specified index.
1507 pub fn set_ex_data
<T
>(&mut self, index
: Index
<Ssl
, T
>, data
: T
) {
1509 let data
= Box
::new(data
);
1510 ffi
::SSL_set_ex_data(
1513 Box
::into_raw(data
) as *mut c_void
,
1518 /// Returns a reference to the extra data at the specified index.
1519 pub fn ex_data
<T
>(&self, index
: Index
<Ssl
, T
>) -> Option
<&T
> {
1521 let data
= ffi
::SSL_get_ex_data(self.as_ptr(), index
.as_raw());
1525 Some(&*(data
as *const T
))
1531 unsafe impl Sync
for Ssl {}
1532 unsafe impl Send
for Ssl {}
1534 impl fmt
::Debug
for Ssl
{
1535 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
1536 fmt
::Debug
::fmt(&**self, fmt
)
1541 pub fn new(ctx
: &SslContext
) -> Result
<Ssl
, ErrorStack
> {
1543 let ssl
= try
!(cvt_p(ffi
::SSL_new(ctx
.as_ptr())));
1544 Ok(Ssl
::from_ptr(ssl
))
1548 /// Creates an SSL/TLS client operating over the provided stream.
1552 /// OpenSSL's default configuration is insecure. It is highly recommended to use
1553 /// `SslConnector` rather than `Ssl` directly, as it manages that configuration.
1554 pub fn connect
<S
>(self, stream
: S
) -> Result
<SslStream
<S
>, HandshakeError
<S
>>
1558 let mut stream
= SslStream
::new_base(self, stream
);
1559 let ret
= unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) }
;
1563 match stream
.make_error(ret
) {
1564 e @ Error
::WantWrite(_
) |
1565 e @ Error
::WantRead(_
) => {
1566 Err(HandshakeError
::Interrupted(MidHandshakeSslStream
{
1572 Err(HandshakeError
::Failure(MidHandshakeSslStream
{
1581 /// Creates an SSL/TLS server operating over the provided stream.
1585 /// OpenSSL's default configuration is insecure. It is highly recommended to use
1586 /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration.
1587 pub fn accept
<S
>(self, stream
: S
) -> Result
<SslStream
<S
>, HandshakeError
<S
>>
1591 let mut stream
= SslStream
::new_base(self, stream
);
1592 let ret
= unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) }
;
1596 match stream
.make_error(ret
) {
1597 e @ Error
::WantWrite(_
) |
1598 e @ Error
::WantRead(_
) => {
1599 Err(HandshakeError
::Interrupted(MidHandshakeSslStream
{
1605 Err(HandshakeError
::Failure(MidHandshakeSslStream
{
1615 /// An SSL stream midway through the handshake process.
1617 pub struct MidHandshakeSslStream
<S
> {
1618 stream
: SslStream
<S
>,
1622 impl<S
> MidHandshakeSslStream
<S
> {
1623 /// Returns a shared reference to the inner stream.
1624 pub fn get_ref(&self) -> &S
{
1625 self.stream
.get_ref()
1628 /// Returns a mutable reference to the inner stream.
1629 pub fn get_mut(&mut self) -> &mut S
{
1630 self.stream
.get_mut()
1633 /// Returns a shared reference to the `Ssl` of the stream.
1634 pub fn ssl(&self) -> &SslRef
{
1638 /// Returns the underlying error which interrupted this handshake.
1639 pub fn error(&self) -> &Error
{
1643 /// Consumes `self`, returning its error.
1644 pub fn into_error(self) -> Error
{
1648 /// Restarts the handshake process.
1649 pub fn handshake(mut self) -> Result
<SslStream
<S
>, HandshakeError
<S
>> {
1650 let ret
= unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) }
;
1654 match self.stream
.make_error(ret
) {
1655 e @ Error
::WantWrite(_
) |
1656 e @ Error
::WantRead(_
) => {
1658 Err(HandshakeError
::Interrupted(self))
1662 Err(HandshakeError
::Failure(self))
1669 /// A stream wrapper which handles SSL encryption for an underlying stream.
1670 pub struct SslStream
<S
> {
1672 _method
: BioMethod
, // NOTE: this *must* be after the Ssl field so things drop right
1676 impl<S
> fmt
::Debug
for SslStream
<S
>
1680 fn fmt(&self, fmt
: &mut fmt
::Formatter
) -> fmt
::Result
{
1681 fmt
.debug_struct("SslStream")
1682 .field("stream", &self.get_ref())
1683 .field("ssl", &self.ssl())
1688 impl<S
: Read
+ Write
> SslStream
<S
> {
1689 fn new_base(ssl
: Ssl
, stream
: S
) -> Self {
1691 let (bio
, method
) = bio
::new(stream
).unwrap();
1692 ffi
::SSL_set_bio(ssl
.as_ptr(), bio
, bio
);
1702 /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`.
1704 /// This is particularly useful with a nonblocking socket, where the error
1705 /// value will identify if OpenSSL is waiting on read or write readiness.
1706 pub fn ssl_read(&mut self, buf
: &mut [u8]) -> Result
<usize, Error
> {
1707 // The intepretation of the return code here is a little odd with a
1708 // zero-length write. OpenSSL will likely correctly report back to us
1709 // that it read zero bytes, but zero is also the sentinel for "error".
1710 // To avoid that confusion short-circuit that logic and return quickly
1711 // if `buf` has a length of zero.
1716 let ret
= self.ssl
.read(buf
);
1720 match self.make_error(ret
) {
1721 // Don't treat unexpected EOFs as errors when reading
1722 Error
::Stream(ref e
) if e
.kind() == io
::ErrorKind
::ConnectionAborted
=> Ok(0),
1728 /// Like `write`, but returns an `ssl::Error` rather than an `io::Error`.
1730 /// This is particularly useful with a nonblocking socket, where the error
1731 /// value will identify if OpenSSL is waiting on read or write readiness.
1732 pub fn ssl_write(&mut self, buf
: &[u8]) -> Result
<usize, Error
> {
1733 // See above for why we short-circuit on zero-length buffers
1738 let ret
= self.ssl
.write(buf
);
1742 Err(self.make_error(ret
))
1746 /// Shuts down the session.
1748 /// The shutdown process consists of two steps. The first step sends a
1749 /// close notify message to the peer, after which `ShutdownResult::Sent`
1750 /// is returned. The second step awaits the receipt of a close notify
1751 /// message from the peer, after which `ShutdownResult::Received` is
1754 /// While the connection may be closed after the first step, it is
1755 /// recommended to fully shut the session down. In particular, it must
1756 /// be fully shut down if the connection is to be used for further
1757 /// communication in the future.
1758 pub fn shutdown(&mut self) -> Result
<ShutdownResult
, Error
> {
1759 match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) }
{
1760 0 => Ok(ShutdownResult
::Sent
),
1761 1 => Ok(ShutdownResult
::Received
),
1762 n
=> Err(self.make_error(n
)),
1767 impl<S
> SslStream
<S
> {
1768 fn make_error(&mut self, ret
: c_int
) -> Error
{
1771 match self.ssl
.get_error(ret
) {
1772 ffi
::SSL_ERROR_SSL
=> Error
::Ssl(ErrorStack
::get()),
1773 ffi
::SSL_ERROR_SYSCALL
=> {
1774 let errs
= ErrorStack
::get();
1775 if errs
.errors().is_empty() {
1776 match self.get_bio_error() {
1777 Some(err
) => Error
::Stream(err
),
1779 Error
::Stream(io
::Error
::new(
1780 io
::ErrorKind
::ConnectionAborted
,
1781 "unexpected EOF observed",
1789 ffi
::SSL_ERROR_ZERO_RETURN
=> Error
::ZeroReturn
,
1790 ffi
::SSL_ERROR_WANT_WRITE
=> {
1791 let err
= match self.get_bio_error() {
1795 io
::ErrorKind
::Other
,
1796 "BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO",
1800 Error
::WantWrite(err
)
1802 ffi
::SSL_ERROR_WANT_READ
=> {
1803 let err
= match self.get_bio_error() {
1807 io
::ErrorKind
::Other
,
1808 "BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO",
1812 Error
::WantRead(err
)
1815 Error
::Stream(io
::Error
::new(
1816 io
::ErrorKind
::InvalidData
,
1817 format
!("unexpected error {}", err
),
1823 fn check_panic(&mut self) {
1824 if let Some(err
) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) }
{
1829 fn get_bio_error(&mut self) -> Option
<io
::Error
> {
1830 unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) }
1833 /// Returns a reference to the underlying stream.
1834 pub fn get_ref(&self) -> &S
{
1836 let bio
= self.ssl
.get_raw_rbio();
1841 /// Returns a mutable reference to the underlying stream.
1845 /// It is inadvisable to read from or write to the underlying stream as it
1846 /// will most likely corrupt the SSL session.
1847 pub fn get_mut(&mut self) -> &mut S
{
1849 let bio
= self.ssl
.get_raw_rbio();
1854 /// Returns the OpenSSL `Ssl` object associated with this stream.
1855 pub fn ssl(&self) -> &SslRef
{
1860 impl<S
: Read
+ Write
> Read
for SslStream
<S
> {
1861 fn read(&mut self, buf
: &mut [u8]) -> io
::Result
<usize> {
1862 match self.ssl_read(buf
) {
1864 Err(Error
::ZeroReturn
) => Ok(0),
1865 Err(Error
::Stream(e
)) => Err(e
),
1866 Err(Error
::WantRead(e
)) => Err(e
),
1867 Err(Error
::WantWrite(e
)) => Err(e
),
1868 Err(e
) => Err(io
::Error
::new(io
::ErrorKind
::Other
, e
)),
1873 impl<S
: Read
+ Write
> Write
for SslStream
<S
> {
1874 fn write(&mut self, buf
: &[u8]) -> io
::Result
<usize> {
1875 self.ssl_write(buf
).map_err(|e
| match e
{
1876 Error
::Stream(e
) => e
,
1877 Error
::WantRead(e
) => e
,
1878 Error
::WantWrite(e
) => e
,
1879 e
=> io
::Error
::new(io
::ErrorKind
::Other
, e
),
1883 fn flush(&mut self) -> io
::Result
<()> {
1884 self.get_mut().flush()
1888 /// The result of a shutdown request.
1889 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
1890 pub enum ShutdownResult
{
1891 /// A close notify message has been sent to the peer.
1894 /// A close notify response message has been received from the peer.
1905 pub use ffi
::{SSL_CTX_get_options
, SSL_CTX_set_options
, SSL_CTX_clear_options
, SSL_CTX_up_ref
,
1906 SSL_SESSION_get_master_key
, SSL_is_server
, SSL_SESSION_up_ref
};
1908 pub unsafe fn get_new_idx(f
: ffi
::CRYPTO_EX_free
) -> c_int
{
1909 ffi
::CRYPTO_get_ex_new_index(
1910 ffi
::CRYPTO_EX_INDEX_SSL_CTX
,
1919 pub unsafe fn get_new_ssl_idx(f
: ffi
::CRYPTO_EX_free
) -> c_int
{
1920 ffi
::CRYPTO_get_ex_new_index(
1921 ffi
::CRYPTO_EX_INDEX_SSL
,
1930 pub fn tls_method() -> *const ffi
::SSL_METHOD
{
1931 unsafe { ffi::TLS_method() }
1934 pub fn dtls_method() -> *const ffi
::SSL_METHOD
{
1935 unsafe { ffi::DTLS_method() }
1945 use libc
::{self, c_long, c_ulong, c_int, size_t, c_uchar}
;
1947 pub unsafe fn SSL_CTX_get_options(ctx
: *const ffi
::SSL_CTX
) -> c_ulong
{
1948 ffi
::SSL_CTX_ctrl(ctx
as *mut _
, ffi
::SSL_CTRL_OPTIONS
, 0, ptr
::null_mut()) as c_ulong
1951 pub unsafe fn SSL_CTX_set_options(ctx
: *const ffi
::SSL_CTX
, op
: c_ulong
) -> c_ulong
{
1954 ffi
::SSL_CTRL_OPTIONS
,
1960 pub unsafe fn SSL_CTX_clear_options(ctx
: *const ffi
::SSL_CTX
, op
: c_ulong
) -> c_ulong
{
1963 ffi
::SSL_CTRL_CLEAR_OPTIONS
,
1969 pub unsafe fn get_new_idx(f
: ffi
::CRYPTO_EX_free
) -> c_int
{
1970 ffi
::SSL_CTX_get_ex_new_index(0, ptr
::null_mut(), None
, None
, Some(f
))
1973 pub unsafe fn get_new_ssl_idx(f
: ffi
::CRYPTO_EX_free
) -> c_int
{
1974 ffi
::SSL_get_ex_new_index(0, ptr
::null_mut(), None
, None
, Some(f
))
1977 pub unsafe fn SSL_CTX_up_ref(ssl
: *mut ffi
::SSL_CTX
) -> libc
::c_int
{
1978 ffi
::CRYPTO_add_lock(
1979 &mut (*ssl
).references
,
1981 ffi
::CRYPTO_LOCK_SSL_CTX
,
1982 "mod.rs\0".as_ptr() as *const _
,
1983 line
!() as libc
::c_int
,
1988 pub unsafe fn SSL_SESSION_get_master_key(
1989 session
: *const ffi
::SSL_SESSION
,
1994 return (*session
).master_key_length
as size_t
;
1996 if outlen
> (*session
).master_key_length
as size_t
{
1997 outlen
= (*session
).master_key_length
as size_t
;
1999 ptr
::copy_nonoverlapping((*session
).master_key
.as_ptr(), out
, outlen
);
2003 pub fn tls_method() -> *const ffi
::SSL_METHOD
{
2004 unsafe { ffi::SSLv23_method() }
2007 pub fn dtls_method() -> *const ffi
::SSL_METHOD
{
2008 unsafe { ffi::DTLSv1_method() }
2011 pub unsafe fn SSL_is_server(s
: *mut ffi
::SSL
) -> c_int
{
2015 pub unsafe fn SSL_SESSION_up_ref(ses
: *mut ffi
::SSL_SESSION
) -> c_int
{
2016 ffi
::CRYPTO_add_lock(
2017 &mut (*ses
).references
,
2019 ffi
::CRYPTO_LOCK_SSL_CTX
,
2020 "mod.rs\0".as_ptr() as *const _
,
2021 line
!() as libc
::c_int
,