Example #1
0
/** Called when we're trying to connect an ap conn; sends an INTRODUCE1 cell
 * down introcirc if possible.
 */
int
rend_client_send_introduction(origin_circuit_t *introcirc,
                              origin_circuit_t *rendcirc)
{
  const or_options_t *options = get_options();
  size_t payload_len;
  int r, v3_shift = 0;
  char payload[RELAY_PAYLOAD_SIZE];
  char tmp[RELAY_PAYLOAD_SIZE];
  rend_cache_entry_t *entry = NULL;
  crypt_path_t *cpath;
  off_t dh_offset;
  crypto_pk_t *intro_key = NULL;
  int status = 0;
  const char *onion_address;

  tor_assert(introcirc->base_.purpose == CIRCUIT_PURPOSE_C_INTRODUCING);
  tor_assert(rendcirc->base_.purpose == CIRCUIT_PURPOSE_C_REND_READY);
  tor_assert(introcirc->rend_data);
  tor_assert(rendcirc->rend_data);
  tor_assert(!rend_cmp_service_ids(rend_data_get_address(introcirc->rend_data),
                                  rend_data_get_address(rendcirc->rend_data)));
  assert_circ_anonymity_ok(introcirc, options);
  assert_circ_anonymity_ok(rendcirc, options);
  onion_address = rend_data_get_address(introcirc->rend_data);

  r = rend_cache_lookup_entry(onion_address, -1, &entry);
  /* An invalid onion address is not possible else we have a big issue. */
  tor_assert(r != -EINVAL);
  if (r < 0 || !rend_client_any_intro_points_usable(entry)) {
    /* If the descriptor is not found or the intro points are not usable
     * anymore, trigger a fetch. */
    log_info(LD_REND,
             "query %s didn't have valid rend desc in cache. "
             "Refetching descriptor.",
             safe_str_client(onion_address));
    rend_client_refetch_v2_renddesc(introcirc->rend_data);
    {
      connection_t *conn;

      while ((conn = connection_get_by_type_state_rendquery(CONN_TYPE_AP,
                       AP_CONN_STATE_CIRCUIT_WAIT, onion_address))) {
        connection_ap_mark_as_waiting_for_renddesc(TO_ENTRY_CONN(conn));
      }
    }

    status = -1;
    goto cleanup;
  }

  /* first 20 bytes of payload are the hash of the service's pk */
  intro_key = NULL;
  SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
                    intro, {
    if (tor_memeq(introcirc->build_state->chosen_exit->identity_digest,
                intro->extend_info->identity_digest, DIGEST_LEN)) {
      intro_key = intro->intro_key;
      break;
    }
  });
Example #2
0
/** If we aren't currently dormant, close all connections and become
 * dormant. */
static void
hibernate_go_dormant(time_t now)
{
  connection_t *conn;

  if (hibernate_state == HIBERNATE_STATE_DORMANT)
    return;
  else if (hibernate_state == HIBERNATE_STATE_LOWBANDWIDTH)
    hibernate_state = HIBERNATE_STATE_DORMANT;
  else
    hibernate_begin(HIBERNATE_STATE_DORMANT, now);

  log_notice(LD_ACCT,"Going dormant. Blowing away remaining connections.");

  /* Close all OR/AP/exit conns. Leave dir conns because we still want
   * to be able to upload server descriptors so people know we're still
   * running, and download directories so we can detect if we're obsolete.
   * Leave control conns because we still want to be controllable.
   */
  while ((conn = connection_get_by_type(CONN_TYPE_OR)) ||
         (conn = connection_get_by_type(CONN_TYPE_AP)) ||
         (conn = connection_get_by_type(CONN_TYPE_EXIT))) {
    if (CONN_IS_EDGE(conn))
      connection_edge_end(TO_EDGE_CONN(conn), END_STREAM_REASON_HIBERNATING);
    log_info(LD_NET,"Closing conn type %d", conn->type);
    if (conn->type == CONN_TYPE_AP) /* send socks failure if needed */
      connection_mark_unattached_ap(TO_ENTRY_CONN(conn),
                                    END_STREAM_REASON_HIBERNATING);
    else if (conn->type == CONN_TYPE_OR) {
      if (TO_OR_CONN(conn)->chan) {
        channel_mark_for_close(TLS_CHAN_TO_BASE(TO_OR_CONN(conn)->chan));
      } else {
         connection_mark_for_close(conn);
      }
    } else
      connection_mark_for_close(conn);
  }

  if (now < interval_wakeup_time)
    hibernate_end_time = interval_wakeup_time;
  else
    hibernate_end_time = interval_end_time;

  accounting_record_bandwidth_usage(now, get_or_state());

  or_state_mark_dirty(get_or_state(),
                      get_options()->AvoidDiskWrites ? now+600 : 0);
}
Example #3
0
static int
test_conn_get_basic_teardown(const struct testcase_t *tc, void *arg)
{
  (void)tc;
  connection_t *conn = arg;

  tt_assert(conn);
  assert_connection_ok(conn, time(NULL));

  /* teardown the connection as fast as possible */
  if (conn->linked_conn) {
    assert_connection_ok(conn->linked_conn, time(NULL));

    /* We didn't call tor_libevent_initialize(), so event_base was NULL,
     * so we can't rely on connection_unregister_events() use of event_del().
     */
    if (conn->linked_conn->read_event) {
      tor_free(conn->linked_conn->read_event);
      conn->linked_conn->read_event = NULL;
    }
    if (conn->linked_conn->write_event) {
      tor_free(conn->linked_conn->write_event);
      conn->linked_conn->write_event = NULL;
    }

    if (!conn->linked_conn->marked_for_close) {
      connection_close_immediate(conn->linked_conn);
      if (CONN_IS_EDGE(conn->linked_conn)) {
        /* Suppress warnings about all the stuff we didn't do */
        TO_EDGE_CONN(conn->linked_conn)->edge_has_sent_end = 1;
        TO_EDGE_CONN(conn->linked_conn)->end_reason =
          END_STREAM_REASON_INTERNAL;
        if (conn->linked_conn->type == CONN_TYPE_AP) {
          TO_ENTRY_CONN(conn->linked_conn)->socks_request->has_finished = 1;
        }
      }
      connection_mark_for_close(conn->linked_conn);
    }

    close_closeable_connections();
  }

  /* We didn't set the events up properly, so we can't use event_del() in
   * close_closeable_connections() > connection_free()
   * > connection_unregister_events() */
  if (conn->read_event) {
    tor_free(conn->read_event);
    conn->read_event = NULL;
  }
  if (conn->write_event) {
    tor_free(conn->write_event);
    conn->write_event = NULL;
  }

  if (!conn->marked_for_close) {
    connection_close_immediate(conn);
    if (CONN_IS_EDGE(conn)) {
      /* Suppress warnings about all the stuff we didn't do */
      TO_EDGE_CONN(conn)->edge_has_sent_end = 1;
      TO_EDGE_CONN(conn)->end_reason = END_STREAM_REASON_INTERNAL;
      if (conn->type == CONN_TYPE_AP) {
        TO_ENTRY_CONN(conn)->socks_request->has_finished = 1;
      }
    }
    connection_mark_for_close(conn);
  }

  close_closeable_connections();

  /* The unit test will fail if we return 0 */
  return 1;

  /* When conn == NULL, we can't cleanup anything */
 done:
  return 0;
}