Commit 193a144c authored by Roger Dingledine's avatar Roger Dingledine
Browse files

Make "UpdateBridgesFromAuthority" torrc option work: when bridge

users configure that and specify a bridge with an identity
fingerprint, now they will lookup the bridge descriptor at the
default bridge authority via a one-hop tunnel, but once circuits
are established they will switch to a three-hop tunnel for later
connections to the bridge authority.


svn:r11550
parent 6aadc607
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -3,6 +3,14 @@ Changes in version 0.2.0.7-alpha - 2007-09-21
    - Set up moria1 and tor26 as the first v3 directory authorities. See
      doc/spec/dir-spec.txt for details on the new directory design.

  o Major features (bridges):
    - Make "UpdateBridgesFromAuthority" torrc option work: when bridge
      users configure that and specify a bridge with an identity
      fingerprint, now they will lookup the bridge descriptor at the
      default bridge authority via a one-hop tunnel, but once circuits
      are established they will switch to a three-hop tunnel for later
      connections to the bridge authority.

  o Minor features (security):
    - As a client, do not believe any server that tells us that any address
      maps to an internal address space.
+4 −1
Original line number Diff line number Diff line
@@ -2927,6 +2927,9 @@ fetch_bridge_descriptors(time_t now)
      ask_bridge_directly = tor_digest_is_zero(bridge->identity) ||
                            !options->UpdateBridgesFromAuthority ||
                            !num_bridge_auths;
      log_debug(LD_DIR, "ask_bridge_directly=%d (%d, %d, %d)",
                ask_bridge_directly, tor_digest_is_zero(bridge->identity),
                !options->UpdateBridgesFromAuthority, !num_bridge_auths);

      if (ask_bridge_directly &&
          !fascist_firewall_allows_address_or(bridge->addr, bridge->port)) {
@@ -2961,7 +2964,7 @@ fetch_bridge_descriptors(time_t now)
        log_info(LD_DIR, "Fetching bridge info '%s' from bridge authority.",
                 resource);
        directory_get_from_dirserver(DIR_PURPOSE_FETCH_SERVERDESC,
                ROUTER_PURPOSE_BRIDGE, resource, 1);
                ROUTER_PURPOSE_BRIDGE, resource, 0);
      }
    });
}
+55 −41
Original line number Diff line number Diff line
@@ -49,7 +49,8 @@ static void dir_networkstatus_download_failed(smartlist_t *failed,
                                              int status_code);
static void dir_routerdesc_download_failed(smartlist_t *failed,
                                           int status_code,
                                           int was_extrainfo);
                                           int was_extrainfo,
                                           int was_descriptor_digests);
static void note_request(const char *key, size_t bytes);

/********* START VARIABLES **********/
@@ -78,8 +79,8 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose)
{
  if (get_options()->AllDirActionsPrivate)
    return 1;
  if (router_purpose == ROUTER_PURPOSE_BRIDGE)
    return 1; /* if we have to ask, better make it anonymous */
  if (router_purpose == ROUTER_PURPOSE_BRIDGE && has_completed_circuit)
    return 1; /* if no circuits yet, we may need this info to bootstrap. */
  if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
      dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
      dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
@@ -307,7 +308,8 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
  if (!options->FetchServerDescriptors && type != HIDSERV_AUTHORITY)
    return;

  if (!get_via_tor && options->UseBridges) {
  if (!get_via_tor) {
    if (options->UseBridges && type != BRIDGE_AUTHORITY) {
      /* want to ask a running bridge for which we have a descriptor. */
      routerinfo_t *ri = choose_random_entry(NULL);
      if (ri) {
@@ -321,13 +323,13 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
        log_notice(LD_DIR, "Ignoring directory request, since no bridge "
                           "nodes are available yet.");
      return;
  } else if (!get_via_tor) {
    if (prefer_authority) {
    } else {
      if (prefer_authority || type == BRIDGE_AUTHORITY) {
        /* only ask authdirservers, and don't ask myself */
        rs = router_pick_trusteddirserver(type, 1, 1,
                                          retry_if_no_servers);
      }
    if (!rs) {
      if (!rs && type != BRIDGE_AUTHORITY) {
        /* anybody with a non-zero dirport will do */
        rs = router_pick_directory_server(1, 1, type,
                                          retry_if_no_servers);
@@ -340,6 +342,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
            get_via_tor = 1; /* last resort: try routing it via Tor */
        }
      }
    }
  } else { /* get_via_tor */
    /* Never use fascistfirewall; we're going via Tor. */
    if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
@@ -1342,6 +1345,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
    int was_ei = conn->_base.purpose == DIR_PURPOSE_FETCH_EXTRAINFO;
    smartlist_t *which = NULL;
    int n_asked_for = 0;
    int descriptor_digests = conn->requested_resource &&
                             !strcmpstart(conn->requested_resource,"d/");
    log_info(LD_DIR,"Received %s (size %d) from server '%s:%d'",
             was_ei ? "extra server info" : "server info",
             (int)body_len, conn->_base.address, conn->_base.port);
@@ -1350,9 +1355,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
    else
      note_request(was_compressed?"dl/server.z":"dl/server", orig_len);
    if (conn->requested_resource &&
        !strcmpstart(conn->requested_resource,"d/")) {
        (!strcmpstart(conn->requested_resource,"d/") ||
         !strcmpstart(conn->requested_resource,"fp/"))) {
      which = smartlist_create();
      dir_split_resource_into_fingerprints(conn->requested_resource+2,
      dir_split_resource_into_fingerprints(conn->requested_resource +
                                             (descriptor_digests ? 2 : 3),
                                           which, NULL, 0, 0);
      n_asked_for = smartlist_len(which);
    }
@@ -1370,7 +1377,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
      if (!which) {
        connection_dir_download_routerdesc_failed(conn);
      } else {
        dir_routerdesc_download_failed(which, status_code, was_ei);
        dir_routerdesc_download_failed(which, status_code,
                                       was_ei, descriptor_digests);
        SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
        smartlist_free(which);
      }
@@ -1391,10 +1399,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
                    get_options()->UseBridges)))) {
      /* as we learn from them, we remove them from 'which' */
      if (was_ei) {
        router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which);
        router_load_extrainfo_from_string(body, NULL, SAVED_NOWHERE, which,
                                          descriptor_digests);
      } else {
        router_load_routers_from_string(body, NULL, SAVED_NOWHERE, which,
                                        conn->router_purpose);
                               descriptor_digests, conn->router_purpose);
        directory_info_has_arrived(now, 0);
      }
    }
@@ -1403,7 +1412,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
               n_asked_for-smartlist_len(which), n_asked_for,
               conn->_base.address, (int)conn->_base.port);
      if (smartlist_len(which)) {
        dir_routerdesc_download_failed(which, status_code, was_ei);
        dir_routerdesc_download_failed(which, status_code,
                                       was_ei, descriptor_digests);
      }
      SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
      smartlist_free(which);
@@ -2527,15 +2537,19 @@ dir_networkstatus_download_failed(smartlist_t *failed, int status_code)
}

/** Called when one or more routerdesc (or extrainfo, if <b>was_extrainfo</b>)
 * fetches have failed (with uppercase fingerprints listed in
 * <b>failed</b>). */
 * fetches have failed (with uppercase fingerprints listed in <b>failed</b>,
 * either as descriptor digests or as identity digests based on
 * <b>was_descriptor_digests</b>).
 */
static void
dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
                               int was_extrainfo)
                               int was_extrainfo, int was_descriptor_digests)
{
  char digest[DIGEST_LEN];
  time_t now = time(NULL);
  int server = server_mode(get_options()) && get_options()->DirPort;
  if (!was_descriptor_digests)
    return; /* FFFF should implement this someday */
  SMARTLIST_FOREACH(failed, const char *, cp,
  {
    download_status_t *dls = NULL;
+3 −1
Original line number Diff line number Diff line
@@ -3514,10 +3514,12 @@ int router_load_single_router(const char *s, uint8_t purpose,
void router_load_routers_from_string(const char *s, const char *eos,
                                     saved_location_t saved_location,
                                     smartlist_t *requested_fingerprints,
                                     int descriptor_digests,
                                     uint8_t purpose);
void router_load_extrainfo_from_string(const char *s, const char *eos,
                                       saved_location_t saved_location,
                                       smartlist_t *requested_fps);
                                       smartlist_t *requested_fps,
                                       int descriptor_digests);

typedef enum {
  NS_FROM_CACHE, NS_FROM_DIR_BY_FP, NS_FROM_DIR_ALL, NS_GENERATED
+22 −10
Original line number Diff line number Diff line
@@ -724,11 +724,11 @@ router_reload_router_list_impl(desc_store_t *store)
    if (extrainfo)
      router_load_extrainfo_from_string(store->mmap->data,
                                        store->mmap->data+store->mmap->size,
                                        SAVED_IN_CACHE, NULL);
                                        SAVED_IN_CACHE, NULL, 0);
    else
      router_load_routers_from_string(store->mmap->data,
                                      store->mmap->data+store->mmap->size,
                                      SAVED_IN_CACHE, NULL,
                                      SAVED_IN_CACHE, NULL, 0,
                                      ROUTER_PURPOSE_GENERAL);
  }

@@ -738,10 +738,11 @@ router_reload_router_list_impl(desc_store_t *store)
    contents = read_file_to_str(fname, RFTS_BIN|RFTS_IGNORE_MISSING, &st);
  if (contents) {
    if (extrainfo)
      router_load_extrainfo_from_string(contents, NULL,SAVED_IN_JOURNAL, NULL);
      router_load_extrainfo_from_string(contents, NULL,SAVED_IN_JOURNAL,
                                        NULL, 0);
    else
      router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL, NULL,
                                      ROUTER_PURPOSE_GENERAL);
      router_load_routers_from_string(contents, NULL, SAVED_IN_JOURNAL,
                                      NULL, 0, ROUTER_PURPOSE_GENERAL);
    store->journal_len = (size_t) st.st_size;
    tor_free(contents);
  }
@@ -3128,14 +3129,18 @@ router_load_single_router(const char *s, uint8_t purpose, const char **msg)
 * the journal.
 *
 * If <b>requested_fingerprints</b> is provided, it must contain a list of
 * uppercased identity fingerprints.  Do not update any router whose
 * uppercased fingerprints.  Do not update any router whose
 * fingerprint is not on the list; after updating a router, remove its
 * fingerprint from the list.
 *
 * If <b>descriptor_digests</b> is non-zero, then the requested_fingerprints
 * are descriptor digests. Otherwise they are identity digests.
 */
void
router_load_routers_from_string(const char *s, const char *eos,
                                saved_location_t saved_location,
                                smartlist_t *requested_fingerprints,
                                int descriptor_digests,
                                uint8_t purpose)
{
  smartlist_t *routers = smartlist_create(), *changed = smartlist_create();
@@ -3151,9 +3156,11 @@ router_load_routers_from_string(const char *s, const char *eos,

  SMARTLIST_FOREACH(routers, routerinfo_t *, ri,
  {
    base16_encode(fp, sizeof(fp), ri->cache_info.signed_descriptor_digest,
                  DIGEST_LEN);
    if (requested_fingerprints) {
      base16_encode(fp, sizeof(fp), descriptor_digests ?
                      ri->cache_info.signed_descriptor_digest :
                      ri->cache_info.identity_digest,
                    DIGEST_LEN);
      if (smartlist_string_isin(requested_fingerprints, fp)) {
        smartlist_string_remove(requested_fingerprints, fp);
      } else {
@@ -3195,7 +3202,8 @@ router_load_routers_from_string(const char *s, const char *eos,
void
router_load_extrainfo_from_string(const char *s, const char *eos,
                                  saved_location_t saved_location,
                                  smartlist_t *requested_fingerprints)
                                  smartlist_t *requested_fingerprints,
                                  int descriptor_digests)
{
  smartlist_t *extrainfo_list = smartlist_create();
  const char *msg;
@@ -3208,9 +3216,13 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
  SMARTLIST_FOREACH(extrainfo_list, extrainfo_t *, ei, {
      if (requested_fingerprints) {
        char fp[HEX_DIGEST_LEN+1];
        base16_encode(fp, sizeof(fp), ei->cache_info.signed_descriptor_digest,
        base16_encode(fp, sizeof(fp), descriptor_digests ?
                        ei->cache_info.signed_descriptor_digest :
                        ei->cache_info.identity_digest,
                      DIGEST_LEN);
        smartlist_string_remove(requested_fingerprints, fp);
        /* XXX020 We silently let people stuff us with extrainfos we
         * didn't ask for. Is this a problem? -RD */
      }
      router_add_extrainfo_to_routerlist(ei, &msg, from_cache, !from_cache);
    });