tor-netdoc: extract fingerprint logic from routerdesc.rs

This commit is contained in:
Nick Mathewson 2020-05-15 14:40:53 -04:00
parent 84fd65fb85
commit 8f20c273cf
2 changed files with 57 additions and 20 deletions

View File

@ -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<SpFingerprint> for RSAIdentity {
fn from(f: SpFingerprint) -> RSAIdentity {
f.0
}
}
impl From<LongIdent> for RSAIdentity {
fn from(f: LongIdent) -> RSAIdentity {
f.0
}
}
fn parse_hex_ident(s: &str) -> Result<RSAIdentity> {
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<SpFingerprint> {
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<LongIdent> {
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))
}
}
}

View File

@ -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<Self> {
let v: Result<Vec<RSAIdentity>> = s
.split(crate::tokenize::is_sp)
.map(parse_family_ent)
.map(|e| e.parse::<LongIdent>().map(|v| v.into()))
.collect();
Ok(RelayFamily(v?))
}
}
/// Parse a single family entry from a string.
fn parse_family_ent(mut s: &str) -> Result<RSAIdentity> {
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::<SpFingerprint>()?.into();
if fp != rsa_identity.to_rsa_identity() {
return Err(Error::BadArgument(
fp_tok.pos(),
"fingerprint does not match RSA identity".into(),