diff options
| author | Jonas Schievink <[email protected]> | 2016-06-14 18:12:50 +0200 |
|---|---|---|
| committer | Jonas Schievink <[email protected]> | 2016-06-26 18:25:54 +0200 |
| commit | 8119f06ca5ca50a677cf584cbe816500153ce783 (patch) | |
| tree | ca938d83276b8f8a34553068ab988050bd8ee4a6 /openssl/src | |
| parent | Try to propagate callback panics (diff) | |
| download | rust-openssl-8119f06ca5ca50a677cf584cbe816500153ce783.tar.xz rust-openssl-8119f06ca5ca50a677cf584cbe816500153ce783.zip | |
Move into utility module
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/crypto/mod.rs | 1 | ||||
| -rw-r--r-- | openssl/src/crypto/pkey.rs | 43 | ||||
| -rw-r--r-- | openssl/src/crypto/util.rs | 58 |
3 files changed, 63 insertions, 39 deletions
diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs index 95b27022..9d79b8b0 100644 --- a/openssl/src/crypto/mod.rs +++ b/openssl/src/crypto/mod.rs @@ -24,6 +24,7 @@ pub mod rand; pub mod symm; pub mod memcmp; pub mod rsa; +mod util; mod symm_internal; diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs index 8ae9aa20..605aed42 100644 --- a/openssl/src/crypto/pkey.rs +++ b/openssl/src/crypto/pkey.rs @@ -1,12 +1,9 @@ -use libc::{c_int, c_uint, c_ulong, c_char, c_void}; -use std::any::Any; +use libc::{c_int, c_uint, c_ulong, c_void}; use std::io; use std::io::prelude::*; use std::iter::repeat; use std::mem; -use std::panic; use std::ptr; -use std::slice; use bio::MemBio; use crypto::HashTypeInternals; @@ -15,6 +12,7 @@ use crypto::hash::Type as HashType; use ffi; use ssl::error::{SslError, StreamError}; use crypto::rsa::RSA; +use crypto::util::{CallbackState, invoke_passwd_cb}; #[derive(Copy, Clone)] pub enum Parts { @@ -104,36 +102,7 @@ impl PKey { pub fn private_key_from_pem_cb<R, F>(reader: &mut R, pass_cb: F) -> Result<PKey, SslError> where R: Read, F: FnMut(&mut [i8]) -> usize { - struct CallbackState<F: FnMut(&mut [i8]) -> usize> { - cb: F, - panic: Option<Box<Any + Send + 'static>>, - } - - extern "C" fn user_cb_wrapper<F>(buf: *mut c_char, - size: c_int, - _rwflag: c_int, - user_cb: *mut c_void) - -> c_int - where F: FnMut(&mut [i8]) -> usize { - let result = panic::catch_unwind(|| { - // build a `i8` slice to pass to the user callback - let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; - let callback = unsafe { &mut *(user_cb as *mut CallbackState<F>) }; - - (callback.cb)(pass_slice) - }); - - if let Ok(len) = result { - return len as c_int; - } else { - return 0; - } - } - - let mut cb = CallbackState { - cb: pass_cb, - panic: None, - }; + let mut cb = CallbackState::new(pass_cb); let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); @@ -141,13 +110,9 @@ impl PKey { unsafe { let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.get_handle(), ptr::null_mut(), - Some(user_cb_wrapper::<F>), + Some(invoke_passwd_cb::<F>), &mut cb as *mut _ as *mut c_void)); - if let Some(panic) = cb.panic { - panic::resume_unwind(panic); - } - Ok(PKey { evp: evp as *mut ffi::EVP_PKEY, parts: Parts::Both, diff --git a/openssl/src/crypto/util.rs b/openssl/src/crypto/util.rs new file mode 100644 index 00000000..85df86b7 --- /dev/null +++ b/openssl/src/crypto/util.rs @@ -0,0 +1,58 @@ +use libc::{c_int, c_char, c_void}; + +use std::any::Any; +use std::panic; +use std::slice; + +/// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI +/// frames are on the stack). +/// +/// When dropped, checks if the callback has panicked, and resumes unwinding if so. +pub struct CallbackState<F> { + /// The user callback. Taken out of the `Option` when called. + cb: Option<F>, + /// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL + /// returns. + panic: Option<Box<Any + Send + 'static>>, +} + +impl<F> CallbackState<F> { + pub fn new(callback: F) -> Self { + CallbackState { + cb: Some(callback), + panic: None, + } + } +} + +impl<F> Drop for CallbackState<F> { + fn drop(&mut self) { + if let Some(panic) = self.panic.take() { + panic::resume_unwind(panic); + } + } +} + +/// Password callback function, passed to private key loading functions. +/// +/// `cb_state` is expected to be a pointer to a `CallbackState`. +pub extern "C" fn invoke_passwd_cb<F>(buf: *mut c_char, + size: c_int, + _rwflag: c_int, + cb_state: *mut c_void) + -> c_int + where F: FnMut(&mut [i8]) -> usize { + let result = panic::catch_unwind(|| { + // build a `i8` slice to pass to the user callback + let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; + let callback = unsafe { &mut *(cb_state as *mut CallbackState<F>) }; + + callback.cb.take().unwrap()(pass_slice) + }); + + if let Ok(len) = result { + return len as c_int; + } else { + return 0; + } +} |