summaryrefslogtreecommitdiffhomepage
path: root/mullvad-daemon/src
diff options
context:
space:
mode:
Diffstat (limited to 'mullvad-daemon/src')
-rw-r--r--mullvad-daemon/src/migrations/v7.rs313
1 files changed, 286 insertions, 27 deletions
diff --git a/mullvad-daemon/src/migrations/v7.rs b/mullvad-daemon/src/migrations/v7.rs
index efd3193624..4614cedce9 100644
--- a/mullvad-daemon/src/migrations/v7.rs
+++ b/mullvad-daemon/src/migrations/v7.rs
@@ -75,6 +75,10 @@ pub struct ShadowsocksProxySettings {
/// that instead of having a Socks5 and Shadowsocks variant instead has a Socks5Local, Socks5Remote
/// and Shadowsocks variant.
///
+/// The predefined access methods "Direct" and "Mullvad Bridges" are now stored as distinct keys in
+/// the api_access_methods settings, separating them from user-defined access methods in the settings
+/// datastructure.
+///
/// We also take the oppertunity to rename a couple of fields that relate to proxy types.
/// We rename
/// - shadowsocks.peer to shadowsocks.endpoint
@@ -141,6 +145,62 @@ fn migrate_api_access_settings(settings: &mut serde_json::Value) -> Result<()> {
}
}
+ // Step 1. Rename { "api_access_methods": { "access_method_settings": .. } } to { "api_access_methods": { "custom": .. } }.
+ // Step 2. Collect all of the built-in methods from { "api_access_methods": { "custom": [ .. ] } }.
+ // Step 3. Remove all of the built-in methods from { "api_access_methods": { "custom": [ .. ] } }.
+ // Step 4. Add the collected built-in methods from step 2 to { "api_access_methods": { .. } } under some appropriate key.
+ if let Some(access_method_settings) = settings
+ .get_mut("api_access_methods")
+ .and_then(serde_json::value::Value::as_object_mut)
+ {
+ // Step 1.
+ rename_map_field(access_method_settings, "access_method_settings", "custom")?;
+
+ if let Some(access_method_settings_list) = access_method_settings
+ .get_mut("custom")
+ .and_then(serde_json::value::Value::as_array_mut)
+ {
+ // Step 2.
+ let built_ins: Vec<_> = access_method_settings_list
+ .iter()
+ .filter(|value| {
+ value
+ .get("access_method")
+ .and_then(|value| value.get("built_in"))
+ .is_some()
+ })
+ .cloned()
+ .collect();
+
+ // Step 3.
+ for built_in in built_ins.iter() {
+ access_method_settings_list
+ .retain(|access_method| access_method.get("id") != built_in.get("id"));
+ }
+
+ // Step 4.
+ // Note that the only supported built-in access methods at this time
+ // are "Direct" and "Mullvad Bridges", so we may discard anything
+ // else.
+ let built_ins: Vec<_> = built_ins
+ .into_iter()
+ .filter_map(|built_in| {
+ match built_in
+ .get("access_method")
+ .and_then(|value| value.get("built_in"))
+ .and_then(|value| value.as_str())
+ {
+ Some("direct") => Some(("direct".to_string(), built_in)),
+ Some("bridge") => Some(("mullvad_bridges".to_string(), built_in)),
+ Some(_) | None => None,
+ }
+ })
+ .collect();
+
+ access_method_settings.extend(built_ins);
+ }
+ }
+
Ok(())
}
@@ -228,15 +288,24 @@ fn extract_str(opt: Option<&serde_json::Value>) -> Result<&str> {
.ok_or(Error::InvalidSettingsContent)
}
-fn rename_field(object: &mut serde_json::Value, old_name: &str, new_name: &str) -> Result<()> {
- object[new_name] = object
+fn rename_field(value: &mut serde_json::Value, old_name: &str, new_name: &str) -> Result<()> {
+ value
+ .as_object_mut()
+ .ok_or(Error::InvalidSettingsContent)
+ .and_then(|object| rename_map_field(object, old_name, new_name))
+}
+
+fn rename_map_field(
+ object: &mut serde_json::Map<String, serde_json::Value>,
+ old_name: &str,
+ new_name: &str,
+) -> Result<()> {
+ let old_value = object
.get(old_name)
.ok_or(Error::InvalidSettingsContent)?
.clone();
- object
- .as_object_mut()
- .ok_or(Error::InvalidSettingsContent)?
- .remove(old_name);
+ let _ = object.insert(new_name.to_string(), old_value);
+ object.remove(old_name);
Ok(())
}
@@ -475,23 +544,23 @@ mod test {
}
},
"api_access_methods": {
- "access_method_settings": [
- {
- "id": "8cbdcfc8-fa7b-41de-8d12-26fa37439f89",
- "name": "Direct",
- "enabled": true,
- "access_method": {
- "built_in": "direct"
- }
- },
- {
- "id": "1d0d8891-dbb3-4439-a8f7-0e7d742ddbe4",
- "name": "Mullvad Bridges",
- "enabled": true,
- "access_method": {
- "built_in": "bridge"
- }
- },
+ "direct": {
+ "id": "8cbdcfc8-fa7b-41de-8d12-26fa37439f89",
+ "name": "Direct",
+ "enabled": true,
+ "access_method": {
+ "built_in": "direct"
+ }
+ },
+ "mullvad_bridges": {
+ "id": "1d0d8891-dbb3-4439-a8f7-0e7d742ddbe4",
+ "name": "Mullvad Bridges",
+ "enabled": true,
+ "access_method": {
+ "built_in": "bridge"
+ }
+ },
+ "custom": [
{
"id": "1aaff7ab-e09f-4c03-af02-765e41943a7b",
"name": "localsox",
@@ -851,7 +920,7 @@ mod test {
r#"
{
"api_access_methods": {
- "access_method_settings": [
+ "custom": [
{
"id": "5eb9b2ee-f764-47c8-8111-ee95910d0099",
"name": "mysocks",
@@ -880,7 +949,6 @@ mod test {
#[test]
fn test_api_access_methods_custom_socks5_remote() {
- println!("wew");
let mut pre: serde_json::Value = serde_json::from_str(
r#"
{
@@ -910,7 +978,7 @@ mod test {
r#"
{
"api_access_methods": {
- "access_method_settings": [
+ "custom": [
{
"id": "8e377232-8a53-4414-8b8f-f487227aaedb",
"name": "remotesox",
@@ -965,7 +1033,7 @@ mod test {
r#"
{
"api_access_methods": {
- "access_method_settings": [
+ "custom": [
{
"id": "74e5c659-acdd-4cad-a632-a25bf63c20e2",
"name": "remotess",
@@ -989,4 +1057,195 @@ mod test {
migrate_api_access_settings(&mut pre).unwrap();
assert_eq!(pre, post);
}
+
+ #[test]
+ fn test_api_access_methods_extract_direct() {
+ let mut pre: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "access_method_settings": [
+ {
+ "id": "8cbdcfc8-fa7b-41de-8d12-26fa37439f89",
+ "name": "Direct",
+ "enabled": true,
+ "access_method": {
+ "built_in": "direct"
+ }
+ }
+ ]
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ let post: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "direct": {
+ "id": "8cbdcfc8-fa7b-41de-8d12-26fa37439f89",
+ "name": "Direct",
+ "enabled": true,
+ "access_method": {
+ "built_in": "direct"
+ }
+ },
+ "custom": []
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ migrate_api_access_settings(&mut pre).unwrap();
+ assert_eq!(pre, post);
+ }
+
+ #[test]
+ fn test_api_access_methods_extract_mullvad_bridges() {
+ let mut pre: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "access_method_settings": [
+ {
+ "id": "1d0d8891-dbb3-4439-a8f7-0e7d742ddbe4",
+ "name": "Mullvad Bridges",
+ "enabled": true,
+ "access_method": {
+ "built_in": "bridge"
+ }
+ }
+ ]
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ let post: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "mullvad_bridges": {
+ "id": "1d0d8891-dbb3-4439-a8f7-0e7d742ddbe4",
+ "name": "Mullvad Bridges",
+ "enabled": true,
+ "access_method": {
+ "built_in": "bridge"
+ }
+ },
+ "custom": []
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ migrate_api_access_settings(&mut pre).unwrap();
+ assert_eq!(pre, post);
+ }
+
+ #[test]
+ fn test_api_access_methods_do_not_extract_custom_methods() {
+ let mut pre: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "access_method_settings": [
+ {
+ "id": "1aaff7ab-e09f-4c03-af02-765e41943a7b",
+ "name": "localsox",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "socks5": {
+ "local": {
+ "remote_endpoint": {
+ "address": "1.3.3.7:1080",
+ "protocol": "tcp"
+ },
+ "local_port": 1079
+ }
+ }
+ }
+ }
+ }
+ ]
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ let post: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "custom": [
+ {
+ "id": "1aaff7ab-e09f-4c03-af02-765e41943a7b",
+ "name": "localsox",
+ "enabled": false,
+ "access_method": {
+ "custom": {
+ "socks5_local": {
+ "remote_endpoint": {
+ "address": "1.3.3.7:1080",
+ "protocol": "tcp"
+ },
+ "local_port": 1079
+ }
+ }
+ }
+ }
+ ]
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ migrate_api_access_settings(&mut pre).unwrap();
+ assert_eq!(pre, post);
+ }
+
+ #[test]
+ fn test_api_access_methods_extract_corrupt_built_in() {
+ let mut pre: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "access_method_settings": [
+ {
+ "id": "1d0d8891-dbb3-4439-a8f7-0e7d742ddbe4",
+ "name": "Mullvad Bridges",
+ "enabled": true,
+ "access_method": {
+ "built_in": "some_other_alternative"
+ }
+ }
+ ]
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ let post: serde_json::Value = serde_json::from_str(
+ r#"
+{
+ "api_access_methods": {
+ "custom": []
+ }
+}
+"#,
+ )
+ .unwrap();
+
+ migrate_api_access_settings(&mut pre).unwrap();
+ assert_eq!(pre, post);
+ }
}