diff --git a/crates/ironrdp-server/src/helper.rs b/crates/ironrdp-server/src/helper.rs index 7548c2494..68a7a9a58 100644 --- a/crates/ironrdp-server/src/helper.rs +++ b/crates/ironrdp-server/src/helper.rs @@ -5,23 +5,43 @@ use std::sync::Arc; use anyhow::Context; use rustls_pemfile::{certs, pkcs8_private_keys}; -use tokio_rustls::{rustls, TlsAcceptor}; +use tokio_rustls::rustls::pki_types::pem::PemObject; +use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer}; +use tokio_rustls::rustls::{self}; +use tokio_rustls::TlsAcceptor; pub struct TlsIdentityCtx { - pub cert: rustls::pki_types::CertificateDer<'static>, - pub priv_key: rustls::pki_types::PrivateKeyDer<'static>, + pub certs: Vec>, + pub priv_key: PrivateKeyDer<'static>, pub pub_key: Vec, } impl TlsIdentityCtx { + /// A constructor to create a `TlsIdentityCtx` from the given certificate and key paths. + /// + /// The file format can be either PEM (if the file extension ends with .pem) or DER. pub fn init_from_paths(cert_path: &Path, key_path: &Path) -> anyhow::Result { - use x509_cert::der::Decode as _; + let certs: Vec<_> = if cert_path.extension().map_or(false, |ext| ext == "pem") { + CertificateDer::pem_file_iter(cert_path) + } else { + certs(&mut BufReader::new(File::open(cert_path)?)) + } + .collect::>() + .context(format!("reading server cert `{cert_path:?}`"))?; - let cert = certs(&mut BufReader::new(File::open(cert_path)?)) - .next() - .context("no certificate")??; + let priv_key = if key_path.extension().map_or(false, |ext| ext == "pem") { + PrivateKeyDer::from_pem_file(key_path).context("reading server key `{key_path:?}`")? + } else { + pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?)) + .next() + .context("no private key")? + .map(PrivateKeyDer::from)? + }; let pub_key = { + use x509_cert::der::Decode as _; + + let cert = certs.first().ok_or_else(|| std::io::Error::other("invalid cert"))?; let cert = x509_cert::Certificate::from_der(&cert).map_err(std::io::Error::other)?; cert.tbs_certificate .subject_public_key_info @@ -31,13 +51,8 @@ impl TlsIdentityCtx { .to_owned() }; - let priv_key = pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?)) - .next() - .context("no private key")? - .map(rustls::pki_types::PrivateKeyDer::from)?; - Ok(Self { - cert, + certs, priv_key, pub_key, }) @@ -46,7 +61,7 @@ impl TlsIdentityCtx { pub fn make_acceptor(&self) -> anyhow::Result { let mut server_config = rustls::ServerConfig::builder() .with_no_client_auth() - .with_single_cert(vec![self.cert.clone()], self.priv_key.clone_key()) + .with_single_cert(self.certs.clone(), self.priv_key.clone_key()) .context("bad certificate/key")?; // This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)