use ffi;
use foreign_types::ForeignTypeRef;
use std::mem;
use error::ErrorStack;
use stack::StackRef;
use x509::{X509Object, X509};
use {cvt, cvt_p};
foreign_type_and_impl_send_sync! {
type CType = ffi::X509_STORE;
fn drop = ffi::X509_STORE_free;
pub struct X509StoreBuilder;
pub struct X509StoreBuilderRef;
}
impl X509StoreBuilder {
pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
unsafe {
ffi::init();
cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
}
}
pub fn build(self) -> X509Store {
let store = X509Store(self.0);
mem::forget(self);
store
}
}
impl X509StoreBuilderRef {
pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
}
pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
}
pub fn add_lookup<T>(
&mut self,
method: &'static X509LookupMethodRef<T>,
) -> Result<&mut X509LookupRef<T>, ErrorStack> {
let lookup = unsafe { ffi::X509_STORE_add_lookup(self.as_ptr(), method.as_ptr()) };
cvt_p(lookup).map(|ptr| unsafe { X509LookupRef::from_ptr_mut(ptr) })
}
}
generic_foreign_type_and_impl_send_sync! {
type CType = ffi::X509_LOOKUP;
fn drop = ffi::X509_LOOKUP_free;
pub struct X509Lookup<T>;
pub struct X509LookupRef<T>;
}
pub struct HashDir;
impl X509Lookup<HashDir> {
pub fn hash_dir() -> &'static X509LookupMethodRef<HashDir> {
unsafe { X509LookupMethodRef::from_ptr(ffi::X509_LOOKUP_hash_dir()) }
}
}
impl X509LookupRef<HashDir> {
pub fn add_dir(
&mut self,
name: &str,
file_type: crate::ssl::SslFiletype,
) -> Result<(), ErrorStack> {
let name = std::ffi::CString::new(name).unwrap();
unsafe {
cvt(ffi::X509_LOOKUP_add_dir(
self.as_ptr(),
name.as_ptr(),
file_type.as_raw(),
))
.map(|_| ())
}
}
}
generic_foreign_type_and_impl_send_sync! {
type CType = ffi::X509_LOOKUP_METHOD;
fn drop = |_method| {
#[cfg(ossl110)]
ffi::X509_LOOKUP_meth_free(_method);
};
pub struct X509LookupMethod<T>;
pub struct X509LookupMethodRef<T>;
}
foreign_type_and_impl_send_sync! {
type CType = ffi::X509_STORE;
fn drop = ffi::X509_STORE_free;
pub struct X509Store;
pub struct X509StoreRef;
}
impl X509StoreRef {
pub fn objects(&self) -> &StackRef<X509Object> {
unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
}
}
cfg_if! {
if #[cfg(any(ossl110, libressl270))] {
use ffi::X509_STORE_get0_objects;
} else {
#[allow(bad_style)]
unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT {
(*x).objs
}
}
}