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/x509/mod.rs +16 −129 Original line number Diff line number Diff line use libc::{c_char, c_int, c_long, c_ulong, c_void}; use libc::{c_char, c_int, c_long, c_ulong}; use std::borrow::Borrow; use std::cmp; use std::collections::HashMap; use std::error::Error; use std::ffi::{CStr, CString}; use std::fmt; use std::marker::PhantomData; use std::mem; use std::ptr; use std::slice; Loading @@ -21,6 +20,7 @@ use error::ErrorStack; use ffi; use nid::Nid; use types::{OpenSslType, Ref}; use stack::{Stack, Stackable}; #[cfg(ossl10x)] use ffi::{X509_set_notBefore, X509_set_notAfter, ASN1_STRING_data}; Loading Loading @@ -346,7 +346,7 @@ impl Ref<X509> { } /// Returns this certificate's SAN entries, if they exist. pub fn subject_alt_names(&self) -> Option<GeneralNames> { pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> { unsafe { let stack = ffi::X509_get_ext_d2i(self.as_ptr(), ffi::NID_subject_alt_name, Loading @@ -356,7 +356,7 @@ impl Ref<X509> { return None; } Some(GeneralNames { stack: stack as *mut _ }) Some(Stack::from_ptr(stack as *mut _)) } } Loading Loading @@ -678,135 +678,18 @@ impl X509VerifyError { } } /// A collection of OpenSSL `GENERAL_NAME`s. pub struct GeneralNames { stack: *mut ffi::stack_st_GENERAL_NAME, } impl Drop for GeneralNames { #[cfg(ossl10x)] fn drop(&mut self) { unsafe { // This transmute is dubious but it's what openssl itself does... let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free); ffi::sk_pop_free(&mut (*self.stack).stack, Some(free)); } } #[cfg(ossl110)] fn drop(&mut self) { unsafe { // This transmute is dubious but it's what openssl itself does... let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free); ffi::OPENSSL_sk_pop_free(self.stack as *mut _, Some(free)); } } } impl GeneralNames { /// Returns the number of `GeneralName`s in this structure. pub fn len(&self) -> usize { self._len() } #[cfg(ossl10x)] fn _len(&self) -> usize { unsafe { (*self.stack).stack.num as usize } } #[cfg(ossl110)] fn _len(&self) -> usize { unsafe { ffi::OPENSSL_sk_num(self.stack as *const _) as usize } } /// Returns the specified `GeneralName`. /// /// # Panics /// /// Panics if `idx` is not less than `len()`. pub fn get<'a>(&'a self, idx: usize) -> GeneralName<'a> { unsafe { assert!(idx < self.len()); GeneralName { name: self._get(idx), m: PhantomData, } } } #[cfg(ossl10x)] unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME } #[cfg(ossl110)] unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { ffi::OPENSSL_sk_value(self.stack as *const _, idx as c_int) as *mut _ } /// Returns an iterator over the `GeneralName`s in this structure. pub fn iter(&self) -> GeneralNamesIter { GeneralNamesIter { names: self, idx: 0, } } } impl<'a> IntoIterator for &'a GeneralNames { type Item = GeneralName<'a>; type IntoIter = GeneralNamesIter<'a>; fn into_iter(self) -> GeneralNamesIter<'a> { self.iter() } } /// An iterator over OpenSSL `GENERAL_NAME`s. pub struct GeneralNamesIter<'a> { names: &'a GeneralNames, idx: usize, } impl<'a> Iterator for GeneralNamesIter<'a> { type Item = GeneralName<'a>; type_!(GeneralName, ffi::GENERAL_NAME, ffi::GENERAL_NAME_free); fn next(&mut self) -> Option<Self::Item> { if self.idx < self.names.len() { let name = self.names.get(self.idx); self.idx += 1; Some(name) } else { None } } fn size_hint(&self) -> (usize, Option<usize>) { let size = self.names.len() - self.idx; (size, Some(size)) } } impl<'a> ExactSizeIterator for GeneralNamesIter<'a> {} /// An OpenSSL `GENERAL_NAME`. pub struct GeneralName<'a> { name: *const ffi::GENERAL_NAME, m: PhantomData<&'a ()>, } impl<'a> GeneralName<'a> { impl Ref<GeneralName> { /// Returns the contents of this `GeneralName` if it is a `dNSName`. pub fn dnsname(&self) -> Option<&str> { unsafe { if (*self.name).type_ != ffi::GEN_DNS { if (*self.as_ptr()).type_ != ffi::GEN_DNS { return None; } let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); let slice = slice::from_raw_parts(ptr as *const u8, len as usize); // dNSNames are stated to be ASCII (specifically IA5). Hopefully Loading @@ -819,18 +702,22 @@ impl<'a> GeneralName<'a> { /// Returns the contents of this `GeneralName` if it is an `iPAddress`. pub fn ipaddress(&self) -> Option<&[u8]> { unsafe { if (*self.name).type_ != ffi::GEN_IPADD { if (*self.as_ptr()).type_ != ffi::GEN_IPADD { return None; } let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); Some(slice::from_raw_parts(ptr as *const u8, len as usize)) } } } impl Stackable for GeneralName { type StackType = ffi::stack_st_GENERAL_NAME; } #[test] fn test_negative_serial() { // I guess that's enough to get a random negative number Loading openssl/src/x509/tests.rs +3 −3 Original line number Diff line number Diff line Loading @@ -152,10 +152,10 @@ fn test_subject_alt_name() { let subject_alt_names = cert.subject_alt_names().unwrap(); assert_eq!(3, subject_alt_names.len()); assert_eq!(Some("foobar.com"), subject_alt_names.get(0).dnsname()); assert_eq!(subject_alt_names.get(1).ipaddress(), assert_eq!(Some("foobar.com"), subject_alt_names[0].dnsname()); assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..])); assert_eq!(subject_alt_names.get(2).ipaddress(), assert_eq!(subject_alt_names[2].ipaddress(), Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); } Loading 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/x509/mod.rs +16 −129 Original line number Diff line number Diff line use libc::{c_char, c_int, c_long, c_ulong, c_void}; use libc::{c_char, c_int, c_long, c_ulong}; use std::borrow::Borrow; use std::cmp; use std::collections::HashMap; use std::error::Error; use std::ffi::{CStr, CString}; use std::fmt; use std::marker::PhantomData; use std::mem; use std::ptr; use std::slice; Loading @@ -21,6 +20,7 @@ use error::ErrorStack; use ffi; use nid::Nid; use types::{OpenSslType, Ref}; use stack::{Stack, Stackable}; #[cfg(ossl10x)] use ffi::{X509_set_notBefore, X509_set_notAfter, ASN1_STRING_data}; Loading Loading @@ -346,7 +346,7 @@ impl Ref<X509> { } /// Returns this certificate's SAN entries, if they exist. pub fn subject_alt_names(&self) -> Option<GeneralNames> { pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> { unsafe { let stack = ffi::X509_get_ext_d2i(self.as_ptr(), ffi::NID_subject_alt_name, Loading @@ -356,7 +356,7 @@ impl Ref<X509> { return None; } Some(GeneralNames { stack: stack as *mut _ }) Some(Stack::from_ptr(stack as *mut _)) } } Loading Loading @@ -678,135 +678,18 @@ impl X509VerifyError { } } /// A collection of OpenSSL `GENERAL_NAME`s. pub struct GeneralNames { stack: *mut ffi::stack_st_GENERAL_NAME, } impl Drop for GeneralNames { #[cfg(ossl10x)] fn drop(&mut self) { unsafe { // This transmute is dubious but it's what openssl itself does... let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free); ffi::sk_pop_free(&mut (*self.stack).stack, Some(free)); } } #[cfg(ossl110)] fn drop(&mut self) { unsafe { // This transmute is dubious but it's what openssl itself does... let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free; let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free); ffi::OPENSSL_sk_pop_free(self.stack as *mut _, Some(free)); } } } impl GeneralNames { /// Returns the number of `GeneralName`s in this structure. pub fn len(&self) -> usize { self._len() } #[cfg(ossl10x)] fn _len(&self) -> usize { unsafe { (*self.stack).stack.num as usize } } #[cfg(ossl110)] fn _len(&self) -> usize { unsafe { ffi::OPENSSL_sk_num(self.stack as *const _) as usize } } /// Returns the specified `GeneralName`. /// /// # Panics /// /// Panics if `idx` is not less than `len()`. pub fn get<'a>(&'a self, idx: usize) -> GeneralName<'a> { unsafe { assert!(idx < self.len()); GeneralName { name: self._get(idx), m: PhantomData, } } } #[cfg(ossl10x)] unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME } #[cfg(ossl110)] unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME { ffi::OPENSSL_sk_value(self.stack as *const _, idx as c_int) as *mut _ } /// Returns an iterator over the `GeneralName`s in this structure. pub fn iter(&self) -> GeneralNamesIter { GeneralNamesIter { names: self, idx: 0, } } } impl<'a> IntoIterator for &'a GeneralNames { type Item = GeneralName<'a>; type IntoIter = GeneralNamesIter<'a>; fn into_iter(self) -> GeneralNamesIter<'a> { self.iter() } } /// An iterator over OpenSSL `GENERAL_NAME`s. pub struct GeneralNamesIter<'a> { names: &'a GeneralNames, idx: usize, } impl<'a> Iterator for GeneralNamesIter<'a> { type Item = GeneralName<'a>; type_!(GeneralName, ffi::GENERAL_NAME, ffi::GENERAL_NAME_free); fn next(&mut self) -> Option<Self::Item> { if self.idx < self.names.len() { let name = self.names.get(self.idx); self.idx += 1; Some(name) } else { None } } fn size_hint(&self) -> (usize, Option<usize>) { let size = self.names.len() - self.idx; (size, Some(size)) } } impl<'a> ExactSizeIterator for GeneralNamesIter<'a> {} /// An OpenSSL `GENERAL_NAME`. pub struct GeneralName<'a> { name: *const ffi::GENERAL_NAME, m: PhantomData<&'a ()>, } impl<'a> GeneralName<'a> { impl Ref<GeneralName> { /// Returns the contents of this `GeneralName` if it is a `dNSName`. pub fn dnsname(&self) -> Option<&str> { unsafe { if (*self.name).type_ != ffi::GEN_DNS { if (*self.as_ptr()).type_ != ffi::GEN_DNS { return None; } let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); let slice = slice::from_raw_parts(ptr as *const u8, len as usize); // dNSNames are stated to be ASCII (specifically IA5). Hopefully Loading @@ -819,18 +702,22 @@ impl<'a> GeneralName<'a> { /// Returns the contents of this `GeneralName` if it is an `iPAddress`. pub fn ipaddress(&self) -> Option<&[u8]> { unsafe { if (*self.name).type_ != ffi::GEN_IPADD { if (*self.as_ptr()).type_ != ffi::GEN_IPADD { return None; } let ptr = ASN1_STRING_data((*self.name).d as *mut _); let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); Some(slice::from_raw_parts(ptr as *const u8, len as usize)) } } } impl Stackable for GeneralName { type StackType = ffi::stack_st_GENERAL_NAME; } #[test] fn test_negative_serial() { // I guess that's enough to get a random negative number Loading
openssl/src/x509/tests.rs +3 −3 Original line number Diff line number Diff line Loading @@ -152,10 +152,10 @@ fn test_subject_alt_name() { let subject_alt_names = cert.subject_alt_names().unwrap(); assert_eq!(3, subject_alt_names.len()); assert_eq!(Some("foobar.com"), subject_alt_names.get(0).dnsname()); assert_eq!(subject_alt_names.get(1).ipaddress(), assert_eq!(Some("foobar.com"), subject_alt_names[0].dnsname()); assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..])); assert_eq!(subject_alt_names.get(2).ipaddress(), assert_eq!(subject_alt_names[2].ipaddress(), Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); } Loading