mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-23 14:40:51 +01:00
Add reasons to DESTROY and RELAY_TRUNCATED cells.
svn:r5734
This commit is contained in:
parent
d8e3bc0288
commit
878962bee1
17 changed files with 234 additions and 141 deletions
13
doc/TODO
13
doc/TODO
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
25
src/or/or.h
25
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 ***************************/
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Add table
Reference in a new issue