1use crate::error::ErrorStack;
44use crate::ffi;
45use crate::stack::StackRef;
46use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
47use crate::x509::{X509Object, X509Ref};
48use crate::{cvt, cvt_p};
49use foreign_types::{ForeignType, ForeignTypeRef};
50use openssl_macros::corresponds;
51use std::mem::ManuallyDrop;
52
53foreign_type_and_impl_send_sync! {
54 type CType = ffi::X509_STORE;
55 fn drop = ffi::X509_STORE_free;
56
57 pub struct X509StoreBuilder;
59}
60
61impl X509StoreBuilder {
62 pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
66 unsafe {
67 ffi::init();
68
69 cvt_p(ffi::X509_STORE_new()).map(|p| X509StoreBuilder::from_ptr(p))
70 }
71 }
72
73 #[must_use]
75 pub fn build(self) -> X509Store {
76 X509Store(ManuallyDrop::new(self).0)
77 }
78}
79
80impl X509StoreBuilderRef {
81 #[corresponds(X509_STORE_add_cert)]
83 pub fn add_cert(&mut self, cert: impl AsRef<X509Ref>) -> Result<(), ErrorStack> {
84 let cert = cert.as_ref();
85 unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())) }
86 }
87
88 #[corresponds(X509_STORE_set_default_paths)]
94 pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
95 unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())) }
96 }
97
98 #[corresponds(X509_STORE_set_flags)]
100 pub fn set_flags(&mut self, flags: X509VerifyFlags) {
101 unsafe {
102 cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).unwrap();
103 }
104 }
105
106 #[corresponds(X509_STORE_get0_param)]
108 pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef {
109 unsafe { X509VerifyParamRef::from_ptr_mut(ffi::X509_STORE_get0_param(self.as_ptr())) }
110 }
111
112 #[corresponds(X509_STORE_set1_param)]
114 pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> {
115 unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())) }
116 }
117
118 #[cfg(test)]
120 pub fn objects_len(&self) -> usize {
121 unsafe {
122 StackRef::<X509Object>::from_ptr(ffi::X509_STORE_get0_objects(self.as_ptr())).len()
123 }
124 }
125}
126
127foreign_type_and_impl_send_sync! {
128 type CType = ffi::X509_STORE;
129 fn drop = ffi::X509_STORE_free;
130
131 pub struct X509Store;
133}
134
135impl ToOwned for X509StoreRef {
136 type Owned = X509Store;
137
138 fn to_owned(&self) -> X509Store {
139 unsafe {
140 ffi::X509_STORE_up_ref(self.as_ptr());
141 X509Store::from_ptr(self.as_ptr())
142 }
143 }
144}
145
146impl Clone for X509Store {
147 fn clone(&self) -> X509Store {
148 (**self).to_owned()
149 }
150}
151
152impl X509StoreRef {
153 #[deprecated(
160 note = "This method is unsound https://github.com/sfackler/rust-openssl/issues/2096"
161 )]
162 #[corresponds(X509_STORE_get0_objects)]
163 #[must_use]
164 pub fn objects(&self) -> &StackRef<X509Object> {
165 unsafe { StackRef::from_ptr(ffi::X509_STORE_get0_objects(self.as_ptr())) }
166 }
167
168 #[cfg(test)]
170 #[allow(deprecated)]
171 #[must_use]
172 pub fn objects_len(&self) -> usize {
173 self.objects().len()
174 }
175}
176
177#[test]
178#[allow(clippy::redundant_clone)]
179#[should_panic = "Shared X509Store can't be mutated"]
180fn set_cert_store_pevents_mutability() {
181 use crate::ssl::*;
182
183 let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
184 let store = X509StoreBuilder::new().unwrap().build();
185
186 ctx.set_cert_store(store.clone());
187
188 let _aliased_store = ctx.cert_store_mut();
190}