|
@@ -92,13 +92,25 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
|
|
|
if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
|
|
|
&entry) < 1) {
|
|
|
- log_warn(LD_REND,
|
|
|
- "query %s didn't have valid rend desc in cache. Failing.",
|
|
|
- escaped_safe_str_client(introcirc->rend_data->onion_address));
|
|
|
- goto err;
|
|
|
+ log_info(LD_REND,
|
|
|
+ "query %s didn't have valid rend desc in cache. "
|
|
|
+ "Refetching descriptor.",
|
|
|
+ safe_str_client(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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
- /* first 20 bytes of payload are the hash of the intro key */
|
|
|
+ /* first 20 bytes of payload are the hash of Bob's pk */
|
|
|
intro_key = NULL;
|
|
|
SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
|
|
|
intro, {
|
|
@@ -113,11 +125,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
"mid-connect! Could not find intro key; we only have a "
|
|
|
"v2 rend desc with %d intro points. Giving up.",
|
|
|
smartlist_len(entry->parsed->intro_nodes));
|
|
|
- goto err;
|
|
|
+ goto perm_err;
|
|
|
}
|
|
|
if (crypto_pk_get_digest(intro_key, payload)<0) {
|
|
|
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. */
|
|
@@ -128,11 +140,11 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
cpath->magic = CRYPT_PATH_MAGIC;
|
|
|
if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
|
|
|
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) {
|
|
|
log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
|
|
|
- goto err;
|
|
|
+ goto perm_err;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -182,7 +194,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
|
|
|
DH_KEY_LEN)<0) {
|
|
|
log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
|
|
|
- goto err;
|
|
|
+ goto perm_err;
|
|
|
}
|
|
|
|
|
|
note_crypto_pk_op(REND_CLIENT);
|
|
@@ -195,7 +207,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
PK_PKCS1_OAEP_PADDING, 0);
|
|
|
if (r<0) {
|
|
|
log_warn(LD_BUG,"Internal error: hybrid pk encrypt failed.");
|
|
|
- goto err;
|
|
|
+ goto perm_err;
|
|
|
}
|
|
|
|
|
|
payload_len = DIGEST_LEN + r;
|
|
@@ -208,17 +220,17 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
|
|
|
introcirc->cpath->prev)<0) {
|
|
|
/* introcirc is already marked for close. leave rendcirc alone. */
|
|
|
log_warn(LD_BUG, "Couldn't send INTRODUCE1 cell");
|
|
|
- return -1;
|
|
|
+ return -2;
|
|
|
}
|
|
|
|
|
|
/* Now, we wait for an ACK or NAK on this circuit. */
|
|
|
introcirc->_base.purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT;
|
|
|
|
|
|
return 0;
|
|
|
- err:
|
|
|
+perm_err:
|
|
|
circuit_mark_for_close(TO_CIRCUIT(introcirc), 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
|
|
@@ -529,8 +541,44 @@ rend_client_refetch_v2_renddesc(const rend_data_t *rend_query)
|
|
|
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
|
|
|
* service is unrecognized, then launch a new renddesc fetch.
|
|
|
+
|
|
|
*
|
|
|
* Return -1 if error, 0 if no intro points remain or service
|
|
|
* unrecognized, 1 if recognized and some intro points remain.
|