diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 0af8ec11e441b09ff6591bedaa9c81232ff99a33..7a09ddbc69f3d94ff4a73393125a416fbe72e6d5 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -556,6 +556,70 @@ impl AuthorityKeyIdentifier { } } +pub struct SubjectAlternativeName { + critical: bool, + names: Vec, +} + +impl SubjectAlternativeName { + pub fn new() -> SubjectAlternativeName { + SubjectAlternativeName { + critical: false, + names: vec![], + } + } + + pub fn critical(&mut self) -> &mut SubjectAlternativeName { + self.critical = true; + self + } + + pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("email:{}", email)); + self + } + + pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("URI:{}", uri)); + self + } + + pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("DNS:{}", dns)); + self + } + + pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("RID:{}", rid)); + self + } + + pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("IP:{}", ip)); + self + } + + pub fn dir_name(&mut self, dir_name: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("dirName:{}", dir_name)); + self + } + + pub fn other_name(&mut self, other_name: &str) -> &mut SubjectAlternativeName { + self.names.push(format!("otherName:{}", other_name)); + self + } + + pub fn build(&self, ctx: &X509v3Context) -> Result { + let mut value = String::new(); + let mut first = true; + append(&mut value, &mut first, self.critical, "critical"); + for name in &self.names { + append(&mut value, &mut first, true, name); + } + X509Extension::new_nid(None, Some(ctx), nid::SUBJECT_ALT_NAME, &value) + } +} + fn append(value: &mut String, first: &mut bool, should: bool, element: &str) { if !should { return; diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index a1ab6de55548aeaa124e1cdf853951b9cd7c6d6c..510bb4371f53887ad41c77ce09772aaeca3ef1c6 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -7,7 +7,7 @@ use pkey::PKey; use rsa::Rsa; use x509::{X509, X509Generator, X509Name}; use x509::extension::{Extension, BasicConstraints, KeyUsage, ExtendedKeyUsage, - SubjectKeyIdentifier, AuthorityKeyIdentifier}; + SubjectKeyIdentifier, AuthorityKeyIdentifier, SubjectAlternativeName}; use x509::extension::AltNameOption as SAN; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; @@ -217,6 +217,11 @@ fn x509_builder() { .build(&builder.x509v3_context(None, None)) .unwrap(); builder.append_extension(authority_key_identifier).unwrap(); + let subject_alternative_name = SubjectAlternativeName::new() + .dns("example.com") + .build(&builder.x509v3_context(None, None)) + .unwrap(); + builder.append_extension(subject_alternative_name).unwrap(); builder.sign(&pkey, MessageDigest::sha256()).unwrap();