aboutsummaryrefslogtreecommitdiff
path: root/openssl/src
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2015-05-17 14:17:19 -0400
committerSteven Fackler <[email protected]>2015-05-17 14:17:19 -0400
commitaf19831c9dda758c75f300a89db8b7418bd28598 (patch)
treecbf942f177b5208435cc3537879063679bfd4046 /openssl/src
parentMerge pull request #214 from josephglanville/feature/peer_cert (diff)
parentTest reading CN from test certificate (diff)
downloadrust-openssl-af19831c9dda758c75f300a89db8b7418bd28598.tar.xz
rust-openssl-af19831c9dda758c75f300a89db8b7418bd28598.zip
Merge pull request #213 from josephglanville/feature/read_subject
Add support for reading X509 subject information
Diffstat (limited to 'openssl/src')
-rw-r--r--openssl/src/lib.rs1
-rw-r--r--openssl/src/nid.rs170
-rw-r--r--openssl/src/ssl/tests.rs4
-rw-r--r--openssl/src/x509/mod.rs84
-rw-r--r--openssl/src/x509/tests.rs20
5 files changed, 274 insertions, 5 deletions
diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs
index b283a479..4c9b176a 100644
--- a/openssl/src/lib.rs
+++ b/openssl/src/lib.rs
@@ -22,3 +22,4 @@ pub mod bio;
pub mod crypto;
pub mod ssl;
pub mod x509;
+pub mod nid;
diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs
new file mode 100644
index 00000000..08424ae8
--- /dev/null
+++ b/openssl/src/nid.rs
@@ -0,0 +1,170 @@
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone)]
+#[repr(usize)]
+pub enum Nid {
+ Undefined,
+ Rsadsi,
+ Pkcs,
+ MD2,
+ MD4,
+ MD5,
+ RC4,
+ RsaEncryption,
+ RSA_MD2,
+ RSA_MD5,
+ PBE_MD2_DES,
+ X500,
+ x509,
+ CN,
+ C,
+ L,
+ ST,
+ O,
+ OU,
+ RSA,
+ Pkcs7,
+ Pkcs7_data,
+ Pkcs7_signedData,
+ Pkcs7_envelopedData,
+ Pkcs7_signedAndEnvelopedData,
+ Pkcs7_digestData,
+ Pkcs7_encryptedData,
+ Pkcs3,
+ DhKeyAgreement,
+ DES_ECB,
+ DES_CFB,
+ DES_CBC,
+ DES_EDE,
+ DES_EDE3,
+ IDEA_CBC,
+ IDEA_ECB,
+ RC2_CBC,
+ RC2_ECB,
+ RC2_CFB,
+ RC2_OFB,
+ SHA,
+ RSA_SHA,
+ DES_EDE_CBC,
+ DES_EDE3_CBC,
+ DES_OFB,
+ IDEA_OFB,
+ Pkcs9,
+ Email,
+ UnstructuredName,
+ ContentType,
+ MessageDigest,
+ SigningTime,
+ CounterSignature,
+ UnstructuredAddress,
+ ExtendedCertificateAttributes,
+ Netscape,
+ NetscapeCertExtention,
+ NetscapeDatatype,
+ DES_EDE_CFB64,
+ DES_EDE3_CFB64,
+ DES_EDE_OFB64,
+ DES_EDE3_OFB64,
+ SHA1,
+ RSA_SHA1,
+ DSA_SHA,
+ DSA_OLD,
+ PBE_SHA1_RC2_64,
+ PBKDF2,
+ DSA_SHA1_OLD,
+ NetscapeCertType,
+ NetscapeBaseUrl,
+ NetscapeRevocationUrl,
+ NetscapeCARevocationUrl,
+ NetscapeRenewalUrl,
+ NetscapeCAPolicyUrl,
+ NetscapeSSLServerName,
+ NetscapeComment,
+ NetscapeCertSequence,
+ DESX_CBC,
+ ID_CE,
+ SubjectKeyIdentifier,
+ KeyUsage,
+ PrivateKeyUsagePeriod,
+ SubjectAltName,
+ IssuerAltName,
+ BasicConstraints,
+ CrlNumber,
+ CertificatePolicies,
+ AuthorityKeyIdentifier,
+ BF_CBC,
+ BF_ECB,
+ BF_OFB,
+ MDC2,
+ RSA_MDC2,
+ RC4_40,
+ RC2_40_CBC,
+ G,
+ S,
+ I,
+ UID,
+ CrlDistributionPoints,
+ RSA_NP_MD5,
+ SN,
+ T,
+ D,
+ CAST5_CBC,
+ CAST5_ECB,
+ CAST5_CFB,
+ CAST5_OFB,
+ PbeWithMD5AndCast5CBC,
+ DSA_SHA1,
+ MD5_SHA1,
+ RSA_SHA1_2,
+ DSA,
+ RIPEMD160,
+ RSA_RIPEMD160,
+ RC5_CBC,
+ RC5_ECB,
+ RC5_CFB,
+ RC5_OFB,
+ RLE,
+ ZLIB,
+ ExtendedKeyUsage,
+ PKIX,
+ ID_KP,
+ ServerAuth,
+ ClientAuth,
+ CodeSigning,
+ EmailProtection,
+ TimeStamping,
+ MsCodeInd,
+ MsCodeCom,
+ MsCtlSigh,
+ MsSGC,
+ MsEFS,
+ NsSGC,
+ DeltaCRL,
+ CRLReason,
+ InvalidityDate,
+ SXNetID,
+ Pkcs12,
+ PBE_SHA1_RC4_128,
+ PBE_SHA1_RC4_40,
+ PBE_SHA1_3DES,
+ PBE_SHA1_2DES,
+ PBE_SHA1_RC2_128,
+ PBE_SHA1_RC2_40,
+ KeyBag,
+ Pkcs8ShroudedKeyBag,
+ CertBag,
+ CrlBag,
+ SecretBag,
+ SafeContentsBag,
+ FriendlyName,
+ LocalKeyID,
+ X509Certificate,
+ SdsiCertificate,
+ X509Crl,
+ PBES2,
+ PBMAC1,
+ HmacWithSha1,
+ ID_QT_CPS,
+ ID_QT_UNOTICE,
+ RC2_64_CBC,
+ SMIMECaps
+}
diff --git a/openssl/src/ssl/tests.rs b/openssl/src/ssl/tests.rs
index 6759b2bb..ec4f2b01 100644
--- a/openssl/src/ssl/tests.rs
+++ b/openssl/src/ssl/tests.rs
@@ -223,7 +223,7 @@ run_test!(verify_callback_data, |method, stream| {
// in DER format.
// Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256
// Please update if "test/cert.pem" will ever change
- let node_hash_str = "46e3f1a6d17a41ce70d0c66ef51cee2ab4ba67cac8940e23f10c1f944b49fb5c";
+ let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b";
let node_id = node_hash_str.from_hex().unwrap();
ctx.set_verify_with_data(SSL_VERIFY_PEER, callback, node_id);
ctx.set_verify_depth(1);
@@ -320,7 +320,7 @@ run_test!(get_peer_certificate, |method, stream| {
let stream = SslStream::new(&SslContext::new(method).unwrap(), stream).unwrap();
let cert = stream.get_peer_certificate().unwrap();
let fingerprint = cert.fingerprint(SHA256).unwrap();
- let node_hash_str = "46e3f1a6d17a41ce70d0c66ef51cee2ab4ba67cac8940e23f10c1f944b49 fb5c";
+ let node_hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b";
let node_id = node_hash_str.from_hex().unwrap();
assert_eq!(node_id, fingerprint)
});
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
index c0e730f7..0f7585cc 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -1,11 +1,14 @@
-use libc::{c_char, c_int, c_long, c_ulong, c_uint};
+use libc::{c_char, c_int, c_long, c_ulong, c_uint, c_void};
use std::io;
use std::io::prelude::*;
use std::cmp::Ordering;
-use std::ffi::CString;
+use std::ffi::{CString, CStr};
use std::iter::repeat;
use std::mem;
use std::ptr;
+use std::ops::Deref;
+use std::fmt;
+use std::str;
use asn1::{Asn1Time};
use bio::{MemBio};
@@ -15,11 +18,50 @@ use crypto::pkey::{PKey,Parts};
use crypto::rand::rand_bytes;
use ffi;
use ssl::error::{SslError, StreamError};
+use nid;
#[cfg(test)]
mod tests;
+pub struct SslString<'s> {
+ s : &'s str
+}
+
+impl<'s> Drop for SslString<'s> {
+ fn drop(&mut self) {
+ unsafe { ffi::CRYPTO_free(self.s.as_ptr() as *mut c_void); }
+ }
+}
+
+impl<'s> Deref for SslString<'s> {
+ type Target = str;
+
+ fn deref(&self) -> &str {
+ self.s
+ }
+}
+
+impl<'s> SslString<'s> {
+ pub unsafe fn new(buf: *const c_char) -> SslString<'s> {
+ SslString {
+ s: str::from_utf8(CStr::from_ptr(buf).to_bytes()).unwrap()
+ }
+ }
+}
+
+impl<'s> fmt::Display for SslString<'s> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
+impl<'s> fmt::Debug for SslString<'s> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{:?}", self)
+ }
+}
+
#[derive(Copy, Clone)]
#[repr(i32)]
pub enum X509FileType {
@@ -458,6 +500,44 @@ pub struct X509Name<'x> {
name: *mut ffi::X509_NAME
}
+#[allow(dead_code)]
+pub struct X509NameEntry<'x> {
+ x509_name: &'x X509Name<'x>,
+ ne: *mut ffi::X509_NAME_ENTRY
+}
+
+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);
+ if loc == -1 {
+ return None;
+ }
+
+ let ne = ffi::X509_NAME_get_entry(self.name, loc);
+ if ne.is_null() {
+ return None;
+ }
+
+ let asn1_str = ffi::X509_NAME_ENTRY_get_data(ne);
+ if asn1_str.is_null() {
+ return None;
+ }
+
+ 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
+ }
+
+ assert!(!str_from_asn1.is_null());
+
+ Some(SslString::new(str_from_asn1))
+ }
+ }
+}
+
macro_rules! make_validation_error(
($ok_val:ident, $($name:ident = $val:ident,)+) => (
#[derive(Copy, Clone)]
diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs
index e9a8a4a5..6d95b966 100644
--- a/openssl/src/x509/tests.rs
+++ b/openssl/src/x509/tests.rs
@@ -7,6 +7,7 @@ use crypto::hash::Type::{SHA256};
use x509::{X509, X509Generator};
use x509::KeyUsage::{DigitalSignature, KeyEncipherment};
use x509::ExtKeyUsage::{ClientAuth, ServerAuth};
+use nid::Nid;
#[test]
fn test_cert_gen() {
@@ -46,8 +47,25 @@ fn test_cert_loading() {
// in DER format.
// Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256
// Please update if "test/cert.pem" will ever change
- let hash_str = "46e3f1a6d17a41ce70d0c66ef51cee2ab4ba67cac8940e23f10c1f944b49fb5c";
+ let hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b";
let hash_vec = hash_str.from_hex().unwrap();
assert_eq!(fingerprint, hash_vec);
}
+
+#[test]
+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`");
+
+ 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")
+ };
+
+ assert_eq!(&cn as &str, "test_cert")
+}