Merge branch 'maint-0.2.2' into release-0.2.2

This commit is contained in:
Nick Mathewson 2011-05-16 14:55:50 -04:00
commit c0fae841ec
10 changed files with 96 additions and 15 deletions

5
changes/bug2850 Normal file
View File

@ -0,0 +1,5 @@
- Minor features
o Set SO_REUSEADDR on all sockets, not just listeners. This should
help busy exit nodes avoid running out of useable ports just because
all the ports have been used in the near past. Resolves issue 2850.

View File

@ -0,0 +1,7 @@
o Security fixes:
- When fetching a hidden service descriptor, check that it is for
the hidden service we were trying to connect to, in order to
stop a directory from pre-seeding a client with a descriptor for
a hidden service that they didn't want. Bugfix on 0.0.6.

View File

@ -0,0 +1,5 @@
o Minor bugfixes:
- Require that introduction point keys and onion keys have public
exponent 65537. Bugfix on 0.2.0.10-alpha.

View File

@ -733,6 +733,18 @@ crypto_pk_key_is_private(const crypto_pk_env_t *key)
return PRIVATE_KEY_OK(key);
}
/** Return true iff <b>env</b> contains a public key whose public exponent
* equals 65537.
*/
int
crypto_pk_public_exponent_ok(crypto_pk_env_t *env)
{
tor_assert(env);
tor_assert(env->key);
return BN_is_word(env->key->e, 65537);
}
/** Compare the public-key components of a and b. Return -1 if a\<b, 0
* if a==b, and 1 if a\>b.
*/

View File

@ -122,6 +122,7 @@ size_t crypto_pk_keysize(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);
int crypto_pk_public_exponent_ok(crypto_pk_env_t *env);
int crypto_pk_public_encrypt(crypto_pk_env_t *env, char *to, size_t tolen,
const char *from, size_t fromlen, int padding);

View File

@ -890,6 +890,25 @@ check_location_for_unix_socket(or_options_t *options, const char *path)
}
#endif
/** Tell the TCP stack that it shouldn't wait for a long time after
* <b>sock</b> has closed before reusing its port. */
static void
make_socket_reuseable(int sock)
{
#ifdef MS_WINDOWS
(void) sock;
#else
int one=1;
/* REUSEADDR on normal places means you can rebind to the port
* right after somebody else has let it go. But REUSEADDR on win32
* means you can bind to the port _even when somebody else
* already has it bound_. So, don't do that on Win32. */
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
(socklen_t)sizeof(one));
#endif
}
/** Bind a new non-blocking socket listening to the socket described
* by <b>listensockaddr</b>.
*
@ -914,9 +933,6 @@ connection_create_listener(const struct sockaddr *listensockaddr,
if (listensockaddr->sa_family == AF_INET) {
tor_addr_t addr;
int is_tcp = (type != CONN_TYPE_AP_DNS_LISTENER);
#ifndef MS_WINDOWS
int one=1;
#endif
if (is_tcp)
start_reading = 1;
@ -933,14 +949,7 @@ connection_create_listener(const struct sockaddr *listensockaddr,
goto err;
}
#ifndef MS_WINDOWS
/* REUSEADDR on normal places means you can rebind to the port
* right after somebody else has let it go. But REUSEADDR on win32
* means you can bind to the port _even when somebody else
* already has it bound_. So, don't do that on Win32. */
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void*) &one,
(socklen_t)sizeof(one));
#endif
make_socket_reuseable(s);
if (bind(s,listensockaddr,socklen) < 0) {
const char *helpfulhint = "";
@ -1159,6 +1168,7 @@ connection_handle_listener_read(connection_t *conn, int new_type)
"Connection accepted on socket %d (child of fd %d).",
news,conn->s);
make_socket_reuseable(news);
set_socket_nonblocking(news);
if (options->ConstrainedSockets)
@ -1368,6 +1378,8 @@ connection_connect(connection_t *conn, const char *address,
log_debug(LD_NET, "Connecting to %s:%u.",
escaped_safe_str_client(address), port);
make_socket_reuseable(s);
if (connect(s, dest_addr, dest_addr_len) < 0) {
int e = tor_socket_errno(s);
if (!ERRNO_IS_CONN_EINPROGRESS(e)) {

View File

@ -2003,7 +2003,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
(int)body_len, status_code, escaped(reason));
switch (status_code) {
case 200:
if (rend_cache_store(body, body_len, 0) < -1) {
if (rend_cache_store(body, body_len, 0,
conn->rend_data->onion_address) < -1) {
log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
/* Any pending rendezvous attempts will notice when
* connection_about_to_close_connection()
@ -3271,7 +3272,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
!strcmpstart(url,"/tor/rendezvous/publish")) {
/* rendezvous descriptor post */
log_info(LD_REND, "Handling rendezvous descriptor post.");
if (rend_cache_store(body, body_len, 1) < 0) {
if (rend_cache_store(body, body_len, 1, NULL) < 0) {
log_fn(LOG_PROTOCOL_WARN, LD_DIRSERV,
"Rejected rend descriptor (length %d) from %s.",
(int)body_len, conn->_base.address);

View File

@ -1015,9 +1015,14 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
*
* The published flag tells us if we store the descriptor
* in our role as directory (1) or if we cache it as client (0).
*
* If <b>service_id</b> is non-NULL and the descriptor is not for that
* service ID, reject it. <b>service_id</b> must be specified if and
* only if <b>published</b> is 0 (we fetched this descriptor).
*/
int
rend_cache_store(const char *desc, size_t desc_len, int published)
rend_cache_store(const char *desc, size_t desc_len, int published,
const char *service_id)
{
rend_cache_entry_t *e;
rend_service_descriptor_t *parsed;
@ -1035,6 +1040,12 @@ rend_cache_store(const char *desc, size_t desc_len, int published)
rend_service_descriptor_free(parsed);
return -2;
}
if ((service_id != NULL) && strcmp(query, service_id)) {
log_warn(LD_REND, "Received service descriptor for service ID %s; "
"expected descriptor for service ID %s.",
query, safe_str(service_id));
return -2;
}
now = time(NULL);
if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
log_fn(LOG_PROTOCOL_WARN, LD_REND,
@ -1215,6 +1226,8 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
* If we have an older descriptor with the same ID, replace it.
* If we have any v0 descriptor with the same ID, reject this one in order
* to not get confused with having both versions for the same service.
* If the descriptor's service ID does not match
* <b>rend_query</b>-\>onion_address, reject it.
* Return -2 if it's malformed or otherwise rejected; return -1 if we
* already have a v0 descriptor here; return 0 if it's the same or older
* than one we've already got; return 1 if it's novel.
@ -1265,6 +1278,13 @@ rend_cache_store_v2_desc_as_client(const char *desc,
retval = -2;
goto err;
}
if (strcmp(rend_query->onion_address, service_id)) {
log_warn(LD_REND, "Received service descriptor for service ID %s; "
"expected descriptor for service ID %s.",
service_id, safe_str(rend_query->onion_address));
retval = -2;
goto err;
}
/* Decode/decrypt introduction points. */
if (intro_content) {
if (rend_query->auth_type != REND_NO_AUTH &&

View File

@ -44,7 +44,8 @@ int rend_cache_lookup_desc(const char *query, int version, const char **desc,
int rend_cache_lookup_entry(const char *query, int version,
rend_cache_entry_t **entry_out);
int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
int rend_cache_store(const char *desc, size_t desc_len, int published);
int rend_cache_store(const char *desc, size_t desc_len, int published,
const char *service_id);
int rend_cache_store_v2_desc_as_client(const char *desc,
const rend_data_t *rend_query);
int rend_cache_store_v2_desc_as_dir(const char *desc);

View File

@ -1462,6 +1462,11 @@ router_parse_entry_from_string(const char *s, const char *end,
goto err;
tok = find_by_keyword(tokens, K_ONION_KEY);
if (!crypto_pk_public_exponent_ok(tok->key)) {
log_warn(LD_DIR,
"Relay's onion key had invalid exponent.");
goto err;
}
router->onion_pkey = tok->key;
tok->key = NULL; /* Prevent free */
@ -4982,10 +4987,22 @@ rend_parse_introduction_points(rend_service_descriptor_t *parsed,
}
/* Parse onion key. */
tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
if (!crypto_pk_public_exponent_ok(tok->key)) {
log_warn(LD_REND,
"Introduction point's onion key had invalid exponent.");
rend_intro_point_free(intro);
goto err;
}
info->onion_key = tok->key;
tok->key = NULL; /* Prevent free */
/* Parse service key. */
tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
if (!crypto_pk_public_exponent_ok(tok->key)) {
log_warn(LD_REND,
"Introduction point key had invalid exponent.");
rend_intro_point_free(intro);
goto err;
}
intro->intro_key = tok->key;
tok->key = NULL; /* Prevent free */
/* Add extend info to list of introduction points. */