Skip to content

Commit

Permalink
TOR bridge + TOR Proxy + migration config_file_version (#617)
Browse files Browse the repository at this point in the history
* tor bridge config and args

* migration `config_file_version=2`

* small fixes typo, comment etc..

* support: snowflake, meek_lite, obsf4 and tor proxy

* remove useless serde

* improve migrate function

* few fixes

* add bridge flags to pay and receive + few fixes

* some improvements
  • Loading branch information
deevope committed Feb 3, 2022
1 parent f5dbed2 commit c424a0e
Show file tree
Hide file tree
Showing 18 changed files with 1,334 additions and 37 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions api/src/owner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2451,6 +2451,8 @@ pub fn try_slatepack_sync_workflow(
&tor_addr.to_http_str(),
&tor_config.as_ref().unwrap().socks_proxy_addr,
&tor_config.as_ref().unwrap().send_config_dir,
tor_config.as_ref().unwrap().bridge.clone(),
tor_config.as_ref().unwrap().proxy.clone(),
) {
Ok(s) => Some(s),
Err(e) => {
Expand Down
144 changes: 140 additions & 4 deletions config/src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ use std::collections::HashMap;
fn comments() -> HashMap<String, String> {
let mut retval = HashMap::new();

retval.insert(
"config_file_version".to_string(),
"
#Version of the Generated Configuration File for the Grin Wallet (DO NOT EDIT)
"
.to_string(),
);

retval.insert(
"[wallet]".to_string(),
"
Expand Down Expand Up @@ -124,6 +132,22 @@ fn comments() -> HashMap<String, String> {
retval.insert(
"[logging]".to_string(),
"
#Type of proxy, eg \"socks4\", \"socks5\", \"http\", \"https\"
#transport = \"https\"
#Proxy address, eg IP:PORT or Hostname
#server = \"\"
#Username for the proxy server authentification
#user = \"\"
#Password for the proxy server authentification
#pass = \"\"
#This computer goes through a firewall that only allows connections to certain ports (Optional)
#allowed_port = [80, 443]
#########################################
### LOGGING CONFIGURATION ###
#########################################
Expand Down Expand Up @@ -215,21 +239,44 @@ fn comments() -> HashMap<String, String> {
);

retval.insert(
"socks_proxy_addr".to_string(),
"send_config_dir".to_string(),
"
# TOR (SOCKS) proxy server address
#Directory to output TOR configuration to when sending
"
.to_string(),
);

retval.insert(
"send_config_dir".to_string(),
"[tor.bridge]".to_string(),
"
#Directory to output TOR configuration to when sending
#########################################
### TOR BRIDGE ###
#########################################
"
.to_string(),
);

retval.insert(
"[tor.proxy]".to_string(),
"
#Tor bridge relay: allow to send and receive via TOR in a country where it is censored.
#Enable it by entering a single bridge line. To disable it, you must comment it.
#Support of the transport: obfs4, meek and snowflake.
#obfs4proxy or snowflake client binary must be installed and on your path.
#For example, the bridge line must be in the following format for obfs4 transport: \"obfs4 [IP:PORT] [FINGERPRINT] cert=[CERT] iat-mode=[IAT-MODE]\"
#bridge_line = \"\"
#Plugging client option, needed only for snowflake (let it empty if you want to use the default option of tor) or debugging purpose
#client_option = \"\"
#########################################
### TOR PROXY ###
#########################################
"
.to_string(),
);

retval
}

Expand Down Expand Up @@ -261,3 +308,92 @@ pub fn insert_comments(orig: String) -> String {
}
ret_val
}

pub fn migrate_comments(
old_config: String,
new_config: String,
old_version: Option<u32>,
) -> String {
let comments = comments();
// Prohibe the key we are basing on to introduce new comments for [tor.proxy]
let prohibited_key = match old_version {
None => vec!["[logging]"],
Some(_) => vec![],
};
let mut vec_old_conf = vec![];
let mut hm_key_cmt_old = HashMap::new();
let old_conf: Vec<&str> = old_config.split_inclusive('\n').collect();
// collect old key in a vec and insert old key/comments from the old conf in a hashmap
let vec_key_old = old_conf
.iter()
.filter_map(|line| {
let line_nospace = line.trim();
let is_ascii_control = line_nospace.chars().all(|x| x.is_ascii_control());
match line.contains("#") || is_ascii_control {
true => {
vec_old_conf.push(line.to_owned());
None
}
false => {
let comments: String =
vec_old_conf.iter().map(|s| s.chars()).flatten().collect();
let key = get_key(line_nospace);
match !(key == "NOT_FOUND") {
true => {
vec_old_conf.clear();
hm_key_cmt_old.insert(key.clone(), comments);
Some(key)
}
false => None,
}
}
}
})
.collect::<Vec<String>>();

let new_conf: Vec<&str> = new_config.split_inclusive('\n').collect();
// collect new key and the whole key line from the new config
let vec_key_cmt_new = new_conf
.iter()
.filter_map(|line| {
let line_nospace = line.trim();
let is_ascii_control = line_nospace.chars().all(|x| x.is_ascii_control());
match !(line.contains("#") || is_ascii_control) {
true => {
let key = get_key(line_nospace);
match !(key == "NOT_FOUND") {
true => Some((key, line_nospace.to_string())),
false => None,
}
}
false => None,
}
})
.collect::<Vec<(String, String)>>();

let mut new_config_str = String::from("");
// Merging old comments in the new config (except if the key is contained in the prohibited vec) with all new introduced key comments
for (key, key_line) in vec_key_cmt_new {
let old_key_exist = vec_key_old.iter().any(|old_key| *old_key == key);
let key_fmt = format!("{}\n", key_line);
if old_key_exist {
if prohibited_key.contains(&key.as_str()) {
// push new config key/comments
let value = comments.get(&key).unwrap();
new_config_str.push_str(value);
new_config_str.push_str(&key_fmt);
} else {
// push old config key/comment
let value = hm_key_cmt_old.get(&key).unwrap();
new_config_str.push_str(value);
new_config_str.push_str(&key_fmt);
}
} else {
// old key does not exist, we push new key/comments
let value = comments.get(&key).unwrap();
new_config_str.push_str(value);
new_config_str.push_str(&key_fmt);
}
}
new_config_str
}
71 changes: 61 additions & 10 deletions config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ use std::env;
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::BufReader;
use std::io::Read;
use std::path::PathBuf;
use toml;

use crate::comments::insert_comments;
use crate::comments::{insert_comments, migrate_comments};
use crate::core::global;
use crate::types::{ConfigError, GlobalWalletConfig, GlobalWalletConfigMembers};
use crate::types::{
ConfigError, GlobalWalletConfig, GlobalWalletConfigMembers, TorBridgeConfig, TorProxyConfig,
};
use crate::types::{TorConfig, WalletConfig};
use crate::util::logger::LoggingConfig;

Expand Down Expand Up @@ -187,6 +188,7 @@ pub fn initial_setup_wallet(
impl Default for GlobalWalletConfigMembers {
fn default() -> GlobalWalletConfigMembers {
GlobalWalletConfigMembers {
config_file_version: Some(2),
logging: Some(LoggingConfig::default()),
tor: Some(TorConfig::default()),
wallet: WalletConfig::default(),
Expand Down Expand Up @@ -245,10 +247,13 @@ impl GlobalWalletConfig {

/// Read config
fn read_config(mut self) -> Result<GlobalWalletConfig, ConfigError> {
let mut file = File::open(self.config_file_path.as_mut().unwrap())?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let fixed = GlobalWalletConfig::fix_warning_level(contents);
let config_file_path = self.config_file_path.as_mut().unwrap();
let contents = fs::read_to_string(config_file_path.clone())?;
let migrated = GlobalWalletConfig::migrate_config_file_version_none_to_2(
contents,
config_file_path.to_owned(),
)?;
let fixed = GlobalWalletConfig::fix_warning_level(migrated);
let decoded: Result<GlobalWalletConfigMembers, toml::de::Error> = toml::from_str(&fixed);
match decoded {
Ok(gc) => {
Expand Down Expand Up @@ -306,14 +311,60 @@ impl GlobalWalletConfig {
}

/// Write configuration to a file
pub fn write_to_file(&mut self, name: &str) -> Result<(), ConfigError> {
pub fn write_to_file(
&mut self,
name: &str,
migration: bool,
old_config: Option<String>,
old_version: Option<u32>,
) -> Result<(), ConfigError> {
let conf_out = self.ser_config()?;
let fixed_config = GlobalWalletConfig::fix_log_level(conf_out);
let commented_config = insert_comments(fixed_config);
let commented_config = if migration {
migrate_comments(old_config.unwrap(), conf_out, old_version)
} else {
let fixed_config = GlobalWalletConfig::fix_log_level(conf_out);
insert_comments(fixed_config)
};
let mut file = File::create(name)?;
file.write_all(commented_config.as_bytes())?;
Ok(())
}
/// This migration does the following:
/// - Adds "config_file_version = 2"
/// - Introduce new key config_file_version, [tor.bridge] and [tor.proxy]
/// - Migrate old config key/value and comments while it does not conflict with newly indroduced key and comments
fn migrate_config_file_version_none_to_2(
config_str: String,
config_file_path: PathBuf,
) -> Result<String, ConfigError> {
let config: GlobalWalletConfigMembers =
toml::from_str(&GlobalWalletConfig::fix_warning_level(config_str.clone())).unwrap();
if config.config_file_version != None {
return Ok(config_str);
}
let adjusted_config = GlobalWalletConfigMembers {
config_file_version: GlobalWalletConfigMembers::default().config_file_version,
tor: Some(TorConfig {
bridge: TorBridgeConfig::default(),
proxy: TorProxyConfig::default(),
..config.tor.unwrap_or(TorConfig::default())
}),
..config
};
let mut gc = GlobalWalletConfig {
members: Some(adjusted_config),
config_file_path: Some(config_file_path.clone()),
};
let str_path = config_file_path.into_os_string().into_string().unwrap();
gc.write_to_file(
&str_path,
true,
Some(config_str),
config.config_file_version,
)?;
let adjusted_config_str = fs::read_to_string(str_path.clone())?;
Ok(adjusted_config_str)
}

// For forwards compatibility old config needs `Warning` log level changed to standard log::Level `WARN`
fn fix_warning_level(conf: String) -> String {
Expand Down
Loading

0 comments on commit c424a0e

Please sign in to comment.