commit ae9220cb41083c876af3a7492cf0d5218eaf1d60
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Thu Mar 10 09:17:06 2011 +0100
Warn if a bridge network status is possibly stale.
In February 2011, Tonga's tor process died, but it's tar cronjob continued
to suppy us with "fresh" bridge descriptor tarballs (containing stale
descriptors). We didn't detect this for two weeks, because we derive the
bridge network status publication time from the tarball filename, and it
looked recent all the time.
Adding a check whether the most recent descriptor that is contained in a
bridge network status was published more than 1 hour before the status
itself. This is a sign for the status being stale, even though it's not
100% reliable. We still should investigate these cases when they occur.
A test with the January and February 2011 tarballs shows that we'd have
learned about Tonga's tor process dying 60-90 minutes after the fact.
---
.../ernie/db/SanitizedBridgesWriter.java | 25 ++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/src/org/torproject/ernie/db/SanitizedBridgesWriter.java b/src/org/torproject/ernie/db/SanitizedBridgesWriter.java
index aa1bcec..7376e5a 100644
--- a/src/org/torproject/ernie/db/SanitizedBridgesWriter.java
+++ b/src/org/torproject/ernie/db/SanitizedBridgesWriter.java
@@ -403,6 +403,7 @@ public class SanitizedBridgesWriter {
BufferedReader br = new BufferedReader(new StringReader(new String(
data, "US-ASCII")));
String line = null;
+ String mostRecentDescPublished = null;
while ((line = br.readLine()) != null) {
/* r lines contain sensitive information that needs to be removed
@@ -433,6 +434,13 @@ public class SanitizedBridgesWriter {
this.bridgeDescriptorMappings.put(mappingKey, mapping);
}
+ /* Determine most recent descriptor publication time. */
+ if (descPublicationTime.compareTo(publicationTime) <= 0 &&
+ (mostRecentDescPublished == null ||
+ descPublicationTime.compareTo(mostRecentDescPublished) > 0)) {
+ mostRecentDescPublished = descPublicationTime;
+ }
+
/* Write scrubbed r line to buffer. */
String hashedBridgeIdentityBase64 = Base64.encodeBase64String(
DigestUtils.sha(Base64.decodeBase64(bridgeIdentity
@@ -480,6 +488,23 @@ public class SanitizedBridgesWriter {
scrubbed = new StringBuilder();
}
+ /* Check if we can tell from the descriptor publication times
+ * whether this status is possibly stale. */
+ SimpleDateFormat formatter = new SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss");
+ formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
+ if (formatter.parse(publicationTime).getTime() -
+ formatter.parse(mostRecentDescPublished).getTime() >
+ 60L * 60L * 1000L) {
+ this.logger.warning("The most recent descriptor in the bridge "
+ + "network status published at " + publicationTime + " was "
+ + "published at " + mostRecentDescPublished + " which is "
+ + "more than 1 hour before the status. This is a sign for "
+ + "the status being stale. Please check!");
+ }
+ } catch (ParseException e) {
+ this.logger.log(Level.WARNING, "Could not parse timestamp in "
+ + "bridge network status.", e);
} catch (IOException e) {
this.logger.log(Level.WARNING, "Could not parse bridge network "
+ "status.", e);