Loading openssl-sys/src/ossl10x.rs +1 −0 Original line number Diff line number Diff line Loading @@ -583,6 +583,7 @@ extern { pub fn X509_get_ext_d2i(x: *mut ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void; pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY; pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING; pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int; pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar; pub fn CRYPTO_add_lock(pointer: *mut c_int, Loading openssl-sys/src/ossl110.rs +4 −4 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ pub enum HMAC_CTX {} pub enum OPENSSL_STACK {} pub enum RSA {} pub enum SSL_CTX {} pub enum _STACK {} pub enum stack_st_ASN1_OBJECT {} pub enum stack_st_GENERAL_NAME {} pub enum stack_st_OPENSSL_STRING {} Loading Loading @@ -142,12 +141,13 @@ extern { pub fn X509_up_ref(x: *mut X509) -> c_int; pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int; 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; pub fn EVP_MD_CTX_free(ctx: *mut EVP_MD_CTX); pub fn OpenSSL_version_num() -> c_ulong; pub fn OpenSSL_version(key: c_int) -> *const c_char; pub fn OPENSSL_sk_free(st: *mut _STACK); pub fn OPENSSL_sk_pop_free(st: *mut _STACK, free: Option<unsafe extern "C" fn (*mut c_void)>); pub fn OPENSSL_sk_pop(st: *mut _STACK) -> *mut c_void; pub fn OPENSSL_sk_free(st: *mut ::OPENSSL_STACK); pub fn OPENSSL_sk_pop_free(st: *mut ::OPENSSL_STACK, free: Option<unsafe extern "C" fn (*mut c_void)>); pub fn OPENSSL_sk_pop(st: *mut ::OPENSSL_STACK) -> *mut c_void; } openssl/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ pub mod ssl; pub mod symm; pub mod version; pub mod x509; pub mod stack; #[cfg(any(ossl102, ossl110))] mod verify; Loading openssl/src/ssl/connector.rs +6 −4 Original line number Diff line number Diff line Loading @@ -256,7 +256,8 @@ mod verify { use std::str; use nid; use x509::{X509StoreContext, X509, GeneralNames, X509Name}; use x509::{X509StoreContext, X509, X509Name, GeneralName}; use stack::Stack; use types::Ref; pub fn verify_callback(domain: &str, Loading @@ -275,15 +276,16 @@ mod verify { fn verify_hostname(domain: &str, cert: &Ref<X509>) -> bool { match cert.subject_alt_names() { Some(names) => verify_subject_alt_names(domain, &names), Some(names) => verify_subject_alt_names(domain, names), None => verify_subject_name(domain, &cert.subject_name()), } } fn verify_subject_alt_names(domain: &str, names: &GeneralNames) -> bool { fn verify_subject_alt_names(domain: &str, names: Stack<GeneralName>) -> bool { let ip = domain.parse(); for name in names { for name in &names { match ip { Ok(ip) => { if let Some(actual) = name.ipaddress() { Loading openssl/src/stack.rs 0 → 100644 +319 −0 Original line number Diff line number Diff line use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::iter; use std::borrow::Borrow; use std::convert::AsRef; #[cfg(ossl110)] use libc::c_int; use ffi; use types::{OpenSslType, Ref}; /// Trait implemented by stackable types. This must *only* be /// implemented on opaque types that can be directly casted into their /// `CType`. pub trait Stackable: OpenSslType { /// C stack type for this element. Generally called /// `stack_st_{ELEMENT_TYPE}`, normally hidden by the /// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API. type StackType; } /// An owned stack of `T`. pub struct Stack<T: Stackable>(*mut T::StackType); impl<T: Stackable> Stack<T> { /// Return a new Stack<T>, taking ownership of the handle pub unsafe fn from_ptr(stack: *mut T::StackType) -> Stack<T> { Stack(stack) } } impl<T: Stackable> Drop for Stack<T> { #[cfg(ossl10x)] fn drop(&mut self) { unsafe { loop { let ptr = ffi::sk_pop(self.as_stack()); if ptr.is_null() { break; } // Build the owned version of the object just to run // its `drop` implementation and delete the item. T::from_ptr(ptr as *mut _); } ffi::sk_free(self.0 as *mut _); } } #[cfg(ossl110)] fn drop(&mut self) { unsafe { loop { let ptr = ffi::OPENSSL_sk_pop(self.as_stack()); if ptr.is_null() { break; } // Build the owned version of the object just to run // its `drop` implementation and delete the item. T::from_ptr(ptr as *mut _); } ffi::OPENSSL_sk_free(self.0 as *mut _); } } } impl<T: Stackable> AsRef<Ref<Stack<T>>> for Stack<T> { fn as_ref(&self) -> &Ref<Stack<T>> { &*self } } impl<T: Stackable> Borrow<Ref<Stack<T>>> for Stack<T> { fn borrow(&self) -> &Ref<Stack<T>> { &*self } } unsafe impl<T: Stackable> OpenSslType for Stack<T> { type CType = T::StackType; unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> { Stack(ptr) } fn as_ptr(&self) -> *mut T::StackType { self.0 } } impl<T: Stackable> Deref for Stack<T> { type Target = Ref<Stack<T>>; fn deref(&self) -> &Ref<Stack<T>> { unsafe { Ref::from_ptr(self.0) } } } impl<T: Stackable> DerefMut for Stack<T> { fn deref_mut(&mut self) -> &mut ::types::Ref<Stack<T>> { unsafe { Ref::from_ptr_mut(self.0) } } } impl<T: Stackable> Ref<Stack<T>> { /// OpenSSL stack types are just a (kinda) typesafe wrapper around /// a `_STACK` object. We can therefore safely cast it and access /// the `_STACK` members without having to worry about the real /// layout of `T::StackType`. /// /// If that sounds unsafe then keep in mind that's exactly how the /// OpenSSL 1.1.0 new C stack code works. #[cfg(ossl10x)] fn as_stack(&self) -> *mut ffi::_STACK { self.as_ptr() as *mut _ } /// OpenSSL 1.1.0 replaced the stack macros with a functions and /// only exposes an opaque OPENSSL_STACK struct /// publicly. #[cfg(ossl110)] fn as_stack(&self) -> *mut ffi::OPENSSL_STACK { self.as_ptr() as *mut _ } /// Returns the number of items in the stack pub fn len(&self) -> usize { self._len() } #[cfg(ossl10x)] fn _len(&self) -> usize { unsafe { (*self.as_stack()).num as usize } } #[cfg(ossl110)] fn _len(&self) -> usize { unsafe { ffi::OPENSSL_sk_num(self.as_stack()) as usize } } pub fn iter(&self) -> Iter<T> { // Unfortunately we can't simply convert the stack into a // slice and use that because OpenSSL 1.1.0 doesn't directly // expose the stack data (we have to use `OPENSSL_sk_value` // instead). We have to rewrite the entire iteration framework // instead. Iter { stack: self, pos: 0, } } pub fn iter_mut(&mut self) -> IterMut<T> { IterMut { stack: self, pos: 0, } } /// Returns a reference to the element at the given index in the /// stack or `None` if the index is out of bounds pub fn get(&self, idx: usize) -> Option<&Ref<T>> { if idx >= self.len() { return None; } unsafe { let r = Ref::from_ptr(self._get(idx)); Some(r) } } /// Returns a mutable reference to the element at the given index in the /// stack or `None` if the index is out of bounds pub fn get_mut(&mut self, idx: usize) -> Option<&mut Ref<T>> { if idx >= self.len() { return None; } unsafe { Some(Ref::from_ptr_mut(self._get(idx))) } } #[cfg(ossl10x)] unsafe fn _get(&self, idx: usize) -> *mut T::CType { *(*self.as_stack()).data.offset(idx as isize) as *mut _ } #[cfg(ossl110)] unsafe fn _get(&self, idx: usize) -> *mut T::CType { ffi::OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _ } } impl<T: Stackable> Index<usize> for Ref<Stack<T>> { type Output = Ref<T>; fn index(&self, index: usize) -> &Ref<T> { self.get(index).unwrap() } } impl<T: Stackable> IndexMut<usize> for Ref<Stack<T>> { fn index_mut(&mut self, index: usize) -> &mut Ref<T> { self.get_mut(index).unwrap() } } impl<'a, T: Stackable> iter::IntoIterator for &'a Ref<Stack<T>> { type Item = &'a Ref<T>; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() } } impl<'a, T: Stackable> iter::IntoIterator for &'a mut Ref<Stack<T>> { type Item = &'a mut Ref<T>; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> { type Item = &'a Ref<T>; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() } } impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> { type Item = &'a mut Ref<T>; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } /// An iterator over the stack's contents. pub struct Iter<'a, T: Stackable> where T: 'a { stack: &'a Ref<Stack<T>>, pos: usize, } impl<'a, T: Stackable> iter::Iterator for Iter<'a, T> { type Item = &'a Ref<T>; fn next(&mut self) -> Option<&'a Ref<T>> { let n = self.stack.get(self.pos); if n.is_some() { self.pos += 1; } n } fn size_hint(&self) -> (usize, Option<usize>) { let rem = self.stack.len() - self.pos; (rem, Some(rem)) } } impl<'a, T: Stackable> iter::ExactSizeIterator for Iter<'a, T> { } /// A mutable iterator over the stack's contents. pub struct IterMut<'a, T: Stackable + 'a> { stack: &'a mut Ref<Stack<T>>, pos: usize, } impl<'a, T: Stackable> iter::Iterator for IterMut<'a, T> { type Item = &'a mut Ref<T>; fn next(&mut self) -> Option<&'a mut Ref<T>> { if self.pos >= self.stack.len() { None } else { // Rust won't allow us to get a mutable reference into // `stack` in this situation since it can't statically // guarantee that we won't return several references to // the same object, so we have to use unsafe code for // mutable iterators. let n = unsafe { Some(Ref::from_ptr_mut(self.stack._get(self.pos))) }; self.pos += 1; n } } fn size_hint(&self) -> (usize, Option<usize>) { let rem = self.stack.len() - self.pos; (rem, Some(rem)) } } impl<'a, T: Stackable> iter::ExactSizeIterator for IterMut<'a, T> { } Loading
openssl-sys/src/ossl10x.rs +1 −0 Original line number Diff line number Diff line Loading @@ -583,6 +583,7 @@ extern { pub fn X509_get_ext_d2i(x: *mut ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void; pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY; pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING; pub fn X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int; pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar; pub fn CRYPTO_add_lock(pointer: *mut c_int, Loading
openssl-sys/src/ossl110.rs +4 −4 Original line number Diff line number Diff line Loading @@ -13,7 +13,6 @@ pub enum HMAC_CTX {} pub enum OPENSSL_STACK {} pub enum RSA {} pub enum SSL_CTX {} pub enum _STACK {} pub enum stack_st_ASN1_OBJECT {} pub enum stack_st_GENERAL_NAME {} pub enum stack_st_OPENSSL_STRING {} Loading Loading @@ -142,12 +141,13 @@ extern { pub fn X509_up_ref(x: *mut X509) -> c_int; pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int; 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; pub fn EVP_MD_CTX_free(ctx: *mut EVP_MD_CTX); pub fn OpenSSL_version_num() -> c_ulong; pub fn OpenSSL_version(key: c_int) -> *const c_char; pub fn OPENSSL_sk_free(st: *mut _STACK); pub fn OPENSSL_sk_pop_free(st: *mut _STACK, free: Option<unsafe extern "C" fn (*mut c_void)>); pub fn OPENSSL_sk_pop(st: *mut _STACK) -> *mut c_void; pub fn OPENSSL_sk_free(st: *mut ::OPENSSL_STACK); pub fn OPENSSL_sk_pop_free(st: *mut ::OPENSSL_STACK, free: Option<unsafe extern "C" fn (*mut c_void)>); pub fn OPENSSL_sk_pop(st: *mut ::OPENSSL_STACK) -> *mut c_void; }
openssl/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -81,6 +81,7 @@ pub mod ssl; pub mod symm; pub mod version; pub mod x509; pub mod stack; #[cfg(any(ossl102, ossl110))] mod verify; Loading
openssl/src/ssl/connector.rs +6 −4 Original line number Diff line number Diff line Loading @@ -256,7 +256,8 @@ mod verify { use std::str; use nid; use x509::{X509StoreContext, X509, GeneralNames, X509Name}; use x509::{X509StoreContext, X509, X509Name, GeneralName}; use stack::Stack; use types::Ref; pub fn verify_callback(domain: &str, Loading @@ -275,15 +276,16 @@ mod verify { fn verify_hostname(domain: &str, cert: &Ref<X509>) -> bool { match cert.subject_alt_names() { Some(names) => verify_subject_alt_names(domain, &names), Some(names) => verify_subject_alt_names(domain, names), None => verify_subject_name(domain, &cert.subject_name()), } } fn verify_subject_alt_names(domain: &str, names: &GeneralNames) -> bool { fn verify_subject_alt_names(domain: &str, names: Stack<GeneralName>) -> bool { let ip = domain.parse(); for name in names { for name in &names { match ip { Ok(ip) => { if let Some(actual) = name.ipaddress() { Loading
openssl/src/stack.rs 0 → 100644 +319 −0 Original line number Diff line number Diff line use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::iter; use std::borrow::Borrow; use std::convert::AsRef; #[cfg(ossl110)] use libc::c_int; use ffi; use types::{OpenSslType, Ref}; /// Trait implemented by stackable types. This must *only* be /// implemented on opaque types that can be directly casted into their /// `CType`. pub trait Stackable: OpenSslType { /// C stack type for this element. Generally called /// `stack_st_{ELEMENT_TYPE}`, normally hidden by the /// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API. type StackType; } /// An owned stack of `T`. pub struct Stack<T: Stackable>(*mut T::StackType); impl<T: Stackable> Stack<T> { /// Return a new Stack<T>, taking ownership of the handle pub unsafe fn from_ptr(stack: *mut T::StackType) -> Stack<T> { Stack(stack) } } impl<T: Stackable> Drop for Stack<T> { #[cfg(ossl10x)] fn drop(&mut self) { unsafe { loop { let ptr = ffi::sk_pop(self.as_stack()); if ptr.is_null() { break; } // Build the owned version of the object just to run // its `drop` implementation and delete the item. T::from_ptr(ptr as *mut _); } ffi::sk_free(self.0 as *mut _); } } #[cfg(ossl110)] fn drop(&mut self) { unsafe { loop { let ptr = ffi::OPENSSL_sk_pop(self.as_stack()); if ptr.is_null() { break; } // Build the owned version of the object just to run // its `drop` implementation and delete the item. T::from_ptr(ptr as *mut _); } ffi::OPENSSL_sk_free(self.0 as *mut _); } } } impl<T: Stackable> AsRef<Ref<Stack<T>>> for Stack<T> { fn as_ref(&self) -> &Ref<Stack<T>> { &*self } } impl<T: Stackable> Borrow<Ref<Stack<T>>> for Stack<T> { fn borrow(&self) -> &Ref<Stack<T>> { &*self } } unsafe impl<T: Stackable> OpenSslType for Stack<T> { type CType = T::StackType; unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> { Stack(ptr) } fn as_ptr(&self) -> *mut T::StackType { self.0 } } impl<T: Stackable> Deref for Stack<T> { type Target = Ref<Stack<T>>; fn deref(&self) -> &Ref<Stack<T>> { unsafe { Ref::from_ptr(self.0) } } } impl<T: Stackable> DerefMut for Stack<T> { fn deref_mut(&mut self) -> &mut ::types::Ref<Stack<T>> { unsafe { Ref::from_ptr_mut(self.0) } } } impl<T: Stackable> Ref<Stack<T>> { /// OpenSSL stack types are just a (kinda) typesafe wrapper around /// a `_STACK` object. We can therefore safely cast it and access /// the `_STACK` members without having to worry about the real /// layout of `T::StackType`. /// /// If that sounds unsafe then keep in mind that's exactly how the /// OpenSSL 1.1.0 new C stack code works. #[cfg(ossl10x)] fn as_stack(&self) -> *mut ffi::_STACK { self.as_ptr() as *mut _ } /// OpenSSL 1.1.0 replaced the stack macros with a functions and /// only exposes an opaque OPENSSL_STACK struct /// publicly. #[cfg(ossl110)] fn as_stack(&self) -> *mut ffi::OPENSSL_STACK { self.as_ptr() as *mut _ } /// Returns the number of items in the stack pub fn len(&self) -> usize { self._len() } #[cfg(ossl10x)] fn _len(&self) -> usize { unsafe { (*self.as_stack()).num as usize } } #[cfg(ossl110)] fn _len(&self) -> usize { unsafe { ffi::OPENSSL_sk_num(self.as_stack()) as usize } } pub fn iter(&self) -> Iter<T> { // Unfortunately we can't simply convert the stack into a // slice and use that because OpenSSL 1.1.0 doesn't directly // expose the stack data (we have to use `OPENSSL_sk_value` // instead). We have to rewrite the entire iteration framework // instead. Iter { stack: self, pos: 0, } } pub fn iter_mut(&mut self) -> IterMut<T> { IterMut { stack: self, pos: 0, } } /// Returns a reference to the element at the given index in the /// stack or `None` if the index is out of bounds pub fn get(&self, idx: usize) -> Option<&Ref<T>> { if idx >= self.len() { return None; } unsafe { let r = Ref::from_ptr(self._get(idx)); Some(r) } } /// Returns a mutable reference to the element at the given index in the /// stack or `None` if the index is out of bounds pub fn get_mut(&mut self, idx: usize) -> Option<&mut Ref<T>> { if idx >= self.len() { return None; } unsafe { Some(Ref::from_ptr_mut(self._get(idx))) } } #[cfg(ossl10x)] unsafe fn _get(&self, idx: usize) -> *mut T::CType { *(*self.as_stack()).data.offset(idx as isize) as *mut _ } #[cfg(ossl110)] unsafe fn _get(&self, idx: usize) -> *mut T::CType { ffi::OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _ } } impl<T: Stackable> Index<usize> for Ref<Stack<T>> { type Output = Ref<T>; fn index(&self, index: usize) -> &Ref<T> { self.get(index).unwrap() } } impl<T: Stackable> IndexMut<usize> for Ref<Stack<T>> { fn index_mut(&mut self, index: usize) -> &mut Ref<T> { self.get_mut(index).unwrap() } } impl<'a, T: Stackable> iter::IntoIterator for &'a Ref<Stack<T>> { type Item = &'a Ref<T>; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() } } impl<'a, T: Stackable> iter::IntoIterator for &'a mut Ref<Stack<T>> { type Item = &'a mut Ref<T>; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } impl<'a, T: Stackable> iter::IntoIterator for &'a Stack<T> { type Item = &'a Ref<T>; type IntoIter = Iter<'a, T>; fn into_iter(self) -> Iter<'a, T> { self.iter() } } impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack<T> { type Item = &'a mut Ref<T>; type IntoIter = IterMut<'a, T>; fn into_iter(self) -> IterMut<'a, T> { self.iter_mut() } } /// An iterator over the stack's contents. pub struct Iter<'a, T: Stackable> where T: 'a { stack: &'a Ref<Stack<T>>, pos: usize, } impl<'a, T: Stackable> iter::Iterator for Iter<'a, T> { type Item = &'a Ref<T>; fn next(&mut self) -> Option<&'a Ref<T>> { let n = self.stack.get(self.pos); if n.is_some() { self.pos += 1; } n } fn size_hint(&self) -> (usize, Option<usize>) { let rem = self.stack.len() - self.pos; (rem, Some(rem)) } } impl<'a, T: Stackable> iter::ExactSizeIterator for Iter<'a, T> { } /// A mutable iterator over the stack's contents. pub struct IterMut<'a, T: Stackable + 'a> { stack: &'a mut Ref<Stack<T>>, pos: usize, } impl<'a, T: Stackable> iter::Iterator for IterMut<'a, T> { type Item = &'a mut Ref<T>; fn next(&mut self) -> Option<&'a mut Ref<T>> { if self.pos >= self.stack.len() { None } else { // Rust won't allow us to get a mutable reference into // `stack` in this situation since it can't statically // guarantee that we won't return several references to // the same object, so we have to use unsafe code for // mutable iterators. let n = unsafe { Some(Ref::from_ptr_mut(self.stack._get(self.pos))) }; self.pos += 1; n } } fn size_hint(&self) -> (usize, Option<usize>) { let rem = self.stack.len() - self.pos; (rem, Some(rem)) } } impl<'a, T: Stackable> iter::ExactSizeIterator for IterMut<'a, T> { }