Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add reading X509 certificate extensions #2032

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions openssl/src/x509/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Option<&X509ExtensionRef>, 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(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm kind of not sure if cvt_p is necessary here or whether returned null pointer can just be converted into None (that'd remove the Result from function signature, making it simpler). The docs doesn't seem to be conclusive on this matter: 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<Option<&X509ExtensionRef>, 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<Stack<GeneralName>> {
Expand Down Expand Up @@ -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`.
Expand Down
20 changes: 20 additions & 0 deletions openssl/test/extensions.pem
Original file line number Diff line number Diff line change
@@ -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-----