Skip to content

Commit

Permalink
feat: read tor cookies from a file (#4317)
Browse files Browse the repository at this point in the history
Description
---
The PR adds a capability to read a tor cookie from a file.
To set a `cookie` value in the config of the `tari_base_node` we could use three ways:

```toml
tor.control_auth = "cookie=HEX"
tor.control_auth = "cookie=@" # read `/run/tor/control.authcookie` default cookie file
tor.control_auth = "cookie=@/custom/path/to/cookie/file"
```

Motivation and Context
---
Fixes #2808

How Has This Been Tested?
---
CI and manually (Fedora 35, stardard `tor` service + added `ControlPort` to the config)
  • Loading branch information
therustmonk authored Jul 18, 2022
1 parent 3b467b9 commit c75d224
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 18 deletions.
2 changes: 1 addition & 1 deletion base_layer/p2p/src/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ async fn initialize_hidden_service(
.with_hs_flags(tor::HsFlags::DETACH)
.with_port_mapping(config.to_port_mapping()?)
.with_socks_authentication(config.to_socks_auth())
.with_control_server_auth(config.to_control_auth())
.with_control_server_auth(config.to_control_auth()?)
.with_socks_address_override(config.socks_address_override)
.with_control_server_address(config.control_address)
.with_bypass_proxy_addresses(config.proxy_bypass_addresses.into());
Expand Down
97 changes: 83 additions & 14 deletions base_layer/p2p/src/tor_authentication.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,45 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::{convert::TryFrom, fmt, fmt::Formatter, str::FromStr};
use std::{convert::TryFrom, fmt, fmt::Formatter, fs, io::Error, str::FromStr};

use serde::{Deserialize, Serialize};
use tari_comms::tor;
use tari_utilities::hex::Hex;

#[derive(Clone, Serialize, Deserialize)]
const DEFAULT_TOR_COOKIE_PATH: &str = "/run/tor/control.authcookie";

#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TorCookie {
Hex(String),
FilePath(String),
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
#[serde(try_from = "String")]
pub enum TorControlAuthentication {
None,
Password(String),
/// Cookie authentication. The contents of the cookie file encoded as hex
Cookie(String),
Cookie(TorCookie),
}

impl From<TorControlAuthentication> for tor::Authentication {
fn from(auth: TorControlAuthentication) -> Self {
match auth {
TorControlAuthentication::None => tor::Authentication::None,
TorControlAuthentication::Password(passwd) => tor::Authentication::HashedPassword(passwd),
TorControlAuthentication::Cookie(cookie) => tor::Authentication::Cookie(cookie),
impl TorControlAuthentication {
pub fn hex(data: String) -> Self {
Self::Cookie(TorCookie::Hex(data))
}

pub fn make_tor_auth(self) -> Result<tor::Authentication, Error> {
match self {
TorControlAuthentication::None => Ok(tor::Authentication::None),
TorControlAuthentication::Password(passwd) => Ok(tor::Authentication::HashedPassword(passwd)),
TorControlAuthentication::Cookie(cookie) => match cookie {
TorCookie::Hex(hex) => Ok(tor::Authentication::Cookie(hex)),
TorCookie::FilePath(path) => {
let data = fs::read(path)?.to_hex();
Ok(tor::Authentication::Cookie(data))
},
},
}
}
}
Expand Down Expand Up @@ -79,11 +98,22 @@ impl FromStr for TorControlAuthentication {
Ok(TorControlAuthentication::Password(password.to_string()))
},
"cookie" => {
let password = maybe_value.ok_or_else(|| {
"Invalid format for 'cookie' tor authentication type. It should be in the format 'cookie=xxxxxx'."
.to_string()
})?;
Ok(TorControlAuthentication::Cookie(password.to_string()))
if let Some(value) = maybe_value {
if let Some(mut path) = value.strip_prefix('@') {
if path.is_empty() {
path = DEFAULT_TOR_COOKIE_PATH;
}
Ok(TorControlAuthentication::Cookie(TorCookie::FilePath(path.to_string())))
} else {
Ok(TorControlAuthentication::Cookie(TorCookie::Hex(value.to_string())))
}
} else {
Err(
"Invalid format for 'cookie' tor authentication type. It should be in the format \
'cookie=xxxxxx'."
.into(),
)
}
},
s => Err(format!("Invalid tor auth type '{}'", s)),
}
Expand All @@ -101,3 +131,42 @@ impl fmt::Debug for TorControlAuthentication {
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn tor_parser_test() {
let auth = TorControlAuthentication::from_str("none");
assert_eq!(auth, Ok(TorControlAuthentication::None));

let auth = TorControlAuthentication::from_str("password=");
assert_eq!(auth, Ok(TorControlAuthentication::Password("".into())));

let auth = TorControlAuthentication::from_str("password=123");
assert_eq!(auth, Ok(TorControlAuthentication::Password("123".into())));

let auth = TorControlAuthentication::from_str("cookie=");
assert_eq!(auth, Ok(TorControlAuthentication::hex("".into())));

let auth = TorControlAuthentication::from_str("cookie=8b6f");
assert_eq!(auth, Ok(TorControlAuthentication::hex("8b6f".into())));

let auth = TorControlAuthentication::from_str("cookie=@");
assert_eq!(
auth,
Ok(TorControlAuthentication::Cookie(TorCookie::FilePath(
DEFAULT_TOR_COOKIE_PATH.into()
)))
);

let auth = TorControlAuthentication::from_str("cookie=@/path/to/file");
assert_eq!(
auth,
Ok(TorControlAuthentication::Cookie(TorCookie::FilePath(
"/path/to/file".into()
)))
);
}
}
7 changes: 5 additions & 2 deletions base_layer/p2p/src/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,11 @@ impl TorTransportConfig {
Ok(tor::PortMapping::new(self.onion_port.get(), forward_addr))
}

pub fn to_control_auth(&self) -> tor::Authentication {
self.control_auth.clone().into()
pub fn to_control_auth(&self) -> Result<tor::Authentication, CommsInitializationError> {
self.control_auth
.clone()
.make_tor_auth()
.map_err(CommsInitializationError::from)
}

pub fn to_socks_auth(&self) -> socks::Authentication {
Expand Down
2 changes: 1 addition & 1 deletion base_layer/wallet_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3374,7 +3374,7 @@ pub unsafe extern "C" fn transport_tor_create(
TorControlAuthentication::None
} else {
let cookie_hex = hex::to_hex((*tor_cookie).0.as_slice());
TorControlAuthentication::Cookie(cookie_hex)
TorControlAuthentication::hex(cookie_hex)
};

let onion_port = match NonZeroU16::new(tor_port) {
Expand Down

0 comments on commit c75d224

Please sign in to comment.