Merge branch 'bug3000-022-part2-squashed' into maint-0.2.2

This commit is contained in:
Nick Mathewson 2011-04-28 18:13:17 -04:00
commit 30003e4318
5 changed files with 90 additions and 44 deletions

View File

@ -2,6 +2,18 @@
- Forget all hidden service descriptors cached as a client when - Forget all hidden service descriptors cached as a client when
processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on
0.0.6. 0.0.6.
o Major bugfixes:
- When we find that we have extended a hidden service's introduction
circuit to a relay which isn't listed as an introduction point in
the HS descriptor we currently have for the service, we now retry
one of the introduction points in the current HS descriptor.
Previously we would just give up. Bugfix on 0.2.0.10-alpha; fixes
bugs 1024 and 1930.
o Minor bugfixes:
- Don't allow v0 hidden service authorities to act as clients.
Required by fix for bug 3000.
- Ignore SIGNAL NEWNYM commands on relay-only Tor instances.
Required by fix for bug 3000.
o Code simplifications and refactoring: o Code simplifications and refactoring:
- Allow rend_client_send_introduction to fail without closing the - Allow rend_client_send_introduction to fail without closing the
AP connection permanently. AP connection permanently.

View File

@ -3078,6 +3078,10 @@ options_validate(or_options_t *old_options, or_options_t *options,
REJECT("FetchDirInfoExtraEarly requires that you also set " REJECT("FetchDirInfoExtraEarly requires that you also set "
"FetchDirInfoEarly"); "FetchDirInfoEarly");
if (options->HSAuthoritativeDir && proxy_mode(options))
REJECT("Running as authoritative v0 HS directory, but also configured "
"as a client.");
if (options->ConnLimit <= 0) { if (options->ConnLimit <= 0) {
tor_asprintf(msg, tor_asprintf(msg,
"ConnLimit must be greater than 0, but was set to %d", "ConnLimit must be greater than 0, but was set to %d",

View File

@ -842,6 +842,13 @@ run_connection_housekeeping(int i, time_t now)
static void static void
signewnym_impl(time_t now) signewnym_impl(time_t now)
{ {
or_options_t *options = get_options();
if (!proxy_mode(options)) {
log_info(LD_CONTROL, "Ignoring SIGNAL NEWNYM because client functionality "
"is disabled.");
return;
}
circuit_expire_all_dirty_circs(); circuit_expire_all_dirty_circs();
addressmap_clear_transient(); addressmap_clear_transient();
rend_cache_purge(); rend_cache_purge();

View File

@ -66,6 +66,50 @@ rend_client_send_establish_rendezvous(origin_circuit_t *circ)
return 0; return 0;
} }
/** Extend the introduction circuit <b>circ</b> to another valid
* introduction point for the hidden service it is trying to connect
* to, or mark it and launch a new circuit if we can't extend it.
* Return 0 on success. Return -1 and mark the introduction
* circuit on failure.
*
* On failure, the caller is responsible for marking the associated
* rendezvous circuit for close. */
static int
rend_client_reextend_intro_circuit(origin_circuit_t *circ)
{
extend_info_t *extend_info;
int result;
extend_info = rend_client_get_random_intro(circ->rend_data);
if (!extend_info) {
log_warn(LD_REND,
"No usable introduction points left for %s. Closing.",
safe_str_client(circ->rend_data->onion_address));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
if (circ->remaining_relay_early_cells) {
log_info(LD_REND,
"Re-extending circ %d, this time to %s.",
circ->_base.n_circ_id, extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
"Building a new introduction circuit, this time to %s.",
extend_info->nickname);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
extend_info,
CIRCLAUNCH_IS_INTERNAL)) {
log_warn(LD_REND, "Building introduction circuit failed.");
result = -1;
} else {
result = 0;
}
}
extend_info_free(extend_info);
return result;
}
/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell /** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell
* down introcirc if possible. * down introcirc if possible.
*/ */
@ -120,11 +164,18 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
} }
}); });
if (!intro_key) { if (!intro_key) {
log_info(LD_REND, "Our introduction point knowledge changed in " log_info(LD_REND, "Could not find intro key for %s at %s; we "
"mid-connect! Could not find intro key; we only have a " "have a v2 rend desc with %d intro points. "
"v2 rend desc with %d intro points. Giving up.", "Trying a different intro point...",
safe_str_client(introcirc->rend_data->onion_address),
introcirc->build_state->chosen_exit->nickname,
smartlist_len(entry->parsed->intro_nodes)); smartlist_len(entry->parsed->intro_nodes));
if (rend_client_reextend_intro_circuit(introcirc)) {
goto perm_err; goto perm_err;
} else {
return -1;
}
} }
if (crypto_pk_get_digest(intro_key, payload)<0) { if (crypto_pk_get_digest(intro_key, payload)<0) {
log_warn(LD_BUG, "Internal error: couldn't hash public key."); log_warn(LD_BUG, "Internal error: couldn't hash public key.");
@ -227,6 +278,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
return 0; return 0;
perm_err: perm_err:
if (!introcirc->_base.marked_for_close)
circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL); circuit_mark_for_close(TO_CIRCUIT(introcirc), END_CIRC_REASON_INTERNAL);
circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL); circuit_mark_for_close(TO_CIRCUIT(rendcirc), END_CIRC_REASON_INTERNAL);
return -2; return -2;
@ -290,45 +342,16 @@ rend_client_introduction_acked(origin_circuit_t *circ,
* points. If any remain, extend to a new one and try again. * points. If any remain, extend to a new one and try again.
* If none remain, refetch the service descriptor. * If none remain, refetch the service descriptor.
*/ */
log_info(LD_REND, "Got nack for %s from %s...",
safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname);
if (rend_client_remove_intro_point(circ->build_state->chosen_exit, if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
circ->rend_data) > 0) { circ->rend_data) > 0) {
/* There are introduction points left. Re-extend the circuit to /* There are introduction points left. Re-extend the circuit to
* another intro point and try again. */ * another intro point and try again. */
extend_info_t *extend_info; int result = rend_client_reextend_intro_circuit(circ);
int result; /* XXXX If that call failed, should we close the rend circuit,
extend_info = rend_client_get_random_intro(circ->rend_data); * too? */
if (!extend_info) {
log_warn(LD_REND, "No introduction points left for %s. Closing.",
escaped_safe_str_client(circ->rend_data->onion_address));
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
return -1;
}
if (circ->remaining_relay_early_cells) {
log_info(LD_REND,
"Got nack for %s from %s. Re-extending circ %d, "
"this time to %s.",
escaped_safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname,
circ->_base.n_circ_id, extend_info->nickname);
result = circuit_extend_to_new_exit(circ, extend_info);
} else {
log_info(LD_REND,
"Got nack for %s from %s. Building a new introduction "
"circuit, this time to %s.",
escaped_safe_str_client(circ->rend_data->onion_address),
circ->build_state->chosen_exit->nickname,
extend_info->nickname);
circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_FINISHED);
if (!circuit_launch_by_extend_info(CIRCUIT_PURPOSE_C_INTRODUCING,
extend_info,
CIRCLAUNCH_IS_INTERNAL)) {
log_warn(LD_REND, "Building introduction circuit failed.");
result = -1;
} else {
result = 0;
}
}
extend_info_free(extend_info);
return result; return result;
} }
} }

View File

@ -1107,10 +1107,10 @@ set_server_advertised(int s)
int int
proxy_mode(or_options_t *options) proxy_mode(or_options_t *options)
{ {
return (options->SocksPort != 0 || options->SocksListenAddress || return (options->SocksPort != 0 ||
options->TransPort != 0 || options->TransListenAddress || options->TransPort != 0 ||
options->NATDPort != 0 || options->NATDListenAddress || options->NATDPort != 0 ||
options->DNSPort != 0 || options->DNSListenAddress); options->DNSPort != 0);
} }
/** Decide if we're a publishable server. We are a publishable server if: /** Decide if we're a publishable server. We are a publishable server if: