diff options
author | Nick Mathewson <nickm@torproject.org> | 2012-12-05 23:59:12 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2013-01-03 11:29:47 -0500 |
commit | 1ed4786dba8912ab7a6eb16adf7554cf9a5c1ed1 (patch) | |
tree | a2b5d39e835482408b8100c8b1e73c437605e266 /src/or | |
parent | 115e8fe9a5342d9f04e14d155d11e8c88f551c84 (diff) | |
download | tor-1ed4786dba8912ab7a6eb16adf7554cf9a5c1ed1.tar tor-1ed4786dba8912ab7a6eb16adf7554cf9a5c1ed1.tar.gz |
Implement scheme to allow ntor requests/responses via older servers
Diffstat (limited to 'src/or')
-rw-r--r-- | src/or/onion.c | 73 |
1 files changed, 57 insertions, 16 deletions
diff --git a/src/or/onion.c b/src/or/onion.c index ce5eb93b1..753ddcff7 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -337,7 +337,7 @@ onion_skin_server_handshake(int type, break; case ONION_HANDSHAKE_TYPE_NTOR: #ifdef CURVE25519_ENABLED - if (onionskin_len != NTOR_ONIONSKIN_LEN) + if (onionskin_len < NTOR_ONIONSKIN_LEN) return -1; { size_t keys_tmp_len = keys_out_len + DIGEST_LEN; @@ -409,7 +409,7 @@ onion_skin_client_handshake(int type, return 0; #ifdef CURVE25519_ENABLED case ONION_HANDSHAKE_TYPE_NTOR: - if (reply_len != NTOR_REPLY_LEN) + if (reply_len < NTOR_REPLY_LEN) return -1; { size_t keys_tmp_len = keys_out_len + DIGEST_LEN; @@ -442,7 +442,8 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) { switch (cell->cell_type) { case CELL_CREATE: - if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP) + if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP && + cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR) return -1; break; case CELL_CREATE_FAST: @@ -502,6 +503,14 @@ parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) return 0; } +/** Magic string which, in a CREATE or EXTEND cell, indicates that a seeming + * TAP payload is really an ntor payload. We'd do away with this if every + * relay supported EXTEND2, but we want to be able to extend from A to B with + * ntor even when A doesn't understand EXTEND2 and so can't generate a + * CREATE2 cell. + **/ +#define NTOR_CREATE_MAGIC "ntorNTORntorNTOR" + /** 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.) */ @@ -513,9 +522,16 @@ create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) switch (cell_in->command) { case CELL_CREATE: cell_out->cell_type = CELL_CREATE; - 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); + 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); + } 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); + } break; case CELL_CREATE_FAST: cell_out->cell_type = CELL_CREATE_FAST; @@ -603,7 +619,8 @@ check_extend_cell(const extend_cell_t *cell) if (cell->cell_type != RELAY_COMMAND_EXTEND) return -1; } else if (cell->create_cell.cell_type == CELL_CREATE2) { - if (cell->cell_type != RELAY_COMMAND_EXTEND2) + if (cell->cell_type != RELAY_COMMAND_EXTEND2 && + cell->cell_type != RELAY_COMMAND_EXTEND) return -1; } else { /* In particular, no CREATE_FAST cells are allowed */ @@ -647,11 +664,19 @@ extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, tor_addr_from_ipv4n(&cell_out->orport_ipv4.addr, get_uint32(payload)); cell_out->orport_ipv4.port = ntohs(get_uint16(payload+4)); tor_addr_make_unspec(&cell_out->orport_ipv6.addr); - cell_out->create_cell.cell_type = CELL_CREATE; - cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP; - cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN; - memcpy(cell_out->create_cell.onionskin, payload + 6, - TAP_ONIONSKIN_CHALLENGE_LEN); + if (tor_memeq(payload + 6, NTOR_CREATE_MAGIC, 16)) { + cell_out->create_cell.cell_type = CELL_CREATE2; + cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR; + cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN; + memcpy(cell_out->create_cell.onionskin, payload + 22, + NTOR_ONIONSKIN_LEN); + } else { + cell_out->create_cell.cell_type = CELL_CREATE; + cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP; + cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN; + memcpy(cell_out->create_cell.onionskin, payload + 6, + TAP_ONIONSKIN_CHALLENGE_LEN); + } memcpy(cell_out->node_id, payload + 6 + TAP_ONIONSKIN_CHALLENGE_LEN, DIGEST_LEN); break; @@ -787,17 +812,28 @@ extended_cell_parse(extended_cell_t *cell_out, int create_cell_format(cell_t *cell_out, const create_cell_t *cell_in) { + uint8_t *p; + size_t space; if (check_create_cell(cell_in, 0) < 0) return -1; memset(cell_out->payload, 0, sizeof(cell_out->payload)); cell_out->command = cell_in->cell_type; + p = cell_out->payload; + space = sizeof(cell_out->payload); + switch (cell_in->cell_type) { case CELL_CREATE: + if (cell_in->handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { + memcpy(p, NTOR_CREATE_MAGIC, 16); + p += 16; + space -= 16; + } + /* Fall through */ case CELL_CREATE_FAST: - tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)); - memcpy(cell_out->payload, cell_in->onionskin, cell_in->handshake_len); + tor_assert(cell_in->handshake_len <= space); + memcpy(p, cell_in->onionskin, cell_in->handshake_len); break; case CELL_CREATE2: tor_assert(cell_in->handshake_len <= sizeof(cell_out->payload)-4); @@ -865,8 +901,13 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out, *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN; set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr)); set_uint16(p+4, ntohs(cell_in->orport_ipv4.port)); - memcpy(p+6, cell_in->create_cell.onionskin, - TAP_ONIONSKIN_CHALLENGE_LEN); + if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { + memcpy(p+6, NTOR_CREATE_MAGIC, 16); + memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN); + } else { + memcpy(p+6, cell_in->create_cell.onionskin, + TAP_ONIONSKIN_CHALLENGE_LEN); + } memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN); } break; |