mirror of
https://gitlab.com/marcandre.lureau/qemu-display.git
synced 2024-12-22 05:35:20 +00:00
rdp: use hybrid + credentials support
Credentials must be set with dbus, ex: busctl --user call org.QemuDisplay /org/qemu_display/rdp org.QemuDisplay.RDP SetCredentials sss user pass '' Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
parent
31d80e55b5
commit
3b282c440a
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -2164,6 +2164,7 @@ version = "0.5.0"
|
||||
source = "git+https://github.com/Devolutions/IronRDP#3c503cb2d1805a4164b668284e656c07437623b4"
|
||||
dependencies = [
|
||||
"ironrdp-cliprdr",
|
||||
"ironrdp-connector",
|
||||
"ironrdp-core",
|
||||
"ironrdp-displaycontrol",
|
||||
"ironrdp-pdu",
|
||||
@ -3375,6 +3376,7 @@ dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"clap 4.5.20",
|
||||
"enumflags2",
|
||||
"futures-util",
|
||||
"ironrdp",
|
||||
"keycodemap",
|
||||
@ -3384,6 +3386,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -22,6 +22,7 @@ anyhow = "1.0"
|
||||
clap = { version = "4.5", features = ["derive", "cargo"] }
|
||||
async-trait = "0.1"
|
||||
ironrdp = { git = "https://github.com/Devolutions/IronRDP", features = [
|
||||
"connector",
|
||||
"server",
|
||||
"svc",
|
||||
"cliprdr",
|
||||
@ -29,3 +30,5 @@ ironrdp = { git = "https://github.com/Devolutions/IronRDP", features = [
|
||||
"rdpsnd",
|
||||
] }
|
||||
futures-util = "0.3"
|
||||
zbus.workspace = true
|
||||
enumflags2 = "0.7.10"
|
||||
|
@ -1,43 +1,20 @@
|
||||
use clap::{clap_derive::ValueEnum, Parser};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
|
||||
pub enum SecurityProtocol {
|
||||
Ssl,
|
||||
Hybrid,
|
||||
HybridEx,
|
||||
}
|
||||
|
||||
impl From<SecurityProtocol> for ironrdp::pdu::nego::SecurityProtocol {
|
||||
fn from(value: SecurityProtocol) -> Self {
|
||||
match value {
|
||||
SecurityProtocol::Ssl => ironrdp::pdu::nego::SecurityProtocol::SSL,
|
||||
SecurityProtocol::Hybrid => ironrdp::pdu::nego::SecurityProtocol::HYBRID,
|
||||
SecurityProtocol::HybridEx => ironrdp::pdu::nego::SecurityProtocol::HYBRID_EX,
|
||||
}
|
||||
}
|
||||
}
|
||||
use clap::Parser;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
pub struct ServerArgs {
|
||||
/// IP address
|
||||
#[clap(short, long, default_value = "127.0.0.1")]
|
||||
pub address: std::net::IpAddr,
|
||||
|
||||
/// IP port
|
||||
#[clap(short, long, default_value = "3389")]
|
||||
pub port: u16,
|
||||
|
||||
/// Specify the security protocols to use
|
||||
#[clap(long, value_enum, value_parser, default_value_t = SecurityProtocol::Ssl)]
|
||||
pub security_protocol: SecurityProtocol,
|
||||
#[clap(short, long, default_value = "0.0.0.0:3389")]
|
||||
pub bind_addr: std::net::SocketAddr,
|
||||
|
||||
/// Path to tls certificate
|
||||
#[clap(short, long, value_parser)]
|
||||
pub cert: Option<String>,
|
||||
pub cert: PathBuf,
|
||||
|
||||
/// Path to private key
|
||||
#[clap(short, long, value_parser)]
|
||||
pub key: Option<String>,
|
||||
pub key: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
|
@ -3,15 +3,12 @@ mod display;
|
||||
mod input;
|
||||
mod sound;
|
||||
|
||||
use anyhow::{anyhow, Context, Error};
|
||||
use ironrdp::server::{
|
||||
tokio_rustls::{rustls, TlsAcceptor},
|
||||
ServerEvent,
|
||||
};
|
||||
use anyhow::Error;
|
||||
use enumflags2::BitFlags;
|
||||
use ironrdp::server::{Credentials, ServerEvent, TlsIdentityCtx};
|
||||
|
||||
use qemu_display::{zbus, Display};
|
||||
use rustls_pemfile::{certs, pkcs8_private_keys};
|
||||
use std::{fs::File, io::BufReader, sync::Arc};
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
use tracing::debug;
|
||||
|
||||
use ironrdp::server::RdpServer;
|
||||
@ -28,20 +25,16 @@ pub struct Server {
|
||||
args: ServerArgs,
|
||||
}
|
||||
|
||||
struct DBusCtrl {
|
||||
ev: UnboundedSender<ServerEvent>,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn new(dbus: zbus::Connection, args: ServerArgs) -> Self {
|
||||
Self { dbus, args }
|
||||
}
|
||||
|
||||
pub async fn run(&mut self) -> Result<(), Error> {
|
||||
let tls = self
|
||||
.args
|
||||
.cert
|
||||
.as_ref()
|
||||
.zip(self.args.key.as_ref())
|
||||
.map(|(cert, key)| acceptor(cert, key).unwrap())
|
||||
.ok_or_else(|| anyhow!("Failed to setup TLS"))?;
|
||||
|
||||
let dbus_display = Display::new::<()>(&self.dbus, None).await?;
|
||||
|
||||
let handler = InputHandler::connect(&dbus_display).await?;
|
||||
@ -55,9 +48,11 @@ impl Server {
|
||||
}
|
||||
};
|
||||
|
||||
let tls =
|
||||
TlsIdentityCtx::init_from_paths(self.args.cert.as_path(), self.args.key.as_path())?;
|
||||
let mut server = RdpServer::builder()
|
||||
.with_addr((self.args.address, self.args.port))
|
||||
.with_tls(tls)
|
||||
.with_addr(self.args.bind_addr)
|
||||
.with_hybrid(tls.make_acceptor()?, tls.pub_key)
|
||||
.with_input_handler(handler)
|
||||
.with_display_handler(display)
|
||||
.with_cliprdr_factory(Some(Box::new(clipboard)))
|
||||
@ -74,26 +69,33 @@ impl Server {
|
||||
ev.send(ServerEvent::Quit("org.qemu is gone".to_owned()))
|
||||
.unwrap();
|
||||
});
|
||||
|
||||
let ev = server.event_sender().clone();
|
||||
self.dbus
|
||||
.object_server()
|
||||
.at("/org/qemu_display/rdp", DBusCtrl { ev })
|
||||
.await?;
|
||||
self.dbus
|
||||
.request_name_with_flags("org.QemuDisplay", BitFlags::EMPTY)
|
||||
.await?;
|
||||
|
||||
server.run().await
|
||||
}
|
||||
}
|
||||
|
||||
fn acceptor(cert_path: &str, key_path: &str) -> Result<TlsAcceptor, Error> {
|
||||
let cert = certs(&mut BufReader::new(File::open(cert_path)?))
|
||||
.next()
|
||||
.context("no certificate")??;
|
||||
let key = pkcs8_private_keys(&mut BufReader::new(File::open(key_path)?))
|
||||
.next()
|
||||
.context("no private key")?
|
||||
.map(rustls::pki_types::PrivateKeyDer::from)?;
|
||||
|
||||
let mut server_config = rustls::ServerConfig::builder()
|
||||
.with_no_client_auth()
|
||||
.with_single_cert(vec![cert], key)
|
||||
.expect("bad certificate/key");
|
||||
|
||||
// This adds support for the SSLKEYLOGFILE env variable (https://wiki.wireshark.org/TLS#using-the-pre-master-secret)
|
||||
server_config.key_log = Arc::new(rustls::KeyLogFile::new());
|
||||
|
||||
Ok(TlsAcceptor::from(Arc::new(server_config)))
|
||||
#[zbus::interface(name = "org.QemuDisplay.RDP")]
|
||||
impl DBusCtrl {
|
||||
async fn set_credentials(&self, username: &str, password: &str, domain: &str) {
|
||||
self.ev
|
||||
.send(ServerEvent::SetCredentials(Credentials {
|
||||
username: username.into(),
|
||||
password: password.into(),
|
||||
domain: if domain.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(domain.into())
|
||||
},
|
||||
}))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user