diff options
| -rw-r--r-- | mullvad-api/src/https_client_with_sni.rs | 4 | ||||
| -rw-r--r-- | mullvad-api/src/proxy.rs | 14 | ||||
| -rw-r--r-- | mullvad-cli/src/cmds/api_access.rs | 237 | ||||
| -rw-r--r-- | mullvad-daemon/src/access_method.rs | 33 | ||||
| -rw-r--r-- | mullvad-daemon/src/api.rs | 20 | ||||
| -rw-r--r-- | mullvad-daemon/src/lib.rs | 39 | ||||
| -rw-r--r-- | mullvad-daemon/src/management_interface.rs | 34 | ||||
| -rw-r--r-- | mullvad-management-interface/proto/management_interface.proto | 38 | ||||
| -rw-r--r-- | mullvad-management-interface/src/client.rs | 56 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types/conversions/access_method.rs | 258 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types/conversions/api_access_method.rs | 288 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types/conversions/mod.rs | 2 | ||||
| -rw-r--r-- | mullvad-management-interface/src/types/conversions/settings.rs | 2 | ||||
| -rw-r--r-- | mullvad-types/src/access_method.rs (renamed from mullvad-types/src/api_access.rs) | 52 | ||||
| -rw-r--r-- | mullvad-types/src/lib.rs | 2 | ||||
| -rw-r--r-- | mullvad-types/src/settings/mod.rs | 6 |
16 files changed, 511 insertions, 574 deletions
diff --git a/mullvad-api/src/https_client_with_sni.rs b/mullvad-api/src/https_client_with_sni.rs index e95fbf98fc..cc7557a8d2 100644 --- a/mullvad-api/src/https_client_with_sni.rs +++ b/mullvad-api/src/https_client_with_sni.rs @@ -248,12 +248,12 @@ impl TryFrom<ApiConnectionMode> for InnerConnectionMode { }) } ProxyConfig::Socks(config) => match config { - mullvad_types::api_access::Socks5::Local(config) => { + mullvad_types::access_method::Socks5::Local(config) => { InnerConnectionMode::Socks5(SocksConfig { peer: SocketAddr::new("127.0.0.1".parse().unwrap(), config.port), }) } - mullvad_types::api_access::Socks5::Remote(config) => { + mullvad_types::access_method::Socks5::Remote(config) => { InnerConnectionMode::Socks5(SocksConfig { peer: config.peer }) } }, diff --git a/mullvad-api/src/proxy.rs b/mullvad-api/src/proxy.rs index 7d33840d69..44a2309587 100644 --- a/mullvad-api/src/proxy.rs +++ b/mullvad-api/src/proxy.rs @@ -1,6 +1,6 @@ use futures::Stream; use hyper::client::connect::Connected; -use mullvad_types::api_access; +use mullvad_types::access_method; use serde::{Deserialize, Serialize}; use std::{ fmt, io, @@ -36,8 +36,8 @@ impl fmt::Display for ApiConnectionMode { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub enum ProxyConfig { - Shadowsocks(api_access::Shadowsocks), - Socks(api_access::Socks5), + Shadowsocks(access_method::Shadowsocks), + Socks(access_method::Socks5), } impl ProxyConfig { @@ -46,8 +46,8 @@ impl ProxyConfig { match self { ProxyConfig::Shadowsocks(ss) => ss.peer, ProxyConfig::Socks(socks) => match socks { - api_access::Socks5::Local(s) => s.peer, - api_access::Socks5::Remote(s) => s.peer, + access_method::Socks5::Local(s) => s.peer, + access_method::Socks5::Remote(s) => s.peer, }, } } @@ -59,10 +59,10 @@ impl fmt::Display for ProxyConfig { // TODO: Do not hardcode TCP ProxyConfig::Shadowsocks(ss) => write!(f, "Shadowsocks {}/TCP", ss.peer), ProxyConfig::Socks(socks) => match socks { - api_access::Socks5::Local(s) => { + access_method::Socks5::Local(s) => { write!(f, "Socks5 {}/TCP via localhost:{}", s.peer, s.port) } - api_access::Socks5::Remote(s) => write!(f, "Socks5 {}/TCP", s.peer), + access_method::Socks5::Remote(s) => write!(f, "Socks5 {}/TCP", s.peer), }, } } diff --git a/mullvad-cli/src/cmds/api_access.rs b/mullvad-cli/src/cmds/api_access.rs index efb1e7bfd8..260f0c4496 100644 --- a/mullvad-cli/src/cmds/api_access.rs +++ b/mullvad-cli/src/cmds/api_access.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Result}; use mullvad_management_interface::MullvadProxyClient; -use mullvad_types::api_access::{AccessMethod, AccessMethodSetting, CustomAccessMethod}; +use mullvad_types::access_method::{AccessMethod, AccessMethodSetting, CustomAccessMethod}; use std::net::IpAddr; use clap::{Args, Subcommand}; @@ -72,8 +72,10 @@ impl ApiAccess { /// Add a custom API access method. async fn add(cmd: AddCustomCommands) -> Result<()> { let mut rpc = MullvadProxyClient::new().await?; - let access_method = AccessMethodSetting::try_from(cmd)?; - rpc.add_access_method(access_method).await?; + let name = cmd.name(); + let enabled = cmd.enabled(); + let access_method = AccessMethod::try_from(cmd)?; + rpc.add_access_method(name, enabled, access_method).await?; Ok(()) } @@ -89,60 +91,46 @@ impl ApiAccess { /// Edit the data of an API access method. async fn edit(cmd: EditCustomCommands) -> Result<()> { let mut rpc = MullvadProxyClient::new().await?; - let api_access_method = Self::get_access_method(&mut rpc, &cmd.item).await?; - let id = api_access_method.get_id(); - let access_method = api_access_method - .as_custom() - .cloned() - .ok_or(anyhow!("Can not edit built-in access method"))?; + let mut api_access_method = Self::get_access_method(&mut rpc, &cmd.item).await?; // Create a new access method combining the new params with the previous values - let edited_access_method: AccessMethodSetting = match access_method { - CustomAccessMethod::Shadowsocks(shadowsocks) => { - let ip = cmd.params.ip.unwrap_or(shadowsocks.peer.ip()).to_string(); - let port = cmd.params.port.unwrap_or(shadowsocks.peer.port()); - let password = cmd.params.password.unwrap_or(shadowsocks.password); - let cipher = cmd.params.cipher.unwrap_or(shadowsocks.cipher); - let name = cmd.params.name.unwrap_or(api_access_method.name); - let enabled = api_access_method.enabled; - mullvad_types::api_access::Shadowsocks::from_args(ip, port, cipher, password).map( - |shadowsocks| { - AccessMethodSetting::new(name, enabled, AccessMethod::from(shadowsocks)) - }, - ) - } - CustomAccessMethod::Socks5(socks) => match socks { - mullvad_types::api_access::Socks5::Local(local) => { - let ip = cmd.params.ip.unwrap_or(local.peer.ip()).to_string(); - let port = cmd.params.port.unwrap_or(local.peer.port()); - let local_port = cmd.params.local_port.unwrap_or(local.port); - let name = cmd.params.name.unwrap_or(api_access_method.get_name()); - let enabled = api_access_method.enabled(); - mullvad_types::api_access::Socks5Local::from_args(ip, port, local_port).map( - |socks| AccessMethodSetting::new(name, enabled, AccessMethod::from(socks)), - ) - } - mullvad_types::api_access::Socks5::Remote(remote) => { - let ip = cmd.params.ip.unwrap_or(remote.peer.ip()).to_string(); - let port = cmd.params.port.unwrap_or(remote.peer.port()); - let name = cmd.params.name.unwrap_or(api_access_method.get_name()); - let enabled = api_access_method.enabled(); - mullvad_types::api_access::Socks5Remote::from_args(ip, port).map(|socks| { - AccessMethodSetting::new(name, enabled, AccessMethod::from(socks)) - }) + let access_method = match api_access_method.as_custom() { + None => return Err(anyhow!("Can not edit built-in access method")), + Some(x) => match x.clone() { + CustomAccessMethod::Shadowsocks(shadowsocks) => { + let ip = cmd.params.ip.unwrap_or(shadowsocks.peer.ip()).to_string(); + let port = cmd.params.port.unwrap_or(shadowsocks.peer.port()); + let password = cmd.params.password.unwrap_or(shadowsocks.password); + let cipher = cmd.params.cipher.unwrap_or(shadowsocks.cipher); + mullvad_types::access_method::Shadowsocks::from_args(ip, port, cipher, password) + .map(AccessMethod::from) } + CustomAccessMethod::Socks5(socks) => match socks { + mullvad_types::access_method::Socks5::Local(local) => { + let ip = cmd.params.ip.unwrap_or(local.peer.ip()).to_string(); + let port = cmd.params.port.unwrap_or(local.peer.port()); + let local_port = cmd.params.local_port.unwrap_or(local.port); + mullvad_types::access_method::Socks5Local::from_args(ip, port, local_port) + .map(AccessMethod::from) + } + mullvad_types::access_method::Socks5::Remote(remote) => { + let ip = cmd.params.ip.unwrap_or(remote.peer.ip()).to_string(); + let port = cmd.params.port.unwrap_or(remote.peer.port()); + mullvad_types::access_method::Socks5Remote::from_args(ip, port) + .map(AccessMethod::from) + } + }, }, + }; + + if let Some(name) = cmd.params.name { + api_access_method.name = name; + }; + if let Some(access_method) = access_method { + api_access_method.access_method = access_method; } - .ok_or(anyhow!( - "Could not edit access method {}, reverting changes.", - cmd.item - ))?; - rpc.update_access_method(ApiAccessMethodUpdate { - id, - access_method: edited_access_method, - }) - .await?; + rpc.update_access_method(api_access_method).await?; Ok(()) } @@ -169,7 +157,7 @@ impl ApiAccess { let access_method = Self::get_access_method(&mut rpc, &item).await?; rpc.set_access_method(access_method.get_id()).await?; // Make the daemon perform an network request which involves talking to the Mullvad API. - match rpc.get_api_addressess().await { + match rpc.get_api_addresses().await { Ok(_) => println!("Connected to the Mullvad API!"), Err(_) => println!( "Could *not* connect to the Mullvad API using access method \"{}\"", @@ -204,32 +192,8 @@ impl ApiAccess { #[derive(Subcommand, Debug, Clone)] pub enum AddCustomCommands { - /// Configure SOCKS5 proxy - #[clap(subcommand)] - Socks5(Socks5AddCommands), - - /// Configure Shadowsocks proxy - Shadowsocks { - /// An easy to remember name for this custom proxy - name: String, - /// The IP of the remote Shadowsocks server - remote_ip: IpAddr, - /// The port of the remote Shadowsocks server - #[arg(default_value = "443")] - remote_port: u16, - /// Password for authentication - #[arg(default_value = "mullvad")] - password: String, - /// Cipher to use - #[arg(value_parser = SHADOWSOCKS_CIPHERS, default_value = "aes-256-gcm")] - cipher: String, - }, -} - -#[derive(Subcommand, Debug, Clone)] -pub enum Socks5AddCommands { /// Configure a local SOCKS5 proxy - Local { + Socks5Local { /// An easy to remember name for this custom proxy name: String, /// The port that the server on localhost is listening on @@ -240,7 +204,7 @@ pub enum Socks5AddCommands { remote_port: u16, }, /// Configure a remote SOCKS5 proxy - Remote { + Socks5Remote { /// An easy to remember name for this custom proxy name: String, /// The IP of the remote proxy server @@ -248,6 +212,37 @@ pub enum Socks5AddCommands { /// The port of the remote proxy server remote_port: u16, }, + /// Configure Shadowsocks proxy + Shadowsocks { + /// An easy to remember name for this custom proxy + name: String, + /// The IP of the remote Shadowsocks server + remote_ip: IpAddr, + /// The port of the remote Shadowsocks server + #[arg(default_value = "443")] + remote_port: u16, + /// Password for authentication + #[arg(default_value = "mullvad")] + password: String, + /// Cipher to use + #[arg(value_parser = SHADOWSOCKS_CIPHERS, default_value = "aes-256-gcm")] + cipher: String, + }, +} + +impl AddCustomCommands { + fn name(&self) -> String { + match self { + AddCustomCommands::Socks5Local { name, .. } => name, + AddCustomCommands::Socks5Remote { name, .. } => name, + AddCustomCommands::Shadowsocks { name, .. } => name, + } + .clone() + } + /// TODO: Actually add an `enabled` flag to the variants of `AddCustomCommands` + fn enabled(&self) -> bool { + true + } } /// A minimal wrapper type allowing the user to supply a list index to some @@ -311,65 +306,50 @@ pub struct EditParams { /// we define them in a hidden-away module. mod conversions { use anyhow::{anyhow, Error}; - use mullvad_types::api_access as daemon_types; + use mullvad_types::access_method as daemon_types; - use super::{AddCustomCommands, Socks5AddCommands}; + use super::AddCustomCommands; - impl TryFrom<AddCustomCommands> for daemon_types::AccessMethodSetting { + impl TryFrom<AddCustomCommands> for daemon_types::AccessMethod { type Error = Error; fn try_from(value: AddCustomCommands) -> Result<Self, Self::Error> { - // All api proxies are automatically enabled from the start. - let enabled = true; Ok(match value { - AddCustomCommands::Socks5(variant) => match variant { - Socks5AddCommands::Local { - local_port, - remote_ip, - remote_port, - name, - } => { - println!("Adding Local SOCKS5-proxy: localhost:{local_port} => {remote_ip}:{remote_port}"); - let socks_proxy = daemon_types::Socks5::Local( - daemon_types::Socks5Local::from_args( - remote_ip.to_string(), - remote_port, - local_port, - ) - .ok_or(anyhow!("Could not create a local Socks5 api proxy"))?, - ); - daemon_types::AccessMethodSetting::new( - name, - enabled, - daemon_types::AccessMethod::from(socks_proxy), + AddCustomCommands::Socks5Local { + local_port, + remote_ip, + remote_port, + name: _, + } => { + println!("Adding Local SOCKS5-proxy: localhost:{local_port} => {remote_ip}:{remote_port}"); + let socks_proxy = daemon_types::Socks5::Local( + daemon_types::Socks5Local::from_args( + remote_ip.to_string(), + remote_port, + local_port, ) - } - Socks5AddCommands::Remote { - remote_ip, - remote_port, - name, - } => { - println!("Adding SOCKS5-proxy: {remote_ip}:{remote_port}"); - let socks_proxy = daemon_types::Socks5::Remote( - daemon_types::Socks5Remote::from_args( - remote_ip.to_string(), - remote_port, - ) + .ok_or(anyhow!("Could not create a local Socks5 api proxy"))?, + ); + daemon_types::AccessMethod::from(socks_proxy) + } + AddCustomCommands::Socks5Remote { + remote_ip, + remote_port, + name: _, + } => { + println!("Adding SOCKS5-proxy: {remote_ip}:{remote_port}"); + let socks_proxy = daemon_types::Socks5::Remote( + daemon_types::Socks5Remote::from_args(remote_ip.to_string(), remote_port) .ok_or(anyhow!("Could not create a remote Socks5 api proxy"))?, - ); - daemon_types::AccessMethodSetting::new( - name, - enabled, - daemon_types::AccessMethod::from(socks_proxy), - ) - } - }, + ); + daemon_types::AccessMethod::from(socks_proxy) + } AddCustomCommands::Shadowsocks { remote_ip, remote_port, password, cipher, - name, + name: _, } => { println!( "Adding Shadowsocks-proxy: {password} @ {remote_ip}:{remote_port} using {cipher}" @@ -381,12 +361,7 @@ mod conversions { password, ) .ok_or(anyhow!("Could not create a Shadowsocks api proxy"))?; - - daemon_types::AccessMethodSetting::new( - name, - enabled, - daemon_types::AccessMethod::from(shadowsocks_proxy), - ) + daemon_types::AccessMethod::from(shadowsocks_proxy) } }) } @@ -395,7 +370,7 @@ mod conversions { /// Pretty printing of [`ApiAccessMethod`]s mod pp { - use mullvad_types::api_access::{ + use mullvad_types::access_method::{ AccessMethod, AccessMethodSetting, CustomAccessMethod, Socks5, }; diff --git a/mullvad-daemon/src/access_method.rs b/mullvad-daemon/src/access_method.rs index a3ece35ecb..0501a4336c 100644 --- a/mullvad-daemon/src/access_method.rs +++ b/mullvad-daemon/src/access_method.rs @@ -2,9 +2,7 @@ use crate::{ settings::{self, MadeChanges}, Daemon, EventListener, }; -use mullvad_types::access_method::{ - daemon::ApiAccessMethodUpdate, ApiAccessMethod, ApiAccessMethodId, -}; +use mullvad_types::access_method::{self, AccessMethod, AccessMethodSetting}; #[derive(err_derive::Error, Debug)] pub enum Error { @@ -16,7 +14,7 @@ pub enum Error { RemoveBuiltIn, /// Can not find access method #[error(display = "Cannot find custom access method {}", _0)] - NoSuchMethod(ApiAccessMethodId), + NoSuchMethod(access_method::Id), /// Access methods settings error #[error(display = "Settings error")] Settings(#[error(source)] settings::Error), @@ -28,18 +26,23 @@ where { pub async fn add_access_method( &mut self, - access_method: AccessMethodSetting, - ) -> Result<(), Error> { + name: String, + enabled: bool, + access_method: AccessMethod, + ) -> Result<access_method::Id, Error> { + let access_method_setting = AccessMethodSetting::new(name, enabled, access_method); + let id = access_method_setting.get_id(); self.settings - .update(|settings| settings.api_access_methods.append(access_method)) + .update(|settings| settings.api_access_methods.append(access_method_setting)) .await .map(|did_change| self.notify_on_change(did_change)) + .map(|_| id) .map_err(Error::Settings) } pub async fn remove_access_method( &mut self, - access_method: ApiAccessMethodId, + access_method: access_method::Id, ) -> Result<(), Error> { // Make sure that we are not trying to remove a built-in API access // method @@ -59,15 +62,19 @@ where .map_err(Error::Settings) } + /// "Updates" an [`AccessMethodSetting`] by replacing the existing entry + /// with the argument `access_method_update` if an existing entry with + /// matching UUID is found. pub async fn update_access_method( &mut self, - access_method_update: ApiAccessMethodUpdate, + access_method_update: AccessMethodSetting, ) -> Result<(), Error> { self.settings .update(|settings| { let access_methods = &mut settings.api_access_methods; - if let Some(access_method) = access_methods.find_mut(&access_method_update.id) { - *access_method = access_method_update.access_method + if let Some(access_method) = access_methods.find_mut(&access_method_update.get_id()) + { + *access_method = access_method_update } }) .await @@ -75,7 +82,7 @@ where .map_err(Error::Settings) } - pub fn set_api_access_method(&mut self, access_method: ApiAccessMethodId) -> Result<(), Error> { + pub fn set_api_access_method(&mut self, access_method: access_method::Id) -> Result<(), Error> { if let Some(access_method) = self.settings.api_access_methods.find(&access_method) { { let mut connection_modes = self.connection_modes.lock().unwrap(); @@ -99,7 +106,7 @@ where connection_modes.update_access_methods( self.settings .api_access_methods - .api_access_methods + .access_method_settings .iter() .filter(|api_access_method| api_access_method.enabled()) .map(|api_access_method| api_access_method.access_method.clone()) diff --git a/mullvad-daemon/src/api.rs b/mullvad-daemon/src/api.rs index c5a5bda73e..8c8af4d4dc 100644 --- a/mullvad-daemon/src/api.rs +++ b/mullvad-daemon/src/api.rs @@ -10,7 +10,7 @@ use mullvad_api::{ ApiEndpointUpdateCallback, }; use mullvad_relay_selector::RelaySelector; -use mullvad_types::api_access::{self, AccessMethod, BuiltInAccessMethod}; +use mullvad_types::access_method::{self, AccessMethod, BuiltInAccessMethod}; use std::{ net::SocketAddr, path::PathBuf, @@ -39,7 +39,6 @@ pub struct ApiConnectionModeProvider { cache_dir: PathBuf, /// Used for selecting a Relay when the `Mullvad Bridges` access method is used. relay_selector: RelaySelector, - retry_attempt: u32, current_task: Option<Pin<Box<dyn Future<Output = ApiConnectionMode> + Send>>>, connection_modes: Arc<Mutex<ConnectionModesIterator>>, } @@ -63,7 +62,6 @@ impl Stream for ApiConnectionModeProvider { } let connection_mode = self.new_connection_mode(); - self.retry_attempt = self.retry_attempt.wrapping_add(1); let cache_dir = self.cache_dir.clone(); self.current_task = Some(Box::pin(async move { @@ -89,7 +87,6 @@ impl ApiConnectionModeProvider { Self { cache_dir, relay_selector, - retry_attempt: 0, current_task: None, connection_modes: Arc::new(Mutex::new(ConnectionModesIterator::new(connection_modes))), } @@ -131,11 +128,12 @@ impl ApiConnectionModeProvider { .get_bridge_forced() .and_then(|settings| match settings { ProxySettings::Shadowsocks(ss_settings) => { - let ss_settings: api_access::Shadowsocks = api_access::Shadowsocks::new( - ss_settings.peer, - ss_settings.cipher, - ss_settings.password, - ); + let ss_settings: access_method::Shadowsocks = + access_method::Shadowsocks::new( + ss_settings.peer, + ss_settings.cipher, + ss_settings.password, + ); Some(ApiConnectionMode::Proxied(ProxyConfig::Shadowsocks( ss_settings, ))) @@ -148,10 +146,10 @@ impl ApiConnectionModeProvider { .unwrap_or(ApiConnectionMode::Direct), }, AccessMethod::Custom(access_method) => match &access_method { - api_access::CustomAccessMethod::Shadowsocks(shadowsocks_config) => { + access_method::CustomAccessMethod::Shadowsocks(shadowsocks_config) => { ApiConnectionMode::Proxied(ProxyConfig::Shadowsocks(shadowsocks_config.clone())) } - api_access::CustomAccessMethod::Socks5(socks_config) => { + access_method::CustomAccessMethod::Socks5(socks_config) => { ApiConnectionMode::Proxied(ProxyConfig::Socks(socks_config.clone())) } }, diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index cac152c843..26f7956dfb 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -39,9 +39,8 @@ use mullvad_relay_selector::{ RelaySelector, SelectorConfig, }; use mullvad_types::{ - access_method::{daemon::ApiAccessMethodUpdate, ApiAccessMethod, ApiAccessMethodId}, + access_method::{AccessMethod, AccessMethodSetting}, account::{AccountData, AccountToken, VoucherSubmission}, - api_access::{AccessMethodSetting, ApiAccessMethodId}, auth_failed::AuthFailed, custom_list::CustomList, device::{Device, DeviceEvent, DeviceEventCause, DeviceId, DeviceState, RemoveDeviceEvent}, @@ -264,13 +263,18 @@ pub enum DaemonCommand { /// Get API access methods GetApiAccessMethods(ResponseTx<Vec<AccessMethodSetting>, Error>), /// Add API access methods - AddApiAccessMethod(ResponseTx<(), Error>, AccessMethodSetting), + AddApiAccessMethod( + ResponseTx<mullvad_types::access_method::Id, Error>, + String, + bool, + AccessMethod, + ), /// Remove an API access method - RemoveApiAccessMethod(ResponseTx<(), Error>, ApiAccessMethodId), + RemoveApiAccessMethod(ResponseTx<(), Error>, mullvad_types::access_method::Id), /// Set the API access method to use - SetApiAccessMethod(ResponseTx<(), Error>, ApiAccessMethodId), + SetApiAccessMethod(ResponseTx<(), Error>, mullvad_types::access_method::Id), /// Edit an API access method - UpdateApiAccessMethod(ResponseTx<(), Error>, ApiAccessMethodUpdate), + UpdateApiAccessMethod(ResponseTx<(), Error>, AccessMethodSetting), /// Get the addresses of all known API endpoints GetApiAddresses(ResponseTx<Vec<std::net::SocketAddr>, Error>), /// Get information about the currently running and latest app versions @@ -640,7 +644,7 @@ where relay_selector.clone(), settings .api_access_methods - .api_access_methods + .access_method_settings .iter() // We only care about the access methods which are set to 'enabled' by the user. .filter(|api_access_method| api_access_method.enabled()) @@ -1064,7 +1068,10 @@ where UpdateCustomList(tx, update) => self.on_update_custom_list(tx, update).await, GetVersionInfo(tx) => self.on_get_version_info(tx), GetApiAccessMethods(tx) => self.on_get_api_access_methods(tx), - AddApiAccessMethod(tx, method) => self.on_add_api_access_method(tx, method).await, + AddApiAccessMethod(tx, name, enabled, access_method) => { + self.on_add_access_method(tx, name, enabled, access_method) + .await + } RemoveApiAccessMethod(tx, method) => self.on_remove_api_access_method(tx, method).await, UpdateApiAccessMethod(tx, method) => self.on_update_api_access_method(tx, method).await, SetApiAccessMethod(tx, method) => self.on_set_api_access_method(tx, method), @@ -2248,13 +2255,15 @@ where Self::oneshot_send(tx, result, "get_api_access_methods response"); } - async fn on_add_api_access_method( + async fn on_add_access_method( &mut self, - tx: ResponseTx<(), Error>, - method: AccessMethodSetting, + tx: ResponseTx<mullvad_types::access_method::Id, Error>, + name: String, + enabled: bool, + access_method: AccessMethod, ) { let result = self - .add_access_method(method) + .add_access_method(name, enabled, access_method) .await .map_err(Error::AccessMethodError); Self::oneshot_send(tx, result, "add_api_access_method response"); @@ -2263,7 +2272,7 @@ where async fn on_remove_api_access_method( &mut self, tx: ResponseTx<(), Error>, - api_access_method: ApiAccessMethodId, + api_access_method: mullvad_types::access_method::Id, ) { let result = self .remove_access_method(api_access_method) @@ -2275,7 +2284,7 @@ where async fn on_update_api_access_method( &mut self, tx: ResponseTx<(), Error>, - method: ApiAccessMethodUpdate, + method: AccessMethodSetting, ) { let result = self .update_access_method(method) @@ -2287,7 +2296,7 @@ where fn on_set_api_access_method( &mut self, tx: ResponseTx<(), Error>, - access_method: ApiAccessMethodId, + access_method: mullvad_types::access_method::Id, ) { let result = self .set_api_access_method(access_method) diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index eabdb11826..ce12332b3b 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -621,23 +621,30 @@ impl ManagementService for ManagementServiceImpl { async fn add_api_access_method( &self, - request: Request<types::ApiAccessMethod>, - ) -> ServiceResult<()> { + request: Request<types::NewAccessMethodSetting>, + ) -> ServiceResult<types::Uuid> { log::debug!("add_api_access_method"); - let api_access_method = - mullvad_types::api_access::AccessMethodSetting::try_from(request.into_inner())?; + let request = request.into_inner(); let (tx, rx) = oneshot::channel(); - self.send_command_to_daemon(DaemonCommand::AddApiAccessMethod(tx, api_access_method))?; + self.send_command_to_daemon(DaemonCommand::AddApiAccessMethod( + tx, + request.name, + request.enabled, + request + .access_method + .ok_or(Status::invalid_argument("Could not find access method")) + .map(mullvad_types::access_method::AccessMethod::try_from)??, + ))?; self.wait_for_result(rx) .await? + .map(types::Uuid::from) .map(Response::new) .map_err(map_daemon_error) } async fn remove_api_access_method(&self, request: Request<types::Uuid>) -> ServiceResult<()> { log::debug!("remove_api_access_method"); - let api_access_method = - mullvad_types::api_access::ApiAccessMethodId::try_from(request.into_inner())?; + let api_access_method = mullvad_types::access_method::Id::try_from(request.into_inner())?; let (tx, rx) = oneshot::channel(); self.send_command_to_daemon(DaemonCommand::RemoveApiAccessMethod(tx, api_access_method))?; self.wait_for_result(rx) @@ -648,13 +655,11 @@ impl ManagementService for ManagementServiceImpl { async fn update_api_access_method( &self, - request: Request<types::ApiAccessMethodUpdate>, + request: Request<types::AccessMethodSetting>, ) -> ServiceResult<()> { log::debug!("update_api_access_method"); let access_method_update = - mullvad_types::access_method::daemon::ApiAccessMethodUpdate::try_from( - request.into_inner(), - )?; + mullvad_types::access_method::AccessMethodSetting::try_from(request.into_inner())?; let (tx, rx) = oneshot::channel(); self.send_command_to_daemon(DaemonCommand::UpdateApiAccessMethod( tx, @@ -668,8 +673,7 @@ impl ManagementService for ManagementServiceImpl { async fn set_api_access_method(&self, request: Request<types::Uuid>) -> ServiceResult<()> { log::debug!("set_api_access_method"); - let api_access_method = - mullvad_types::api_access::ApiAccessMethodId::try_from(request.into_inner())?; + let api_access_method = mullvad_types::access_method::Id::try_from(request.into_inner())?; let (tx, rx) = oneshot::channel(); self.send_command_to_daemon(DaemonCommand::SetApiAccessMethod(tx, api_access_method))?; self.wait_for_result(rx) @@ -678,8 +682,8 @@ impl ManagementService for ManagementServiceImpl { .map_err(map_daemon_error) } - async fn get_api_addressess(&self, _: Request<()>) -> ServiceResult<()> { - log::debug!("test_api"); + async fn get_api_addresses(&self, _: Request<()>) -> ServiceResult<()> { + log::debug!("get_api_addresses"); let (tx, rx) = oneshot::channel(); self.send_command_to_daemon(DaemonCommand::GetApiAddresses(tx))?; self.wait_for_result(rx) diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 667778475a..a7b3cb11a1 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -22,7 +22,7 @@ service ManagementService { rpc GetCurrentVersion(google.protobuf.Empty) returns (google.protobuf.StringValue) {} rpc GetVersionInfo(google.protobuf.Empty) returns (AppVersionInfo) {} - rpc GetApiAddressess(google.protobuf.Empty) returns (google.protobuf.Empty) {} + rpc GetApiAddresses(google.protobuf.Empty) returns (google.protobuf.Empty) {} rpc IsPerformingPostUpgrade(google.protobuf.Empty) returns (google.protobuf.BoolValue) {} @@ -75,10 +75,10 @@ service ManagementService { rpc UpdateCustomList(CustomList) returns (google.protobuf.Empty) {} // API Access methods - rpc AddApiAccessMethod(ApiAccessMethod) returns (google.protobuf.Empty) {} + rpc AddApiAccessMethod(NewAccessMethodSetting) returns (UUID) {} rpc RemoveApiAccessMethod(UUID) returns (google.protobuf.Empty) {} rpc SetApiAccessMethod(UUID) returns (google.protobuf.Empty) {} - rpc UpdateApiAccessMethod(ApiAccessMethodUpdate) returns (google.protobuf.Empty) {} + rpc UpdateApiAccessMethod(AccessMethodSetting) returns (google.protobuf.Empty) {} // Split tunneling (Linux) rpc GetSplitTunnelProcesses(google.protobuf.Empty) returns (stream google.protobuf.Int32Value) {} @@ -333,7 +333,7 @@ message CustomList { message CustomListSettings { repeated CustomList custom_lists = 1; } -message ApiAccessMethod { +message AccessMethod { message Direct {} message Bridges {} message Socks5Local { @@ -351,28 +351,30 @@ message ApiAccessMethod { string password = 4; string cipher = 5; } + oneof access_method { + Direct direct = 1; + Bridges bridges = 2; + Socks5Local socks5local = 3; + Socks5Remote socks5remote = 4; + Shadowsocks shadowsocks = 5; + } +} +message AccessMethodSetting { UUID id = 1; string name = 2; bool enabled = 3; - oneof access_method { - Direct direct = 4; - Bridges bridges = 5; - Socks5Local socks5local = 6; - Socks5Remote socks5remote = 7; - Shadowsocks shadowsocks = 8; - } + AccessMethod access_method = 4; } -message ApiAccessMethods { repeated ApiAccessMethod api_access_methods = 1; } - -message ApiAccessMethodSettings { repeated ApiAccessMethod api_access_methods = 1; } - -message ApiAccessMethodUpdate { - UUID id = 1; - ApiAccessMethod access_method = 2; +message NewAccessMethodSetting { + string name = 1; + bool enabled = 2; + AccessMethod access_method = 3; } +message ApiAccessMethodSettings { repeated AccessMethodSetting access_method_settings = 1; } + message Settings { RelaySettings relay_settings = 1; BridgeSettings bridge_settings = 2; diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs index a7de6ae55f..aafee5b5c5 100644 --- a/mullvad-management-interface/src/client.rs +++ b/mullvad-management-interface/src/client.rs @@ -3,9 +3,8 @@ use crate::types; use futures::{Stream, StreamExt}; use mullvad_types::{ - access_method::{daemon::ApiAccessMethodUpdate, ApiAccessMethod, ApiAccessMethodId}, + access_method::{self, AccessMethod, AccessMethodSetting}, account::{AccountData, AccountToken, VoucherSubmission}, - api_access::{AccessMethodSetting, ApiAccessMethodId}, custom_list::{CustomList, Id}, device::{Device, DeviceEvent, DeviceId, DeviceState, RemoveDeviceEvent}, location::GeoIpLocation, @@ -173,7 +172,7 @@ impl MullvadProxyClient { .into_inner() .api_access_methods .ok_or(Error::ApiAccessMethodSettingsNotFound)? - .api_access_methods + .access_method_settings .into_iter() .map(|api_access_method| { AccessMethodSetting::try_from(api_access_method).map_err(Error::InvalidResponse) @@ -183,7 +182,7 @@ impl MullvadProxyClient { pub async fn get_api_access_method( &mut self, - id: &ApiAccessMethodId, + id: &access_method::Id, ) -> Result<AccessMethodSetting> { self.get_api_access_methods() .await? @@ -192,8 +191,8 @@ impl MullvadProxyClient { .ok_or(Error::ApiAccessMethodNotFound) } - pub async fn get_api_addressess(&mut self) -> Result<()> { - self.0.get_api_addressess(()).await.map_err(Error::Rpc)?; + pub async fn get_api_addresses(&mut self) -> Result<()> { + self.0.get_api_addresses(()).await.map_err(Error::Rpc)?; Ok(()) } @@ -493,10 +492,17 @@ impl MullvadProxyClient { pub async fn add_access_method( &mut self, - api_access_method: AccessMethodSetting, + name: String, + enabled: bool, + access_method: AccessMethod, ) -> Result<()> { + let request = types::NewAccessMethodSetting { + name, + enabled, + access_method: Some(types::AccessMethod::from(access_method)), + }; self.0 - .add_api_access_method(types::ApiAccessMethod::from(api_access_method)) + .add_api_access_method(request) .await .map_err(Error::Rpc) .map(drop) @@ -504,43 +510,25 @@ impl MullvadProxyClient { pub async fn enable_access_method( &mut self, - api_access_method_id: ApiAccessMethodId, + api_access_method_id: access_method::Id, ) -> Result<()> { let mut new_api_access_method = self.get_api_access_method(&api_access_method_id).await?; new_api_access_method.enable(); - let update = ApiAccessMethodUpdate { - id: api_access_method_id, - access_method: new_api_access_method, - }; - - self.0 - .update_api_access_method(types::ApiAccessMethodUpdate::from(update)) - .await - .map_err(Error::Rpc) - .map(drop) + self.update_access_method(new_api_access_method).await } pub async fn disable_access_method( &mut self, - api_access_method_id: ApiAccessMethodId, + api_access_method_id: access_method::Id, ) -> Result<()> { let mut new_api_access_method = self.get_api_access_method(&api_access_method_id).await?; new_api_access_method.disable(); - let update = ApiAccessMethodUpdate { - id: api_access_method_id, - access_method: new_api_access_method, - }; - - self.0 - .update_api_access_method(types::ApiAccessMethodUpdate::from(update)) - .await - .map_err(Error::Rpc) - .map(drop) + self.update_access_method(new_api_access_method).await } pub async fn remove_access_method( &mut self, - api_access_method: ApiAccessMethodId, + api_access_method: access_method::Id, ) -> Result<()> { self.0 .remove_api_access_method(types::Uuid::from(api_access_method)) @@ -551,10 +539,10 @@ impl MullvadProxyClient { pub async fn update_access_method( &mut self, - access_method_update: ApiAccessMethodUpdate, + access_method_update: AccessMethodSetting, ) -> Result<()> { self.0 - .update_api_access_method(types::ApiAccessMethodUpdate::from(access_method_update)) + .update_api_access_method(types::AccessMethodSetting::from(access_method_update)) .await .map_err(Error::Rpc) .map(drop) @@ -569,7 +557,7 @@ impl MullvadProxyClient { /// method "randomly" /// /// [`ApiConnectionModeProvider`]: mullvad_daemon::api::ApiConnectionModeProvider - pub async fn set_access_method(&mut self, api_access_method: ApiAccessMethodId) -> Result<()> { + pub async fn set_access_method(&mut self, api_access_method: access_method::Id) -> Result<()> { self.0 .set_api_access_method(types::Uuid::from(api_access_method)) .await diff --git a/mullvad-management-interface/src/types/conversions/access_method.rs b/mullvad-management-interface/src/types/conversions/access_method.rs new file mode 100644 index 0000000000..0f39d34e9e --- /dev/null +++ b/mullvad-management-interface/src/types/conversions/access_method.rs @@ -0,0 +1,258 @@ +/// Implements conversions for the auxilliary +/// [`crate::types::proto::ApiAccessMethodSettings`] type to the internal +/// [`mullvad_types::access_method::Settings`] data type. +mod settings { + use crate::types::{proto, FromProtobufTypeError}; + use mullvad_types::access_method; + + impl From<&access_method::Settings> for proto::ApiAccessMethodSettings { + fn from(settings: &access_method::Settings) -> Self { + Self { + access_method_settings: settings + .access_method_settings + .iter() + .map(|method| method.clone().into()) + .collect(), + } + } + } + + impl From<access_method::Settings> for proto::ApiAccessMethodSettings { + fn from(settings: access_method::Settings) -> Self { + proto::ApiAccessMethodSettings::from(&settings) + } + } + + impl TryFrom<proto::ApiAccessMethodSettings> for access_method::Settings { + type Error = FromProtobufTypeError; + + fn try_from(settings: proto::ApiAccessMethodSettings) -> Result<Self, Self::Error> { + Ok(Self { + access_method_settings: settings + .access_method_settings + .iter() + .map(access_method::AccessMethodSetting::try_from) + .collect::<Result<Vec<access_method::AccessMethodSetting>, _>>()?, + }) + } + } +} + +/// Implements conversions for the auxilliary +/// [`crate::types::proto::ApiAccessMethod`] type to the internal +/// [`mullvad_types::access_method::AccessMethodSetting`] data type. +mod data { + use crate::types::{proto, FromProtobufTypeError}; + use mullvad_types::access_method::{ + AccessMethod, AccessMethodSetting, BuiltInAccessMethod, CustomAccessMethod, Id, + Shadowsocks, Socks5, Socks5Local, Socks5Remote, + }; + + impl TryFrom<proto::AccessMethodSetting> for AccessMethodSetting { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::AccessMethodSetting) -> Result<Self, Self::Error> { + let id = value + .id + .ok_or(FromProtobufTypeError::InvalidArgument( + "Could not deserialize Access Method from protobuf", + )) + .and_then(Id::try_from)?; + let name = value.name; + let enabled = value.enabled; + let access_method = value + .access_method + .ok_or(FromProtobufTypeError::InvalidArgument( + "Could not deserialize Access Method from protobuf", + )) + .and_then(AccessMethod::try_from)?; + + Ok(AccessMethodSetting::with_id( + id, + name, + enabled, + access_method, + )) + } + } + + impl From<AccessMethodSetting> for proto::AccessMethodSetting { + fn from(value: AccessMethodSetting) -> Self { + let id = proto::Uuid::from(value.get_id()); + let name = value.get_name(); + let enabled = value.enabled(); + proto::AccessMethodSetting { + id: Some(id), + name, + enabled, + access_method: Some(proto::AccessMethod::from(value.access_method)), + } + } + } + + impl TryFrom<proto::AccessMethod> for AccessMethod { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::AccessMethod) -> Result<Self, Self::Error> { + let access_method = + value + .access_method + .ok_or(FromProtobufTypeError::InvalidArgument( + "Could not deserialize Access Method from protobuf", + ))?; + + Ok(match access_method { + proto::access_method::AccessMethod::Direct(direct) => AccessMethod::from(direct), + proto::access_method::AccessMethod::Bridges(bridge) => AccessMethod::from(bridge), + proto::access_method::AccessMethod::Socks5local(sockslocal) => { + AccessMethod::try_from(sockslocal)? + } + proto::access_method::AccessMethod::Socks5remote(socksremote) => { + AccessMethod::try_from(socksremote)? + } + proto::access_method::AccessMethod::Shadowsocks(shadowsocks) => { + AccessMethod::try_from(shadowsocks)? + } + }) + } + } + + impl From<AccessMethod> for proto::AccessMethod { + fn from(value: AccessMethod) -> Self { + match value { + AccessMethod::Custom(value) => proto::AccessMethod::from(value), + AccessMethod::BuiltIn(value) => proto::AccessMethod::from(value), + } + } + } + + impl From<proto::access_method::Direct> for AccessMethod { + fn from(_value: proto::access_method::Direct) -> Self { + AccessMethod::from(BuiltInAccessMethod::Direct) + } + } + + impl From<proto::access_method::Bridges> for AccessMethod { + fn from(_value: proto::access_method::Bridges) -> Self { + AccessMethod::from(BuiltInAccessMethod::Bridge) + } + } + + impl TryFrom<proto::access_method::Socks5Local> for AccessMethod { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::access_method::Socks5Local) -> Result<Self, Self::Error> { + Socks5Local::from_args(value.ip, value.port as u16, value.local_port as u16) + .ok_or(FromProtobufTypeError::InvalidArgument( + "Could not parse Socks5 (local) message from protobuf", + )) + .map(AccessMethod::from) + } + } + + impl TryFrom<proto::access_method::Socks5Remote> for AccessMethod { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::access_method::Socks5Remote) -> Result<Self, Self::Error> { + Socks5Remote::from_args(value.ip, value.port as u16) + .ok_or({ + FromProtobufTypeError::InvalidArgument( + "Could not parse Socks5 (remote) message from protobuf", + ) + }) + .map(AccessMethod::from) + } + } + + impl TryFrom<proto::access_method::Shadowsocks> for AccessMethod { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::access_method::Shadowsocks) -> Result<Self, Self::Error> { + Shadowsocks::from_args(value.ip, value.port as u16, value.cipher, value.password) + .ok_or(FromProtobufTypeError::InvalidArgument( + "Could not parse Shadowsocks message from protobuf", + )) + .map(AccessMethod::from) + } + } + + impl From<BuiltInAccessMethod> for proto::AccessMethod { + fn from(value: BuiltInAccessMethod) -> Self { + let access_method = match value { + mullvad_types::access_method::BuiltInAccessMethod::Direct => { + proto::access_method::AccessMethod::Direct(proto::access_method::Direct {}) + } + mullvad_types::access_method::BuiltInAccessMethod::Bridge => { + proto::access_method::AccessMethod::Bridges(proto::access_method::Bridges {}) + } + }; + proto::AccessMethod { + access_method: Some(access_method), + } + } + } + + impl From<CustomAccessMethod> for proto::AccessMethod { + fn from(value: CustomAccessMethod) -> Self { + let access_method = match value { + CustomAccessMethod::Shadowsocks(ss) => { + proto::access_method::AccessMethod::Shadowsocks( + proto::access_method::Shadowsocks { + ip: ss.peer.ip().to_string(), + port: ss.peer.port() as u32, + password: ss.password, + cipher: ss.cipher, + }, + ) + } + CustomAccessMethod::Socks5(Socks5::Local(Socks5Local { peer, port })) => { + proto::access_method::AccessMethod::Socks5local( + proto::access_method::Socks5Local { + ip: peer.ip().to_string(), + port: peer.port() as u32, + local_port: port as u32, + }, + ) + } + CustomAccessMethod::Socks5(Socks5::Remote(Socks5Remote { peer })) => { + proto::access_method::AccessMethod::Socks5remote( + proto::access_method::Socks5Remote { + ip: peer.ip().to_string(), + port: peer.port() as u32, + }, + ) + } + }; + + proto::AccessMethod { + access_method: Some(access_method), + } + } + } + + impl From<Id> for proto::Uuid { + fn from(value: Id) -> Self { + proto::Uuid { + value: value.to_string(), + } + } + } + + impl TryFrom<proto::Uuid> for Id { + type Error = FromProtobufTypeError; + + fn try_from(value: proto::Uuid) -> Result<Self, Self::Error> { + Self::from_string(value.value).ok_or(FromProtobufTypeError::InvalidArgument( + "Could not parse UUID message from protobuf", + )) + } + } + + impl TryFrom<&proto::AccessMethodSetting> for AccessMethodSetting { + type Error = FromProtobufTypeError; + + fn try_from(value: &proto::AccessMethodSetting) -> Result<Self, Self::Error> { + AccessMethodSetting::try_from(value.clone()) + } + } +} diff --git a/mullvad-management-interface/src/types/conversions/api_access_method.rs b/mullvad-management-interface/src/types/conversions/api_access_method.rs deleted file mode 100644 index 0fd29f4b93..0000000000 --- a/mullvad-management-interface/src/types/conversions/api_access_method.rs +++ /dev/null @@ -1,288 +0,0 @@ -/// Implements conversions for the auxilliary -/// [`crate::types::proto::ApiAccessMethodSettings`] type to the internal -/// [`mullvad_types::access_method::Settings`] data type. -mod settings { - use crate::types::{proto, FromProtobufTypeError}; - use mullvad_types::access_method; - - impl From<&api_access::Settings> for proto::ApiAccessMethodSettings { - fn from(settings: &api_access::Settings) -> Self { - Self { - api_access_methods: settings - .api_access_methods - .iter() - .map(|method| method.clone().into()) - .collect(), - } - } - } - - impl From<api_access::Settings> for proto::ApiAccessMethodSettings { - fn from(settings: api_access::Settings) -> Self { - proto::ApiAccessMethodSettings::from(&settings) - } - } - - impl TryFrom<proto::ApiAccessMethodSettings> for api_access::Settings { - type Error = FromProtobufTypeError; - - fn try_from(settings: proto::ApiAccessMethodSettings) -> Result<Self, Self::Error> { - Ok(Self { - api_access_methods: settings - .api_access_methods - .iter() - .map(api_access::AccessMethodSetting::try_from) - .collect::<Result<Vec<api_access::AccessMethodSetting>, _>>()?, - }) - } - } - - impl From<access_method::daemon::ApiAccessMethodUpdate> for proto::ApiAccessMethodUpdate { - fn from(value: access_method::daemon::ApiAccessMethodUpdate) -> Self { - proto::ApiAccessMethodUpdate { - id: Some(proto::Uuid::from(value.id)), - access_method: Some(proto::ApiAccessMethod::from(value.access_method)), - } - } - } - - impl TryFrom<proto::ApiAccessMethodUpdate> for access_method::daemon::ApiAccessMethodUpdate { - type Error = FromProtobufTypeError; - - fn try_from(value: proto::ApiAccessMethodUpdate) -> Result<Self, Self::Error> { - let api_access_method = value - .access_method - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not convert Access Method from protobuf", - )) - .and_then(api_access::AccessMethodSetting::try_from)?; - - let id = value - .id - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not convert Access Method from protobuf", - )) - .map(api_access::ApiAccessMethodId::from)?; - - Ok(access_method::daemon::ApiAccessMethodUpdate { - id, - access_method: api_access_method, - }) - } - } -} - -/// Implements conversions for the auxilliary -/// [`crate::types::proto::ApiAccessMethod`] type to the internal -/// [`mullvad_types::access_method::AccessMethod`] data type. -mod data { - use crate::types::{proto, FromProtobufTypeError}; - use mullvad_types::api_access::{ - AccessMethod, AccessMethodSetting, ApiAccessMethodId, BuiltInAccessMethod, - CustomAccessMethod, Shadowsocks, Socks5, Socks5Local, Socks5Remote, - }; - - impl TryFrom<proto::ApiAccessMethods> for Vec<AccessMethodSetting> { - type Error = FromProtobufTypeError; - - fn try_from(value: proto::ApiAccessMethods) -> Result<Self, Self::Error> { - value - .api_access_methods - .iter() - .map(AccessMethodSetting::try_from) - .collect() - } - } - - impl TryFrom<proto::ApiAccessMethod> for AccessMethodSetting { - type Error = FromProtobufTypeError; - - fn try_from(value: proto::ApiAccessMethod) -> Result<Self, Self::Error> { - let id = value - .id - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not deserialize Access Method from protobuf", - )) - .and_then(ApiAccessMethodId::try_from)?; - let name = value.name; - let enabled = value.enabled; - let access_method = value - .access_method - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not deserialize Access Method from protobuf", - )) - .and_then(AccessMethod::try_from)?; - - Ok(AccessMethodSetting::with_id( - id, - name, - enabled, - access_method, - )) - } - } - - impl From<AccessMethodSetting> for proto::ApiAccessMethod { - fn from(value: AccessMethodSetting) -> Self { - let id = proto::Uuid::from(value.get_id()); - let name = value.get_name(); - let enabled = value.enabled(); - proto::ApiAccessMethod { - id: Some(id), - name, - enabled, - access_method: Some(proto::AccessMethod::from(value.access_method)), - } - } - } - - impl TryFrom<proto::AccessMethod> for AccessMethod { - type Error = FromProtobufTypeError; - - fn try_from(value: proto::AccessMethod) -> Result<Self, Self::Error> { - let access_method = - value - .access_method - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not deserialize Access Method from protobuf", - ))?; - - let access_method = match access_method { - proto::api_access_method::AccessMethod::Direct( - proto::api_access_method::Direct {}, - ) => AccessMethod::from(BuiltInAccessMethod::Direct), - - proto::api_access_method::AccessMethod::Bridges( - proto::api_access_method::Bridges {}, - ) => AccessMethod::from(BuiltInAccessMethod::Bridge), - proto::api_access_method::AccessMethod::Socks5local(local) => { - let socks = Socks5Local::from_args( - local.ip, - local.port as u16, - local.local_port as u16, - ) - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not parse Socks5 (local) message from protobuf", - ))?; - AccessMethod::from(socks) - } - - proto::api_access_method::AccessMethod::Socks5remote(remote) => { - let socks = Socks5Remote::from_args(remote.ip, remote.port as u16).ok_or({ - FromProtobufTypeError::InvalidArgument( - "Could not parse Socks5 (remote) message from protobuf", - ) - })?; - AccessMethod::from(socks) - } - proto::api_access_method::AccessMethod::Shadowsocks(ss) => { - let socks = - Shadowsocks::from_args(ss.ip, ss.port as u16, ss.cipher, ss.password) - .ok_or(FromProtobufTypeError::InvalidArgument( - "Could not parse Shadowsocks message from protobuf", - ))?; - AccessMethod::from(socks) - } - }; - - Ok(AccessMethodSetting::with_id( - id, - name, - enabled, - access_method, - )) - } - } - - impl From<ApiAccessMethodId> for proto::Uuid { - fn from(value: ApiAccessMethodId) -> Self { - proto::Uuid { - value: value.to_string(), - } - } - } - - impl TryFrom<proto::Uuid> for ApiAccessMethodId { - type Error = FromProtobufTypeError; - - fn try_from(value: proto::Uuid) -> Result<Self, Self::Error> { - Self::from_string(value.value).ok_or(FromProtobufTypeError::InvalidArgument( - "Could not parse UUID message from protobuf", - )) - } - } - - impl From<AccessMethodSetting> for proto::ApiAccessMethod { - fn from(value: AccessMethodSetting) -> Self { - let id = proto::Uuid::from(value.get_id()); - let name = value.get_name(); - let enabled = value.enabled(); - let access_method = match value.access_method { - AccessMethod::Custom(value) => match value { - CustomAccessMethod::Shadowsocks(ss) => { - proto::api_access_method::AccessMethod::Shadowsocks( - proto::api_access_method::Shadowsocks { - ip: ss.peer.ip().to_string(), - port: ss.peer.port() as u32, - password: ss.password, - cipher: ss.cipher, - }, - ) - } - CustomAccessMethod::Socks5(Socks5::Local(Socks5Local { peer, port })) => { - proto::api_access_method::AccessMethod::Socks5local( - proto::api_access_method::Socks5Local { - ip: peer.ip().to_string(), - port: peer.port() as u32, - local_port: port as u32, - }, - ) - } - CustomAccessMethod::Socks5(Socks5::Remote(Socks5Remote { peer })) => { - proto::api_access_method::AccessMethod::Socks5remote( - proto::api_access_method::Socks5Remote { - ip: peer.ip().to_string(), - port: peer.port() as u32, - }, - ) - } - }, - AccessMethod::BuiltIn(value) => match value { - mullvad_types::api_access::BuiltInAccessMethod::Direct => { - proto::api_access_method::AccessMethod::Direct( - proto::api_access_method::Direct {}, - ) - } - mullvad_types::api_access::BuiltInAccessMethod::Bridge => { - proto::api_access_method::AccessMethod::Bridges( - proto::api_access_method::Bridges {}, - ) - } - }, - }; - - proto::ApiAccessMethod { - id: Some(id), - name, - enabled, - access_method: Some(access_method), - } - } - } - - impl TryFrom<&proto::ApiAccessMethod> for AccessMethodSetting { - type Error = FromProtobufTypeError; - - fn try_from(value: &proto::ApiAccessMethod) -> Result<Self, Self::Error> { - AccessMethodSetting::try_from(value.clone()) - } - } - - impl From<Vec<AccessMethodSetting>> for proto::ApiAccessMethods { - fn from(value: Vec<AccessMethodSetting>) -> proto::ApiAccessMethods { - proto::ApiAccessMethods { - api_access_methods: value.iter().map(|method| method.clone().into()).collect(), - } - } - } -} diff --git a/mullvad-management-interface/src/types/conversions/mod.rs b/mullvad-management-interface/src/types/conversions/mod.rs index ddfe3f4282..dd6fcd4501 100644 --- a/mullvad-management-interface/src/types/conversions/mod.rs +++ b/mullvad-management-interface/src/types/conversions/mod.rs @@ -1,7 +1,7 @@ use std::str::FromStr; +mod access_method; mod account; -mod api_access_method; mod custom_list; mod custom_tunnel; mod device; diff --git a/mullvad-management-interface/src/types/conversions/settings.rs b/mullvad-management-interface/src/types/conversions/settings.rs index 532e5e8f29..98c195d935 100644 --- a/mullvad-management-interface/src/types/conversions/settings.rs +++ b/mullvad-management-interface/src/types/conversions/settings.rs @@ -180,7 +180,7 @@ impl TryFrom<proto::Settings> for mullvad_types::settings::Settings { custom_lists: mullvad_types::custom_list::CustomListsSettings::try_from( custom_lists_settings, )?, - api_access_methods: mullvad_types::api_access::Settings::try_from( + api_access_methods: mullvad_types::access_method::Settings::try_from( api_access_methods_settings, )?, }) diff --git a/mullvad-types/src/api_access.rs b/mullvad-types/src/access_method.rs index b916a7f323..a300072c82 100644 --- a/mullvad-types/src/api_access.rs +++ b/mullvad-types/src/access_method.rs @@ -6,23 +6,23 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; /// Daemon settings for API access methods. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct Settings { - pub api_access_methods: Vec<AccessMethodSetting>, + pub access_method_settings: Vec<AccessMethodSetting>, } impl Settings { /// Append an [`AccessMethod`] to the end of `api_access_methods`. pub fn append(&mut self, api_access_method: AccessMethodSetting) { - self.api_access_methods.push(api_access_method) + self.access_method_settings.push(api_access_method) } /// Remove an [`ApiAccessMethod`] from `api_access_methods`. - pub fn remove(&mut self, api_access_method: &ApiAccessMethodId) { + pub fn remove(&mut self, api_access_method: &Id) { self.retain(|method| method.get_id() != *api_access_method) } /// Search for a particular [`AccessMethod`] in `api_access_methods`. - pub fn find(&self, element: &ApiAccessMethodId) -> Option<&AccessMethodSetting> { - self.api_access_methods + pub fn find(&self, element: &Id) -> Option<&AccessMethodSetting> { + self.access_method_settings .iter() .find(|api_access_method| *element == api_access_method.get_id()) } @@ -32,8 +32,8 @@ impl Settings { /// If the [`AccessMethod`] is found to be part of `api_access_methods`, a /// mutable reference to that inner element is returned. Otherwise, `None` /// is returned. - pub fn find_mut(&mut self, element: &ApiAccessMethodId) -> Option<&mut AccessMethodSetting> { - self.api_access_methods + pub fn find_mut(&mut self, element: &Id) -> Option<&mut AccessMethodSetting> { + self.access_method_settings .iter_mut() .find(|api_access_method| *element == api_access_method.get_id()) } @@ -43,19 +43,19 @@ impl Settings { where F: FnMut(&AccessMethodSetting) -> bool, { - self.api_access_methods.retain(f) + self.access_method_settings.retain(f) } /// Clone the content of `api_access_methods`. pub fn cloned(&self) -> Vec<AccessMethodSetting> { - self.api_access_methods.clone() + self.access_method_settings.clone() } } impl Default for Settings { fn default() -> Self { Self { - api_access_methods: vec![BuiltInAccessMethod::Direct, BuiltInAccessMethod::Bridge] + access_method_settings: vec![BuiltInAccessMethod::Direct, BuiltInAccessMethod::Bridge] .into_iter() .map(|built_in| { AccessMethodSetting::new( @@ -75,28 +75,28 @@ impl Default for Settings { #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct AccessMethodSetting { /// Some unique id (distinct for each `AccessMethod`). - id: ApiAccessMethodId, + id: Id, pub name: String, pub enabled: bool, pub access_method: AccessMethod, } #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] -pub struct ApiAccessMethodId(uuid::Uuid); +pub struct Id(uuid::Uuid); -impl ApiAccessMethodId { +impl Id { #[allow(clippy::new_without_default)] pub fn new() -> Self { Self(uuid::Uuid::new_v4()) } /// Tries to parse a UUID from a raw String. If it is successful, an - /// [`ApiAccessMethodId`] is instantiated. + /// [`Id`] is instantiated. pub fn from_string(id: String) -> Option<Self> { uuid::Uuid::from_str(&id).ok().map(Self) } } -impl std::fmt::Display for ApiAccessMethodId { +impl std::fmt::Display for Id { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } @@ -112,7 +112,7 @@ pub enum AccessMethod { impl AccessMethodSetting { pub fn new(name: String, enabled: bool, access_method: AccessMethod) -> Self { Self { - id: ApiAccessMethodId::new(), + id: Id::new(), name, enabled, access_method, @@ -128,12 +128,7 @@ impl AccessMethodSetting { /// /// [`new`]: ApiAccessMethod::new /// [`with_id`]: ApiAccessMethod::with_id - pub fn with_id( - id: ApiAccessMethodId, - name: String, - enabled: bool, - access_method: AccessMethod, - ) -> Self { + pub fn with_id(id: Id, name: String, enabled: bool, access_method: AccessMethod) -> Self { Self { id, name, @@ -142,7 +137,7 @@ impl AccessMethodSetting { } } - pub fn get_id(&self) -> ApiAccessMethodId { + pub fn get_id(&self) -> Id { self.id.clone() } @@ -326,14 +321,3 @@ impl From<Socks5Local> for Socks5 { Socks5::Local(value) } } - -/// Some short-lived datastructure used in some RPC calls to the mullvad daemon. -pub mod daemon { - use super::*; - /// Argument to protobuf rpc `UpdateApiAccessMethod`. - #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] - pub struct ApiAccessMethodUpdate { - pub id: ApiAccessMethodId, - pub access_method: ApiAccessMethod, - } -} diff --git a/mullvad-types/src/lib.rs b/mullvad-types/src/lib.rs index e1af195220..8aefaeb400 100644 --- a/mullvad-types/src/lib.rs +++ b/mullvad-types/src/lib.rs @@ -1,7 +1,7 @@ #![deny(rust_2018_idioms)] +pub mod access_method; pub mod account; -pub mod api_access; pub mod auth_failed; pub mod custom_list; pub mod device; diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs index 2c40172a2c..6ade7dea32 100644 --- a/mullvad-types/src/settings/mod.rs +++ b/mullvad-types/src/settings/mod.rs @@ -1,5 +1,5 @@ use crate::{ - api_access, + access_method, custom_list::CustomListsSettings, relay_constraints::{ BridgeConstraints, BridgeSettings, BridgeState, Constraint, GeographicLocationConstraint, @@ -79,7 +79,7 @@ pub struct Settings { pub custom_lists: CustomListsSettings, /// API access methods. #[cfg_attr(target_os = "android", jnix(skip))] - pub api_access_methods: api_access::Settings, + pub api_access_methods: access_method::Settings, /// If the daemon should allow communication with private (LAN) networks. pub allow_lan: bool, /// Extra level of kill switch. When this setting is on, the disconnected state will block @@ -140,7 +140,7 @@ impl Default for Settings { split_tunnel: SplitTunnelSettings::default(), settings_version: CURRENT_SETTINGS_VERSION, custom_lists: CustomListsSettings::default(), - api_access_methods: api_access::Settings::default(), + api_access_methods: access_method::Settings::default(), } } } |
