From 0a195e6bb122f355520f93a5adfcdf88869df974 Mon Sep 17 00:00:00 2001 From: John Bland Date: Fri, 1 Sep 2023 02:33:50 -0400 Subject: [PATCH] add relay_sendme and the cell windows so that the full consensus can be fetched without the windows closing, fixed bugs related to consensus fetching --- h/circuit.h | 5 +- h/constants.h | 3 + h/structures/cell.h | 7 ++ h/structures/circuit.h | 2 + h/structures/consensus.h | 5 +- h/structures/onion_message.h | 1 - src/cell.c | 3 +- src/circuit.c | 121 ++++++++++++++++++--------- src/config.c | 1 + src/connections.c | 10 ++- src/consensus.c | 154 +++++++++++++++++++++-------------- src/core.c | 71 +++++++++++----- src/minitor.c | 1 - src/models/relay.c | 26 ++++-- src/onion_service.c | 3 + src/structures/consensus.c | 15 +++- 16 files changed, 291 insertions(+), 137 deletions(-) diff --git a/h/circuit.h b/h/circuit.h index f0e5b50..ee56fac 100644 --- a/h/circuit.h +++ b/h/circuit.h @@ -52,7 +52,8 @@ int d_process_certs( DlConnection* or_connection, CellVariable* certs_cell, int int d_process_challenge( DlConnection* or_connection, CellVariable* challenge_cell, int length ); int d_process_netinfo( DlConnection* or_connection, Cell* netinfo_cell ); int d_router_begin_dir( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id ); -int d_rounter_relay_data_cell( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id, uint8_t* data, uint32_t data_len ); -int d_router_relay_end( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id ); +int d_router_relay_data_cell( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id, uint8_t* data, uint32_t data_len ); +int d_router_relay_end(OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id); +int d_router_relay_sendme(OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id); #endif diff --git a/h/constants.h b/h/constants.h index 3c3dbe8..dbdacb7 100644 --- a/h/constants.h +++ b/h/constants.h @@ -70,4 +70,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #define WATCHDOG_TIMEOUT_PERIOD 30 +#define RELAY_WINDOW_DEFAULT 1000 +#define STREAM_RELAY_WINDOW_DEFAULT 500 + #endif diff --git a/h/structures/cell.h b/h/structures/cell.h index dd33e5f..44ee961 100644 --- a/h/structures/cell.h +++ b/h/structures/cell.h @@ -461,6 +461,13 @@ typedef union __attribute__((__packed__)) CellPayload uint8_t destroy_code; uint8_t data[RELAY_PAYLOAD_LEN]; + + struct __attribute__((__packed__)) + { + uint8_t version; + uint16_t data_len; + uint8_t data[]; + } sendme; }; } relay; diff --git a/h/structures/circuit.h b/h/structures/circuit.h index 3df2332..a3a0e22 100644 --- a/h/structures/circuit.h +++ b/h/structures/circuit.h @@ -96,6 +96,8 @@ typedef struct OnionCircuit int desc_index; int target_relay_index; int relay_early_count; + uint16_t stream_package_windows[5]; + uint16_t stream_deliver_windows[5]; } OnionCircuit; extern unsigned int circ_id_counter; diff --git a/h/structures/consensus.h b/h/structures/consensus.h index 58437fa..7025db4 100644 --- a/h/structures/consensus.h +++ b/h/structures/consensus.h @@ -108,6 +108,8 @@ struct DoublyLinkedOnionRelay { DoublyLinkedOnionRelay* next; OnionRelay* relay; RelayCrypto* relay_crypto; + unsigned int package_window; + unsigned int deliver_window; }; typedef struct DoublyLinkedOnionRelayList { @@ -119,7 +121,8 @@ typedef struct DoublyLinkedOnionRelayList { void v_add_relay_to_list( DoublyLinkedOnionRelay* node, DoublyLinkedOnionRelayList* list ); void v_pop_relay_from_list_back( DoublyLinkedOnionRelayList* list ); -OnionRelay* px_get_relay_by_index( DoublyLinkedOnionRelayList* list, int index ); +DoublyLinkedOnionRelay* px_get_dl_relay_by_index(DoublyLinkedOnionRelayList* list, int index); +OnionRelay* px_get_relay_by_index(DoublyLinkedOnionRelayList* list, int index); // shared state must be protected by mutex extern NetworkConsensus network_consensus; diff --git a/h/structures/onion_message.h b/h/structures/onion_message.h index 9579170..68eaa1a 100644 --- a/h/structures/onion_message.h +++ b/h/structures/onion_message.h @@ -41,7 +41,6 @@ typedef enum OnionMessageType CLIENT_RELAY_END, CLIENT_CLOSED, CONSENSUS_FETCHED, - EXTERNAL_CONSENSUS_FETCHED, } OnionMessageType; typedef struct OnionMessage diff --git a/src/cell.c b/src/cell.c index 8744090..99333c7 100644 --- a/src/cell.c +++ b/src/cell.c @@ -632,5 +632,6 @@ int d_decrypt_cell( Cell* cell, int circ_id_length, DoublyLinkedOnionRelayList* } } - return 0; + // return the circuit index that sent this cell + return i; } diff --git a/src/circuit.c b/src/circuit.c index 0b0fb2d..738a6cc 100644 --- a/src/circuit.c +++ b/src/circuit.c @@ -161,6 +161,9 @@ int d_prepare_onion_circuit( OnionCircuit* circuit, int length, OnionRelay* star if ( start_relay != NULL ) { dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + memset(dl_relay, 0, sizeof(DoublyLinkedOnionRelay)); + dl_relay->package_window = RELAY_WINDOW_DEFAULT; + dl_relay->deliver_window = RELAY_WINDOW_DEFAULT; dl_relay->relay = start_relay; dl_relay->next = circuit->relay_list.head; @@ -183,8 +186,10 @@ int d_prepare_onion_circuit( OnionCircuit* circuit, int length, OnionRelay* star // append the destination_relay to the list if ( end_relay != NULL ) { - dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + memset(dl_relay, 0, sizeof(DoublyLinkedOnionRelay)); + dl_relay->package_window = RELAY_WINDOW_DEFAULT; + dl_relay->deliver_window = RELAY_WINDOW_DEFAULT; dl_relay->relay = end_relay; v_add_relay_to_list( dl_relay, &circuit->relay_list ); @@ -207,21 +212,24 @@ int d_prepare_onion_circuit( OnionCircuit* circuit, int length, OnionRelay* star int d_get_suitable_relay( DoublyLinkedOnionRelayList* relay_list, int guard, uint8_t* exclude_start, uint8_t* exclude_end ) { - DoublyLinkedOnionRelay* db_relay; + DoublyLinkedOnionRelay* dl_relay; - db_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); - db_relay->relay = px_get_random_fast_relay( guard, relay_list, exclude_start, exclude_end ); + dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + memset(dl_relay, 0, sizeof(DoublyLinkedOnionRelay)); + dl_relay->package_window = RELAY_WINDOW_DEFAULT; + dl_relay->deliver_window = RELAY_WINDOW_DEFAULT; + dl_relay->relay = px_get_random_fast_relay( guard, relay_list, exclude_start, exclude_end ); - if ( db_relay->relay == NULL ) + if ( dl_relay->relay == NULL ) { MINITOR_LOG( MINITOR_TAG, "Failed to get guard relay" ); - free( db_relay ); + free( dl_relay ); return -1; } - v_add_relay_to_list( db_relay, relay_list ); + v_add_relay_to_list( dl_relay, relay_list ); return 0; } @@ -229,26 +237,26 @@ int d_get_suitable_relay( DoublyLinkedOnionRelayList* relay_list, int guard, uin int d_get_suitable_onion_relays( DoublyLinkedOnionRelayList* relay_list, int desired_length, uint8_t* exclude_start, uint8_t* exclude_end ) { int i; - DoublyLinkedOnionRelay* db_relay; + DoublyLinkedOnionRelay* dl_relay; for ( i = relay_list->length; i < desired_length; i++ ) { - db_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); if ( i == 0 ) { - db_relay->relay = px_get_random_fast_relay( 1, NULL, exclude_start, exclude_end ); + dl_relay->relay = px_get_random_fast_relay( 1, NULL, exclude_start, exclude_end ); } else { - db_relay->relay = px_get_random_fast_relay( 0, relay_list, exclude_start, exclude_end ); + dl_relay->relay = px_get_random_fast_relay( 0, relay_list, exclude_start, exclude_end ); } - if ( db_relay->relay == NULL ) + if ( dl_relay->relay == NULL ) { MINITOR_LOG( MINITOR_TAG, "Failed to get guard relay" ); - free( db_relay ); + free( dl_relay ); while ( relay_list->length > 0 ) { @@ -258,7 +266,7 @@ int d_get_suitable_onion_relays( DoublyLinkedOnionRelayList* relay_list, int des return -1; } - v_add_relay_to_list( db_relay, relay_list ); + v_add_relay_to_list( dl_relay, relay_list ); } return 0; @@ -632,7 +640,7 @@ int d_ntor_handshake_start( unsigned char* handshake_data, OnionRelay* relay, cu return 0; } -int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db_relay, curve25519_key* key ) +int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* dl_relay, curve25519_key* key ) { int wolf_succ; unsigned int idx; @@ -654,12 +662,12 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db wc_curve25519_init( &responder_handshake_public_key ); wc_curve25519_init( &ntor_onion_key ); - db_relay->relay_crypto = malloc( sizeof( RelayCrypto ) ); + dl_relay->relay_crypto = malloc( sizeof( RelayCrypto ) ); - wc_InitSha( &db_relay->relay_crypto->running_sha_forward ); - wc_InitSha( &db_relay->relay_crypto->running_sha_backward ); - wc_AesInit( &db_relay->relay_crypto->aes_forward, NULL, INVALID_DEVID ); - wc_AesInit( &db_relay->relay_crypto->aes_backward, NULL, INVALID_DEVID ); + wc_InitSha( &dl_relay->relay_crypto->running_sha_forward ); + wc_InitSha( &dl_relay->relay_crypto->running_sha_backward ); + wc_AesInit( &dl_relay->relay_crypto->aes_forward, NULL, INVALID_DEVID ); + wc_AesInit( &dl_relay->relay_crypto->aes_backward, NULL, INVALID_DEVID ); wolf_succ = wc_curve25519_import_public_ex( handshake_data, G_LENGTH, &responder_handshake_public_key, EC25519_LITTLE_ENDIAN ); @@ -670,7 +678,7 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db goto fail; } - wolf_succ = wc_curve25519_import_public_ex( db_relay->relay->ntor_onion_key, H_LENGTH, &ntor_onion_key, EC25519_LITTLE_ENDIAN ); + wolf_succ = wc_curve25519_import_public_ex( dl_relay->relay->ntor_onion_key, H_LENGTH, &ntor_onion_key, EC25519_LITTLE_ENDIAN ); if ( wolf_succ < 0 ) { @@ -704,10 +712,10 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db working_secret_input += 32; - memcpy( working_secret_input, db_relay->relay->identity, ID_LENGTH ); + memcpy( working_secret_input, dl_relay->relay->identity, ID_LENGTH ); working_secret_input += ID_LENGTH; - memcpy( working_secret_input, db_relay->relay->ntor_onion_key, H_LENGTH ); + memcpy( working_secret_input, dl_relay->relay->ntor_onion_key, H_LENGTH ); working_secret_input += H_LENGTH; idx = 32; @@ -735,10 +743,10 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db working_auth_input += WC_SHA256_DIGEST_SIZE; - memcpy( working_auth_input, db_relay->relay->identity, ID_LENGTH ); + memcpy( working_auth_input, dl_relay->relay->identity, ID_LENGTH ); working_auth_input += ID_LENGTH; - memcpy( working_auth_input, db_relay->relay->ntor_onion_key, H_LENGTH ); + memcpy( working_auth_input, dl_relay->relay->ntor_onion_key, H_LENGTH ); working_auth_input += H_LENGTH; memcpy( working_auth_input, handshake_data, G_LENGTH ); @@ -788,9 +796,9 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db wc_HmacFree( &reusable_hmac ); // seed the forward sha - wc_ShaUpdate( &db_relay->relay_crypto->running_sha_forward, reusable_hmac_digest, HASH_LEN ); + wc_ShaUpdate( &dl_relay->relay_crypto->running_sha_forward, reusable_hmac_digest, HASH_LEN ); // seed the first 16 bytes of backwards sha - wc_ShaUpdate( &db_relay->relay_crypto->running_sha_backward, reusable_hmac_digest + HASH_LEN, WC_SHA256_DIGEST_SIZE - HASH_LEN ); + wc_ShaUpdate( &dl_relay->relay_crypto->running_sha_backward, reusable_hmac_digest + HASH_LEN, WC_SHA256_DIGEST_SIZE - HASH_LEN ); // mark how many bytes we've written to the backwards sha and how many remain bytes_written = WC_SHA256_DIGEST_SIZE - HASH_LEN; bytes_remaining = HASH_LEN - bytes_written; @@ -804,10 +812,10 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db wc_HmacFree( &reusable_hmac ); // seed the last 8 bytes of backward sha - wc_ShaUpdate( &db_relay->relay_crypto->running_sha_backward, reusable_hmac_digest, bytes_remaining ); + wc_ShaUpdate( &dl_relay->relay_crypto->running_sha_backward, reusable_hmac_digest, bytes_remaining ); // set the forward aes key memcpy( reusable_aes_key, reusable_hmac_digest + bytes_remaining, KEY_LEN ); - wc_AesSetKeyDirect( &db_relay->relay_crypto->aes_forward, reusable_aes_key, KEY_LEN, aes_iv, AES_ENCRYPTION ); + wc_AesSetKeyDirect( &dl_relay->relay_crypto->aes_forward, reusable_aes_key, KEY_LEN, aes_iv, AES_ENCRYPTION ); // copy the first part of the backward key into the buffer memcpy( reusable_aes_key, reusable_hmac_digest + bytes_remaining + KEY_LEN, WC_SHA256_DIGEST_SIZE - bytes_remaining - KEY_LEN ); // mark how many bytes we've written to the backwards key and how many remain @@ -824,10 +832,10 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db // copy the last part of the key into the buffer and initialize the key memcpy( reusable_aes_key + bytes_written, reusable_hmac_digest, bytes_remaining ); - wc_AesSetKeyDirect( &db_relay->relay_crypto->aes_backward, reusable_aes_key, KEY_LEN, aes_iv, AES_ENCRYPTION ); + wc_AesSetKeyDirect( &dl_relay->relay_crypto->aes_backward, reusable_aes_key, KEY_LEN, aes_iv, AES_ENCRYPTION ); // copy the nonce - memcpy( db_relay->relay_crypto->nonce, reusable_hmac_digest + bytes_remaining, DIGEST_LEN ); + memcpy( dl_relay->relay_crypto->nonce, reusable_hmac_digest + bytes_remaining, DIGEST_LEN ); // free all the heap resources wc_curve25519_free( &responder_handshake_public_key ); @@ -839,12 +847,12 @@ int d_ntor_handshake_finish( uint8_t* handshake_data, DoublyLinkedOnionRelay* db return 0; fail: - wc_ShaFree( &db_relay->relay_crypto->running_sha_forward ); - wc_ShaFree( &db_relay->relay_crypto->running_sha_backward ); - wc_AesFree( &db_relay->relay_crypto->aes_forward ); - wc_AesFree( &db_relay->relay_crypto->aes_backward ); + wc_ShaFree( &dl_relay->relay_crypto->running_sha_forward ); + wc_ShaFree( &dl_relay->relay_crypto->running_sha_backward ); + wc_AesFree( &dl_relay->relay_crypto->aes_forward ); + wc_AesFree( &dl_relay->relay_crypto->aes_backward ); - free( db_relay->relay_crypto ); + free( dl_relay->relay_crypto ); wc_curve25519_free( &responder_handshake_public_key ); wc_curve25519_free( &ntor_onion_key ); @@ -1737,7 +1745,7 @@ int d_router_begin_dir( OnionCircuit* circuit, DlConnection* or_connection, uint int ret; Cell* begin_dir_cell; - begin_dir_cell = malloc( MINITOR_CELL_LEN ); + begin_dir_cell = malloc(MINITOR_CELL_LEN); begin_dir_cell->circ_id = circuit->circ_id; begin_dir_cell->command = RELAY; @@ -1748,17 +1756,19 @@ int d_router_begin_dir( OnionCircuit* circuit, DlConnection* or_connection, uint begin_dir_cell->payload.relay.length = 0; begin_dir_cell->length = FIXED_CELL_HEADER_SIZE + RELAY_CELL_HEADER_SIZE + begin_dir_cell->payload.relay.length; - if ( d_send_relay_cell_and_free( or_connection, begin_dir_cell, &circuit->relay_list, NULL ) < 0 ) + if (d_send_relay_cell_and_free(or_connection, begin_dir_cell, &circuit->relay_list, NULL) < 0) { MINITOR_LOG( MINITOR_TAG, "Failed to send RELAY_EXTEND2 cell" ); return -1; } + circuit->stream_deliver_windows[stream_id - 1] = STREAM_RELAY_WINDOW_DEFAULT; + return 0; } -int d_rounter_relay_data_cell( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id, uint8_t* data, uint32_t data_len ) +int d_router_relay_data_cell( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id, uint8_t* data, uint32_t data_len ) { Cell* data_cell; @@ -1793,11 +1803,12 @@ int d_rounter_relay_data_cell( OnionCircuit* circuit, DlConnection* or_connectio return 0; } -int d_router_relay_end( OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id ) +int d_router_relay_end(OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id) { Cell* end_cell; end_cell = malloc( MINITOR_CELL_LEN ); + memset(end_cell, 0, MINITOR_CELL_LEN); end_cell->circ_id = circuit->circ_id; end_cell->command = RELAY; @@ -1818,3 +1829,33 @@ int d_router_relay_end( OnionCircuit* circuit, DlConnection* or_connection, uint return 0; } + +int d_router_relay_sendme(OnionCircuit* circuit, DlConnection* or_connection, uint16_t stream_id) +{ + Cell* sendme_cell; + + sendme_cell = malloc( MINITOR_CELL_LEN ); + memset(sendme_cell, 0, MINITOR_CELL_LEN); + + sendme_cell->circ_id = circuit->circ_id; + sendme_cell->command = RELAY; + sendme_cell->payload.relay.relay_command = RELAY_SENDME; + sendme_cell->payload.relay.recognized = 0; + sendme_cell->payload.relay.stream_id = stream_id; + sendme_cell->payload.relay.digest = 0; + sendme_cell->payload.relay.length = 3; + + sendme_cell->payload.relay.sendme.version = 0; + sendme_cell->payload.relay.sendme.data_len = 0; + + sendme_cell->length = FIXED_CELL_HEADER_SIZE + RELAY_CELL_HEADER_SIZE + sendme_cell->payload.relay.length; + + if ( d_send_relay_cell_and_free( or_connection, sendme_cell, &circuit->relay_list, NULL ) < 0 ) + { + MINITOR_LOG( MINITOR_TAG, "Failed to send RELAY_SENDME cell" ); + + return -1; + } + + return 0; +} diff --git a/src/config.c b/src/config.c index f1ec583..b7516af 100644 --- a/src/config.c +++ b/src/config.c @@ -30,6 +30,7 @@ const char* tor_authorities[] = // the identity can be found at /tor/status-vote/current/consensus // the ntor-onion-key can be found at /tor/server/all #ifdef MINITOR_CHUTNEY +// ip:port:identity:nto_onion_key MINITOR_CHUTNEY_ADDRESS_STR ":5000:JM022IGoVYCo1n4HRKNmEyRJflI:jq+kM4ZFUbZqYWym4+sCmr9zOUn8DDlPSP0JP1crbBg", MINITOR_CHUTNEY_ADDRESS_STR ":5001:Ewduz4NDJe1DNGMPLcMZVB/U7oc:z5Yd0lVNE8VLmNjG0Wp3ui9Czbc6E60wKGDb5hQy6B0", MINITOR_CHUTNEY_ADDRESS_STR ":5002:biV7oePe1m9MXWyQteX44pcEnPI:HMHNA06WJOv/ywNk+6Hw/SUvOse4e12L7Z0/evLS1RI" diff --git a/src/connections.c b/src/connections.c index d22dab3..e6c4462 100644 --- a/src/connections.c +++ b/src/connections.c @@ -96,6 +96,7 @@ static void v_cleanup_connection_in_lock( DlConnection* dl_connection ) if ( dl_connection->cell_ring_buf[i] != NULL ) { free( dl_connection->cell_ring_buf[i] ); + dl_connection->cell_ring_buf[i] = NULL; } } @@ -339,16 +340,19 @@ void v_connections_daemon( void* pv_parameters ) while ( dl_connection != NULL ) { + access_mutex = connection_access_mutex[dl_connection->mutex_index]; + tmp_connection = dl_connection->next; + if ( dl_connection->is_or == 1 ) { if ( ( connections_poll[dl_connection->poll_index].revents & POLLERR ) != 0 || ( connections_poll[dl_connection->poll_index].revents & POLLHUP ) != 0 ) { // MUTEX TAKE - MINITOR_MUTEX_TAKE_BLOCKING( connection_access_mutex[dl_connection->mutex_index] ); + MINITOR_MUTEX_TAKE_BLOCKING(access_mutex); v_cleanup_connection_in_lock( dl_connection ); - MINITOR_MUTEX_GIVE( connection_access_mutex[dl_connection->mutex_index] ); + MINITOR_MUTEX_GIVE(access_mutex); // MUTEX GIVE } else if @@ -362,7 +366,7 @@ void v_connections_daemon( void* pv_parameters ) } } - dl_connection = dl_connection->next; + dl_connection = tmp_connection; } MINITOR_MUTEX_GIVE( connections_mutex ); diff --git a/src/consensus.c b/src/consensus.c index efb47b2..cf87e3f 100644 --- a/src/consensus.c +++ b/src/consensus.c @@ -113,6 +113,8 @@ void v_handle_crypto_and_insert( void* pv_parameters ) OnionRelay* onion_relay; NetworkConsensus* working_consensus = (NetworkConsensus*)pv_parameters; + MINITOR_LOG( MINITOR_TAG, "START v_handle_crypto_and_insert", process_count ); + // MUTEX TAKE MINITOR_MUTEX_TAKE_BLOCKING( crypto_insert_finish ); @@ -121,6 +123,7 @@ void v_handle_crypto_and_insert( void* pv_parameters ) if ( onion_relay == NULL ) { null_count++; + MINITOR_LOG( MINITOR_TAG, "NULL count %d", null_count ); if ( null_count == 2 ) { @@ -129,7 +132,9 @@ void v_handle_crypto_and_insert( void* pv_parameters ) MINITOR_MUTEX_GIVE( crypto_insert_finish ); // MUTEX GIVE + MINITOR_QUEUE_DELETE( insert_relays_queue ); MINITOR_TASK_DELETE( NULL ); + return; } continue; @@ -200,7 +205,7 @@ void v_handle_crypto_and_insert( void* pv_parameters ) MINITOR_MUTEX_TAKE_BLOCKING( waiting_relays_lock ); // if we're not fetching or all relays are waiting - if ( !fetch_in_progress ) + if ( !fetch_in_progress && fetch_relays_length < 9 ) { // enqueue to the relay to be fetched MINITOR_ENQUEUE_BLOCKING( fetch_relays_queue, &onion_relay ); @@ -420,7 +425,7 @@ int d_consensus_request( OnionCircuit* circuit, DlConnection* or_connection ) close( fd ); - return d_rounter_relay_data_cell( circuit, or_connection, 1, REQUEST, strlen( REQUEST ) ); + return d_router_relay_data_cell( circuit, or_connection, CONSENSUS_STREAM_ID, REQUEST, strlen( REQUEST ) ); } static int d_parse_consensus_r( char* line, int line_length, OnionRelay* parse_relay ) @@ -591,7 +596,7 @@ int d_parse_consensus( OnionCircuit* circuit, DlConnection* or_connection, Cell* all_relays_waiting = true; - // if we have 9 and are not already fetching descriptors + // if we are not already fetching descriptors if ( !fetch_in_progress ) { ret = d_router_begin_dir( circuit, or_connection, DESCRIPTORS_STREAM_ID ); @@ -650,41 +655,11 @@ int d_parse_consensus( OnionCircuit* circuit, DlConnection* or_connection, Cell* { have_network_consensus = true; - // copy the new new consenus - // BEGIN MUTEX - MINITOR_MUTEX_TAKE_BLOCKING( network_consensus_mutex ); - - memcpy( &network_consensus, &working_network_consensus, sizeof( NetworkConsensus ) ); - - // if we didn't find these values explicitly set - if ( network_consensus.hsdir_interval == 0 ) - { -#ifdef MINITOR_CHUTNEY - network_consensus.hsdir_interval = 8; -#else - network_consensus.hsdir_interval = HSDIR_INTERVAL_DEFAULT; -#endif - } - - if ( network_consensus.hsdir_n_replicas == 0 ) - { - network_consensus.hsdir_n_replicas = HSDIR_N_REPLICAS_DEFAULT; - } - - if ( network_consensus.hsdir_spread_store == 0 ) - { -#ifdef MINITOR_CHUTNEY - network_consensus.hsdir_spread_store = 3; -#else - network_consensus.hsdir_spread_store = HSDIR_SPREAD_STORE_DEFAULT; -#endif - } - - MINITOR_MUTEX_GIVE( network_consensus_mutex ); - // END MUTEX + // create the insert queue + insert_relays_queue = MINITOR_QUEUE_CREATE( 9, sizeof( OnionRelay* ) ); // create the insert queue and task - b_create_insert_task( &crypto_insert_handle, &network_consensus ); + b_create_insert_task( &crypto_insert_handle, &working_network_consensus ); } else if ( have_network_consensus == true ) { @@ -760,9 +735,12 @@ int d_parse_consensus( OnionCircuit* circuit, DlConnection* or_connection, Cell* return 0; fail: + MINITOR_LOG( MINITOR_TAG, "failed" ); + if ( crypto_insert_handle != NULL ) { MINITOR_TASK_DELETE( crypto_insert_handle ); + MINITOR_QUEUE_DELETE( insert_relays_queue ); } return -1; @@ -776,7 +754,7 @@ int d_descriptors_request( OnionCircuit* circuit, DlConnection* or_connection, O const char* REQUEST_2 = " HTTP/1.0\r\nHost: 127.0.0.1\r\n" "User-Agent: esp-idf/1.0 esp3266\r\n" "\r\n"; - char REQUEST[440]; + char REQUEST[600]; sprintf( REQUEST, REQUEST_1 ); @@ -812,7 +790,7 @@ int d_descriptors_request( OnionCircuit* circuit, DlConnection* or_connection, O // 41 for each digest+, -1 for the last one sprintf( REQUEST + 18 + list_length * 41 - 1, REQUEST_2 ); - return d_rounter_relay_data_cell( circuit, or_connection, DESCRIPTORS_STREAM_ID, REQUEST, strlen( REQUEST ) ); + return d_router_relay_data_cell( circuit, or_connection, DESCRIPTORS_STREAM_ID, REQUEST, strlen( REQUEST ) ); } static int d_parse_http_version_line( char* line, int line_len ) @@ -974,6 +952,9 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel int j; int space_count; int ret = 0; + time_t now; + time_t voting_interval; + time_t srv_start_time; bool more_relays; bool all_waiting; OnionRelay* send_relay; @@ -1025,16 +1006,67 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel MINITOR_MUTEX_GIVE( crypto_insert_finish ); // MUTEX GIVE - ret = d_finalize_staged_relay_lists(); + // MUTEX TAKE + MINITOR_MUTEX_TAKE_BLOCKING( network_consensus_mutex ); + + memcpy( &network_consensus, &working_network_consensus, sizeof( NetworkConsensus ) ); - if ( ret < 0 ) + // if we didn't find these values explicitly set + if ( network_consensus.hsdir_interval == 0 ) + { +#ifdef MINITOR_CHUTNEY + network_consensus.hsdir_interval = 8; +#else + network_consensus.hsdir_interval = HSDIR_INTERVAL_DEFAULT; +#endif + } + + if ( network_consensus.hsdir_n_replicas == 0 ) { - MINITOR_LOG( MINITOR_TAG, "Failed to d_finalize_staged_relay_lists" ); + network_consensus.hsdir_n_replicas = HSDIR_N_REPLICAS_DEFAULT; } - else + + if ( network_consensus.hsdir_spread_store == 0 ) { - ret = 1; +#ifdef MINITOR_CHUTNEY + network_consensus.hsdir_spread_store = 3; +#else + network_consensus.hsdir_spread_store = HSDIR_SPREAD_STORE_DEFAULT; +#endif + } + + ret = d_finalize_staged_relay_lists( network_consensus.valid_until ); + + if ( ret == 0 ) + { + time( &now ); + +#ifdef MINITOR_CHUTNEY + voting_interval = network_consensus.fresh_until - network_consensus.valid_after; + + // 24 is SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES + srv_start_time = network_consensus.valid_after - ( ( ( ( network_consensus.valid_after / voting_interval ) ) % ( SHARED_RANDOM_N_ROUNDS * SHARED_RANDOM_N_PHASES ) ) * voting_interval ); + + // start the update timer a half second after the consensus update + if ( now > ( srv_start_time + ( 25 * voting_interval ) ) ) + { + MINITOR_TIMER_SET_MS_BLOCKING( consensus_timer, 1000 * ( 25 * voting_interval ) ); + } + else + { + MINITOR_TIMER_SET_MS_BLOCKING( consensus_timer, 1000 * ( ( srv_start_time + ( 25 * voting_interval ) ) - now ) ); + } +#else + MINITOR_TIMER_SET_MS_BLOCKING( consensus_timer, ( network_consensus.valid_until - now ) * 1000 ); +#endif } + + MINITOR_MUTEX_GIVE( network_consensus_mutex ); + // MUTEX GIVE + + // MUTEX GIVE + if ( ret == 0 ) + ret = 1; } } @@ -1071,11 +1103,10 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel fetch_in_progress = true; + ret = d_descriptors_request( circuit, or_connection, fetch_relays, fetch_relays_length ); MINITOR_MUTEX_GIVE( waiting_relays_lock ); // MUTEX GIVE - ret = d_descriptors_request( circuit, or_connection, fetch_relays, fetch_relays_length ); - if ( ret == 0 ) { parse_descriptors_sate = FIND_STATUS; @@ -1248,6 +1279,9 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel // parse the onion key d_base_64_decode( working_ntor_onion_key, working_desc_line + strlen( "ntor-onion-key " ), 43 ); + // MUTEX TAKE + MINITOR_MUTEX_TAKE_BLOCKING( waiting_relays_lock ); + for ( j = 0; j < fetch_relays_length; j++ ) { // match the digest @@ -1261,7 +1295,10 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel } } - if ( j == fetch_relays_length ) + MINITOR_MUTEX_GIVE( waiting_relays_lock ); + // MUTEX GIVE + + if ( j >= fetch_relays_length ) { goto fail; } @@ -1279,9 +1316,11 @@ int d_parse_descriptors( OnionCircuit* circuit, DlConnection* or_connection, Cel return 0; fail: + MINITOR_LOG( MINITOR_TAG, "failed desc" ); if ( crypto_insert_handle != NULL ) { MINITOR_TASK_DELETE( crypto_insert_handle ); + MINITOR_QUEUE_DELETE( insert_relays_queue ); } return -1; @@ -1387,7 +1426,7 @@ bool b_consensus_outdated() network_consensus.hsdir_n_replicas = HSDIR_N_REPLICAS_DEFAULT; network_consensus.hsdir_spread_store = HSDIR_SPREAD_STORE_DEFAULT; - if ( d_parse_network_consensus_from_file( fd, &network_consensus ) ) + if ( d_parse_network_consensus_from_file( fd, &network_consensus ) < 0 ) { MINITOR_LOG( MINITOR_TAG, "Failed to parse network consensus from file" ); @@ -1420,17 +1459,12 @@ bool b_consensus_outdated() int d_reset_relay_files() { - if ( d_reset_staging_hsdir_relays() < 0 ) - { - return -1; - } - - if ( d_reset_staging_cache_relays() < 0 ) - { - return -1; - } - - if ( d_reset_staging_fast_relays() < 0 ) + if ( + d_reset_staging_hsdir_relays() < 0 || + d_reset_staging_cache_relays() < 0 || + d_reset_staging_fast_relays() < 0 || + d_reset_waiting_relays() < 0 + ) { return -1; } @@ -1490,13 +1524,15 @@ int d_fetch_consensus() return -1; } - if ( onion_message->type != EXTERNAL_CONSENSUS_FETCHED ) + if ( onion_message->type != CONSENSUS_FETCHED ) { MINITOR_LOG( MINITOR_TAG, "Failed to fetch the network consensus" ); ret = -1; } + external_want_consensus = false; + free( onion_message ); return ret; diff --git a/src/core.c b/src/core.c index 7ac841c..bb3be32 100644 --- a/src/core.c +++ b/src/core.c @@ -534,10 +534,7 @@ static void v_handle_tor_cell( uint32_t conn_id ) if ( cell == NULL ) { - MINITOR_MUTEX_GIVE( access_mutex ); - // MUTEX GIVE - - return; + goto cleanup; } // MUTEX TAKE @@ -552,12 +549,7 @@ static void v_handle_tor_cell( uint32_t conn_id ) { MINITOR_LOG( CORE_TAG, "Discarding circuitless cell %d", cell->circ_id ); - MINITOR_MUTEX_GIVE( access_mutex ); - // MUTEX GIVE - - free( cell ); - - return; + goto cleanup; } MINITOR_LOG( CORE_TAG, "status %d target %d", working_circuit->status, working_circuit->target_status ); @@ -591,15 +583,44 @@ static void v_handle_tor_cell( uint32_t conn_id ) // after decryption we need to change from network byte order to our byte order v_hostize_cell( cell ); - // discard padding cell - if ( cell->command == PADDING ) + /* do flow control logic */ + if (cell->command == RELAY) { - MINITOR_MUTEX_GIVE( access_mutex ); - // MUTEX GIVE + if (cell->payload.relay.relay_command == RELAY_DATA) + { + // decrement the deliver window + dl_relay = px_get_dl_relay_by_index(&working_circuit->relay_list, ret); + dl_relay->deliver_window--; + working_circuit->stream_deliver_windows[cell->payload.relay.stream_id - 1]--; - free( cell ); + // send a RELAY_SENDME to increment deliver window + if (dl_relay->deliver_window < RELAY_WINDOW_DEFAULT - 100) + { + ret = d_router_relay_sendme(working_circuit, or_connection, 0); - return; + if (ret == 0) + dl_relay->deliver_window += 100; + } + + if (working_circuit->stream_deliver_windows[cell->payload.relay.stream_id - 1] < STREAM_RELAY_WINDOW_DEFAULT - 50) + { + ret = d_router_relay_sendme(working_circuit, or_connection, cell->payload.relay.stream_id); + + if (ret == 0) + working_circuit->stream_deliver_windows[cell->payload.relay.stream_id - 1] += 50; + } + } + else if (cell->payload.relay.relay_command == RELAY_SENDME) + { + // TODO ignore sendme for now, not sure if we care about this since we're always polling to read new data + goto cleanup; + } + } + + // discard padding cell + if ( cell->command == PADDING ) + { + goto cleanup; } switch ( working_circuit->status ) @@ -802,6 +823,9 @@ static void v_handle_tor_cell( uint32_t conn_id ) else { dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + memset(dl_relay, 0, sizeof(DoublyLinkedOnionRelay)); + dl_relay->package_window = RELAY_WINDOW_DEFAULT; + dl_relay->deliver_window = RELAY_WINDOW_DEFAULT; dl_relay->relay = target_relay; v_add_relay_to_list( dl_relay, &working_circuit->relay_list ); @@ -844,6 +868,7 @@ static void v_handle_tor_cell( uint32_t conn_id ) ( cell->payload.relay.relay_command != RELAY_DATA && cell->payload.relay.relay_command != RELAY_END && cell->payload.relay.relay_command != RELAY_CONNECTED ) ) { + MINITOR_LOG( CORE_TAG, "CIRCUIT_CONSENSUS_FETCH ERROR" ); goto circuit_rebuild; } @@ -851,22 +876,27 @@ static void v_handle_tor_cell( uint32_t conn_id ) { // parse this part of the consensus ret = d_parse_consensus( working_circuit, or_connection, cell ); + MINITOR_LOG( CORE_TAG, "d_parse_consensus %d %d", ret, cell->payload.relay.relay_command ); + } else { // parse this part of the descriptors ret = d_parse_descriptors( working_circuit, or_connection, cell ); + MINITOR_LOG( CORE_TAG, "d_parse_descriptors %d %d", ret, cell->payload.relay.stream_id ); } - if ( ret == 1 ) { onion_message = malloc( sizeof( OnionMessage ) ); - onion_message->type = EXTERNAL_CONSENSUS_FETCHED; + onion_message->type = CONSENSUS_FETCHED; - // inform the external task that we're done fetching - MINITOR_ENQUEUE_BLOCKING( external_consensus_queue, (void*)(&onion_message) ); + if ( external_want_consensus == true ) + { + // inform the external task that we're done fetching + MINITOR_ENQUEUE_BLOCKING( external_consensus_queue, (void*)(&onion_message) ); + } v_circuit_remove_destroy( working_circuit, or_connection ); // MUTEX GIVE @@ -1136,6 +1166,7 @@ static void v_handle_tor_cell( uint32_t conn_id ) } } +cleanup: if ( access_mutex != NULL ) { MINITOR_MUTEX_GIVE( access_mutex ); diff --git a/src/minitor.c b/src/minitor.c index 59ef14c..0d6e0d7 100644 --- a/src/minitor.c +++ b/src/minitor.c @@ -121,7 +121,6 @@ int d_minitor_INIT() connections_task_queue = MINITOR_QUEUE_CREATE( 25, sizeof( OnionMessage* ) ); external_consensus_queue = MINITOR_QUEUE_CREATE( 25, sizeof( OnionMessage* ) ); fetch_relays_queue = MINITOR_QUEUE_CREATE( 9, sizeof( OnionRelay* ) ); - insert_relays_queue = MINITOR_QUEUE_CREATE( 9, sizeof( OnionRelay* ) ); b_create_core_task( &core_task ); diff --git a/src/models/relay.c b/src/models/relay.c index 62d1a6f..e41bab0 100644 --- a/src/models/relay.c +++ b/src/models/relay.c @@ -41,14 +41,14 @@ uint32_t staging_hsdir_relay_count = 0; uint32_t staging_cache_relay_count = 0; uint32_t staging_fast_relay_count = 0; uint32_t waiting_relay_count = 0; -int waiting_relay_index = 0; +int waiting_relay_index = sizeof(time_t); static int d_add_relay_to_list( OnionRelay* onion_relay, const char* filename, int seek ) { int fd; int ret = 0; - fd = open( filename, O_WRONLY ); + fd = open( filename, O_WRONLY | O_CREAT, 0600 ); if ( fd < 0 ) { @@ -70,6 +70,8 @@ static int d_add_relay_to_list( OnionRelay* onion_relay, const char* filename, i if ( ret < 0 ) { + close(fd); + return ret; } @@ -166,11 +168,14 @@ OnionRelay* px_get_waiting_relay() { waiting_relay_index += sizeof( OnionRelay ); waiting_relay_count--; + close(fd); return onion_relay; } free( onion_relay ); + close(fd); + return NULL; } @@ -288,6 +293,8 @@ DoublyLinkedOnionRelayList* px_get_responsible_hsdir_relays_by_hs_index( uint8_t new_db_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); memset( new_db_relay, 0, sizeof( DoublyLinkedOnionRelay ) ); + new_db_relay->package_window = RELAY_WINDOW_DEFAULT; + new_db_relay->deliver_window = RELAY_WINDOW_DEFAULT; new_db_relay->relay = onion_relay; if ( db_relay == NULL ) @@ -674,7 +681,7 @@ int d_reset_staging_fast_relays() int d_reset_waiting_relays() { waiting_relay_count = 0; - waiting_relay_index = 0; + waiting_relay_index = sizeof(time_t); return d_reset_relay_list( FILESYSTEM_PREFIX "waiting_list" ); } @@ -756,7 +763,7 @@ static int d_set_relay_list_valid_until( time_t valid_until, const char* filenam return -1; } - return valid_until; + return 0; } int d_set_staging_hsdir_relay_valid_until( time_t valid_until ) @@ -810,10 +817,19 @@ int d_load_fast_relay_count() return fast_relay_count; } -int d_finalize_staged_relay_lists() +int d_finalize_staged_relay_lists( time_t valid_until ) { + int ret; struct stat st; + ret = d_set_staging_hsdir_relay_valid_until( valid_until ); + + if ( ret == 0 ) + ret = d_set_staging_cache_relay_valid_until( valid_until ); + + if ( ret == 0 ) + ret = d_set_staging_fast_relay_valid_until( valid_until ); + if ( stat( FILESYSTEM_PREFIX "hsdir_list", &st ) == 0 ) { if ( unlink( FILESYSTEM_PREFIX "hsdir_list" ) < 0 ) diff --git a/src/onion_service.c b/src/onion_service.c index f922e3c..3d794ad 100644 --- a/src/onion_service.c +++ b/src/onion_service.c @@ -520,6 +520,9 @@ int d_onion_service_handle_introduce_2( OnionCircuit* intro_circuit, Cell* intro else { dl_relay = malloc( sizeof( DoublyLinkedOnionRelay ) ); + memset(dl_relay, 0, sizeof(DoublyLinkedOnionRelay)); + dl_relay->package_window = RELAY_WINDOW_DEFAULT; + dl_relay->deliver_window = RELAY_WINDOW_DEFAULT; dl_relay->relay = rend_relay; v_add_relay_to_list( dl_relay, &rend_circuit->relay_list ); diff --git a/src/structures/consensus.c b/src/structures/consensus.c index f4ce80c..de15a19 100644 --- a/src/structures/consensus.c +++ b/src/structures/consensus.c @@ -94,7 +94,7 @@ void v_pop_relay_from_list_back( DoublyLinkedOnionRelayList* list ) list->length--; } -OnionRelay* px_get_relay_by_index( DoublyLinkedOnionRelayList* list, int index ) +DoublyLinkedOnionRelay* px_get_dl_relay_by_index(DoublyLinkedOnionRelayList* list, int index) { int i; DoublyLinkedOnionRelay* dl_relay; @@ -106,10 +106,17 @@ OnionRelay* px_get_relay_by_index( DoublyLinkedOnionRelayList* list, int index ) dl_relay = dl_relay->next; } - if ( dl_relay == NULL ) - { + return dl_relay; +} + +OnionRelay* px_get_relay_by_index(DoublyLinkedOnionRelayList* list, int index) +{ + DoublyLinkedOnionRelay* dl_relay; + + dl_relay = px_get_dl_relay_by_index(list, index); + + if (dl_relay == NULL) return NULL; - } return dl_relay->relay; }