guardmgr: Don't use no-md guards for data circs.

If we don't know a current microdescriptor for a guard, we can't use it
for multihop circuits, since we don't know its onion keys.

This is part of a fix for #178.
This commit is contained in:
Nick Mathewson 2022-01-06 09:52:21 -05:00
parent 214ac17eed
commit db65fdd04e
1 changed files with 31 additions and 5 deletions

View File

@ -118,6 +118,11 @@ pub(crate) struct Guard {
#[serde(with = "humantime_serde")]
unlisted_since: Option<SystemTime>,
/// True if this guard is listed in the latest consensus, but we don't
/// have a microdescriptor for it.
#[serde(skip)]
microdescriptor_missing: bool,
/// When did we last give out this guard in response to a request?
#[serde(skip)]
last_tried_to_connect_at: Option<Instant>,
@ -204,6 +209,7 @@ impl Guard {
confirmed_at: None,
unlisted_since: None,
microdescriptor_missing: false,
last_tried_to_connect_at: None,
reachable: Reachable::Unknown,
failing_since: None,
@ -313,8 +319,19 @@ impl Guard {
/// Return true if this guard is suitable to use for the provided `usage`.
pub(crate) fn conforms_to_usage(&self, usage: &GuardUsage) -> bool {
use crate::GuardUsageKind;
if usage.kind == GuardUsageKind::OneHopDirectory && !self.is_dir_cache {
return false;
match usage.kind {
GuardUsageKind::OneHopDirectory => {
if !self.is_dir_cache {
return false;
}
}
GuardUsageKind::Data => {
// We need a "definitely listed" guard to build a multihop
// circuit.
if self.microdescriptor_missing {
return false;
}
}
}
self.obeys_restrictions(&usage.restrictions[..])
}
@ -331,7 +348,7 @@ impl Guard {
// This is a tricky check, since if we're missing a microdescriptor
// for the RSA id, we won't know whether the ed25519 id is listed or
// not.
let listed = match netdir.id_pair_listed(&self.id.ed25519, &self.id.rsa) {
let listed_as_guard = match netdir.id_pair_listed(&self.id.ed25519, &self.id.rsa) {
Some(true) => {
// Definitely listed.
let relay = self
@ -346,10 +363,19 @@ impl Guard {
relay.is_flagged_guard()
}
Some(false) => false, // Definitely not listed.
None => return, // Nothing to do: we can't tell if it's listed.
None => {
// We can't tell if this is listed: The RSA id is present, but
// the microdescriptor is missing so we don't know the Ed25519 ID.
self.microdescriptor_missing = true;
return;
}
};
if listed {
// We got a definite answer, so we aren't missing a microdesc for this
// guard.
self.microdescriptor_missing = false;
if listed_as_guard {
// Definitely listed, so clear unlisted_since.
self.mark_listed();
} else {