Skip to content

Commit 9676877

Browse files
committed
feat(server): make TlsIdentityCtx accept PEM files
This is in general more convenient than DER files. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
1 parent 114098b commit 9676877

File tree

1 file changed

+30
-14
lines changed

1 file changed

+30
-14
lines changed

crates/ironrdp-server/src/helper.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,44 @@ use std::sync::Arc;
55

66
use anyhow::Context;
77
use rustls_pemfile::{certs, pkcs8_private_keys};
8-
use tokio_rustls::{rustls, TlsAcceptor};
8+
use tokio_rustls::rustls::pki_types::pem::PemObject;
9+
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
10+
use tokio_rustls::rustls::{self};
11+
use tokio_rustls::TlsAcceptor;
912

1013
pub struct TlsIdentityCtx {
11-
pub cert: rustls::pki_types::CertificateDer<'static>,
12-
pub priv_key: rustls::pki_types::PrivateKeyDer<'static>,
14+
pub certs: Vec<CertificateDer<'static>>,
15+
pub priv_key: PrivateKeyDer<'static>,
1316
pub pub_key: Vec<u8>,
1417
}
1518

1619
impl TlsIdentityCtx {
20+
/// A constructor to create a `TlsIdentityCtx` from the given certificate and key paths.
21+
///
22+
/// The file format can be either PEM (if the file extension ends with .pem) or DER.
1723
pub fn init_from_paths(cert_path: &Path, key_path: &Path) -> anyhow::Result<Self> {
18-
use x509_cert::der::Decode as _;
24+
let certs: Vec<_> = if cert_path.extension().map_or(false, |ext| ext == "pem") {
25+
CertificateDer::pem_file_iter(cert_path)
26+
.context(format!("reading server cert `{cert_path:?}`"))?
27+
.map(|cert| cert.unwrap())
28+
.collect()
29+
} else {
30+
certs(&mut BufReader::new(File::open(cert_path)?)).collect::<Result<_, _>>()?
31+
};
1932

20-
let cert = certs(&mut BufReader::new(File::open(cert_path)?))
21-
.next()
22-
.context("no certificate")??;
33+
let priv_key = if key_path.extension().map_or(false, |ext| ext == "pem") {
34+
PrivateKeyDer::from_pem_file(key_path).context("reading server key `{key_path:?}`")?
35+
} else {
36+
pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?))
37+
.next()
38+
.context("no private key")?
39+
.map(PrivateKeyDer::from)?
40+
};
2341

2442
let pub_key = {
43+
use x509_cert::der::Decode as _;
44+
45+
let cert = certs.first().ok_or_else(|| std::io::Error::other("invalid cert"))?;
2546
let cert = x509_cert::Certificate::from_der(&cert).map_err(std::io::Error::other)?;
2647
cert.tbs_certificate
2748
.subject_public_key_info
@@ -31,13 +52,8 @@ impl TlsIdentityCtx {
3152
.to_owned()
3253
};
3354

34-
let priv_key = pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?))
35-
.next()
36-
.context("no private key")?
37-
.map(rustls::pki_types::PrivateKeyDer::from)?;
38-
3955
Ok(Self {
40-
cert,
56+
certs,
4157
priv_key,
4258
pub_key,
4359
})
@@ -46,7 +62,7 @@ impl TlsIdentityCtx {
4662
pub fn make_acceptor(&self) -> anyhow::Result<TlsAcceptor> {
4763
let mut server_config = rustls::ServerConfig::builder()
4864
.with_no_client_auth()
49-
.with_single_cert(vec![self.cert.clone()], self.priv_key.clone_key())
65+
.with_single_cert(self.certs.clone(), self.priv_key.clone_key())
5066
.context("bad certificate/key")?;
5167

5268
// This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)

0 commit comments

Comments
 (0)