commit 4581684aa786d9966df190388b18e2b24a734ce1 Author: Karsten Loesing karsten.loesing@gmx.net Date: Fri Dec 9 15:22:08 2011 +0100
Check votes and signatures in downloaded consensuses.
Implements the rest of #4250. --- src/org/torproject/doctor/Checker.java | 49 +++++++++++++++++++++++ src/org/torproject/doctor/Parser.java | 18 ++++++-- src/org/torproject/doctor/Status.java | 20 +++++++++ src/org/torproject/doctor/StatusFileReport.java | 12 ++++++ src/org/torproject/doctor/Warning.java | 11 +++++- 5 files changed, 104 insertions(+), 6 deletions(-)
diff --git a/src/org/torproject/doctor/Checker.java b/src/org/torproject/doctor/Checker.java index a0f55c2..4d6493f 100755 --- a/src/org/torproject/doctor/Checker.java +++ b/src/org/torproject/doctor/Checker.java @@ -35,6 +35,8 @@ public class Checker { this.findMostRecentConsensus(); this.checkMissingConsensuses(); this.checkAllConsensusesFresh(); + this.checkContainedVotes(); + this.checkConsensusSignatures(); if (this.downloadedConsensus != null) { if (this.isConsensusFresh(this.downloadedConsensus)) { this.checkConsensusMethods(); @@ -102,6 +104,53 @@ public class Checker { } }
+ /* Check if all downloaded consensuses contain the same set of votes. */ + private void checkContainedVotes() { + Set<String> allVotes = new HashSet<String>(); + for (Status consensus : downloadedConsensuses.values()) { + allVotes.addAll(consensus.getContainedVotes()); + } + SortedSet<String> missingVotes = new TreeSet<String>(); + for (Map.Entry<String, Status> e : downloadedConsensuses.entrySet()) { + String nickname = e.getKey(); + Status downloadedConsensus = e.getValue(); + if (!downloadedConsensus.getContainedVotes().containsAll( + allVotes)) { + missingVotes.add(nickname); + } + } + if (!missingVotes.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String nickname : missingVotes) { + sb.append(", " + nickname); + } + this.warnings.put(Warning.ConsensusMissingVotes, + sb.toString().substring(2)); + } + } + + /* Check if all downloaded consensuses contain signatures from all other + * authorities. */ + private void checkConsensusSignatures() { + SortedSet<String> missingSignatures = new TreeSet<String>(); + for (Map.Entry<String, Status> e : downloadedConsensuses.entrySet()) { + String nickname = e.getKey(); + Status downloadedConsensus = e.getValue(); + if (!downloadedConsensus.getContainedSignatures().containsAll( + downloadedConsensus.getContainedVotes())) { + missingSignatures.add(nickname); + } + } + if (!missingSignatures.isEmpty()) { + StringBuilder sb = new StringBuilder(); + for (String nickname : missingSignatures) { + sb.append(", " + nickname); + } + this.warnings.put(Warning.ConsensusMissingSignatures, + sb.toString().substring(2)); + } + } + /* Check if the most recent consensus is older than 1 hour. */ private boolean isConsensusFresh(Status consensus) { return (consensus.getValidAfterMillis() >= diff --git a/src/org/torproject/doctor/Parser.java b/src/org/torproject/doctor/Parser.java index 9a91033..d318f29 100755 --- a/src/org/torproject/doctor/Parser.java +++ b/src/org/torproject/doctor/Parser.java @@ -108,9 +108,15 @@ public class Parser { status.addConsensusParam(paramName, paramValue); } } - } else if (line.startsWith("dir-source ") && !isConsensus) { - status.setNickname(line.split(" ")[1]); - status.setFingerprint(line.split(" ")[2]); + } else if (line.startsWith("dir-source ")) { + String nickname = line.split(" ")[1]; + String fingerprint = line.split(" ")[2]; + if (isConsensus) { + status.addContainedVote(fingerprint); + } else { + status.setNickname(line.split(" ")[1]); + status.setFingerprint(line.split(" ")[2]); + } } else if (line.startsWith("dir-key-expires ")) { try { status.setDirKeyExpiresMillis(dateTimeFormat.parse( @@ -140,8 +146,6 @@ public class Parser { } if (line.startsWith("r ")) { rLine = line; - } else { - break; } } else if (line.startsWith("s ") || line.equals("s")) { sLine = line; @@ -156,6 +160,10 @@ public class Parser { } else if (line.startsWith("w ") && !isConsensus && line.contains(" Measured")) { bandwidthWeights++; + } else if (line.startsWith("directory-signature ") && + isConsensus) { + String fingerprint = line.split(" ")[1]; + status.addContainedSignature(fingerprint); } } br.close(); diff --git a/src/org/torproject/doctor/Status.java b/src/org/torproject/doctor/Status.java index 0573ae2..df41e47 100755 --- a/src/org/torproject/doctor/Status.java +++ b/src/org/torproject/doctor/Status.java @@ -136,6 +136,26 @@ public class Status implements Comparable<Status> { return this.knownFlags; }
+ /* Fingerprints of directory authorities of contained votes (only + * relevant for consensuses). */ + private SortedSet<String> containedVotes = new TreeSet<String>(); + public void addContainedVote(String fingerprint) { + this.containedVotes.add(fingerprint); + } + public SortedSet<String> getContainedVotes() { + return this.containedVotes; + } + + /* Fingerprints of directory authorities of contained signatures (only + * relevant for consensuses). */ + private SortedSet<String> containedSignatures = new TreeSet<String>(); + public void addContainedSignature(String fingerprint) { + this.containedSignatures.add(fingerprint); + } + public SortedSet<String> getContainedSignatures() { + return this.containedSignatures; + } + /* Number of status entries with the Running flag. */ private int runningRelays; public void setRunningRelays(int runningRelays) { diff --git a/src/org/torproject/doctor/StatusFileReport.java b/src/org/torproject/doctor/StatusFileReport.java index 1fe3b87..a43a27e 100755 --- a/src/org/torproject/doctor/StatusFileReport.java +++ b/src/org/torproject/doctor/StatusFileReport.java @@ -138,6 +138,18 @@ public class StatusFileReport implements Report { + "not reporting bandwidth scanner results: " + details, 150L * 60L * 1000L); break; + case ConsensusMissingVotes: + warningStrings.put("The consensuses downloaded from the " + + "following authorities are missing votes that are " + + "contained in consensuses downloaded from other " + + "authorities: " + details, 150L * 60L * 1000L); + break; + case ConsensusMissingSignatures: + warningStrings.put("The consensuses downloaded from the " + + "following authorities are missing signatures from " + + "other, previously voting authorities: " + details, + 150L * 60L * 1000L); + break; } } long now = System.currentTimeMillis(); diff --git a/src/org/torproject/doctor/Warning.java b/src/org/torproject/doctor/Warning.java index d592926..0cb8cd8 100755 --- a/src/org/torproject/doctor/Warning.java +++ b/src/org/torproject/doctor/Warning.java @@ -41,6 +41,15 @@ public enum Warning {
/* One or more directory authorities are not reporting bandwidth scanner * results. */ - BandwidthScannerResultsMissing + BandwidthScannerResultsMissing, + + /* The consensuses downloaded from one or more authorities are missing + * votes that are contained in consensuses downloaded from other + * authorities. */ + ConsensusMissingVotes, + + /* The consensuses downloaded from one or more authorities are missing + * signatures from other, previously voting authorities. */ + ConsensusMissingSignatures }
tor-commits@lists.torproject.org