From 8cfb59b9ea9046d26063837c914826a55ad9c3d7 Mon Sep 17 00:00:00 2001 From: Noah <33094578+coolreader18@users.noreply.github.com> Date: Sun, 22 Mar 2020 23:20:59 -0500 Subject: [PATCH] Add a way to get the certificates stored in an X509Store --- openssl-sys/src/x509.rs | 40 +++++++++++++++++++++++++++++++++++++ openssl/src/x509/mod.rs | 42 +++++++++++++++++++++++++++++++++++++++ openssl/src/x509/store.rs | 10 +++++++++- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/openssl-sys/src/x509.rs b/openssl-sys/src/x509.rs index d9f4aae4..a3bd9fb0 100644 --- a/openssl-sys/src/x509.rs +++ b/openssl-sys/src/x509.rs @@ -74,6 +74,32 @@ cfg_if! { stack!(stack_st_X509); +pub type X509_LOOKUP_TYPE = i32; +pub const X509_LU_NONE: X509_LOOKUP_TYPE = 0; +pub const X509_LU_X509: X509_LOOKUP_TYPE = 1; +pub const X509_LU_CRL: X509_LOOKUP_TYPE = 2; + +cfg_if! { + if #[cfg(any(ossl110, libressl270))] { + pub enum X509_OBJECT {} + } else { + #[repr(C)] + pub struct X509_OBJECT { + pub type_: X509_LOOKUP_TYPE, + pub data: X509_OBJECT_data, + } + #[repr(C)] + pub union X509_OBJECT_data { + pub ptr: *mut c_char, + pub x509: *mut X509, + pub crl: *mut X509_CRL, + pub pkey: *mut EVP_PKEY, + } + } +} + +stack!(stack_st_X509_OBJECT); + extern "C" { pub fn X509_verify_cert_error_string(n: c_long) -> *const c_char; @@ -347,3 +373,17 @@ cfg_if! { extern "C" { pub fn X509_verify_cert(ctx: *mut X509_STORE_CTX) -> c_int; } + +extern "C" { + pub fn X509_STORE_get0_objects(ctx: *mut X509_STORE) -> *mut stack_st_X509_OBJECT; + pub fn X509_OBJECT_free(a: *mut X509_OBJECT); +} + +cfg_if! { + if #[cfg(any(ossl110, libressl270))] { + extern "C" { + pub fn X509_OBJECT_get_type(x: *const X509_OBJECT) -> X509_LOOKUP_TYPE; + pub fn X509_OBJECT_get0_X509(x: *const X509_OBJECT) -> *mut X509; + } + } +} diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 45d09f71..b2a5db7e 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1322,6 +1322,32 @@ impl X509AlgorithmRef { } } +foreign_type_and_impl_send_sync! { + type CType = ffi::X509_OBJECT; + fn drop = ffi::X509_OBJECT_free; + + /// An `X509` or an X509 certificate revocation list. + pub struct X509Object; + /// Reference to `X509Object` + pub struct X509ObjectRef; +} + +impl X509ObjectRef { + pub fn x509(&self) -> Option<&X509Ref> { + unsafe { + if X509_OBJECT_get_type(self.as_ptr()) == ffi::X509_LU_X509 { + Some(X509Ref::from_ptr(X509_OBJECT_get0_X509(self.as_ptr()))) + } else { + None + } + } + } +} + +impl Stackable for X509Object { + type StackType = ffi::stack_st_X509_OBJECT; +} + cfg_if! { if #[cfg(any(ossl110, libressl273))] { use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature}; @@ -1402,3 +1428,19 @@ cfg_if! { } } } + +cfg_if! { + if #[cfg(any(ossl110, libressl270))] { + use ffi::{X509_OBJECT_get_type, X509_OBJECT_get0_X509}; + } else { + #[allow(bad_style)] + unsafe fn X509_OBJECT_get_type(x: *mut ffi::X509_OBJECT) -> ffi::X509_LOOKUP_TYPE { + (*x).type_ + } + + #[allow(bad_style)] + unsafe fn X509_OBJECT_get0_X509(x: *mut ffi::X509_OBJECT) -> *mut ffi::X509 { + (*x).data.x509 + } + } +} diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs index f533d9c7..2459a06b 100644 --- a/openssl/src/x509/store.rs +++ b/openssl/src/x509/store.rs @@ -45,7 +45,8 @@ use foreign_types::ForeignTypeRef; use std::mem; use error::ErrorStack; -use x509::X509; +use stack::StackRef; +use x509::{X509Object, X509}; use {cvt, cvt_p}; foreign_type_and_impl_send_sync! { @@ -104,3 +105,10 @@ foreign_type_and_impl_send_sync! { /// Reference to an `X509Store`. pub struct X509StoreRef; } + +impl X509StoreRef { + /// Get a reference to the cache of certificates in this store. + pub fn certs(&self) -> &StackRef { + unsafe { StackRef::from_ptr(ffi::X509_STORE_get0_objects(self.as_ptr())) } + } +}