diff options
author | Nick Mathewson <nickm@torproject.org> | 2006-01-05 21:23:03 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2006-01-05 21:23:03 +0000 |
commit | 878962bee11eb47042d49ebd7df0d18d403c98c0 (patch) | |
tree | 04b1c7ef50ea43a81b1b2b3536fb5b00584d88ed | |
parent | d8e3bc02884cfb85f113e44c9f61a1035789f0bc (diff) | |
download | tor-878962bee11eb47042d49ebd7df0d18d403c98c0.tar.gz tor-878962bee11eb47042d49ebd7df0d18d403c98c0.zip |
Add reasons to DESTROY and RELAY_TRUNCATED cells.
svn:r5734
-rw-r--r-- | doc/TODO | 13 | ||||
-rw-r--r-- | doc/tor-spec.txt | 25 | ||||
-rw-r--r-- | src/or/circuitbuild.c | 39 | ||||
-rw-r--r-- | src/or/circuitlist.c | 31 | ||||
-rw-r--r-- | src/or/circuituse.c | 10 | ||||
-rw-r--r-- | src/or/command.c | 40 | ||||
-rw-r--r-- | src/or/connection.c | 35 | ||||
-rw-r--r-- | src/or/connection_edge.c | 8 | ||||
-rw-r--r-- | src/or/connection_or.c | 23 | ||||
-rw-r--r-- | src/or/control.c | 6 | ||||
-rw-r--r-- | src/or/cpuworker.c | 4 | ||||
-rw-r--r-- | src/or/onion.c | 2 | ||||
-rw-r--r-- | src/or/or.h | 25 | ||||
-rw-r--r-- | src/or/relay.c | 62 | ||||
-rw-r--r-- | src/or/rendclient.c | 18 | ||||
-rw-r--r-- | src/or/rendmid.c | 26 | ||||
-rw-r--r-- | src/or/rendservice.c | 8 |
17 files changed, 234 insertions, 141 deletions
@@ -43,9 +43,10 @@ N - if they're trying to be a tor server and they're running other nodes *are* reachable. o Make EntryNodes and StrictEntrynodes do what we want. -N - Destroy and truncated cells should have reasons. - - Specify - - Implement +N . Destroy and truncated cells should have reasons. + o Specify + o Implement + - Display the reasons under some circumstances? N . Only use a routerdesc if you recognize its hash. o (Must defer till dirservers are upgraded to latest code, which @@ -85,9 +86,6 @@ N . Only use a routerdesc if you recognize its hash. - Test. - Non-directories don't need to keep descriptors in memory. -N - Should router info have a pointer to routerstatus? - - We should at least do something about the duplicated fields. - R - Christian Grothoff's attack of infinite-length circuit. the solution is to have a separate 'extend-data' cell type which is used for the first N data cells, and only @@ -115,6 +113,9 @@ Deferred from 0.1.1.x: those, if circuits aren't working and it's a pattern we recognize ("port 443 worked once and port 9001 keeps not working"). +N - Should router info have a pointer to routerstatus? + - We should at least do something about the duplicated fields. + N . Additional controller features o Find a way to make event info more extensible - change circuit status events to give more details, like purpose, diff --git a/doc/tor-spec.txt b/doc/tor-spec.txt index 5bd449dcf1..4b0931cdb0 100644 --- a/doc/tor-spec.txt +++ b/doc/tor-spec.txt @@ -136,7 +136,8 @@ when do we rotate which keys (tls, link, etc)? CREATE: Payload contains the handshake challenge. CREATED: Payload contains the handshake response. RELAY: Payload contains the relay header and relay body. - DESTROY: Payload is unused. + DESTROY: Payload contains a reason for closing the circuit. + (see 4.4) Upon receiving any other value for the command field, an OR must drop the cell. @@ -376,6 +377,28 @@ when do we rotate which keys (tls, link, etc)? RELAY_TRUNCATED cell towards the OP; the node farther from the OP should send a DESTROY cell down the circuit. + The payload of a RELAY_TRUNCATED or DESTROY cell contains a single octet, + describing why the circuit is being closed or truncated. When sending a + TRUNCATED or DESTROY cell because of another TRUNCATED or DESTROY cell, + the error code should be propagated. The origin of a circuit always sets + this error code to 0, to avoid leaking its version. + + The error codes are: + 0 -- NONE (No reason given.) + 1 -- PROTOCOL (Tor protocol violation.) + 2 -- INTERNAL (Internal error.) + 3 -- REQUESTED (A client sent a TRUNCATE command.) + 4 -- HIBERNATING (Not currently operating; trying to save bandwidth.) + 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.) + 6 -- CONNECTFAILED (Unable to reach server.) + 7 -- OR_IDENTITY (Connected to server, but its OR identity was not + as expected.) + 8 -- OR_CONN_CLOSED (The OR connection that was carrying this circuit + died.) + + [Versions of Tor prior to 0.1.0.11 didn't sent versions; implementations + MUST accept empty TRUNCATED and DESTROY cells.] + 4.5. Routing relay cells When an OR receives a RELAY cell, it checks the cell's circID and diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index bfe61ff878..e371e269ef 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -313,14 +313,14 @@ circuit_establish_circuit(uint8_t purpose, extend_info_t *info, if (onion_pick_cpath_exit(circ, info) < 0 || onion_populate_cpath(circ) < 0) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return NULL; } control_event_circuit_status(circ, CIRC_EVENT_LAUNCHED); if (circuit_handle_first_hop(circ) < 0) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return NULL; } return circ; @@ -420,7 +420,7 @@ circuit_n_conn_done(connection_t *or_conn, int status) DIGEST_LEN)) { if (!status) { /* or_conn failed; close circ */ info(LD_CIRC,"or_conn failed. Closing circ."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_OR_IDENTITY); continue; } debug(LD_CIRC,"Found circ %d, sending create cell.", circ->n_circ_id); @@ -432,7 +432,7 @@ circuit_n_conn_done(connection_t *or_conn, int status) if (circuit_send_next_onion_skin(circ) < 0) { info(LD_CIRC, "send_next_onion_skin failed; circuit marked for closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); continue; /* XXX could this be bad, eg if next_onion_skin failed because conn * died? */ @@ -441,7 +441,7 @@ circuit_n_conn_done(connection_t *or_conn, int status) /* pull the create cell out of circ->onionskin, and send it */ tor_assert(circ->onionskin); if (circuit_deliver_create_cell(circ,CELL_CREATE,circ->onionskin)<0) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); continue; } tor_free(circ->onionskin); @@ -537,7 +537,7 @@ extern int has_completed_circuit; * Otherwise, we need to build a relay extend cell and send it * forward. * - * Return -1 if we want to tear down circ, else return 0. + * Return -reason if we want to tear down circ, else return 0. */ int circuit_send_next_onion_skin(circuit_t *circ) @@ -567,7 +567,7 @@ circuit_send_next_onion_skin(circuit_t *circ) &(circ->cpath->dh_handshake_state), payload) < 0) { warn(LD_CIRC,"onion_skin_create (first hop) failed."); - return -1; + return - END_CIRC_REASON_INTERNAL; } } else { /* We are not an OR, and we're building the first hop of a circuit to a @@ -582,7 +582,7 @@ circuit_send_next_onion_skin(circuit_t *circ) } if (circuit_deliver_create_cell(circ, cell_type, payload) < 0) - return -1; + return - END_CIRC_REASON_RESOURCELIMIT; circ->cpath->state = CPATH_STATE_AWAITING_KEYS; circuit_set_state(circ, CIRCUIT_STATE_BUILDING); @@ -625,7 +625,7 @@ circuit_send_next_onion_skin(circuit_t *circ) if (onion_skin_create(hop->extend_info->onion_key, &(hop->dh_handshake_state), onionskin) < 0) { warn(LD_CIRC,"onion_skin_create failed."); - return -1; + return - END_CIRC_REASON_INTERNAL; } debug(LD_CIRC,"Sending extend relay cell."); @@ -719,7 +719,7 @@ circuit_extend(cell_t *cell, circuit_t *circ) n_conn = connection_or_connect(circ->n_addr, circ->n_port, id_digest); if (!n_conn) { info(LD_CIRC,"Launching n_conn failed. Closing circuit."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); return 0; } debug(LD_CIRC,"connecting in progress (or finished). Good."); @@ -801,7 +801,7 @@ circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse) * Calculate the appropriate keys and digests, make sure KH is * correct, and initialize this hop of the cpath. * - * Return -1 if we want to mark circ for close, else return 0. + * Return - reason if we want to mark circ for close, else return 0. */ int circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) @@ -816,7 +816,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) hop = onion_next_hop_in_cpath(circ->cpath); if (!hop) { /* got an extended when we're all done? */ warn(LD_PROTOCOL,"got extended when circ already built? Closing."); - return -1; + return - END_CIRC_REASON_TORPROTOCOL; } } tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS); @@ -825,7 +825,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) if (onion_skin_client_handshake(hop->dh_handshake_state, reply, keys, DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { warn(LD_CIRC,"onion_skin_client_handshake failed."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } /* Remember hash of g^xy */ memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN); @@ -833,12 +833,12 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) if (fast_client_handshake(hop->fast_handshake_state, reply, keys, DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) { warn(LD_CIRC,"fast_client_handshake failed."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN); } else { warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } if (hop->dh_handshake_state) { @@ -848,7 +848,7 @@ circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state)); if (circuit_init_cpath_crypto(hop, keys, 0)<0) { - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } hop->state = CPATH_STATE_OPEN; @@ -880,7 +880,7 @@ circuit_truncated(circuit_t *circ, crypt_path_t *layer) * means that a connection broke or an extend failed. For now, * just give up. */ - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return 0; #if 0 @@ -1375,12 +1375,13 @@ circuit_append_new_exit(circuit_t *circ, extend_info_t *info) int circuit_extend_to_new_exit(circuit_t *circ, extend_info_t *info) { + tor_assert(CIRCUIT_IS_ORIGIN(circ)); circuit_append_new_exit(circ, info); circuit_set_state(circ, CIRCUIT_STATE_BUILDING); if (circuit_send_next_onion_skin(circ)<0) { warn(LD_CIRC, "Couldn't extend circuit to new point '%s'.", info->nickname); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } return 0; @@ -1731,7 +1732,7 @@ static INLINE int is_an_entry_node(char *digest) { SMARTLIST_FOREACH(entry_nodes, entry_node_t *, entry, - if(!memcmp(digest, entry->identity, DIGEST_LEN)) + if (!memcmp(digest, entry->identity, DIGEST_LEN)) return 1; ); return 0; diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c index a90af469b4..ab60327a2d 100644 --- a/src/or/circuitlist.c +++ b/src/or/circuitlist.c @@ -470,7 +470,7 @@ circuit_get_by_edge_conn(connection_t *conn) * been marked already. */ void -circuit_unlink_all_from_or_conn(connection_t *conn) +circuit_unlink_all_from_or_conn(connection_t *conn, int reason) { circuit_t *circ; for (circ = global_circuitlist; circ; circ = circ->next) { @@ -480,7 +480,7 @@ circuit_unlink_all_from_or_conn(connection_t *conn) if (circ->p_conn == conn) circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED); if (!circ->marked_for_close) - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); } } } @@ -607,7 +607,7 @@ circuit_mark_all_unused_circs(void) if (CIRCUIT_IS_ORIGIN(circ) && !circ->marked_for_close && !circ->timestamp_dirty) - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } } @@ -648,7 +648,8 @@ circuit_expire_all_dirty_circs(void) * rendezvous stream), then mark the other circuit to close as well. */ void -_circuit_mark_for_close(circuit_t *circ, int line, const char *file) +_circuit_mark_for_close(circuit_t *circ, int reason, int line, + const char *file) { connection_t *conn; @@ -663,6 +664,22 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file) circ->marked_for_close_file, circ->marked_for_close); return; } + if (reason == END_CIRC_AT_ORIGIN) { + if (!CIRCUIT_IS_ORIGIN(circ)) { + warn(LD_BUG, "Specified 'at-origin' non-reason for ending circuit, " + "but circuit was not at origin. (called %s:%d, purpose=%d)", + file, line, circ->purpose); + } + reason = END_CIRC_REASON_NONE; + } else if (CIRCUIT_IS_ORIGIN(circ) && reason != END_CIRC_REASON_NONE) { + /* Don't warn about this; there are plenty of places where our code + * is origin-agnosic. */ + reason = END_CIRC_REASON_NONE; + } + if (reason < _END_CIRC_REASON_MIN || reason > _END_CIRC_REASON_MAX) { + warn(LD_BUG, "Reason %d out of range at %s:%d", reason, file, line); + reason = END_CIRC_REASON_NONE; + } if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) { onion_pending_remove(circ); @@ -698,7 +715,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file) } if (circ->n_conn) - connection_send_destroy(circ->n_circ_id, circ->n_conn); + connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason); for (conn=circ->n_streams; conn; conn=conn->next_stream) connection_edge_destroy(circ->n_circ_id, conn); while (circ->resolving_streams) { @@ -714,7 +731,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file) conn->on_circuit = NULL; } if (circ->p_conn) - connection_send_destroy(circ->p_circ_id, circ->p_conn); + connection_or_send_destroy(circ->p_circ_id, circ->p_conn, reason); for (conn=circ->p_streams; conn; conn=conn->next_stream) connection_edge_destroy(circ->p_circ_id, conn); @@ -724,7 +741,7 @@ _circuit_mark_for_close(circuit_t *circ, int line, const char *file) if (circ->rend_splice) { if (!circ->rend_splice->marked_for_close) { /* do this after marking this circuit, to avoid infinite recursion. */ - circuit_mark_for_close(circ->rend_splice); + circuit_mark_for_close(circ->rend_splice, reason); } circ->rend_splice = NULL; } diff --git a/src/or/circuituse.c b/src/or/circuituse.c index cf15b3ce95..1f52387829 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -264,7 +264,7 @@ circuit_expire_building(time_t now) circuit_state_to_string(victim->state), victim->purpose); circuit_log_path(LOG_INFO,LD_CIRC,victim); - circuit_mark_for_close(victim); + circuit_mark_for_close(victim, END_CIRC_AT_ORIGIN); } } @@ -523,7 +523,7 @@ circuit_about_to_close_connection(connection_t *conn) /* Inform any pending (not attached) circs that they should give up. */ circuit_n_conn_done(conn, 0); /* Now close all the attached circuits on it. */ - circuit_unlink_all_from_or_conn(conn); + circuit_unlink_all_from_or_conn(conn, END_CIRC_REASON_OR_CONN_CLOSED); return; } case CONN_TYPE_AP: @@ -568,7 +568,7 @@ circuit_expire_old_circuits(void) /* (only general and purpose_c circs can get dirty) */ tor_assert(!circ->n_streams); tor_assert(circ->purpose <= CIRCUIT_PURPOSE_C_REND_JOINED); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } else if (!circ->timestamp_dirty && CIRCUIT_IS_ORIGIN(circ) && circ->state == CIRCUIT_STATE_OPEN && circ->purpose == CIRCUIT_PURPOSE_C_GENERAL) { @@ -576,7 +576,7 @@ circuit_expire_old_circuits(void) if (circ->timestamp_created + CIRCUIT_UNUSED_CIRC_TIMEOUT < now) { debug(LD_CIRC,"Closing circuit that has been unused for %d seconds.", (int)(now - circ->timestamp_created)); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } } } @@ -589,7 +589,7 @@ circuit_testing_opened(circuit_t *circ) /* For now, we only use testing circuits to see if our ORPort is reachable. But we remember reachability in onionskin_answer(), so there's no need to record anything here. Just close the circ. */ - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } /** A testing circuit has failed to build. Take whatever stats we want. */ diff --git a/src/or/command.c b/src/or/command.c index 4e7e103d7d..49a9a8f6a7 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -166,7 +166,8 @@ command_process_create_cell(cell_t *cell, connection_t *conn) if (we_are_hibernating()) { info(LD_OR,"Received create cell but we're shutting down. Sending back " "destroy."); - connection_send_destroy(cell->circ_id, conn); + connection_or_send_destroy(cell->circ_id, conn, + END_CIRC_REASON_HIBERNATING); return; } @@ -214,7 +215,7 @@ command_process_create_cell(cell_t *cell, connection_t *conn) /* hand it off to the cpuworkers, and then return */ if (assign_to_cpuworker(NULL, CPUWORKER_TASK_ONION, circ) < 0) { warn(LD_GENERAL,"Failed to hand off onionskin. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return; } debug(LD_OR,"success: handed off onionskin."); @@ -226,12 +227,12 @@ command_process_create_cell(cell_t *cell, connection_t *conn) tor_assert(cell->command == CELL_CREATE_FAST); if (fast_server_handshake(cell->payload, reply, keys, sizeof(keys))<0) { warn(LD_OR,"Failed to generate key material. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return; } if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) { warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return; } } @@ -261,7 +262,7 @@ command_process_created_cell(cell_t *cell, connection_t *conn) if (circ->n_circ_id != cell->circ_id) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL, "got created cell from OPward? Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); return; } @@ -269,13 +270,14 @@ command_process_created_cell(cell_t *cell, connection_t *conn) debug(LD_OR,"at OP. Finishing handshake."); if (circuit_finish_handshake(circ, cell->command, cell->payload) < 0) { warn(LD_OR,"circuit_finish_handshake failed."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return; } debug(LD_OR,"Moving to next skin."); if (circuit_send_next_onion_skin(circ) < 0) { info(LD_OR,"circuit_send_next_onion_skin failed."); - circuit_mark_for_close(circ); /* XXX push this circuit_close lower */ + /* XXX push this circuit_close lower */ + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return; } } else { /* pack it into an extended relay cell, and send it. */ @@ -293,6 +295,7 @@ static void command_process_relay_cell(cell_t *cell, connection_t *conn) { circuit_t *circ; + int reason; circ = circuit_get_by_circid_orconn(cell->circ_id, conn); @@ -304,22 +307,24 @@ command_process_relay_cell(cell_t *cell, connection_t *conn) if (circ->state == CIRCUIT_STATE_ONIONSKIN_PENDING) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit in create_wait. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); return; } if (cell->circ_id == circ->p_circ_id) { /* it's an outgoing cell */ - if (circuit_receive_relay_cell(cell, circ, CELL_DIRECTION_OUT) < 0) { + if ((reason = circuit_receive_relay_cell(cell, circ, + CELL_DIRECTION_OUT)) < 0) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell " "(forward) failed. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, -reason); return; } } else { /* it's an ingoing cell */ - if (circuit_receive_relay_cell(cell, circ, CELL_DIRECTION_IN) < 0) { + if ((reason = circuit_receive_relay_cell(cell, circ, + CELL_DIRECTION_IN)) < 0) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,"circuit_receive_relay_cell " "(backward) failed. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, -reason); return; } } @@ -342,9 +347,10 @@ static void command_process_destroy_cell(cell_t *cell, connection_t *conn) { circuit_t *circ; + uint8_t reason; circ = circuit_get_by_circid_orconn(cell->circ_id, conn); - + reason = (uint8_t)cell->payload[0]; if (!circ) { info(LD_OR,"unknown circuit %d on connection from %s:%d. Dropping.", cell->circ_id, conn->address, conn->port); @@ -355,15 +361,17 @@ command_process_destroy_cell(cell_t *cell, connection_t *conn) if (cell->circ_id == circ->p_circ_id) { /* the destroy came from behind */ circuit_set_circid_orconn(circ, 0, NULL, P_CONN_CHANGED); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); } else { /* the destroy came from ahead */ circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED); if (CIRCUIT_IS_ORIGIN(circ)) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); } else { + char payload[1]; debug(LD_OR, "Delivering 'truncated' back."); + payload[0] = (char)reason; connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED, - NULL, 0, NULL); + payload, sizeof(payload), NULL); } } } diff --git a/src/or/connection.c b/src/or/connection.c index 64a8679dd8..ef94b60c36 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -1038,7 +1038,8 @@ connection_read_bucket_decrement(connection_t *conn, int num_read) } } -/** DOCDOC */ +/** If we have exhaused our global read bucket, or the read bucket for conn, + * stop reading. */ static void connection_consider_empty_buckets(connection_t *conn) { @@ -1546,7 +1547,8 @@ connection_write_to_buf(const char *string, size_t len, connection_t *conn) /* if it failed, it means we have our package/delivery windows set wrong compared to our max outbuf size. close the whole circuit. */ warn(LD_NET,"write_to_buf failed. Closing circuit (fd %d).", conn->s); - circuit_mark_for_close(circuit_get_by_edge_conn(conn)); + circuit_mark_for_close(circuit_get_by_edge_conn(conn), + END_CIRC_REASON_INTERNAL); } else { warn(LD_NET,"write_to_buf failed. Closing connection (fd %d).", conn->s); connection_mark_for_close(conn); @@ -1784,28 +1786,6 @@ connection_state_is_connecting(connection_t *conn) return 0; } -/** Write a destroy cell with circ ID <b>circ_id</b> onto OR connection - * <b>conn</b>. - * - * Return 0. - */ -/*XXXX Why isn't this in connection_or.c?*/ -int -connection_send_destroy(uint16_t circ_id, connection_t *conn) -{ - cell_t cell; - - tor_assert(conn); - tor_assert(connection_speaks_cells(conn)); - - memset(&cell, 0, sizeof(cell_t)); - cell.circ_id = circ_id; - cell.command = CELL_DESTROY; - debug(LD_OR,"Sending destroy (circID %d).", circ_id); - connection_or_write_cell_to_buf(&cell, conn); - return 0; -} - /** Alloocates a base64'ed authenticator for use in http or https * auth, based on the input string <b>authenticator</b>. Returns it * if success, else returns NULL. */ @@ -1829,9 +1809,12 @@ alloc_http_authenticator(const char *authenticator) return base64_authenticator; } -/** DOCDOC - * XXXX ipv6 NM +/** Given a socket handle, check whether the local address (sockname) of the + * socket is one that we've connected from before. If so, double-check + * whether our address has changed and we need to generate keys. If we do, + * call init_keys(). */ +/* XXXX Handle IPv6, eventually. */ static void client_check_address_changed(int sock) { diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index 0954bc4e1d..93d6e884a3 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -1208,7 +1208,7 @@ connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ) ap_conn->stream_id = get_unique_stream_id_by_circ(circ); if (ap_conn->stream_id==0) { connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); return -1; } @@ -1254,7 +1254,7 @@ connection_ap_handshake_send_resolve(connection_t *ap_conn, circuit_t *circ) ap_conn->stream_id = get_unique_stream_id_by_circ(circ); if (ap_conn->stream_id==0) { connection_mark_unattached_ap(ap_conn, END_STREAM_REASON_INTERNAL); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); return -1; } @@ -1519,8 +1519,8 @@ connection_exit_begin_conn(cell_t *cell, circuit_t *circ) connection_edge_end(n_stream, END_STREAM_REASON_EXITPOLICY, n_stream->cpath_layer); connection_free(n_stream); - circuit_mark_for_close(circ); /* knock the whole thing down, somebody - * screwed up */ + /* knock the whole thing down, somebody screwed up */ + circuit_mark_for_close(circ, END_CIRC_REASON_CONNECTFAILED); tor_free(address); return 0; } diff --git a/src/or/connection_or.c b/src/or/connection_or.c index a5e837cd8a..e714a65dd1 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -779,3 +779,26 @@ loop: goto loop; /* process the remainder of the buffer */ } +/** Write a destroy cell with circ ID <b>circ_id</b> and reason <b>reason</b> + * onto OR connection <b>conn</b>. Don't perform range-checking on reason: + * we may want to propagate reasons from other cells. + * + * Return 0. + */ +int +connection_or_send_destroy(uint16_t circ_id, connection_t *conn, int reason) +{ + cell_t cell; + + tor_assert(conn); + tor_assert(connection_speaks_cells(conn)); + + memset(&cell, 0, sizeof(cell_t)); + cell.circ_id = circ_id; + cell.command = CELL_DESTROY; + cell.payload[0] = (uint8_t) reason; + debug(LD_OR,"Sending destroy (circID %d).", circ_id); + connection_or_write_cell_to_buf(&cell, conn); + return 0; +} + diff --git a/src/or/control.c b/src/or/control.c index b5efb84f64..d557fab854 100644 --- a/src/or/control.c +++ b/src/or/control.c @@ -1611,7 +1611,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, /* now that we've populated the cpath, start extending */ if (zero_circ) { if (circuit_handle_first_hop(circ) < 0) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); if (v0) send_control0_error(conn, ERR_INTERNAL, "couldn't start circuit"); else @@ -1624,7 +1624,7 @@ handle_control_extendcircuit(connection_t *conn, uint32_t len, if (circuit_send_next_onion_skin(circ) < 0) { info(LD_CONTROL, "send_next_onion_skin failed; circuit marked for closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); if (v0) send_control0_error(conn, ERR_INTERNAL, "couldn't send onion skin"); else @@ -1967,7 +1967,7 @@ handle_control_closecircuit(connection_t *conn, uint32_t len, } if (!safe || !circ->p_streams) { - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_NONE); } send_control_done(conn); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index de5b33a4da..ad07852530 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -169,7 +169,7 @@ connection_cpu_process_inbuf(connection_t *conn) debug(LD_OR, "decoding onionskin failed. (Old key or bad software.) Closing."); if (circ) - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); goto done_processing; } if (!circ) { @@ -185,7 +185,7 @@ connection_cpu_process_inbuf(connection_t *conn) if (onionskin_answer(circ, CELL_CREATED, buf+TAG_LEN, buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) { warn(LD_OR,"onionskin_answer failed. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); goto done_processing; } debug(LD_OR,"onionskin_answer succeeded. Yay."); diff --git a/src/or/onion.c b/src/or/onion.c index 7aaf5ddeb1..cbe7bd6730 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -71,7 +71,7 @@ onion_pending_add(circuit_t *circ) onion_pending_remove(ol_list->circ); info(LD_CIRC, "Circuit create request is too old; cancelling due to overload."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT); } return 0; } diff --git a/src/or/or.h b/src/or/or.h index fe78382420..06043f9e37 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -481,6 +481,19 @@ typedef enum { #define RESOLVED_TYPE_ERROR_TRANSIENT 0xF0 #define RESOLVED_TYPE_ERROR 0xF1 +#define END_CIRC_AT_ORIGIN -1 +#define _END_CIRC_REASON_MIN 0 +#define END_CIRC_REASON_NONE 0 +#define END_CIRC_REASON_TORPROTOCOL 1 +#define END_CIRC_REASON_INTERNAL 2 +#define END_CIRC_REASON_REQUESTED 3 +#define END_CIRC_REASON_HIBERNATING 4 +#define END_CIRC_REASON_RESOURCELIMIT 5 +#define END_CIRC_REASON_CONNECTFAILED 6 +#define END_CIRC_REASON_OR_IDENTITY 7 +#define END_CIRC_REASON_OR_CONN_CLOSED 8 +#define _END_CIRC_REASON_MAX 8 + /** Length of 'y' portion of 'y.onion' URL. */ #define REND_SERVICE_ID_LEN 16 @@ -1494,7 +1507,7 @@ circuit_t *circuit_new(uint16_t p_circ_id, connection_t *p_conn); circuit_t *circuit_get_by_circid_orconn(uint16_t circ_id, connection_t *conn); int circuit_id_used_on_conn(uint16_t circ_id, connection_t *conn); circuit_t *circuit_get_by_edge_conn(connection_t *conn); -void circuit_unlink_all_from_or_conn(connection_t *conn); +void circuit_unlink_all_from_or_conn(connection_t *conn, int reason); circuit_t *circuit_get_by_global_id(uint32_t id); circuit_t *circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose); @@ -1506,10 +1519,11 @@ circuit_t *circuit_find_to_cannibalize(uint8_t purpose, extend_info_t *info, int need_capacity, int internal); void circuit_mark_all_unused_circs(void); void circuit_expire_all_dirty_circs(void); -void _circuit_mark_for_close(circuit_t *circ, int line, const char *file); +void _circuit_mark_for_close(circuit_t *circ, int reason, + int line, const char *file); -#define circuit_mark_for_close(c) \ - _circuit_mark_for_close((c), __LINE__, _SHORT_FILE_) +#define circuit_mark_for_close(c, reason) \ + _circuit_mark_for_close((c), (reason), __LINE__, _SHORT_FILE_) void assert_cpath_layer_ok(const crypt_path_t *cp); void assert_circuit_ok(const circuit_t *c); @@ -1651,7 +1665,6 @@ int connection_is_listener(connection_t *conn); int connection_state_is_open(connection_t *conn); int connection_state_is_connecting(connection_t *conn); -int connection_send_destroy(uint16_t circ_id, connection_t *conn); char *alloc_http_authenticator(const char *authenticator); void assert_connection_ok(connection_t *conn, time_t now); @@ -1742,6 +1755,8 @@ int connection_tls_start_handshake(connection_t *conn, int receiving); int connection_tls_continue_handshake(connection_t *conn); void connection_or_write_cell_to_buf(const cell_t *cell, connection_t *conn); +int connection_or_send_destroy(uint16_t circ_id, connection_t *conn, + int reason); /********************************* control.c ***************************/ diff --git a/src/or/relay.c b/src/or/relay.c index f923ae59a3..8ec5142e7f 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -138,6 +138,8 @@ relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, * connection_edge. * - Else connection_or_write_cell_to_buf to the conn on the other * side of the circuit. + * + * Return -reason on failure. */ int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) @@ -145,6 +147,7 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) connection_t *conn=NULL; crypt_path_t *layer_hint=NULL; char recognized=0; + int reason; tor_assert(cell); tor_assert(circ); @@ -163,20 +166,21 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) if (cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; debug(LD_OR,"Sending away from origin."); - if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) { + if ((reason=connection_edge_process_relay_cell(cell, circ, conn, NULL)) + < 0) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "connection_edge_process_relay_cell (away from origin) " "failed."); - return -1; + return reason; } } if (cell_direction == CELL_DIRECTION_IN) { ++stats_n_relay_cells_delivered; debug(LD_OR,"Sending to origin."); - if (connection_edge_process_relay_cell(cell, circ, conn, - layer_hint) < 0) { + if ((reason = connection_edge_process_relay_cell(cell, circ, conn, + layer_hint)) < 0) { warn(LD_OR,"connection_edge_process_relay_cell (at origin) failed."); - return -1; + return reason; } } return 0; @@ -197,19 +201,19 @@ circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction) tor_assert(circ->rend_splice->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); cell->circ_id = circ->rend_splice->p_circ_id; - if (circuit_receive_relay_cell(cell, circ->rend_splice, - CELL_DIRECTION_IN) < 0) { + if ((reason = circuit_receive_relay_cell(cell, circ->rend_splice, + CELL_DIRECTION_IN)) < 0) { warn(LD_REND, "Error relaying cell across rendezvous; closing " "circuits"); /* XXXX Do this here, or just return -1? */ - circuit_mark_for_close(circ); - return -1; + circuit_mark_for_close(circ, -reason); + return reason; } return 0; } log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "Didn't recognize cell, but circ stops here! Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } debug(LD_OR,"Passing on unrecognized cell."); @@ -489,7 +493,7 @@ connection_edge_send_command(connection_t *fromconn, circuit_t *circ, if (circuit_package_relay_cell(&cell, circ, cell_direction, cpath_layer) < 0) { warn(LD_BUG,"circuit_package_relay_cell failed. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; } return 0; @@ -655,7 +659,7 @@ connection_edge_process_end_not_open( warn(LD_PROTOCOL, "Got an end because of %s, but we're not an AP. Closing.", connection_edge_end_reason_str(reason)); - return -1; + return - END_CIRC_REASON_TORPROTOCOL; } info(LD_APP,"Address '%s' refused due to '%s'. Considering retrying.", safe_str(conn->socks_request->address), @@ -848,7 +852,7 @@ connection_edge_process_relay_cell_not_open( * If <b>layer_hint</b> is defined, then we're the origin of the * circuit, and it specifies the hop that packaged <b>cell</b>. * - * Return -1 if you want to warn and tear down the circuit, else 0. + * Return -reason if you want to warn and tear down the circuit, else 0. */ static int connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, @@ -858,6 +862,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, static int num_seen=0; relay_header_t rh; unsigned domain = layer_hint?LD_APP:LD_EXIT; + int reason; tor_assert(cell); tor_assert(circ); @@ -869,7 +874,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (rh.length > RELAY_PAYLOAD_SIZE) { warn(LD_PROTOCOL, "Relay cell length field too long. Closing circuit."); - return -1; + return - END_CIRC_REASON_TORPROTOCOL; } /* either conn is NULL, in which case we've got a control cell, or else @@ -904,7 +909,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, connection_edge_end(conn, END_STREAM_REASON_TORPROTOCOL, conn->cpath_layer); connection_mark_for_close(conn); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } debug(domain,"circ deliver_window now %d.", layer_hint ? layer_hint->deliver_window : circ->deliver_window); @@ -919,7 +924,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (--conn->deliver_window < 0) { /* is it below 0 after decrement? */ log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "(relay data) conn deliver_window below 0. Killing."); - return -1; /* somebody's breaking protocol. kill the whole circuit. */ + return -END_CIRC_REASON_TORPROTOCOL; } stats_n_data_bytes_received += rh.length; @@ -974,14 +979,14 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } debug(domain,"Got an extended cell! Yay."); - if (circuit_finish_handshake(circ, CELL_CREATED, - cell->payload+RELAY_HEADER_SIZE) < 0) { + if ((reason = circuit_finish_handshake(circ, CELL_CREATED, + cell->payload+RELAY_HEADER_SIZE)) < 0) { warn(domain,"circuit_finish_handshake failed."); - return -1; + return reason; } - if (circuit_send_next_onion_skin(circ)<0) { + if ((reason=circuit_send_next_onion_skin(circ))<0) { info(domain,"circuit_send_next_onion_skin() failed."); - return -1; + return reason; } return 0; case RELAY_COMMAND_TRUNCATE: @@ -990,12 +995,17 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } if (circ->n_conn) { - connection_send_destroy(circ->n_circ_id, circ->n_conn); + uint8_t reason = *(uint8_t*)(cell->payload + RELAY_HEADER_SIZE); + connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason); circuit_set_circid_orconn(circ, 0, NULL, N_CONN_CHANGED); } debug(LD_EXIT, "Processed 'truncate', replying."); - connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED, - NULL, 0, NULL); + { + char payload[1]; + payload[0] = (char)END_CIRC_REASON_REQUESTED; + connection_edge_send_command(NULL, circ, RELAY_COMMAND_TRUNCATED, + payload, sizeof(payload), NULL); + } return 0; case RELAY_COMMAND_TRUNCATED: if (!layer_hint) { @@ -1008,7 +1018,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, if (conn) { log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, "'connected' unsupported while open. Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } info(domain,"'connected' received, no conn attached anymore. Ignoring."); return 0; @@ -1055,7 +1065,7 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, case RELAY_COMMAND_RESOLVED: if (conn) { warn(domain,"'resolved' unsupported while open. Closing circ."); - return -1; + return -END_CIRC_REASON_TORPROTOCOL; } info(domain,"'resolved' received, no conn attached anymore. Ignoring."); return 0; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index f80c86a2cb..3e89d8fa92 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -35,7 +35,7 @@ rend_client_send_establish_rendezvous(circuit_t *circ) if (crypto_rand(circ->rend_cookie, REND_COOKIE_LEN) < 0) { warn(LD_BUG, "Internal error: Couldn't produce random cookie."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } if (connection_edge_send_command(NULL,circ, @@ -154,8 +154,8 @@ rend_client_send_introduction(circuit_t *introcirc, circuit_t *rendcirc) return 0; err: - circuit_mark_for_close(introcirc); - circuit_mark_for_close(rendcirc); + circuit_mark_for_close(introcirc, END_CIRC_AT_ORIGIN); + circuit_mark_for_close(rendcirc, END_CIRC_AT_ORIGIN); return -1; } @@ -186,7 +186,7 @@ rend_client_introduction_acked(circuit_t *circ, if (circ->purpose != CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) { warn(LD_PROTOCOL, "Received REND_INTRODUCE_ACK on unexpected circuit %d.", circ->n_circ_id); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } @@ -208,7 +208,7 @@ rend_client_introduction_acked(circuit_t *circ, } /* close the circuit: we won't need it anymore. */ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCE_ACKED; - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); } else { /* It's a NAK; the introduction point didn't relay our request. */ circ->purpose = CIRCUIT_PURPOSE_C_INTRODUCING; @@ -226,7 +226,7 @@ rend_client_introduction_acked(circuit_t *circ, if (!extend_info) { warn(LD_REND, "No introduction points left for %s. Closing.", safe_str(circ->rend_query)); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } info(LD_REND, @@ -340,7 +340,7 @@ rend_client_rendezvous_acked(circuit_t *circ, const char *request, if (circ->purpose != CIRCUIT_PURPOSE_C_ESTABLISH_REND) { warn(LD_PROTOCOL,"Got a rendezvous ack when we weren't expecting one. " "Closing circ."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } info(LD_REND,"Got rendezvous ack. This circuit is now ready for " @@ -362,7 +362,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request, || !circ->build_state->pending_final_cpath) { warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not " "expecting it. Closing."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } @@ -408,7 +408,7 @@ rend_client_receive_rendezvous(circuit_t *circ, const char *request, circ->build_state->pending_final_cpath = NULL; /* prevent double-free */ return 0; err: - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_AT_ORIGIN); return -1; } diff --git a/src/or/rendmid.c b/src/or/rendmid.c index 4059d3e692..cf0ec0baa9 100644 --- a/src/or/rendmid.c +++ b/src/or/rendmid.c @@ -25,6 +25,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, size_t asn1len; circuit_t *c; char serviceid[REND_SERVICE_ID_LEN+1]; + int reason = END_CIRC_REASON_INTERNAL; info(LD_REND, "Received an ESTABLISH_INTRO request on circuit %d", circ->p_circ_id); @@ -32,6 +33,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) { warn(LD_PROTOCOL, "Rejecting ESTABLISH_INTRO on non-OR or non-edge circuit."); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } if (request_len < 2+DIGEST_LEN) @@ -44,6 +46,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, goto truncated; pk = crypto_pk_asn1_decode(request+2, asn1len); if (!pk) { + reason = END_CIRC_REASON_TORPROTOCOL; warn(LD_PROTOCOL, "Couldn't decode public key."); goto err; } @@ -57,6 +60,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, } if (memcmp(expected_digest, request+2+asn1len, DIGEST_LEN)) { warn(LD_PROTOCOL, "Hash of session info was not as expected."); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } /* Rest of body: signature of previous data */ @@ -65,6 +69,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, request_len-(2+DIGEST_LEN+asn1len))<0) { warn(LD_PROTOCOL, "Incorrect signature on ESTABLISH_INTRO cell; rejecting."); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -85,7 +90,7 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, c,pk_digest,CIRCUIT_PURPOSE_INTRO_POINT))) { info(LD_REND, "Replacing old circuit %d for service %s", c->p_circ_id, safe_str(serviceid)); - circuit_mark_for_close(c); + circuit_mark_for_close(c, END_CIRC_REASON_REQUESTED); } /* Acknowledge the request. */ @@ -107,9 +112,10 @@ rend_mid_establish_intro(circuit_t *circ, const char *request, return 0; truncated: warn(LD_PROTOCOL, "Rejecting truncated ESTABLISH_INTRO cell."); + reason = END_CIRC_REASON_TORPROTOCOL; err: if (pk) crypto_free_pk_env(pk); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); return -1; } @@ -168,7 +174,7 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len) if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK, NULL,0,NULL)) { warn(LD_GENERAL, "Unable to send INTRODUCE_ACK cell to Tor client."); - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); return -1; } @@ -179,7 +185,8 @@ rend_mid_introduce(circuit_t *circ, const char *request, size_t request_len) if (connection_edge_send_command(NULL,circ,RELAY_COMMAND_INTRODUCE_ACK, nak_body, 1, NULL)) { warn(LD_GENERAL, "Unable to send NAK to Tor client."); - circuit_mark_for_close(circ); /* Is this right? */ + /* Is this right? */ + circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); } return -1; } @@ -192,6 +199,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request, size_t request_len) { char hexid[9]; + int reason = END_CIRC_REASON_TORPROTOCOL; if (circ->purpose != CIRCUIT_PURPOSE_OR || circ->n_conn) { warn(LD_PROTOCOL, @@ -214,6 +222,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request, RELAY_COMMAND_RENDEZVOUS_ESTABLISHED, "", 0, NULL)<0) { warn(LD_PROTOCOL, "Couldn't send RENDEZVOUS_ESTABLISHED cell."); + reason = END_CIRC_REASON_INTERNAL; goto err; } @@ -227,7 +236,7 @@ rend_mid_establish_rendezvous(circuit_t *circ, const char *request, return 0; err: - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); return -1; } @@ -240,7 +249,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len) { circuit_t *rend_circ; char hexid[9]; - + int reason = END_CIRC_REASON_INTERNAL; base16_encode(hexid,9,request,request_len<4?request_len:4); if (request_len>=4) { @@ -252,6 +261,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len) info(LD_REND, "Tried to complete rendezvous on non-OR or non-edge circuit %d.", circ->p_circ_id); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -259,6 +269,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len) warn(LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with bad length (%d) on circuit %d.", (int)request_len, circ->p_circ_id); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -267,6 +278,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len) warn(LD_PROTOCOL, "Rejecting RENDEZVOUS1 cell with unrecognized rendezvous cookie %s.", hexid); + reason = END_CIRC_REASON_TORPROTOCOL; goto err; } @@ -295,7 +307,7 @@ rend_mid_rendezvous(circuit_t *circ, const char *request, size_t request_len) return 0; err: - circuit_mark_for_close(circ); + circuit_mark_for_close(circ, reason); return -1; } diff --git a/src/or/rendservice.c b/src/or/rendservice.c index 81762c43a5..85da116038 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -605,7 +605,7 @@ rend_service_introduce(circuit_t *circuit, const char *request, return 0; err: if (dh) crypto_dh_free(dh); - if (launched) circuit_mark_for_close(launched); + if (launched) circuit_mark_for_close(launched, END_CIRC_AT_ORIGIN); if (extend_info) extend_info_free(extend_info); return -1; } @@ -751,7 +751,7 @@ rend_service_intro_has_opened(circuit_t *circuit) return; err: - circuit_mark_for_close(circuit); + circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN); } /** Called when we get an INTRO_ESTABLISHED cell; mark the circuit as a @@ -778,7 +778,7 @@ rend_service_intro_established(circuit_t *circuit, const char *request, return 0; err: - circuit_mark_for_close(circuit); + circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN); return -1; } @@ -852,7 +852,7 @@ rend_service_rendezvous_has_opened(circuit_t *circuit) return; err: - circuit_mark_for_close(circuit); + circuit_mark_for_close(circuit, END_CIRC_AT_ORIGIN); } /* |