diff options
Diffstat (limited to 'src/or/router.c')
-rw-r--r-- | src/or/router.c | 212 |
1 files changed, 160 insertions, 52 deletions
diff --git a/src/or/router.c b/src/or/router.c index 31f2ff00d2..55b58e5d11 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-2016, The Tor Project, Inc. */ + * Copyright (c) 2007-2017, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #define ROUTER_PRIVATE @@ -148,6 +148,51 @@ dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last) tor_mutex_release(key_lock); } +/** Expire our old set of onion keys. This is done by setting + * last_curve25519_onion_key and lastonionkey to all zero's and NULL + * respectively. + * + * This function does not perform any grace period checks for the old onion + * keys. + */ +void +expire_old_onion_keys(void) +{ + char *fname = NULL; + + tor_mutex_acquire(key_lock); + + /* Free lastonionkey and set it to NULL. */ + if (lastonionkey) { + crypto_pk_free(lastonionkey); + lastonionkey = NULL; + } + + /* We zero out the keypair. See the tor_mem_is_zero() check made in + * construct_ntor_key_map() below. */ + memset(&last_curve25519_onion_key, 0, sizeof(last_curve25519_onion_key)); + + tor_mutex_release(key_lock); + + fname = get_datadir_fname2("keys", "secret_onion_key.old"); + if (file_status(fname) == FN_FILE) { + if (tor_unlink(fname) != 0) { + log_warn(LD_FS, "Couldn't unlink old onion key file %s: %s", + fname, strerror(errno)); + } + } + tor_free(fname); + + fname = get_datadir_fname2("keys", "secret_onion_key_ntor.old"); + if (file_status(fname) == FN_FILE) { + if (tor_unlink(fname) != 0) { + log_warn(LD_FS, "Couldn't unlink old ntor onion key file %s: %s", + fname, strerror(errno)); + } + } + tor_free(fname); +} + /** Return the current secret onion key for the ntor handshake. Must only * be called from the main thread. */ static const curve25519_keypair_t * @@ -212,7 +257,11 @@ set_server_identity_key(crypto_pk_t *k) { crypto_pk_free(server_identitykey); server_identitykey = k; - crypto_pk_get_digest(server_identitykey, server_identitykey_digest); + if (crypto_pk_get_digest(server_identitykey, + server_identitykey_digest) < 0) { + log_err(LD_BUG, "Couldn't compute our own identity key digest."); + tor_assert(0); + } } /** Make sure that we have set up our identity keys to match or not match as @@ -683,6 +732,47 @@ v3_authority_check_key_expiry(void) last_warned = now; } +/** Get the lifetime of an onion key in days. This value is defined by the + * network consesus parameter "onion-key-rotation-days". Always returns a value + * between <b>MIN_ONION_KEY_LIFETIME_DAYS</b> and + * <b>MAX_ONION_KEY_LIFETIME_DAYS</b>. + */ +static int +get_onion_key_rotation_days_(void) +{ + return networkstatus_get_param(NULL, + "onion-key-rotation-days", + DEFAULT_ONION_KEY_LIFETIME_DAYS, + MIN_ONION_KEY_LIFETIME_DAYS, + MAX_ONION_KEY_LIFETIME_DAYS); +} + +/** Get the current lifetime of an onion key in seconds. This value is defined + * by the network consesus parameter "onion-key-rotation-days", but the value + * is converted to seconds. + */ +int +get_onion_key_lifetime(void) +{ + return get_onion_key_rotation_days_()*24*60*60; +} + +/** Get the grace period of an onion key in seconds. This value is defined by + * the network consesus parameter "onion-key-grace-period-days", but the value + * is converted to seconds. + */ +int +get_onion_key_grace_period(void) +{ + int grace_period; + grace_period = networkstatus_get_param(NULL, + "onion-key-grace-period-days", + DEFAULT_ONION_KEY_GRACE_PERIOD_DAYS, + MIN_ONION_KEY_GRACE_PERIOD_DAYS, + get_onion_key_rotation_days_()); + return grace_period*24*60*60; +} + /** Set up Tor's TLS contexts, based on our configuration and keys. Return 0 * on success, and -1 on failure. */ int @@ -693,12 +783,6 @@ router_initialize_tls_context(void) int lifetime = options->SSLKeyLifetime; if (public_server_mode(options)) flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER; - if (options->TLSECGroup) { - if (!strcasecmp(options->TLSECGroup, "P256")) - flags |= TOR_TLS_CTX_USE_ECDHE_P256; - else if (!strcasecmp(options->TLSECGroup, "P224")) - flags |= TOR_TLS_CTX_USE_ECDHE_P224; - } if (!lifetime) { /* we should guess a good ssl cert lifetime */ /* choose between 5 and 365 days, and round to the day */ @@ -849,7 +933,12 @@ init_keys(void) if (init_keys_common() < 0) return -1; /* Make sure DataDirectory exists, and is private. */ - if (check_private_dir(options->DataDirectory, CPD_CREATE, options->User)) { + cpd_check_t cpd_opts = CPD_CREATE; + if (options->DataDirectoryGroupReadable) + cpd_opts |= CPD_GROUP_READ; + if (check_private_dir(options->DataDirectory, cpd_opts, options->User)) { + log_err(LD_OR, "Can't create/check datadirectory %s", + options->DataDirectory); return -1; } /* Check the key directory. */ @@ -871,8 +960,12 @@ init_keys(void) } cert = get_my_v3_authority_cert(); if (cert) { - crypto_pk_get_digest(get_my_v3_authority_cert()->identity_key, - v3_digest); + if (crypto_pk_get_digest(get_my_v3_authority_cert()->identity_key, + v3_digest) < 0) { + log_err(LD_BUG, "Couldn't compute my v3 authority identity key " + "digest."); + return -1; + } v3_digest_set = 1; } } @@ -901,7 +994,8 @@ init_keys(void) } /* 1d. Load all ed25519 keys */ - if (load_ed_keys(options,now) < 0) + const int new_signing_key = load_ed_keys(options,now); + if (new_signing_key < 0) return -1; /* 2. Read onion key. Make it if none is found. */ @@ -923,7 +1017,7 @@ init_keys(void) /* We have no LastRotatedOnionKey set; either we just created the key * or it's a holdover from 0.1.2.4-alpha-dev or earlier. In either case, * start the clock ticking now so that we will eventually rotate it even - * if we don't stay up for a full MIN_ONION_KEY_LIFETIME. */ + * if we don't stay up for the full lifetime of an onion key. */ state->LastRotatedOnionKey = onionkey_set_at = now; or_state_mark_dirty(state, options->AvoidDiskWrites ? time(NULL)+3600 : 0); @@ -971,7 +1065,7 @@ init_keys(void) /* 3b. Get an ed25519 link certificate. Note that we need to do this * after we set up the TLS context */ - if (generate_ed_link_cert(options, now) < 0) { + if (generate_ed_link_cert(options, now, new_signing_key > 0) < 0) { log_err(LD_GENERAL,"Couldn't make link cert"); return -1; } @@ -1178,9 +1272,9 @@ router_should_be_directory_server(const or_options_t *options, int dir_port) 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. Directory traffic has a much - * larger effect on output than input so there is no reason to turn it + * but allow DirPort otherwise. Some relay operators set AccountingMax + * because 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); @@ -1312,8 +1406,15 @@ extend_info_from_router(const routerinfo_t *r) /* Make sure we don't need to check address reachability */ tor_assert_nonfatal(router_skip_or_reachability(get_options(), 0)); + const ed25519_public_key_t *ed_id_key; + if (r->cache_info.signing_key_cert) + ed_id_key = &r->cache_info.signing_key_cert->signing_key; + else + ed_id_key = NULL; + router_get_prim_orport(r, &ap); return extend_info_new(r->nickname, r->cache_info.identity_digest, + ed_id_key, r->onion_pkey, r->onion_curve25519_pkey, &ap.addr, ap.port); } @@ -1372,13 +1473,23 @@ consider_testing_reachability(int test_or, int test_dir) !connection_get_by_type_addr_port_purpose( CONN_TYPE_DIR, &addr, me->dir_port, DIR_PURPOSE_FETCH_SERVERDESC)) { + tor_addr_port_t my_orport, my_dirport; + memcpy(&my_orport.addr, &addr, sizeof(addr)); + memcpy(&my_dirport.addr, &addr, sizeof(addr)); + my_orport.port = me->or_port; + my_dirport.port = me->dir_port; /* ask myself, via tor, for my server descriptor. */ - directory_initiate_command(&addr, me->or_port, - &addr, me->dir_port, - me->cache_info.identity_digest, - DIR_PURPOSE_FETCH_SERVERDESC, - ROUTER_PURPOSE_GENERAL, - DIRIND_ANON_DIRPORT, "authority.z", NULL, 0, 0); + directory_request_t *req = + directory_request_new(DIR_PURPOSE_FETCH_SERVERDESC); + directory_request_set_or_addr_port(req, &my_orport); + directory_request_set_dir_addr_port(req, &my_dirport); + directory_request_set_directory_id_digest(req, + me->cache_info.identity_digest); + // ask via an anon circuit, connecting to our dirport. + directory_request_set_indirection(req, DIRIND_ANON_DIRPORT); + directory_request_set_resource(req, "authority.z"); + directory_initiate_request(req); + directory_request_free(req); } } @@ -1555,8 +1666,7 @@ MOCK_IMPL(int, server_mode,(const or_options_t *options)) { if (options->ClientOnly) return 0; - /* XXXX I believe we can kill off ORListenAddress here.*/ - return (options->ORPort_set || options->ORListenAddress); + return (options->ORPort_set); } /** Return true iff we are trying to be a non-bridge server. @@ -2180,17 +2290,15 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) } if (options->MyFamily && ! options->BridgeRelay) { - smartlist_t *family; if (!warned_nonexistent_family) warned_nonexistent_family = smartlist_new(); - family = smartlist_new(); ri->declared_family = smartlist_new(); - smartlist_split_string(family, options->MyFamily, ",", - SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK|SPLIT_STRIP_SPACE, 0); - SMARTLIST_FOREACH_BEGIN(family, char *, name) { + config_line_t *family; + for (family = options->MyFamily; family; family = family->next) { + char *name = family->value; const node_t *member; if (!strcasecmp(name, options->Nickname)) - goto skip; /* Don't list ourself, that's redundant */ + continue; /* Don't list ourself, that's redundant */ else member = node_get_by_nickname(name, 1); if (!member) { @@ -2206,11 +2314,10 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) log_warn(LD_CONFIG, "There is a router named \"%s\" in my " "declared family, but that isn't a legal nickname. " "Skipping it.", escaped(name)); - smartlist_add(warned_nonexistent_family, tor_strdup(name)); + smartlist_add_strdup(warned_nonexistent_family, name); } if (is_legal) { - smartlist_add(ri->declared_family, name); - name = NULL; + smartlist_add_strdup(ri->declared_family, name); } } else if (router_digest_is_me(member->identity)) { /* Don't list ourself in our own family; that's redundant */ @@ -2224,15 +2331,11 @@ router_build_fresh_descriptor(routerinfo_t **r, extrainfo_t **e) if (smartlist_contains_string(warned_nonexistent_family, name)) smartlist_string_remove(warned_nonexistent_family, name); } - skip: - tor_free(name); - } SMARTLIST_FOREACH_END(name); + } /* remove duplicates from the list */ smartlist_sort_strings(ri->declared_family); smartlist_uniq_strings(ri->declared_family); - - smartlist_free(family); } /* Now generate the extrainfo. */ @@ -2748,7 +2851,7 @@ router_dump_router_to_string(routerinfo_t *router, make_ntor_onion_key_crosscert(ntor_keypair, &router->cache_info.signing_key_cert->signing_key, router->cache_info.published_on, - MIN_ONION_KEY_LIFETIME, &sign); + get_onion_key_lifetime(), &sign); if (!cert) { log_warn(LD_BUG,"make_ntor_onion_key_crosscert failed!"); goto err; @@ -2834,7 +2937,7 @@ router_dump_router_to_string(routerinfo_t *router, "onion-key\n%s" "signing-key\n%s" "%s%s" - "%s%s%s%s", + "%s%s%s", router->nickname, address, router->or_port, @@ -2857,8 +2960,7 @@ router_dump_router_to_string(routerinfo_t *router, ntor_cc_line ? ntor_cc_line : "", family_line, we_are_hibernating() ? "hibernating 1\n" : "", - "hidden-service-dir\n", - options->AllowSingleHopExits ? "allow-single-hop-exits\n" : ""); + "hidden-service-dir\n"); if (options->ContactInfo && strlen(options->ContactInfo)) { const char *ci = options->ContactInfo; @@ -2890,7 +2992,7 @@ router_dump_router_to_string(routerinfo_t *router, /* Write the exit policy to the end of 's'. */ if (!router->exit_policy || !smartlist_len(router->exit_policy)) { - smartlist_add(chunks, tor_strdup("reject *:*\n")); + smartlist_add_strdup(chunks, "reject *:*\n"); } else if (router->exit_policy) { char *exit_policy = router_dump_exit_policy_to_string(router,1,0); @@ -2912,12 +3014,12 @@ router_dump_router_to_string(routerinfo_t *router, if (decide_to_advertise_begindir(options, router->supports_tunnelled_dir_requests)) { - smartlist_add(chunks, tor_strdup("tunnelled-dir-server\n")); + smartlist_add_strdup(chunks, "tunnelled-dir-server\n"); } /* Sign the descriptor with Ed25519 */ if (emit_ed_sigs) { - smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); + smartlist_add_strdup(chunks, "router-sig-ed25519 "); crypto_digest_smartlist_prefix(digest, DIGEST256_LEN, ED_DESC_SIGNATURE_PREFIX, chunks, "", DIGEST_SHA256); @@ -2933,7 +3035,7 @@ router_dump_router_to_string(routerinfo_t *router, } /* Sign the descriptor with RSA */ - smartlist_add(chunks, tor_strdup("router-signature\n")); + smartlist_add_strdup(chunks, "router-signature\n"); crypto_digest_smartlist(digest, DIGEST_LEN, chunks, "", DIGEST_SHA1); @@ -2948,7 +3050,7 @@ router_dump_router_to_string(routerinfo_t *router, } /* include a last '\n' */ - smartlist_add(chunks, tor_strdup("\n")); + smartlist_add_strdup(chunks, "\n"); output = smartlist_join_strings(chunks, "", 0, NULL); @@ -3196,6 +3298,12 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, } } + if (options->PaddingStatistics) { + contents = rep_hist_get_padding_count_lines(); + if (contents) + smartlist_add(chunks, contents); + } + /* Add information about the pluggable transports we support. */ if (options->ServerTransportPlugin) { char *pluggable_transports = pt_get_extra_info_descriptor_string(); @@ -3206,13 +3314,13 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, if (should_record_bridge_info(options) && write_stats_to_extrainfo) { const char *bridge_stats = geoip_get_bridge_stats_extrainfo(now); if (bridge_stats) { - smartlist_add(chunks, tor_strdup(bridge_stats)); + smartlist_add_strdup(chunks, bridge_stats); } } if (emit_ed_sigs) { char sha256_digest[DIGEST256_LEN]; - smartlist_add(chunks, tor_strdup("router-sig-ed25519 ")); + smartlist_add_strdup(chunks, "router-sig-ed25519 "); crypto_digest_smartlist_prefix(sha256_digest, DIGEST256_LEN, ED_DESC_SIGNATURE_PREFIX, chunks, "", DIGEST_SHA256); @@ -3227,7 +3335,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, smartlist_add_asprintf(chunks, "%s\n", buf); } - smartlist_add(chunks, tor_strdup("router-signature\n")); + smartlist_add_strdup(chunks, "router-signature\n"); s = smartlist_join_strings(chunks, "", 0, NULL); while (strlen(s) > MAX_EXTRAINFO_UPLOAD_SIZE - DIROBJ_MAX_SIG_LEN) { @@ -3262,7 +3370,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo, "descriptor."); goto err; } - smartlist_add(chunks, tor_strdup(sig)); + smartlist_add_strdup(chunks, sig); tor_free(s); s = smartlist_join_strings(chunks, "", 0, NULL); |