/** Parse a CREATE, CREATE_FAST, or CREATE2 cell from <b>cell_in</b> into * <b>cell_out</b>. Return 0 on success, -1 on failure. (We reject some * syntactically valid CREATE2 cells that we can't generate or react to.) */ int create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) { switch (cell_in->command) { case CELL_CREATE: if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) { create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, cell_in->payload+16); } else { create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload); } break; case CELL_CREATE_FAST: 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, CELL_PAYLOAD_SIZE) < 0) return -1; break; default: return -1; } return check_create_cell(cell_out, 0); }
/** Run unit tests for the onion queues. */ static void test_onion_queues(void *arg) { 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, *create2_ptr; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); (void)arg; create2_ptr = create2; /* remember, but do not free */ 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); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1)); create1 = NULL; tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2)); create2 = NULL; tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_ptr_op(onionskin, OP_EQ, create2_ptr); clear_pending_onions(); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: circuit_free_(TO_CIRCUIT(circ1)); circuit_free_(TO_CIRCUIT(circ2)); tor_free(create1); tor_free(create2); tor_free(onionskin); }
/** 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. * * Note that part of the body of an EXTEND2 cell is a CREATE2 payload, so * this function is also used for parsing those. */ 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; 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 (handshake_type == ONION_HANDSHAKE_TYPE_FAST) return -1; create_cell_init(cell_out, CELL_CREATE2, handshake_type, handshake_len, p+4); return 0; }