diff options
author | Nick Mathewson <nickm@torproject.org> | 2005-04-06 21:09:47 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2005-04-06 21:09:47 +0000 |
commit | 7709547c08709cfdbd5866a3dc0c73c0a6925346 (patch) | |
tree | c79ddb275cd1ec1ed6a7c874fc8852a1feb332ec /src/or | |
parent | 03720b39fdb347296c02d9f42618910c83d83f4f (diff) | |
download | tor-7709547c08709cfdbd5866a3dc0c73c0a6925346.tar.gz tor-7709547c08709cfdbd5866a3dc0c73c0a6925346.zip |
When we connect and finish TLS negotiation with address:port, it is obvious that any other key or nickname we might know about (as an authdirserver) does not actually exist at address:port.
svn:r4036
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/connection_or.c | 15 | ||||
-rw-r--r-- | src/or/dirserv.c | 47 | ||||
-rw-r--r-- | src/or/or.h | 4 |
3 files changed, 58 insertions, 8 deletions
diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 0d7f40376b..4f8943e60a 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -498,7 +498,13 @@ connection_tls_finish_handshake(connection_t *conn) { #endif if (connection_or_nonopen_was_started_here(conn)) { - /* I initiated this connection. */ + if (authdir_mode(options)) { + /* We initiated this connection to address:port. Drop all routers + * with the same address:port and a different key or nickname. + */ + dirserv_orconn_tls_done(conn->address, conn->port, + digest_rcvd, nickname); + } if (conn->nickname[0] == '$') { /* I was aiming for a particular digest. Did I get it? */ char d[HEX_DIGEST_LEN+1]; @@ -508,7 +514,6 @@ connection_tls_finish_handshake(connection_t *conn) { "Identity key not as expected for router at %s:%d: wanted %s but got %s", conn->address, conn->port, conn->nickname, d); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); - // XXX if we're an authdir_mode, forget about nickname's descriptor return -1; } } else if (strcasecmp(conn->nickname, nickname)) { @@ -517,14 +522,8 @@ connection_tls_finish_handshake(connection_t *conn) { "Other side (%s:%d) is '%s', but we tried to connect to '%s'", conn->address, conn->port, nickname, conn->nickname); control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED); - // XXX if we're an authdir_mode, forget about nickname's descriptor return -1; } - if (authdir_mode(options)) { - /* I got exactly the guy I wanted. Now go through and blow away - * descriptors for exactly this Address:ORPort that aren't this guy. */ - //XXX - } } else { if ((c=connection_get_by_identity_digest(digest_rcvd, CONN_TYPE_OR))) { log_fn(LOG_INFO,"Router '%s' is already connected on fd %d. Dropping fd %d.", nickname, c->s, conn->s); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 3ed831710f..d966fb1ca8 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -993,6 +993,53 @@ size_t dirserv_get_runningrouters(const char **rr, int compress) return compress ? the_runningrouters_z_len : the_runningrouters_len; } +/** Called when a TLS handshake has completed successfully with a + * router listening at <b>address</b>:<b>or_port</b>, and has yielded + * a certificate with digest <b>digest_rcvd</b> and nickname + * <b>nickname_rcvd</b>. When this happens, it's clear that any other + * descriptors for that address/port combination must be unusable: + * delete them if they are not verified. + */ +void +dirserv_orconn_tls_done(const char *address, + uint16_t or_port, + const char *digest_rcvd, + const char *nickname_rcvd) +{ + int i; + tor_assert(address); + tor_assert(digest_rcvd); + tor_assert(nickname_rcvd); + + if (!descriptor_list) + return; + + for (i = 0; i < smartlist_len(descriptor_list); ++i) { + routerinfo_t *ri = smartlist_get(descriptor_list, i); + int drop = 0; + if (ri->is_verified) + continue; + if (!strcasecmp(address, ri->address) && + or_port == ri->or_port) { + /* We have a router at the same address! */ + if (strcasecmp(ri->nickname, nickname_rcvd)) { + log_fn(LOG_WARN, "Dropping descriptor: nickname '%s' does not match nickname '%s' in cert from %s:%d", + ri->nickname, nickname_rcvd, address, or_port); + drop = 1; + } else if (memcmp(ri->identity_digest, digest_rcvd, DIGEST_LEN)) { + log_fn(LOG_WARN, "Dropping descriptor: identity key does not match key in cert from %s:%d", + address, or_port); + drop = 1; + } + if (drop) { + routerinfo_free(ri); + smartlist_del(descriptor_list, i--); + directory_set_dirty(); + } + } + } +} + void dirserv_free_all(void) { diff --git a/src/or/or.h b/src/or/or.h index 6d1467e79a..09b1fbc5a1 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1480,6 +1480,10 @@ size_t dirserv_get_directory(const char **cp, int compress); size_t dirserv_get_runningrouters(const char **rr, int compress); void dirserv_set_cached_directory(const char *directory, time_t when, int is_running_routers); +void dirserv_orconn_tls_done(const char *address, + uint16_t or_port, + const char *digest_rcvd, + const char *nickname); void dirserv_free_all(void); /********************************* dns.c ***************************/ |