use crate::{
ApplicationProtocol, KeyLogIntent, ProtocolVersion, TlsAlpn, TlsKeyLog, TlsSupportedVersions,
client::ClientHello,
};
use rama_core::{
error::BoxError,
extensions::{Extension, Extensions},
};
use rama_crypto::cert::self_signed_server_auth;
pub use rama_crypto::cert::{SelfSignedData, SelfSignedKeyKind};
use rama_crypto::pki_types::{CertificateDer, PrivateKeyDer};
use rama_net::address::Domain;
use rama_utils::{collections::smallvec::SmallVec, macros::generate_set_and_with};
#[derive(Debug, Default)]
pub struct TlsServerConfig(Extensions);
impl TlsServerConfig {
#[must_use]
pub fn new() -> Self {
Self(Extensions::new())
}
pub fn default_http() -> Result<Self, BoxError> {
Ok(Self::new()
.try_with_self_signed(SelfSignedData::default())?
.with_alpn_http_auto()
.with_keylog(KeyLogIntent::Environment))
}
pub fn self_signed_http_auto() -> Result<Self, BoxError> {
Ok(Self::new()
.try_with_self_signed(SelfSignedData::default())?
.with_alpn_http_auto())
}
pub fn write_to(&self, extensions: &Extensions) {
extensions.extend(&self.0);
}
generate_set_and_with! {
pub fn server_auth(mut self, auth: ServerAuthData) -> Self {
self.0.insert(TlsServerAuth(auth));
self
}
}
generate_set_and_with! {
pub fn self_signed(mut self, data: SelfSignedData) -> Result<Self, BoxError> {
self.0
.insert(TlsServerAuth(ServerAuthData::new_self_signed(data)?));
Ok(self)
}
}
generate_set_and_with! {
pub fn single_cert(mut self, data: ServerAuthData) -> Self {
self.0.insert(TlsServerAuth(data));
self
}
}
generate_set_and_with! {
pub fn alpn(mut self, protocols: SmallVec<[ApplicationProtocol; 2]>) -> Self {
self.0.insert(TlsAlpn(protocols));
self
}
}
generate_set_and_with! {
pub fn alpn_http_auto(mut self) -> Self {
self.0.insert(TlsAlpn::http_auto());
self
}
}
generate_set_and_with! {
pub fn alpn_http_1(mut self) -> Self {
self.0.insert(TlsAlpn::http_1());
self
}
}
generate_set_and_with! {
pub fn alpn_http_2(mut self) -> Self {
self.0.insert(TlsAlpn::http_2());
self
}
}
generate_set_and_with! {
pub fn supported_versions(mut self, versions: Vec<ProtocolVersion>) -> Self {
self.0.insert(TlsSupportedVersions(versions));
self
}
}
generate_set_and_with! {
pub fn keylog(mut self, intent: KeyLogIntent) -> Self {
self.0.insert(TlsKeyLog(intent));
self
}
}
generate_set_and_with! {
pub fn client_verify(mut self, mode: ClientVerifyMode) -> Self {
self.0.insert(TlsClientVerify(mode));
self
}
}
generate_set_and_with! {
pub fn store_client_cert_chain(mut self, store: bool) -> Self {
self.0.insert(TlsStoreClientCertChain(store));
self
}
}
pub fn as_extensions(&self) -> &Extensions {
&self.0
}
#[doc(hidden)]
pub fn insert<T: Extension>(&self, piece: T) {
self.0.insert(piece);
}
}
impl Clone for TlsServerConfig {
fn clone(&self) -> Self {
let clone = Self::new();
clone.as_extensions().extend(self.as_extensions());
clone
}
}
#[derive(Debug)]
pub struct ServerAuthData {
pub private_key: PrivateKeyDer<'static>,
pub cert_chain: Vec<CertificateDer<'static>>,
pub ocsp: Option<Vec<u8>>,
}
impl ServerAuthData {
#[must_use]
pub fn new(
cert_chain: Vec<CertificateDer<'static>>,
private_key: PrivateKeyDer<'static>,
) -> Self {
Self {
cert_chain,
private_key,
ocsp: None,
}
}
pub fn new_self_signed(data: SelfSignedData) -> Result<Self, BoxError> {
let (cert_chain, private_key) = self_signed_server_auth(data)?;
Ok(Self {
cert_chain,
private_key,
ocsp: None,
})
}
}
impl Clone for ServerAuthData {
fn clone(&self) -> Self {
Self {
cert_chain: self.cert_chain.clone(),
ocsp: self.ocsp.clone(),
private_key: self.private_key.clone_key(),
}
}
}
pub trait DynamicCertIssuer: Send + Sync + 'static {
fn issue_cert(
&self,
client_hello: ClientHello,
server_name: Option<Domain>,
) -> impl Future<Output = Result<ServerAuthData, BoxError>> + Send + '_;
fn norm_cn(&self, _domain: &Domain) -> Option<&Domain> {
None
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub enum ClientVerifyMode {
#[default]
Auto,
Disable,
ClientAuth(Vec<CertificateDer<'static>>),
}
#[derive(Debug, Clone, Extension)]
#[extension(tags(tls))]
pub struct TlsServerAuth(pub ServerAuthData);
#[derive(Debug, Clone, Extension)]
#[extension(tags(tls))]
pub struct TlsClientVerify(pub ClientVerifyMode);
#[derive(Debug, Clone, Extension)]
#[extension(tags(tls))]
pub struct TlsStoreClientCertChain(pub bool);