192f3ab15Sopenharmony_ci//! Describe a context in which to verify an `X509` certificate. 292f3ab15Sopenharmony_ci//! 392f3ab15Sopenharmony_ci//! The `X509` certificate store holds trusted CA certificates used to verify 492f3ab15Sopenharmony_ci//! peer certificates. 592f3ab15Sopenharmony_ci//! 692f3ab15Sopenharmony_ci//! # Example 792f3ab15Sopenharmony_ci//! 892f3ab15Sopenharmony_ci//! ```rust 992f3ab15Sopenharmony_ci//! use openssl::x509::store::{X509StoreBuilder, X509Store}; 1092f3ab15Sopenharmony_ci//! use openssl::x509::{X509, X509Name}; 1192f3ab15Sopenharmony_ci//! use openssl::asn1::Asn1Time; 1292f3ab15Sopenharmony_ci//! use openssl::pkey::PKey; 1392f3ab15Sopenharmony_ci//! use openssl::hash::MessageDigest; 1492f3ab15Sopenharmony_ci//! use openssl::rsa::Rsa; 1592f3ab15Sopenharmony_ci//! use openssl::nid::Nid; 1692f3ab15Sopenharmony_ci//! 1792f3ab15Sopenharmony_ci//! let rsa = Rsa::generate(2048).unwrap(); 1892f3ab15Sopenharmony_ci//! let pkey = PKey::from_rsa(rsa).unwrap(); 1992f3ab15Sopenharmony_ci//! 2092f3ab15Sopenharmony_ci//! let mut name = X509Name::builder().unwrap(); 2192f3ab15Sopenharmony_ci//! name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com").unwrap(); 2292f3ab15Sopenharmony_ci//! let name = name.build(); 2392f3ab15Sopenharmony_ci//! 2492f3ab15Sopenharmony_ci//! // Sep 27th, 2016 2592f3ab15Sopenharmony_ci//! let sample_time = Asn1Time::from_unix(1474934400).unwrap(); 2692f3ab15Sopenharmony_ci//! 2792f3ab15Sopenharmony_ci//! let mut builder = X509::builder().unwrap(); 2892f3ab15Sopenharmony_ci//! builder.set_version(2).unwrap(); 2992f3ab15Sopenharmony_ci//! builder.set_subject_name(&name).unwrap(); 3092f3ab15Sopenharmony_ci//! builder.set_issuer_name(&name).unwrap(); 3192f3ab15Sopenharmony_ci//! builder.set_pubkey(&pkey).unwrap(); 3292f3ab15Sopenharmony_ci//! builder.set_not_before(&sample_time); 3392f3ab15Sopenharmony_ci//! builder.set_not_after(&sample_time); 3492f3ab15Sopenharmony_ci//! builder.sign(&pkey, MessageDigest::sha256()).unwrap(); 3592f3ab15Sopenharmony_ci//! 3692f3ab15Sopenharmony_ci//! let certificate: X509 = builder.build(); 3792f3ab15Sopenharmony_ci//! 3892f3ab15Sopenharmony_ci//! let mut builder = X509StoreBuilder::new().unwrap(); 3992f3ab15Sopenharmony_ci//! let _ = builder.add_cert(certificate); 4092f3ab15Sopenharmony_ci//! 4192f3ab15Sopenharmony_ci//! let store: X509Store = builder.build(); 4292f3ab15Sopenharmony_ci//! ``` 4392f3ab15Sopenharmony_ci 4492f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 4592f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef}; 4692f3ab15Sopenharmony_ciuse std::mem; 4792f3ab15Sopenharmony_ci 4892f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 4992f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 5092f3ab15Sopenharmony_ciuse crate::ssl::SslFiletype; 5192f3ab15Sopenharmony_ciuse crate::stack::{Stack, StackRef}; 5292f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl261))] 5392f3ab15Sopenharmony_ciuse crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef}; 5492f3ab15Sopenharmony_ciuse crate::x509::{X509Object, X509PurposeId, X509}; 5592f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p}; 5692f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 5792f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 5892f3ab15Sopenharmony_ciuse std::ffi::CString; 5992f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 6092f3ab15Sopenharmony_ciuse std::path::Path; 6192f3ab15Sopenharmony_ci 6292f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 6392f3ab15Sopenharmony_ci type CType = ffi::X509_STORE; 6492f3ab15Sopenharmony_ci fn drop = ffi::X509_STORE_free; 6592f3ab15Sopenharmony_ci 6692f3ab15Sopenharmony_ci /// A builder type used to construct an `X509Store`. 6792f3ab15Sopenharmony_ci pub struct X509StoreBuilder; 6892f3ab15Sopenharmony_ci /// A reference to an [`X509StoreBuilder`]. 6992f3ab15Sopenharmony_ci pub struct X509StoreBuilderRef; 7092f3ab15Sopenharmony_ci} 7192f3ab15Sopenharmony_ci 7292f3ab15Sopenharmony_ciimpl X509StoreBuilder { 7392f3ab15Sopenharmony_ci /// Returns a builder for a certificate store. 7492f3ab15Sopenharmony_ci /// 7592f3ab15Sopenharmony_ci /// The store is initially empty. 7692f3ab15Sopenharmony_ci #[corresponds(X509_STORE_new)] 7792f3ab15Sopenharmony_ci pub fn new() -> Result<X509StoreBuilder, ErrorStack> { 7892f3ab15Sopenharmony_ci unsafe { 7992f3ab15Sopenharmony_ci ffi::init(); 8092f3ab15Sopenharmony_ci 8192f3ab15Sopenharmony_ci cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder) 8292f3ab15Sopenharmony_ci } 8392f3ab15Sopenharmony_ci } 8492f3ab15Sopenharmony_ci 8592f3ab15Sopenharmony_ci /// Constructs the `X509Store`. 8692f3ab15Sopenharmony_ci pub fn build(self) -> X509Store { 8792f3ab15Sopenharmony_ci let store = X509Store(self.0); 8892f3ab15Sopenharmony_ci mem::forget(self); 8992f3ab15Sopenharmony_ci store 9092f3ab15Sopenharmony_ci } 9192f3ab15Sopenharmony_ci} 9292f3ab15Sopenharmony_ci 9392f3ab15Sopenharmony_ciimpl X509StoreBuilderRef { 9492f3ab15Sopenharmony_ci /// Adds a certificate to the certificate store. 9592f3ab15Sopenharmony_ci // FIXME should take an &X509Ref 9692f3ab15Sopenharmony_ci #[corresponds(X509_STORE_add_cert)] 9792f3ab15Sopenharmony_ci pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { 9892f3ab15Sopenharmony_ci unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) } 9992f3ab15Sopenharmony_ci } 10092f3ab15Sopenharmony_ci 10192f3ab15Sopenharmony_ci /// Load certificates from their default locations. 10292f3ab15Sopenharmony_ci /// 10392f3ab15Sopenharmony_ci /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR` 10492f3ab15Sopenharmony_ci /// environment variables if present, or defaults specified at OpenSSL 10592f3ab15Sopenharmony_ci /// build time otherwise. 10692f3ab15Sopenharmony_ci #[corresponds(X509_STORE_set_default_paths)] 10792f3ab15Sopenharmony_ci pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> { 10892f3ab15Sopenharmony_ci unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) } 10992f3ab15Sopenharmony_ci } 11092f3ab15Sopenharmony_ci 11192f3ab15Sopenharmony_ci /// Adds a lookup method to the store. 11292f3ab15Sopenharmony_ci #[corresponds(X509_STORE_add_lookup)] 11392f3ab15Sopenharmony_ci pub fn add_lookup<T>( 11492f3ab15Sopenharmony_ci &mut self, 11592f3ab15Sopenharmony_ci method: &'static X509LookupMethodRef<T>, 11692f3ab15Sopenharmony_ci ) -> Result<&mut X509LookupRef<T>, ErrorStack> { 11792f3ab15Sopenharmony_ci let lookup = unsafe { ffi::X509_STORE_add_lookup(self.as_ptr(), method.as_ptr()) }; 11892f3ab15Sopenharmony_ci cvt_p(lookup).map(|ptr| unsafe { X509LookupRef::from_ptr_mut(ptr) }) 11992f3ab15Sopenharmony_ci } 12092f3ab15Sopenharmony_ci 12192f3ab15Sopenharmony_ci /// Sets certificate chain validation related flags. 12292f3ab15Sopenharmony_ci #[corresponds(X509_STORE_set_flags)] 12392f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 12492f3ab15Sopenharmony_ci pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { 12592f3ab15Sopenharmony_ci unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) } 12692f3ab15Sopenharmony_ci } 12792f3ab15Sopenharmony_ci 12892f3ab15Sopenharmony_ci /// Sets the certificate purpose. 12992f3ab15Sopenharmony_ci /// The purpose value can be obtained by `X509PurposeRef::get_by_sname()` 13092f3ab15Sopenharmony_ci #[corresponds(X509_STORE_set_purpose)] 13192f3ab15Sopenharmony_ci pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> { 13292f3ab15Sopenharmony_ci unsafe { cvt(ffi::X509_STORE_set_purpose(self.as_ptr(), purpose.as_raw())).map(|_| ()) } 13392f3ab15Sopenharmony_ci } 13492f3ab15Sopenharmony_ci 13592f3ab15Sopenharmony_ci /// Sets certificate chain validation related parameters. 13692f3ab15Sopenharmony_ci #[corresponds[X509_STORE_set1_param]] 13792f3ab15Sopenharmony_ci #[cfg(any(ossl102, libressl261))] 13892f3ab15Sopenharmony_ci pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> { 13992f3ab15Sopenharmony_ci unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) } 14092f3ab15Sopenharmony_ci } 14192f3ab15Sopenharmony_ci} 14292f3ab15Sopenharmony_ci 14392f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! { 14492f3ab15Sopenharmony_ci type CType = ffi::X509_LOOKUP; 14592f3ab15Sopenharmony_ci fn drop = ffi::X509_LOOKUP_free; 14692f3ab15Sopenharmony_ci 14792f3ab15Sopenharmony_ci /// Information used by an `X509Store` to look up certificates and CRLs. 14892f3ab15Sopenharmony_ci pub struct X509Lookup<T>; 14992f3ab15Sopenharmony_ci /// A reference to an [`X509Lookup`]. 15092f3ab15Sopenharmony_ci pub struct X509LookupRef<T>; 15192f3ab15Sopenharmony_ci} 15292f3ab15Sopenharmony_ci 15392f3ab15Sopenharmony_ci/// Marker type corresponding to the [`X509_LOOKUP_hash_dir`] lookup method. 15492f3ab15Sopenharmony_ci/// 15592f3ab15Sopenharmony_ci/// [`X509_LOOKUP_hash_dir`]: https://www.openssl.org/docs/manmaster/crypto/X509_LOOKUP_hash_dir.html 15692f3ab15Sopenharmony_ci// FIXME should be an enum 15792f3ab15Sopenharmony_cipub struct HashDir; 15892f3ab15Sopenharmony_ci 15992f3ab15Sopenharmony_ciimpl X509Lookup<HashDir> { 16092f3ab15Sopenharmony_ci /// Lookup method that loads certificates and CRLs on demand and caches 16192f3ab15Sopenharmony_ci /// them in memory once they are loaded. It also checks for newer CRLs upon 16292f3ab15Sopenharmony_ci /// each lookup, so that newer CRLs are used as soon as they appear in the 16392f3ab15Sopenharmony_ci /// directory. 16492f3ab15Sopenharmony_ci #[corresponds(X509_LOOKUP_hash_dir)] 16592f3ab15Sopenharmony_ci pub fn hash_dir() -> &'static X509LookupMethodRef<HashDir> { 16692f3ab15Sopenharmony_ci unsafe { X509LookupMethodRef::from_ptr(ffi::X509_LOOKUP_hash_dir()) } 16792f3ab15Sopenharmony_ci } 16892f3ab15Sopenharmony_ci} 16992f3ab15Sopenharmony_ci 17092f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 17192f3ab15Sopenharmony_ciimpl X509LookupRef<HashDir> { 17292f3ab15Sopenharmony_ci /// Specifies a directory from which certificates and CRLs will be loaded 17392f3ab15Sopenharmony_ci /// on-demand. Must be used with `X509Lookup::hash_dir`. 17492f3ab15Sopenharmony_ci #[corresponds(X509_LOOKUP_add_dir)] 17592f3ab15Sopenharmony_ci pub fn add_dir(&mut self, name: &str, file_type: SslFiletype) -> Result<(), ErrorStack> { 17692f3ab15Sopenharmony_ci let name = CString::new(name).unwrap(); 17792f3ab15Sopenharmony_ci unsafe { 17892f3ab15Sopenharmony_ci cvt(ffi::X509_LOOKUP_add_dir( 17992f3ab15Sopenharmony_ci self.as_ptr(), 18092f3ab15Sopenharmony_ci name.as_ptr(), 18192f3ab15Sopenharmony_ci file_type.as_raw(), 18292f3ab15Sopenharmony_ci )) 18392f3ab15Sopenharmony_ci .map(|_| ()) 18492f3ab15Sopenharmony_ci } 18592f3ab15Sopenharmony_ci } 18692f3ab15Sopenharmony_ci} 18792f3ab15Sopenharmony_ci 18892f3ab15Sopenharmony_ci/// Marker type corresponding to the [`X509_LOOKUP_file`] lookup method. 18992f3ab15Sopenharmony_ci/// 19092f3ab15Sopenharmony_ci/// [`X509_LOOKUP_file`]: https://www.openssl.org/docs/man1.1.1/man3/X509_LOOKUP_file.html 19192f3ab15Sopenharmony_cipub struct File; 19292f3ab15Sopenharmony_ci 19392f3ab15Sopenharmony_ciimpl X509Lookup<File> { 19492f3ab15Sopenharmony_ci /// Lookup method loads all the certificates or CRLs present in a file 19592f3ab15Sopenharmony_ci /// into memory at the time the file is added as a lookup source. 19692f3ab15Sopenharmony_ci #[corresponds(X509_LOOKUP_file)] 19792f3ab15Sopenharmony_ci pub fn file() -> &'static X509LookupMethodRef<File> { 19892f3ab15Sopenharmony_ci unsafe { X509LookupMethodRef::from_ptr(ffi::X509_LOOKUP_file()) } 19992f3ab15Sopenharmony_ci } 20092f3ab15Sopenharmony_ci} 20192f3ab15Sopenharmony_ci 20292f3ab15Sopenharmony_ci#[cfg(not(boringssl))] 20392f3ab15Sopenharmony_ciimpl X509LookupRef<File> { 20492f3ab15Sopenharmony_ci /// Specifies a file from which certificates will be loaded 20592f3ab15Sopenharmony_ci #[corresponds(X509_load_cert_file)] 20692f3ab15Sopenharmony_ci // FIXME should return 'Result<i32, ErrorStack' like load_crl_file 20792f3ab15Sopenharmony_ci pub fn load_cert_file<P: AsRef<Path>>( 20892f3ab15Sopenharmony_ci &mut self, 20992f3ab15Sopenharmony_ci file: P, 21092f3ab15Sopenharmony_ci file_type: SslFiletype, 21192f3ab15Sopenharmony_ci ) -> Result<(), ErrorStack> { 21292f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 21392f3ab15Sopenharmony_ci unsafe { 21492f3ab15Sopenharmony_ci cvt(ffi::X509_load_cert_file( 21592f3ab15Sopenharmony_ci self.as_ptr(), 21692f3ab15Sopenharmony_ci file.as_ptr(), 21792f3ab15Sopenharmony_ci file_type.as_raw(), 21892f3ab15Sopenharmony_ci )) 21992f3ab15Sopenharmony_ci .map(|_| ()) 22092f3ab15Sopenharmony_ci } 22192f3ab15Sopenharmony_ci } 22292f3ab15Sopenharmony_ci 22392f3ab15Sopenharmony_ci /// Specifies a file from which certificate revocation lists will be loaded 22492f3ab15Sopenharmony_ci #[corresponds(X509_load_crl_file)] 22592f3ab15Sopenharmony_ci pub fn load_crl_file<P: AsRef<Path>>( 22692f3ab15Sopenharmony_ci &mut self, 22792f3ab15Sopenharmony_ci file: P, 22892f3ab15Sopenharmony_ci file_type: SslFiletype, 22992f3ab15Sopenharmony_ci ) -> Result<i32, ErrorStack> { 23092f3ab15Sopenharmony_ci let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 23192f3ab15Sopenharmony_ci unsafe { 23292f3ab15Sopenharmony_ci cvt(ffi::X509_load_crl_file( 23392f3ab15Sopenharmony_ci self.as_ptr(), 23492f3ab15Sopenharmony_ci file.as_ptr(), 23592f3ab15Sopenharmony_ci file_type.as_raw(), 23692f3ab15Sopenharmony_ci )) 23792f3ab15Sopenharmony_ci } 23892f3ab15Sopenharmony_ci } 23992f3ab15Sopenharmony_ci} 24092f3ab15Sopenharmony_ci 24192f3ab15Sopenharmony_cigeneric_foreign_type_and_impl_send_sync! { 24292f3ab15Sopenharmony_ci type CType = ffi::X509_LOOKUP_METHOD; 24392f3ab15Sopenharmony_ci fn drop = X509_LOOKUP_meth_free; 24492f3ab15Sopenharmony_ci 24592f3ab15Sopenharmony_ci /// Method used to look up certificates and CRLs. 24692f3ab15Sopenharmony_ci pub struct X509LookupMethod<T>; 24792f3ab15Sopenharmony_ci /// A reference to an [`X509LookupMethod`]. 24892f3ab15Sopenharmony_ci pub struct X509LookupMethodRef<T>; 24992f3ab15Sopenharmony_ci} 25092f3ab15Sopenharmony_ci 25192f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 25292f3ab15Sopenharmony_ci type CType = ffi::X509_STORE; 25392f3ab15Sopenharmony_ci fn drop = ffi::X509_STORE_free; 25492f3ab15Sopenharmony_ci 25592f3ab15Sopenharmony_ci /// A certificate store to hold trusted `X509` certificates. 25692f3ab15Sopenharmony_ci pub struct X509Store; 25792f3ab15Sopenharmony_ci /// Reference to an `X509Store`. 25892f3ab15Sopenharmony_ci pub struct X509StoreRef; 25992f3ab15Sopenharmony_ci} 26092f3ab15Sopenharmony_ci 26192f3ab15Sopenharmony_ciimpl X509StoreRef { 26292f3ab15Sopenharmony_ci /// Get a reference to the cache of certificates in this store. 26392f3ab15Sopenharmony_ci /// 26492f3ab15Sopenharmony_ci /// This method is deprecated. It is **unsound** and will be removed in a 26592f3ab15Sopenharmony_ci /// future version of rust-openssl. `X509StoreRef::all_certificates` 26692f3ab15Sopenharmony_ci /// should be used instead. 26792f3ab15Sopenharmony_ci #[deprecated( 26892f3ab15Sopenharmony_ci note = "This method is unsound, and will be removed in a future version of rust-openssl. X509StoreRef::all_certificates should be used instead." 26992f3ab15Sopenharmony_ci )] 27092f3ab15Sopenharmony_ci #[corresponds(X509_STORE_get0_objects)] 27192f3ab15Sopenharmony_ci pub fn objects(&self) -> &StackRef<X509Object> { 27292f3ab15Sopenharmony_ci unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) } 27392f3ab15Sopenharmony_ci } 27492f3ab15Sopenharmony_ci 27592f3ab15Sopenharmony_ci /// Returns a stack of all the certificates in this store. 27692f3ab15Sopenharmony_ci #[corresponds(X509_STORE_get1_all_certs)] 27792f3ab15Sopenharmony_ci #[cfg(ossl300)] 27892f3ab15Sopenharmony_ci pub fn all_certificates(&self) -> Stack<X509> { 27992f3ab15Sopenharmony_ci unsafe { Stack::from_ptr(ffi::X509_STORE_get1_all_certs(self.as_ptr())) } 28092f3ab15Sopenharmony_ci } 28192f3ab15Sopenharmony_ci} 28292f3ab15Sopenharmony_ci 28392f3ab15Sopenharmony_cicfg_if! { 28492f3ab15Sopenharmony_ci if #[cfg(any(boringssl, ossl110, libressl270))] { 28592f3ab15Sopenharmony_ci use ffi::X509_STORE_get0_objects; 28692f3ab15Sopenharmony_ci } else { 28792f3ab15Sopenharmony_ci #[allow(bad_style)] 28892f3ab15Sopenharmony_ci unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT { 28992f3ab15Sopenharmony_ci (*x).objs 29092f3ab15Sopenharmony_ci } 29192f3ab15Sopenharmony_ci } 29292f3ab15Sopenharmony_ci} 29392f3ab15Sopenharmony_ci 29492f3ab15Sopenharmony_cicfg_if! { 29592f3ab15Sopenharmony_ci if #[cfg(ossl110)] { 29692f3ab15Sopenharmony_ci use ffi::X509_LOOKUP_meth_free; 29792f3ab15Sopenharmony_ci } else { 29892f3ab15Sopenharmony_ci #[allow(bad_style)] 29992f3ab15Sopenharmony_ci unsafe fn X509_LOOKUP_meth_free(_x: *mut ffi::X509_LOOKUP_METHOD) {} 30092f3ab15Sopenharmony_ci } 30192f3ab15Sopenharmony_ci} 302