1 //! Describe a context in which to verify an `X509` certificate.
2 //!
3 //! The `X509` certificate store holds trusted CA certificates used to verify
4 //! peer certificates.
5 //!
6 //! # Example
7 //!
8 //! ```rust
9 //!
10 //! extern crate openssl;
11 //!
12 //! use openssl::x509::store::{X509StoreBuilder, X509Store};
13 //! use openssl::x509::{X509, X509Name};
14 //! use openssl::pkey::PKey;
15 //! use openssl::hash::MessageDigest;
16 //! use openssl::rsa::Rsa;
17 //! use openssl::nid::Nid;
18 //!
19 //! fn main() {
20 //!     let rsa = Rsa::generate(2048).unwrap();
21 //!     let pkey = PKey::from_rsa(rsa).unwrap();
22 //!
23 //!     let mut name = X509Name::builder().unwrap();
24 //!     name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com").unwrap();
25 //!     let name = name.build();
26 //!
27 //!     let mut builder = X509::builder().unwrap();
28 //!     builder.set_version(2).unwrap();
29 //!     builder.set_subject_name(&name).unwrap();
30 //!     builder.set_issuer_name(&name).unwrap();
31 //!     builder.set_pubkey(&pkey).unwrap();
32 //!     builder.sign(&pkey, MessageDigest::sha256()).unwrap();
33 //!
34 //!     let certificate: X509 = builder.build();
35 //!
36 //!     let mut builder = X509StoreBuilder::new().unwrap();
37 //!     let _ = builder.add_cert(certificate);
38 //!
39 //!     let store: X509Store = builder.build();
40 //! }
41 //! ```
42 
43 use ffi;
44 use foreign_types::ForeignTypeRef;
45 use std::mem;
46 
47 use error::ErrorStack;
48 use stack::StackRef;
49 use x509::{X509Object, X509};
50 use {cvt, cvt_p};
51 
52 foreign_type_and_impl_send_sync! {
53     type CType = ffi::X509_STORE;
54     fn drop = ffi::X509_STORE_free;
55 
56     /// A builder type used to construct an `X509Store`.
57     pub struct X509StoreBuilder;
58     /// Reference to an `X509StoreBuilder`.
59     pub struct X509StoreBuilderRef;
60 }
61 
62 impl X509StoreBuilder {
63     /// Returns a builder for a certificate store.
64     ///
65     /// The store is initially empty.
new() -> Result<X509StoreBuilder, ErrorStack>66     pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
67         unsafe {
68             ffi::init();
69 
70             cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
71         }
72     }
73 
74     /// Constructs the `X509Store`.
build(self) -> X509Store75     pub fn build(self) -> X509Store {
76         let store = X509Store(self.0);
77         mem::forget(self);
78         store
79     }
80 }
81 
82 impl X509StoreBuilderRef {
83     /// Adds a certificate to the certificate store.
84     // FIXME should take an &X509Ref
add_cert(&mut self, cert: X509) -> Result<(), ErrorStack>85     pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
86         unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
87     }
88 
89     /// Load certificates from their default locations.
90     ///
91     /// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`
92     /// environment variables if present, or defaults specified at OpenSSL
93     /// build time otherwise.
set_default_paths(&mut self) -> Result<(), ErrorStack>94     pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
95         unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
96     }
97 }
98 
99 foreign_type_and_impl_send_sync! {
100     type CType = ffi::X509_STORE;
101     fn drop = ffi::X509_STORE_free;
102 
103     /// A certificate store to hold trusted `X509` certificates.
104     pub struct X509Store;
105     /// Reference to an `X509Store`.
106     pub struct X509StoreRef;
107 }
108 
109 impl X509StoreRef {
110     /// Get a reference to the cache of certificates in this store.
objects(&self) -> &StackRef<X509Object>111     pub fn objects(&self) -> &StackRef<X509Object> {
112         unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
113     }
114 }
115 
116 cfg_if! {
117     if #[cfg(any(ossl110, libressl270))] {
118         use ffi::X509_STORE_get0_objects;
119     } else {
120         #[allow(bad_style)]
121         unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT {
122             (*x).objs
123         }
124     }
125 }
126