From 336175990cb3584b85385a093b2d1e245ffdb1f1 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 20:54:53 -0800 Subject: [PATCH 1/8] Add SSL_SESSION --- openssl-sys/src/libressl.rs | 36 +++++++++++++++++++++ openssl-sys/src/ossl10x.rs | 63 +++++++++++++++++++++++++++++++++++-- openssl-sys/src/ossl110.rs | 1 + 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/openssl-sys/src/libressl.rs b/openssl-sys/src/libressl.rs index 0f20713e..83c5aee6 100644 --- a/openssl-sys/src/libressl.rs +++ b/openssl-sys/src/libressl.rs @@ -358,6 +358,38 @@ pub struct SSL_CTX { srtp_profiles: *mut c_void, } +#[repr(C)] +pub struct SSL_SESSION { + ssl_version: c_int, + master_key_length: c_int, + master_key: [c_uchar; SSL_MAX_MASTER_KEY_LENGTH as usize], + session_id_length: c_uint, + session_id: [c_uchar; SSL_MAX_SSL_SESSION_ID_LENGTH as usize], + sid_ctx_length: c_uint, + sid_ctx: [c_uchar; SSL_MAX_SID_CTX_LENGTH as usize], + not_resumable: c_int, + sess_cert: *mut c_void, + peer: *mut X509, + verify_result: c_long, + timeout: c_long, + time: time_t, + references: c_int, + cipher: *const c_void, + cipher_id: c_ulong, + ciphers: *mut c_void, + ex_data: ::CRYPTO_EX_DATA, + prev: *mut c_void, + next: *mut c_void, + tlsext_hostname: *mut c_char, + tlsext_ecpointformatlist_length: size_t, + tlsext_ecpointformatlist: *mut u8, + tlsext_ellipticcurvelist_length: size_t, + tlsext_ellipticcurvelist: *mut u16, + tlsext_tick: *mut c_uchar, + tlsext_ticklen: size_t, + tlsext_tick_lifetime_hint: c_long, +} + #[repr(C)] pub struct X509_VERIFY_PARAM { pub name: *mut c_char, @@ -393,6 +425,10 @@ pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000; pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000; pub const SSL_OP_NO_SSLv2: c_ulong = 0x0; +pub const SSL_MAX_SSL_SESSION_ID_LENGTH: c_int = 32; +pub const SSL_MAX_SID_CTX_LENGTH: c_int = 32; +pub const SSL_MAX_MASTER_KEY_LENGTH: c_int = 48; + pub const SSLEAY_VERSION : c_int = 0; pub const SSLEAY_CFLAGS : c_int = 2; pub const SSLEAY_BUILT_ON : c_int = 3; diff --git a/openssl-sys/src/ossl10x.rs b/openssl-sys/src/ossl10x.rs index 4f418f14..5b0ca3d5 100644 --- a/openssl-sys/src/ossl10x.rs +++ b/openssl-sys/src/ossl10x.rs @@ -2,9 +2,7 @@ use std::sync::{Mutex, MutexGuard}; use std::sync::{Once, ONCE_INIT}; use std::mem; -use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong}; -#[cfg(not(ossl101))] -use libc::time_t; +use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong, time_t}; #[repr(C)] pub struct stack_st_ASN1_OBJECT { @@ -417,6 +415,59 @@ pub struct SSL_CTX { tlsext_ellipticcurvelist: *mut c_uchar, } +#[repr(C)] +pub struct SSL_SESSION { + ssl_version: c_int, + key_arg_length: c_uint, + key_arg: [c_uchar; SSL_MAX_KEY_ARG_LENGTH as usize], + master_key_length: c_uint, + master_key: [c_uchar; SSL_MAX_MASTER_KEY_LENGTH as usize], + session_id_length: c_uint, + session_id: [c_uchar; SSL_MAX_SSL_SESSION_ID_LENGTH as usize], + sid_ctx_length: c_uint, + sid_ctx: [c_uchar; SSL_MAX_SID_CTX_LENGTH as usize], + #[cfg(not(osslconf = "OPENSSL_NO_KRB5"))] + krb5_client_princ_len: c_uint, + #[cfg(not(osslconf = "OPENSSL_NO_KRB5"))] + krb5_client_princ: [c_uchar; SSL_MAX_KRB5_PRINCIPAL_LENGTH], + #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] + psk_identity_hint: *mut c_char, + #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] + psk_identity: *mut c_char, + not_resumable: c_int, + sess_cert: *mut c_void, + peer: *mut X509, + verify_result: c_long, + references: c_int, + timeout: c_long, + time: time_t, + compress_meth: c_uint, + cipher: *const c_void, + cipher_id: c_ulong, + ciphers: *mut c_void, + ex_data: ::CRYPTO_EX_DATA, + prev: *mut c_void, + next: *mut c_void, + #[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))] + tlsext_hostname: *mut c_char, + #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC")))] + tlsext_ecpointformatlist_length: size_t, + #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC")))] + tlsext_ecpointformatlist: *mut c_uchar, + #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC")))] + tlsext_ellipticcurvelist_length: size_t, + #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC")))] + tlsext_ellipticcurvelist: *mut c_uchar, + #[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))] + tlsext_tick: *mut c_uchar, + #[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))] + tlsext_ticklen: size_t, + #[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))] + tlsext_tick_lifetime_hint: c_long, + #[cfg(not(osslconf = "OPENSSL_NO_SRP"))] + srp_username: *mut c_char, +} + #[repr(C)] pub struct SRP_CTX { SRP_cb_arg: *mut c_void, @@ -470,6 +521,12 @@ pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000; pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000; pub const SSL_OP_NO_SSLv2: c_ulong = 0x01000000; +pub const SSL_MAX_SSL_SESSION_ID_LENGTH: c_int = 32; +pub const SSL_MAX_SID_CTX_LENGTH: c_int = 32; +pub const SSL_MAX_KEY_ARG_LENGTH: c_int = 8; +pub const SSL_MAX_MASTER_KEY_LENGTH: c_int = 48; +pub const SSL_MAX_KRB5_PRINCIPAL_LENGTH: c_int = 256; + pub const SSLEAY_VERSION : c_int = 0; pub const SSLEAY_CFLAGS : c_int = 2; pub const SSLEAY_BUILT_ON : c_int = 3; diff --git a/openssl-sys/src/ossl110.rs b/openssl-sys/src/ossl110.rs index bb4fa19b..9a5d287b 100644 --- a/openssl-sys/src/ossl110.rs +++ b/openssl-sys/src/ossl110.rs @@ -13,6 +13,7 @@ pub enum HMAC_CTX {} pub enum OPENSSL_STACK {} pub enum RSA {} pub enum SSL_CTX {} +pub enum SSL_SESSION {} pub enum stack_st_ASN1_OBJECT {} pub enum stack_st_GENERAL_NAME {} pub enum stack_st_OPENSSL_STRING {} From 1ffe57429885f935c10301e7838fa9871c35c95b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 20:57:50 -0800 Subject: [PATCH 2/8] Add SSL_SESSION functions --- openssl-sys/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 22af7c96..a8ac9ba1 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1748,6 +1748,9 @@ extern { inbuf: *const c_uchar, inlen: c_uint, 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_SESSION_free(s: *mut SSL_SESSION); #[cfg(not(ossl101))] pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int; From 88a7032f4b78895eaeeb72d3837dd698e571e882 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 20:59:46 -0800 Subject: [PATCH 3/8] Types and accessor for SslSession --- openssl/src/ssl/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3eead8f2..d1ed55fe 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1334,6 +1334,11 @@ impl SslRef { pub fn verify_result(&self) -> Option { unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr())) } } + + /// Returns the SSL session. + pub fn session(&self) -> &SslSessionRef { + unsafe { SslSessionRef::from_ptr(ffi::SSL_get_session(self.as_ptr())) } + } } unsafe impl Sync for Ssl {} @@ -1345,6 +1350,8 @@ impl fmt::Debug for Ssl { } } +type_!(SslSession, SslSessionRef, ffi::SSL_SESSION, ffi::SSL_SESSION_free); + impl Ssl { pub fn new(ctx: &SslContext) -> Result { unsafe { From 5d53405597f2e8dc3a6543e8c4a56705b0ecd47a Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 21:07:51 -0800 Subject: [PATCH 4/8] Provide access to the session ID --- openssl-sys/src/lib.rs | 1 + openssl/src/ssl/mod.rs | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index a8ac9ba1..0ea0e5d8 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1751,6 +1751,7 @@ extern { pub fn SSL_get_session(s: *const SSL) -> *mut SSL_SESSION; pub fn SSL_SESSION_free(s: *mut SSL_SESSION); + pub fn SSL_SESSION_get_id(s: *const SSL_SESSION, len: *mut c_uint) -> *const c_uchar; #[cfg(not(ossl101))] pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index d1ed55fe..3949210d 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1029,6 +1029,19 @@ impl SslCipherRef { } } +type_!(SslSession, SslSessionRef, ffi::SSL_SESSION, ffi::SSL_SESSION_free); + +impl SslSessionRef { + /// Returns the SSL session ID. + pub fn id(&self) -> &[u8] { + unsafe { + let mut len = 0; + let p = ffi::SSL_SESSION_get_id(self.as_ptr(), &mut len); + slice::from_raw_parts(p as *const u8, len as usize) + } + } +} + type_!(Ssl, SslRef, ffi::SSL, ffi::SSL_free); impl fmt::Debug for SslRef { @@ -1350,8 +1363,6 @@ impl fmt::Debug for Ssl { } } -type_!(SslSession, SslSessionRef, ffi::SSL_SESSION, ffi::SSL_SESSION_free); - impl Ssl { pub fn new(ctx: &SslContext) -> Result { unsafe { From 0b1bfee46d6c986d6cb073c922045ae98b598900 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 21:15:09 -0800 Subject: [PATCH 5/8] session is nullable --- openssl/src/ssl/mod.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3949210d..ce9d65ef 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1349,8 +1349,15 @@ impl SslRef { } /// Returns the SSL session. - pub fn session(&self) -> &SslSessionRef { - unsafe { SslSessionRef::from_ptr(ffi::SSL_get_session(self.as_ptr())) } + pub fn session(&self) -> Option<&SslSessionRef> { + unsafe { + let p = ffi::SSL_get_session(self.as_ptr()); + if p.is_null() { + None + } else { + Some(SslSessionRef::from_ptr(p)) + } + } } } From a2c118bf82ac4fbb13d5dd32b931490862ccd930 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 21:18:13 -0800 Subject: [PATCH 6/8] Add basic session tests --- openssl/src/ssl/tests/mod.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index e685d658..744b2688 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1372,6 +1372,22 @@ fn tmp_ecdh_callback_ssl() { assert!(CALLED_BACK.load(Ordering::SeqCst)); } +#[test] +fn idle_session() { + let ctx = SslContext::builder(SslMethod::tls()).unwrap().build(); + let ssl = Ssl::new(&ctx).unwrap(); + assert!(ssl.session().is_none()); +} + +#[test] +fn active_session() { + let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); + + let s = TcpStream::connect("google.com:443").unwrap(); + let socket = connector.connect("google.com", s).unwrap(); + assert!(socket.ssl().session().is_some()); +} + fn _check_kinds() { fn is_send() {} fn is_sync() {} From 404e0341d82d5aab58daaa48b864eaf1a281d101 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 21:33:47 -0800 Subject: [PATCH 7/8] Provide master key access --- openssl-sys/src/libressl.rs | 4 ++-- openssl-sys/src/ossl10x.rs | 6 +++--- openssl-sys/src/ossl110.rs | 6 +++++- openssl/src/ssl/mod.rs | 28 +++++++++++++++++++++++++++- openssl/src/ssl/tests/mod.rs | 10 +++++++++- 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/openssl-sys/src/libressl.rs b/openssl-sys/src/libressl.rs index 83c5aee6..2c747ffe 100644 --- a/openssl-sys/src/libressl.rs +++ b/openssl-sys/src/libressl.rs @@ -361,8 +361,8 @@ pub struct SSL_CTX { #[repr(C)] pub struct SSL_SESSION { ssl_version: c_int, - master_key_length: c_int, - master_key: [c_uchar; SSL_MAX_MASTER_KEY_LENGTH as usize], + pub master_key_length: c_int, + pub master_key: [c_uchar; 48], session_id_length: c_uint, session_id: [c_uchar; SSL_MAX_SSL_SESSION_ID_LENGTH as usize], sid_ctx_length: c_uint, diff --git a/openssl-sys/src/ossl10x.rs b/openssl-sys/src/ossl10x.rs index 5b0ca3d5..4d37d2a1 100644 --- a/openssl-sys/src/ossl10x.rs +++ b/openssl-sys/src/ossl10x.rs @@ -420,8 +420,8 @@ pub struct SSL_SESSION { ssl_version: c_int, key_arg_length: c_uint, key_arg: [c_uchar; SSL_MAX_KEY_ARG_LENGTH as usize], - master_key_length: c_uint, - master_key: [c_uchar; SSL_MAX_MASTER_KEY_LENGTH as usize], + pub master_key_length: c_int, + pub master_key: [c_uchar; 48], session_id_length: c_uint, session_id: [c_uchar; SSL_MAX_SSL_SESSION_ID_LENGTH as usize], sid_ctx_length: c_uint, @@ -429,7 +429,7 @@ pub struct SSL_SESSION { #[cfg(not(osslconf = "OPENSSL_NO_KRB5"))] krb5_client_princ_len: c_uint, #[cfg(not(osslconf = "OPENSSL_NO_KRB5"))] - krb5_client_princ: [c_uchar; SSL_MAX_KRB5_PRINCIPAL_LENGTH], + krb5_client_princ: [c_uchar; SSL_MAX_KRB5_PRINCIPAL_LENGTH as usize], #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] psk_identity_hint: *mut c_char, #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] diff --git a/openssl-sys/src/ossl110.rs b/openssl-sys/src/ossl110.rs index 9a5d287b..898ad4a2 100644 --- a/openssl-sys/src/ossl110.rs +++ b/openssl-sys/src/ossl110.rs @@ -1,4 +1,4 @@ -use libc::{c_int, c_void, c_char, c_uchar, c_ulong, c_long, c_uint}; +use libc::{c_int, c_void, c_char, c_uchar, c_ulong, c_long, c_uint, size_t}; pub enum BIGNUM {} pub enum BIO {} @@ -156,6 +156,10 @@ 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_get_master_key(session: *const SSL_SESSION, + out: *mut c_uchar, + outlen: size_t) + -> size_t; 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; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index ce9d65ef..6d49f2b1 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1040,6 +1040,18 @@ impl SslSessionRef { slice::from_raw_parts(p as *const u8, len as usize) } } + + /// Returns the length of the master key. + pub fn master_key_len(&self) -> usize { + unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) } + } + + /// Copies the master key into the provided buffer. + /// + /// Returns the number of bytes written. + pub fn master_key(&self, buf: &mut [u8]) -> usize { + unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } + } } type_!(Ssl, SslRef, ffi::SSL, ffi::SSL_free); @@ -1728,6 +1740,7 @@ mod compat { pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options}; pub use ffi::{SSL_CTX_clear_options, SSL_CTX_up_ref}; + pub use ffi::SSL_SESSION_get_master_key; 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, @@ -1762,7 +1775,7 @@ mod compat { use std::ptr; use ffi; - use libc::{self, c_long, c_ulong, c_int}; + use libc::{self, c_long, c_ulong, c_int, size_t, c_uchar}; pub unsafe fn SSL_CTX_get_options(ctx: *const ffi::SSL_CTX) -> c_ulong { ffi::SSL_CTX_ctrl(ctx as *mut _, ffi::SSL_CTRL_OPTIONS, 0, ptr::null_mut()) as c_ulong @@ -1799,6 +1812,19 @@ mod compat { 0 } + pub unsafe fn SSL_SESSION_get_master_key(session: *const ffi::SSL_SESSION, + out: *mut c_uchar, + mut outlen: size_t) -> size_t { + if outlen == 0 { + return (*session).master_key_length as size_t; + } + if outlen > (*session).master_key_length as size_t { + outlen = (*session).master_key_length as size_t; + } + ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen); + outlen + } + pub fn tls_method() -> *const ffi::SSL_METHOD { unsafe { ffi::SSLv23_method() } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 744b2688..14bb2f71 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1385,7 +1385,15 @@ fn active_session() { let s = TcpStream::connect("google.com:443").unwrap(); let socket = connector.connect("google.com", s).unwrap(); - assert!(socket.ssl().session().is_some()); + let session = socket.ssl().session().unwrap(); + let len = session.master_key_len(); + let mut buf = vec![0; len - 1]; + let copied = session.master_key(&mut buf); + assert_eq!(copied, buf.len()); + let mut buf = vec![0; len + 1]; + let copied = session.master_key(&mut buf); + assert_eq!(copied, len); + } fn _check_kinds() { From c6ea4f3e2a8b6159d4772ee5274001cff7caff2f Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Wed, 4 Jan 2017 22:34:50 -0800 Subject: [PATCH 8/8] Fix time type --- openssl-sys/src/ossl10x.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/openssl-sys/src/ossl10x.rs b/openssl-sys/src/ossl10x.rs index 4d37d2a1..037298c1 100644 --- a/openssl-sys/src/ossl10x.rs +++ b/openssl-sys/src/ossl10x.rs @@ -2,7 +2,9 @@ use std::sync::{Mutex, MutexGuard}; use std::sync::{Once, ONCE_INIT}; use std::mem; -use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong, time_t}; +use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong}; +#[cfg(not(ossl101))] +use libc::time_t; #[repr(C)] pub struct stack_st_ASN1_OBJECT { @@ -440,7 +442,7 @@ pub struct SSL_SESSION { verify_result: c_long, references: c_int, timeout: c_long, - time: time_t, + time: c_long, compress_meth: c_uint, cipher: *const c_void, cipher_id: c_ulong,