Commit d6634001 authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

Merge remote-tracking branch 'public/wide_circ_ids'

Conflicts:
	src/or/channel.h
	src/or/connection_or.c
	src/or/cpuworker.c
parents 5fcc5dfa 076654ce
Loading
Loading
Loading
Loading
+27 −15
Original line number Diff line number Diff line
@@ -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();
@@ -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;
+12 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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();

+4 −1
Original line number Diff line number Diff line
@@ -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.
@@ -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);
+21 −8
Original line number Diff line number Diff line
@@ -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 */
@@ -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:
@@ -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) {
@@ -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;
}

@@ -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");
@@ -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),
@@ -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);
    }

@@ -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,
+6 −6
Original line number Diff line number Diff line
@@ -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);

@@ -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