commit 71bd10097677cd035bd97a6c36b85d07fdbafb62 Author: Nick Mathewson nickm@torproject.org Date: Mon Oct 21 13:02:25 2013 -0400
DROPGUARDS controller command
Implements ticket 9934; patch from "ra" --- changes/bug9934 | 4 ++++ src/or/control.c | 27 +++++++++++++++++++++++++++ src/or/entrynodes.c | 19 +++++++++++++++++++ src/or/entrynodes.h | 2 ++ 4 files changed, 52 insertions(+)
diff --git a/changes/bug9934 b/changes/bug9934 new file mode 100644 index 0000000..2a636db --- /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 e97c18d..65c543a 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 b97b2ea..59cc9a3 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 533f202..1f8cff7 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);
tor-commits@lists.torproject.org