diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 05aec9a9c7..618a952c39 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -420,6 +420,67 @@ impl X509Ref { } } + /// Returns this certificate's extensions for the given [Nid]. + /// + /// # Examples + /// + /// ``` + /// use openssl::nid::Nid; + /// use openssl::x509::X509; + /// + /// let cert = X509::from_pem(include_bytes!("../../test/extensions.pem")).unwrap(); + /// let nid = Nid::create(&"1.3.6.1.4.1.41482.5.3", &"fw", &"firmware").unwrap(); + /// let extension = cert.get_ext_by_nid(nid).unwrap().unwrap(); + /// let value = extension.data().as_slice(); + /// assert_eq!(value, [4, 3, 5, 2, 7]); + /// ``` + #[corresponds(X509_get_ext_by_NID)] + pub fn get_ext_by_nid(&self, nid: Nid) -> Result, ErrorStack> { + unsafe { + let loc = ffi::X509_get_ext_by_NID(self.as_ptr(), nid.as_raw(), -1); + Ok(if loc >= 0 { + Some(X509ExtensionRef::from_ptr(cvt_p(ffi::X509_get_ext( + self.as_ptr(), + loc, + ))?)) + } else { + None + }) + } + } + + /// Returns this certificate's extensions for the given [Asn1Object]. + /// + /// # Examples + /// + /// ``` + /// use openssl::asn1::Asn1Object; + /// use openssl::x509::X509; + /// + /// let cert = X509::from_pem(include_bytes!("../../test/extensions.pem")).unwrap(); + /// let obj = Asn1Object::from_str(&"1.3.6.1.4.1.41482.5.3").unwrap(); + /// let extension = cert.get_ext_by_obj(&obj).unwrap().unwrap(); + /// let value = extension.data().as_slice(); + /// assert_eq!(value, [4, 3, 5, 2, 7]); + /// ``` + #[corresponds(X509_get_ext_by_OBJ)] + pub fn get_ext_by_obj( + &self, + obj: &Asn1ObjectRef, + ) -> Result, ErrorStack> { + unsafe { + let loc = ffi::X509_get_ext_by_OBJ(self.as_ptr(), obj.as_ptr(), -1); + Ok(if loc >= 0 { + Some(X509ExtensionRef::from_ptr(cvt_p(ffi::X509_get_ext( + self.as_ptr(), + loc, + ))?)) + } else { + None + }) + } + } + /// Returns this certificate's subject alternative name entries, if they exist. #[corresponds(X509_get_ext_d2i)] pub fn subject_alt_names(&self) -> Option> { @@ -1056,6 +1117,29 @@ impl X509ExtensionRef { to_der, ffi::i2d_X509_EXTENSION } + + /// Returns the field value of an `X509Extension`. + /// + /// # Examples + /// + /// ``` + /// use openssl::asn1::{Asn1Object, Asn1OctetString}; + /// use openssl::x509::X509Extension; + /// + /// let extension = X509Extension::new_from_der(&Asn1Object::from_str("2.999").unwrap(), + /// true, + /// &Asn1OctetString::new_from_bytes(b"\x30\x03\x01\x01\xff").unwrap(), + /// ).unwrap(); + /// let value = extension.data().as_slice(); + /// assert_eq!(value, [48, 3, 1, 1, 255]); + /// ``` + #[corresponds(X509_EXTENSION_get_data)] + pub fn data(&self) -> &Asn1OctetStringRef { + unsafe { + let data = ffi::X509_EXTENSION_get_data(self.as_ptr()); + Asn1OctetStringRef::from_ptr(data) + } + } } /// A builder used to construct an `X509Name`. diff --git a/openssl/test/extensions.pem b/openssl/test/extensions.pem new file mode 100644 index 0000000000..627086f809 --- /dev/null +++ b/openssl/test/extensions.pem @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDOTCCAiGgAwIBAgIJAN1RLZj8pwQyMA0GCSqGSIb3DQEBCwUAMCgxJjAkBgNV +BAMMHVl1YmljbyBPcGVuUEdQIEF0dGVzdGF0aW9uIENBMB4XDTE5MDgwMTAwMDAw +MFoXDTQ2MTIxNzAwMDAwMFowIzEhMB8GA1UEAwwYWXViaWtleSBPUEdQIEF0dGVz +dGF0aW9uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+gnQOA27wOHe +aflJf1R5hNlRM2dJ3Bm8h4HbavsONxgeB2pf17/OwKHtOSl7NznfeiiD1nmIo2k3 +rxOplhxuWBEwkn2mxdvMqClbnsmmiZdASYaqYICjFzAu2HNgjfGOuFOuqfp7Vkut +x+uFZtNpwtTwOrUs3hb3m4BAa7D+u0WoAFHWzhuFPDOYuI/S6pN9nBdZddEvBFAB +XpGJdv9pOGAecymzNRaTYuG9nsI5hB7Buw8fDXfy/qcqX1x6/jtAnpwEU7JlzJki +Ek75ETfLKlQQmoBLPk9TPW1Z9Dfk4Q191mOjW5kLdxJy65/PHAyqBzqO1vg+6475 +TXAHjLUu1wIDAQABo2swaTATBgorBgEEAYLECgUDBAUEAwUCBzAdBgNVHQ4EFgQU +sRtH7kxAgfcF53Jq2bwMf/En5scwHwYDVR0jBBgwFoAU+/zJb8n0p2mpdkSR93HP +JmUuEkowEgYDVR0TAQH/BAgwBgEB/wIBADANBgkqhkiG9w0BAQsFAAOCAQEAYZA7 +EP9WIF7I/L8FLxeAmeqPW9qgEXNjfwvoS732omeEOK1Y465/suEXDnMd2GhufgrM +9NFf0djmvGHQWhu+2/1GPlt7LSC3K95ERyjzSZ7rNPw9ITtgG25KG5MoLFmTP5H1 ++AGqopS+dlsGE6iQUJqW53wBxsko3DGp1G7Fy/71tEwP5tomfrQgNxvSrNYHrpSZ +oQdzKypYMI16Z2p/WEJDXoWk0+tA3SlX8fP0X5AxTkOTE7L6R//7NCmkObxBdy2q +EM05C5JASEmkPxkG+d+ArcCSe2jOIwxeWKkCMzCk9kie2f0hCzh1vzJdJJ7GUglf +3MevZb+xsxi0oAS32A== +-----END CERTIFICATE-----