Let bridge users use the non-primary address of a multi-homed bridge

This commit is contained in:
Roger Dingledine 2010-06-03 20:29:29 -04:00
parent 2eec9ea4e8
commit 7e300cbba3
4 changed files with 55 additions and 11 deletions

View File

@ -0,0 +1,8 @@
o Minor bugfixes:
- If you run a bridge that listens on multiple IP addresses, and
some user configures a bridge address that uses a different IP
address than your bridge writes in its router descriptor, and the
user doesn't specify an identity key, their Tor would discard the
descriptor because "it isn't one of our configured bridges", and
fail to bootstrap. Now believe the descriptor and bootstrap anyway.
Bugfix on 0.2.0.3-alpha.

View File

@ -4053,29 +4053,56 @@ clear_bridge_list(void)
* (either by comparing keys if possible, else by comparing addr/port).
* Else return NULL. */
static bridge_info_t *
routerinfo_get_configured_bridge(routerinfo_t *ri)
get_configured_bridge_by_addr_port_digest(tor_addr_t *addr, uint16_t port,
const char *digest)
{
if (!bridge_list)
return NULL;
SMARTLIST_FOREACH_BEGIN(bridge_list, bridge_info_t *, bridge)
{
if (tor_digest_is_zero(bridge->identity) &&
tor_addr_eq_ipv4h(&bridge->addr, ri->addr) &&
bridge->port == ri->or_port)
!tor_addr_compare(&bridge->addr, addr, CMP_EXACT) &&
bridge->port == port)
return bridge;
if (!memcmp(bridge->identity, ri->cache_info.identity_digest,
DIGEST_LEN))
if (!memcmp(bridge->identity, digest, DIGEST_LEN))
return bridge;
}
SMARTLIST_FOREACH_END(bridge);
return NULL;
}
/** Wrapper around get_configured_bridge_by_addr_port_digest() to look
* it up via router descriptor <b>ri</b>. */
static bridge_info_t *
get_configured_bridge_by_routerinfo(routerinfo_t *ri)
{
tor_addr_t addr;
tor_addr_from_ipv4h(&addr, ri->addr);
return get_configured_bridge_by_addr_port_digest(&addr,
ri->or_port, ri->cache_info.identity_digest);
}
/** Return 1 if <b>ri</b> is one of our known bridges, else 0. */
int
routerinfo_is_a_configured_bridge(routerinfo_t *ri)
{
return routerinfo_get_configured_bridge(ri) ? 1 : 0;
return get_configured_bridge_by_routerinfo(ri) ? 1 : 0;
}
/** We made a connection to a router at <b>addr</b>:<b>port</b>
* without knowing its digest. Its digest turned out to be <b>digest</b>.
* If it was a bridge, and we still don't know its digest, record it.
*/
void
learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest)
{
bridge_info_t *bridge =
get_configured_bridge_by_addr_port_digest(addr, port, digest);
if (bridge && tor_digest_is_zero(bridge->identity)) {
memcpy(bridge->identity, digest, DIGEST_LEN);
log_notice(LD_DIR, "Learned fingerprint %s for bridge %s:%d",
hex_str(digest, DIGEST_LEN), fmt_addr(addr), port);
}
}
/** Remember a new bridge at <b>addr</b>:<b>port</b>. If <b>digest</b>
@ -4215,7 +4242,7 @@ learned_bridge_descriptor(routerinfo_t *ri, int from_cache)
tor_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
if (get_options()->UseBridges) {
int first = !any_bridge_descriptors_known();
bridge_info_t *bridge = routerinfo_get_configured_bridge(ri);
bridge_info_t *bridge = get_configured_bridge_by_routerinfo(ri);
time_t now = time(NULL);
ri->is_running = 1;

View File

@ -926,16 +926,19 @@ connection_or_nonopen_was_started_here(or_connection_t *conn)
* the certificate to be weird or absent.
*
* If we return 0, and the certificate is as expected, write a hash of the
* identity key into digest_rcvd, which must have DIGEST_LEN space in it. (If
* we return -1 this buffer is undefined.) If the certificate is invalid
* or missing on an incoming connection, we return 0 and set digest_rcvd to
* DIGEST_LEN 0 bytes.
* identity key into <b>digest_rcvd_out</b>, which must have DIGEST_LEN
* space in it.
* If the certificate is invalid or missing on an incoming connection,
* we return 0 and set <b>digest_rcvd_out</b> to DIGEST_LEN NUL bytes.
* (If we return -1, the contents of this buffer are undefined.)
*
* As side effects,
* 1) Set conn->circ_id_type according to tor-spec.txt.
* 2) If we're an authdirserver and we initiated the connection: drop all
* descriptors that claim to be on that IP/port but that aren't
* this guy; and note that this guy is reachable.
* 3) If this is a bridge and we didn't configure its identity
* fingerprint, remember the keyid we just learned.
*/
static int
connection_or_check_valid_tls_handshake(or_connection_t *conn,
@ -1007,6 +1010,10 @@ connection_or_check_valid_tls_handshake(or_connection_t *conn,
log_info(LD_HANDSHAKE, "Connected to router %s at %s:%d without knowing "
"its key. Hoping for the best.",
conn->nickname, conn->_base.address, conn->_base.port);
/* if it's a bridge and we didn't know its identity fingerprint, now
* we do -- remember it for future attempts. */
learned_router_identity(&conn->_base.addr, conn->_base.port,
digest_rcvd_out);
}
if (started_here) {

View File

@ -2997,6 +2997,8 @@ int getinfo_helper_entry_guards(control_connection_t *conn,
void clear_bridge_list(void);
int routerinfo_is_a_configured_bridge(routerinfo_t *ri);
void
learned_router_identity(tor_addr_t *addr, uint16_t port, const char *digest);
void bridge_add_from_config(const tor_addr_t *addr, uint16_t port,
char *digest);
void retry_bridge_descriptor_fetch_directly(const char *digest);