diff options
-rw-r--r-- | changes/8712 | 6 | ||||
-rw-r--r-- | src/or/circuituse.c | 2 | ||||
-rw-r--r-- | src/or/dirserv.c | 5 | ||||
-rw-r--r-- | src/or/rendcommon.c | 2 | ||||
-rw-r--r-- | src/or/rendservice.c | 49 | ||||
-rw-r--r-- | src/or/rendservice.h | 9 | ||||
-rw-r--r-- | src/or/routerkeys.c | 59 | ||||
-rw-r--r-- | src/or/torcert.c | 9 |
8 files changed, 73 insertions, 68 deletions
diff --git a/changes/8712 b/changes/8712 new file mode 100644 index 0000000000..c7423e84c8 --- /dev/null +++ b/changes/8712 @@ -0,0 +1,6 @@ + o Minor features (directory authorities): + - Directory authorities no longer vote against the "Fast", + "Stable", and "HSDir" flags just because they were going to vote + against "Running": if the consensus turns out to be that the + router was running, then the authority's vote should count. + Patch from Peter Retzlaff; closes issue 8712.
\ No newline at end of file diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 572a4f3ed8..05e67361b8 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -1128,7 +1128,7 @@ circuit_build_needed_circs(time_t now) /* make sure any hidden services have enough intro points * HS intro point streams only require an internal circuit */ if (router_have_consensus_path() != CONSENSUS_PATH_UNKNOWN) - rend_services_introduce(); + rend_consider_services_intro_points(); circuit_expire_old_circs_as_needed(now); diff --git a/src/or/dirserv.c b/src/or/dirserv.c index ed38ba2259..71be626fff 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -1372,8 +1372,7 @@ dirserv_thinks_router_is_hs_dir(const routerinfo_t *router, return (router->wants_to_be_hs_dir && router->dir_port && node->is_stable && - uptime >= get_options()->MinUptimeHidServDirectoryV2 && - router_is_active(router, node, now)); + uptime >= get_options()->MinUptimeHidServDirectoryV2); } /** Don't consider routers with less bandwidth than this when computing @@ -2143,10 +2142,8 @@ set_routerstatus_from_routerinfo(routerstatus_t *rs, /* Already set by compute_performance_thresholds. */ rs->is_exit = node->is_exit; rs->is_stable = node->is_stable = - router_is_active(ri, node, now) && !dirserv_thinks_router_is_unreliable(now, ri, 1, 0); rs->is_fast = node->is_fast = - router_is_active(ri, node, now) && !dirserv_thinks_router_is_unreliable(now, ri, 0, 1); rs->is_flagged_running = node->is_running; /* computed above */ diff --git a/src/or/rendcommon.c b/src/or/rendcommon.c index 411a87c004..22599e9830 100644 --- a/src/or/rendcommon.c +++ b/src/or/rendcommon.c @@ -787,7 +787,7 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint, break; case RELAY_COMMAND_INTRODUCE2: if (origin_circ) - r = rend_service_introduce(origin_circ,payload,length); + r = rend_service_receive_introduction(origin_circ,payload,length); break; case RELAY_COMMAND_INTRODUCE_ACK: if (origin_circ) diff --git a/src/or/rendservice.c b/src/or/rendservice.c index f4fb860078..74e8a8d5ec 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1437,8 +1437,9 @@ rend_check_authorization(rend_service_t *service, * rendezvous point. */ int -rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, - size_t request_len) +rend_service_receive_introduction(origin_circuit_t *circuit, + const uint8_t *request, + size_t request_len) { /* Global status stuff */ int status = 0, result; @@ -1537,17 +1538,6 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, tor_free(err_msg); } - stage_descr = "early validation"; - /* Early validation of pk/ciphertext part */ - result = rend_service_validate_intro_early(parsed_req, &err_msg); - if (result < 0) { - goto log_error; - } else if (err_msg) { - log_info(LD_REND, "%s on circ %u.", err_msg, - (unsigned)circuit->base_.n_circ_id); - tor_free(err_msg); - } - /* make sure service replay caches are present */ if (!service->accepted_intro_dh_parts) { service->accepted_intro_dh_parts = @@ -2514,37 +2504,6 @@ rend_service_parse_intro_plaintext( return status; } -/** Do validity checks on a parsed intro cell before decryption; some of - * these are not done in rend_service_begin_parse_intro() itself because - * they depend on a lot of other state and would make it hard to unit test. - * Returns >= 0 if successful or < 0 if the intro cell is invalid, and - * optionally writes out an error message for logging. If an err_msg - * pointer is provided, it is the caller's responsibility to free any - * provided message. - */ - -int -rend_service_validate_intro_early(const rend_intro_cell_t *intro, - char **err_msg_out) -{ - int status = 0; - - if (!intro) { - if (err_msg_out) - *err_msg_out = - tor_strdup("NULL intro cell passed to " - "rend_service_validate_intro_early()"); - - status = -1; - goto err; - } - - /* TODO */ - - err: - return status; -} - /** Do validity checks on a parsed intro cell after decryption; some of * these are not done in rend_service_parse_intro_plaintext() itself because * they depend on a lot of other state and would make it hard to unit test. @@ -3523,7 +3482,7 @@ rend_service_desc_has_uploaded(const rend_data_t *rend_data) * This is called once a second by the main loop. */ void -rend_services_introduce(void) +rend_consider_services_intro_points(void) { int i; time_t now; diff --git a/src/or/rendservice.h b/src/or/rendservice.h index 35a0bb25e6..a16a99cf88 100644 --- a/src/or/rendservice.h +++ b/src/or/rendservice.h @@ -70,7 +70,7 @@ int rend_config_services(const or_options_t *options, int validate_only); int rend_service_load_all_keys(void); void rend_services_add_filenames_to_lists(smartlist_t *open_lst, smartlist_t *stat_lst); -void rend_services_introduce(void); +void rend_consider_services_intro_points(void); void rend_consider_services_upload(time_t now); void rend_hsdir_routers_changed(void); void rend_consider_descriptor_republication(void); @@ -80,8 +80,9 @@ int rend_service_intro_established(origin_circuit_t *circuit, const uint8_t *request, size_t request_len); void rend_service_rendezvous_has_opened(origin_circuit_t *circuit); -int rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, - size_t request_len); +int rend_service_receive_introduction(origin_circuit_t *circuit, + const uint8_t *request, + size_t request_len); int rend_service_decrypt_intro(rend_intro_cell_t *request, crypto_pk_t *key, char **err_msg_out); @@ -92,8 +93,6 @@ rend_intro_cell_t * rend_service_begin_parse_intro(const uint8_t *request, char **err_msg_out); int rend_service_parse_intro_plaintext(rend_intro_cell_t *intro, char **err_msg_out); -int rend_service_validate_intro_early(const rend_intro_cell_t *intro, - char **err_msg_out); int rend_service_validate_intro_late(const rend_intro_cell_t *intro, char **err_msg_out); void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc); diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index c9afad9b6b..955cb9ce23 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -191,10 +191,12 @@ ed_key_init_from_file(const char *fname, uint32_t flags, char *encrypted_secret_fname = NULL; char *public_fname = NULL; char *cert_fname = NULL; + const char *loaded_secret_fname = NULL; int created_pk = 0, created_sk = 0, created_cert = 0; const int try_to_load = ! (flags & INIT_ED_KEY_REPLACE); - const int encrypt_key = (flags & INIT_ED_KEY_TRY_ENCRYPTED); - const int norepair = (flags & INIT_ED_KEY_NO_REPAIR); + const int encrypt_key = !! (flags & INIT_ED_KEY_TRY_ENCRYPTED); + const int norepair = !! (flags & INIT_ED_KEY_NO_REPAIR); + const int split = !! (flags & INIT_ED_KEY_SPLIT); /* we don't support setting both of these flags at once. */ tor_assert((flags & (INIT_ED_KEY_NO_REPAIR|INIT_ED_KEY_NEEDCERT)) != @@ -220,6 +222,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags, &got_tag, secret_fname); if (rv == 0) { have_secret = 1; + loaded_secret_fname = secret_fname; } else { if (errno != ENOENT && norepair) { tor_log(severity, LD_OR, "Unable to read %s: %s", secret_fname, @@ -236,6 +239,7 @@ ed_key_init_from_file(const char *fname, uint32_t flags, if (r > 0) { have_secret = 1; got_tag = tor_strdup(tag); + loaded_secret_fname = encrypted_secret_fname; } else if (errno != ENOENT && norepair) { tor_log(severity, LD_OR, "Unable to read %s: %s", encrypted_secret_fname, strerror(errno)); @@ -245,21 +249,24 @@ ed_key_init_from_file(const char *fname, uint32_t flags, if (have_secret) { if (strcmp(got_tag, tag)) { - tor_log(severity, LD_OR, "%s has wrong tag", secret_fname); + tor_log(severity, LD_OR, "%s has wrong tag", loaded_secret_fname); goto err; } /* Derive the public key */ if (ed25519_public_key_generate(&keypair->pubkey, &keypair->seckey)<0) { - tor_log(severity, LD_OR, "%s can't produce a public key", secret_fname); + tor_log(severity, LD_OR, "%s can't produce a public key", + loaded_secret_fname); goto err; } } - /* If it's absent and that's okay, try to read the pubkey. */ + /* If it's absent and that's okay, or if we do split keys here, try to re + * the pubkey. */ int found_public = 0; - if (!have_secret && try_to_load) { + if ((!have_secret && try_to_load) || (have_secret && split)) { + ed25519_public_key_t pubkey_tmp; tor_free(got_tag); - found_public = ed25519_pubkey_read_from_file(&keypair->pubkey, + found_public = ed25519_pubkey_read_from_file(&pubkey_tmp, &got_tag, public_fname) == 0; if (!found_public && errno != ENOENT && norepair) { tor_log(severity, LD_OR, "Unable to read %s: %s", public_fname, @@ -270,6 +277,20 @@ ed_key_init_from_file(const char *fname, uint32_t flags, tor_log(severity, LD_OR, "%s has wrong tag", public_fname); goto err; } + if (found_public) { + if (have_secret) { + /* If we have a secret key and we're reloading the public key, + * the key must match! */ + if (! ed25519_pubkey_eq(&keypair->pubkey, &pubkey_tmp)) { + tor_log(severity, LD_OR, "%s does not match %s!", + public_fname, loaded_secret_fname); + goto err; + } + } else { + tor_assert(split); + memcpy(&keypair->pubkey, &pubkey_tmp, sizeof(pubkey_tmp)); + } + } } /* If the secret key is absent and it's not allowed to be, fail. */ @@ -282,7 +303,6 @@ ed_key_init_from_file(const char *fname, uint32_t flags, /* if it's absent, make a new keypair and save it. */ if (!have_secret && !found_public) { - const int split = !! (flags & INIT_ED_KEY_SPLIT); tor_free(keypair); keypair = ed_key_new(signing_key, flags, now, lifetime, cert_type, &cert); @@ -336,6 +356,10 @@ ed_key_init_from_file(const char *fname, uint32_t flags, (signing_key || cert->cert_expired)) { tor_log(severity, LD_OR, "Can't check certificate"); bad_cert = 1; + } else if (signing_key && cert->signing_key_included && + ! ed25519_pubkey_eq(&signing_key->pubkey, &cert->signing_key)) { + tor_log(severity, LD_OR, "Certificate signed by unexpectd key!"); + bad_cert = 1; } if (bad_cert) { @@ -553,9 +577,24 @@ load_ed_keys(const or_options_t *options, time_t now) sign_signing_key_with_id = id; } + if (master_identity_key && + !ed25519_pubkey_eq(&id->pubkey, &master_identity_key->pubkey)) { + FAIL("Identity key on disk does not match key we loaded earlier!"); + } + if (need_new_signing_key && NULL == sign_signing_key_with_id) FAIL("Can't load master key make a new signing key."); + if (sign_cert) { + if (! sign_cert->signing_key_included) + FAIL("Loaded a signing cert with no key included!"); + if (! ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey)) + FAIL("The signing cert we have was not signed with the master key " + "we loaded!"); + if (tor_cert_checksig(sign_cert, &id->pubkey, 0) < 0) + FAIL("The signing cert we loaded was not signed correctly!"); + } + if (want_new_signing_key && sign_signing_key_with_id) { uint32_t flags = (INIT_ED_KEY_CREATE| INIT_ED_KEY_REPLACE| @@ -573,6 +612,10 @@ load_ed_keys(const or_options_t *options, time_t now) if (!sign) FAIL("Missing signing key"); use_signing = sign; + + tor_assert(sign_cert->signing_key_included); + tor_assert(ed25519_pubkey_eq(&sign_cert->signing_key, &id->pubkey)); + tor_assert(ed25519_pubkey_eq(&sign_cert->signed_key, &sign->pubkey)); } else if (want_new_signing_key) { static ratelim_t missing_master = RATELIM_INIT(3600); log_fn_ratelim(&missing_master, LOG_WARN, LD_OR, diff --git a/src/or/torcert.c b/src/or/torcert.c index f028910a70..596cd2be31 100644 --- a/src/or/torcert.c +++ b/src/or/torcert.c @@ -181,9 +181,10 @@ tor_cert_get_checkable_sig(ed25519_checkable_t *checkable_out, return 0; } -/** Validates the signature on <b>cert</b> with <b>pubkey</b> relative to - * the current time <b>now</b>. Return 0 on success, -1 on failure. - * Sets flags in <b>cert</b> as appropriate. +/** Validates the signature on <b>cert</b> with <b>pubkey</b> relative to the + * current time <b>now</b>. (If <b>now</b> is 0, do not check the expiration + * time.) Return 0 on success, -1 on failure. Sets flags in <b>cert</b> as + * appropriate. */ int tor_cert_checksig(tor_cert_t *cert, @@ -192,7 +193,7 @@ tor_cert_checksig(tor_cert_t *cert, ed25519_checkable_t checkable; int okay; - if (now > cert->valid_until) { + if (now && now > cert->valid_until) { cert->cert_expired = 1; return -1; } |