aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Fackler <[email protected]>2017-01-03 15:31:03 -0800
committerGitHub <[email protected]>2017-01-03 15:31:03 -0800
commit0897c196e12627ef8e5eca99bada9027dfe9baaa (patch)
tree55b26cc538b35c712eca27f20e00d0fe1cc58b6e
parentMerge pull request #541 from bluejekyll/master (diff)
parentAdd X509::stack_from_pem (diff)
downloadrust-openssl-0897c196e12627ef8e5eca99bada9027dfe9baaa.tar.xz
rust-openssl-0897c196e12627ef8e5eca99bada9027dfe9baaa.zip
Merge pull request #547 from sfackler/x509-stack
Add X509::stack_from_pem
-rw-r--r--openssl-sys/src/lib.rs5
-rw-r--r--openssl/src/x509/mod.rs30
-rw-r--r--openssl/src/x509/tests.rs14
-rw-r--r--openssl/test/certs.pem40
4 files changed, 88 insertions, 1 deletions
diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs
index 9b733402..80cfc47e 100644
--- a/openssl-sys/src/lib.rs
+++ b/openssl-sys/src/lib.rs
@@ -126,6 +126,9 @@ pub const BIO_FLAGS_SHOULD_RETRY: c_int = 0x08;
pub const CRYPTO_LOCK: c_int = 1;
+pub const ERR_LIB_PEM: c_int = 9;
+pub const PEM_R_NO_START_LINE: c_int = 108;
+
pub const EVP_MAX_MD_SIZE: c_uint = 64;
pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption;
pub const EVP_PKEY_HMAC: c_int = NID_hmac;
@@ -1429,10 +1432,12 @@ extern {
pub fn EC_POINT_cmp(group: *const EC_GROUP, a: *const EC_POINT, b: *const EC_POINT, ctx: *mut BN_CTX) -> c_int;
pub fn EC_POINT_free(point: *mut EC_POINT);
+ pub fn ERR_peek_last_error() -> c_ulong;
pub fn ERR_get_error() -> c_ulong;
pub fn ERR_lib_error_string(err: c_ulong) -> *const c_char;
pub fn ERR_func_error_string(err: c_ulong) -> *const c_char;
pub fn ERR_reason_error_string(err: c_ulong) -> *const c_char;
+ pub fn ERR_clear_error();
pub fn EVP_md5() -> *const EVP_MD;
pub fn EVP_ripemd160() -> *const EVP_MD;
diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs
index 68652f8e..d90cee22 100644
--- a/openssl/src/x509/mod.rs
+++ b/openssl/src/x509/mod.rs
@@ -433,6 +433,36 @@ impl ToOwned for X509Ref {
impl X509 {
from_pem!(X509, ffi::PEM_read_bio_X509);
from_der!(X509, ffi::d2i_X509);
+
+ /// Deserializes a list of PEM-formatted certificates.
+ pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> {
+ unsafe {
+ ffi::init();
+ let bio = try!(MemBioSlice::new(pem));
+
+ let mut certs = vec![];
+ loop {
+ let r = ffi::PEM_read_bio_X509(bio.as_ptr(),
+ ptr::null_mut(),
+ None,
+ ptr::null_mut());
+ if r.is_null() {
+ let err = ffi::ERR_peek_last_error();
+ if ffi::ERR_GET_LIB(err) == ffi::ERR_LIB_PEM
+ && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE {
+ ffi::ERR_clear_error();
+ break;
+ }
+
+ return Err(ErrorStack::get());
+ } else {
+ certs.push(X509(r));
+ }
+ }
+
+ Ok(certs)
+ }
+ }
}
impl Clone for X509 {
diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs
index 16ad661d..0843b19f 100644
--- a/openssl/src/x509/tests.rs
+++ b/openssl/src/x509/tests.rs
@@ -1,4 +1,4 @@
-use hex::FromHex;
+use hex::{FromHex, ToHex};
use hash::MessageDigest;
use pkey::PKey;
@@ -174,3 +174,15 @@ fn test_subject_alt_name_iter() {
Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..]));
assert!(subject_alt_names_iter.next().is_none());
}
+
+#[test]
+fn test_stack_from_pem() {
+ let certs = include_bytes!("../../test/certs.pem");
+ let certs = X509::stack_from_pem(certs).unwrap();
+
+ assert_eq!(certs.len(), 2);
+ assert_eq!(certs[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
+ "59172d9313e84459bcff27f967e79e6e9217e584");
+ assert_eq!(certs[1].fingerprint(MessageDigest::sha1()).unwrap().to_hex(),
+ "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875");
+}
diff --git a/openssl/test/certs.pem b/openssl/test/certs.pem
new file mode 100644
index 00000000..9d351662
--- /dev/null
+++ b/openssl/test/certs.pem
@@ -0,0 +1,40 @@
+-----BEGIN CERTIFICATE-----
+MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
+VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
+cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
+A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
+IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
+3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
+mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
+TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
+ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
+euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
+hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
+6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
+wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
+oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
+dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
+HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G
+ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV
+eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr
+7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92
+aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc
+klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN
+XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn
+BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv
+Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3
+AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy
+OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3
+mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9
+GA==
+-----END CERTIFICATE-----