arti_testing/
dirfilter.rsuse anyhow::{anyhow, Result};
use rand::Rng;
use std::sync::{Arc, Mutex};
use tor_dirmgr::filter::DirFilter;
use tor_netdoc::{
doc::{
microdesc::Microdesc,
netstatus::{RouterStatus, UncheckedMdConsensus},
},
types::{family::RelayFamily, policy::PortPolicy},
};
pub(crate) fn new_filter(s: &str) -> Result<Arc<dyn DirFilter + 'static>> {
Ok(match s {
"replace-onion-keys" => Arc::new(ReplaceOnionKeysFilter),
"one-big-family" => Arc::new(OneBigFamilyFilter::default()),
"no-exit-ports" => Arc::new(NoExitPortsFilter::default()),
"bad-signatures" => Arc::new(BadSignaturesFilter),
"non-existent-signing-keys" => Arc::new(NonexistentSigningKeysFilter),
"bad-microdesc-digests" => Arc::new(BadMicrodescDigestsFilter),
_ => {
return Err(anyhow!(
"Unrecognized filter. Options are:
replace-onion-keys, one-big-family, no-exit-ports, bad-signatures,
non-existent-signing-keys, bad-microdesc-digests."
));
}
})
}
#[derive(Debug)]
struct NilFilter;
impl DirFilter for NilFilter {}
pub(crate) fn nil_filter() -> Arc<dyn DirFilter + 'static> {
Arc::new(NilFilter)
}
#[derive(Debug, Default)]
struct ReplaceOnionKeysFilter;
impl DirFilter for ReplaceOnionKeysFilter {
fn filter_md(&self, mut md: Microdesc) -> tor_dirmgr::Result<Microdesc> {
let junk_key: [u8; 32] = rand::thread_rng().gen();
md.ntor_onion_key = junk_key.into();
Ok(md)
}
}
#[derive(Debug, Default)]
struct OneBigFamilyFilter {
new_family: Mutex<Arc<RelayFamily>>,
}
impl DirFilter for OneBigFamilyFilter {
fn filter_consensus(
&self,
consensus: UncheckedMdConsensus,
) -> tor_dirmgr::Result<UncheckedMdConsensus> {
let mut new_family = RelayFamily::new();
for r in consensus.dangerously_peek().consensus.relays() {
new_family.push(*r.rsa_identity());
}
*self.new_family.lock().expect("poisoned lock") = Arc::new(new_family);
Ok(consensus)
}
fn filter_md(&self, mut md: Microdesc) -> tor_dirmgr::Result<Microdesc> {
let big_family = self.new_family.lock().expect("poisoned lock").clone();
md.family = big_family;
Ok(md)
}
}
#[derive(Debug)]
struct NoExitPortsFilter {
reject_all: Arc<PortPolicy>,
}
impl Default for NoExitPortsFilter {
fn default() -> Self {
Self {
reject_all: Arc::new(PortPolicy::new_reject_all()),
}
}
}
impl DirFilter for NoExitPortsFilter {
fn filter_md(&self, mut md: Microdesc) -> tor_dirmgr::Result<Microdesc> {
md.ipv4_policy = self.reject_all.clone();
md.ipv6_policy = self.reject_all.clone();
Ok(md)
}
}
#[derive(Debug, Default)]
struct BadSignaturesFilter;
impl DirFilter for BadSignaturesFilter {
fn filter_consensus(
&self,
consensus: UncheckedMdConsensus,
) -> tor_dirmgr::Result<UncheckedMdConsensus> {
let (mut consensus, (start_time, end_time)) = consensus.dangerously_into_parts();
consensus.siggroup.sha1 = Some(*b"can you reverse sha1");
consensus.siggroup.sha256 = Some(*b"sha256 preimage is harder so far");
Ok(UncheckedMdConsensus::new_from_start_end(
consensus, start_time, end_time,
))
}
}
#[derive(Debug, Default)]
struct NonexistentSigningKeysFilter;
impl DirFilter for NonexistentSigningKeysFilter {
fn filter_consensus(
&self,
consensus: UncheckedMdConsensus,
) -> tor_dirmgr::Result<UncheckedMdConsensus> {
let (mut consensus, (start_time, end_time)) = consensus.dangerously_into_parts();
let mut rng = rand::thread_rng();
for signature in consensus.siggroup.signatures.iter_mut() {
let sk_fingerprint: [u8; 20] = rng.gen();
signature.key_ids.sk_fingerprint = sk_fingerprint.into();
}
Ok(UncheckedMdConsensus::new_from_start_end(
consensus, start_time, end_time,
))
}
}
#[derive(Debug, Default)]
struct BadMicrodescDigestsFilter;
impl DirFilter for BadMicrodescDigestsFilter {
fn filter_consensus(
&self,
consensus: UncheckedMdConsensus,
) -> tor_dirmgr::Result<UncheckedMdConsensus> {
let (mut consensus, (start_time, end_time)) = consensus.dangerously_into_parts();
let mut rng = rand::thread_rng();
for rs in consensus.consensus.relays.iter_mut() {
rs.rs.doc_digest = rng.gen();
}
Ok(UncheckedMdConsensus::new_from_start_end(
consensus, start_time, end_time,
))
}
}