diff options
Diffstat (limited to 'src/or/router.c')
-rw-r--r-- | src/or/router.c | 449 |
1 files changed, 272 insertions, 177 deletions
diff --git a/src/or/router.c b/src/or/router.c index 841f6fde1b..01316c1bc2 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -1,7 +1,7 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2015, The Tor Project, Inc. */ + * Copyright (c) 2007-2016, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ROUTER_PRIVATE @@ -269,8 +269,8 @@ client_identity_key_is_set(void) /** Return the key certificate for this v3 (voting) authority, or NULL * if we have no such certificate. */ -authority_cert_t * -get_my_v3_authority_cert(void) +MOCK_IMPL(authority_cert_t *, +get_my_v3_authority_cert, (void)) { return authority_key_certificate; } @@ -1026,6 +1026,7 @@ init_keys(void) ds = trusted_dir_server_new(options->Nickname, NULL, router_get_advertised_dir_port(options, 0), router_get_advertised_or_port(options), + NULL, digest, v3_digest, type, 0.0); @@ -1078,63 +1079,93 @@ router_reset_reachability(void) can_reach_or_port = can_reach_dir_port = 0; } -/** Return 1 if ORPort is known reachable; else return 0. */ -int -check_whether_orport_reachable(void) +/** Return 1 if we won't do reachability checks, because: + * - AssumeReachable is set, or + * - the network is disabled. + * Otherwise, return 0. + */ +static int +router_reachability_checks_disabled(const or_options_t *options) { - const or_options_t *options = get_options(); return options->AssumeReachable || + net_is_disabled(); +} + +/** Return 0 if we need to do an ORPort reachability check, because: + * - no reachability check has been done yet, or + * - we've initiated reachability checks, but none have succeeded. + * Return 1 if we don't need to do an ORPort reachability check, because: + * - we've seen a successful reachability check, or + * - AssumeReachable is set, or + * - the network is disabled. + */ +int +check_whether_orport_reachable(const or_options_t *options) +{ + int reach_checks_disabled = router_reachability_checks_disabled(options); + return reach_checks_disabled || can_reach_or_port; } -/** Return 1 if we don't have a dirport configured, or if it's reachable. */ +/** Return 0 if we need to do a DirPort reachability check, because: + * - no reachability check has been done yet, or + * - we've initiated reachability checks, but none have succeeded. + * Return 1 if we don't need to do a DirPort reachability check, because: + * - we've seen a successful reachability check, or + * - there is no DirPort set, or + * - AssumeReachable is set, or + * - the network is disabled. + */ int -check_whether_dirport_reachable(void) +check_whether_dirport_reachable(const or_options_t *options) { - const or_options_t *options = get_options(); - return !options->DirPort_set || - options->AssumeReachable || - net_is_disabled() || + int reach_checks_disabled = router_reachability_checks_disabled(options) || + !options->DirPort_set; + return reach_checks_disabled || can_reach_dir_port; } -/** Look at a variety of factors, and return 0 if we don't want to - * advertise the fact that we have a DirPort open. Else return the - * DirPort we want to advertise. - * - * Log a helpful message if we change our mind about whether to publish - * a DirPort. +/** The lower threshold of remaining bandwidth required to advertise (or + * automatically provide) directory services */ +/* XXX Should this be increased? */ +#define MIN_BW_TO_ADVERTISE_DIRSERVER 51200 + +/** Return true iff we have enough configured bandwidth to cache directory + * information. */ +static int +router_has_bandwidth_to_be_dirserver(const or_options_t *options) +{ + if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) { + return 0; + } + if (options->RelayBandwidthRate > 0 && + options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRSERVER) { + return 0; + } + return 1; +} + +/** Helper: Return 1 if we have sufficient resources for serving directory + * requests, return 0 otherwise. + * dir_port is either 0 or the configured DirPort number. + * If AccountingMax is set less than our advertised bandwidth, then don't + * serve requests. Likewise, if our advertised bandwidth is less than + * MIN_BW_TO_ADVERTISE_DIRSERVER, don't bother trying to serve requests. */ static int -decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) +router_should_be_directory_server(const or_options_t *options, int dir_port) { static int advertising=1; /* start out assuming we will advertise */ int new_choice=1; const char *reason = NULL; - /* Section one: reasons to publish or not publish that aren't - * worth mentioning to the user, either because they're obvious - * or because they're normal behavior. */ - - if (!dir_port) /* short circuit the rest of the function */ - return 0; - if (authdir_mode(options)) /* always publish */ - return dir_port; - if (net_is_disabled()) - return 0; - if (!check_whether_dirport_reachable()) - return 0; - if (!router_get_advertised_dir_port(options, dir_port)) - return 0; - - /* Section two: reasons to publish or not publish that the user - * might find surprising. These are generally config options that - * make us choose not to publish. */ - - if (accounting_is_enabled(options)) { + if (accounting_is_enabled(options) && + get_options()->AccountingRule != ACCT_IN) { /* Don't spend bytes for directory traffic if we could end up hibernating, * but allow DirPort otherwise. Some people set AccountingMax because - * they're confused or to get statistics. */ + * they're confused or to get statistics. Directory traffic has a much + * larger effect on output than input so there is no reason to turn it + * off if using AccountingRule in. */ int interval_length = accounting_get_interval_length(); uint32_t effective_bw = get_effective_bwrate(options); uint64_t acc_bytes; @@ -1143,10 +1174,11 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) "seconds long. Raising to 1."); interval_length = 1; } - log_info(LD_GENERAL, "Calculating whether to disable dirport: effective " + log_info(LD_GENERAL, "Calculating whether to advertise %s: effective " "bwrate: %u, AccountingMax: "U64_FORMAT", " - "accounting interval length %d", effective_bw, - U64_PRINTF_ARG(options->AccountingMax), + "accounting interval length %d", + dir_port ? "dirport" : "begindir", + effective_bw, U64_PRINTF_ARG(options->AccountingMax), interval_length); acc_bytes = options->AccountingMax; @@ -1157,10 +1189,7 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) new_choice = 0; reason = "AccountingMax enabled"; } -#define MIN_BW_TO_ADVERTISE_DIRPORT 51200 - } else if (options->BandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT || - (options->RelayBandwidthRate > 0 && - options->RelayBandwidthRate < MIN_BW_TO_ADVERTISE_DIRPORT)) { + } else if (! router_has_bandwidth_to_be_dirserver(options)) { /* if we're advertising a small amount */ new_choice = 0; reason = "BandwidthRate under 50KB"; @@ -1168,15 +1197,91 @@ decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) if (advertising != new_choice) { if (new_choice == 1) { - log_notice(LD_DIR, "Advertising DirPort as %d", dir_port); + if (dir_port > 0) + log_notice(LD_DIR, "Advertising DirPort as %d", dir_port); + else + log_notice(LD_DIR, "Advertising directory service support"); } else { tor_assert(reason); - log_notice(LD_DIR, "Not advertising DirPort (Reason: %s)", reason); + log_notice(LD_DIR, "Not advertising Dir%s (Reason: %s)", + dir_port ? "Port" : "ectory Service support", reason); } advertising = new_choice; } - return advertising ? dir_port : 0; + return advertising; +} + +/** Return 1 if we are configured to accept either relay or directory requests + * from clients and we aren't at risk of exceeding our bandwidth limits, thus + * we should be a directory server. If not, return 0. + */ +int +dir_server_mode(const or_options_t *options) +{ + if (!options->DirCache) + return 0; + return options->DirPort_set || + (server_mode(options) && router_has_bandwidth_to_be_dirserver(options)); +} + +/** Look at a variety of factors, and return 0 if we don't want to + * advertise the fact that we have a DirPort open or begindir support, else + * return 1. + * + * Where dir_port or supports_tunnelled_dir_requests are not relevant, they + * must be 0. + * + * Log a helpful message if we change our mind about whether to publish. + */ +static int +decide_to_advertise_dir_impl(const or_options_t *options, + uint16_t dir_port, + int supports_tunnelled_dir_requests) +{ + /* Part one: reasons to publish or not publish that aren't + * worth mentioning to the user, either because they're obvious + * or because they're normal behavior. */ + + /* short circuit the rest of the function */ + if (!dir_port && !supports_tunnelled_dir_requests) + return 0; + if (authdir_mode(options)) /* always publish */ + return 1; + if (net_is_disabled()) + return 0; + if (dir_port && !router_get_advertised_dir_port(options, dir_port)) + return 0; + if (supports_tunnelled_dir_requests && + !router_get_advertised_or_port(options)) + return 0; + + /* Part two: consider config options that could make us choose to + * publish or not publish that the user might find surprising. */ + return router_should_be_directory_server(options, dir_port); +} + +/** Front-end to decide_to_advertise_dir_impl(): return 0 if we don't want to + * advertise the fact that we have a DirPort open, else return the + * DirPort we want to advertise. + */ +static int +decide_to_advertise_dirport(const or_options_t *options, uint16_t dir_port) +{ + /* supports_tunnelled_dir_requests is not relevant, pass 0 */ + return decide_to_advertise_dir_impl(options, dir_port, 0) ? dir_port : 0; +} + +/** Front-end to decide_to_advertise_dir_impl(): return 0 if we don't want to + * advertise the fact that we support begindir requests, else return 1. + */ +static int +decide_to_advertise_begindir(const or_options_t *options, + int supports_tunnelled_dir_requests) +{ + /* dir_port is not relevant, pass 0 */ + return decide_to_advertise_dir_impl(options, 0, + supports_tunnelled_dir_requests); } /** Allocate and return a new extend_info_t that can be used to build @@ -1210,9 +1315,9 @@ void consider_testing_reachability(int test_or, int test_dir) { const routerinfo_t *me = router_get_my_routerinfo(); - int orport_reachable = check_whether_orport_reachable(); - tor_addr_t addr; const or_options_t *options = get_options(); + int orport_reachable = check_whether_orport_reachable(options); + tor_addr_t addr; if (!me) return; @@ -1243,14 +1348,15 @@ consider_testing_reachability(int test_or, int test_dir) extend_info_free(ei); } + /* XXX IPv6 self testing */ tor_addr_from_ipv4h(&addr, me->addr); - if (test_dir && !check_whether_dirport_reachable() && + if (test_dir && !check_whether_dirport_reachable(options) && !connection_get_by_type_addr_port_purpose( CONN_TYPE_DIR, &addr, me->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)) { /* ask myself, via tor, for my server descriptor. */ - directory_initiate_command(&addr, - me->or_port, me->dir_port, + directory_initiate_command(&addr, me->or_port, + &addr, me->dir_port, me->cache_info.identity_digest, DIR_PURPOSE_FETCH_SERVERDESC, ROUTER_PURPOSE_GENERAL, @@ -1263,18 +1369,19 @@ void router_orport_found_reachable(void) { const routerinfo_t *me = router_get_my_routerinfo(); + const or_options_t *options = get_options(); if (!can_reach_or_port && me) { char *address = tor_dup_ip(me->addr); log_notice(LD_OR,"Self-testing indicates your ORPort is reachable from " "the outside. Excellent.%s", - get_options()->PublishServerDescriptor_ != NO_DIRINFO - && check_whether_dirport_reachable() ? + options->PublishServerDescriptor_ != NO_DIRINFO + && check_whether_dirport_reachable(options) ? " Publishing server descriptor." : ""); can_reach_or_port = 1; mark_my_descriptor_dirty("ORPort found reachable"); /* This is a significant enough change to upload immediately, * at least in a test network */ - if (get_options()->TestingTorNetwork == 1) { + if (options->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } control_event_server_status(LOG_NOTICE, @@ -1289,19 +1396,20 @@ void router_dirport_found_reachable(void) { const routerinfo_t *me = router_get_my_routerinfo(); + const or_options_t *options = get_options(); if (!can_reach_dir_port && me) { char *address = tor_dup_ip(me->addr); log_notice(LD_DIRSERV,"Self-testing indicates your DirPort is reachable " "from the outside. Excellent.%s", - get_options()->PublishServerDescriptor_ != NO_DIRINFO - && check_whether_orport_reachable() ? + options->PublishServerDescriptor_ != NO_DIRINFO + && check_whether_orport_reachable(options) ? " Publishing server descriptor." : ""); can_reach_dir_port = 1; - if (decide_to_advertise_dirport(get_options(), me->dir_port)) { + if (decide_to_advertise_dirport(options, me->dir_port)) { mark_my_descriptor_dirty("DirPort found reachable"); /* This is a significant enough change to upload immediately, * at least in a test network */ - if (get_options()->TestingTorNetwork == 1) { + if (options->TestingTorNetwork == 1) { reschedule_descriptor_update_check(); } } @@ -1460,8 +1568,8 @@ static int server_is_advertised=0; /** Return true iff we have published our descriptor lately. */ -int -advertised_server_mode(void) +MOCK_IMPL(int, +advertised_server_mode,(void)) { return server_is_advertised; } @@ -1498,8 +1606,10 @@ proxy_mode(const or_options_t *options) * and * - We have ORPort set * and - * - We believe both our ORPort and DirPort (if present) are reachable from + * - We believe our ORPort and DirPort (if present) are reachable from * the outside; or + * - We believe our ORPort is reachable from the outside, and we can't + * check our DirPort because the consensus has no exits; or * - We are an authoritative directory server. */ static int @@ -1517,8 +1627,15 @@ decide_if_publishable_server(void) return 1; if (!router_get_advertised_or_port(options)) return 0; - - return check_whether_orport_reachable() && check_whether_dirport_reachable(); + if (!check_whether_orport_reachable(options)) + return 0; + if (router_have_consensus_path() == CONSENSUS_PATH_INTERNAL) { + /* All set: there are no exits in the consensus (maybe this is a tiny + * test network), so we can't check our DirPort reachability. */ + return 1; + } else { + return check_whether_dirport_reachable(options); + } } /** Initiate server descriptor upload as reasonable (if server is publishable, @@ -1689,7 +1806,8 @@ router_upload_dir_desc_to_dirservers(int force) int router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port) { - if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ + const routerinfo_t *me = router_get_my_routerinfo(); + if (!me) /* make sure routerinfo exists */ return -1; /* make sure it's resolved to something. this way we can't get a @@ -1697,20 +1815,21 @@ router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port) if (tor_addr_is_null(addr)) return -1; - /* look at desc_routerinfo->exit_policy for both the v4 and the v6 - * policies. The exit_policy field in desc_routerinfo is a bit unusual, - * in that it contains IPv6 and IPv6 entries. We don't want to look - * at desc_routerinfio->ipv6_exit_policy, since that's a port summary. */ + /* look at router_get_my_routerinfo()->exit_policy for both the v4 and the + * v6 policies. The exit_policy field in router_get_my_routerinfo() is a + * bit unusual, in that it contains IPv6 and IPv6 entries. We don't want to + * look at router_get_my_routerinfo()->ipv6_exit_policy, since that's a port + * summary. */ if ((tor_addr_family(addr) == AF_INET || tor_addr_family(addr) == AF_INET6)) { return compare_tor_addr_to_addr_policy(addr, port, - desc_routerinfo->exit_policy) != ADDR_POLICY_ACCEPTED; + me->exit_policy) != ADDR_POLICY_ACCEPTED; #if 0 } else if (tor_addr_family(addr) == AF_INET6) { return get_options()->IPv6Exit && desc_routerinfo->ipv6_exit_policy && compare_tor_addr_to_short_policy(addr, port, - desc_routerinfo->ipv6_exit_policy) != ADDR_POLICY_ACCEPTED; + me->ipv6_exit_policy) != ADDR_POLICY_ACCEPTED; #endif } else { return -1; @@ -1719,13 +1838,13 @@ router_compare_to_my_exit_policy(const tor_addr_t *addr, uint16_t port) /** Return true iff my exit policy is reject *:*. Return -1 if we don't * have a descriptor */ -int -router_my_exit_policy_is_reject_star(void) +MOCK_IMPL(int, +router_my_exit_policy_is_reject_star,(void)) { - if (!router_get_my_routerinfo()) /* make sure desc_routerinfo exists */ + if (!router_get_my_routerinfo()) /* make sure routerinfo exists */ return -1; - return desc_routerinfo->policy_is_reject_star; + return router_get_my_routerinfo()->policy_is_reject_star; } /** Return true iff I'm a server and <b>digest</b> is equal to @@ -1784,12 +1903,13 @@ const char * router_get_my_descriptor(void) { const char *body; - if (!router_get_my_routerinfo()) + const routerinfo_t *me = router_get_my_routerinfo(); + if (! me) return NULL; + tor_assert(me->cache_info.saved_location == SAVED_NOWHERE); + body = signed_descriptor_get_body(&me->cache_info); /* Make sure this is nul-terminated. */ - tor_assert(desc_routerinfo->cache_info.saved_location == SAVED_NOWHERE); - body = signed_descriptor_get_body(&desc_routerinfo->cache_info); - tor_assert(!body[desc_routerinfo->cache_info.signed_descriptor_len]); + tor_assert(!body[me->cache_info.signed_descriptor_len]); log_debug(LD_GENERAL,"my desc is '%s'", body); return body; } @@ -1824,8 +1944,8 @@ static int router_guess_address_from_dir_headers(uint32_t *guess); * it's configured in torrc, or because we've learned it from * dirserver headers. Place the answer in *<b>addr</b> and return * 0 on success, else return -1 if we have no guess. */ -int -router_pick_published_address(const or_options_t *options, uint32_t *addr) +MOCK_IMPL(int, +router_pick_published_address,(const or_options_t *options, uint32_t *addr)) { *addr = get_last_resolved_addr(); if (!*addr && @@ -1870,6 +1990,8 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) ri->addr = addr; ri->or_port = router_get_advertised_or_port(options); ri->dir_port = router_get_advertised_dir_port(options, 0); + ri->supports_tunnelled_dir_requests = + directory_permits_begindir_requests(options); ri->cache_info.published_on = time(NULL); ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from * main thread */ @@ -1885,7 +2007,11 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) ! p->server_cfg.no_advertise && ! p->server_cfg.bind_ipv4_only && tor_addr_family(&p->addr) == AF_INET6) { - if (! tor_addr_is_internal(&p->addr, 0)) { + /* Like IPv4, if the relay is configured using the default + * authorities, disallow internal IPs. Otherwise, allow them. */ + const int default_auth = (!options->DirAuthorities && + !options->AlternateDirAuthority); + if (! tor_addr_is_internal(&p->addr, 0) || ! default_auth) { ipv6_orport = p; break; } else { @@ -1893,7 +2019,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) log_warn(LD_CONFIG, "Unable to use configured IPv6 address \"%s\" in a " "descriptor. Skipping it. " - "Try specifying a globally reachable address explicitly. ", + "Try specifying a globally reachable address explicitly.", tor_addr_to_str(addrbuf, &p->addr, sizeof(addrbuf), 1)); } } @@ -1910,7 +2036,8 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) routerinfo_free(ri); return -1; } - ri->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); + ri->cache_info.signing_key_cert = + tor_cert_dup(get_master_signing_key_cert()); get_platform_str(platform, sizeof(platform)); ri->platform = tor_strdup(platform); @@ -1927,7 +2054,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) /* DNS is screwed up; don't claim to be an exit. */ policies_exit_policy_append_reject_star(&ri->exit_policy); } else { - policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr,1, + policies_parse_exit_policy_from_options(options,ri->addr,&ri->ipv6_addr, &ri->exit_policy); } ri->policy_is_reject_star = @@ -2002,7 +2129,9 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) ei->cache_info.is_extrainfo = 1; strlcpy(ei->nickname, get_options()->Nickname, sizeof(ei->nickname)); ei->cache_info.published_on = ri->cache_info.published_on; - ei->signing_key_cert = tor_cert_dup(get_master_signing_key_cert()); + ei->cache_info.signing_key_cert = + tor_cert_dup(get_master_signing_key_cert()); + memcpy(ei->cache_info.identity_digest, ri->cache_info.identity_digest, DIGEST_LEN); if (extrainfo_dump_to_string(&ei->cache_info.signed_descriptor_body, @@ -2028,7 +2157,7 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) memcpy(ri->cache_info.extra_info_digest, ei->cache_info.signed_descriptor_digest, DIGEST_LEN); - memcpy(ri->extra_info_digest256, + memcpy(ri->cache_info.extra_info_digest256, ei->digest256, DIGEST256_LEN); } else { @@ -2069,7 +2198,9 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) ri->cache_info.signed_descriptor_digest); if (ei) { - tor_assert(! routerinfo_incompatible_with_extrainfo(ri, ei, NULL, NULL)); + tor_assert(! + routerinfo_incompatible_with_extrainfo(ri->identity_pkey, ei, + &ri->cache_info, NULL)); } *r = ri; @@ -2190,10 +2321,10 @@ check_descriptor_bandwidth_changed(time_t now) { static time_t last_changed = 0; uint64_t prev, cur; - if (!desc_routerinfo) + if (!router_get_my_routerinfo()) return; - prev = desc_routerinfo->bandwidthcapacity; + prev = router_get_my_routerinfo()->bandwidthcapacity; cur = we_are_hibernating() ? 0 : rep_hist_bandwidth_assess(); if ((prev != cur && (!prev || !cur)) || cur > prev*2 || @@ -2247,11 +2378,11 @@ check_descriptor_ipaddress_changed(time_t now) (void) now; - if (!desc_routerinfo) + if (router_get_my_routerinfo() == NULL) return; /* XXXX ipv6 */ - prev = desc_routerinfo->addr; + prev = router_get_my_routerinfo()->addr; if (resolve_my_address(LOG_INFO, options, &cur, &method, &hostname) < 0) { log_info(LD_CONFIG,"options->Address didn't resolve into an IP."); return; @@ -2323,7 +2454,7 @@ router_new_address_suggestion(const char *suggestion, if (tor_addr_eq(&d_conn->base_.addr, &addr)) { /* Don't believe anybody who says our IP is their IP. */ log_debug(LD_DIR, "A directory server told us our IP address is %s, " - "but he's just reporting his own IP address. Ignoring.", + "but they are just reporting their own IP address. Ignoring.", suggestion); return; } @@ -2398,7 +2529,8 @@ router_dump_router_to_string(routerinfo_t *router, const or_options_t *options = get_options(); smartlist_t *chunks = NULL; char *output = NULL; - const int emit_ed_sigs = signing_keypair && router->signing_key_cert; + const int emit_ed_sigs = signing_keypair && + router->cache_info.signing_key_cert; char *ed_cert_line = NULL; char *rsa_tap_cc_line = NULL; char *ntor_cc_line = NULL; @@ -2410,12 +2542,12 @@ router_dump_router_to_string(routerinfo_t *router, goto err; } if (emit_ed_sigs) { - if (!router->signing_key_cert->signing_key_included || - !ed25519_pubkey_eq(&router->signing_key_cert->signed_key, + if (!router->cache_info.signing_key_cert->signing_key_included || + !ed25519_pubkey_eq(&router->cache_info.signing_key_cert->signed_key, &signing_keypair->pubkey)) { log_warn(LD_BUG, "Tried to sign a router descriptor with a mismatched " "ed25519 key chain %d", - router->signing_key_cert->signing_key_included); + router->cache_info.signing_key_cert->signing_key_included); goto err; } } @@ -2431,14 +2563,14 @@ router_dump_router_to_string(routerinfo_t *router, char ed_cert_base64[256]; char ed_fp_base64[ED25519_BASE64_LEN+1]; if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), - (const char*)router->signing_key_cert->encoded, - router->signing_key_cert->encoded_len, - BASE64_ENCODE_MULTILINE) < 0) { + (const char*)router->cache_info.signing_key_cert->encoded, + router->cache_info.signing_key_cert->encoded_len, + BASE64_ENCODE_MULTILINE) < 0) { log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); goto err; } if (ed25519_public_to_base64(ed_fp_base64, - &router->signing_key_cert->signing_key)<0) { + &router->cache_info.signing_key_cert->signing_key)<0) { log_err(LD_BUG,"Couldn't base64-encode identity key\n"); goto err; } @@ -2465,15 +2597,15 @@ router_dump_router_to_string(routerinfo_t *router, } /* Cross-certify with RSA key */ - if (tap_key && router->signing_key_cert && - router->signing_key_cert->signing_key_included) { + if (tap_key && router->cache_info.signing_key_cert && + router->cache_info.signing_key_cert->signing_key_included) { char buf[256]; int tap_cc_len = 0; uint8_t *tap_cc = make_tap_onion_key_crosscert(tap_key, - &router->signing_key_cert->signing_key, - router->identity_pkey, - &tap_cc_len); + &router->cache_info.signing_key_cert->signing_key, + router->identity_pkey, + &tap_cc_len); if (!tap_cc) { log_warn(LD_BUG,"make_tap_onion_key_crosscert failed!"); goto err; @@ -2495,16 +2627,16 @@ router_dump_router_to_string(routerinfo_t *router, } /* Cross-certify with onion keys */ - if (ntor_keypair && router->signing_key_cert && - router->signing_key_cert->signing_key_included) { + if (ntor_keypair && router->cache_info.signing_key_cert && + router->cache_info.signing_key_cert->signing_key_included) { int sign = 0; char buf[256]; /* XXXX Base the expiration date on the actual onion key expiration time?*/ tor_cert_t *cert = make_ntor_onion_key_crosscert(ntor_keypair, - &router->signing_key_cert->signing_key, - router->cache_info.published_on, - MIN_ONION_KEY_LIFETIME, &sign); + &router->cache_info.signing_key_cert->signing_key, + router->cache_info.published_on, + MIN_ONION_KEY_LIFETIME, &sign); if (!cert) { log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!"); goto err; @@ -2543,9 +2675,9 @@ router_dump_router_to_string(routerinfo_t *router, char extra_info_digest[HEX_DIGEST_LEN+1]; base16_encode(extra_info_digest, sizeof(extra_info_digest), router->cache_info.extra_info_digest, DIGEST_LEN); - if (!tor_digest256_is_zero(router->extra_info_digest256)) { + if (!tor_digest256_is_zero(router->cache_info.extra_info_digest256)) { char d256_64[BASE64_DIGEST256_LEN+1]; - digest256_to_base64(d256_64, router->extra_info_digest256); + digest256_to_base64(d256_64, router->cache_info.extra_info_digest256); tor_asprintf(&extra_info_line, "extra-info-digest %s %s\n", extra_info_digest, d256_64); } else { @@ -2646,6 +2778,11 @@ router_dump_router_to_string(routerinfo_t *router, tor_free(p6); } + if (decide_to_advertise_begindir(options, + router->supports_tunnelled_dir_requests)) { + smartlist_add(chunks, tor_strdup("tunnelled-dir-server\n")); + } + /* Sign the descriptor with Ed25519 */ if (emit_ed_sigs) { smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); @@ -2733,44 +2870,13 @@ router_dump_exit_policy_to_string(const routerinfo_t *router, int include_ipv4, int include_ipv6) { - smartlist_t *exit_policy_strings; - char *policy_string = NULL; - if ((!router->exit_policy) || (router->policy_is_reject_star)) { return tor_strdup("reject *:*"); } - exit_policy_strings = smartlist_new(); - - SMARTLIST_FOREACH_BEGIN(router->exit_policy, addr_policy_t *, tmpe) { - char *pbuf; - int bytes_written_to_pbuf; - if ((tor_addr_family(&tmpe->addr) == AF_INET6) && (!include_ipv6)) { - continue; /* Don't include IPv6 parts of address policy */ - } - if ((tor_addr_family(&tmpe->addr) == AF_INET) && (!include_ipv4)) { - continue; /* Don't include IPv4 parts of address policy */ - } - - pbuf = tor_malloc(POLICY_BUF_LEN); - bytes_written_to_pbuf = policy_write_item(pbuf,POLICY_BUF_LEN, tmpe, 1); - - if (bytes_written_to_pbuf < 0) { - log_warn(LD_BUG, "router_dump_exit_policy_to_string ran out of room!"); - tor_free(pbuf); - goto done; - } - - smartlist_add(exit_policy_strings,pbuf); - } SMARTLIST_FOREACH_END(tmpe); - - policy_string = smartlist_join_strings(exit_policy_strings, "\n", 0, NULL); - - done: - SMARTLIST_FOREACH(exit_policy_strings, char *, str, tor_free(str)); - smartlist_free(exit_policy_strings); - - return policy_string; + return policy_dump_to_string(router->exit_policy, + include_ipv4, + include_ipv6); } /** Copy the primary (IPv4) OR port (IP address and TCP port) for @@ -2877,7 +2983,8 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, time_t now = time(NULL); smartlist_t *chunks = smartlist_new(); extrainfo_t *ei_tmp = NULL; - const int emit_ed_sigs = signing_keypair && extrainfo->signing_key_cert; + const int emit_ed_sigs = signing_keypair && + extrainfo->cache_info.signing_key_cert; char *ed_cert_line = NULL; base16_encode(identity, sizeof(identity), @@ -2885,19 +2992,19 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, format_iso_time(published, extrainfo->cache_info.published_on); bandwidth_usage = rep_hist_get_bandwidth_lines(); if (emit_ed_sigs) { - if (!extrainfo->signing_key_cert->signing_key_included || - !ed25519_pubkey_eq(&extrainfo->signing_key_cert->signed_key, + if (!extrainfo->cache_info.signing_key_cert->signing_key_included || + !ed25519_pubkey_eq(&extrainfo->cache_info.signing_key_cert->signed_key, &signing_keypair->pubkey)) { log_warn(LD_BUG, "Tried to sign a extrainfo descriptor with a " "mismatched ed25519 key chain %d", - extrainfo->signing_key_cert->signing_key_included); + extrainfo->cache_info.signing_key_cert->signing_key_included); goto err; } char ed_cert_base64[256]; if (base64_encode(ed_cert_base64, sizeof(ed_cert_base64), - (const char*)extrainfo->signing_key_cert->encoded, - extrainfo->signing_key_cert->encoded_len, - BASE64_ENCODE_MULTILINE) < 0) { + (const char*)extrainfo->cache_info.signing_key_cert->encoded, + extrainfo->cache_info.signing_key_cert->encoded_len, + BASE64_ENCODE_MULTILINE) < 0) { log_err(LD_BUG,"Couldn't base64-encode signing key certificate!"); goto err; } @@ -3385,28 +3492,16 @@ router_free_all(void) /** Return a smartlist of tor_addr_port_t's with all the OR ports of <b>ri</b>. Note that freeing of the items in the list as well as - the smartlist itself is the callers responsibility. - - XXX duplicating code from node_get_all_orports(). */ + the smartlist itself is the callers responsibility. */ smartlist_t * router_get_all_orports(const routerinfo_t *ri) { - smartlist_t *sl = smartlist_new(); tor_assert(ri); - - if (ri->addr != 0) { - tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); - tor_addr_from_ipv4h(&ap->addr, ri->addr); - ap->port = ri->or_port; - smartlist_add(sl, ap); - } - if (!tor_addr_is_null(&ri->ipv6_addr)) { - tor_addr_port_t *ap = tor_malloc(sizeof(tor_addr_port_t)); - tor_addr_copy(&ap->addr, &ri->ipv6_addr); - ap->port = ri->or_port; - smartlist_add(sl, ap); - } - - return sl; + node_t fake_node; + memset(&fake_node, 0, sizeof(fake_node)); + /* we don't modify ri, fake_node is passed as a const node_t * + */ + fake_node.ri = (routerinfo_t *)ri; + return node_get_all_orports(&fake_node); } |