mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-04-09 18:41:28 +03:00
add logic for fingerprint verification
This commit is contained in:
@@ -274,12 +274,15 @@ impl Cli {
|
|||||||
FrontendEvent::EmulationStatus(s) => {
|
FrontendEvent::EmulationStatus(s) => {
|
||||||
eprintln!("emulation status: {s:?}")
|
eprintln!("emulation status: {s:?}")
|
||||||
}
|
}
|
||||||
FrontendEvent::AuthorizedUpdated(keys) => {
|
FrontendEvent::AuthorizedUpdated(fingerprints) => {
|
||||||
eprintln!("authorized keys changed:");
|
eprintln!("authorized keys changed:");
|
||||||
for key in keys {
|
for (desc, fp) in fingerprints {
|
||||||
eprintln!("{key}");
|
eprintln!("{desc}: {fp}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FrontendEvent::PublicKeyFingerprint(fp) => {
|
||||||
|
eprintln!("the public key fingerprint of this device is {fp}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
<property name="modal">True</property>
|
<property name="modal">True</property>
|
||||||
<property name="width-request">880</property>
|
<property name="width-request">880</property>
|
||||||
<property name="default-width">880</property>
|
<property name="default-width">880</property>
|
||||||
<property name="default-height">240</property>
|
<property name="height-request">340</property>
|
||||||
|
<property name="default-height">340</property>
|
||||||
<property name="title" translatable="yes">Add Public Key Fingerprint</property>
|
<property name="title" translatable="yes">Add Public Key Fingerprint</property>
|
||||||
<property name="content">
|
<property name="content">
|
||||||
<object class="AdwToolbarView">
|
<object class="AdwToolbarView">
|
||||||
@@ -21,13 +22,39 @@
|
|||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<property name="spacing">18</property>
|
<property name="spacing">18</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="label">you can find the fingerprint of a device under the `General` section</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwPreferencesGroup">
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title">description</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwActionRow">
|
<object class="AdwActionRow">
|
||||||
<property name="title" translatable="yes">fingerprint</property>
|
|
||||||
<property name="child">
|
<property name="child">
|
||||||
<object class="GtkText" id="text">
|
<object class="GtkText" id="description">
|
||||||
|
<property name="margin-top">10</property>
|
||||||
|
<property name="margin-bottom">10</property>
|
||||||
|
<property name="margin-start">10</property>
|
||||||
|
<property name="margin-end">10</property>
|
||||||
|
<property name="enable-undo">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="vexpand">True</property>
|
||||||
|
<property name="max-length">0</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title">sha256 fingerprint</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkText" id="fingerprint">
|
||||||
<property name="margin-top">10</property>
|
<property name="margin-top">10</property>
|
||||||
<property name="margin-bottom">10</property>
|
<property name="margin-bottom">10</property>
|
||||||
<property name="margin-start">10</property>
|
<property name="margin-start">10</property>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface>
|
<interface>
|
||||||
<template class="KeyRow" parent="AdwActionRow">
|
<template class="KeyRow" parent="AdwActionRow">
|
||||||
<property name="title">hostname</property>
|
|
||||||
<child type="prefix">
|
<child type="prefix">
|
||||||
<object class="GtkButton" id="delete_button">
|
<object class="GtkButton" id="delete_button">
|
||||||
<property name="valign">center</property>
|
<property name="valign">center</property>
|
||||||
|
|||||||
@@ -178,6 +178,19 @@
|
|||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow" id="fingerprint_row">
|
||||||
|
<property name="title">public key fingerprint</property>
|
||||||
|
<property name="icon-name">auth-fingerprint-symbolic</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="copy-fingerprint-button">
|
||||||
|
<property name="icon-name">edit-copy-symbolic</property>
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<signal name="clicked" handler="handle_copy_fingerprint" swapped="true"/>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
|
|||||||
@@ -12,7 +12,9 @@ use gtk::{
|
|||||||
#[template(resource = "/de/feschber/LanMouse/fingerprint_window.ui")]
|
#[template(resource = "/de/feschber/LanMouse/fingerprint_window.ui")]
|
||||||
pub struct FingerprintWindow {
|
pub struct FingerprintWindow {
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub text: TemplateChild<Text>,
|
pub description: TemplateChild<Text>,
|
||||||
|
#[template_child]
|
||||||
|
pub fingerprint: TemplateChild<Text>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub confirm_button: TemplateChild<Button>,
|
pub confirm_button: TemplateChild<Button>,
|
||||||
}
|
}
|
||||||
@@ -39,8 +41,9 @@ impl ObjectSubclass for FingerprintWindow {
|
|||||||
impl FingerprintWindow {
|
impl FingerprintWindow {
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_confirm(&self, _button: Button) {
|
fn handle_confirm(&self, _button: Button) {
|
||||||
let fp = self.text.text().to_string();
|
let desc = self.description.text().to_string();
|
||||||
self.obj().emit_by_name("confirm-clicked", &[&fp])
|
let fp = self.fingerprint.text().to_string();
|
||||||
|
self.obj().emit_by_name("confirm-clicked", &[&fp, &desc])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +52,7 @@ impl ObjectImpl for FingerprintWindow {
|
|||||||
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
|
static SIGNALS: OnceLock<Vec<Signal>> = OnceLock::new();
|
||||||
SIGNALS.get_or_init(|| {
|
SIGNALS.get_or_init(|| {
|
||||||
vec![Signal::builder("confirm-clicked")
|
vec![Signal::builder("confirm-clicked")
|
||||||
.param_types([String::static_type()])
|
.param_types([String::static_type(), String::static_type()])
|
||||||
.build()]
|
.build()]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,15 @@ glib::wrapper! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl KeyObject {
|
impl KeyObject {
|
||||||
pub fn new(fp: String) -> Self {
|
pub fn new(desc: String, fp: String) -> Self {
|
||||||
Object::builder().property("fingerprint", fp).build()
|
Object::builder()
|
||||||
|
.property("description", desc)
|
||||||
|
.property("fingerprint", fp)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_description(&self) -> String {
|
||||||
|
self.imp().description.borrow().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_fingerprint(&self) -> String {
|
pub fn get_fingerprint(&self) -> String {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ use gtk::subclass::prelude::*;
|
|||||||
#[derive(Properties, Default)]
|
#[derive(Properties, Default)]
|
||||||
#[properties(wrapper_type = super::KeyObject)]
|
#[properties(wrapper_type = super::KeyObject)]
|
||||||
pub struct KeyObject {
|
pub struct KeyObject {
|
||||||
|
#[property(name = "description", get, set, type = String)]
|
||||||
|
pub description: RefCell<String>,
|
||||||
#[property(name = "fingerprint", get, set, type = String)]
|
#[property(name = "fingerprint", get, set, type = String)]
|
||||||
pub fingerprint: RefCell<String>,
|
pub fingerprint: RefCell<String>,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,11 +21,17 @@ impl KeyRow {
|
|||||||
let mut bindings = self.imp().bindings.borrow_mut();
|
let mut bindings = self.imp().bindings.borrow_mut();
|
||||||
|
|
||||||
let title_binding = key_object
|
let title_binding = key_object
|
||||||
.bind_property("fingerprint", self, "title")
|
.bind_property("description", self, "title")
|
||||||
|
.sync_create()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let subtitle_binding = key_object
|
||||||
|
.bind_property("fingerprint", self, "subtitle")
|
||||||
.sync_create()
|
.sync_create()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
bindings.push(title_binding);
|
bindings.push(title_binding);
|
||||||
|
bindings.push(subtitle_binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unbind(&self) {
|
pub fn unbind(&self) {
|
||||||
|
|||||||
@@ -139,6 +139,9 @@ fn build_ui(app: &Application) {
|
|||||||
FrontendEvent::AuthorizedUpdated(keys) => {
|
FrontendEvent::AuthorizedUpdated(keys) => {
|
||||||
window.set_authorized_keys(keys);
|
window.set_authorized_keys(keys);
|
||||||
}
|
}
|
||||||
|
FrontendEvent::PublicKeyFingerprint(fp) => {
|
||||||
|
window.set_pk_fp(&fp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
mod imp;
|
mod imp;
|
||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use adw::subclass::prelude::*;
|
use adw::subclass::prelude::*;
|
||||||
@@ -360,8 +360,8 @@ impl Window {
|
|||||||
closure_local!(
|
closure_local!(
|
||||||
#[strong(rename_to = parent)]
|
#[strong(rename_to = parent)]
|
||||||
self,
|
self,
|
||||||
move |w: FingerprintWindow, fp: String| {
|
move |w: FingerprintWindow, desc: String, fp: String| {
|
||||||
parent.request_fingerprint_add(fp);
|
parent.request_fingerprint_add(desc, fp);
|
||||||
w.close();
|
w.close();
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
@@ -369,12 +369,12 @@ impl Window {
|
|||||||
window.present();
|
window.present();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_fingerprint_add(&self, fp: String) {
|
pub fn request_fingerprint_add(&self, desc: String, fp: String) {
|
||||||
self.request(FrontendRequest::FingerprintAdd(fp));
|
self.request(FrontendRequest::AuthorizeKey(desc, fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_fingerprint_remove(&self, fp: String) {
|
pub fn request_fingerprint_remove(&self, fp: String) {
|
||||||
self.request(FrontendRequest::FingerprintRemove(fp));
|
self.request(FrontendRequest::RemoveAuthorizedKey(fp));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request(&self, request: FrontendRequest) {
|
pub fn request(&self, request: FrontendRequest) {
|
||||||
@@ -411,15 +411,19 @@ impl Window {
|
|||||||
.set_visible(!capture || !emulation);
|
.set_visible(!capture || !emulation);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_authorized_keys(&self, fingerprints: HashSet<String>) {
|
pub(crate) fn set_authorized_keys(&self, fingerprints: HashMap<String, String>) {
|
||||||
let authorized = self.authorized();
|
let authorized = self.authorized();
|
||||||
// clear list
|
// clear list
|
||||||
authorized.remove_all();
|
authorized.remove_all();
|
||||||
// insert fingerprints
|
// insert fingerprints
|
||||||
for fingerprint in fingerprints {
|
for (description, fingerprint) in fingerprints {
|
||||||
let key_obj = KeyObject::new(fingerprint);
|
let key_obj = KeyObject::new(description, fingerprint);
|
||||||
authorized.append(&key_obj);
|
authorized.append(&key_obj);
|
||||||
}
|
}
|
||||||
self.update_auth_placeholder_visibility();
|
self.update_auth_placeholder_visibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_pk_fp(&self, fingerprint: &str) {
|
||||||
|
self.imp().fingerprint_row.set_subtitle(fingerprint);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ pub struct Window {
|
|||||||
#[template_child]
|
#[template_child]
|
||||||
pub authorized_placeholder: TemplateChild<ActionRow>,
|
pub authorized_placeholder: TemplateChild<ActionRow>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
|
pub fingerprint_row: TemplateChild<ActionRow>,
|
||||||
|
#[template_child]
|
||||||
pub port_edit_apply: TemplateChild<Button>,
|
pub port_edit_apply: TemplateChild<Button>,
|
||||||
#[template_child]
|
#[template_child]
|
||||||
pub port_edit_cancel: TemplateChild<Button>,
|
pub port_edit_cancel: TemplateChild<Button>,
|
||||||
@@ -93,6 +95,25 @@ impl Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[template_callback]
|
||||||
|
fn handle_copy_fingerprint(&self, button: &Button) {
|
||||||
|
let fingerprint: String = self.fingerprint_row.property("subtitle");
|
||||||
|
let display = gdk::Display::default().unwrap();
|
||||||
|
let clipboard = display.clipboard();
|
||||||
|
clipboard.set_text(&fingerprint);
|
||||||
|
button.set_icon_name("emblem-ok-symbolic");
|
||||||
|
button.set_css_classes(&["success"]);
|
||||||
|
glib::spawn_future_local(clone!(
|
||||||
|
#[weak]
|
||||||
|
button,
|
||||||
|
async move {
|
||||||
|
glib::timeout_future_seconds(1).await;
|
||||||
|
button.set_icon_name("edit-copy-symbolic");
|
||||||
|
button.set_css_classes(&[]);
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn handle_port_changed(&self, _entry: &Entry) {
|
fn handle_port_changed(&self, _entry: &Entry) {
|
||||||
self.port_edit_apply.set_visible(true);
|
self.port_edit_apply.set_visible(true);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::{HashMap, HashSet},
|
||||||
env::VarError,
|
env::VarError,
|
||||||
fmt::Display,
|
fmt::Display,
|
||||||
io,
|
io,
|
||||||
@@ -197,7 +197,10 @@ pub enum FrontendEvent {
|
|||||||
CaptureStatus(Status),
|
CaptureStatus(Status),
|
||||||
/// emulation status
|
/// emulation status
|
||||||
EmulationStatus(Status),
|
EmulationStatus(Status),
|
||||||
AuthorizedUpdated(HashSet<String>),
|
/// authorized public key fingerprints have been updated
|
||||||
|
AuthorizedUpdated(HashMap<String, String>),
|
||||||
|
/// public key fingerprint of this device
|
||||||
|
PublicKeyFingerprint(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Serialize, Deserialize)]
|
||||||
@@ -230,10 +233,10 @@ pub enum FrontendRequest {
|
|||||||
EnableEmulation,
|
EnableEmulation,
|
||||||
/// synchronize all state
|
/// synchronize all state
|
||||||
Sync,
|
Sync,
|
||||||
/// authorize fingerprint
|
/// authorize fingerprint (description, fingerprint)
|
||||||
FingerprintAdd(String),
|
AuthorizeKey(String, String),
|
||||||
/// remove fingerprint
|
/// remove fingerprint (fingerprint)
|
||||||
FingerprintRemove(String),
|
RemoveAuthorizedKey(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize)]
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::{fs::File, io::BufReader};
|
|||||||
|
|
||||||
use rcgen::KeyPair;
|
use rcgen::KeyPair;
|
||||||
use rustls::pki_types::CertificateDer;
|
use rustls::pki_types::CertificateDer;
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use webrtc_dtls::crypto::{Certificate, CryptoPrivateKey};
|
use webrtc_dtls::crypto::{Certificate, CryptoPrivateKey};
|
||||||
|
|
||||||
@@ -28,6 +29,18 @@ pub enum Error {
|
|||||||
Other(String),
|
Other(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn generate_fingerprint(cert: &[u8]) -> String {
|
||||||
|
let mut hash = Sha256::new();
|
||||||
|
hash.update(cert);
|
||||||
|
let bytes = hash
|
||||||
|
.finalize()
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{x:02x}"))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let fingerprint = bytes.join(":").to_lowercase();
|
||||||
|
fingerprint
|
||||||
|
}
|
||||||
|
|
||||||
/// load_key_and_certificate reads certificates or key from file
|
/// load_key_and_certificate reads certificates or key from file
|
||||||
pub fn load_key_and_certificate(
|
pub fn load_key_and_certificate(
|
||||||
key_path: PathBuf,
|
key_path: PathBuf,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ pub mod capture_test;
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
mod connect;
|
mod connect;
|
||||||
#[allow(unused)]
|
|
||||||
mod crypto;
|
mod crypto;
|
||||||
mod dns;
|
mod dns;
|
||||||
mod emulation;
|
mod emulation;
|
||||||
|
|||||||
@@ -2,8 +2,13 @@ use futures::{Stream, StreamExt};
|
|||||||
use lan_mouse_proto::{ProtoEvent, MAX_EVENT_SIZE};
|
use lan_mouse_proto::{ProtoEvent, MAX_EVENT_SIZE};
|
||||||
use local_channel::mpsc::{channel, Receiver, Sender};
|
use local_channel::mpsc::{channel, Receiver, Sender};
|
||||||
use rustls::pki_types::CertificateDer;
|
use rustls::pki_types::CertificateDer;
|
||||||
use sha2::{Digest, Sha256};
|
use std::{
|
||||||
use std::{net::SocketAddr, rc::Rc, sync::Arc, time::Duration};
|
collections::HashMap,
|
||||||
|
net::SocketAddr,
|
||||||
|
rc::Rc,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
sync::Mutex,
|
sync::Mutex,
|
||||||
@@ -16,6 +21,8 @@ use webrtc_dtls::{
|
|||||||
};
|
};
|
||||||
use webrtc_util::{conn::Listener, Conn, Error};
|
use webrtc_util::{conn::Listener, Conn, Error};
|
||||||
|
|
||||||
|
use crate::crypto;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum ListenerCreationError {
|
pub enum ListenerCreationError {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
@@ -38,29 +45,31 @@ type VerifyPeerCertificateFn = Arc<
|
|||||||
>;
|
>;
|
||||||
|
|
||||||
impl LanMouseListener {
|
impl LanMouseListener {
|
||||||
pub(crate) async fn new(port: u16) -> Result<Self, ListenerCreationError> {
|
pub(crate) async fn new(
|
||||||
|
port: u16,
|
||||||
|
authorized_keys: Arc<RwLock<HashMap<String, String>>>,
|
||||||
|
) -> Result<Self, ListenerCreationError> {
|
||||||
let (listen_tx, listen_rx) = channel();
|
let (listen_tx, listen_rx) = channel();
|
||||||
|
|
||||||
let listen_addr = SocketAddr::new("0.0.0.0".parse().expect("invalid ip"), port);
|
let listen_addr = SocketAddr::new("0.0.0.0".parse().expect("invalid ip"), port);
|
||||||
let certificate = Certificate::generate_self_signed(["localhost".to_owned()])?;
|
let certificate = Certificate::generate_self_signed(["localhost".to_owned()])?;
|
||||||
let verify_peer_certificate: Option<VerifyPeerCertificateFn> = Some(Arc::new(
|
let verify_peer_certificate: Option<VerifyPeerCertificateFn> = Some(Arc::new(
|
||||||
|certs: &[Vec<u8>], _chains: &[CertificateDer<'static>]| {
|
move |certs: &[Vec<u8>], _chains: &[CertificateDer<'static>]| {
|
||||||
|
assert!(certs.len() == 1);
|
||||||
let fingerprints = certs
|
let fingerprints = certs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|cert| {
|
.map(|c| crypto::generate_fingerprint(c))
|
||||||
let mut hash = Sha256::new();
|
|
||||||
hash.update(cert);
|
|
||||||
let bytes = hash
|
|
||||||
.finalize()
|
|
||||||
.iter()
|
|
||||||
.map(|x| format!("{x:02x}"))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let fingerprint = bytes.join(":").to_lowercase();
|
|
||||||
fingerprint
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
log::info!("fingerprints: {fingerprints:?}");
|
log::info!("fingerprints: {fingerprints:?}");
|
||||||
Ok(())
|
if authorized_keys
|
||||||
|
.read()
|
||||||
|
.expect("lock")
|
||||||
|
.contains_key(&fingerprints[0])
|
||||||
|
{
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(webrtc_dtls::Error::ErrVerifyDataMismatch)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
let cfg = Config {
|
let cfg = Config {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ use crate::{
|
|||||||
client::ClientManager,
|
client::ClientManager,
|
||||||
config::Config,
|
config::Config,
|
||||||
connect::LanMouseConnection,
|
connect::LanMouseConnection,
|
||||||
|
crypto,
|
||||||
dns::DnsResolver,
|
dns::DnsResolver,
|
||||||
emulation::Emulation,
|
emulation::Emulation,
|
||||||
listen::{LanMouseListener, ListenerCreationError},
|
listen::{LanMouseListener, ListenerCreationError},
|
||||||
@@ -20,6 +21,7 @@ use std::{
|
|||||||
io,
|
io,
|
||||||
net::{IpAddr, SocketAddr},
|
net::{IpAddr, SocketAddr},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tokio::{signal, sync::Notify};
|
use tokio::{signal, sync::Notify};
|
||||||
@@ -42,10 +44,11 @@ pub struct ReleaseToken;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
active: Rc<Cell<Option<ClientHandle>>>,
|
active: Rc<Cell<Option<ClientHandle>>>,
|
||||||
authorized_keys: Rc<RefCell<HashSet<String>>>,
|
authorized_keys: Arc<RwLock<HashMap<String, String>>>,
|
||||||
known_hosts: Rc<RefCell<HashSet<String>>>,
|
known_hosts: Rc<RefCell<HashSet<String>>>,
|
||||||
pub(crate) client_manager: ClientManager,
|
pub(crate) client_manager: ClientManager,
|
||||||
port: Rc<Cell<u16>>,
|
port: Rc<Cell<u16>>,
|
||||||
|
public_key_fingerprint: String,
|
||||||
notifies: Rc<Notifies>,
|
notifies: Rc<Notifies>,
|
||||||
pub(crate) config: Rc<Config>,
|
pub(crate) config: Rc<Config>,
|
||||||
pending_frontend_events: Rc<RefCell<VecDeque<FrontendEvent>>>,
|
pending_frontend_events: Rc<RefCell<VecDeque<FrontendEvent>>>,
|
||||||
@@ -95,6 +98,7 @@ impl Server {
|
|||||||
active: Rc::new(Cell::new(None)),
|
active: Rc::new(Cell::new(None)),
|
||||||
authorized_keys: Default::default(),
|
authorized_keys: Default::default(),
|
||||||
known_hosts: Default::default(),
|
known_hosts: Default::default(),
|
||||||
|
public_key_fingerprint: "87:f9:d9:a6:c4:a1:14:d2:c8:25:4f:72:b7:01:86:65:73:cc:bc:a1:37:cc:96:69:f8:f4:72:8a:60:9a:3b:4d".to_owned(),
|
||||||
config,
|
config,
|
||||||
client_manager,
|
client_manager,
|
||||||
port,
|
port,
|
||||||
@@ -118,8 +122,11 @@ impl Server {
|
|||||||
e => e?,
|
e => e?,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// let cert = crypto::load_key_and_certificate(config.sk_path, config.pk_path)?;
|
||||||
|
|
||||||
// listener + connection
|
// listener + connection
|
||||||
let listener = LanMouseListener::new(self.config.port).await?;
|
let listener =
|
||||||
|
LanMouseListener::new(self.config.port, self.authorized_keys.clone()).await?;
|
||||||
let conn = LanMouseConnection::new(self.clone());
|
let conn = LanMouseConnection::new(self.clone());
|
||||||
|
|
||||||
// input capture + emulation
|
// input capture + emulation
|
||||||
@@ -257,28 +264,34 @@ impl Server {
|
|||||||
self.notify_frontend(FrontendEvent::EmulationStatus(self.emulation_status.get()));
|
self.notify_frontend(FrontendEvent::EmulationStatus(self.emulation_status.get()));
|
||||||
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
self.notify_frontend(FrontendEvent::CaptureStatus(self.capture_status.get()));
|
||||||
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
self.notify_frontend(FrontendEvent::PortChanged(self.port.get(), None));
|
||||||
|
self.notify_frontend(FrontendEvent::PublicKeyFingerprint(
|
||||||
|
self.public_key_fingerprint.clone(),
|
||||||
|
));
|
||||||
|
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
||||||
|
self.authorized_keys.read().expect("lock").clone(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
FrontendRequest::FingerprintAdd(key) => {
|
FrontendRequest::AuthorizeKey(desc, fp) => {
|
||||||
self.add_authorized_key(key);
|
self.add_authorized_key(desc, fp);
|
||||||
}
|
}
|
||||||
FrontendRequest::FingerprintRemove(key) => {
|
FrontendRequest::RemoveAuthorizedKey(key) => {
|
||||||
self.remove_authorized_key(key);
|
self.remove_authorized_key(key);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_authorized_key(&self, key: String) {
|
fn add_authorized_key(&self, desc: String, fp: String) {
|
||||||
self.authorized_keys.borrow_mut().insert(key);
|
self.authorized_keys.write().expect("lock").insert(fp, desc);
|
||||||
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
||||||
self.authorized_keys.borrow().clone(),
|
self.authorized_keys.read().expect("lock").clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_authorized_key(&self, key: String) {
|
fn remove_authorized_key(&self, fp: String) {
|
||||||
self.authorized_keys.borrow_mut().remove(&key);
|
self.authorized_keys.write().expect("lock").remove(&fp);
|
||||||
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
self.notify_frontend(FrontendEvent::AuthorizedUpdated(
|
||||||
self.authorized_keys.borrow().clone(),
|
self.authorized_keys.read().expect("lock").clone(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user