From 8f20c273cfb0270b00f7082ad4b676268d13fff9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 15 May 2020 14:40:53 -0400 Subject: [PATCH] tor-netdoc: extract fingerprint logic from routerdesc.rs --- tor-netdoc/src/argtype.rs | 53 ++++++++++++++++++++++++++++++++++++ tor-netdoc/src/routerdesc.rs | 24 +++------------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/tor-netdoc/src/argtype.rs b/tor-netdoc/src/argtype.rs index f20554fe1..042488ba6 100644 --- a/tor-netdoc/src/argtype.rs +++ b/tor-netdoc/src/argtype.rs @@ -8,6 +8,7 @@ pub use b64impl::*; pub use curve25519impl::*; pub use edcert::*; +pub use fingerprint::*; pub use rsa::*; pub use timeimpl::*; @@ -200,3 +201,55 @@ mod edcert { } } } + +mod fingerprint { + use crate::{Error, Pos, Result}; + use tor_llcrypto::pk::rsa::RSAIdentity; + + // A hex-encoded fingerprint with spaces in it. + pub struct SpFingerprint(RSAIdentity); + + // A "long identity" in the format used for Family members. + pub struct LongIdent(RSAIdentity); + + impl From for RSAIdentity { + fn from(f: SpFingerprint) -> RSAIdentity { + f.0 + } + } + + impl From for RSAIdentity { + fn from(f: LongIdent) -> RSAIdentity { + f.0 + } + } + + fn parse_hex_ident(s: &str) -> Result { + let bytes = hex::decode(s) + .map_err(|_| Error::BadArgument(Pos::at(s), "invalid hexadecimal in family".into()))?; + RSAIdentity::from_bytes(&bytes) + .ok_or_else(|| Error::BadArgument(Pos::at(s), "wrong length on fingerprint".into())) + } + + impl std::str::FromStr for SpFingerprint { + type Err = Error; + fn from_str(s: &str) -> Result { + let ident = parse_hex_ident(&s.replace(' ', "")).map_err(|e| e.at_pos(Pos::at(s)))?; + Ok(SpFingerprint(ident)) + } + } + + impl std::str::FromStr for LongIdent { + type Err = Error; + fn from_str(mut s: &str) -> Result { + if s.starts_with('$') { + s = &s[1..]; + } + if let Some(idx) = s.find(|ch| ch == '=' || ch == '~') { + s = &s[..idx]; + } + let ident = parse_hex_ident(s)?; + Ok(LongIdent(ident)) + } + } +} diff --git a/tor-netdoc/src/routerdesc.rs b/tor-netdoc/src/routerdesc.rs index dfd78a9a5..b9819bbf2 100644 --- a/tor-netdoc/src/routerdesc.rs +++ b/tor-netdoc/src/routerdesc.rs @@ -33,7 +33,7 @@ use crate::parse::{Section, SectionRules}; use crate::policy::*; use crate::rules::Keyword; use crate::version::TorVersion; -use crate::{Error, Pos, Result}; +use crate::{Error, Result}; use lazy_static::lazy_static; use std::{net, time}; @@ -99,26 +99,12 @@ impl std::str::FromStr for RelayFamily { fn from_str(s: &str) -> Result { let v: Result> = s .split(crate::tokenize::is_sp) - .map(parse_family_ent) + .map(|e| e.parse::().map(|v| v.into())) .collect(); Ok(RelayFamily(v?)) } } -/// Parse a single family entry from a string. -fn parse_family_ent(mut s: &str) -> Result { - if s.starts_with('$') { - s = &s[1..]; - } - if let Some(idx) = s.find(|ch| ch == '=' || ch == '~') { - s = &s[..idx]; - } - let bytes = hex::decode(s) - .map_err(|_| Error::BadArgument(Pos::at(s), "invalid hexadecimal in family".into()))?; - RSAIdentity::from_bytes(&bytes) - .ok_or_else(|| Error::BadArgument(Pos::at(s), "wrong length on fingerprint".into())) -} - /// Description of the software a relay is running. pub enum RelayPlatform { /// Software advertised to be some version of Tor, on some platform. @@ -485,10 +471,8 @@ impl RouterDesc { // fingerprint: check for consistency with RSA identity. if let Some(fp_tok) = body.get(FINGERPRINT) { - let fp_val = fp_tok.args_as_str().replace(' ', ""); - let bytes = hex::decode(&fp_val) - .map_err(|e| Error::BadArgument(fp_tok.pos(), e.to_string()))?; - if bytes != rsa_identity.to_rsa_identity().as_bytes() { + let fp: RSAIdentity = fp_tok.args_as_str().parse::()?.into(); + if fp != rsa_identity.to_rsa_identity() { return Err(Error::BadArgument( fp_tok.pos(), "fingerprint does not match RSA identity".into(),