From 9c9039bdcd3f829ff0cfee5153b0435e0d209114 Mon Sep 17 00:00:00 2001 From: Lia Lenckowski Date: Thu, 15 Aug 2024 00:28:47 +0200 Subject: RemoveNetwork, merging AddNetwork (both untested xD) --- Cargo.lock | 1 - Cargo.toml | 1 - src/daemon_dbus.rs | 135 ++++++++++++++++++++++++++++++++++++++++++++--------- vpn-notes | 9 ++++ 4 files changed, 122 insertions(+), 24 deletions(-) create mode 100644 vpn-notes diff --git a/Cargo.lock b/Cargo.lock index 31fd936..d71400c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -490,7 +490,6 @@ name = "mäsch" version = "0.1.0" dependencies = [ "atomic-write-file", - "base64", "clap", "dbus", "dbus-crossroads", diff --git a/Cargo.toml b/Cargo.toml index 1d1fb6e..098c381 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] atomic-write-file = "0" -base64 = "0" clap = { version = "4.5.13", features = ["derive"] } dbus = "0" dbus-crossroads = "0" diff --git a/src/daemon_dbus.rs b/src/daemon_dbus.rs index 5ed4d94..f0873f0 100644 --- a/src/daemon_dbus.rs +++ b/src/daemon_dbus.rs @@ -1,4 +1,3 @@ -use base64::prelude::*; use dbus::{ channel::{MatchingReceiver, Token}, message::MatchRule, @@ -22,7 +21,11 @@ pub async fn start_dbus( ) -> Result<(Arc, Token), DaemonError> { let mut cr = Crossroads::new(); let if_token = cr.register("de.a.maesch", move |b| { - b.signal::<(String, String), _>("Proposal", ("network", "peer_data")); + //b.signal::<(String, String), _>("Proposal", ("network", "peer_data")); + + let state_rem_network = state.clone(); + let config_path_rem_network = config_path.clone(); + b.method_with_cr_async( "AddNetwork", ("name", "key", "ip", "listen_port", "maesch_port"), @@ -32,6 +35,20 @@ pub async fn start_dbus( handle_add_network(ctx, state.clone(), config_path.clone(), args) }, ); + b.method_with_cr_async( + "RemoveNetwork", + ("name",), + ("success",), + move |ctx, _, args: (String,)| { + debug!("Received RemoveNetwork"); + handle_remove_network( + ctx, + state_rem_network.clone(), + config_path_rem_network.clone(), + args, + ) + }, + ); }); cr.insert("/de/a/maesch", &[if_token], ()); @@ -59,29 +76,84 @@ pub async fn start_dbus( Ok((c, receive_token)) } -// TODO also take peers +pub async fn handle_remove_network( + mut ctx: Context, + state: Arc>, + config_path: PathBuf, + (name,): (String,), +) -> PhantomData<(bool,)> { + let mut state_rw_guard = state.write().await; + + if let Some(_) = state_rw_guard.conf.networks.remove(&name) { + let (wg_api, h) = state_rw_guard + .nw_handles + .remove(&name) + .expect("state.conf.networks and state.nw_handles desynced"); + h.abort(); + + let ri = wg_api.remove_interface(); + let _ = h.await; + + match write_config(&state_rw_guard.conf, &config_path) { + Ok(_) => info!("Synced config"), + Err(e) => { + error!("Couldn't sync config: {e}"); + return ctx.reply(Err(MethodErr::failed(&e))); + } + }; + drop(state_rw_guard); + + match ri { + Ok(_) => info!("Removed network: {name}"), + Err(e) => { + error!("Removing network: {e}"); + return ctx.reply(Err(MethodErr::failed(&e))); + } + }; + } else { + warn!("Tried to remove non-existent network: {name}"); + return ctx.reply(Err(MethodErr::invalid_arg("bad network"))); + } + + ctx.reply(Ok((true,))) +} + +// TODO make this merge correctly... pub async fn handle_add_network( mut ctx: Context, state: Arc>, config_path: PathBuf, (name, may_key, may_ip, may_lp, may_mp): (String, String, String, u16, u16), ) -> PhantomData<(bool,)> { - // NOTE: this is kinda stupid: we convert to a string later anyways, as thats what - // defguard_wg takes... - let key = Key::new(match may_key.as_str() { - "" => rand::thread_rng().gen(), - _ => match BASE64_STANDARD.decode(may_key) { - Ok(v) if v.len() == 32 => v.try_into().unwrap(), - _ => { - warn!("AddNetwork with bad key"); - return ctx.reply(Err(MethodErr::invalid_arg("bad key"))); - } - }, - }); + let mut state_rw_guard = state.write().await; + let state_rw = state_rw_guard.deref_mut(); + + // TODO do more with the entry... + let prev_entry = state_rw.conf.networks.remove(&name); + + let key = if may_key.as_str() == "" { + prev_entry + .as_ref() + .map(|nw| nw.privkey.clone()) + .unwrap_or_else(|| Key::new(rand::thread_rng().gen()).to_string()) + } else { + may_key + }; // we store the ip as the original string, but should validate it regardless let (ip, ip_string) = match may_ip.as_str() { - "" => todo!(), + "" => match prev_entry.as_ref() { + Some(e) => ( + IpAddrMask::from_str(&e.address) + .expect("Impossible: old config broken!") + .ip, + e.address.clone(), + ), + None => { + warn!("AddNetwork with no ip"); + return ctx.reply(Err(MethodErr::invalid_arg("ip required"))); + } + }, _ => match IpAddrMask::from_str(&may_ip) { Ok(ip_mask) => (ip_mask.ip, may_ip), Err(_) => { @@ -91,13 +163,24 @@ pub async fn handle_add_network( }, }; - let lp = if may_lp == 0 { 25565 } else { may_lp }; - let mp = if may_mp == 0 { 51820 } else { may_mp }; + let lp = if may_lp == 0 { + prev_entry + .as_ref() + .map(|nw| nw.listen_port) + .unwrap_or(25565) + } else { + may_lp + }; + let mp = if may_mp == 0 { + prev_entry.as_ref().map(|nw| nw.mäsch_port).unwrap_or(51820) + } else { + may_mp + }; let (wg_api, hostnames) = match add_network( name.clone(), - key.to_string(), - ip_string, + key.clone(), + ip_string.clone(), lp, &HashMap::new(), ) @@ -124,9 +207,17 @@ pub async fn handle_add_network( name.clone(), ))); - let mut state_rw_guard = state.write().await; - let state_rw = state_rw_guard.deref_mut(); state_rw.nw_handles.insert(name.clone(), (wg_api, h)); + state_rw.conf.networks.insert( + name, + Network { + privkey: key, + address: ip_string, + listen_port: lp, + peers: prev_entry.map_or_else(|| HashMap::new(), |nw| nw.peers), + mäsch_port: mp, + }, + ); // NOTE this _is_ thread-safe, as we hold an exclusive write handle to the state. match write_config(&state_rw.conf, &config_path) { diff --git a/vpn-notes b/vpn-notes new file mode 100644 index 0000000..36a38cf --- /dev/null +++ b/vpn-notes @@ -0,0 +1,9 @@ +- pull on network join, and on command +- cli: + - add/update network + - add/update list of peers + - remove peer + - remove network + - list pending, remotely-received peers to merge <- must be transformed to add/update peer call in frontend + - delete pending peer by id + - send list of peers to peer. list of peers provided by the frontend. -- cgit v1.2.3-70-g09d2