diff options
| author | Steven Fackler <[email protected]> | 2016-04-25 22:26:46 -0700 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2016-04-30 08:09:12 -0700 |
| commit | 62a7dd10e588d7636c7720af6786efaa7015246b (patch) | |
| tree | 2b145b003727999eeaf30696487e90703182ab6d /openssl/src/ssl/mod.rs | |
| parent | Cut out tests against beta (diff) | |
| download | rust-openssl-62a7dd10e588d7636c7720af6786efaa7015246b.tar.xz rust-openssl-62a7dd10e588d7636c7720af6786efaa7015246b.zip | |
Add Ssl::set_verify
It also uses a better, closure based API than the existing callback
methods.
Diffstat (limited to 'openssl/src/ssl/mod.rs')
| -rw-r--r-- | openssl/src/ssl/mod.rs | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 3610627a..b3c558c4 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -227,6 +227,7 @@ bitflags! { lazy_static! { static ref INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new()); + static ref SSL_INDEXES: Mutex<HashMap<TypeId, c_int>> = Mutex::new(HashMap::new()); } // Creates a static index for user data of type T @@ -236,6 +237,10 @@ fn get_verify_data_idx<T: Any + 'static>() -> c_int { *INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_idx::<T>()) } +fn get_ssl_verify_data_idx<T: Any + 'static>() -> c_int { + *SSL_INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_ssl_idx::<T>()) +} + #[cfg(feature = "npn")] lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>(); @@ -267,6 +272,26 @@ fn get_new_idx<T>() -> c_int { } } +fn get_new_ssl_idx<T>() -> c_int { + extern "C" fn free_data_box<T>(_parent: *mut c_void, + ptr: *mut c_void, + _ad: *mut ffi::CRYPTO_EX_DATA, + _idx: c_int, + _argl: c_long, + _argp: *mut c_void) { + if !ptr.is_null() { + let _: Box<T> = unsafe { mem::transmute(ptr) }; + } + } + + unsafe { + let f: ffi::CRYPTO_EX_free = free_data_box::<T>; + let idx = ffi::SSL_get_ex_new_index(0, ptr::null(), None, None, Some(f)); + assert!(idx >= 0); + idx + } +} + extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int { unsafe { let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); @@ -311,6 +336,21 @@ extern "C" fn raw_verify_with_data<T>(preverify_ok: c_int, } } +extern "C" fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send +{ + unsafe { + let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx(); + let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx); + let verify = ffi::SSL_get_ex_data(ssl, get_ssl_verify_data_idx::<F>()); + let verify: &F = mem::transmute(verify); + + let ctx = X509StoreContext::new(x509_ctx); + + verify(preverify_ok != 0, &ctx) as c_int + } +} + extern "C" 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); @@ -928,6 +968,23 @@ impl Ssl { } } + /// Sets the certificate verification callback to be used during the + /// handshake process. + /// + /// The callback is provided with a boolean indicating if the + /// preveification process was successful, and an object providing access + /// to the certificate chain. It should return `true` if the certificate + /// chain is valid and `false` otherwise. + pub fn set_verify<F>(&mut self, mode: SslVerifyMode, verify: F) + where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + { + unsafe { + let verify = Box::new(verify); + ffi::SSL_set_ex_data(self.ssl, get_ssl_verify_data_idx::<F>(), mem::transmute(verify)); + ffi::SSL_set_verify(self.ssl, mode.bits as c_int, Some(ssl_raw_verify::<F>)); + } + } + pub fn get_current_cipher<'a>(&'a self) -> Option<SslCipher<'a>> { unsafe { let ptr = ffi::SSL_get_current_cipher(self.ssl); |