1use cfg_if::cfg_if;
45use foreign_types::{ForeignType, ForeignTypeRef};
46use std::mem;
47
48use crate::error::ErrorStack;
49#[cfg(not(any(boringssl, awslc)))]
50use crate::ssl::SslFiletype;
51#[cfg(ossl300)]
52use crate::stack::Stack;
53use crate::stack::StackRef;
54use crate::util::ForeignTypeRefExt;
55use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
56use crate::x509::{X509Object, X509PurposeId, X509};
57use crate::{cvt, cvt_p};
58use openssl_macros::corresponds;
59#[cfg(not(any(boringssl, awslc)))]
60use std::ffi::CString;
61#[cfg(not(any(boringssl, awslc)))]
62use std::path::Path;
63
64foreign_type_and_impl_send_sync! {
65 type CType = ffi::X509_STORE;
66 fn drop = ffi::X509_STORE_free;
67
68 pub struct X509StoreBuilder;
70 pub struct X509StoreBuilderRef;
72}
73
74impl X509StoreBuilder {
75 #[corresponds(X509_STORE_new)]
79 pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
80 unsafe {
81 ffi::init();
82
83 cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
84 }
85 }
86
87 pub fn build(self) -> X509Store {
89 let store = X509Store(self.0);
90 mem::forget(self);
91 store
92 }
93}
94
95impl X509StoreBuilderRef {
96 #[corresponds(X509_STORE_add_cert)]
99 pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
100 unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
101 }
102
103 #[corresponds(X509_STORE_set_default_paths)]
109 pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
110 unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
111 }
112
113 #[corresponds(X509_STORE_add_lookup)]
115 pub fn add_lookup<T>(
116 &mut self,
117 method: &'static X509LookupMethodRef<T>,
118 ) -> Result<&mut X509LookupRef<T>, ErrorStack> {
119 let lookup = unsafe { ffi::X509_STORE_add_lookup(self.as_ptr(), method.as_ptr()) };
120 cvt_p(lookup).map(|ptr| unsafe { X509LookupRef::from_ptr_mut(ptr) })
121 }
122
123 #[corresponds(X509_STORE_set_flags)]
125 pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
126 unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) }
127 }
128
129 #[corresponds(X509_STORE_set_purpose)]
132 pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> {
133 unsafe { cvt(ffi::X509_STORE_set_purpose(self.as_ptr(), purpose.as_raw())).map(|_| ()) }
134 }
135
136 #[corresponds[X509_STORE_set1_param]]
138 pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> {
139 unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) }
140 }
141}
142
143generic_foreign_type_and_impl_send_sync! {
144 type CType = ffi::X509_LOOKUP;
145 fn drop = ffi::X509_LOOKUP_free;
146
147 pub struct X509Lookup<T>;
149 pub struct X509LookupRef<T>;
151}
152
153pub struct HashDir;
158
159impl X509Lookup<HashDir> {
160 #[corresponds(X509_LOOKUP_hash_dir)]
165 pub fn hash_dir() -> &'static X509LookupMethodRef<HashDir> {
166 unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_hash_dir()) }
167 }
168}
169
170#[cfg(not(any(boringssl, awslc)))]
171impl X509LookupRef<HashDir> {
172 #[corresponds(X509_LOOKUP_add_dir)]
175 pub fn add_dir(&mut self, name: &str, file_type: SslFiletype) -> Result<(), ErrorStack> {
176 let name = CString::new(name).unwrap();
177 unsafe {
178 cvt(ffi::X509_LOOKUP_add_dir(
179 self.as_ptr(),
180 name.as_ptr(),
181 file_type.as_raw(),
182 ))
183 .map(|_| ())
184 }
185 }
186}
187
188pub struct File;
192
193impl X509Lookup<File> {
194 #[corresponds(X509_LOOKUP_file)]
197 pub fn file() -> &'static X509LookupMethodRef<File> {
198 unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_file()) }
199 }
200}
201
202#[cfg(not(any(boringssl, awslc)))]
203impl X509LookupRef<File> {
204 #[corresponds(X509_load_cert_file)]
206 pub fn load_cert_file<P: AsRef<Path>>(
208 &mut self,
209 file: P,
210 file_type: SslFiletype,
211 ) -> Result<(), ErrorStack> {
212 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
213 unsafe {
214 cvt(ffi::X509_load_cert_file(
215 self.as_ptr(),
216 file.as_ptr(),
217 file_type.as_raw(),
218 ))
219 .map(|_| ())
220 }
221 }
222
223 #[corresponds(X509_load_crl_file)]
225 pub fn load_crl_file<P: AsRef<Path>>(
226 &mut self,
227 file: P,
228 file_type: SslFiletype,
229 ) -> Result<i32, ErrorStack> {
230 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
231 unsafe {
232 cvt(ffi::X509_load_crl_file(
233 self.as_ptr(),
234 file.as_ptr(),
235 file_type.as_raw(),
236 ))
237 }
238 }
239}
240
241generic_foreign_type_and_impl_send_sync! {
242 type CType = ffi::X509_LOOKUP_METHOD;
243 fn drop = X509_LOOKUP_meth_free;
244
245 pub struct X509LookupMethod<T>;
247 pub struct X509LookupMethodRef<T>;
249}
250
251foreign_type_and_impl_send_sync! {
252 type CType = ffi::X509_STORE;
253 fn drop = ffi::X509_STORE_free;
254
255 pub struct X509Store;
257 pub struct X509StoreRef;
259}
260
261impl X509StoreRef {
262 #[deprecated(
268 note = "This method is unsound, and will be removed in a future version of rust-openssl. X509StoreRef::all_certificates should be used instead."
269 )]
270 #[corresponds(X509_STORE_get0_objects)]
271 pub fn objects(&self) -> &StackRef<X509Object> {
272 unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
273 }
274
275 #[corresponds(X509_STORE_get1_all_certs)]
277 #[cfg(ossl300)]
278 pub fn all_certificates(&self) -> Stack<X509> {
279 unsafe { Stack::from_ptr(ffi::X509_STORE_get1_all_certs(self.as_ptr())) }
280 }
281}
282
283cfg_if! {
284 if #[cfg(any(boringssl, ossl110, libressl, awslc))] {
285 use ffi::X509_STORE_get0_objects;
286 } else {
287 #[allow(bad_style)]
288 unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT {
289 (*x).objs
290 }
291 }
292}
293
294cfg_if! {
295 if #[cfg(ossl110)] {
296 use ffi::X509_LOOKUP_meth_free;
297 } else {
298 #[allow(bad_style)]
299 unsafe fn X509_LOOKUP_meth_free(_x: *mut ffi::X509_LOOKUP_METHOD) {}
300 }
301}