Skip to content

Commit 7dd1787

Browse files
elmarcoCBenoit
authored andcommitted
feat(server): add a "helper" feature for TlsIdentityCtx
This snippet is useful for server implementations, as long as the server must be configured with a tokio-rustls TlsAcceptor, and not directly with certificate paths for examples. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
1 parent a9356fc commit 7dd1787

File tree

4 files changed

+65
-0
lines changed

4 files changed

+65
-0
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ironrdp-server/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ categories.workspace = true
1515
doctest = true
1616
test = false
1717

18+
[features]
19+
helper = ["dep:x509-cert", "dep:rustls-pemfile"]
20+
1821
[dependencies]
1922
anyhow = "1.0"
2023
tokio = { version = "1", features = ["net", "macros", "sync", "rt"] }
@@ -33,6 +36,8 @@ ironrdp-acceptor.workspace = true
3336
ironrdp-graphics.workspace = true
3437
ironrdp-rdpsnd.workspace = true
3538
tracing.workspace = true
39+
x509-cert = { version = "0.2.5", optional = true }
40+
rustls-pemfile = { version = "2.2.0", optional = true }
3641

3742
[dev-dependencies]
3843
tokio = { version = "1", features = ["sync"] }

crates/ironrdp-server/src/helper.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
use std::{fs::File, io::BufReader, path::Path, sync::Arc};
2+
3+
use anyhow::Context;
4+
use rustls_pemfile::{certs, pkcs8_private_keys};
5+
use tokio_rustls::{rustls, TlsAcceptor};
6+
7+
pub struct TlsIdentityCtx {
8+
pub cert: rustls::pki_types::CertificateDer<'static>,
9+
pub priv_key: rustls::pki_types::PrivateKeyDer<'static>,
10+
pub pub_key: Vec<u8>,
11+
}
12+
13+
impl TlsIdentityCtx {
14+
pub fn init_from_paths(cert_path: &Path, key_path: &Path) -> anyhow::Result<Self> {
15+
use x509_cert::der::Decode as _;
16+
17+
let cert = certs(&mut BufReader::new(File::open(cert_path)?))
18+
.next()
19+
.context("no certificate")??;
20+
21+
let pub_key = {
22+
let cert = x509_cert::Certificate::from_der(&cert).map_err(std::io::Error::other)?;
23+
cert.tbs_certificate
24+
.subject_public_key_info
25+
.subject_public_key
26+
.as_bytes()
27+
.ok_or_else(|| std::io::Error::other("subject public key BIT STRING is not aligned"))?
28+
.to_owned()
29+
};
30+
31+
let priv_key = pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?))
32+
.next()
33+
.context("no private key")?
34+
.map(rustls::pki_types::PrivateKeyDer::from)?;
35+
36+
Ok(Self {
37+
cert,
38+
priv_key,
39+
pub_key,
40+
})
41+
}
42+
43+
pub fn make_acceptor(&self) -> anyhow::Result<TlsAcceptor> {
44+
let mut server_config = rustls::ServerConfig::builder()
45+
.with_no_client_auth()
46+
.with_single_cert(vec![self.cert.clone()], self.priv_key.clone_key())
47+
.context("bad certificate/key")?;
48+
49+
// This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)
50+
server_config.key_log = Arc::new(rustls::KeyLogFile::new());
51+
52+
Ok(TlsAcceptor::from(Arc::new(server_config)))
53+
}
54+
}

crates/ironrdp-server/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,15 @@ mod clipboard;
1616
mod display;
1717
mod encoder;
1818
mod handler;
19+
#[cfg(feature = "helper")]
20+
mod helper;
1921
mod server;
2022
mod sound;
2123

2224
pub use clipboard::*;
2325
pub use display::*;
2426
pub use handler::*;
27+
#[cfg(feature = "helper")]
28+
pub use helper::*;
2529
pub use server::*;
2630
pub use sound::*;

0 commit comments

Comments
 (0)