Upstream commit: 474dd0229cb20cf513036619781ed97bd8073c3f Enterprise-only files removed or emptied: 63 Enterprise-only snippets removed: 117 in 50 files Dangling module declarations removed: 5 Cargo edits turning enterprise off: 14 Verification: clean Enterprise feature gates left for rebuilt features: 19 in 18 files Produced by tools/fork/strip.py. The full report is in docs/fork/strip-reports/ on main.
112 lines
3.5 KiB
Rust
112 lines
3.5 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
|
*/
|
|
|
|
use crate::{
|
|
KV_ACME, Server,
|
|
network::acme::{SerializedCert, StaticResolver, directory::ACME_TLS_ALPN_NAME},
|
|
};
|
|
use rustls::{
|
|
ServerConfig,
|
|
crypto::aws_lc_rs::sign::any_ecdsa_type,
|
|
server::{ClientHello, ResolvesServerCert},
|
|
sign::CertifiedKey,
|
|
};
|
|
use rustls_pki_types::{CertificateDer, PrivateKeyDer, PrivatePkcs8KeyDer};
|
|
use std::sync::Arc;
|
|
use store::{
|
|
dispatch::lookup::KeyValue,
|
|
write::{AlignedBytes, Archive},
|
|
};
|
|
use trc::AcmeEvent;
|
|
|
|
impl Server {
|
|
pub(crate) async fn build_acme_certificate(&self, domain: &str) -> Option<Arc<CertifiedKey>> {
|
|
match self
|
|
.in_memory_store()
|
|
.key_get::<Archive<AlignedBytes>>(KeyValue::<()>::build_key(KV_ACME, domain))
|
|
.await
|
|
{
|
|
Ok(Some(cert_)) => match cert_.unarchive::<SerializedCert>() {
|
|
Ok(cert) => {
|
|
match any_ecdsa_type(&PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
|
|
cert.private_key.as_ref(),
|
|
))) {
|
|
Ok(key) => Some(Arc::new(CertifiedKey::new(
|
|
vec![CertificateDer::from(cert.certificate.to_vec())],
|
|
key,
|
|
))),
|
|
Err(err) => {
|
|
trc::event!(
|
|
Acme(AcmeEvent::Error),
|
|
Domain = domain.to_string(),
|
|
Reason = err.to_string(),
|
|
Details = "Failed to parse private key"
|
|
);
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
Err(err) => {
|
|
trc::event!(
|
|
Acme(AcmeEvent::Error),
|
|
Domain = domain.to_string(),
|
|
CausedBy = err,
|
|
Details = "Failed to unarchive certificate"
|
|
);
|
|
None
|
|
}
|
|
},
|
|
Err(err) => {
|
|
trc::event!(
|
|
Acme(AcmeEvent::Error),
|
|
Domain = domain.to_string(),
|
|
CausedBy = err
|
|
);
|
|
None
|
|
}
|
|
Ok(None) => {
|
|
trc::event!(Acme(AcmeEvent::TokenNotFound), Domain = domain.to_string());
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn has_acme_tls_providers(&self) -> bool {
|
|
self.core.network.has_acme_tls_challenge
|
|
}
|
|
|
|
#[inline(always)]
|
|
pub fn has_acme_http_providers(&self) -> bool {
|
|
self.core.network.has_acme_http_challenge
|
|
}
|
|
}
|
|
|
|
impl ResolvesServerCert for StaticResolver {
|
|
fn resolve(&self, _: ClientHello) -> Option<Arc<CertifiedKey>> {
|
|
self.key.clone()
|
|
}
|
|
}
|
|
|
|
pub(crate) fn build_acme_static_resolver(key: Option<Arc<CertifiedKey>>) -> Arc<ServerConfig> {
|
|
let mut challenge = ServerConfig::builder()
|
|
.with_no_client_auth()
|
|
.with_cert_resolver(Arc::new(StaticResolver { key }));
|
|
challenge.alpn_protocols.push(ACME_TLS_ALPN_NAME.to_vec());
|
|
Arc::new(challenge)
|
|
}
|
|
|
|
pub trait IsTlsAlpnChallenge {
|
|
fn is_tls_alpn_challenge(&self) -> bool;
|
|
}
|
|
|
|
impl IsTlsAlpnChallenge for ClientHello<'_> {
|
|
fn is_tls_alpn_challenge(&self) -> bool {
|
|
self.alpn().into_iter().flatten().eq([ACME_TLS_ALPN_NAME])
|
|
}
|
|
}
|