mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Merge branch 'bug3k_021' into bug3k_022
Conflicts: src/or/or.h src/or/rendclient.c
This commit is contained in:
commit
4b13ebd5ab
9
changes/forget-rend-descs-on-newnym
Normal file
9
changes/forget-rend-descs-on-newnym
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
o Security fixes:
|
||||||
|
- Forget all hidden service descriptors cached as a client when
|
||||||
|
processing a SIGNAL NEWNYM command. Fixes bug 3000. Bugfix on
|
||||||
|
0.0.6.
|
||||||
|
o Code simplifications and refactoring:
|
||||||
|
- Allow rend_client_send_introduction to fail without closing the
|
||||||
|
AP connection permanently.
|
||||||
|
|
||||||
|
|
@ -1744,14 +1744,21 @@ connection_ap_handshake_attach_circuit(edge_connection_t *conn)
|
|||||||
"introduction. (stream %d sec old)",
|
"introduction. (stream %d sec old)",
|
||||||
introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
|
introcirc->_base.n_circ_id, rendcirc->_base.n_circ_id,
|
||||||
conn_age);
|
conn_age);
|
||||||
if (rend_client_send_introduction(introcirc, rendcirc) < 0) {
|
switch (rend_client_send_introduction(introcirc, rendcirc)) {
|
||||||
return -1;
|
case 0: /* success */
|
||||||
}
|
|
||||||
rendcirc->_base.timestamp_dirty = time(NULL);
|
rendcirc->_base.timestamp_dirty = time(NULL);
|
||||||
introcirc->_base.timestamp_dirty = time(NULL);
|
introcirc->_base.timestamp_dirty = time(NULL);
|
||||||
assert_circuit_ok(TO_CIRCUIT(rendcirc));
|
assert_circuit_ok(TO_CIRCUIT(rendcirc));
|
||||||
assert_circuit_ok(TO_CIRCUIT(introcirc));
|
assert_circuit_ok(TO_CIRCUIT(introcirc));
|
||||||
return 0;
|
return 0;
|
||||||
|
case -1: /* transient error */
|
||||||
|
return 0;
|
||||||
|
case -2: /* permanent error */
|
||||||
|
return -1;
|
||||||
|
default: /* oops */
|
||||||
|
tor_fragile_assert();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,6 +844,8 @@ signewnym_impl(time_t now)
|
|||||||
{
|
{
|
||||||
circuit_expire_all_dirty_circs();
|
circuit_expire_all_dirty_circs();
|
||||||
addressmap_clear_transient();
|
addressmap_clear_transient();
|
||||||
|
rend_cache_purge();
|
||||||
|
rend_client_cancel_descriptor_fetches();
|
||||||
time_of_last_signewnym = now;
|
time_of_last_signewnym = now;
|
||||||
signewnym_is_pending = 0;
|
signewnym_is_pending = 0;
|
||||||
}
|
}
|
||||||
|
@ -91,13 +91,25 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
|
|
||||||
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
|
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
|
||||||
&entry) < 1) {
|
&entry) < 1) {
|
||||||
log_warn(LD_REND,
|
log_info(LD_REND,
|
||||||
"query %s didn't have valid rend desc in cache. Failing.",
|
"query %s didn't have valid rend desc in cache. "
|
||||||
escaped_safe_str_client(introcirc->rend_data->onion_address));
|
"Refetching descriptor.",
|
||||||
goto err;
|
safe_str(introcirc->rend_data->onion_address));
|
||||||
|
rend_client_refetch_v2_renddesc(introcirc->rend_data);
|
||||||
|
{
|
||||||
|
connection_t *conn;
|
||||||
|
|
||||||
|
while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
|
||||||
|
AP_CONN_STATE_CIRCUIT_WAIT,
|
||||||
|
introcirc->rend_data->onion_address))) {
|
||||||
|
conn->state = AP_CONN_STATE_RENDDESC_WAIT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* first 20 bytes of payload are the hash of the intro key */
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* first 20 bytes of payload are the hash of Bob's pk */
|
||||||
intro_key = NULL;
|
intro_key = NULL;
|
||||||
SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
|
SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
|
||||||
intro, {
|
intro, {
|
||||||
@ -108,15 +120,14 @@ 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, "Internal error: could not find intro key; we "
|
||||||
"mid-connect! Could not find intro key; we only have a "
|
"only have a v2 rend desc with %d intro points.",
|
||||||
"v2 rend desc with %d intro points. Giving up.",
|
|
||||||
smartlist_len(entry->parsed->intro_nodes));
|
smartlist_len(entry->parsed->intro_nodes));
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
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.");
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize the pending_final_cpath and start the DH handshake. */
|
/* Initialize the pending_final_cpath and start the DH handshake. */
|
||||||
@ -127,11 +138,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
cpath->magic = CRYPT_PATH_MAGIC;
|
cpath->magic = CRYPT_PATH_MAGIC;
|
||||||
if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
|
if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
|
||||||
log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
|
log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
|
if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
|
||||||
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
|
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,7 +192,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
|
if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
|
||||||
DH_KEY_LEN)<0) {
|
DH_KEY_LEN)<0) {
|
||||||
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
|
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
note_crypto_pk_op(REND_CLIENT);
|
note_crypto_pk_op(REND_CLIENT);
|
||||||
@ -194,7 +205,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
PK_PKCS1_OAEP_PADDING, 0);
|
PK_PKCS1_OAEP_PADDING, 0);
|
||||||
if (r<0) {
|
if (r<0) {
|
||||||
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
|
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
|
||||||
goto err;
|
goto perm_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload_len = DIGEST_LEN + r;
|
payload_len = DIGEST_LEN + r;
|
||||||
@ -207,17 +218,17 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|||||||
introcirc->cpath->prev)<0) {
|
introcirc->cpath->prev)<0) {
|
||||||
/* introcirc is already marked for close. leave rendcirc alone. */
|
/* introcirc is already marked for close. leave rendcirc alone. */
|
||||||
log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell");
|
log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell");
|
||||||
return -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, we wait for an ACK or NAK on this circuit. */
|
/* Now, we wait for an ACK or NAK on this circuit. */
|
||||||
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
err:
|
perm_err:
|
||||||
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 -1;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called when a rendezvous circuit is open; sends a establish
|
/** Called when a rendezvous circuit is open; sends a establish
|
||||||
@ -526,8 +537,44 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Cancel all rendezvous descriptor fetches currently in progress.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rend_client_cancel_descriptor_fetches(void)
|
||||||
|
{
|
||||||
|
smartlist_t *connection_array = get_connection_array();
|
||||||
|
|
||||||
|
SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
|
||||||
|
if (conn->type == CONN_TYPE_DIR &&
|
||||||
|
(conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
|
||||||
|
conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
|
||||||
|
/* It's a rendezvous descriptor fetch in progress -- cancel it
|
||||||
|
* by marking the connection for close.
|
||||||
|
*
|
||||||
|
* Even if this connection has already reached EOF, this is
|
||||||
|
* enough to make sure that if the descriptor hasn't been
|
||||||
|
* processed yet, it won't be. See the end of
|
||||||
|
* connection_handle_read; connection_reached_eof (indirectly)
|
||||||
|
* processes whatever response the connection received. */
|
||||||
|
|
||||||
|
const rend_data_t *rd = (TO_DIR_CONN(conn))->rend_data;
|
||||||
|
if (!rd) {
|
||||||
|
log_warn(LD_BUG | LD_REND,
|
||||||
|
"Marking for close dir conn fetching rendezvous "
|
||||||
|
"descriptor for unknown service!");
|
||||||
|
} else {
|
||||||
|
log_debug(LD_REND, "Marking for close dir conn fetching "
|
||||||
|
"rendezvous descriptor for service %s",
|
||||||
|
safe_str(rd->onion_address));
|
||||||
|
}
|
||||||
|
connection_mark_for_close(conn);
|
||||||
|
}
|
||||||
|
} SMARTLIST_FOREACH_END(conn);
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove failed_intro from ent. If ent now has no intro points, or
|
/** Remove failed_intro from ent. If ent now has no intro points, or
|
||||||
* service is unrecognized, then launch a new renddesc fetch.
|
* service is unrecognized, then launch a new renddesc fetch.
|
||||||
|
|
||||||
*
|
*
|
||||||
* Return -1 if error, 0 if no intro points remain or service
|
* Return -1 if error, 0 if no intro points remain or service
|
||||||
* unrecognized, 1 if recognized and some intro points remain.
|
* unrecognized, 1 if recognized and some intro points remain.
|
||||||
|
@ -18,6 +18,7 @@ int rend_client_introduction_acked(origin_circuit_t *circ,
|
|||||||
const uint8_t *request,
|
const uint8_t *request,
|
||||||
size_t request_len);
|
size_t request_len);
|
||||||
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
|
void rend_client_refetch_v2_renddesc(const rend_data_t *rend_query);
|
||||||
|
void rend_client_cancel_descriptor_fetches(void);
|
||||||
int rend_client_remove_intro_point(extend_info_t *failed_intro,
|
int rend_client_remove_intro_point(extend_info_t *failed_intro,
|
||||||
const rend_data_t *rend_query);
|
const rend_data_t *rend_query);
|
||||||
int rend_client_rendezvous_acked(origin_circuit_t *circ,
|
int rend_client_rendezvous_acked(origin_circuit_t *circ,
|
||||||
|
@ -834,6 +834,16 @@ rend_cache_clean(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Remove ALL entries from the rendezvous service descriptor cache.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
rend_cache_purge(void)
|
||||||
|
{
|
||||||
|
if (rend_cache)
|
||||||
|
strmap_free(rend_cache, _rend_cache_entry_free);
|
||||||
|
rend_cache = strmap_new();
|
||||||
|
}
|
||||||
|
|
||||||
/** Remove all old v2 descriptors and those for which this hidden service
|
/** Remove all old v2 descriptors and those for which this hidden service
|
||||||
* directory is not responsible for any more. */
|
* directory is not responsible for any more. */
|
||||||
void
|
void
|
||||||
|
@ -36,6 +36,7 @@ void rend_intro_point_free(rend_intro_point_t *intro);
|
|||||||
void rend_cache_init(void);
|
void rend_cache_init(void);
|
||||||
void rend_cache_clean(void);
|
void rend_cache_clean(void);
|
||||||
void rend_cache_clean_v2_descs_as_dir(void);
|
void rend_cache_clean_v2_descs_as_dir(void);
|
||||||
|
void rend_cache_purge(void);
|
||||||
void rend_cache_free_all(void);
|
void rend_cache_free_all(void);
|
||||||
int rend_valid_service_id(const char *query);
|
int rend_valid_service_id(const char *query);
|
||||||
int rend_cache_lookup_desc(const char *query, int version, const char **desc,
|
int rend_cache_lookup_desc(const char *query, int version, const char **desc,
|
||||||
|
Loading…
Reference in New Issue
Block a user