aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2017-01-05 12:56:14 -0800
committerGitHub <[email protected]>2017-01-05 12:56:14 -0800
commit58c468803160f6f0d78c80c846dbf4622bb43df9 (patch)
tree20205314f7c3ce878a76b41e794e818caaa5e5c2
parentRelease v0.9.5 (diff)
parentFix time type (diff)
downloadrust-openssl-58c468803160f6f0d78c80c846dbf4622bb43df9.tar.xz
rust-openssl-58c468803160f6f0d78c80c846dbf4622bb43df9.zip
Merge pull request #549 from sfackler/ssl-session
Ssl session
-rw-r--r--openssl-sys/src/lib.rs4
-rw-r--r--openssl-sys/src/libressl.rs36
-rw-r--r--openssl-sys/src/ossl10x.rs59
-rw-r--r--openssl-sys/src/ossl110.rs7
-rw-r--r--openssl/src/ssl/mod.rs53
-rw-r--r--openssl/src/ssl/tests/mod.rs24
6 files changed, 181 insertions, 2 deletions
diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs
index 22af7c96..0ea0e5d8 100644
--- a/openssl-sys/src/lib.rs
+++ b/openssl-sys/src/lib.rs
@@ -1748,6 +1748,10 @@ 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);
+ 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-sys/src/libressl.rs b/openssl-sys/src/libressl.rs
index 0f20713e..2c747ffe 100644
--- a/openssl-sys/src/libressl.rs
+++ b/openssl-sys/src/libressl.rs
@@ -359,6 +359,38 @@ pub struct SSL_CTX {
}
#[repr(C)]
+pub struct SSL_SESSION {
+ ssl_version: c_int,
+ 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,
+ 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,
pub check_time: time_t,
@@ -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..037298c1 100644
--- a/openssl-sys/src/ossl10x.rs
+++ b/openssl-sys/src/ossl10x.rs
@@ -418,6 +418,59 @@ pub struct SSL_CTX {
}
#[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],
+ 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,
+ 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 as usize],
+ #[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: c_long,
+ 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,
TLS_ext_srp_username_callback: *mut c_void,
@@ -470,6 +523,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..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 {}
@@ -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 {}
@@ -155,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 3eead8f2..6d49f2b1 100644
--- a/openssl/src/ssl/mod.rs
+++ b/openssl/src/ssl/mod.rs
@@ -1029,6 +1029,31 @@ 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)
+ }
+ }
+
+ /// 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);
impl fmt::Debug for SslRef {
@@ -1334,6 +1359,18 @@ impl SslRef {
pub fn verify_result(&self) -> Option<X509VerifyError> {
unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr())) }
}
+
+ /// Returns the SSL session.
+ 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))
+ }
+ }
+ }
}
unsafe impl Sync for Ssl {}
@@ -1703,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,
@@ -1737,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
@@ -1774,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 e685d658..14bb2f71 100644
--- a/openssl/src/ssl/tests/mod.rs
+++ b/openssl/src/ssl/tests/mod.rs
@@ -1372,6 +1372,30 @@ 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();
+ 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() {
fn is_send<T: Send>() {}
fn is_sync<T: Sync>() {}