Loading src/or/buffers.c +27 −15 Original line number Diff line number Diff line Loading @@ -1045,28 +1045,34 @@ cell_command_is_var_length(uint8_t command, int linkproto) int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) { char hdr[VAR_CELL_HEADER_SIZE]; char hdr[VAR_CELL_MAX_HEADER_SIZE]; var_cell_t *result; uint8_t command; uint16_t length; const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; const int circ_id_len = get_circ_id_size(wide_circ_ids); const unsigned header_len = get_var_cell_header_size(wide_circ_ids); check(); *out = NULL; if (buf->datalen < VAR_CELL_HEADER_SIZE) if (buf->datalen < header_len) return 0; peek_from_buf(hdr, sizeof(hdr), buf); command = get_uint8(hdr+2); command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) return 0; length = ntohs(get_uint16(hdr+3)); if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) length = ntohs(get_uint16(hdr + circ_id_len + 1)); if (buf->datalen < (size_t)(header_len+length)) return 1; result = var_cell_new(length); result->command = command; if (wide_circ_ids) result->circ_id = ntohl(get_uint32(hdr)); else result->circ_id = ntohs(get_uint16(hdr)); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); buf_remove_from_front(buf, header_len); peek_from_buf((char*) result->payload, length, buf); buf_remove_from_front(buf, length); check(); Loading Loading @@ -1125,30 +1131,36 @@ fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, uint16_t cell_length; var_cell_t *cell; int result = 0; const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; const int circ_id_len = get_circ_id_size(wide_circ_ids); const unsigned header_len = get_var_cell_header_size(wide_circ_ids); *out = NULL; buf_len = evbuffer_get_length(buf); if (buf_len < VAR_CELL_HEADER_SIZE) if (buf_len < header_len) return 0; n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL); tor_assert(n >= VAR_CELL_HEADER_SIZE); n = inspect_evbuffer(buf, &hdr, header_len, &free_hdr, NULL); tor_assert(n >= header_len); command = get_uint8(hdr+2); command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) { goto done; } cell_length = ntohs(get_uint16(hdr+3)); if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) { cell_length = ntohs(get_uint16(hdr + circ_id_len + 1)); if (buf_len < (size_t)(header_len+cell_length)) { result = 1; /* Not all here yet. */ goto done; } cell = var_cell_new(cell_length); cell->command = command; if (wide_circ_ids) cell->circ_id = ntohl(get_uint32(hdr)); else cell->circ_id = ntohs(get_uint16(hdr)); evbuffer_drain(buf, VAR_CELL_HEADER_SIZE); evbuffer_drain(buf, header_len); evbuffer_remove(buf, cell->payload, cell_length); *out = cell; result = 1; Loading src/or/channel.c +12 −2 Original line number Diff line number Diff line Loading @@ -4068,9 +4068,10 @@ channel_num_circuits(channel_t *chan) * This is called when setting up a channel and replaces the old * connection_or_set_circid_type() */ void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd) channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, int consider_identity) { int started_here; crypto_pk_t *our_identity; Loading @@ -4078,6 +4079,15 @@ channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd) tor_assert(chan); started_here = channel_is_outgoing(chan); if (! consider_identity) { if (started_here) chan->circ_id_type = CIRC_ID_TYPE_HIGHER; else chan->circ_id_type = CIRC_ID_TYPE_LOWER; return; } our_identity = started_here ? get_tlsclient_identity_key() : get_server_identity_key(); Loading src/or/channel.h +4 −1 Original line number Diff line number Diff line Loading @@ -143,6 +143,8 @@ struct channel_s { * space should we use? */ ENUM_BF(circ_id_type_t) circ_id_type:2; /** DOCDOC*/ unsigned wide_circ_ids:1; /* * Which circ_id do we try to use next on this connection? This is * always in the range 0..1<<15-1. Loading Loading @@ -447,7 +449,8 @@ int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info); int channel_matches_target_addr_for_extend(channel_t *chan, const tor_addr_t *target); unsigned int channel_num_circuits(channel_t *chan); void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd); void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, int consider_identity); void channel_timestamp_client(channel_t *chan); const char * channel_listener_describe_transport(channel_listener_t *chan_l); Loading src/or/channeltls.c +21 −8 Original line number Diff line number Diff line Loading @@ -600,12 +600,13 @@ channel_tls_write_packed_cell_method(channel_t *chan, packed_cell_t *packed_cell) { channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); size_t cell_network_size = get_cell_network_size(chan->wide_circ_ids); tor_assert(tlschan); tor_assert(packed_cell); tor_assert(tlschan->conn); connection_write_to_buf(packed_cell->body, CELL_NETWORK_SIZE, connection_write_to_buf(packed_cell->body, cell_network_size, TO_CONN(tlschan->conn)); /* This is where the cell is finished; used to be done from relay.c */ Loading Loading @@ -893,7 +894,7 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn) } if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) or_handshake_state_record_cell(conn->handshake_state, cell, 1); or_handshake_state_record_cell(conn, conn->handshake_state, cell, 1); switch (cell->command) { case CELL_PADDING: Loading Loading @@ -1034,7 +1035,8 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn) break; case OR_CONN_STATE_OR_HANDSHAKING_V3: if (var_cell->command != CELL_AUTHENTICATE) or_handshake_state_record_var_cell(conn->handshake_state, var_cell, 1); or_handshake_state_record_var_cell(conn, conn->handshake_state, var_cell, 1); break; /* Everything is allowed */ case OR_CONN_STATE_OPEN: if (conn->link_proto < 3) { Loading Loading @@ -1154,7 +1156,8 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan) connection_or_close_for_error(chan->conn, 0); return -1; } or_handshake_state_record_var_cell(chan->conn->handshake_state, cell, 1); or_handshake_state_record_var_cell(chan->conn, chan->conn->handshake_state, cell, 1); return 0; } Loading Loading @@ -1294,6 +1297,13 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) return; } } /* We set this after sending the verions cell. */ /*XXXXX symbolic const.*/ chan->base_.wide_circ_ids = chan->conn->link_proto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; chan->conn->wide_circ_ids = chan->base_.wide_circ_ids; if (send_certs) { if (connection_or_send_certs_cell(chan->conn) < 0) { log_warn(LD_OR, "Couldn't send certs cell"); Loading Loading @@ -1375,7 +1385,8 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan) tor_assert(tor_digest_is_zero( (const char*)(chan->conn->handshake_state-> authenticated_peer_id))); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); connection_or_init_conn_from_address(chan->conn, &(chan->conn->base_.addr), Loading Loading @@ -1629,7 +1640,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan) ERR("Internal error: Couldn't get RSA key from ID cert."); memcpy(chan->conn->handshake_state->authenticated_peer_id, id_digests->d[DIGEST_SHA1], DIGEST_LEN); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); crypto_pk_free(identity_rcvd); } Loading Loading @@ -1913,7 +1925,8 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan) memcpy(chan->conn->handshake_state->authenticated_peer_id, id_digests->d[DIGEST_SHA1], DIGEST_LEN); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); crypto_pk_free(identity_rcvd); connection_or_init_conn_from_address(chan->conn, Loading src/or/circuitbuild.c +6 −6 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ get_unique_circ_id_by_chan(channel_t *chan) { circid_t test_circ_id; circid_t attempts=0; circid_t high_bit; circid_t high_bit, max_range; tor_assert(chan); Loading @@ -110,17 +110,17 @@ get_unique_circ_id_by_chan(channel_t *chan) "a client with no identity."); return 0; } high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; max_range = (chan->wide_circ_ids) ? (1u<<31) : (1u<<15); high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? max_range : 0; do { /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a /* Sequentially iterate over test_circ_id=1...max_range until we find a * circID such that (high_bit|test_circ_id) is not already used. */ test_circ_id = chan->next_circ_id++; if (test_circ_id == 0 || test_circ_id >= 1<<15) { if (test_circ_id == 0 || test_circ_id >= max_range) { test_circ_id = 1; chan->next_circ_id = 2; } if (++attempts > 1<<15) { if (++attempts > max_range) { /* Make sure we don't loop forever if all circ_id's are used. This * matters because it's an external DoS opportunity. */ Loading Loading
src/or/buffers.c +27 −15 Original line number Diff line number Diff line Loading @@ -1045,28 +1045,34 @@ cell_command_is_var_length(uint8_t command, int linkproto) int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto) { char hdr[VAR_CELL_HEADER_SIZE]; char hdr[VAR_CELL_MAX_HEADER_SIZE]; var_cell_t *result; uint8_t command; uint16_t length; const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; const int circ_id_len = get_circ_id_size(wide_circ_ids); const unsigned header_len = get_var_cell_header_size(wide_circ_ids); check(); *out = NULL; if (buf->datalen < VAR_CELL_HEADER_SIZE) if (buf->datalen < header_len) return 0; peek_from_buf(hdr, sizeof(hdr), buf); command = get_uint8(hdr+2); command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) return 0; length = ntohs(get_uint16(hdr+3)); if (buf->datalen < (size_t)(VAR_CELL_HEADER_SIZE+length)) length = ntohs(get_uint16(hdr + circ_id_len + 1)); if (buf->datalen < (size_t)(header_len+length)) return 1; result = var_cell_new(length); result->command = command; if (wide_circ_ids) result->circ_id = ntohl(get_uint32(hdr)); else result->circ_id = ntohs(get_uint16(hdr)); buf_remove_from_front(buf, VAR_CELL_HEADER_SIZE); buf_remove_from_front(buf, header_len); peek_from_buf((char*) result->payload, length, buf); buf_remove_from_front(buf, length); check(); Loading Loading @@ -1125,30 +1131,36 @@ fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, uint16_t cell_length; var_cell_t *cell; int result = 0; const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; const int circ_id_len = get_circ_id_size(wide_circ_ids); const unsigned header_len = get_var_cell_header_size(wide_circ_ids); *out = NULL; buf_len = evbuffer_get_length(buf); if (buf_len < VAR_CELL_HEADER_SIZE) if (buf_len < header_len) return 0; n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL); tor_assert(n >= VAR_CELL_HEADER_SIZE); n = inspect_evbuffer(buf, &hdr, header_len, &free_hdr, NULL); tor_assert(n >= header_len); command = get_uint8(hdr+2); command = get_uint8(hdr + circ_id_len); if (!(cell_command_is_var_length(command, linkproto))) { goto done; } cell_length = ntohs(get_uint16(hdr+3)); if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) { cell_length = ntohs(get_uint16(hdr + circ_id_len + 1)); if (buf_len < (size_t)(header_len+cell_length)) { result = 1; /* Not all here yet. */ goto done; } cell = var_cell_new(cell_length); cell->command = command; if (wide_circ_ids) cell->circ_id = ntohl(get_uint32(hdr)); else cell->circ_id = ntohs(get_uint16(hdr)); evbuffer_drain(buf, VAR_CELL_HEADER_SIZE); evbuffer_drain(buf, header_len); evbuffer_remove(buf, cell->payload, cell_length); *out = cell; result = 1; Loading
src/or/channel.c +12 −2 Original line number Diff line number Diff line Loading @@ -4068,9 +4068,10 @@ channel_num_circuits(channel_t *chan) * This is called when setting up a channel and replaces the old * connection_or_set_circid_type() */ void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd) channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, int consider_identity) { int started_here; crypto_pk_t *our_identity; Loading @@ -4078,6 +4079,15 @@ channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd) tor_assert(chan); started_here = channel_is_outgoing(chan); if (! consider_identity) { if (started_here) chan->circ_id_type = CIRC_ID_TYPE_HIGHER; else chan->circ_id_type = CIRC_ID_TYPE_LOWER; return; } our_identity = started_here ? get_tlsclient_identity_key() : get_server_identity_key(); Loading
src/or/channel.h +4 −1 Original line number Diff line number Diff line Loading @@ -143,6 +143,8 @@ struct channel_s { * space should we use? */ ENUM_BF(circ_id_type_t) circ_id_type:2; /** DOCDOC*/ unsigned wide_circ_ids:1; /* * Which circ_id do we try to use next on this connection? This is * always in the range 0..1<<15-1. Loading Loading @@ -447,7 +449,8 @@ int channel_matches_extend_info(channel_t *chan, extend_info_t *extend_info); int channel_matches_target_addr_for_extend(channel_t *chan, const tor_addr_t *target); unsigned int channel_num_circuits(channel_t *chan); void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd); void channel_set_circid_type(channel_t *chan, crypto_pk_t *identity_rcvd, int consider_identity); void channel_timestamp_client(channel_t *chan); const char * channel_listener_describe_transport(channel_listener_t *chan_l); Loading
src/or/channeltls.c +21 −8 Original line number Diff line number Diff line Loading @@ -600,12 +600,13 @@ channel_tls_write_packed_cell_method(channel_t *chan, packed_cell_t *packed_cell) { channel_tls_t *tlschan = BASE_CHAN_TO_TLS(chan); size_t cell_network_size = get_cell_network_size(chan->wide_circ_ids); tor_assert(tlschan); tor_assert(packed_cell); tor_assert(tlschan->conn); connection_write_to_buf(packed_cell->body, CELL_NETWORK_SIZE, connection_write_to_buf(packed_cell->body, cell_network_size, TO_CONN(tlschan->conn)); /* This is where the cell is finished; used to be done from relay.c */ Loading Loading @@ -893,7 +894,7 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn) } if (conn->base_.state == OR_CONN_STATE_OR_HANDSHAKING_V3) or_handshake_state_record_cell(conn->handshake_state, cell, 1); or_handshake_state_record_cell(conn, conn->handshake_state, cell, 1); switch (cell->command) { case CELL_PADDING: Loading Loading @@ -1034,7 +1035,8 @@ channel_tls_handle_var_cell(var_cell_t *var_cell, or_connection_t *conn) break; case OR_CONN_STATE_OR_HANDSHAKING_V3: if (var_cell->command != CELL_AUTHENTICATE) or_handshake_state_record_var_cell(conn->handshake_state, var_cell, 1); or_handshake_state_record_var_cell(conn, conn->handshake_state, var_cell, 1); break; /* Everything is allowed */ case OR_CONN_STATE_OPEN: if (conn->link_proto < 3) { Loading Loading @@ -1154,7 +1156,8 @@ enter_v3_handshake_with_cell(var_cell_t *cell, channel_tls_t *chan) connection_or_close_for_error(chan->conn, 0); return -1; } or_handshake_state_record_var_cell(chan->conn->handshake_state, cell, 1); or_handshake_state_record_var_cell(chan->conn, chan->conn->handshake_state, cell, 1); return 0; } Loading Loading @@ -1294,6 +1297,13 @@ channel_tls_process_versions_cell(var_cell_t *cell, channel_tls_t *chan) return; } } /* We set this after sending the verions cell. */ /*XXXXX symbolic const.*/ chan->base_.wide_circ_ids = chan->conn->link_proto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS; chan->conn->wide_circ_ids = chan->base_.wide_circ_ids; if (send_certs) { if (connection_or_send_certs_cell(chan->conn) < 0) { log_warn(LD_OR, "Couldn't send certs cell"); Loading Loading @@ -1375,7 +1385,8 @@ channel_tls_process_netinfo_cell(cell_t *cell, channel_tls_t *chan) tor_assert(tor_digest_is_zero( (const char*)(chan->conn->handshake_state-> authenticated_peer_id))); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), NULL, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); connection_or_init_conn_from_address(chan->conn, &(chan->conn->base_.addr), Loading Loading @@ -1629,7 +1640,8 @@ channel_tls_process_certs_cell(var_cell_t *cell, channel_tls_t *chan) ERR("Internal error: Couldn't get RSA key from ID cert."); memcpy(chan->conn->handshake_state->authenticated_peer_id, id_digests->d[DIGEST_SHA1], DIGEST_LEN); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); crypto_pk_free(identity_rcvd); } Loading Loading @@ -1913,7 +1925,8 @@ channel_tls_process_authenticate_cell(var_cell_t *cell, channel_tls_t *chan) memcpy(chan->conn->handshake_state->authenticated_peer_id, id_digests->d[DIGEST_SHA1], DIGEST_LEN); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd); channel_set_circid_type(TLS_CHAN_TO_BASE(chan), identity_rcvd, chan->conn->link_proto < MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS); crypto_pk_free(identity_rcvd); connection_or_init_conn_from_address(chan->conn, Loading
src/or/circuitbuild.c +6 −6 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ get_unique_circ_id_by_chan(channel_t *chan) { circid_t test_circ_id; circid_t attempts=0; circid_t high_bit; circid_t high_bit, max_range; tor_assert(chan); Loading @@ -110,17 +110,17 @@ get_unique_circ_id_by_chan(channel_t *chan) "a client with no identity."); return 0; } high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? 1<<15 : 0; max_range = (chan->wide_circ_ids) ? (1u<<31) : (1u<<15); high_bit = (chan->circ_id_type == CIRC_ID_TYPE_HIGHER) ? max_range : 0; do { /* Sequentially iterate over test_circ_id=1...1<<15-1 until we find a /* Sequentially iterate over test_circ_id=1...max_range until we find a * circID such that (high_bit|test_circ_id) is not already used. */ test_circ_id = chan->next_circ_id++; if (test_circ_id == 0 || test_circ_id >= 1<<15) { if (test_circ_id == 0 || test_circ_id >= max_range) { test_circ_id = 1; chan->next_circ_id = 2; } if (++attempts > 1<<15) { if (++attempts > max_range) { /* Make sure we don't loop forever if all circ_id's are used. This * matters because it's an external DoS opportunity. */ Loading