aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-10-21 13:02:25 -0400
committerNick Mathewson <nickm@torproject.org>2013-10-21 13:02:25 -0400
commit71bd10097677cd035bd97a6c36b85d07fdbafb62 (patch)
treec721e0bbe724ae462e46b7c44ab094c7d4fcdccb
parent17d368281ad374908fb019e29f3f012659be010c (diff)
downloadtor-71bd10097677cd035bd97a6c36b85d07fdbafb62.tar
tor-71bd10097677cd035bd97a6c36b85d07fdbafb62.tar.gz
DROPGUARDS controller command
Implements ticket 9934; patch from "ra"
-rw-r--r--changes/bug99344
-rw-r--r--src/or/control.c27
-rw-r--r--src/or/entrynodes.c19
-rw-r--r--src/or/entrynodes.h2
4 files changed, 52 insertions, 0 deletions
diff --git a/changes/bug9934 b/changes/bug9934
new file mode 100644
index 000000000..2a636dba8
--- /dev/null
+++ b/changes/bug9934
@@ -0,0 +1,4 @@
+ o Minor features (controller):
+ - New DROPGUARDS command to forget all current entry guards. Not
+ recommended for ordinary use, since replacing guards too frequently
+ makes several attacks easier. Resolves ticket #9934; patch from "ra".
diff --git a/src/or/control.c b/src/or/control.c
index e97c18d89..65c543a43 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -3141,6 +3141,30 @@ handle_control_usefeature(control_connection_t *conn,
return 0;
}
+/** Implementation for the DROPGUARDS command. */
+static int
+handle_control_dropguards(control_connection_t *conn,
+ uint32_t len,
+ const char *body)
+{
+ smartlist_t *args;
+ (void) len; /* body is nul-terminated; it's safe to ignore the length */
+ args = smartlist_new();
+ smartlist_split_string(args, body, " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+
+ if (smartlist_len(args)) {
+ connection_printf_to_buf(conn, "512 Too many arguments to DROPGUARDS\r\n");
+ } else {
+ remove_all_entry_guards();
+ send_control_done(conn);
+ }
+
+ SMARTLIST_FOREACH(args, char *, cp, tor_free(cp));
+ smartlist_free(args);
+ return 0;
+}
+
/** Called when <b>conn</b> has no more bytes left on its outbuf. */
int
connection_control_finished_flushing(control_connection_t *conn)
@@ -3440,6 +3464,9 @@ connection_control_process_inbuf(control_connection_t *conn)
} else if (!strcasecmp(conn->incoming_cmd, "AUTHCHALLENGE")) {
if (handle_control_authchallenge(conn, cmd_data_len, args))
return -1;
+ } else if (!strcasecmp(conn->incoming_cmd, "DROPGUARDS")) {
+ if (handle_control_dropguards(conn, cmd_data_len, args))
+ return -1;
} else {
connection_printf_to_buf(conn, "510 Unrecognized command \"%s\"\r\n",
conn->incoming_cmd);
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index b97b2ea39..59cc9a3fc 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -598,6 +598,25 @@ remove_dead_entry_guards(time_t now)
return changed ? 1 : 0;
}
+/** Remove all currently listed entry guards. So new ones will be chosen. */
+void
+remove_all_entry_guards(void)
+{
+ char dbuf[HEX_DIGEST_LEN+1];
+
+ while (smartlist_len(entry_guards)) {
+ entry_guard_t *entry = smartlist_get(entry_guards, 0);
+ base16_encode(dbuf, sizeof(dbuf), entry->identity, DIGEST_LEN);
+ log_info(LD_CIRC, "Entry guard '%s' (%s) has been dropped.",
+ entry->nickname, dbuf);
+ control_event_guard(entry->nickname, entry->identity, "DROPPED");
+ entry_guard_free(entry);
+ smartlist_del(entry_guards, 0);
+ }
+ log_entry_guards(LOG_INFO);
+ entry_guards_changed();
+}
+
/** A new directory or router-status has arrived; update the down/listed
* status of the entry guards.
*
diff --git a/src/or/entrynodes.h b/src/or/entrynodes.h
index 533f2027a..1f8cff75a 100644
--- a/src/or/entrynodes.h
+++ b/src/or/entrynodes.h
@@ -77,6 +77,8 @@ int num_live_entry_guards(int for_directory);
#endif
+void remove_all_entry_guards(void);
+
void entry_guards_compute_status(const or_options_t *options, time_t now);
int entry_guard_register_connect_status(const char *digest, int succeeded,
int mark_relay_status, time_t now);