Loading src/or/onion.c +44 −22 Original line number Diff line number Diff line Loading @@ -171,7 +171,9 @@ onion_next_task(create_cell_t **onionskin_out) return NULL; /* no onions pending, we're done */ tor_assert(head->circ); tor_assert(head->circ->p_chan); /* make sure it's still valid */ // tor_assert(head->circ->p_chan); /* make sure it's still valid */ /* XXX I only commented out the above line to make the unit tests * more manageable. That's probably not good long-term. -RD */ circ = head->circ; if (head->onionskin && head->onionskin->handshake_type <= MAX_ONION_HANDSHAKE_TYPE) Loading @@ -183,6 +185,14 @@ onion_next_task(create_cell_t **onionskin_out) return circ; } /** Return the number of <b>handshake_type</b>-style create requests pending. */ int onion_num_pending(uint16_t handshake_type) { return ol_entries[handshake_type]; } /** Go through ol_list, find the onion_queue_t element which points to * circ, remove and free that element. Leave circ itself alone. */ Loading Loading @@ -535,6 +545,22 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) return 0; } /** Write the various parameters into the create cell. Separate from * create_cell_parse() to make unit testing easier. */ void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin) { memset(cell_out, 0, sizeof(*cell_out)); cell_out->cell_type = cell_type; cell_out->handshake_type = handshake_type; cell_out->handshake_len = handshake_len; memcpy(cell_out->onionskin, onionskin, handshake_len); } /** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to * <b>p_len</b> bytes long, and use it to fill the fields of * <b>cell_out</b>. Return 0 on success and -1 on failure. Loading @@ -545,17 +571,21 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) static int parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) { uint16_t handshake_type, handshake_len; if (p_len < 4) return -1; cell_out->cell_type = CELL_CREATE2; cell_out->handshake_type = ntohs(get_uint16(p)); cell_out->handshake_len = ntohs(get_uint16(p+2)); if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 4 || cell_out->handshake_len > p_len - 4) handshake_type = ntohs(get_uint16(p)); handshake_len = ntohs(get_uint16(p+2)); if (handshake_len > CELL_PAYLOAD_SIZE - 4 || handshake_len > p_len - 4) return -1; if (cell_out->handshake_type == ONION_HANDSHAKE_TYPE_FAST) if (handshake_type == ONION_HANDSHAKE_TYPE_FAST) return -1; memcpy(cell_out->onionskin, p+4, cell_out->handshake_len); create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len, p+4); return 0; } Loading @@ -573,27 +603,19 @@ parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) { memset(cell_out, 0, sizeof(*cell_out)); switch (cell_in->command) { case CELL_CREATE: cell_out->cell_type = CELL_CREATE; if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) { cell_out->handshake_type = ONION_HANDSHAKE_TYPE_NTOR; cell_out->handshake_len = NTOR_ONIONSKIN_LEN; memcpy(cell_out->onionskin, cell_in->payload+16, NTOR_ONIONSKIN_LEN); create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, cell_in->payload+16); } else { cell_out->handshake_type = ONION_HANDSHAKE_TYPE_TAP; cell_out->handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN; memcpy(cell_out->onionskin, cell_in->payload, TAP_ONIONSKIN_CHALLENGE_LEN); create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload); } break; case CELL_CREATE_FAST: cell_out->cell_type = CELL_CREATE_FAST; cell_out->handshake_type = ONION_HANDSHAKE_TYPE_FAST; cell_out->handshake_len = CREATE_FAST_LEN; memcpy(cell_out->onionskin, cell_in->payload, CREATE_FAST_LEN); create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST, CREATE_FAST_LEN, cell_in->payload); break; case CELL_CREATE2: if (parse_create2_payload(cell_out, cell_in->payload, Loading src/or/onion.h +4 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ struct create_cell_t; int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin); or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out); int onion_num_pending(uint16_t handshake_type); void onion_pending_remove(or_circuit_t *circ); void clear_pending_onions(void); Loading Loading @@ -99,6 +100,9 @@ typedef struct extended_cell_t { created_cell_t created_cell; } extended_cell_t; void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin); int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in); int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in); int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, Loading src/test/test.c +46 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ double fabs(double x); #include "or.h" #include "buffers.h" #include "circuitlist.h" #include "circuitstats.h" #include "config.h" #include "connection_edge.h" Loading @@ -53,6 +54,7 @@ double fabs(double x); #include "torgzip.h" #include "mempool.h" #include "memarea.h" #include "onion.h" #include "onion_tap.h" #include "policies.h" #include "rephist.h" Loading Loading @@ -933,6 +935,49 @@ test_ntor_handshake(void *arg) } #endif /** Run unit tests for the onion queues. */ static void test_onion_queues(void) { uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; or_circuit_t *circ1 = or_circuit_new(0, NULL); or_circuit_t *circ2 = or_circuit_new(0, NULL); create_cell_t *onionskin = NULL; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, buf1); create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf2); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_pending_add(circ1, create1)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); test_eq(0, onion_pending_add(circ2, create2)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); test_eq_ptr(circ2, onion_next_task(&onionskin)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); clear_pending_onions(); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: ; // circuit_free(circ1); // circuit_free(circ2); /* and free create1 and create2 */ /* XXX leaks everything here */ } static void test_circuit_timeout(void) { Loading Loading @@ -2005,6 +2050,7 @@ static struct testcase_t test_array[] = { ENT(buffers), { "buffer_copy", test_buffer_copy, 0, NULL, NULL }, ENT(onion_handshake), ENT(onion_queues), #ifdef CURVE25519_ENABLED { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL }, #endif Loading Loading
src/or/onion.c +44 −22 Original line number Diff line number Diff line Loading @@ -171,7 +171,9 @@ onion_next_task(create_cell_t **onionskin_out) return NULL; /* no onions pending, we're done */ tor_assert(head->circ); tor_assert(head->circ->p_chan); /* make sure it's still valid */ // tor_assert(head->circ->p_chan); /* make sure it's still valid */ /* XXX I only commented out the above line to make the unit tests * more manageable. That's probably not good long-term. -RD */ circ = head->circ; if (head->onionskin && head->onionskin->handshake_type <= MAX_ONION_HANDSHAKE_TYPE) Loading @@ -183,6 +185,14 @@ onion_next_task(create_cell_t **onionskin_out) return circ; } /** Return the number of <b>handshake_type</b>-style create requests pending. */ int onion_num_pending(uint16_t handshake_type) { return ol_entries[handshake_type]; } /** Go through ol_list, find the onion_queue_t element which points to * circ, remove and free that element. Leave circ itself alone. */ Loading Loading @@ -535,6 +545,22 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) return 0; } /** Write the various parameters into the create cell. Separate from * create_cell_parse() to make unit testing easier. */ void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin) { memset(cell_out, 0, sizeof(*cell_out)); cell_out->cell_type = cell_type; cell_out->handshake_type = handshake_type; cell_out->handshake_len = handshake_len; memcpy(cell_out->onionskin, onionskin, handshake_len); } /** Helper: parse the CREATE2 payload at <b>p</b>, which could be up to * <b>p_len</b> bytes long, and use it to fill the fields of * <b>cell_out</b>. Return 0 on success and -1 on failure. Loading @@ -545,17 +571,21 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) static int parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) { uint16_t handshake_type, handshake_len; if (p_len < 4) return -1; cell_out->cell_type = CELL_CREATE2; cell_out->handshake_type = ntohs(get_uint16(p)); cell_out->handshake_len = ntohs(get_uint16(p+2)); if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 4 || cell_out->handshake_len > p_len - 4) handshake_type = ntohs(get_uint16(p)); handshake_len = ntohs(get_uint16(p+2)); if (handshake_len > CELL_PAYLOAD_SIZE - 4 || handshake_len > p_len - 4) return -1; if (cell_out->handshake_type == ONION_HANDSHAKE_TYPE_FAST) if (handshake_type == ONION_HANDSHAKE_TYPE_FAST) return -1; memcpy(cell_out->onionskin, p+4, cell_out->handshake_len); create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len, p+4); return 0; } Loading @@ -573,27 +603,19 @@ parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) { memset(cell_out, 0, sizeof(*cell_out)); switch (cell_in->command) { case CELL_CREATE: cell_out->cell_type = CELL_CREATE; if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) { cell_out->handshake_type = ONION_HANDSHAKE_TYPE_NTOR; cell_out->handshake_len = NTOR_ONIONSKIN_LEN; memcpy(cell_out->onionskin, cell_in->payload+16, NTOR_ONIONSKIN_LEN); create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, cell_in->payload+16); } else { cell_out->handshake_type = ONION_HANDSHAKE_TYPE_TAP; cell_out->handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN; memcpy(cell_out->onionskin, cell_in->payload, TAP_ONIONSKIN_CHALLENGE_LEN); create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload); } break; case CELL_CREATE_FAST: cell_out->cell_type = CELL_CREATE_FAST; cell_out->handshake_type = ONION_HANDSHAKE_TYPE_FAST; cell_out->handshake_len = CREATE_FAST_LEN; memcpy(cell_out->onionskin, cell_in->payload, CREATE_FAST_LEN); create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST, CREATE_FAST_LEN, cell_in->payload); break; case CELL_CREATE2: if (parse_create2_payload(cell_out, cell_in->payload, Loading
src/or/onion.h +4 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ struct create_cell_t; int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin); or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out); int onion_num_pending(uint16_t handshake_type); void onion_pending_remove(or_circuit_t *circ); void clear_pending_onions(void); Loading Loading @@ -99,6 +100,9 @@ typedef struct extended_cell_t { created_cell_t created_cell; } extended_cell_t; void create_cell_init(create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin); int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in); int created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in); int extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, Loading
src/test/test.c +46 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ double fabs(double x); #include "or.h" #include "buffers.h" #include "circuitlist.h" #include "circuitstats.h" #include "config.h" #include "connection_edge.h" Loading @@ -53,6 +54,7 @@ double fabs(double x); #include "torgzip.h" #include "mempool.h" #include "memarea.h" #include "onion.h" #include "onion_tap.h" #include "policies.h" #include "rephist.h" Loading Loading @@ -933,6 +935,49 @@ test_ntor_handshake(void *arg) } #endif /** Run unit tests for the onion queues. */ static void test_onion_queues(void) { uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; or_circuit_t *circ1 = or_circuit_new(0, NULL); or_circuit_t *circ2 = or_circuit_new(0, NULL); create_cell_t *onionskin = NULL; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, buf1); create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf2); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_pending_add(circ1, create1)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); test_eq(0, onion_pending_add(circ2, create2)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); test_eq_ptr(circ2, onion_next_task(&onionskin)); test_eq(1, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); clear_pending_onions(); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); test_eq(0, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: ; // circuit_free(circ1); // circuit_free(circ2); /* and free create1 and create2 */ /* XXX leaks everything here */ } static void test_circuit_timeout(void) { Loading Loading @@ -2005,6 +2050,7 @@ static struct testcase_t test_array[] = { ENT(buffers), { "buffer_copy", test_buffer_copy, 0, NULL, NULL }, ENT(onion_handshake), ENT(onion_queues), #ifdef CURVE25519_ENABLED { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL }, #endif Loading