diff options
| author | Steven Fackler <[email protected]> | 2016-04-29 21:15:32 -0700 |
|---|---|---|
| committer | Steven Fackler <[email protected]> | 2016-04-29 21:15:32 -0700 |
| commit | 32722e18501b06fbd51a8871f8bea0cddb4b132c (patch) | |
| tree | a80964967a6aa180eabb05fc7ac8058476592fe9 /openssl/src | |
| parent | Start on GeneralName (diff) | |
| download | rust-openssl-32722e18501b06fbd51a8871f8bea0cddb4b132c.tar.xz rust-openssl-32722e18501b06fbd51a8871f8bea0cddb4b132c.zip | |
Add accessors for x509 subject alt names
Diffstat (limited to 'openssl/src')
| -rw-r--r-- | openssl/src/x509/extension.rs | 38 | ||||
| -rw-r--r-- | openssl/src/x509/mod.rs | 79 | ||||
| -rw-r--r-- | openssl/src/x509/tests.rs | 12 |
3 files changed, 89 insertions, 40 deletions
diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index c0b3bad4..7ff0c1ca 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,8 +1,4 @@ use std::fmt; -use std::marker::PhantomData; -use std::slice; -use std::str; -use ffi; use nid::Nid; @@ -223,37 +219,3 @@ impl fmt::Display for AltNameOption { }) } } - -pub struct GeneralName<'a> { - name: *const ffi::GENERAL_NAME, - m: PhantomData<&'a ()>, -} - -impl<'a> GeneralName<'a> { - pub fn dns(&self) -> Option<&str> { - unsafe { - if (*self.name).type_ != ffi::GEN_DNS { - return None; - } - - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); - - let slice = slice::from_raw_parts(ptr as *const u8, len as usize); - Some(str::from_utf8_unchecked(slice)) - } - } - - pub fn ipadd(&self) -> Option<&[u8]> { - unsafe { - if (*self.name).type_ != ffi::GEN_IPADD { - return None; - } - - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); - - Some(slice::from_raw_parts(ptr as *const u8, len as usize)) - } - } -} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index cb2c7494..cdd729aa 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -11,6 +11,7 @@ use std::fmt; use std::str; use std::slice; use std::collections::HashMap; +use std::marker::PhantomData; use asn1::Asn1Time; use bio::MemBio; @@ -21,7 +22,7 @@ use crypto::rand::rand_bytes; use ffi; use ffi_extras; use ssl::error::{SslError, StreamError}; -use nid; +use nid::Nid; pub mod extension; @@ -464,6 +465,23 @@ impl<'ctx> X509<'ctx> { } } + pub fn subject_alt_names<'a>(&'a self) -> Option<GeneralNames<'a>> { + unsafe { + let stack = ffi::X509_get_ext_d2i(self.handle, + Nid::SubjectAltName as c_int, + ptr::null_mut(), + ptr::null_mut()); + if stack.is_null() { + return None; + } + + Some(GeneralNames { + stack: stack as *const _, + m: PhantomData, + }) + } + } + pub fn public_key(&self) -> PKey { let pkey = unsafe { ffi::X509_get_pubkey(self.handle) }; assert!(!pkey.is_null()); @@ -544,7 +562,7 @@ pub struct X509NameEntry<'x> { } impl<'x> X509Name<'x> { - pub fn text_by_nid(&self, nid: nid::Nid) -> Option<SslString> { + pub fn text_by_nid(&self, nid: Nid) -> Option<SslString> { unsafe { let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1); if loc == -1 { @@ -766,6 +784,63 @@ make_validation_error!(X509_V_OK, X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION, ); +pub struct GeneralNames<'a> { + stack: *const ffi::stack_st_GENERAL_NAME, + m: PhantomData<&'a ()>, +} + +impl<'a> GeneralNames<'a> { + pub fn len(&self) -> usize { + unsafe { + (*self.stack).stack.num as usize + } + } + + pub fn get(&self, idx: usize) -> GeneralName<'a> { + unsafe { + assert!(idx < self.len()); + + GeneralName { + name: *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME, + m: PhantomData, + } + } + } +} + +pub struct GeneralName<'a> { + name: *const ffi::GENERAL_NAME, + m: PhantomData<&'a ()>, +} + +impl<'a> GeneralName<'a> { + pub fn dns(&self) -> Option<&str> { + unsafe { + if (*self.name).type_ != ffi::GEN_DNS { + return None; + } + + let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); + let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); + + let slice = slice::from_raw_parts(ptr as *const u8, len as usize); + Some(str::from_utf8_unchecked(slice)) + } + } + + pub fn ipadd(&self) -> Option<&[u8]> { + unsafe { + if (*self.name).type_ != ffi::GEN_IPADD { + return None; + } + + let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); + let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); + + Some(slice::from_raw_parts(ptr as *const u8, len as usize)) + } + } +} #[test] fn test_negative_serial() { diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 69ad37f8..5f4d432e 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -157,3 +157,15 @@ fn test_nid_uid_value() { }; assert_eq!(&cn as &str, "this is the userId"); } + +#[test] +fn test_subject_alt_name() { + let mut file = File::open("test/alt_name_cert.pem").unwrap(); + let cert = X509::from_pem(&mut file).unwrap(); + + 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).dns()); + assert_eq!(subject_alt_names.get(1).ipadd(), Some(&[127, 0, 0, 1][..])); + assert_eq!(subject_alt_names.get(2).ipadd(), Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); +} |