From 14a2f5c5e9541d30b825bd7e2dc6961bc11e6200 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 17:23:57 -0700 Subject: [PATCH 01/12] Move X509 extensions to seperate module, implement ToString instead of custom AsStr --- openssl/src/x509/extension.rs | 69 +++++++++++++++++++++++++++++++ openssl/src/x509/mod.rs | 76 +++-------------------------------- 2 files changed, 75 insertions(+), 70 deletions(-) create mode 100644 openssl/src/x509/extension.rs diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs new file mode 100644 index 00000000..b7f5fc52 --- /dev/null +++ b/openssl/src/x509/extension.rs @@ -0,0 +1,69 @@ +use std::fmt; + +#[derive(Clone)] +pub enum Extension { + KeyUsage(Vec), + ExtKeyUsage(Vec), +} + +#[derive(Clone,Copy)] +pub enum KeyUsageOption { + DigitalSignature, + NonRepudiation, + KeyEncipherment, + DataEncipherment, + KeyAgreement, + KeyCertSign, + CRLSign, + EncipherOnly, + DecipherOnly, +} + +impl fmt::Display for KeyUsageOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &KeyUsageOption::DigitalSignature => "digitalSignature", + &KeyUsageOption::NonRepudiation => "nonRepudiation", + &KeyUsageOption::KeyEncipherment => "keyEncipherment", + &KeyUsageOption::DataEncipherment => "dataEncipherment", + &KeyUsageOption::KeyAgreement => "keyAgreement", + &KeyUsageOption::KeyCertSign => "keyCertSign", + &KeyUsageOption::CRLSign => "cRLSign", + &KeyUsageOption::EncipherOnly => "encipherOnly", + &KeyUsageOption::DecipherOnly => "decipherOnly", + }) + } +} + +#[derive(Clone,Copy)] +pub enum ExtKeyUsageOption { + ServerAuth, + ClientAuth, + CodeSigning, + EmailProtection, + TimeStamping, + MsCodeInd, + MsCodeCom, + MsCtlSign, + MsSgc, + MsEfs, + NsSgc, +} + +impl fmt::Display for ExtKeyUsageOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &ExtKeyUsageOption::ServerAuth => "serverAuth", + &ExtKeyUsageOption::ClientAuth => "clientAuth", + &ExtKeyUsageOption::CodeSigning => "codeSigning", + &ExtKeyUsageOption::EmailProtection => "emailProtection", + &ExtKeyUsageOption::TimeStamping => "timeStamping", + &ExtKeyUsageOption::MsCodeInd => "msCodeInd", + &ExtKeyUsageOption::MsCodeCom => "msCodeCom", + &ExtKeyUsageOption::MsCtlSign => "msCTLSign", + &ExtKeyUsageOption::MsSgc => "msSGC", + &ExtKeyUsageOption::MsEfs => "msEFS", + &ExtKeyUsageOption::NsSgc =>"nsSGC", + }) + } +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 5446f125..6292579b 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -20,6 +20,7 @@ use ffi; use ssl::error::{SslError, StreamError}; use nid; +mod extension; #[cfg(test)] mod tests; @@ -98,74 +99,9 @@ impl X509StoreContext { } } -#[doc(hidden)] -trait AsStr<'a> { - fn as_str(&self) -> &'a str; -} - -#[derive(Clone, Copy)] -pub enum KeyUsage { - DigitalSignature, - NonRepudiation, - KeyEncipherment, - DataEncipherment, - KeyAgreement, - KeyCertSign, - CRLSign, - EncipherOnly, - DecipherOnly -} - -impl AsStr<'static> for KeyUsage { - fn as_str(&self) -> &'static str { - match self { - &KeyUsage::DigitalSignature => "digitalSignature", - &KeyUsage::NonRepudiation => "nonRepudiation", - &KeyUsage::KeyEncipherment => "keyEncipherment", - &KeyUsage::DataEncipherment => "dataEncipherment", - &KeyUsage::KeyAgreement => "keyAgreement", - &KeyUsage::KeyCertSign => "keyCertSign", - &KeyUsage::CRLSign => "cRLSign", - &KeyUsage::EncipherOnly => "encipherOnly", - &KeyUsage::DecipherOnly => "decipherOnly" - } - } -} - - -#[derive(Clone, Copy)] -pub enum ExtKeyUsage { - ServerAuth, - ClientAuth, - CodeSigning, - EmailProtection, - TimeStamping, - MsCodeInd, - MsCodeCom, - MsCtlSign, - MsSgc, - MsEfs, - NsSgc -} - -impl AsStr<'static> for ExtKeyUsage { - fn as_str(&self) -> &'static str { - match self { - &ExtKeyUsage::ServerAuth => "serverAuth", - &ExtKeyUsage::ClientAuth => "clientAuth", - &ExtKeyUsage::CodeSigning => "codeSigning", - &ExtKeyUsage::EmailProtection => "emailProtection", - &ExtKeyUsage::TimeStamping => "timeStamping", - &ExtKeyUsage::MsCodeInd => "msCodeInd", - &ExtKeyUsage::MsCodeCom => "msCodeCom", - &ExtKeyUsage::MsCtlSign => "msCTLSign", - &ExtKeyUsage::MsSgc => "msSGC", - &ExtKeyUsage::MsEfs => "msEFS", - &ExtKeyUsage::NsSgc =>"nsSGC" - } - } -} - +// Backwards-compatibility +pub use self::extension::KeyUsageOption as KeyUsage; +pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; // FIXME: a dirty hack as there is no way to // implement ToString for Vec as both are defined @@ -175,11 +111,11 @@ trait ToStr { fn to_str(&self) -> String; } -impl<'a, T: AsStr<'a>> ToStr for Vec { +impl ToStr for Vec { fn to_str(&self) -> String { self.iter().enumerate().fold(String::new(), |mut acc, (idx, v)| { if idx > 0 { acc.push(',') }; - acc.push_str(v.as_str()); + acc.push_str(&v.to_string()); acc }) } From c4e398d39785e20640216ac595355d45a32c8618 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 17:27:44 -0700 Subject: [PATCH 02/12] Turn "dirty hack" into slightly less dirty hack, with potential to become non-dirty --- openssl/src/x509/mod.rs | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 6292579b..864e94c8 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -103,22 +103,14 @@ impl X509StoreContext { pub use self::extension::KeyUsageOption as KeyUsage; pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; -// FIXME: a dirty hack as there is no way to -// implement ToString for Vec as both are defined -// in another crate -#[doc(hidden)] -trait ToStr { - fn to_str(&self) -> String; -} - -impl ToStr for Vec { - fn to_str(&self) -> String { - self.iter().enumerate().fold(String::new(), |mut acc, (idx, v)| { - if idx > 0 { acc.push(',') }; - acc.push_str(&v.to_string()); - acc - }) - } +// FIXME: This would be nicer as a method on Iterator. This can +// eventually be replaced by the successor to std::slice::SliceConcatExt.connect +fn join,T: ToString>(iter: I, sep: &str) -> String { + iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { + if idx > 0 { acc.push_str(sep) }; + acc.push_str(&v.to_string()); + acc + }) } #[allow(non_snake_case)] @@ -314,12 +306,12 @@ impl X509Generator { if self.key_usage.len() > 0 { try!(X509Generator::add_extension(x509.handle, ffi::NID_key_usage, - &self.key_usage.to_str())); + &join(self.key_usage.iter(),","))); } if self.ext_key_usage.len() > 0 { try!(X509Generator::add_extension(x509.handle, ffi::NID_ext_key_usage, - &self.ext_key_usage.to_str())); + &join(self.ext_key_usage.iter(),","))); } let hash_fn = self.hash_type.evp_md(); From d5a4d48caba81ffcd46abc49d7373a2d81c370d9 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 18:52:17 -0700 Subject: [PATCH 03/12] Turn assertions into unwraps such that tests provide useful output on panic. --- openssl/src/x509/tests.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 4e1c4f15..ca9ce68c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -19,13 +19,9 @@ fn test_cert_gen() { .set_usage(&[DigitalSignature, KeyEncipherment]) .set_ext_usage(&[ClientAuth, ServerAuth]); - let res = gen.generate(); - assert!(res.is_ok()); - - let (cert, pkey) = res.unwrap(); - - assert!(cert.write_pem(&mut io::sink()).is_ok()); - assert!(pkey.write_pem(&mut io::sink()).is_ok()); + let (cert, pkey) = gen.generate().unwrap(); + cert.write_pem(&mut io::sink()).unwrap(); + pkey.write_pem(&mut io::sink()).unwrap(); // FIXME: check data in result to be correct, needs implementation // of X509 getters From 8d1abf5156840cb718f637959a1f98f499a64519 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 18:54:48 -0700 Subject: [PATCH 04/12] Implement "extensions" field in X509generator, and change existing extensions to use that --- openssl/src/nid.rs | 2 +- openssl/src/x509/extension.rs | 42 +++++++++++++++++++++++++++++++++++ openssl/src/x509/mod.rs | 34 +++++++++------------------- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs index c5b9e277..81cc4975 100644 --- a/openssl/src/nid.rs +++ b/openssl/src/nid.rs @@ -1,5 +1,5 @@ #[allow(non_camel_case_types)] -#[derive(Copy, Clone)] +#[derive(Copy, Clone, Hash, PartialEq, Eq)] #[repr(usize)] pub enum Nid { Undefined, diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index b7f5fc52..4f8a3c3b 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,4 +1,11 @@ use std::fmt; +use nid::Nid; + +#[derive(Clone,Copy,Hash,PartialEq,Eq)] +pub enum ExtensionType { + KeyUsage, + ExtKeyUsage, +} #[derive(Clone)] pub enum Extension { @@ -6,6 +13,41 @@ pub enum Extension { ExtKeyUsage(Vec), } +impl Extension { + pub fn get_type(&self) -> ExtensionType { + match self { + &Extension::KeyUsage(_) => ExtensionType::KeyUsage, + &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + } + } + + pub fn get_nid(&self) -> Nid { + match self { + &Extension::KeyUsage(_) => Nid::KeyUsage, + &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, + } + } +} + +// FIXME: This would be nicer as a method on Iterator. This can +// eventually be replaced by the successor to std::slice::SliceConcatExt.connect +fn join,T: ToString>(iter: I, sep: &str) -> String { + iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { + if idx > 0 { acc.push_str(sep) }; + acc.push_str(&v.to_string()); + acc + }) +} + +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(),","), + } + } +} + #[derive(Clone,Copy)] pub enum KeyUsageOption { DigitalSignature, diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 864e94c8..7d936f7e 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -9,6 +9,7 @@ use std::ptr; use std::ops::Deref; use std::fmt; use std::str; +use std::collections::HashMap; use asn1::{Asn1Time}; use bio::{MemBio}; @@ -22,6 +23,8 @@ use nid; mod extension; +use self::extension::{ExtensionType,Extension}; + #[cfg(test)] mod tests; @@ -103,16 +106,6 @@ impl X509StoreContext { pub use self::extension::KeyUsageOption as KeyUsage; pub use self::extension::ExtKeyUsageOption as ExtKeyUsage; -// FIXME: This would be nicer as a method on Iterator. This can -// eventually be replaced by the successor to std::slice::SliceConcatExt.connect -fn join,T: ToString>(iter: I, sep: &str) -> String { - iter.enumerate().fold(String::new(), |mut acc, (idx, v)| { - if idx > 0 { acc.push_str(sep) }; - acc.push_str(&v.to_string()); - acc - }) -} - #[allow(non_snake_case)] /// Generator of private key/certificate pairs /// @@ -153,8 +146,8 @@ pub struct X509Generator { bits: u32, days: u32, CN: String, - key_usage: Vec, - ext_key_usage: Vec, + // RFC 3280 ยง4.2: A certificate MUST NOT include more than one instance of a particular extension. + extensions: HashMap, hash_type: HashType, } @@ -173,8 +166,7 @@ impl X509Generator { bits: 1024, days: 365, CN: "rust-openssl".to_string(), - key_usage: Vec::new(), - ext_key_usage: Vec::new(), + extensions: HashMap::new(), hash_type: HashType::SHA1 } } @@ -200,13 +192,13 @@ impl X509Generator { /// Sets what for certificate could be used pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator { - self.key_usage = purposes.to_vec(); + self.extensions.insert(ExtensionType::KeyUsage,Extension::KeyUsage(purposes.to_owned())); self } /// Sets allowed extended usage of certificate pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator { - self.ext_key_usage = purposes.to_vec(); + self.extensions.insert(ExtensionType::ExtKeyUsage,Extension::ExtKeyUsage(purposes.to_owned())); self } @@ -304,14 +296,8 @@ impl X509Generator { try!(X509Generator::add_name(name, "CN", &self.CN)); ffi::X509_set_issuer_name(x509.handle, name); - if self.key_usage.len() > 0 { - try!(X509Generator::add_extension(x509.handle, ffi::NID_key_usage, - &join(self.key_usage.iter(),","))); - } - - if self.ext_key_usage.len() > 0 { - try!(X509Generator::add_extension(x509.handle, ffi::NID_ext_key_usage, - &join(self.ext_key_usage.iter(),","))); + for ext in self.extensions.values() { + try!(X509Generator::add_extension(x509.handle, ext.get_nid() as c_int, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); From 53b868697a754229ba457908f29af5e8fd83404a Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:25:00 -0700 Subject: [PATCH 05/12] Implement arbitrary X509 Extended Key Usage values --- openssl/src/x509/extension.rs | 5 ++++- openssl/src/x509/tests.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 4f8a3c3b..66b218ad 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -77,7 +77,7 @@ impl fmt::Display for KeyUsageOption { } } -#[derive(Clone,Copy)] +#[derive(Clone)] pub enum ExtKeyUsageOption { ServerAuth, ClientAuth, @@ -90,6 +90,8 @@ pub enum ExtKeyUsageOption { MsSgc, MsEfs, NsSgc, + /// An arbitrary key usage by OID. + Other(String), } impl fmt::Display for ExtKeyUsageOption { @@ -106,6 +108,7 @@ impl fmt::Display for ExtKeyUsageOption { &ExtKeyUsageOption::MsSgc => "msSGC", &ExtKeyUsageOption::MsEfs => "msEFS", &ExtKeyUsageOption::NsSgc =>"nsSGC", + &ExtKeyUsageOption::Other(ref s) => &s[..], }) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ca9ce68c..66dc33d3 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -6,7 +6,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; use x509::KeyUsage::{DigitalSignature, KeyEncipherment}; -use x509::ExtKeyUsage::{ClientAuth, ServerAuth}; +use x509::ExtKeyUsage::{self, ClientAuth, ServerAuth}; use nid::Nid; #[test] @@ -17,7 +17,7 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .set_usage(&[DigitalSignature, KeyEncipherment]) - .set_ext_usage(&[ClientAuth, ServerAuth]); + .set_ext_usage(&[ClientAuth, ServerAuth, ExtKeyUsage::Other("2.999".to_owned())]); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From 2fa134436707454d8c46a0fba8a7e252fb9f1668 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:30:54 -0700 Subject: [PATCH 06/12] Add public generic extension interface to X509Generator * Add add_extension and add_extensions functions * Deprecate set_usage and set_ext_usage * Change test to use add_extension --- openssl/src/x509/mod.rs | 53 ++++++++++++++++++++++++++++++++------- openssl/src/x509/tests.rs | 9 ++++--- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 7d936f7e..42bb7a08 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -21,7 +21,7 @@ use ffi; use ssl::error::{SslError, StreamError}; use nid; -mod extension; +pub mod extension; use self::extension::{ExtensionType,Extension}; @@ -190,15 +190,50 @@ impl X509Generator { self } - /// Sets what for certificate could be used - pub fn set_usage(mut self, purposes: &[KeyUsage]) -> X509Generator { - self.extensions.insert(ExtensionType::KeyUsage,Extension::KeyUsage(purposes.to_owned())); + /// (deprecated) Sets what for certificate could be used + /// + /// This function is deprecated, use `X509Generator.add_extension` instead. + pub fn set_usage(self, purposes: &[KeyUsage]) -> X509Generator { + self.add_extension(Extension::KeyUsage(purposes.to_owned())) + } + + /// (deprecated) Sets allowed extended usage of certificate + /// + /// This function is deprecated, use `X509Generator.add_extension` instead. + pub fn set_ext_usage(self, purposes: &[ExtKeyUsage]) -> X509Generator { + self.add_extension(Extension::ExtKeyUsage(purposes.to_owned())) + } + + /// Add an extension to a certificate + /// + /// If the extension already exists, it will be replaced. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::KeyUsageOption::*; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// 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 } - /// Sets allowed extended usage of certificate - pub fn set_ext_usage(mut self, purposes: &[ExtKeyUsage]) -> X509Generator { - self.extensions.insert(ExtensionType::ExtKeyUsage,Extension::ExtKeyUsage(purposes.to_owned())); + /// Add multiple extensions to a certificate + /// + /// If any of the extensions already exist, they will be replaced. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::KeyUsageOption::*; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extensions(vec![KeyUsage(vec![DigitalSignature, KeyEncipherment])]); + /// ``` + pub fn add_extensions(mut self, exts: I) -> X509Generator + where I: IntoIterator { + self.extensions.extend(exts.into_iter().map(|ext|(ext.get_type(),ext))); self } @@ -207,7 +242,7 @@ impl X509Generator { self } - fn add_extension(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> { + fn add_extension_internal(x509: *mut ffi::X509, extension: c_int, value: &str) -> Result<(), SslError> { unsafe { let mut ctx: ffi::X509V3_CTX = mem::zeroed(); ffi::X509V3_set_ctx(&mut ctx, x509, x509, @@ -297,7 +332,7 @@ impl X509Generator { ffi::X509_set_issuer_name(x509.handle, name); for ext in self.extensions.values() { - try!(X509Generator::add_extension(x509.handle, ext.get_nid() as c_int, &ext.to_string())); + try!(X509Generator::add_extension_internal(x509.handle, ext.get_nid() as c_int, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 66dc33d3..806bc671 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,8 +5,9 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::KeyUsage::{DigitalSignature, KeyEncipherment}; -use x509::ExtKeyUsage::{self, ClientAuth, ServerAuth}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage}; +use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; +use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; #[test] @@ -16,8 +17,8 @@ fn test_cert_gen() { .set_valid_period(365*2) .set_CN("test_me") .set_sign_hash(SHA256) - .set_usage(&[DigitalSignature, KeyEncipherment]) - .set_ext_usage(&[ClientAuth, ServerAuth, ExtKeyUsage::Other("2.999".to_owned())]); + .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From e367567d00cdbd6b12906a424971146f6c3eea28 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 22:37:49 -0700 Subject: [PATCH 07/12] Add arbitrary X509 extensions by NID --- openssl/src/x509/extension.rs | 5 +++++ openssl/src/x509/tests.rs | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 66b218ad..4576ad1a 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -5,12 +5,14 @@ use nid::Nid; pub enum ExtensionType { KeyUsage, ExtKeyUsage, + OtherNid(Nid), } #[derive(Clone)] pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), + OtherNid(Nid,String), } impl Extension { @@ -18,6 +20,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), } } @@ -25,6 +28,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => Nid::KeyUsage, &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, + &Extension::OtherNid(nid,_) => nid, } } } @@ -44,6 +48,7 @@ impl ToString for Extension { match self { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), + &Extension::OtherNid(_,ref value) => value.clone(), } } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 806bc671..0061453c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid}; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; @@ -18,7 +18,8 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) - .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])); + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])) + .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From b46574b63587dab26eb46aa8f45b2dc830053988 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:00:48 -0700 Subject: [PATCH 08/12] Add arbitrary X509 extensions by OID string --- openssl-sys/src/lib.rs | 1 + openssl/src/x509/extension.rs | 24 +++++++++++++++++++----- openssl/src/x509/mod.rs | 19 ++++++++++++------- openssl/src/x509/tests.rs | 7 ++++--- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 9f2041a4..950ca42f 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -603,6 +603,7 @@ extern "C" { pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void; pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION; + pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION; pub fn X509V3_set_ctx(ctx: *mut X509V3_CTX, issuer: *mut X509, subject: *mut X509, req: *mut X509_REQ, crl: *mut X509_CRL, flags: c_int); pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *const *mut u8) -> c_int; diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 4576ad1a..78058b72 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,11 +1,12 @@ use std::fmt; use nid::Nid; -#[derive(Clone,Copy,Hash,PartialEq,Eq)] +#[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { KeyUsage, ExtKeyUsage, OtherNid(Nid), + OtherStr(String), } #[derive(Clone)] @@ -13,6 +14,7 @@ pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), OtherNid(Nid,String), + OtherStr(String,String), } impl Extension { @@ -21,14 +23,25 @@ impl Extension { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), + &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), + } + } +} + +impl ExtensionType { + pub fn get_nid(&self) -> Option { + match self { + &ExtensionType::KeyUsage => Some(Nid::KeyUsage), + &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::OtherNid(nid) => Some(nid), + &ExtensionType::OtherStr(_) => None, } } - pub fn get_nid(&self) -> Nid { + pub fn get_name<'a>(&'a self) -> Option<&'a str> { match self { - &Extension::KeyUsage(_) => Nid::KeyUsage, - &Extension::ExtKeyUsage(_) => Nid::ExtendedKeyUsage, - &Extension::OtherNid(nid,_) => nid, + &ExtensionType::OtherStr(ref s) => Some(s), + _ => None, } } } @@ -49,6 +62,7 @@ impl ToString for Extension { &Extension::KeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::ExtKeyUsage(ref purposes) => join(purposes.iter(),","), &Extension::OtherNid(_,ref value) => value.clone(), + &Extension::OtherStr(_,ref value) => value.clone(), } } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 42bb7a08..423a258f 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -242,17 +242,22 @@ impl X509Generator { self } - fn add_extension_internal(x509: *mut ffi::X509, extension: c_int, 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); let value = CString::new(value.as_bytes()).unwrap(); - let ext = ffi::X509V3_EXT_conf_nid(ptr::null_mut(), + let ext=match exttype.get_nid() { + Some(nid) => ffi::X509V3_EXT_conf_nid(ptr::null_mut(), mem::transmute(&ctx), - extension, - value.as_ptr() as *mut c_char); - + nid as c_int, + value.as_ptr() as *mut c_char), + None => ffi::X509V3_EXT_conf(ptr::null_mut(), + mem::transmute(&ctx), + exttype.get_name().unwrap().as_ptr() as *mut c_char, + value.as_ptr() as *mut c_char), + }; let mut success = false; if ext != ptr::null_mut() { success = ffi::X509_add_ext(x509, ext, -1) != 0; @@ -331,8 +336,8 @@ impl X509Generator { try!(X509Generator::add_name(name, "CN", &self.CN)); ffi::X509_set_issuer_name(x509.handle, name); - for ext in self.extensions.values() { - try!(X509Generator::add_extension_internal(x509.handle, ext.get_nid() as c_int, &ext.to_string())); + for (exttype,ext) in self.extensions.iter() { + try!(X509Generator::add_extension_internal(x509.handle, exttype, &ext.to_string())); } let hash_fn = self.hash_type.evp_md(); diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 0061453c..ff7d1173 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,7 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid}; +use x509::extension::Extension::{KeyUsage,ExtKeyUsage,OtherNid,OtherStr}; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; use nid::Nid; @@ -18,8 +18,9 @@ fn test_cert_gen() { .set_CN("test_me") .set_sign_hash(SHA256) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) - .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999".to_owned())])) - .add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); + .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".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())); let (cert, pkey) = gen.generate().unwrap(); cert.write_pem(&mut io::sink()).unwrap(); From f4168b1161081523705657adc4a324e533483ca3 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:11:42 -0700 Subject: [PATCH 09/12] Add Subject Alternate Name extension --- openssl/src/x509/extension.rs | 32 ++++++++++++++++++++++++++++++++ openssl/src/x509/tests.rs | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 78058b72..8091d058 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -5,6 +5,7 @@ use nid::Nid; pub enum ExtensionType { KeyUsage, ExtKeyUsage, + SubjectAltName, OtherNid(Nid), OtherStr(String), } @@ -13,6 +14,7 @@ pub enum ExtensionType { pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), + SubjectAltName(Vec<(AltNameOption,String)>), OtherNid(Nid,String), OtherStr(String,String), } @@ -22,6 +24,7 @@ impl Extension { match self { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &Extension::ExtKeyUsage(_) => ExtensionType::ExtKeyUsage, + &Extension::SubjectAltName(_) => ExtensionType::SubjectAltName, &Extension::OtherNid(nid,_) => ExtensionType::OtherNid(nid), &Extension::OtherStr(ref s,_) => ExtensionType::OtherStr(s.clone()), } @@ -33,6 +36,7 @@ impl ExtensionType { match self { &ExtensionType::KeyUsage => Some(Nid::KeyUsage), &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), &ExtensionType::OtherNid(nid) => Some(nid), &ExtensionType::OtherStr(_) => None, } @@ -61,6 +65,7 @@ impl ToString for Extension { 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::OtherNid(_,ref value) => value.clone(), &Extension::OtherStr(_,ref value) => value.clone(), } @@ -131,3 +136,30 @@ impl fmt::Display for ExtKeyUsageOption { }) } } + +#[derive(Clone, Copy)] +pub enum AltNameOption { + Other, + Email, + DNS, + //X400, // Not supported by OpenSSL + Directory, + //EDIParty, // Not supported by OpenSSL + URI, + IPAddress, + RegisteredID, +} + +impl fmt::Display for AltNameOption { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.pad(match self { + &AltNameOption::Other => "otherName", + &AltNameOption::Email => "email", + &AltNameOption::DNS => "DNS", + &AltNameOption::Directory => "dirName", + &AltNameOption::URI => "URI", + &AltNameOption::IPAddress => "IP", + &AltNameOption::RegisteredID => "RID", + }) + } +} diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index ff7d1173..8417ee5c 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -5,7 +5,8 @@ use std::fs::File; use crypto::hash::Type::{SHA256}; use x509::{X509, X509Generator}; -use x509::extension::Extension::{KeyUsage,ExtKeyUsage,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}; use nid::Nid; @@ -19,6 +20,7 @@ fn test_cert_gen() { .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())); From e9cc8cb121b027a9f5faa46339820e573f2efdcf Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:13:30 -0700 Subject: [PATCH 10/12] Add Issuer Alternative Name extension --- openssl/src/x509/extension.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 8091d058..0b050b34 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -6,6 +6,7 @@ pub enum ExtensionType { KeyUsage, ExtKeyUsage, SubjectAltName, + IssuerAltName, OtherNid(Nid), OtherStr(String), } @@ -15,6 +16,7 @@ pub enum Extension { KeyUsage(Vec), ExtKeyUsage(Vec), SubjectAltName(Vec<(AltNameOption,String)>), + IssuerAltName(Vec<(AltNameOption,String)>), OtherNid(Nid,String), OtherStr(String,String), } @@ -25,6 +27,7 @@ impl Extension { &Extension::KeyUsage(_) => ExtensionType::KeyUsage, &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()), } @@ -37,6 +40,7 @@ impl ExtensionType { &ExtensionType::KeyUsage => Some(Nid::KeyUsage), &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), + &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), &ExtensionType::OtherNid(nid) => Some(nid), &ExtensionType::OtherStr(_) => None, } @@ -66,6 +70,7 @@ impl ToString for Extension { &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(), } From 93eb0cfa2d4f7fe2c1091ad972c48e18b140807d Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:30:15 -0700 Subject: [PATCH 11/12] Add documentation on X509 Extensions --- openssl/src/x509/extension.rs | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 0b050b34..e6d992a1 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,6 +1,10 @@ use std::fmt; use nid::Nid; +/// Type-only version of the `Extension` enum. +/// +/// See the `Extension` documentation for more information on the different +/// variants. #[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { KeyUsage, @@ -11,13 +15,42 @@ pub enum ExtensionType { OtherStr(String), } +/// A X.509 v3 certificate extension. +/// +/// Only one extension of each type is allow in a certificate. +/// See RFC 3280 for more information about extensions. #[derive(Clone)] pub enum Extension { + /// The purposes of the key contained in the certificate KeyUsage(Vec), + /// The extended purposes of the key contained in the certificate ExtKeyUsage(Vec), + /// Subject Alternative Names SubjectAltName(Vec<(AltNameOption,String)>), + /// Issuer Alternative Names 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. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::nid::Nid; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); + /// ``` 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. + /// + /// ``` + /// use openssl::x509::extension::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), } @@ -144,6 +177,15 @@ impl fmt::Display for ExtKeyUsageOption { #[derive(Clone, Copy)] pub enum AltNameOption { + /// The value is specified as OID;content. See `man ASN1_generate_nconf` for more information on the content syntax. + /// + /// ``` + /// use openssl::x509::extension::Extension::*; + /// use openssl::x509::extension::AltNameOption::Other as OtherName; + /// + /// # let generator = openssl::x509::X509Generator::new(); + /// generator.add_extension(SubjectAltName(vec![(OtherName,"2.999.3;ASN1:UTF8:some other name".to_owned())])); + /// ``` Other, Email, DNS, From f9a836fae9a8b58513e4e0de6e27bf363bc88740 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Tue, 30 Jun 2015 23:30:45 -0700 Subject: [PATCH 12/12] tabs to spaces --- openssl/src/x509/extension.rs | 152 +++++++++++++++++----------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index e6d992a1..3faa0996 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -7,12 +7,12 @@ use nid::Nid; /// variants. #[derive(Clone,Hash,PartialEq,Eq)] pub enum ExtensionType { - KeyUsage, - ExtKeyUsage, - SubjectAltName, - IssuerAltName, - OtherNid(Nid), - OtherStr(String), + KeyUsage, + ExtKeyUsage, + SubjectAltName, + IssuerAltName, + OtherNid(Nid), + OtherStr(String), } /// A X.509 v3 certificate extension. @@ -21,70 +21,70 @@ pub enum ExtensionType { /// See RFC 3280 for more information about extensions. #[derive(Clone)] pub enum Extension { - /// The purposes of the key contained in the certificate - KeyUsage(Vec), - /// The extended purposes of the key contained in the certificate - ExtKeyUsage(Vec), - /// Subject Alternative Names - SubjectAltName(Vec<(AltNameOption,String)>), - /// Issuer Alternative Names - 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. - /// + /// The purposes of the key contained in the certificate + KeyUsage(Vec), + /// The extended purposes of the key contained in the certificate + ExtKeyUsage(Vec), + /// Subject Alternative Names + SubjectAltName(Vec<(AltNameOption,String)>), + /// Issuer Alternative Names + 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. + /// /// ``` /// use openssl::x509::extension::Extension::*; - /// use openssl::nid::Nid; + /// use openssl::nid::Nid; /// /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); /// ``` - 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. - /// + 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. + /// /// ``` /// use openssl::x509::extension::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 { - pub fn get_type(&self) -> ExtensionType { - match self { - &Extension::KeyUsage(_) => ExtensionType::KeyUsage, - &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()), - } - } + pub fn get_type(&self) -> ExtensionType { + match self { + &Extension::KeyUsage(_) => ExtensionType::KeyUsage, + &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()), + } + } } impl ExtensionType { - pub fn get_nid(&self) -> Option { - match self { - &ExtensionType::KeyUsage => Some(Nid::KeyUsage), - &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), - &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), - &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), - &ExtensionType::OtherNid(nid) => Some(nid), - &ExtensionType::OtherStr(_) => None, - } - } + pub fn get_nid(&self) -> Option { + match self { + &ExtensionType::KeyUsage => Some(Nid::KeyUsage), + &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), + &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), + &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), + &ExtensionType::OtherNid(nid) => Some(nid), + &ExtensionType::OtherStr(_) => None, + } + } - pub fn get_name<'a>(&'a self) -> Option<&'a str> { - match self { - &ExtensionType::OtherStr(ref s) => Some(s), - _ => None, - } - } + pub fn get_name<'a>(&'a self) -> Option<&'a str> { + match self { + &ExtensionType::OtherStr(ref s) => Some(s), + _ => None, + } + } } // FIXME: This would be nicer as a method on Iterator. This can @@ -99,14 +99,14 @@ fn join,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(), - } + 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(), + } } } @@ -178,7 +178,7 @@ impl fmt::Display for ExtKeyUsageOption { #[derive(Clone, Copy)] pub enum AltNameOption { /// The value is specified as OID;content. See `man ASN1_generate_nconf` for more information on the content syntax. - /// + /// /// ``` /// use openssl::x509::extension::Extension::*; /// use openssl::x509::extension::AltNameOption::Other as OtherName; @@ -186,27 +186,27 @@ pub enum AltNameOption { /// # let generator = openssl::x509::X509Generator::new(); /// generator.add_extension(SubjectAltName(vec![(OtherName,"2.999.3;ASN1:UTF8:some other name".to_owned())])); /// ``` - Other, - Email, - DNS, - //X400, // Not supported by OpenSSL - Directory, - //EDIParty, // Not supported by OpenSSL - URI, - IPAddress, - RegisteredID, + Other, + Email, + DNS, + //X400, // Not supported by OpenSSL + Directory, + //EDIParty, // Not supported by OpenSSL + URI, + IPAddress, + RegisteredID, } impl fmt::Display for AltNameOption { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { f.pad(match self { - &AltNameOption::Other => "otherName", - &AltNameOption::Email => "email", - &AltNameOption::DNS => "DNS", - &AltNameOption::Directory => "dirName", - &AltNameOption::URI => "URI", - &AltNameOption::IPAddress => "IP", - &AltNameOption::RegisteredID => "RID", + &AltNameOption::Other => "otherName", + &AltNameOption::Email => "email", + &AltNameOption::DNS => "DNS", + &AltNameOption::Directory => "dirName", + &AltNameOption::URI => "URI", + &AltNameOption::IPAddress => "IP", + &AltNameOption::RegisteredID => "RID", }) } }