Merge pull request #607 from sfackler/set-session
Logic to support client-side session reuse
This commit is contained in:
commit
d66d84b2f5
|
|
@ -77,8 +77,7 @@ matrix:
|
|||
|
||||
before_install:
|
||||
- ./openssl/test/build.sh
|
||||
- curl https://static.rust-lang.org/rustup.sh |
|
||||
sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
|
||||
- rustup target add $TARGET || true
|
||||
script:
|
||||
- ./openssl/test/run.sh
|
||||
|
||||
|
|
|
|||
|
|
@ -1356,7 +1356,7 @@ pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -
|
|||
|
||||
#[cfg(not(any(ossl101, libressl)))]
|
||||
pub unsafe fn SSL_CTX_set0_verify_cert_store(ctx: *mut SSL_CTX, st: *mut X509_STORE) -> c_long {
|
||||
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, st as *mut c_void)
|
||||
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, st as *mut c_void)
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX,
|
||||
|
|
@ -1891,6 +1891,7 @@ extern {
|
|||
client: *const c_uchar, client_len: c_uint) -> c_int;
|
||||
pub fn SSL_get0_next_proto_negotiated(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint);
|
||||
pub fn SSL_get_session(s: *const SSL) -> *mut SSL_SESSION;
|
||||
pub fn SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int;
|
||||
#[cfg(not(any(ossl101, libressl)))]
|
||||
pub fn SSL_is_server(s: *mut SSL) -> c_int;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::{Mutex, MutexGuard};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong};
|
||||
use libc::time_t;
|
||||
|
|
@ -500,7 +501,7 @@ pub struct SSL_SESSION {
|
|||
verify_result: c_long,
|
||||
timeout: c_long,
|
||||
time: time_t,
|
||||
references: c_int,
|
||||
pub references: c_int,
|
||||
cipher: *const c_void,
|
||||
cipher_id: c_ulong,
|
||||
ciphers: *mut c_void,
|
||||
|
|
@ -533,6 +534,7 @@ pub struct X509_VERIFY_PARAM {
|
|||
pub enum X509_VERIFY_PARAM_ID {}
|
||||
pub enum PKCS12 {}
|
||||
|
||||
pub const SSL_CTRL_GET_SESSION_REUSED: c_int = 8;
|
||||
pub const SSL_CTRL_OPTIONS: c_int = 32;
|
||||
pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
|
||||
pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94;
|
||||
|
|
@ -565,6 +567,7 @@ pub const SSLEAY_DIR : c_int = 5;
|
|||
|
||||
pub const CRYPTO_LOCK_X509: c_int = 3;
|
||||
pub const CRYPTO_LOCK_SSL_CTX: c_int = 12;
|
||||
pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14;
|
||||
|
||||
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
|
||||
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
|
||||
|
|
@ -622,11 +625,15 @@ fn set_id_callback() {}
|
|||
// macros
|
||||
|
||||
pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int {
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ::std::ptr::null_mut()) as c_int
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int {
|
||||
::SSL_ctrl(ssl, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ::std::ptr::null_mut()) as c_int
|
||||
::SSL_ctrl(ssl, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
|
||||
::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
extern {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::sync::{Mutex, MutexGuard};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong};
|
||||
#[cfg(not(ossl101))]
|
||||
|
|
@ -610,7 +611,7 @@ pub struct SSL_SESSION {
|
|||
sess_cert: *mut c_void,
|
||||
peer: *mut X509,
|
||||
verify_result: c_long,
|
||||
references: c_int,
|
||||
pub references: c_int,
|
||||
timeout: c_long,
|
||||
time: c_long,
|
||||
compress_meth: c_uint,
|
||||
|
|
@ -678,6 +679,7 @@ pub struct X509_VERIFY_PARAM {
|
|||
pub enum X509_VERIFY_PARAM_ID {}
|
||||
pub enum PKCS12 {}
|
||||
|
||||
pub const SSL_CTRL_GET_SESSION_REUSED: c_int = 8;
|
||||
pub const SSL_CTRL_OPTIONS: c_int = 32;
|
||||
pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
|
||||
#[cfg(ossl102)]
|
||||
|
|
@ -708,6 +710,7 @@ pub const SSLEAY_DIR : c_int = 5;
|
|||
|
||||
pub const CRYPTO_LOCK_X509: c_int = 3;
|
||||
pub const CRYPTO_LOCK_SSL_CTX: c_int = 12;
|
||||
pub const CRYPTO_LOCK_SSL_SESSION: c_int = 14;
|
||||
|
||||
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
|
||||
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
|
||||
|
|
@ -766,12 +769,16 @@ fn set_id_callback() {}
|
|||
|
||||
#[cfg(ossl102)]
|
||||
pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int {
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ::std::ptr::null_mut()) as c_int
|
||||
::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
pub unsafe fn SSL_set_ecdh_auto(ssl: *mut ::SSL, onoff: c_int) -> c_int {
|
||||
::SSL_ctrl(ssl, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ::std::ptr::null_mut()) as c_int
|
||||
::SSL_ctrl(ssl, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
|
||||
::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int
|
||||
}
|
||||
|
||||
extern {
|
||||
|
|
|
|||
|
|
@ -172,10 +172,12 @@ extern {
|
|||
-> c_int;
|
||||
pub fn X509_up_ref(x: *mut X509) -> c_int;
|
||||
pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int;
|
||||
pub fn SSL_session_reused(ssl: *mut SSL) -> c_int;
|
||||
pub fn SSL_SESSION_get_master_key(session: *const SSL_SESSION,
|
||||
out: *mut c_uchar,
|
||||
outlen: size_t)
|
||||
-> size_t;
|
||||
pub fn SSL_SESSION_up_ref(ses: *mut SSL_SESSION) -> c_int;
|
||||
pub fn X509_get0_extensions(req: *const ::X509) -> *const stack_st_X509_EXTENSION;
|
||||
pub fn X509_STORE_CTX_get0_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509;
|
||||
pub fn EVP_MD_CTX_new() -> *mut EVP_MD_CTX;
|
||||
|
|
|
|||
|
|
@ -93,11 +93,7 @@ impl SslConnector {
|
|||
pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where S: Read + Write
|
||||
{
|
||||
let mut ssl = try!(Ssl::new(&self.0));
|
||||
try!(ssl.set_hostname(domain));
|
||||
try!(setup_verify(&mut ssl, domain));
|
||||
|
||||
ssl.connect(stream)
|
||||
try!(self.configure()).connect(domain, stream)
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream without performing hostname verification.
|
||||
|
|
@ -113,7 +109,56 @@ impl SslConnector {
|
|||
&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where S: Read + Write
|
||||
{
|
||||
try!(Ssl::new(&self.0)).connect(stream)
|
||||
try!(self.configure())
|
||||
.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)
|
||||
}
|
||||
|
||||
/// Returns a structure allowing for configuration of a single TLS session before connection.
|
||||
pub fn configure(&self) -> Result<ConnectConfiguration, ErrorStack> {
|
||||
Ssl::new(&self.0).map(ConnectConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which allows for configuration of a client-side TLS session before connection.
|
||||
pub struct ConnectConfiguration(Ssl);
|
||||
|
||||
impl ConnectConfiguration {
|
||||
/// Returns a shared reference to the inner `Ssl`.
|
||||
pub fn ssl(&self) -> &Ssl {
|
||||
&self.0
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the inner `Ssl`.
|
||||
pub fn ssl_mut(&mut self) -> &mut Ssl {
|
||||
&mut self.0
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification.
|
||||
pub fn connect<S>(mut self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where S: Read + Write
|
||||
{
|
||||
try!(self.0.set_hostname(domain));
|
||||
try!(setup_verify(&mut self.0, domain));
|
||||
|
||||
self.0.connect(stream)
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream without performing hostname verification.
|
||||
///
|
||||
/// The verification configuration of the connector's `SslContext` is not overridden.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// You should think very carefully before you use this method. If hostname verification is not
|
||||
/// used, *any* valid certificate for *any* site will be trusted for use from any other. This
|
||||
/// introduces a significant vulnerability to man-in-the-middle attacks.
|
||||
pub fn danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication<S>(
|
||||
self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where S: Read + Write
|
||||
{
|
||||
self.0.connect(stream)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ use libc::{c_int, c_void, c_long, c_ulong};
|
|||
use libc::{c_uchar, c_uint};
|
||||
use std::any::Any;
|
||||
use std::any::TypeId;
|
||||
use std::borrow::Borrow;
|
||||
use std::cmp;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::{CStr, CString};
|
||||
|
|
@ -1161,6 +1162,32 @@ foreign_type! {
|
|||
pub struct SslSessionRef;
|
||||
}
|
||||
|
||||
unsafe impl Sync for SslSession {}
|
||||
unsafe impl Send for SslSession {}
|
||||
|
||||
impl Clone for SslSession {
|
||||
fn clone(&self) -> SslSession {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<SslSessionRef> for SslSession {
|
||||
fn borrow(&self) -> &SslSessionRef {
|
||||
&self
|
||||
}
|
||||
}
|
||||
|
||||
impl ToOwned for SslSessionRef {
|
||||
type Owned = SslSession;
|
||||
|
||||
fn to_owned(&self) -> SslSession {
|
||||
unsafe {
|
||||
compat::SSL_SESSION_up_ref(self.as_ptr());
|
||||
SslSession(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SslSessionRef {
|
||||
/// Returns the SSL session ID.
|
||||
pub fn id(&self) -> &[u8] {
|
||||
|
|
@ -1508,6 +1535,23 @@ impl SslRef {
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the session to be used.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller of this method is responsible for ensuring that the session is associated
|
||||
/// with the same `SslContext` as this `Ssl`.
|
||||
pub unsafe fn set_session(&mut self, session: &SslSessionRef) -> Result<(), ErrorStack> {
|
||||
cvt(ffi::SSL_set_session(self.as_ptr(), session.as_ptr())).map(|_| ())
|
||||
}
|
||||
|
||||
/// Determines if the session provided to `set_session` was successfully reused.
|
||||
pub fn session_reused(&self) -> bool {
|
||||
unsafe {
|
||||
ffi::SSL_session_reused(self.as_ptr()) != 0
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the status response a client wishes the server to reply with.
|
||||
pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
|
|
@ -1918,7 +1962,7 @@ mod compat {
|
|||
use libc::c_int;
|
||||
|
||||
pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_clear_options, SSL_CTX_up_ref,
|
||||
SSL_SESSION_get_master_key, SSL_is_server};
|
||||
SSL_SESSION_get_master_key, SSL_is_server, SSL_SESSION_up_ref};
|
||||
|
||||
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
|
||||
ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL_CTX,
|
||||
|
|
@ -2014,4 +2058,13 @@ mod compat {
|
|||
pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
|
||||
(*s).server
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
|
||||
ffi::CRYPTO_add_lock(&mut (*ses).references,
|
||||
1,
|
||||
ffi::CRYPTO_LOCK_SSL_CTX,
|
||||
"mod.rs\0".as_ptr() as *const _,
|
||||
line!() as libc::c_int);
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue