From 2b1a9a7814293d50829a60d42f4e8f2ea0353bd7 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sun, 29 Mar 2015 10:18:30 -0700 Subject: [PATCH] Fix verify data free function Turns out this is called with a null pointer if you never set the data which didn't end up doing anything until the recent zeroing drop changes. Also use a map of indexes since statics in generic functions don't monomorphize --- openssl/Cargo.toml | 5 ++--- openssl/src/lib.rs | 9 +++++---- openssl/src/ssl/mod.rs | 38 ++++++++++++++++++++++---------------- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 6ba69781..8bfc8aca 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -21,10 +21,9 @@ path = "../openssl-sys" version = "0.5.2" [dependencies] +bitflags = "0.1.1" +lazy_static = "0.1" libc = "0.1" [dev-dependencies] rustc-serialize = "0.3" - -[dependencies] -bitflags = "0.1.1" diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 90749fd8..beafdd91 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,15 +1,16 @@ -#![feature(unsafe_destructor, core, io, std_misc, unique)] +#![feature(unsafe_destructor, core, io, std_misc, unique, collections)] #![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/openssl")] #[macro_use] extern crate bitflags; - extern crate libc; +#[macro_use] +extern crate lazy_static; +extern crate openssl_sys as ffi; + #[cfg(test)] extern crate rustc_serialize as serialize; -extern crate openssl_sys as ffi; - mod macros; pub mod asn1; diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 471bfc5a..5f50a33f 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1,4 +1,6 @@ use libc::{c_int, c_void, c_long}; +use std::any::TypeId; +use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::fmt; use std::io; @@ -10,9 +12,10 @@ use std::num::FromPrimitive; use std::num::Int; use std::path::Path; use std::ptr; -use std::sync::{Once, ONCE_INIT, Arc}; +use std::sync::{Once, ONCE_INIT, Arc, Mutex}; use std::ops::{Deref, DerefMut}; use std::cmp; +use std::marker::Reflect; #[cfg(feature = "npn")] use libc::{c_uchar, c_uint}; #[cfg(feature = "npn")] @@ -124,29 +127,30 @@ pub enum SslVerifyMode { SslVerifyNone = ffi::SSL_VERIFY_NONE } +lazy_static! { + static ref INDEXES: Mutex> = Mutex::new(HashMap::new()); +} + // Creates a static index for user data of type T // Registers a destructor for the data which will be called // when context is freed -fn get_verify_data_idx() -> c_int { - static mut VERIFY_DATA_IDX: c_int = -1; - static mut INIT: Once = ONCE_INIT; - +fn get_verify_data_idx() -> c_int { extern fn free_data_box(_parent: *mut c_void, ptr: *mut c_void, _ad: *mut ffi::CRYPTO_EX_DATA, _idx: c_int, _argl: c_long, _argp: *mut c_void) { - let _: Box = unsafe { mem::transmute(ptr) }; + if ptr != 0 as *mut _ { + let _: Box = unsafe { mem::transmute(ptr) }; + } } - unsafe { - INIT.call_once(|| { + *INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| { + unsafe { let f: ffi::CRYPTO_EX_free = free_data_box::; - let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, - None, Some(f)); + let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f)); assert!(idx >= 0); - VERIFY_DATA_IDX = idx; - }); - VERIFY_DATA_IDX - } + idx + } + }) } /// Creates a static index for the list of NPN protocols. @@ -196,7 +200,8 @@ extern fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) } extern fn raw_verify_with_data(preverify_ok: c_int, - x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { + x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int + where T: Reflect + 'static { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); @@ -352,7 +357,8 @@ impl SslContext { // a function handling it pub fn set_verify_with_data(&mut self, mode: SslVerifyMode, verify: VerifyCallbackData, - data: T) { + data: T) + where T: Reflect + 'static { let data = Box::new(data); unsafe { ffi::SSL_CTX_set_ex_data(*self.ctx, VERIFY_IDX,