diff options
Diffstat (limited to 'openssl/src/x509')
| -rw-r--r-- | openssl/src/x509/extension.rs | 42 | ||||
| -rw-r--r-- | openssl/src/x509/mod.rs | 186 | ||||
| -rw-r--r-- | openssl/src/x509/tests.rs | 38 |
3 files changed, 156 insertions, 110 deletions
diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 3faa0996..88cb64a2 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -26,9 +26,9 @@ pub enum Extension { /// The extended purposes of the key contained in the certificate ExtKeyUsage(Vec<ExtKeyUsageOption>), /// Subject Alternative Names - SubjectAltName(Vec<(AltNameOption,String)>), + SubjectAltName(Vec<(AltNameOption, String)>), /// Issuer Alternative Names - IssuerAltName(Vec<(AltNameOption,String)>), + IssuerAltName(Vec<(AltNameOption, String)>), /// Arbitrary extensions by NID. See `man x509v3_config` for value syntax. /// /// You must not use this to add extensions which this enum can express directly. @@ -40,7 +40,7 @@ pub enum Extension { /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); /// ``` - OtherNid(Nid,String), + OtherNid(Nid, String), /// Arbitrary extensions by OID string. See `man ASN1_generate_nconf` for value syntax. /// /// You must not use this to add extensions which this enum can express directly. @@ -51,7 +51,7 @@ pub enum Extension { /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())); /// ``` - OtherStr(String,String), + OtherStr(String, String), } impl Extension { @@ -61,8 +61,8 @@ impl Extension { &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, &Extension::IssuerAltName(_) => ExtensionType::IssuerAltName, - &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), - &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), + &Extension::OtherNid(nid, _) => ExtensionType::OtherNid(nid), + &Extension::OtherStr(ref s, _) => ExtensionType::OtherStr(s.clone()), } } } @@ -89,9 +89,11 @@ impl ExtensionType { // FIXME: This would be nicer as a method on Iterator<Item=ToString>. This can // eventually be replaced by the successor to std::slice::SliceConcatExt.connect -fn join<I: Iterator<Item=T>,T: ToString>(iter: I, sep: &str) -> String { +fn join<I: Iterator<Item = T>, T: ToString>(iter: I, sep: &str) -> String { iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { - if idx > 0 { acc.push_str(sep) }; + if idx > 0 { + acc.push_str(sep) + }; acc.push_str(&v.to_string()); acc }) @@ -100,12 +102,18 @@ fn join<I: Iterator<Item=T>,T: ToString>(iter: I, sep: &str) -> String { impl ToString for Extension { fn to_string(&self) -> String { match self { - &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), - &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), - &Extension::SubjectAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), - &Extension::IssuerAltName(ref names) => join(names.iter().map(|&(ref opt,ref val)|opt.to_string()+":"+&val),","), - &Extension::OtherNid(_,ref value) => value.clone(), - &Extension::OtherStr(_,ref value) => value.clone(), + &Extension::KeyUsage(ref purposes) => join(purposes.iter(), ","), + &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(), ","), + &Extension::SubjectAltName(ref names) => { + join(names.iter().map(|&(ref opt, ref val)| opt.to_string() + ":" + &val), + ",") + } + &Extension::IssuerAltName(ref names) => { + join(names.iter().map(|&(ref opt, ref val)| opt.to_string() + ":" + &val), + ",") + } + &Extension::OtherNid(_, ref value) => value.clone(), + &Extension::OtherStr(_, ref value) => value.clone(), } } } @@ -169,7 +177,7 @@ impl fmt::Display for ExtKeyUsageOption { &ExtKeyUsageOption::MsCtlSign => "msCTLSign", &ExtKeyUsageOption::MsSgc => "msSGC", &ExtKeyUsageOption::MsEfs => "msEFS", - &ExtKeyUsageOption::NsSgc =>"nsSGC", + &ExtKeyUsageOption::NsSgc => "nsSGC", &ExtKeyUsageOption::Other(ref s) => &s[..], }) } @@ -189,9 +197,9 @@ pub enum AltNameOption { Other, Email, DNS, - //X400, // Not supported by OpenSSL + // X400, // Not supported by OpenSSL Directory, - //EDIParty, // Not supported by OpenSSL + // EDIParty, // Not supported by OpenSSL URI, IPAddress, RegisteredID, diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index c7039089..ffd478ef 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -11,11 +11,11 @@ use std::fmt; use std::str; use std::collections::HashMap; -use asn1::{Asn1Time}; -use bio::{MemBio}; +use asn1::Asn1Time; +use bio::MemBio; use crypto::hash; use crypto::hash::Type as HashType; -use crypto::pkey::{PKey,Parts}; +use crypto::pkey::{PKey, Parts}; use crypto::rand::rand_bytes; use ffi; use ffi_extras; @@ -24,18 +24,20 @@ use nid; pub mod extension; -use self::extension::{ExtensionType,Extension}; +use self::extension::{ExtensionType, Extension}; #[cfg(test)] mod tests; pub struct SslString { - s : &'static str + s: &'static str, } impl<'s> Drop for SslString { fn drop(&mut self) { - unsafe { ffi::CRYPTO_free(self.s.as_ptr() as *mut c_void); } + unsafe { + ffi::CRYPTO_free(self.s.as_ptr() as *mut c_void); + } } } @@ -49,9 +51,7 @@ impl Deref for SslString { impl SslString { unsafe fn new(buf: *const c_char) -> SslString { - SslString { - s: str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap() - } + SslString { s: str::from_utf8(CStr::from_ptr(buf as *const _).to_bytes()).unwrap() } } } @@ -72,19 +72,17 @@ impl fmt::Debug for SslString { pub enum X509FileType { PEM = ffi::X509_FILETYPE_PEM, ASN1 = ffi::X509_FILETYPE_ASN1, - Default = ffi::X509_FILETYPE_DEFAULT + Default = ffi::X509_FILETYPE_DEFAULT, } #[allow(missing_copy_implementations)] pub struct X509StoreContext { - ctx: *mut ffi::X509_STORE_CTX + ctx: *mut ffi::X509_STORE_CTX, } impl X509StoreContext { pub fn new(ctx: *mut ffi::X509_STORE_CTX) -> X509StoreContext { - X509StoreContext { - ctx: ctx - } + X509StoreContext { ctx: ctx } } pub fn get_error(&self) -> Option<X509ValidationError> { @@ -98,7 +96,11 @@ impl X509StoreContext { if ptr.is_null() { None } else { - Some(X509 { ctx: Some(self), handle: ptr, owned: false }) + Some(X509 { + ctx: Some(self), + handle: ptr, + owned: false, + }) } } } @@ -143,9 +145,9 @@ impl X509StoreContext { pub struct X509Generator { bits: u32, days: u32, - names: Vec<(String,String)>, + names: Vec<(String, String)>, // RFC 3280 ยง4.2: A certificate MUST NOT include more than one instance of a particular extension. - extensions: HashMap<ExtensionType,Extension>, + extensions: HashMap<ExtensionType, Extension>, hash_type: HashType, } @@ -165,7 +167,7 @@ impl X509Generator { days: 365, names: vec![], extensions: HashMap::new(), - hash_type: HashType::SHA1 + hash_type: HashType::SHA1, } } @@ -188,7 +190,7 @@ impl X509Generator { /// generator.add_name("CN".to_string(),"example.com".to_string()); /// ``` pub fn add_name(mut self, attr_type: String, attr_value: String) -> X509Generator { - self.names.push((attr_type,attr_value)); + self.names.push((attr_type, attr_value)); self } @@ -199,7 +201,8 @@ impl X509Generator { /// generator.add_names(vec![("CN".to_string(),"example.com".to_string())]); /// ``` pub fn add_names<I>(mut self, attrs: I) -> X509Generator - where I: IntoIterator<Item=(String,String)> { + where I: IntoIterator<Item = (String, String)> + { self.names.extend(attrs); self } @@ -216,7 +219,7 @@ impl X509Generator { /// generator.add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])); /// ``` pub fn add_extension(mut self, ext: extension::Extension) -> X509Generator { - self.extensions.insert(ext.get_type(),ext); + self.extensions.insert(ext.get_type(), ext); self } @@ -232,8 +235,9 @@ impl X509Generator { /// generator.add_extensions(vec![KeyUsage(vec![DigitalSignature, KeyEncipherment])]); /// ``` pub fn add_extensions<I>(mut self, exts: I) -> X509Generator - where I: IntoIterator<Item=extension::Extension> { - self.extensions.extend(exts.into_iter().map(|ext|(ext.get_type(),ext))); + where I: IntoIterator<Item = extension::Extension> + { + self.extensions.extend(exts.into_iter().map(|ext| (ext.get_type(), ext))); self } @@ -242,23 +246,27 @@ impl X509Generator { self } - fn add_extension_internal(x509: *mut ffi::X509, exttype: &extension::ExtensionType, value: &str) -> Result<(), SslError> { + fn add_extension_internal(x509: *mut ffi::X509, + exttype: &extension::ExtensionType, + value: &str) + -> Result<(), SslError> { unsafe { let mut ctx: ffi::X509V3_CTX = mem::zeroed(); - ffi::X509V3_set_ctx(&mut ctx, x509, x509, - ptr::null_mut(), ptr::null_mut(), 0); + ffi::X509V3_set_ctx(&mut ctx, x509, x509, ptr::null_mut(), ptr::null_mut(), 0); let value = CString::new(value.as_bytes()).unwrap(); - let ext=match exttype.get_nid() { - Some(nid) => ffi::X509V3_EXT_conf_nid(ptr::null_mut(), - mem::transmute(&ctx), - nid as c_int, - value.as_ptr() as *mut c_char), + let ext = match exttype.get_nid() { + Some(nid) => { + ffi::X509V3_EXT_conf_nid(ptr::null_mut(), + mem::transmute(&ctx), + nid as c_int, + value.as_ptr() as *mut c_char) + } None => { - let name=CString::new(exttype.get_name().unwrap().as_bytes()).unwrap(); + let name = CString::new(exttype.get_name().unwrap().as_bytes()).unwrap(); ffi::X509V3_EXT_conf(ptr::null_mut(), - mem::transmute(&ctx), - name.as_ptr() as *mut c_char, - value.as_ptr() as *mut c_char) + mem::transmute(&ctx), + name.as_ptr() as *mut c_char, + value.as_ptr() as *mut c_char) } }; let mut success = false; @@ -270,13 +278,21 @@ impl X509Generator { } } - fn add_name_internal(name: *mut ffi::X509_NAME, key: &str, value: &str) -> Result<(), SslError> { + fn add_name_internal(name: *mut ffi::X509_NAME, + key: &str, + value: &str) + -> Result<(), SslError> { let value_len = value.len() as c_int; lift_ssl!(unsafe { let key = CString::new(key.as_bytes()).unwrap(); let value = CString::new(value.as_bytes()).unwrap(); - ffi::X509_NAME_add_entry_by_txt(name, key.as_ptr() as *const _, ffi::MBSTRING_UTF8, - value.as_ptr() as *const _, value_len, -1, 0) + ffi::X509_NAME_add_entry_by_txt(name, + key.as_ptr() as *const _, + ffi::MBSTRING_UTF8, + value.as_ptr() as *const _, + value_len, + -1, + 0) }) } @@ -315,10 +331,15 @@ impl X509Generator { let x509 = ffi::X509_new(); try_ssl_null!(x509); - let x509 = X509 { handle: x509, ctx: None, owned: true}; + let x509 = X509 { + handle: x509, + ctx: None, + owned: true, + }; try_ssl!(ffi::X509_set_version(x509.handle, 2)); - try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle), X509Generator::random_serial())); + try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.handle), + X509Generator::random_serial())); let not_before = try!(Asn1Time::days_from_now(0)); let not_after = try!(Asn1Time::days_from_now(self.days)); @@ -336,18 +357,21 @@ impl X509Generator { let name = ffi::X509_get_subject_name(x509.handle); try_ssl_null!(name); - let default=[("CN","rust-openssl")]; - let default_iter=&mut default.iter().map(|&(k,v)|(k,v)); - let arg_iter=&mut self.names.iter().map(|&(ref k,ref v)|(&k[..],&v[..])); - let iter: &mut Iterator<Item=(&str,&str)> = - if self.names.len()==0 { default_iter } else { arg_iter }; + let default = [("CN", "rust-openssl")]; + let default_iter = &mut default.iter().map(|&(k, v)| (k, v)); + let arg_iter = &mut self.names.iter().map(|&(ref k, ref v)| (&k[..], &v[..])); + let iter: &mut Iterator<Item = (&str, &str)> = if self.names.len() == 0 { + default_iter + } else { + arg_iter + }; - for (key,val) in iter { + for (key, val) in iter { try!(X509Generator::add_name_internal(name, &key, &val)); } ffi::X509_set_issuer_name(x509.handle, name); - for (exttype,ext) in self.extensions.iter() { + for (exttype, ext) in self.extensions.iter() { try!(X509Generator::add_extension_internal(x509.handle, exttype, &ext.to_string())); } @@ -359,9 +383,9 @@ impl X509Generator { /// Obtain a certificate signing request (CSR) pub fn request(&self, p_key: &PKey) -> Result<X509Req, SslError> { - let cert=match self.sign(p_key) { + let cert = match self.sign(p_key) { Ok(c) => c, - Err(x) => return Err(x) + Err(x) => return Err(x), }; unsafe { @@ -370,7 +394,7 @@ impl X509Generator { let exts = ffi_extras::X509_get_extensions(cert.handle); if exts != ptr::null_mut() { - try_ssl!(ffi::X509_REQ_add_extensions(req,exts)); + try_ssl!(ffi::X509_REQ_add_extensions(req, exts)); } let hash_fn = self.hash_type.evp_md(); @@ -387,7 +411,7 @@ impl X509Generator { pub struct X509<'ctx> { ctx: Option<&'ctx X509StoreContext>, handle: *mut ffi::X509, - owned: bool + owned: bool, } impl<'ctx> X509<'ctx> { @@ -406,19 +430,22 @@ impl<'ctx> X509<'ctx> { X509 { ctx: Some(ctx), handle: handle, - owned: false + owned: false, } } /// Reads certificate from PEM, takes ownership of handle - pub fn from_pem<R>(reader: &mut R) -> Result<X509<'ctx>, SslError> where R: Read { + pub fn from_pem<R>(reader: &mut R) -> Result<X509<'ctx>, SslError> + where R: Read + { let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.get_handle(), ptr::null_mut(), - None, ptr::null_mut())); + None, + ptr::null_mut())); Ok(X509::new(handle, true)) } } @@ -429,7 +456,10 @@ impl<'ctx> X509<'ctx> { pub fn subject_name<'a>(&'a self) -> X509Name<'a> { let name = unsafe { ffi::X509_get_subject_name(self.handle) }; - X509Name { x509: self, name: name } + X509Name { + x509: self, + name: name, + } } pub fn public_key(&self) -> PKey { @@ -446,7 +476,9 @@ impl<'ctx> X509<'ctx> { let v: Vec<u8> = repeat(0).take(len as usize).collect(); let act_len: c_uint = 0; let res = unsafe { - ffi::X509_digest(self.handle, evp, mem::transmute(v.as_ptr()), + ffi::X509_digest(self.handle, + evp, + mem::transmute(v.as_ptr()), mem::transmute(&act_len)) }; @@ -457,18 +489,19 @@ impl<'ctx> X509<'ctx> { match len.cmp(&act_len) { Ordering::Greater => None, Ordering::Equal => Some(v), - Ordering::Less => panic!("Fingerprint buffer was corrupted!") + Ordering::Less => panic!("Fingerprint buffer was corrupted!"), } } } } /// Writes certificate as PEM - pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError> where W: Write { + pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError> + where W: Write + { let mut mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), - self.handle)); + try_ssl!(ffi::PEM_write_bio_X509(mem_bio.get_handle(), self.handle)); } io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) } @@ -485,16 +518,16 @@ impl<'ctx> Drop for X509<'ctx> { #[allow(dead_code)] pub struct X509Name<'x> { x509: &'x X509<'x>, - name: *mut ffi::X509_NAME + name: *mut ffi::X509_NAME, } #[allow(dead_code)] pub struct X509NameEntry<'x> { x509_name: &'x X509Name<'x>, - ne: *mut ffi::X509_NAME_ENTRY + ne: *mut ffi::X509_NAME_ENTRY, } -impl <'x> X509Name<'x> { +impl<'x> X509Name<'x> { pub fn text_by_nid(&self, nid: nid::Nid) -> Option<SslString> { unsafe { let loc = ffi::X509_NAME_get_index_by_NID(self.name, nid as c_int, -1); @@ -512,11 +545,11 @@ impl <'x> X509Name<'x> { return None; } - let mut str_from_asn1 : *mut c_char = ptr::null_mut(); + let mut str_from_asn1: *mut c_char = ptr::null_mut(); let len = ffi::ASN1_STRING_to_UTF8(&mut str_from_asn1, asn1_str); if len < 0 { - return None + return None; } assert!(!str_from_asn1.is_null()); @@ -534,30 +567,32 @@ pub struct X509Req { impl X509Req { /// Creates new from handle pub fn new(handle: *mut ffi::X509_REQ) -> X509Req { - X509Req { - handle: handle, - } + X509Req { handle: handle } } /// Reads CSR from PEM - pub fn from_pem<R>(reader: &mut R) -> Result<X509Req, SslError> where R: Read { + pub fn from_pem<R>(reader: &mut R) -> Result<X509Req, SslError> + where R: Read + { let mut mem_bio = try!(MemBio::new()); try!(io::copy(reader, &mut mem_bio).map_err(StreamError)); unsafe { let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.get_handle(), - ptr::null_mut(), - None, ptr::null_mut())); + ptr::null_mut(), + None, + ptr::null_mut())); Ok(X509Req::new(handle)) } } /// Writes CSR as PEM - pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError> where W: Write { + pub fn write_pem<W>(&self, writer: &mut W) -> Result<(), SslError> + where W: Write + { let mut mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), - self.handle)); + try_ssl!(ffi::PEM_write_bio_X509_REQ(mem_bio.get_handle(), self.handle)); } io::copy(&mut mem_bio, writer).map_err(StreamError).map(|_| ()) } @@ -651,6 +686,7 @@ make_validation_error!(X509_V_OK, fn test_negative_serial() { // I guess that's enough to get a random negative number for _ in 0..1000 { - assert!(X509Generator::random_serial() > 0, "All serials should be positive"); + assert!(X509Generator::random_serial() > 0, + "All serials should be positive"); } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 692539ba..43ad0dec 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -3,10 +3,10 @@ use std::io; use std::path::Path; use std::fs::File; -use crypto::hash::Type::{SHA256}; +use crypto::hash::Type::SHA256; use crypto::pkey::PKey; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage,SubjectAltName,OtherNid,OtherStr}; +use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr}; use x509::extension::AltNameOption as SAN; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; @@ -15,14 +15,16 @@ use nid::Nid; fn get_generator() -> X509Generator { X509Generator::new() .set_bitlength(2048) - .set_valid_period(365*2) - .add_name("CN".to_string(),"test_me".to_string()) + .set_valid_period(365 * 2) + .add_name("CN".to_string(), "test_me".to_string()) .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) - .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) - .add_extension(SubjectAltName(vec![(SAN::DNS,"example.com".to_owned())])) - .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())) - .add_extension(OtherStr("2.999.2".to_owned(),"ASN1:UTF8:example value".to_owned())) + .add_extension(ExtKeyUsage(vec![ClientAuth, + ServerAuth, + ExtKeyUsageOption::Other("2.999.1".to_owned())])) + .add_extension(SubjectAltName(vec![(SAN::DNS, "example.com".to_owned())])) + .add_extension(OtherNid(Nid::BasicConstraints, "critical,CA:TRUE".to_owned())) + .add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned())) } #[test] @@ -53,8 +55,8 @@ fn test_req_gen() { fn test_cert_loading() { let cert_path = Path::new("test/cert.pem"); let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); + .ok() + .expect("Failed to open `test/cert.pem`"); let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); let fingerprint = cert.fingerprint(SHA256).unwrap(); @@ -73,14 +75,14 @@ fn test_cert_loading() { fn test_subject_read_cn() { let cert_path = Path::new("test/cert.pem"); let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/cert.pem`"); + .ok() + .expect("Failed to open `test/cert.pem`"); let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); let subject = cert.subject_name(); let cn = match subject.text_by_nid(Nid::CN) { Some(x) => x, - None => panic!("Failed to read CN from cert") + None => panic!("Failed to read CN from cert"), }; assert_eq!(&cn as &str, "test_cert") @@ -90,27 +92,27 @@ fn test_subject_read_cn() { fn test_nid_values() { let cert_path = Path::new("test/nid_test_cert.pem"); let mut file = File::open(&cert_path) - .ok() - .expect("Failed to open `test/nid_test_cert.pem`"); + .ok() + .expect("Failed to open `test/nid_test_cert.pem`"); let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM"); let subject = cert.subject_name(); let cn = match subject.text_by_nid(Nid::CN) { Some(x) => x, - None => panic!("Failed to read CN from cert") + None => panic!("Failed to read CN from cert"), }; assert_eq!(&cn as &str, "example.com"); let email = match subject.text_by_nid(Nid::Email) { Some(x) => x, - None => panic!("Failed to read subject email address from cert") + None => panic!("Failed to read subject email address from cert"), }; assert_eq!(&email as &str, "[email protected]"); let friendly = match subject.text_by_nid(Nid::FriendlyName) { Some(x) => x, - None => panic!("Failed to read subject friendly name from cert") + None => panic!("Failed to read subject friendly name from cert"), }; assert_eq!(&friendly as &str, "Example"); } |