Merge branch 'maint-0.2.2' into release-0.2.2

This commit is contained in:
Roger Dingledine 2011-06-03 15:25:54 -04:00
commit d6d9df241c
22 changed files with 193 additions and 58 deletions

8
changes/bug2355 Normal file
View File

@ -0,0 +1,8 @@
o Major features:
- If "UseBridges 1" is set and no bridges are configured, Tor will
now refuse to build any circuits until some bridges are set.
If "UseBridges auto" is set, Tor will use bridges if they are
configured and we are not running as a server, but otherwise
will make circuits as usual. The new default is "auto". Patch
by anonym.

10
changes/bug2748 Normal file
View File

@ -0,0 +1,10 @@
o Minor bugfixes
- Remove dead code from rend_cache_lookup_v2_desc_as_dir. Fixes
part of bug 2748; bugfix on 0.2.0.10-alpha.
- Log malformed requests for rendezvous descriptors as protocol
warnings, not warnings. Also, use a more informative log
message in case someone sees it at log level warning without
prior info-level messages. Fixes the other part of bug 2748;
bugfix on 0.2.0.10-alpha.

13
changes/bug3309 Normal file
View File

@ -0,0 +1,13 @@
o Minor bugfixes:
- Clear the table recording the time of the last request for each
hidden service descriptor from each HS directory on SIGNAL
NEWNYM. Previously, we would clear our HS descriptor cache on
SIGNAL NEWNYM, but if we had previously retrieved a descriptor
(or tried to) from every directory responsible for it, we would
refuse to fetch it again for up to 15 minutes. Bugfix on
0.2.2.25-alpha; fixes bug 3309.
o Minor features:
- Log (at info level) when purging pieces of hidden-service-client
state on SIGNAL NEWNYM.

7
changes/bug3318 Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes:
- Fix a log message that said "bits" while displaying a value in
bytes. Found by wanoskarnet. Fixes bug 3318; bugfix on
0.2.0.1-alpha.
- When checking for 1024-bit keys, check for 1024 bits, not 128
bytes. This allows Tor to correctly discard keys of length
1017 through 1023. Bugfix on 0.0.9pre5.

7
changes/bug3321 Normal file
View File

@ -0,0 +1,7 @@
o Minor bugfixes:
- In bug 2511 we fixed a case where you could use an unconfigured
bridge if you had configured it as a bridge the last time you ran
Tor. Now fix another edge case: if you had configured it as a bridge
but then switched to a different bridge via the controller, you
would still be willing to use the old one. Bugfix on 0.2.0.1-alpha;
fixes bug 3321.

View File

@ -708,10 +708,14 @@ The following options are useful only for clients (that is, if
from the configured bridge authorities when feasible. It will fall back to
a direct request if the authority responds with a 404. (Default: 0)
**UseBridges** **0**|**1**::
When set, Tor will fetch descriptors for each bridge listed in the "Bridge"
**UseBridges** **0**|**1**|**auto**::
Make Tor fetch descriptors for each bridge listed in the "Bridge"
config lines, and use these relays as both entry guards and directory
guards. (Default: 0)
guards. If the option is 1, bridges must be used and if no bridges are
configured Tor will not make any connections until a bridge is configured;
if it's "auto", Tor will use bridges if any are configured, otherwise it
will connect directly to the Tor network; if it's 0, bridges are not used
at all. (Defaults to auto)
**UseEntryGuards** **0**|**1**::
If this option is set to 1, we pick a few long-term entry servers, and try

View File

@ -777,6 +777,17 @@ crypto_pk_keysize(crypto_pk_env_t *env)
return (size_t) RSA_size(env->key);
}
/** Return the size of the public key modulus of <b>env</b>, in bits. */
int
crypto_pk_num_bits(crypto_pk_env_t *env)
{
tor_assert(env);
tor_assert(env->key);
tor_assert(env->key->n);
return BN_num_bits(env->key->n);
}
/** Increase the reference count of <b>env</b>, and return it.
*/
crypto_pk_env_t *

View File

@ -119,6 +119,7 @@ int crypto_pk_write_private_key_to_filename(crypto_pk_env_t *env,
int crypto_pk_check_key(crypto_pk_env_t *env);
int crypto_pk_cmp_keys(crypto_pk_env_t *a, crypto_pk_env_t *b);
size_t crypto_pk_keysize(crypto_pk_env_t *env);
int crypto_pk_num_bits(crypto_pk_env_t *env);
crypto_pk_env_t *crypto_pk_dup_key(crypto_pk_env_t *orig);
crypto_pk_env_t *crypto_pk_copy_full(crypto_pk_env_t *orig);
int crypto_pk_key_is_private(const crypto_pk_env_t *key);

View File

@ -252,7 +252,7 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
if (!GetExitCodeProcess(procmon->hproc, &exit_code)) {
char *errmsg = format_win32_error(GetLastError());
log_warn(procmon->log_domain, "Error \"%s\" occurred while polling "
"handle for monitored process %d; assuming it's dead."
"handle for monitored process %d; assuming it's dead.",
errmsg, procmon->pid);
tor_free(errmsg);
its_dead_jim = 1;
@ -287,12 +287,12 @@ tor_process_monitor_poll_cb(evutil_socket_t unused1, short unused2,
if (!its_dead_jim)
log_info(procmon->log_domain, "Failed to open handle to monitored "
"process %d, and error code %d (%s) is not 'invalid "
"process %d, and error code %lu (%s) is not 'invalid "
"parameter' -- assuming the process is still alive.",
procmon->pid,
err_code, err_msg);
err_code, errmsg);
tor_free(err_msg);
tor_free(errmsg);
}
}
#else

View File

@ -3383,6 +3383,8 @@ entry_guard_set_status(entry_guard_t *e, routerinfo_t *ri,
*reason = "down";
else if (options->UseBridges && ri->purpose != ROUTER_PURPOSE_BRIDGE)
*reason = "not a bridge";
else if (options->UseBridges && !routerinfo_is_a_configured_bridge(ri))
*reason = "not a configured bridge";
else if (!options->UseBridges && !ri->is_possible_guard &&
!routerset_contains_router(options->EntryNodes,ri))
*reason = "not recommended as a guard";
@ -3467,11 +3469,16 @@ entry_is_live(entry_guard_t *e, int need_uptime, int need_capacity,
*msg = "no descriptor";
return NULL;
}
if (get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_BRIDGE) {
*msg = "not a bridge";
return NULL;
}
if (!get_options()->UseBridges && r->purpose != ROUTER_PURPOSE_GENERAL) {
if (options->UseBridges) {
if (r->purpose != ROUTER_PURPOSE_BRIDGE) {
*msg = "not a bridge";
return NULL;
}
if (!routerinfo_is_a_configured_bridge(r)) {
*msg = "not a configured bridge";
return NULL;
}
} else if (r->purpose != ROUTER_PURPOSE_GENERAL) {
*msg = "not general-purpose";
return NULL;
}

View File

@ -376,7 +376,7 @@ static config_var_t _option_vars[] = {
V(TransPort, PORT, "0"),
V(TunnelDirConns, BOOL, "1"),
V(UpdateBridgesFromAuthority, BOOL, "0"),
V(UseBridges, BOOL, "0"),
VAR("UseBridges", STRING, UseBridges_, "auto"),
V(UseEntryGuards, BOOL, "1"),
V(User, STRING, NULL),
VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir, "0"),
@ -1180,18 +1180,6 @@ options_act(or_options_t *old_options)
return -1;
}
/* We want to reinit keys as needed before we do much of anything else:
keys are important, and other things can depend on them. */
if (running_tor &&
(transition_affects_workers ||
(options->V3AuthoritativeDir && (!old_options ||
!old_options->V3AuthoritativeDir)))) {
if (init_keys() < 0) {
log_warn(LD_BUG,"Error initializing keys; exiting");
return -1;
}
}
if (consider_adding_dir_authorities(options, old_options) < 0)
return -1;
@ -1237,6 +1225,17 @@ options_act(or_options_t *old_options)
finish_daemon(options->DataDirectory);
}
/* We want to reinit keys as needed before we do much of anything else:
keys are important, and other things can depend on them. */
if (transition_affects_workers ||
(options->V3AuthoritativeDir && (!old_options ||
!old_options->V3AuthoritativeDir))) {
if (init_keys() < 0) {
log_warn(LD_BUG,"Error initializing keys; exiting");
return -1;
}
}
/* Write our PID to the PID file. If we do not have write permissions we
* will log a warning */
if (options->PidFile)
@ -3233,6 +3232,19 @@ options_validate(or_options_t *old_options, or_options_t *options,
"of the Internet, so they must not set Reachable*Addresses "
"or FascistFirewall.");
/* XXX023 use autobool instead. */
if (!strcmp(options->UseBridges_, "auto")) {
options->UseBridges = (options->Bridges &&
!server_mode(options) &&
!options->EntryNodes);
} else if (!strcmp(options->UseBridges_, "0")) {
options->UseBridges = 0;
} else if (!strcmp(options->UseBridges_, "1")) {
options->UseBridges = 1;
} else {
REJECT("UseBridges must be 0, 1, or auto");
}
if (options->UseBridges &&
server_mode(options))
REJECT("Servers must be able to freely connect to the rest "
@ -3567,10 +3579,8 @@ options_validate(or_options_t *old_options, or_options_t *options,
if (validate_dir_authorities(options, old_options) < 0)
REJECT("Directory authority line did not parse. See logs for details.");
if (options->UseBridges && !options->Bridges)
REJECT("If you set UseBridges, you must specify at least one bridge.");
if (options->UseBridges && !options->TunnelDirConns)
REJECT("If you set UseBridges, you must set TunnelDirConns.");
REJECT("TunnelDirConns set to 0 only works with UseBridges set to 0");
if (options->Bridges) {
for (cl = options->Bridges; cl; cl = cl->next) {
if (parse_bridge_line(cl->value, 1)<0)

View File

@ -1952,7 +1952,7 @@ retry_all_listeners(smartlist_t *replaced_conns,
or_options_t *options = get_options();
int retval = 0;
const uint16_t old_or_port = router_get_advertised_or_port(options);
const uint16_t old_dir_port = router_get_advertised_dir_port(options);
const uint16_t old_dir_port = router_get_advertised_dir_port(options, 0);
if (retry_listeners(CONN_TYPE_OR_LISTENER, options->ORListenAddress,
options->ORPort, "0.0.0.0",
@ -1998,7 +1998,7 @@ retry_all_listeners(smartlist_t *replaced_conns,
return -1;
if (old_or_port != router_get_advertised_or_port(options) ||
old_dir_port != router_get_advertised_dir_port(options)) {
old_dir_port != router_get_advertised_dir_port(options, 0)) {
/* Our chosen ORPort or DirPort is not what it used to be: the
* descriptor we had (if any) should be regenerated. (We won't
* automatically notice this because of changes in the option,

View File

@ -2705,7 +2705,7 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_env_t *private_key,
voter->sigs = smartlist_create();
voter->address = hostname;
voter->addr = addr;
voter->dir_port = router_get_advertised_dir_port(options);
voter->dir_port = router_get_advertised_dir_port(options, 0);
voter->or_port = router_get_advertised_or_port(options);
voter->contact = tor_strdup(contact);
if (options->V3AuthUseLegacyKey) {
@ -2812,7 +2812,8 @@ generate_v2_networkstatus_opinion(void)
"dir-options%s%s%s%s\n"
"%s" /* client version line, server version line. */
"dir-signing-key\n%s",
hostname, ipaddr, (int)router_get_advertised_dir_port(options),
hostname, ipaddr,
(int)router_get_advertised_dir_port(options, 0),
fingerprint,
contact,
published,

View File

@ -853,8 +853,7 @@ signewnym_impl(time_t now)
circuit_expire_all_dirty_circs();
addressmap_clear_transient();
rend_cache_purge();
rend_client_cancel_descriptor_fetches();
rend_client_purge_state();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
}

View File

@ -2480,7 +2480,17 @@ typedef struct {
* when doing so. */
char *BridgePassword;
int UseBridges; /**< Boolean: should we start all circuits with a bridge? */
/** Whether we should start all circuits with a bridge. "1" means strictly
* yes, "0" means strictly no, and "auto" means that we do iff any bridges
* are configured, we are not running a server and have not specified a list
* of entry nodes. */
char *UseBridges_;
/** Effective value of UseBridges. Will be set equally for UseBridges set to
* 1 or 0, but for 'auto' it will be set to 1 iff any bridges are
* configured, we are not running a server and have not specified a list of
* entry nodes. */
int UseBridges;
config_line_t *Bridges; /**< List of bootstrap bridge addresses. */
int BridgeRelay; /**< Boolean: are we acting as a bridge relay? We make

View File

@ -27,6 +27,16 @@ static extend_info_t *rend_client_get_random_intro_impl(
const rend_cache_entry_t *rend_query,
const int strict, const int warnings);
/** Purge all potentially remotely-detectable state held in the hidden
* service client code. Called on SIGNAL NEWNYM. */
void
rend_client_purge_state(void)
{
rend_cache_purge();
rend_client_cancel_descriptor_fetches();
rend_client_purge_last_hid_serv_requests();
}
/** Called when we've established a circuit to an introduction point:
* send the introduction request. */
void
@ -377,7 +387,17 @@ rend_client_introduction_acked(origin_circuit_t *circ,
* certain queries; keys are strings consisting of base32-encoded
* hidden service directory identities and base32-encoded descriptor IDs;
* values are pointers to timestamps of the last requests. */
static strmap_t *last_hid_serv_requests = NULL;
static strmap_t *last_hid_serv_requests_ = NULL;
/** Returns last_hid_serv_requests_, initializing it to a new strmap if
* necessary. */
static strmap_t *
get_last_hid_serv_requests(void)
{
if (!last_hid_serv_requests_)
last_hid_serv_requests_ = strmap_new();
return last_hid_serv_requests_;
}
/** Look up the last request time to hidden service directory <b>hs_dir</b>
* for descriptor ID <b>desc_id_base32</b>. If <b>set</b> is non-zero,
@ -391,6 +411,7 @@ lookup_last_hid_serv_request(routerstatus_t *hs_dir,
char hsdir_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
char hsdir_desc_comb_id[2 * REND_DESC_ID_V2_LEN_BASE32 + 1];
time_t *last_request_ptr;
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
base32_encode(hsdir_id_base32, sizeof(hsdir_id_base32),
hs_dir->identity_digest, DIGEST_LEN);
tor_snprintf(hsdir_desc_comb_id, sizeof(hsdir_desc_comb_id), "%s%s",
@ -416,8 +437,7 @@ directory_clean_last_hid_serv_requests(void)
{
strmap_iter_t *iter;
time_t cutoff = time(NULL) - REND_HID_SERV_DIR_REQUERY_PERIOD;
if (!last_hid_serv_requests)
last_hid_serv_requests = strmap_new();
strmap_t *last_hid_serv_requests = get_last_hid_serv_requests();
for (iter = strmap_iter_init(last_hid_serv_requests);
!strmap_iter_done(iter); ) {
const char *key;
@ -434,6 +454,26 @@ directory_clean_last_hid_serv_requests(void)
}
}
/** Purge the history of request times to hidden service directories,
* so that future lookups of an HS descriptor will not fail because we
* accessed all of the HSDir relays responsible for the descriptor
* recently. */
void
rend_client_purge_last_hid_serv_requests(void)
{
/* Don't create the table if it doesn't exist yet (and it may very
* well not exist if the user hasn't accessed any HSes)... */
strmap_t *old_last_hid_serv_requests = last_hid_serv_requests_;
/* ... and let get_last_hid_serv_requests re-create it for us if
* necessary. */
last_hid_serv_requests_ = NULL;
if (old_last_hid_serv_requests != NULL) {
log_info(LD_REND, "Purging client last-HS-desc-request-time table");
strmap_free(old_last_hid_serv_requests, _tor_free);
}
}
/** Determine the responsible hidden service directories for <b>desc_id</b>
* and fetch the descriptor belonging to that ID from one of them. Only
* send a request to hidden service directories that we did not try within

View File

@ -12,6 +12,8 @@
#ifndef _TOR_RENDCLIENT_H
#define _TOR_RENDCLIENT_H
void rend_client_purge_state(void);
void rend_client_introcirc_has_opened(origin_circuit_t *circ);
void rend_client_rendcirc_has_opened(origin_circuit_t *circ);
int rend_client_introduction_acked(origin_circuit_t *circ,
@ -19,6 +21,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
size_t request_len);
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
void rend_client_cancel_descriptor_fetches(void);
void rend_client_purge_last_hid_serv_requests(void);
int rend_client_remove_intro_point(extend_info_t *failed_intro,
const rend_data_t *rend_query);
int rend_client_rendezvous_acked(origin_circuit_t *circ,

View File

@ -839,8 +839,10 @@ rend_cache_clean(void)
void
rend_cache_purge(void)
{
if (rend_cache)
if (rend_cache) {
log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
strmap_free(rend_cache, _rend_cache_entry_free);
}
rend_cache = strmap_new();
}
@ -982,15 +984,10 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
tor_assert(rend_cache_v2_dir);
if (base32_decode(desc_id_digest, DIGEST_LEN,
desc_id, REND_DESC_ID_V2_LEN_BASE32) < 0) {
log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
safe_str(desc_id));
return -1;
}
/* Determine if we are responsible. */
if (hid_serv_responsible_for_desc_id(desc_id_digest) < 0) {
log_info(LD_REND, "Could not answer fetch request for v2 descriptor; "
"either we are no hidden service directory, or we are "
"not responsible for the requested ID.");
log_fn(LOG_PROTOCOL_WARN, LD_REND,
"Rejecting v2 rendezvous descriptor request -- descriptor ID "
"contains illegal characters: %s",
safe_str(desc_id));
return -1;
}
/* Lookup descriptor and return. */

View File

@ -704,7 +704,7 @@ init_keys(void)
ds = router_get_trusteddirserver_by_digest(digest);
if (!ds) {
ds = add_trusted_dir_server(options->Nickname, NULL,
router_get_advertised_dir_port(options),
router_get_advertised_dir_port(options, 0),
router_get_advertised_or_port(options),
digest,
v3_digest,
@ -802,7 +802,7 @@ decide_to_advertise_dirport(or_options_t *options, uint16_t dir_port)
return 0;
if (!check_whether_dirport_reachable())
return 0;
if (!router_get_advertised_dir_port(options))
if (!router_get_advertised_dir_port(options, dir_port))
return 0;
/* Section two: reasons to publish or not publish that the user
@ -1184,12 +1184,16 @@ router_get_advertised_or_port(or_options_t *options)
return options->ORPort;
}
/** Return the port that we should advertise as our DirPort; this is either
* the one configured in the DirPort option, or the one we actually bound to
* if DirPort is "auto". */
/** Return the port that we should advertise as our DirPort;
* this is one of three possibilities:
* The one that is passed as <b>dirport</b> if the DirPort option is 0, or
* the one configured in the DirPort option,
* or the one we actually bound to if DirPort is "auto". */
uint16_t
router_get_advertised_dir_port(or_options_t *options)
router_get_advertised_dir_port(or_options_t *options, uint16_t dirport)
{
if (!options->DirPort)
return dirport;
if (options->DirPort == CFG_AUTO_PORT) {
connection_t *c = connection_get_by_type(CONN_TYPE_DIR_LISTENER);
if (c)
@ -1440,7 +1444,7 @@ router_rebuild_descriptor(int force)
ri->nickname = tor_strdup(options->Nickname);
ri->addr = addr;
ri->or_port = router_get_advertised_or_port(options);
ri->dir_port = router_get_advertised_dir_port(options);
ri->dir_port = router_get_advertised_dir_port(options, 0);
ri->cache_info.published_on = time(NULL);
ri->onion_pkey = crypto_pk_dup_key(get_onion_key()); /* must invoke from
* main thread */

View File

@ -51,7 +51,8 @@ int authdir_mode_tests_reachability(or_options_t *options);
int authdir_mode_bridge(or_options_t *options);
uint16_t router_get_advertised_or_port(or_options_t *options);
uint16_t router_get_advertised_dir_port(or_options_t *options);
uint16_t router_get_advertised_dir_port(or_options_t *options,
uint16_t dirport);
int server_mode(or_options_t *options);
int public_server_mode(or_options_t *options);

View File

@ -3765,9 +3765,9 @@ token_check_object(memarea_t *area, const char *kwd,
break;
case NEED_KEY_1024: /* There must be a 1024-bit public key. */
case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
kwd, (int)crypto_pk_keysize(tok->key));
kwd, crypto_pk_num_bits(tok->key));
RET_ERR(ebuf);
}
/* fall through */

View File

@ -343,7 +343,9 @@ test_crypto_pk(void)
test_eq(0, crypto_pk_cmp_keys(pk1, pk2));
test_eq(128, crypto_pk_keysize(pk1));
test_eq(1024, crypto_pk_num_bits(pk1));
test_eq(128, crypto_pk_keysize(pk2));
test_eq(1024, crypto_pk_num_bits(pk2));
test_eq(128, crypto_pk_public_encrypt(pk2, data1, sizeof(data1),
"Hello whirled.", 15,