Loading openssl-sys-extras/src/lib.rs +7 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ extern crate openssl_sys; extern crate libc; use libc::{c_int, c_uint, c_long, c_char}; use libc::{c_int, c_uint, c_long, c_char, c_void}; use openssl_sys::{HMAC_CTX, EVP_MD, ENGINE, SSL_CTX, BIO, X509, stack_st_X509_EXTENSION, SSL, DH}; macro_rules! import_options { Loading Loading @@ -73,4 +73,10 @@ extern { pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long; #[link_name = "X509_get_extensions_shim"] pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; #[link_name = "SSL_CTX_set_tlsext_servername_callback_shim"] pub fn SSL_CTX_set_tlsext_servername_callback(ssl: *mut SSL_CTX, callback: Option<extern fn()>); #[link_name = "SSL_CTX_set_tlsext_servername_arg_shim"] pub fn SSL_CTX_set_tlsext_servername_arg(ssl: *mut SSL_CTX, arg: *const c_void); #[link_name = "SSL_CTX_increment_refcount_shim"] pub fn SSL_CTX_increment_refcount(ssl: *mut SSL_CTX) -> c_long; } openssl-sys-extras/src/openssl_shim.c +13 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,19 @@ long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) { return SSL_CTX_set_tmp_dh(ctx, dh); } long SSL_CTX_set_tlsext_servername_callback_shim(SSL_CTX *ctx, int (*callback)(SSL_CTX *, int *, void*)) { return SSL_CTX_set_tlsext_servername_callback(ctx, callback); } long SSL_CTX_set_tlsext_servername_arg_shim(SSL_CTX *ctx, void* arg) { return SSL_CTX_set_tlsext_servername_arg(ctx, arg); } long SSL_CTX_increment_refcount_shim(SSL_CTX *ctx) { int i = CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); return i; } #if OPENSSL_VERSION_NUMBER >= 0x10002000L int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { return SSL_CTX_set_ecdh_auto(ctx, onoff); Loading openssl-sys/src/lib.rs +5 −1 Original line number Diff line number Diff line Loading @@ -194,6 +194,8 @@ pub const PKCS5_SALT_LEN: 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_TLSEXT_SERVERNAME_CB: c_int = 53; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: c_int = 54; pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; Loading Loading @@ -591,12 +593,15 @@ extern "C" { pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int; pub fn SSL_get_ex_data_X509_STORE_CTX_idx() -> c_int; pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX; pub fn SSL_set_SSL_CTX(ssl: *mut SSL, ctx: *mut SSL_CTX) -> *mut SSL_CTX; pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char; pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char; pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; Loading Loading @@ -625,7 +630,6 @@ extern "C" { pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int; pub fn SSL_CTX_ctrl(ssl: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; #[cfg(feature = "npn")] pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX, cb: extern "C" fn(ssl: *mut SSL, Loading openssl/src/ssl/mod.rs +112 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ extern "C" { } static mut VERIFY_IDX: c_int = -1; static mut SNI_IDX: c_int = -1; /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. Loading @@ -58,6 +59,11 @@ pub fn init() { None, None); assert!(verify_idx >= 0); VERIFY_IDX = verify_idx; let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(sni_idx >= 0); SNI_IDX = sni_idx; }); } } Loading Loading @@ -309,6 +315,53 @@ extern fn raw_verify_with_data<T>(preverify_ok: c_int, } } extern fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); let callback: Option<ServerNameCallback> = mem::transmute(callback); let mut s = Ssl { ssl: ssl }; let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, Some(callback) => callback(&mut s, ad) }; // Allows dropping the Ssl instance without calling SSL_FREE on the SSL object mem::forget(s); res } } extern fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int where T: Any + 'static { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); let callback: Option<ServerNameCallbackData<T>> = mem::transmute(callback); let mut s = Ssl { ssl: ssl }; let data: &T = mem::transmute(arg); let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, Some(callback) => callback(&mut s, ad, &*data) }; // Allows dropping the Ssl instance without calling SSL_FREE on the SSL object mem::forget(s); // Since data might be required on the next verification // it is time to forget about it and avoid dropping // data will be freed once OpenSSL considers it is time // to free all context data res } } #[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, Loading Loading @@ -416,6 +469,11 @@ pub type VerifyCallbackData<T> = fn(preverify_ok: bool, x509_ctx: &X509StoreContext, data: &T) -> bool; /// The signature of functions that can be used to choose the context depending on the server name pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; pub type ServerNameCallbackData<T> = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) -> i32; // FIXME: macro may be instead of inlining? #[inline] fn wrap_ssl_result(res: c_int) -> Result<(),SslError> { Loading Loading @@ -497,6 +555,35 @@ impl SslContext { } } /// Configures the server name indication (SNI) callback for new connections /// /// obtain the server name with `get_servername` then set the corresponding context /// with `set_ssl_context` pub fn set_servername_callback(&mut self, callback: Option<ServerNameCallback>) { unsafe { ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback)); let f: extern fn() = mem::transmute(raw_sni); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } /// Configures the server name indication (SNI) callback for new connections /// carrying supplied data pub fn set_servername_callback_with_data<T>(&mut self, callback: ServerNameCallbackData<T>, data: T) where T: Any + 'static { let data = Box::new(data); unsafe { ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback))); ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data)); let f: extern fn() = mem::transmute(raw_sni_with_data::<T>); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } /// Sets verification depth pub fn set_verify_depth(&mut self, depth: u32) { unsafe { Loading Loading @@ -685,6 +772,7 @@ impl SslContext { ffi::SSL_CTX_set_alpn_select_cb(self.ctx, raw_alpn_select_cb, ptr::null_mut()); } } } pub struct Ssl { Loading Loading @@ -874,6 +962,30 @@ impl Ssl { SslMethod::from_raw(method) } } /// Returns the server's name for the current connection pub fn get_servername(&self) -> Option<String> { let name = unsafe { ffi::SSL_get_servername(self.ssl, ffi::TLSEXT_NAMETYPE_host_name) }; if name == ptr::null() { return None; } unsafe { String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()).ok() } } /// change the context corresponding to the current connection pub fn set_ssl_context(&self, ctx: &SslContext) -> SslContext { SslContext { ctx: unsafe { ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx) } } } /// obtain the context corresponding to the current connection pub fn get_ssl_context(&self) -> SslContext { let ssl_ctx = unsafe { ffi::SSL_get_SSL_CTX(self.ssl) }; let count = unsafe { ffi_extras::SSL_CTX_increment_refcount(ssl_ctx) }; SslContext { ctx: ssl_ctx } } } macro_rules! make_LibSslError { Loading Loading
openssl-sys-extras/src/lib.rs +7 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ extern crate openssl_sys; extern crate libc; use libc::{c_int, c_uint, c_long, c_char}; use libc::{c_int, c_uint, c_long, c_char, c_void}; use openssl_sys::{HMAC_CTX, EVP_MD, ENGINE, SSL_CTX, BIO, X509, stack_st_X509_EXTENSION, SSL, DH}; macro_rules! import_options { Loading Loading @@ -73,4 +73,10 @@ extern { pub fn SSL_CTX_set_tmp_dh(s: *mut SSL, dh: *const DH) -> c_long; #[link_name = "X509_get_extensions_shim"] pub fn X509_get_extensions(x: *mut X509) -> *mut stack_st_X509_EXTENSION; #[link_name = "SSL_CTX_set_tlsext_servername_callback_shim"] pub fn SSL_CTX_set_tlsext_servername_callback(ssl: *mut SSL_CTX, callback: Option<extern fn()>); #[link_name = "SSL_CTX_set_tlsext_servername_arg_shim"] pub fn SSL_CTX_set_tlsext_servername_arg(ssl: *mut SSL_CTX, arg: *const c_void); #[link_name = "SSL_CTX_increment_refcount_shim"] pub fn SSL_CTX_increment_refcount(ssl: *mut SSL_CTX) -> c_long; }
openssl-sys-extras/src/openssl_shim.c +13 −0 Original line number Diff line number Diff line Loading @@ -131,6 +131,19 @@ long SSL_CTX_set_tmp_dh_shim(SSL_CTX *ctx, DH *dh) { return SSL_CTX_set_tmp_dh(ctx, dh); } long SSL_CTX_set_tlsext_servername_callback_shim(SSL_CTX *ctx, int (*callback)(SSL_CTX *, int *, void*)) { return SSL_CTX_set_tlsext_servername_callback(ctx, callback); } long SSL_CTX_set_tlsext_servername_arg_shim(SSL_CTX *ctx, void* arg) { return SSL_CTX_set_tlsext_servername_arg(ctx, arg); } long SSL_CTX_increment_refcount_shim(SSL_CTX *ctx) { int i = CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX); return i; } #if OPENSSL_VERSION_NUMBER >= 0x10002000L int SSL_CTX_set_ecdh_auto_shim(SSL_CTX *ctx, int onoff) { return SSL_CTX_set_ecdh_auto(ctx, onoff); Loading
openssl-sys/src/lib.rs +5 −1 Original line number Diff line number Diff line Loading @@ -194,6 +194,8 @@ pub const PKCS5_SALT_LEN: 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_TLSEXT_SERVERNAME_CB: c_int = 53; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: c_int = 54; pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; Loading Loading @@ -591,12 +593,15 @@ extern "C" { pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int; pub fn SSL_get_ex_data_X509_STORE_CTX_idx() -> c_int; pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX; pub fn SSL_set_SSL_CTX(ssl: *mut SSL, ctx: *mut SSL_CTX) -> *mut SSL_CTX; pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char; pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char; pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char; pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; Loading Loading @@ -625,7 +630,6 @@ extern "C" { pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int; pub fn SSL_CTX_ctrl(ssl: *mut SSL_CTX, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; #[cfg(feature = "npn")] pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX, cb: extern "C" fn(ssl: *mut SSL, Loading
openssl/src/ssl/mod.rs +112 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ extern "C" { } static mut VERIFY_IDX: c_int = -1; static mut SNI_IDX: c_int = -1; /// Manually initialize SSL. /// It is optional to call this function and safe to do so more than once. Loading @@ -58,6 +59,11 @@ pub fn init() { None, None); assert!(verify_idx >= 0); VERIFY_IDX = verify_idx; let sni_idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, None); assert!(sni_idx >= 0); SNI_IDX = sni_idx; }); } } Loading Loading @@ -309,6 +315,53 @@ extern fn raw_verify_with_data<T>(preverify_ok: c_int, } } extern fn raw_sni(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); let callback: Option<ServerNameCallback> = mem::transmute(callback); let mut s = Ssl { ssl: ssl }; let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, Some(callback) => callback(&mut s, ad) }; // Allows dropping the Ssl instance without calling SSL_FREE on the SSL object mem::forget(s); res } } extern fn raw_sni_with_data<T>(ssl: *mut ffi::SSL, ad: &mut c_int, arg: *mut c_void) -> c_int where T: Any + 'static { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, SNI_IDX); let callback: Option<ServerNameCallbackData<T>> = mem::transmute(callback); let mut s = Ssl { ssl: ssl }; let data: &T = mem::transmute(arg); let res = match callback { None => ffi::SSL_TLSEXT_ERR_ALERT_FATAL, Some(callback) => callback(&mut s, ad, &*data) }; // Allows dropping the Ssl instance without calling SSL_FREE on the SSL object mem::forget(s); // Since data might be required on the next verification // it is time to forget about it and avoid dropping // data will be freed once OpenSSL considers it is time // to free all context data res } } #[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, Loading Loading @@ -416,6 +469,11 @@ pub type VerifyCallbackData<T> = fn(preverify_ok: bool, x509_ctx: &X509StoreContext, data: &T) -> bool; /// The signature of functions that can be used to choose the context depending on the server name pub type ServerNameCallback = fn(ssl: &mut Ssl, ad: &mut i32) -> i32; pub type ServerNameCallbackData<T> = fn(ssl: &mut Ssl, ad: &mut i32, data: &T) -> i32; // FIXME: macro may be instead of inlining? #[inline] fn wrap_ssl_result(res: c_int) -> Result<(),SslError> { Loading Loading @@ -497,6 +555,35 @@ impl SslContext { } } /// Configures the server name indication (SNI) callback for new connections /// /// obtain the server name with `get_servername` then set the corresponding context /// with `set_ssl_context` pub fn set_servername_callback(&mut self, callback: Option<ServerNameCallback>) { unsafe { ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(callback)); let f: extern fn() = mem::transmute(raw_sni); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } /// Configures the server name indication (SNI) callback for new connections /// carrying supplied data pub fn set_servername_callback_with_data<T>(&mut self, callback: ServerNameCallbackData<T>, data: T) where T: Any + 'static { let data = Box::new(data); unsafe { ffi::SSL_CTX_set_ex_data(self.ctx, SNI_IDX, mem::transmute(Some(callback))); ffi_extras::SSL_CTX_set_tlsext_servername_arg(self.ctx, mem::transmute(data)); let f: extern fn() = mem::transmute(raw_sni_with_data::<T>); ffi_extras::SSL_CTX_set_tlsext_servername_callback(self.ctx, Some(f)); } } /// Sets verification depth pub fn set_verify_depth(&mut self, depth: u32) { unsafe { Loading Loading @@ -685,6 +772,7 @@ impl SslContext { ffi::SSL_CTX_set_alpn_select_cb(self.ctx, raw_alpn_select_cb, ptr::null_mut()); } } } pub struct Ssl { Loading Loading @@ -874,6 +962,30 @@ impl Ssl { SslMethod::from_raw(method) } } /// Returns the server's name for the current connection pub fn get_servername(&self) -> Option<String> { let name = unsafe { ffi::SSL_get_servername(self.ssl, ffi::TLSEXT_NAMETYPE_host_name) }; if name == ptr::null() { return None; } unsafe { String::from_utf8(CStr::from_ptr(name).to_bytes().to_vec()).ok() } } /// change the context corresponding to the current connection pub fn set_ssl_context(&self, ctx: &SslContext) -> SslContext { SslContext { ctx: unsafe { ffi::SSL_set_SSL_CTX(self.ssl, ctx.ctx) } } } /// obtain the context corresponding to the current connection pub fn get_ssl_context(&self) -> SslContext { let ssl_ctx = unsafe { ffi::SSL_get_SSL_CTX(self.ssl) }; let count = unsafe { ffi_extras::SSL_CTX_increment_refcount(ssl_ctx) }; SslContext { ctx: ssl_ctx } } } macro_rules! make_LibSslError { Loading