use crate::crypto::ellipticcurve::PrivateKey;
use crate::log;
use crate::net::handshake::Certificate;
use crate::rand::PRNG;
use crate::utils::x509::X509;
pub struct ServerConfig {
pub privkey: PrivateKey,
pub cert: Certificate,
pub client_cert_ca: Option<Certificate>,
pub client_cert_custom_verify_fn: Option<fn(cert: &X509) -> bool>,
pub keylog: Option<String>,
pub server_name: Option<String>,
pub prng_type: PRNG,
}
pub struct ServerConfigBuilder {
cert: Option<Certificate>,
privkey: Option<PrivateKey>,
keylog: Option<String>,
server_name: Option<String>,
client_cert_ca: Option<Certificate>,
prng_type: PRNG,
client_cert_custom_verify_fn: Option<fn(cert: &X509) -> bool>,
}
impl Default for ServerConfigBuilder {
fn default() -> Self {
Self::new()
}
}
impl ServerConfigBuilder {
pub fn new() -> Self {
ServerConfigBuilder {
cert: None,
privkey: None,
keylog: None,
server_name: None,
client_cert_ca: None,
prng_type: PRNG::URandom,
client_cert_custom_verify_fn: None,
}
}
pub fn add_cert_pem(mut self, filepath: String) -> Self {
self.cert = Certificate::from_pem(filepath);
if self.cert.is_none() {
panic!("Error reading or parsing certificate");
}
self
}
pub fn add_client_cert_ca(mut self, filepath: String) -> Self {
self.client_cert_ca = Certificate::from_pem_x509(filepath);
if self.client_cert_ca.is_none() {
panic!("Error reading or parsing client certificate ca");
}
self
}
pub fn add_privkey_pem(mut self, filepath: String) -> Self {
self.privkey = PrivateKey::from_pem(filepath);
if self.privkey.is_none() {
panic!("Error reading or parsing private key");
}
self
}
pub fn set_keylog_path(mut self, filepath: String) -> Self {
self.keylog = Some(filepath);
self
}
pub fn enable_keylog(mut self) -> Self {
self.keylog = Some("keylog.txt".to_string());
self
}
pub fn set_client_cert_custom_verify_fn(mut self, f: fn(cert: &X509) -> bool) -> Self {
self.client_cert_custom_verify_fn = Some(f);
self
}
pub fn set_server_name(mut self, server_name: String) -> Self {
self.server_name = Some(server_name);
self
}
pub fn set_prng(mut self, prng: PRNG) -> Self {
self.prng_type = prng;
self
}
pub fn build(self) -> std::result::Result<ServerConfig, String> {
if self.cert.is_none() {
return Err("No cert provided".to_string());
}
if self.privkey.is_none() {
return Err("No privkey for cert provided".to_string());
}
if self.client_cert_custom_verify_fn.is_some() && self.client_cert_ca.is_none() {
return Err("No client certificate CA found. Custom verify fn useless.".to_string());
}
if self.prng_type == PRNG::Simple {
log::error!("The selected random number generator is insecure!");
}
Ok(ServerConfig {
client_cert_ca: self.client_cert_ca,
cert: self.cert.unwrap(),
privkey: self.privkey.unwrap(),
keylog: self.keylog,
prng_type: self.prng_type,
server_name: self.server_name,
client_cert_custom_verify_fn: self.client_cert_custom_verify_fn,
})
}
}