#![allow(unused)]
#[cfg(feature = "boring")]
use boring::x509::store::{X509Store, X509StoreBuilder};
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
use rustls::RootCertStore;
use super::{Certificate, CertificateInput};
use crate::{Error, Result};
#[cfg(feature = "boring")]
type StoreBuilder = X509StoreBuilder;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
type StoreBuilder = RootCertStore;
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
type StoreBuilder = ();
#[cfg(feature = "boring")]
type StoreType = X509Store;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
type StoreType = RootCertStore;
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
type StoreType = ();
pub fn parse_certs<'c, I>(
certs: I,
parser: fn(&'c [u8]) -> crate::Result<Certificate>,
) -> Result<StoreType>
where
I: IntoIterator,
I::Item: Into<CertificateInput<'c>>,
{
#[cfg(feature = "boring")]
let mut store = X509StoreBuilder::new().map_err(Error::tls)?;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
let mut store = RootCertStore::empty();
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
let mut store = ();
let certs = filter_map_certs(certs.into_iter().map(|c| c.into().with_parser(parser)));
process_certs(certs, &mut store)?;
#[cfg(feature = "boring")]
return Ok(store.build());
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
return Ok(store);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
return Ok(());
}
pub fn parse_certs_with_stack<C, F>(certs: C, parse: F) -> Result<StoreType>
where
C: AsRef<[u8]>,
F: Fn(C) -> Result<Vec<Certificate>>,
{
#[cfg(feature = "boring")]
let mut store = X509StoreBuilder::new().map_err(Error::tls)?;
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
let mut store = RootCertStore::empty();
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
let mut store = ();
let certs = parse(certs)?;
process_certs(certs.into_iter(), &mut store)?;
#[cfg(feature = "boring")]
return Ok(store.build());
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
return Ok(store);
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
return Ok(());
}
pub fn process_certs<I>(iter: I, store: &mut StoreBuilder) -> Result<()>
where
I: Iterator<Item = Certificate>,
{
let mut valid_count = 0;
let mut invalid_count = 0;
for cert in iter {
#[cfg(feature = "boring")]
let res = store.add_cert(cert.0).map_err(Error::tls);
#[cfg(all(feature = "rustls-tls", not(feature = "boring")))]
let res = store
.add(cert.0.clone())
.map_err(|e| Error::tls(Box::new(e)));
#[cfg(not(any(feature = "boring", feature = "rustls-tls")))]
let res: Result<()> = Err(Error::tls("TLS not supported"));
if let Err(_err) = res {
invalid_count += 1;
} else {
valid_count += 1;
}
}
if valid_count == 0 && invalid_count > 0 {
return Err(Error::builder("invalid certificate"));
}
Ok(())
}
pub fn filter_map_certs<I>(certs: I) -> impl Iterator<Item = Certificate>
where
I: IntoIterator<Item = Result<Certificate>>,
{
certs.into_iter().filter_map(|res| res.ok())
}