Loading src/or/Makefile.am +2 −3 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ bin_PROGRAMS = tor tor_SOURCES = buffers.c circuit.c command.c config.c \ connection.c connection_edge.c connection_or.c \ cpuworker.c directory.c dirserv.c dns.c main.c \ onion.c rendcommon.c rendclient.c rendmid.c \ onion.c relay.c rendcommon.c rendclient.c rendmid.c \ rendservice.c rephist.c router.c routerlist.c routerparse.c \ tor_main.c Loading @@ -16,7 +16,7 @@ tor_LDADD = ../common/libor.a test_SOURCES = buffers.c circuit.c command.c config.c \ connection.c connection_edge.c connection_or.c \ cpuworker.c directory.c dirserv.c dns.c main.c \ onion.c rendcommon.c rendclient.c rendmid.c \ onion.c relay.c rendcommon.c rendclient.c rendmid.c \ rendservice.c rephist.c router.c routerlist.c routerparse.c \ test.c Loading @@ -24,4 +24,3 @@ test_LDADD = ../common/libor.a noinst_HEADERS = or.h tree.h src/or/circuit.c +1 −339 Original line number Diff line number Diff line Loading @@ -4,17 +4,13 @@ /** * \file circuit.c * \brief Manage circuits and the global circuit list. Also handle * relay cell encryption/decryption. * \brief Manage circuits and the global circuit list. **/ #include "or.h" extern or_options_t options; /* command-line and config-file options */ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, crypt_path_t **layer_hint, char *recognized); static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction); static int circuit_resume_edge_reading_helper(connection_t *conn, circuit_t *circ, crypt_path_t *layer_hint); Loading @@ -27,15 +23,6 @@ static void circuit_is_open(circuit_t *circ); static void circuit_build_failed(circuit_t *circ); static circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_nickname); /** Stats: how many relay cells have originated at this hop, or have * been relayed onward (not recognized at this hop)? */ unsigned long stats_n_relay_cells_relayed = 0; /** Stats: how many relay cells have been delivered to streams at this * hop? */ unsigned long stats_n_relay_cells_delivered = 0; /********* START VARIABLES **********/ /** A global (within this file) list of all circuits at this hop. */ Loading Loading @@ -675,331 +662,6 @@ void circuit_build_needed_circs(time_t now) { /* XXX count idle rendezvous circs and build more */ } /** Update digest from the payload of cell. Assign integrity part to * cell. */ static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { char integrity[4]; relay_header_t rh; crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, integrity, 4); // log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.", // integrity[0], integrity[1], integrity[2], integrity[3]); relay_header_unpack(&rh, cell->payload); memcpy(rh.integrity, integrity, 4); relay_header_pack(cell->payload, &rh); } /** Does the digest for this circuit indicate that this cell is for us? * * Update digest from the payload of cell (with the integrity part set * to 0). If the integrity part is valid, return 1, else restore digest * and cell to their original state and return 0. */ static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) { char received_integrity[4], calculated_integrity[4]; relay_header_t rh; crypto_digest_env_t *backup_digest=NULL; backup_digest = crypto_digest_dup(digest); relay_header_unpack(&rh, cell->payload); memcpy(received_integrity, rh.integrity, 4); memset(rh.integrity, 0, 4); relay_header_pack(cell->payload, &rh); // log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.", // received_integrity[0], received_integrity[1], // received_integrity[2], received_integrity[3]); crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, calculated_integrity, 4); if(memcmp(received_integrity, calculated_integrity, 4)) { // log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing."); // (%d vs %d).", received_integrity, calculated_integrity); /* restore digest to its old form */ crypto_digest_assign(digest, backup_digest); /* restore the relay header */ memcpy(rh.integrity, received_integrity, 4); relay_header_pack(cell->payload, &rh); crypto_free_digest_env(backup_digest); return 0; } crypto_free_digest_env(backup_digest); return 1; } /** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b> * (in place). * * If <b>encrypt_mode</b> is 1 then encrypt, else decrypt. * * Return -1 if the crypto fails, else return 0. */ static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, int encrypt_mode) { char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */ relay_header_t rh; relay_header_unpack(&rh, in); // log_fn(LOG_DEBUG,"before crypt: %d",rh.recognized); if(( encrypt_mode && crypto_cipher_encrypt(cipher, in, CELL_PAYLOAD_SIZE, out)) || (!encrypt_mode && crypto_cipher_decrypt(cipher, in, CELL_PAYLOAD_SIZE, out))) { log_fn(LOG_WARN,"Error during relay encryption"); return -1; } memcpy(in,out,CELL_PAYLOAD_SIZE); relay_header_unpack(&rh, in); // log_fn(LOG_DEBUG,"after crypt: %d",rh.recognized); return 0; } /** Receive a relay cell: * - Crypt it (encrypt APward, decrypt at AP, decrypt exitward). * - Check if recognized (if exitward). * - If recognized and the digest checks out, then find if there's * a conn that the cell is intended for, and deliver it to * connection_edge. * - Else connection_or_write_cell_to_buf to the conn on the other * side of the circuit. */ int 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; tor_assert(cell && circ); tor_assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); if (circ->marked_for_close) return 0; if(relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) { log_fn(LOG_WARN,"relay crypt failed. Dropping connection."); return -1; } if(recognized) { conn = relay_lookup_conn(circ, cell, cell_direction); if(cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; log_fn(LOG_DEBUG,"Sending away from origin."); if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) { log_fn(LOG_WARN,"connection_edge_process_relay_cell (away from origin) failed."); return -1; } } if(cell_direction == CELL_DIRECTION_IN) { ++stats_n_relay_cells_delivered; log_fn(LOG_DEBUG,"Sending to origin."); if (connection_edge_process_relay_cell(cell, circ, conn, layer_hint) < 0) { log_fn(LOG_WARN,"connection_edge_process_relay_cell (at origin) failed."); return -1; } } return 0; } /* not recognized. pass it on. */ if(cell_direction == CELL_DIRECTION_OUT) { cell->circ_id = circ->n_circ_id; /* switch it */ conn = circ->n_conn; } else { cell->circ_id = circ->p_circ_id; /* switch it */ conn = circ->p_conn; } if(!conn) { if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) { tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); 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) { log_fn(LOG_WARN, "Error relaying cell across rendezvous; closing circuits"); circuit_mark_for_close(circ); /* XXXX Do this here, or just return -1? */ return -1; } return 0; } log_fn(LOG_WARN,"Didn't recognize cell, but circ stops here! Closing circ."); return -1; } log_fn(LOG_DEBUG,"Passing on unrecognized cell."); ++stats_n_relay_cells_relayed; connection_or_write_cell_to_buf(cell, conn); return 0; } /** Do the appropriate en/decryptions for <b>cell</b> arriving on * <b>circ</b> in direction <b>cell_direction</b>. * * If cell_direction == CELL_DIRECTION_IN: * - If we're at the origin (we're the OP), for hops 1..N, * decrypt cell. If recognized, stop. * - Else (we're not the OP), encrypt one hop. Cell is not recognized. * * If cell_direction == CELL_DIRECTION_OUT: * - decrypt one hop. Check if recognized. * * If cell is recognized, set *recognized to 1, and set * *layer_hint to the hop that recognized it. * * Return -1 to indicate that we should mark the circuit for close, * else return 0. */ /* wrap this into receive_relay_cell one day */ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, crypt_path_t **layer_hint, char *recognized) { crypt_path_t *thishop; relay_header_t rh; tor_assert(circ && cell && recognized); tor_assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT); if(cell_direction == CELL_DIRECTION_IN) { if(CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit. We'll want to do layered decrypts. */ tor_assert(circ->cpath); thishop = circ->cpath; if(thishop->state != CPATH_STATE_OPEN) { log_fn(LOG_WARN,"Relay cell before first created cell? Closing."); return -1; } do { /* Remember: cpath is in forward order, that is, first hop first. */ tor_assert(thishop); if(relay_crypt_one_payload(thishop->b_crypto, cell->payload, 0) < 0) return -1; relay_header_unpack(&rh, cell->payload); if(rh.recognized == 0) { /* it's possibly recognized. have to check digest to be sure. */ if(relay_digest_matches(thishop->b_digest, cell)) { *recognized = 1; *layer_hint = thishop; return 0; } } thishop = thishop->next; } while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN); log_fn(LOG_WARN,"in-cell at OP not recognized. Closing."); return -1; } else { /* we're in the middle. Just one crypt. */ if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0) return -1; // log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP."); } } else /* cell_direction == CELL_DIRECTION_OUT */ { /* we're in the middle. Just one crypt. */ if(relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0) return -1; relay_header_unpack(&rh, cell->payload); if (rh.recognized == 0) { /* it's possibly recognized. have to check digest to be sure. */ if(relay_digest_matches(circ->n_digest, cell)) { *recognized = 1; return 0; } } } return 0; } /** Package a relay cell: * - Encrypt it to the right layer * - connection_or_write_cell_to_buf to the right conn */ int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint) { connection_t *conn; /* where to send the cell */ crypt_path_t *thishop; /* counter for repeated crypts */ if(cell_direction == CELL_DIRECTION_OUT) { conn = circ->n_conn; if(!conn) { log_fn(LOG_WARN,"outgoing relay cell has n_conn==NULL. Dropping."); return 0; /* just drop it */ } relay_set_digest(layer_hint->f_digest, cell); thishop = layer_hint; /* moving from farthest to nearest hop */ do { tor_assert(thishop); log_fn(LOG_DEBUG,"crypting a layer of the relay cell."); if(relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) { return -1; } thishop = thishop->prev; } while (thishop != circ->cpath->prev); } else { /* incoming cell */ conn = circ->p_conn; if(!conn) { log_fn(LOG_WARN,"incoming relay cell has p_conn==NULL. Dropping."); return 0; /* just drop it */ } relay_set_digest(circ->p_digest, cell); if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0) return -1; } ++stats_n_relay_cells_relayed; connection_or_write_cell_to_buf(cell, conn); return 0; } /** If cell's stream_id matches the stream_id of any conn that's * attached to circ, return that conn, else return NULL. */ static connection_t * relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) { connection_t *tmpconn; relay_header_t rh; relay_header_unpack(&rh, cell->payload); if(!rh.stream_id) return NULL; /* IN or OUT cells could have come from either direction, now * that we allow rendezvous *to* an OP. */ for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); if(cell_direction == CELL_DIRECTION_OUT || connection_edge_is_rendezvous_stream(tmpconn)) return tmpconn; } } for(tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); return tmpconn; } } for(tmpconn = circ->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); return tmpconn; } } return NULL; /* probably a begin relay cell */ } /** The circuit <b>circ</b> has received a circuit-level sendme * (on hop <b>layer_hint</b>, if we're the OP). Go through all the * attached streams and let them resume reading and packaging, if Loading src/or/connection.c +4 −2 Original line number Diff line number Diff line Loading @@ -852,11 +852,12 @@ int connection_handle_write(connection_t *conn) { } } if(!connection_wants_to_flush(conn)) /* it's done flushing */ if(connection_finished_flushing(conn) < 0) { /* ...and get handled here. */ if(!connection_wants_to_flush(conn)) { /* it's done flushing */ if(connection_finished_flushing(conn) < 0) { /* already marked */ return -1; } } return 0; } Loading Loading @@ -1053,6 +1054,7 @@ int connection_state_is_open(connection_t *conn) { return 0; } /** Return 1 if conn is in 'connecting' state, else return 0. */ int connection_state_is_connecting(connection_t *conn) { tor_assert(conn); Loading src/or/directory.c +0 −1 Original line number Diff line number Diff line Loading @@ -527,7 +527,6 @@ static int directory_handle_command(connection_t *conn) { * appropriate. */ int connection_dir_finished_flushing(connection_t *conn) { int e, len=sizeof(e); tor_assert(conn && conn->type == CONN_TYPE_DIR); Loading src/or/or.h +83 −82 Original line number Diff line number Diff line Loading @@ -897,11 +897,6 @@ int circuit_count_building(uint8_t purpose); int circuit_stream_is_being_handled(connection_t *conn); void circuit_build_needed_circs(time_t now); int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction); int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint); void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint); Loading @@ -928,9 +923,6 @@ void assert_cpath_ok(const crypt_path_t *c); void assert_cpath_layer_ok(const crypt_path_t *c); void assert_circuit_ok(const circuit_t *c); extern unsigned long stats_n_relay_cells_relayed; extern unsigned long stats_n_relay_cells_delivered; /********************************* command.c ***************************/ void command_process_cell(cell_t *cell, connection_t *conn); Loading Loading @@ -1090,6 +1082,20 @@ int connection_dir_process_inbuf(connection_t *conn); int connection_dir_finished_flushing(connection_t *conn); int connection_dir_finished_connecting(connection_t *conn); /********************************* dirserv.c ***************************/ int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_parse_fingerprint_file(const char *fname); int dirserv_router_fingerprint_is_known(const routerinfo_t *router); void dirserv_free_fingerprint_list(); int dirserv_add_descriptor(const char **desc); int dirserv_init_from_directory_string(const char *dir); void dirserv_free_descriptors(); int dirserv_dump_directory_to_string(char *s, unsigned int maxlen, crypto_pk_env_t *private_key); void directory_set_dirty(void); size_t dirserv_get_directory(const char **cp); void dirserv_remove_old_servers(void); /********************************* dns.c ***************************/ void dns_init(void); Loading Loading @@ -1155,82 +1161,15 @@ int onion_skin_client_handshake(crypto_dh_env_t *handshake_state, cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname); /********************************* router.c ***************************/ void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); crypto_pk_env_t *get_previous_onion_key(void); time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); int init_keys(void); crypto_pk_env_t *init_key_from_file(const char *fname); void rotate_onion_key(void); void router_retry_connections(void); void router_upload_dir_desc_to_dirservers(void); void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len); int router_compare_to_my_exit_policy(connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); const char *router_get_my_descriptor(void); int router_is_me(routerinfo_t *router); int router_rebuild_descriptor(void); int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); /********************************* routerlist.c ***************************/ routerinfo_t *router_pick_directory_server(void); struct smartlist_t; routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded, struct smartlist_t *excludedsmartlist); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_nickname(char *nickname); void router_get_routerlist(routerlist_t **prouterlist); void routerlist_free(routerlist_t *routerlist); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); void router_mark_as_down(char *nickname); int router_set_routerlist_from_file(char *routerfile); int router_set_routerlist_from_string(const char *s); int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey); int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port, struct exit_policy_t *policy); #define ADDR_POLICY_ACCEPTED 0 #define ADDR_POLICY_REJECTED -1 #define ADDR_POLICY_UNKNOWN 1 int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port); int router_exit_policy_rejects_all(routerinfo_t *router); /********************************* routerparse.c ************************/ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_parse_list_from_string(const char **s, routerlist_t **dest, int n_good_nicknames, const char **good_nickname_lst); int router_parse_routerlist_from_directory(const char *s, routerlist_t **dest, crypto_pk_env_t *pkey); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end); int router_add_exit_policy_from_string(routerinfo_t *router, const char *s); /********************************* relay.c ***************************/ /********************************* dirserv.c ***************************/ int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_parse_fingerprint_file(const char *fname); int dirserv_router_fingerprint_is_known(const routerinfo_t *router); void dirserv_free_fingerprint_list(); int dirserv_add_descriptor(const char **desc); int dirserv_init_from_directory_string(const char *dir); void dirserv_free_descriptors(); int dirserv_dump_directory_to_string(char *s, unsigned int maxlen, crypto_pk_env_t *private_key); void directory_set_dirty(void); size_t dirserv_get_directory(const char **cp); void dirserv_remove_old_servers(void); extern unsigned long stats_n_relay_cells_relayed; extern unsigned long stats_n_relay_cells_delivered; int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction); int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint); /********************************* rephist.c ***************************/ Loading Loading @@ -1318,6 +1257,68 @@ int rend_mid_introduce(circuit_t *circ, const char *request, int request_len); int rend_mid_establish_rendezvous(circuit_t *circ, const char *request, int request_len); int rend_mid_rendezvous(circuit_t *circ, const char *request, int request_len); /********************************* router.c ***************************/ void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); crypto_pk_env_t *get_previous_onion_key(void); time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); int init_keys(void); crypto_pk_env_t *init_key_from_file(const char *fname); void rotate_onion_key(void); void router_retry_connections(void); void router_upload_dir_desc_to_dirservers(void); void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len); int router_compare_to_my_exit_policy(connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); const char *router_get_my_descriptor(void); int router_is_me(routerinfo_t *router); int router_rebuild_descriptor(void); int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); /********************************* routerlist.c ***************************/ routerinfo_t *router_pick_directory_server(void); struct smartlist_t; routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded, struct smartlist_t *excludedsmartlist); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_nickname(char *nickname); void router_get_routerlist(routerlist_t **prouterlist); void routerlist_free(routerlist_t *routerlist); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); void router_mark_as_down(char *nickname); int router_set_routerlist_from_file(char *routerfile); int router_set_routerlist_from_string(const char *s); int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey); int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port, struct exit_policy_t *policy); #define ADDR_POLICY_ACCEPTED 0 #define ADDR_POLICY_REJECTED -1 #define ADDR_POLICY_UNKNOWN 1 int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port); int router_exit_policy_rejects_all(routerinfo_t *router); /********************************* routerparse.c ************************/ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_parse_list_from_string(const char **s, routerlist_t **dest, int n_good_nicknames, const char **good_nickname_lst); int router_parse_routerlist_from_directory(const char *s, routerlist_t **dest, crypto_pk_env_t *pkey); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end); int router_add_exit_policy_from_string(routerinfo_t *router, const char *s); #endif /* Loading Loading
src/or/Makefile.am +2 −3 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ bin_PROGRAMS = tor tor_SOURCES = buffers.c circuit.c command.c config.c \ connection.c connection_edge.c connection_or.c \ cpuworker.c directory.c dirserv.c dns.c main.c \ onion.c rendcommon.c rendclient.c rendmid.c \ onion.c relay.c rendcommon.c rendclient.c rendmid.c \ rendservice.c rephist.c router.c routerlist.c routerparse.c \ tor_main.c Loading @@ -16,7 +16,7 @@ tor_LDADD = ../common/libor.a test_SOURCES = buffers.c circuit.c command.c config.c \ connection.c connection_edge.c connection_or.c \ cpuworker.c directory.c dirserv.c dns.c main.c \ onion.c rendcommon.c rendclient.c rendmid.c \ onion.c relay.c rendcommon.c rendclient.c rendmid.c \ rendservice.c rephist.c router.c routerlist.c routerparse.c \ test.c Loading @@ -24,4 +24,3 @@ test_LDADD = ../common/libor.a noinst_HEADERS = or.h tree.h
src/or/circuit.c +1 −339 Original line number Diff line number Diff line Loading @@ -4,17 +4,13 @@ /** * \file circuit.c * \brief Manage circuits and the global circuit list. Also handle * relay cell encryption/decryption. * \brief Manage circuits and the global circuit list. **/ #include "or.h" extern or_options_t options; /* command-line and config-file options */ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, crypt_path_t **layer_hint, char *recognized); static connection_t *relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction); static int circuit_resume_edge_reading_helper(connection_t *conn, circuit_t *circ, crypt_path_t *layer_hint); Loading @@ -27,15 +23,6 @@ static void circuit_is_open(circuit_t *circ); static void circuit_build_failed(circuit_t *circ); static circuit_t *circuit_establish_circuit(uint8_t purpose, const char *exit_nickname); /** Stats: how many relay cells have originated at this hop, or have * been relayed onward (not recognized at this hop)? */ unsigned long stats_n_relay_cells_relayed = 0; /** Stats: how many relay cells have been delivered to streams at this * hop? */ unsigned long stats_n_relay_cells_delivered = 0; /********* START VARIABLES **********/ /** A global (within this file) list of all circuits at this hop. */ Loading Loading @@ -675,331 +662,6 @@ void circuit_build_needed_circs(time_t now) { /* XXX count idle rendezvous circs and build more */ } /** Update digest from the payload of cell. Assign integrity part to * cell. */ static void relay_set_digest(crypto_digest_env_t *digest, cell_t *cell) { char integrity[4]; relay_header_t rh; crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, integrity, 4); // log_fn(LOG_DEBUG,"Putting digest of %u %u %u %u into relay cell.", // integrity[0], integrity[1], integrity[2], integrity[3]); relay_header_unpack(&rh, cell->payload); memcpy(rh.integrity, integrity, 4); relay_header_pack(cell->payload, &rh); } /** Does the digest for this circuit indicate that this cell is for us? * * Update digest from the payload of cell (with the integrity part set * to 0). If the integrity part is valid, return 1, else restore digest * and cell to their original state and return 0. */ static int relay_digest_matches(crypto_digest_env_t *digest, cell_t *cell) { char received_integrity[4], calculated_integrity[4]; relay_header_t rh; crypto_digest_env_t *backup_digest=NULL; backup_digest = crypto_digest_dup(digest); relay_header_unpack(&rh, cell->payload); memcpy(received_integrity, rh.integrity, 4); memset(rh.integrity, 0, 4); relay_header_pack(cell->payload, &rh); // log_fn(LOG_DEBUG,"Reading digest of %u %u %u %u from relay cell.", // received_integrity[0], received_integrity[1], // received_integrity[2], received_integrity[3]); crypto_digest_add_bytes(digest, cell->payload, CELL_PAYLOAD_SIZE); crypto_digest_get_digest(digest, calculated_integrity, 4); if(memcmp(received_integrity, calculated_integrity, 4)) { // log_fn(LOG_INFO,"Recognized=0 but bad digest. Not recognizing."); // (%d vs %d).", received_integrity, calculated_integrity); /* restore digest to its old form */ crypto_digest_assign(digest, backup_digest); /* restore the relay header */ memcpy(rh.integrity, received_integrity, 4); relay_header_pack(cell->payload, &rh); crypto_free_digest_env(backup_digest); return 0; } crypto_free_digest_env(backup_digest); return 1; } /** Apply <b>cipher</b> to CELL_PAYLOAD_SIZE bytes of <b>in</b> * (in place). * * If <b>encrypt_mode</b> is 1 then encrypt, else decrypt. * * Return -1 if the crypto fails, else return 0. */ static int relay_crypt_one_payload(crypto_cipher_env_t *cipher, char *in, int encrypt_mode) { char out[CELL_PAYLOAD_SIZE]; /* 'in' must be this size too */ relay_header_t rh; relay_header_unpack(&rh, in); // log_fn(LOG_DEBUG,"before crypt: %d",rh.recognized); if(( encrypt_mode && crypto_cipher_encrypt(cipher, in, CELL_PAYLOAD_SIZE, out)) || (!encrypt_mode && crypto_cipher_decrypt(cipher, in, CELL_PAYLOAD_SIZE, out))) { log_fn(LOG_WARN,"Error during relay encryption"); return -1; } memcpy(in,out,CELL_PAYLOAD_SIZE); relay_header_unpack(&rh, in); // log_fn(LOG_DEBUG,"after crypt: %d",rh.recognized); return 0; } /** Receive a relay cell: * - Crypt it (encrypt APward, decrypt at AP, decrypt exitward). * - Check if recognized (if exitward). * - If recognized and the digest checks out, then find if there's * a conn that the cell is intended for, and deliver it to * connection_edge. * - Else connection_or_write_cell_to_buf to the conn on the other * side of the circuit. */ int 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; tor_assert(cell && circ); tor_assert(cell_direction == CELL_DIRECTION_OUT || cell_direction == CELL_DIRECTION_IN); if (circ->marked_for_close) return 0; if(relay_crypt(circ, cell, cell_direction, &layer_hint, &recognized) < 0) { log_fn(LOG_WARN,"relay crypt failed. Dropping connection."); return -1; } if(recognized) { conn = relay_lookup_conn(circ, cell, cell_direction); if(cell_direction == CELL_DIRECTION_OUT) { ++stats_n_relay_cells_delivered; log_fn(LOG_DEBUG,"Sending away from origin."); if (connection_edge_process_relay_cell(cell, circ, conn, NULL) < 0) { log_fn(LOG_WARN,"connection_edge_process_relay_cell (away from origin) failed."); return -1; } } if(cell_direction == CELL_DIRECTION_IN) { ++stats_n_relay_cells_delivered; log_fn(LOG_DEBUG,"Sending to origin."); if (connection_edge_process_relay_cell(cell, circ, conn, layer_hint) < 0) { log_fn(LOG_WARN,"connection_edge_process_relay_cell (at origin) failed."); return -1; } } return 0; } /* not recognized. pass it on. */ if(cell_direction == CELL_DIRECTION_OUT) { cell->circ_id = circ->n_circ_id; /* switch it */ conn = circ->n_conn; } else { cell->circ_id = circ->p_circ_id; /* switch it */ conn = circ->p_conn; } if(!conn) { if (circ->rend_splice && cell_direction == CELL_DIRECTION_OUT) { tor_assert(circ->purpose == CIRCUIT_PURPOSE_REND_ESTABLISHED); 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) { log_fn(LOG_WARN, "Error relaying cell across rendezvous; closing circuits"); circuit_mark_for_close(circ); /* XXXX Do this here, or just return -1? */ return -1; } return 0; } log_fn(LOG_WARN,"Didn't recognize cell, but circ stops here! Closing circ."); return -1; } log_fn(LOG_DEBUG,"Passing on unrecognized cell."); ++stats_n_relay_cells_relayed; connection_or_write_cell_to_buf(cell, conn); return 0; } /** Do the appropriate en/decryptions for <b>cell</b> arriving on * <b>circ</b> in direction <b>cell_direction</b>. * * If cell_direction == CELL_DIRECTION_IN: * - If we're at the origin (we're the OP), for hops 1..N, * decrypt cell. If recognized, stop. * - Else (we're not the OP), encrypt one hop. Cell is not recognized. * * If cell_direction == CELL_DIRECTION_OUT: * - decrypt one hop. Check if recognized. * * If cell is recognized, set *recognized to 1, and set * *layer_hint to the hop that recognized it. * * Return -1 to indicate that we should mark the circuit for close, * else return 0. */ /* wrap this into receive_relay_cell one day */ static int relay_crypt(circuit_t *circ, cell_t *cell, int cell_direction, crypt_path_t **layer_hint, char *recognized) { crypt_path_t *thishop; relay_header_t rh; tor_assert(circ && cell && recognized); tor_assert(cell_direction == CELL_DIRECTION_IN || cell_direction == CELL_DIRECTION_OUT); if(cell_direction == CELL_DIRECTION_IN) { if(CIRCUIT_IS_ORIGIN(circ)) { /* We're at the beginning of the circuit. We'll want to do layered decrypts. */ tor_assert(circ->cpath); thishop = circ->cpath; if(thishop->state != CPATH_STATE_OPEN) { log_fn(LOG_WARN,"Relay cell before first created cell? Closing."); return -1; } do { /* Remember: cpath is in forward order, that is, first hop first. */ tor_assert(thishop); if(relay_crypt_one_payload(thishop->b_crypto, cell->payload, 0) < 0) return -1; relay_header_unpack(&rh, cell->payload); if(rh.recognized == 0) { /* it's possibly recognized. have to check digest to be sure. */ if(relay_digest_matches(thishop->b_digest, cell)) { *recognized = 1; *layer_hint = thishop; return 0; } } thishop = thishop->next; } while(thishop != circ->cpath && thishop->state == CPATH_STATE_OPEN); log_fn(LOG_WARN,"in-cell at OP not recognized. Closing."); return -1; } else { /* we're in the middle. Just one crypt. */ if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0) return -1; // log_fn(LOG_DEBUG,"Skipping recognized check, because we're not the OP."); } } else /* cell_direction == CELL_DIRECTION_OUT */ { /* we're in the middle. Just one crypt. */ if(relay_crypt_one_payload(circ->n_crypto, cell->payload, 0) < 0) return -1; relay_header_unpack(&rh, cell->payload); if (rh.recognized == 0) { /* it's possibly recognized. have to check digest to be sure. */ if(relay_digest_matches(circ->n_digest, cell)) { *recognized = 1; return 0; } } } return 0; } /** Package a relay cell: * - Encrypt it to the right layer * - connection_or_write_cell_to_buf to the right conn */ int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint) { connection_t *conn; /* where to send the cell */ crypt_path_t *thishop; /* counter for repeated crypts */ if(cell_direction == CELL_DIRECTION_OUT) { conn = circ->n_conn; if(!conn) { log_fn(LOG_WARN,"outgoing relay cell has n_conn==NULL. Dropping."); return 0; /* just drop it */ } relay_set_digest(layer_hint->f_digest, cell); thishop = layer_hint; /* moving from farthest to nearest hop */ do { tor_assert(thishop); log_fn(LOG_DEBUG,"crypting a layer of the relay cell."); if(relay_crypt_one_payload(thishop->f_crypto, cell->payload, 1) < 0) { return -1; } thishop = thishop->prev; } while (thishop != circ->cpath->prev); } else { /* incoming cell */ conn = circ->p_conn; if(!conn) { log_fn(LOG_WARN,"incoming relay cell has p_conn==NULL. Dropping."); return 0; /* just drop it */ } relay_set_digest(circ->p_digest, cell); if(relay_crypt_one_payload(circ->p_crypto, cell->payload, 1) < 0) return -1; } ++stats_n_relay_cells_relayed; connection_or_write_cell_to_buf(cell, conn); return 0; } /** If cell's stream_id matches the stream_id of any conn that's * attached to circ, return that conn, else return NULL. */ static connection_t * relay_lookup_conn(circuit_t *circ, cell_t *cell, int cell_direction) { connection_t *tmpconn; relay_header_t rh; relay_header_unpack(&rh, cell->payload); if(!rh.stream_id) return NULL; /* IN or OUT cells could have come from either direction, now * that we allow rendezvous *to* an OP. */ for(tmpconn = circ->n_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); if(cell_direction == CELL_DIRECTION_OUT || connection_edge_is_rendezvous_stream(tmpconn)) return tmpconn; } } for(tmpconn = circ->p_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); return tmpconn; } } for(tmpconn = circ->resolving_streams; tmpconn; tmpconn=tmpconn->next_stream) { if(rh.stream_id == tmpconn->stream_id) { log_fn(LOG_DEBUG,"found conn for stream %d.", rh.stream_id); return tmpconn; } } return NULL; /* probably a begin relay cell */ } /** The circuit <b>circ</b> has received a circuit-level sendme * (on hop <b>layer_hint</b>, if we're the OP). Go through all the * attached streams and let them resume reading and packaging, if Loading
src/or/connection.c +4 −2 Original line number Diff line number Diff line Loading @@ -852,11 +852,12 @@ int connection_handle_write(connection_t *conn) { } } if(!connection_wants_to_flush(conn)) /* it's done flushing */ if(connection_finished_flushing(conn) < 0) { /* ...and get handled here. */ if(!connection_wants_to_flush(conn)) { /* it's done flushing */ if(connection_finished_flushing(conn) < 0) { /* already marked */ return -1; } } return 0; } Loading Loading @@ -1053,6 +1054,7 @@ int connection_state_is_open(connection_t *conn) { return 0; } /** Return 1 if conn is in 'connecting' state, else return 0. */ int connection_state_is_connecting(connection_t *conn) { tor_assert(conn); Loading
src/or/directory.c +0 −1 Original line number Diff line number Diff line Loading @@ -527,7 +527,6 @@ static int directory_handle_command(connection_t *conn) { * appropriate. */ int connection_dir_finished_flushing(connection_t *conn) { int e, len=sizeof(e); tor_assert(conn && conn->type == CONN_TYPE_DIR); Loading
src/or/or.h +83 −82 Original line number Diff line number Diff line Loading @@ -897,11 +897,6 @@ int circuit_count_building(uint8_t purpose); int circuit_stream_is_being_handled(connection_t *conn); void circuit_build_needed_circs(time_t now); int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction); int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint); void circuit_resume_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); int circuit_consider_stop_edge_reading(circuit_t *circ, crypt_path_t *layer_hint); void circuit_consider_sending_sendme(circuit_t *circ, crypt_path_t *layer_hint); Loading @@ -928,9 +923,6 @@ void assert_cpath_ok(const crypt_path_t *c); void assert_cpath_layer_ok(const crypt_path_t *c); void assert_circuit_ok(const circuit_t *c); extern unsigned long stats_n_relay_cells_relayed; extern unsigned long stats_n_relay_cells_delivered; /********************************* command.c ***************************/ void command_process_cell(cell_t *cell, connection_t *conn); Loading Loading @@ -1090,6 +1082,20 @@ int connection_dir_process_inbuf(connection_t *conn); int connection_dir_finished_flushing(connection_t *conn); int connection_dir_finished_connecting(connection_t *conn); /********************************* dirserv.c ***************************/ int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_parse_fingerprint_file(const char *fname); int dirserv_router_fingerprint_is_known(const routerinfo_t *router); void dirserv_free_fingerprint_list(); int dirserv_add_descriptor(const char **desc); int dirserv_init_from_directory_string(const char *dir); void dirserv_free_descriptors(); int dirserv_dump_directory_to_string(char *s, unsigned int maxlen, crypto_pk_env_t *private_key); void directory_set_dirty(void); size_t dirserv_get_directory(const char **cp); void dirserv_remove_old_servers(void); /********************************* dns.c ***************************/ void dns_init(void); Loading Loading @@ -1155,82 +1161,15 @@ int onion_skin_client_handshake(crypto_dh_env_t *handshake_state, cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose, const char *exit_nickname); /********************************* router.c ***************************/ void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); crypto_pk_env_t *get_previous_onion_key(void); time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); int init_keys(void); crypto_pk_env_t *init_key_from_file(const char *fname); void rotate_onion_key(void); void router_retry_connections(void); void router_upload_dir_desc_to_dirservers(void); void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len); int router_compare_to_my_exit_policy(connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); const char *router_get_my_descriptor(void); int router_is_me(routerinfo_t *router); int router_rebuild_descriptor(void); int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); /********************************* routerlist.c ***************************/ routerinfo_t *router_pick_directory_server(void); struct smartlist_t; routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded, struct smartlist_t *excludedsmartlist); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_nickname(char *nickname); void router_get_routerlist(routerlist_t **prouterlist); void routerlist_free(routerlist_t *routerlist); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); void router_mark_as_down(char *nickname); int router_set_routerlist_from_file(char *routerfile); int router_set_routerlist_from_string(const char *s); int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey); int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port, struct exit_policy_t *policy); #define ADDR_POLICY_ACCEPTED 0 #define ADDR_POLICY_REJECTED -1 #define ADDR_POLICY_UNKNOWN 1 int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port); int router_exit_policy_rejects_all(routerinfo_t *router); /********************************* routerparse.c ************************/ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_parse_list_from_string(const char **s, routerlist_t **dest, int n_good_nicknames, const char **good_nickname_lst); int router_parse_routerlist_from_directory(const char *s, routerlist_t **dest, crypto_pk_env_t *pkey); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end); int router_add_exit_policy_from_string(routerinfo_t *router, const char *s); /********************************* relay.c ***************************/ /********************************* dirserv.c ***************************/ int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk); int dirserv_parse_fingerprint_file(const char *fname); int dirserv_router_fingerprint_is_known(const routerinfo_t *router); void dirserv_free_fingerprint_list(); int dirserv_add_descriptor(const char **desc); int dirserv_init_from_directory_string(const char *dir); void dirserv_free_descriptors(); int dirserv_dump_directory_to_string(char *s, unsigned int maxlen, crypto_pk_env_t *private_key); void directory_set_dirty(void); size_t dirserv_get_directory(const char **cp); void dirserv_remove_old_servers(void); extern unsigned long stats_n_relay_cells_relayed; extern unsigned long stats_n_relay_cells_delivered; int circuit_receive_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction); int circuit_package_relay_cell(cell_t *cell, circuit_t *circ, int cell_direction, crypt_path_t *layer_hint); /********************************* rephist.c ***************************/ Loading Loading @@ -1318,6 +1257,68 @@ int rend_mid_introduce(circuit_t *circ, const char *request, int request_len); int rend_mid_establish_rendezvous(circuit_t *circ, const char *request, int request_len); int rend_mid_rendezvous(circuit_t *circ, const char *request, int request_len); /********************************* router.c ***************************/ void set_onion_key(crypto_pk_env_t *k); crypto_pk_env_t *get_onion_key(void); crypto_pk_env_t *get_previous_onion_key(void); time_t get_onion_key_set_at(void); void set_identity_key(crypto_pk_env_t *k); crypto_pk_env_t *get_identity_key(void); int init_keys(void); crypto_pk_env_t *init_key_from_file(const char *fname); void rotate_onion_key(void); void router_retry_connections(void); void router_upload_dir_desc_to_dirservers(void); void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload_len); int router_compare_to_my_exit_policy(connection_t *conn); routerinfo_t *router_get_my_routerinfo(void); const char *router_get_my_descriptor(void); int router_is_me(routerinfo_t *router); int router_rebuild_descriptor(void); int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router, crypto_pk_env_t *ident_key); /********************************* routerlist.c ***************************/ routerinfo_t *router_pick_directory_server(void); struct smartlist_t; routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded, struct smartlist_t *excludedsmartlist); routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port); routerinfo_t *router_get_by_nickname(char *nickname); void router_get_routerlist(routerlist_t **prouterlist); void routerlist_free(routerlist_t *routerlist); void routerinfo_free(routerinfo_t *router); routerinfo_t *routerinfo_copy(const routerinfo_t *router); void router_mark_as_down(char *nickname); int router_set_routerlist_from_file(char *routerfile); int router_set_routerlist_from_string(const char *s); int router_set_routerlist_from_directory(const char *s, crypto_pk_env_t *pkey); int router_compare_addr_to_exit_policy(uint32_t addr, uint16_t port, struct exit_policy_t *policy); #define ADDR_POLICY_ACCEPTED 0 #define ADDR_POLICY_REJECTED -1 #define ADDR_POLICY_UNKNOWN 1 int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port); int router_exit_policy_rejects_all(routerinfo_t *router); /********************************* routerparse.c ************************/ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_parse_list_from_string(const char **s, routerlist_t **dest, int n_good_nicknames, const char **good_nickname_lst); int router_parse_routerlist_from_directory(const char *s, routerlist_t **dest, crypto_pk_env_t *pkey); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end); int router_add_exit_policy_from_string(routerinfo_t *router, const char *s); #endif /* Loading