Пример #1
0
/* Test helper function: Make sure that a bridge line gets parsed
 * properly. Also make sure that the resulting bridge_line_t structure
 * has its fields set correctly. */
static void
good_bridge_line_test(const char *string, const char *test_addrport,
                      const char *test_digest, const char *test_transport,
                      const smartlist_t *test_socks_args)
{
  char *tmp = NULL;
  bridge_line_t *bridge_line = parse_bridge_line(string);
  test_assert(bridge_line);

  /* test addrport */
  tmp = tor_strdup(fmt_addrport(&bridge_line->addr, bridge_line->port));
  test_streq(test_addrport, tmp);
  tor_free(tmp);

  /* If we were asked to validate a digest, but we did not get a
     digest after parsing, we failed. */
  if (test_digest && tor_digest_is_zero(bridge_line->digest))
    test_assert(0);

  /* If we were not asked to validate a digest, and we got a digest
     after parsing, we failed again. */
  if (!test_digest && !tor_digest_is_zero(bridge_line->digest))
    test_assert(0);

  /* If we were asked to validate a digest, and we got a digest after
     parsing, make sure it's correct. */
  if (test_digest) {
    tmp = tor_strdup(hex_str(bridge_line->digest, DIGEST_LEN));
    tor_strlower(tmp);
    test_streq(test_digest, tmp);
    tor_free(tmp);
  }

  /* If we were asked to validate a transport name, make sure tha it
     matches with the transport name that was parsed. */
  if (test_transport && !bridge_line->transport_name)
    test_assert(0);
  if (!test_transport && bridge_line->transport_name)
    test_assert(0);
  if (test_transport)
    test_streq(test_transport, bridge_line->transport_name);

  /* Validate the SOCKS argument smartlist. */
  if (test_socks_args && !bridge_line->socks_args)
    test_assert(0);
  if (!test_socks_args && bridge_line->socks_args)
    test_assert(0);
  if (test_socks_args)
    test_assert(smartlist_strings_eq(test_socks_args,
                                     bridge_line->socks_args));

 done:
  tor_free(tmp);
  bridge_line_free(bridge_line);
}
Пример #2
0
/** Append to <b>out</b> all circuits in state OR_WAIT waiting for
 * the given connection. */
void
circuit_get_all_pending_on_or_conn(smartlist_t *out, or_connection_t *or_conn)
{
  tor_assert(out);
  tor_assert(or_conn);

  if (!circuits_pending_or_conns)
    return;

  SMARTLIST_FOREACH_BEGIN(circuits_pending_or_conns, circuit_t *, circ) {
    if (circ->marked_for_close)
      continue;
    if (!circ->n_hop)
      continue;
    tor_assert(circ->state == CIRCUIT_STATE_OR_WAIT);
    if (tor_digest_is_zero(circ->n_hop->identity_digest)) {
      /* Look at addr/port. This is an unkeyed connection. */
      if (!tor_addr_eq(&circ->n_hop->addr, &or_conn->_base.addr) ||
          circ->n_hop->port != or_conn->_base.port)
        continue;
    } else {
      /* We expected a key. See if it's the right one. */
      if (memcmp(or_conn->identity_digest,
                 circ->n_hop->identity_digest, DIGEST_LEN))
        continue;
    }
    smartlist_add(out, circ);
  } SMARTLIST_FOREACH_END(circ);
}
Пример #3
0
/** If conn is listed in orconn_identity_map, remove it, and clear
 * conn->identity_digest.  Otherwise do nothing. */
void
connection_or_remove_from_identity_map(or_connection_t *conn)
{
  or_connection_t *tmp;
  tor_assert(conn);
  if (!orconn_identity_map)
    return;
  tmp = digestmap_get(orconn_identity_map, conn->identity_digest);
  if (!tmp) {
    if (!tor_digest_is_zero(conn->identity_digest)) {
      log_warn(LD_BUG, "Didn't find connection '%s' on identity map when "
               "trying to remove it.",
               conn->nickname ? conn->nickname : "NULL");
    }
    return;
  }
  if (conn == tmp) {
    if (conn->next_with_same_id)
      digestmap_set(orconn_identity_map, conn->identity_digest,
                    conn->next_with_same_id);
    else
      digestmap_remove(orconn_identity_map, conn->identity_digest);
  } else {
    while (tmp->next_with_same_id) {
      if (tmp->next_with_same_id == conn) {
        tmp->next_with_same_id = conn->next_with_same_id;
        break;
      }
      tmp = tmp->next_with_same_id;
    }
  }
  memset(conn->identity_digest, 0, DIGEST_LEN);
  conn->next_with_same_id = NULL;
}
Пример #4
0
/* Test connection_or_remove_from_ext_or_id_map and
 * connection_or_set_ext_or_identifier */
static void
test_ext_or_id_map(void *arg)
{
  or_connection_t *c1 = NULL, *c2 = NULL, *c3 = NULL;
  char *idp = NULL, *idp2 = NULL;
  (void)arg;

  /* pre-initialization */
  tt_ptr_op(NULL, OP_EQ,
            connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));

  c1 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  c2 = or_connection_new(CONN_TYPE_EXT_OR, AF_INET);
  c3 = or_connection_new(CONN_TYPE_OR, AF_INET);

  tt_ptr_op(c1->ext_or_conn_id, OP_NE, NULL);
  tt_ptr_op(c2->ext_or_conn_id, OP_NE, NULL);
  tt_ptr_op(c3->ext_or_conn_id, OP_EQ, NULL);

  tt_ptr_op(c1, OP_EQ, connection_or_get_by_ext_or_id(c1->ext_or_conn_id));
  tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(c2->ext_or_conn_id));
  tt_ptr_op(NULL, OP_EQ,
            connection_or_get_by_ext_or_id("xxxxxxxxxxxxxxxxxxxx"));

  idp = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);

  /* Give c2 a new ID. */
  connection_or_set_ext_or_identifier(c2);
  tt_mem_op(idp, OP_NE, c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  idp2 = tor_memdup(c2->ext_or_conn_id, EXT_OR_CONN_ID_LEN);
  tt_assert(!tor_digest_is_zero(idp2));

  tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
  tt_ptr_op(c2, OP_EQ, connection_or_get_by_ext_or_id(idp2));

  /* Now remove it. */
  connection_or_remove_from_ext_or_id_map(c2);
  tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp));
  tt_ptr_op(NULL, OP_EQ, connection_or_get_by_ext_or_id(idp2));

 done:
  if (c1)
    connection_free_(TO_CONN(c1));
  if (c2)
    connection_free_(TO_CONN(c2));
  if (c3)
    connection_free_(TO_CONN(c3));
  tor_free(idp);
  tor_free(idp2);
  connection_or_clear_ext_or_id_map();
}
Пример #5
0
/** Helper: return 0 if <b>cell</b> appears valid, -1 otherwise. */
static int
check_extend_cell(const extend_cell_t *cell)
{
  if (tor_digest_is_zero((const char*)cell->node_id))
    return -1;
  /* We don't currently allow EXTEND2 cells without an IPv4 address */
  if (tor_addr_family(&cell->orport_ipv4.addr) == AF_UNSPEC)
    return -1;
  if (cell->create_cell.cell_type == CELL_CREATE) {
    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 &&
        cell->cell_type != RELAY_COMMAND_EXTEND)
      return -1;
  } else {
    /* In particular, no CREATE_FAST cells are allowed */
    return -1;
  }
  if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST)
    return -1;

  return check_create_cell(&cell->create_cell, 1);
}
Пример #6
0
/** Process a 'netinfo' cell: read and act on its contents, and set the
 * connection state to "open". */
static void
command_process_netinfo_cell(cell_t *cell, or_connection_t *conn)
{
  time_t timestamp;
  uint8_t my_addr_type;
  uint8_t my_addr_len;
  const uint8_t *my_addr_ptr;
  const uint8_t *cp, *end;
  uint8_t n_other_addrs;
  time_t now = time(NULL);

  long apparent_skew = 0;
  uint32_t my_apparent_addr = 0;

  if (conn->link_proto < 2) {
    log_fn(LOG_PROTOCOL_WARN, LD_OR,
           "Received a NETINFO cell on %s connection; dropping.",
           conn->link_proto == 0 ? "non-versioned" : "a v1");
    return;
  }
  if (conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V2 &&
      conn->_base.state != OR_CONN_STATE_OR_HANDSHAKING_V3) {
    log_fn(LOG_PROTOCOL_WARN, LD_OR,
           "Received a NETINFO cell on non-handshaking connection; dropping.");
    return;
  }
  tor_assert(conn->handshake_state &&
             conn->handshake_state->received_versions);

  if (conn->_base.state == OR_CONN_STATE_OR_HANDSHAKING_V3) {
    tor_assert(conn->link_proto >= 3);
    if (conn->handshake_state->started_here) {
      if (!conn->handshake_state->authenticated) {
        log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got a NETINFO cell from server, "
               "but no authentication.  Closing the connection.");
        connection_mark_for_close(TO_CONN(conn));
        return;
      }
    } else {
      /* we're the server.  If the client never authenticated, we have
         some housekeeping to do.*/
      if (!conn->handshake_state->authenticated) {
        tor_assert(tor_digest_is_zero(
                  (const char*)conn->handshake_state->authenticated_peer_id));
        connection_or_set_circid_type(conn, NULL);

        connection_or_init_conn_from_address(conn,
                  &conn->_base.addr,
                  conn->_base.port,
                  (const char*)conn->handshake_state->authenticated_peer_id,
                  0);
      }
    }
  }

  /* Decode the cell. */
  timestamp = ntohl(get_uint32(cell->payload));
  if (labs(now - conn->handshake_state->sent_versions_at) < 180) {
    apparent_skew = now - timestamp;
  }

  my_addr_type = (uint8_t) cell->payload[4];
  my_addr_len = (uint8_t) cell->payload[5];
  my_addr_ptr = (uint8_t*) cell->payload + 6;
  end = cell->payload + CELL_PAYLOAD_SIZE;
  cp = cell->payload + 6 + my_addr_len;
  if (cp >= end) {
    log_fn(LOG_PROTOCOL_WARN, LD_OR,
           "Addresses too long in netinfo cell; closing connection.");
    connection_mark_for_close(TO_CONN(conn));
    return;
  } else if (my_addr_type == RESOLVED_TYPE_IPV4 && my_addr_len == 4) {
    my_apparent_addr = ntohl(get_uint32(my_addr_ptr));
  }

  n_other_addrs = (uint8_t) *cp++;
  while (n_other_addrs && cp < end-2) {
    /* Consider all the other addresses; if any matches, this connection is
     * "canonical." */
    tor_addr_t addr;
    const uint8_t *next =
      decode_address_from_payload(&addr, cp, (int)(end-cp));
    if (next == NULL) {
      log_fn(LOG_PROTOCOL_WARN,  LD_OR,
             "Bad address in netinfo cell; closing connection.");
      connection_mark_for_close(TO_CONN(conn));
      return;
    }
    if (tor_addr_eq(&addr, &conn->real_addr)) {
      conn->is_canonical = 1;
      break;
    }
    cp = next;
    --n_other_addrs;
  }

  /* Act on apparent skew. */
  /** Warn when we get a netinfo skew with at least this value. */
#define NETINFO_NOTICE_SKEW 3600
  if (labs(apparent_skew) > NETINFO_NOTICE_SKEW &&
      router_get_by_id_digest(conn->identity_digest)) {
    char dbuf[64];
    int severity;
    /*XXXX be smarter about when everybody says we are skewed. */
    if (router_digest_is_trusted_dir(conn->identity_digest))
      severity = LOG_WARN;
    else
      severity = LOG_INFO;
    format_time_interval(dbuf, sizeof(dbuf), apparent_skew);
    log_fn(severity, LD_GENERAL, "Received NETINFO cell with skewed time from "
           "server at %s:%d.  It seems that our clock is %s by %s, or "
           "that theirs is %s. Tor requires an accurate clock to work: "
           "please check your time and date settings.",
           conn->_base.address, (int)conn->_base.port,
           apparent_skew>0 ? "ahead" : "behind", dbuf,
           apparent_skew>0 ? "behind" : "ahead");
    if (severity == LOG_WARN) /* only tell the controller if an authority */
      control_event_general_status(LOG_WARN,
                          "CLOCK_SKEW SKEW=%ld SOURCE=OR:%s:%d",
                          apparent_skew,
                          conn->_base.address, conn->_base.port);
  }

  /* XXX maybe act on my_apparent_addr, if the source is sufficiently
   * trustworthy. */
  (void)my_apparent_addr;

  if (connection_or_set_state_open(conn)<0) {
    log_fn(LOG_PROTOCOL_WARN, LD_OR, "Got good NETINFO cell from %s:%d; but "
           "was unable to make the OR connection become open.",
           safe_str_client(conn->_base.address),
           conn->_base.port);
    connection_mark_for_close(TO_CONN(conn));
  } else {
    log_info(LD_OR, "Got good NETINFO cell from %s:%d; OR connection is now "
             "open, using protocol version %d. Its ID digest is %s",
             safe_str_client(conn->_base.address),
             conn->_base.port, (int)conn->link_proto,
             hex_str(conn->identity_digest, DIGEST_LEN));
  }
  assert_connection_ok(TO_CONN(conn),time(NULL));
}
Пример #7
0
/* Make sure rend_data_t is valid at creation, destruction and when
 * duplicated. */
static void
test_hs_rend_data(void *arg)
{
  int rep;
  rend_data_t *client = NULL, *client_dup = NULL;
  /* Binary format of a descriptor ID. */
  char desc_id[DIGEST_LEN];
  char client_cookie[REND_DESC_COOKIE_LEN];
  time_t now = time(NULL);
  rend_data_t *service_dup = NULL;
  rend_data_t *service = NULL;

  (void)arg;

  base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32,
                REND_DESC_ID_V2_LEN_BASE32);
  memset(client_cookie, 'e', sizeof(client_cookie));

  client = rend_data_client_create(STR_HS_ADDR, desc_id, client_cookie,
                                   REND_NO_AUTH);
  tt_assert(client);
  rend_data_v2_t *client_v2 = TO_REND_DATA_V2(client);
  tt_int_op(client_v2->auth_type, OP_EQ, REND_NO_AUTH);
  tt_str_op(client_v2->onion_address, OP_EQ, STR_HS_ADDR);
  tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
  tt_mem_op(client_v2->descriptor_cookie, OP_EQ, client_cookie,
            sizeof(client_cookie));
  tt_assert(client->hsdirs_fp);
  tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0);
  for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
    int ret = rend_compute_v2_desc_id(desc_id, client_v2->onion_address,
                                      client_v2->descriptor_cookie, now, rep);
    /* That shouldn't never fail. */
    tt_int_op(ret, OP_EQ, 0);
    tt_mem_op(client_v2->descriptor_id[rep], OP_EQ, desc_id,
              sizeof(desc_id));
  }
  /* The rest should be zeroed because this is a client request. */
  tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1);
  tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1);

  /* Test dup(). */
  client_dup = rend_data_dup(client);
  tt_assert(client_dup);
  rend_data_v2_t *client_dup_v2 = TO_REND_DATA_V2(client_dup);
  tt_int_op(client_dup_v2->auth_type, OP_EQ, client_v2->auth_type);
  tt_str_op(client_dup_v2->onion_address, OP_EQ, client_v2->onion_address);
  tt_mem_op(client_dup_v2->desc_id_fetch, OP_EQ, client_v2->desc_id_fetch,
            sizeof(client_dup_v2->desc_id_fetch));
  tt_mem_op(client_dup_v2->descriptor_cookie, OP_EQ,
            client_v2->descriptor_cookie,
            sizeof(client_dup_v2->descriptor_cookie));

  tt_assert(client_dup->hsdirs_fp);
  tt_int_op(smartlist_len(client_dup->hsdirs_fp), OP_EQ, 0);
  for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
    tt_mem_op(client_dup_v2->descriptor_id[rep], OP_EQ,
              client_v2->descriptor_id[rep], DIGEST_LEN);
  }
  /* The rest should be zeroed because this is a client request. */
  tt_int_op(tor_digest_is_zero(client_dup_v2->rend_pk_digest), OP_EQ, 1);
  tt_int_op(tor_digest_is_zero(client_dup->rend_cookie), OP_EQ, 1);
  rend_data_free(client);
  client = NULL;
  rend_data_free(client_dup);
  client_dup = NULL;

  /* Reset state. */
  base32_decode(desc_id, sizeof(desc_id), STR_DESC_ID_BASE32,
                REND_DESC_ID_V2_LEN_BASE32);
  memset(client_cookie, 'e', sizeof(client_cookie));

  /* Try with different parameters here for which some content should be
   * zeroed out. */
  client = rend_data_client_create(NULL, desc_id, NULL, REND_BASIC_AUTH);
  tt_assert(client);
  client_v2 = TO_REND_DATA_V2(client);
  tt_int_op(client_v2->auth_type, OP_EQ, REND_BASIC_AUTH);
  tt_int_op(strlen(client_v2->onion_address), OP_EQ, 0);
  tt_mem_op(client_v2->desc_id_fetch, OP_EQ, desc_id, sizeof(desc_id));
  tt_int_op(tor_mem_is_zero(client_v2->descriptor_cookie,
                            sizeof(client_v2->descriptor_cookie)), OP_EQ, 1);
  tt_assert(client->hsdirs_fp);
  tt_int_op(smartlist_len(client->hsdirs_fp), OP_EQ, 0);
  for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
    tt_int_op(tor_digest_is_zero(client_v2->descriptor_id[rep]), OP_EQ, 1);
  }
  /* The rest should be zeroed because this is a client request. */
  tt_int_op(tor_digest_is_zero(client_v2->rend_pk_digest), OP_EQ, 1);
  tt_int_op(tor_digest_is_zero(client->rend_cookie), OP_EQ, 1);
  rend_data_free(client);
  client = NULL;

  /* Let's test the service object now. */
  char rend_pk_digest[DIGEST_LEN];
  uint8_t rend_cookie[DIGEST_LEN];
  memset(rend_pk_digest, 'f', sizeof(rend_pk_digest));
  memset(rend_cookie, 'g', sizeof(rend_cookie));

  service = rend_data_service_create(STR_HS_ADDR, rend_pk_digest,
                                     rend_cookie, REND_NO_AUTH);
  tt_assert(service);
  rend_data_v2_t *service_v2 = TO_REND_DATA_V2(service);
  tt_int_op(service_v2->auth_type, OP_EQ, REND_NO_AUTH);
  tt_str_op(service_v2->onion_address, OP_EQ, STR_HS_ADDR);
  tt_mem_op(service_v2->rend_pk_digest, OP_EQ, rend_pk_digest,
            sizeof(rend_pk_digest));
  tt_mem_op(service->rend_cookie, OP_EQ, rend_cookie, sizeof(rend_cookie));
  tt_assert(service->hsdirs_fp);
  tt_int_op(smartlist_len(service->hsdirs_fp), OP_EQ, 0);
  for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
    tt_int_op(tor_digest_is_zero(service_v2->descriptor_id[rep]), OP_EQ, 1);
  }
  /* The rest should be zeroed because this is a service request. */
  tt_int_op(tor_digest_is_zero(service_v2->descriptor_cookie), OP_EQ, 1);
  tt_int_op(tor_digest_is_zero(service_v2->desc_id_fetch), OP_EQ, 1);

  /* Test dup(). */
  service_dup = rend_data_dup(service);
  rend_data_v2_t *service_dup_v2 = TO_REND_DATA_V2(service_dup);
  tt_assert(service_dup);
  tt_int_op(service_dup_v2->auth_type, OP_EQ, service_v2->auth_type);
  tt_str_op(service_dup_v2->onion_address, OP_EQ, service_v2->onion_address);
  tt_mem_op(service_dup_v2->rend_pk_digest, OP_EQ, service_v2->rend_pk_digest,
            sizeof(service_dup_v2->rend_pk_digest));
  tt_mem_op(service_dup->rend_cookie, OP_EQ, service->rend_cookie,
            sizeof(service_dup->rend_cookie));
  tt_assert(service_dup->hsdirs_fp);
  tt_int_op(smartlist_len(service_dup->hsdirs_fp), OP_EQ, 0);
  for (rep = 0; rep < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; rep++) {
    tt_assert(tor_digest_is_zero(service_dup_v2->descriptor_id[rep]));
  }
  /* The rest should be zeroed because this is a service request. */
  tt_int_op(tor_digest_is_zero(service_dup_v2->descriptor_cookie), OP_EQ, 1);
  tt_int_op(tor_digest_is_zero(service_dup_v2->desc_id_fetch), OP_EQ, 1);

 done:
  rend_data_free(service);
  rend_data_free(service_dup);
  rend_data_free(client);
  rend_data_free(client_dup);
}