Skip to content

Commit

Permalink
feat(server): make TlsIdentityCtx accept PEM files (#623)
Browse files Browse the repository at this point in the history
This is in general more convenient than DER files.

Signed-off-by: Marc-André Lureau <[email protected]>
  • Loading branch information
elmarco authored Dec 17, 2024
1 parent 114098b commit 9198284
Showing 1 changed file with 29 additions and 14 deletions.
43 changes: 29 additions & 14 deletions crates/ironrdp-server/src/helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CertificateDer<'static>>,
pub priv_key: PrivateKeyDer<'static>,
pub pub_key: Vec<u8>,
}

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<Self> {
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::<Result<_, _>>()
.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
Expand All @@ -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,
})
Expand All @@ -46,7 +61,7 @@ impl TlsIdentityCtx {
pub fn make_acceptor(&self) -> anyhow::Result<TlsAcceptor> {
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)
Expand Down

0 comments on commit 9198284

Please sign in to comment.