예제 #1
0
파일: loadsave.c 프로젝트: MarcNo/lifelines
/*================================
 * load_gedcom -- have user select gedcom file & import it
 *==============================*/
void
load_gedcom (BOOLEAN picklist)
{
    FILE *fp=NULL;
    struct tag_import_feedback ifeed;
    STRING srcdir=NULL;
    STRING fullpath=0;
    time_t begin = time(NULL);
    time_t beginui = get_uitime();

    srcdir = getlloptstr("InputPath", ".");
    if (!ask_for_gedcom(LLREADTEXT, _(qSwhatgedc), 0, &fullpath, srcdir, ".ged", picklist)
            || !(fp = fopen(fullpath, LLREADBINARY))) {
        strfree(&fullpath);
        return;
    }

    /*
    Note: we read the file in binary mode, so ftell & fseek will work correctly.
    Microsoft's ftell/fseek do not work correctly if the file has simple unix (\n)
    line terminations! -- Perry, 2003-02-11
    */

    memset(&ifeed, 0, sizeof(ifeed));
    ifeed.validating_fnc = import_validating;
    ifeed.validated_rec_fnc = import_validated_rec;
    ifeed.beginning_import_fnc = import_beginning_import;
    ifeed.error_invalid_fnc = import_error_invalid;
    ifeed.error_readonly_fnc = import_readonly;
    ifeed.adding_unused_keys_fnc = import_adding_unused_keys;
    ifeed.added_rec_fnc = import_added_rec;
    ifeed.validation_error_fnc = import_validation_error;
    ifeed.validation_warning_fnc =  import_validation_warning;

    import_from_gedcom_file(&ifeed, fp);

    fclose(fp);
    strfree(&fullpath);


    if (1) {
        INT duration = time(NULL) - begin;
        INT uitime = get_uitime() - beginui;
        ZSTR zt1=approx_time(duration-uitime), zt2=approx_time(uitime);
        /* TRANSLATORS: how long Import ran, and how much of that was UI delay */
        ZSTR zout = zs_newf(_("Import time %s (ui %s)\n")
                            , zs_str(zt1), zs_str(zt2));
        wfield(8,0, zs_str(zout));
        zs_free(&zt1);
        zs_free(&zt2);
        zs_free(&zout);
    }

    /* position cursor further down stdout so check_stdout
    doesn't overwrite our messages from above */
    wpos(15,0);
}
예제 #2
0
파일: onion.c 프로젝트: BwRy/Astoria
/** Add <b>circ</b> to the end of ol_list and return 0, except
 * if ol_list is too long, in which case do nothing and return -1.
 */
int
onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin)
{
  onion_queue_t *tmp;
  time_t now = time(NULL);

  if (onionskin->handshake_type > MAX_ONION_HANDSHAKE_TYPE) {
    log_warn(LD_BUG, "Handshake %d out of range! Dropping.",
             onionskin->handshake_type);
    return -1;
  }

  tmp = tor_malloc_zero(sizeof(onion_queue_t));
  tmp->circ = circ;
  tmp->handshake_type = onionskin->handshake_type;
  tmp->onionskin = onionskin;
  tmp->when_added = now;

  if (!have_room_for_onionskin(onionskin->handshake_type)) {
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60)
    static ratelim_t last_warned =
      RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
    char *m;
    if (onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR &&
        (m = rate_limit_log(&last_warned, approx_time()))) {
      log_warn(LD_GENERAL,
               "Your computer is too slow to handle this many circuit "
               "creation requests! Please consider using the "
               "MaxAdvertisedBandwidth config option or choosing a more "
               "restricted exit policy.%s",m);
      tor_free(m);
    }
    tor_free(tmp);
    return -1;
  }

  ++ol_entries[onionskin->handshake_type];
  log_info(LD_OR, "New create (%s). Queues now ntor=%d and tap=%d.",
    onionskin->handshake_type == ONION_HANDSHAKE_TYPE_NTOR ? "ntor" : "tap",
    ol_entries[ONION_HANDSHAKE_TYPE_NTOR],
    ol_entries[ONION_HANDSHAKE_TYPE_TAP]);

  circ->onionqueue_entry = tmp;
  TOR_TAILQ_INSERT_TAIL(&ol_list[onionskin->handshake_type], tmp, next);

  /* cull elderly requests. */
  while (1) {
    onion_queue_t *head = TOR_TAILQ_FIRST(&ol_list[onionskin->handshake_type]);
    if (now - head->when_added < (time_t)ONIONQUEUE_WAIT_CUTOFF)
      break;

    circ = head->circ;
    circ->onionqueue_entry = NULL;
    onion_queue_entry_remove(head);
    log_info(LD_CIRC,
             "Circuit create request is too old; canceling due to overload.");
    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
  }
  return 0;
}
예제 #3
0
파일: routerkeys.c 프로젝트: ageis/tor
/**
 * Log when our master signing key certificate expires.  Used when tor is given
 * the --key-expiration command-line option.
 *
 * Returns 0 on success and 1 on failure.
 */
static int
log_master_signing_key_cert_expiration(const or_options_t *options)
{
  const tor_cert_t *signing_key;
  char *fn = NULL;
  int failed = 0;
  time_t now = approx_time();

  fn = options_get_keydir_fname(options, "ed25519_signing_cert");

  /* Try to grab our cached copy of the key. */
  signing_key = get_master_signing_key_cert();

  tor_assert(server_identity_key_is_set());

  /* Load our keys from disk, if necessary. */
  if (!signing_key) {
    failed = load_ed_keys(options, now) < 0;
    signing_key = get_master_signing_key_cert();
  }

  /* If we do have a signing key, log the expiration time. */
  if (signing_key) {
    log_ed_cert_expiration(signing_key, "signing", fn);
  } else {
    log_warn(LD_OR, "Could not load signing key certificate from %s, so " \
             "we couldn't learn anything about certificate expiration.", fn);
  }

  tor_free(fn);

  return failed;
}
예제 #4
0
/** Try to tell a cpuworker to perform the public key operations necessary to
 * respond to <b>onionskin</b> for the circuit <b>circ</b>.
 *
 * If <b>cpuworker</b> is defined, assert that he's idle, and use him. Else,
 * look for an idle cpuworker and use him. If none idle, queue task onto the
 * pending onion list and return.  Return 0 if we successfully assign the
 * task, or -1 on failure.
 */
int
assign_onionskin_to_cpuworker(connection_t *cpuworker,
                              or_circuit_t *circ, char *onionskin)
{
  char qbuf[1];
  char tag[TAG_LEN];
  time_t now = approx_time();
  static time_t last_culled_cpuworkers = 0;

  /* Checking for wedged cpuworkers requires a linear search over all
   * connections, so let's do it only once a minute.
   */
#define CULL_CPUWORKERS_INTERVAL 60

  if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) {
    cull_wedged_cpuworkers();
    spawn_enough_cpuworkers();
    last_culled_cpuworkers = now;
  }

  if (1) {
    if (num_cpuworkers_busy == num_cpuworkers) {
      log_debug(LD_OR,"No idle cpuworkers. Queuing.");
      if (onion_pending_add(circ, onionskin) < 0) {
        tor_free(onionskin);
        return -1;
      }
      return 0;
    }

    if (!cpuworker)
      cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER,
                                               CPUWORKER_STATE_IDLE);

    tor_assert(cpuworker);

    if (!circ->p_conn) {
      log_info(LD_OR,"circ->p_conn gone. Failing circ.");
      tor_free(onionskin);
      return -1;
    }
    tag_pack(tag, circ->p_conn->_base.global_identifier,
             circ->p_circ_id);

    cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
    /* touch the lastwritten timestamp, since that's how we check to
     * see how long it's been since we asked the question, and sometimes
     * we check before the first call to connection_handle_write(). */
    cpuworker->timestamp_lastwritten = time(NULL);
    num_cpuworkers_busy++;

    qbuf[0] = CPUWORKER_TASK_ONION;
    connection_write_to_buf(qbuf, 1, cpuworker);
    connection_write_to_buf(tag, sizeof(tag), cpuworker);
    connection_write_to_buf(onionskin, ONIONSKIN_CHALLENGE_LEN, cpuworker);
    tor_free(onionskin);
  }
  return 0;
}
예제 #5
0
/** Helper function to get the HS subcredential using the identity keypair of
 *  an HS. Used to decrypt descriptors in unittests. */
void
hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
                                            uint8_t *subcred_out)
{
  ed25519_keypair_t blinded_kp;
  uint64_t current_time_period = hs_get_time_period_num(approx_time());
  hs_build_blinded_keypair(signing_kp, NULL, 0,
                           current_time_period, &blinded_kp);

  hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey,
                       subcred_out);
}
예제 #6
0
파일: onion.c 프로젝트: fatline/Tor-Puzzles
/** Add <b>circ</b> to the end of ol_list and return 0, except
 * if ol_list is too long, in which case do nothing and return -1.
 */
int
onion_pending_add(or_circuit_t *circ, char *onionskin)
{
  onion_queue_t *tmp;
  time_t now = time(NULL);

  tmp = tor_malloc_zero(sizeof(onion_queue_t));
  tmp->circ = circ;
  tmp->onionskin = onionskin;
  tmp->when_added = now;

  if (!ol_tail) {
    tor_assert(!ol_list);
    tor_assert(!ol_length);
    ol_list = tmp;
    ol_tail = tmp;
    ol_length++;
    return 0;
  }

  tor_assert(ol_list);
  tor_assert(!ol_tail->next);

  if (ol_length >= get_options()->MaxOnionsPending) {
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL (60)
    static ratelim_t last_warned =
      RATELIM_INIT(WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL);
    char *m;
    if ((m = rate_limit_log(&last_warned, approx_time()))) {
      log_warn(LD_GENERAL,
               "Your computer is too slow to handle this many circuit "
               "creation requests! Please consider using the "
               "MaxAdvertisedBandwidth config option or choosing a more "
               "restricted exit policy.%s",m);
      tor_free(m);
    }
    tor_free(tmp);
    return -1;
  }

  ol_length++;
  ol_tail->next = tmp;
  ol_tail = tmp;
  while ((int)(now - ol_list->when_added) >= ONIONQUEUE_WAIT_CUTOFF) {
    /* cull elderly requests. */
    circ = ol_list->circ;
    onion_pending_remove(ol_list->circ);
    log_info(LD_CIRC,
             "Circuit create request is too old; canceling due to overload.");
    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT);
  }
  return 0;
}
예제 #7
0
/**
 * Called to indicate that the network showed some signs of liveness,
 * i.e. we received a cell.
 *
 * This is used by circuit_build_times_network_check_live() to decide
 * if we should record the circuit build timeout or not.
 *
 * This function is called every time we receive a cell. Avoid
 * syscalls, events, and other high-intensity work.
 */
void
circuit_build_times_network_is_live(circuit_build_times_t *cbt)
{
  time_t now = approx_time();
  if (cbt->liveness.nonlive_timeouts > 0) {
    log_notice(LD_CIRC,
               "Tor now sees network activity. Restoring circuit build "
               "timeout recording. Network was down for %d seconds "
               "during %d circuit attempts.",
               (int)(now - cbt->liveness.network_last_live),
               cbt->liveness.nonlive_timeouts);
  }
  cbt->liveness.network_last_live = now;
  cbt->liveness.nonlive_timeouts = 0;
}
예제 #8
0
파일: microdesc.c 프로젝트: jfrazelle/tor
/** Note that we failed to fetch a microdescriptor from the relay with
 *  <b>relay_digest</b> (of size DIGEST_LEN). */
void
microdesc_note_outdated_dirserver(const char *relay_digest)
{
  char relay_hexdigest[HEX_DIGEST_LEN+1];

  /* If we have a reasonably live consensus, then most of our dirservers should
   * still be caching all the microdescriptors in it. Reasonably live
   * consensuses are up to a day old (or a day in the future). But
   * microdescriptors expire 7 days after the last consensus that referenced
   * them. */
  if (!networkstatus_get_reasonably_live_consensus(approx_time(),
                                                   FLAV_MICRODESC)) {
    return;
  }

  if (!outdated_dirserver_list) {
    outdated_dirserver_list = smartlist_new();
  }

  tor_assert(outdated_dirserver_list);

  /* If the list grows too big, clean it up */
  if (BUG(smartlist_len(outdated_dirserver_list) >
          TOO_MANY_OUTDATED_DIRSERVERS)) {
    microdesc_reset_outdated_dirservers_list();
  }

  /* Turn the binary relay digest to a hex since smartlists have better support
   * for strings than digests. */
  base16_encode(relay_hexdigest,sizeof(relay_hexdigest),
                relay_digest, DIGEST_LEN);

  /* Make sure we don't add a dirauth as an outdated dirserver */
  if (router_get_trusteddirserver_by_digest(relay_digest)) {
    log_info(LD_GENERAL, "Auth %s gave us outdated dirinfo.", relay_hexdigest);
    return;
  }

  /* Don't double-add outdated dirservers */
  if (smartlist_contains_string(outdated_dirserver_list, relay_hexdigest)) {
    return;
  }

  /* Add it to the list of outdated dirservers */
  smartlist_add_strdup(outdated_dirserver_list, relay_hexdigest);

  log_info(LD_GENERAL, "Noted %s as outdated md dirserver", relay_hexdigest);
}
예제 #9
0
/** Allocate space for a new circuit, initializing with <b>p_circ_id</b>
 * and <b>p_conn</b>. Add it to the global circuit list.
 */
origin_circuit_t *
origin_circuit_new(void)
{
  origin_circuit_t *circ;
  /* never zero, since a global ID of 0 is treated specially by the
   * controller */
  static uint32_t n_circuits_allocated = 1;

  circ = tor_malloc_zero(sizeof(origin_circuit_t));
  circ->_base.magic = ORIGIN_CIRCUIT_MAGIC;

  circ->next_stream_id = crypto_rand_int(1<<16);
  circ->global_identifier = n_circuits_allocated++;
  circ->remaining_relay_early_cells = MAX_RELAY_EARLY_CELLS_PER_CIRCUIT;
  circ->remaining_relay_early_cells -= crypto_rand_int(2);

  init_circuit_base(TO_CIRCUIT(circ));

  circ_times.last_circ_at = approx_time();

  return circ;
}
예제 #10
0
파일: test_router.c 프로젝트: jfrazelle/tor
static void
test_router_mark_if_too_old(void *arg)
{
  (void)arg;
  time_t now = approx_time();
  MOCK(networkstatus_get_live_consensus,
       mock_networkstatus_get_live_consensus);
  MOCK(networkstatus_vote_find_entry, mock_networkstatus_vote_find_entry);

  routerstatus_t rs;
  networkstatus_t ns;
  memset(&rs, 0, sizeof(rs));
  memset(&ns, 0, sizeof(ns));
  mock_ns = &ns;
  mock_ns->valid_after = now-3600;
  mock_rs = &rs;
  mock_rs->published_on = now - 10;

  // no reason to mark this time.
  desc_clean_since = now-10;
  desc_dirty_reason = NULL;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, now-10);

  // Doesn't appear in consensus?  Still don't mark it.
  mock_ns = NULL;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, now-10);
  mock_ns = &ns;

  // No new descriptor in a long time?  Mark it.
  desc_clean_since = now - 3600 * 96;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, 0);
  tt_str_op(desc_dirty_reason, OP_EQ, "time for new descriptor");

  // Version in consensus published a long time ago?  We won't mark it
  // if it's been clean for only a short time.
  desc_clean_since = now - 10;
  desc_dirty_reason = NULL;
  mock_rs->published_on = now - 3600 * 96;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, now - 10);

  // ... but if it's been clean a while, we mark.
  desc_clean_since = now - 2 * 3600;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, 0);
  tt_str_op(desc_dirty_reason, OP_EQ,
            "version listed in consensus is quite old");

  // same deal if we're marked stale.
  desc_clean_since = now - 2 * 3600;
  desc_dirty_reason = NULL;
  mock_rs->published_on = now - 10;
  mock_rs->is_staledesc = 1;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, 0);
  tt_str_op(desc_dirty_reason, OP_EQ,
            "listed as stale in consensus");

  // same deal if we're absent from the consensus.
  desc_clean_since = now - 2 * 3600;
  desc_dirty_reason = NULL;
  mock_rs = NULL;
  mark_my_descriptor_dirty_if_too_old(now);
  tt_i64_op(desc_clean_since, OP_EQ, 0);
  tt_str_op(desc_dirty_reason, OP_EQ,
            "not listed in consensus");

 done:
  UNMOCK(networkstatus_get_live_consensus);
  UNMOCK(networkstatus_vote_find_entry);
}
예제 #11
0
파일: test.c 프로젝트: ageis/tor
    tt_assert(!circuit_build_times_network_check_changed(&estimate));
    tt_assert(!circuit_build_times_network_check_changed(&final));

    /* Reset liveness to be non-live */
    final.liveness.network_last_live = 0;
    estimate.liveness.network_last_live = 0;

    build_times_idx = estimate.build_times_idx;
    total_build_times = estimate.total_build_times;

    tt_assert(circuit_build_times_network_check_live(&estimate));
    tt_assert(circuit_build_times_network_check_live(&final));

    circuit_build_times_count_close(&estimate, 0,
            (time_t)(approx_time()-estimate.close_ms/1000.0-1));
    circuit_build_times_count_close(&final, 0,
            (time_t)(approx_time()-final.close_ms/1000.0-1));

    tt_assert(!circuit_build_times_network_check_live(&estimate));
    tt_assert(!circuit_build_times_network_check_live(&final));

    log_info(LD_CIRC, "idx: %d %d, tot: %d %d",
             build_times_idx, estimate.build_times_idx,
             total_build_times, estimate.total_build_times);

    /* Check rollback index. Should match top of loop. */
    tt_assert(build_times_idx == estimate.build_times_idx);
    // This can fail if estimate.total_build_times == 1000, because
    // in that case, rewind actually causes us to lose timeouts
    if (total_build_times != CBT_NCIRCUITS_TO_OBSERVE)
예제 #12
0
파일: voteflags.c 프로젝트: unixninja92/Tor
/* DOCDOC running_long_enough_to_decide_unreachable */
int
running_long_enough_to_decide_unreachable(void)
{
  return time_of_process_start
    + get_options()->TestingAuthDirTimeToLearnReachability < approx_time();
}
예제 #13
0
/**
 * Returns true if we should build a timeout test circuit
 * right now.
 */
int
circuit_build_times_needs_circuits_now(circuit_build_times_t *cbt)
{
  return circuit_build_times_needs_circuits(cbt) &&
    approx_time()-cbt->last_circ_at > circuit_build_times_test_frequency();
}
예제 #14
0
파일: cpuworker.c 프로젝트: AllardJ/Tomato
/** Try to tell a cpuworker to perform the public key operations necessary to
 * respond to <b>onionskin</b> for the circuit <b>circ</b>.
 *
 * If <b>cpuworker</b> is defined, assert that he's idle, and use him. Else,
 * look for an idle cpuworker and use him. If none idle, queue task onto the
 * pending onion list and return.  Return 0 if we successfully assign the
 * task, or -1 on failure.
 */
int
assign_onionskin_to_cpuworker(connection_t *cpuworker,
                              or_circuit_t *circ,
                              create_cell_t *onionskin)
{
  cpuworker_request_t req;
  time_t now = approx_time();
  static time_t last_culled_cpuworkers = 0;
  int should_time;

  /* Checking for wedged cpuworkers requires a linear search over all
   * connections, so let's do it only once a minute.
   */
#define CULL_CPUWORKERS_INTERVAL 60

  if (last_culled_cpuworkers + CULL_CPUWORKERS_INTERVAL <= now) {
    cull_wedged_cpuworkers();
    spawn_enough_cpuworkers();
    last_culled_cpuworkers = now;
  }

  if (1) {
    if (num_cpuworkers_busy == num_cpuworkers) {
      log_debug(LD_OR,"No idle cpuworkers. Queuing.");
      if (onion_pending_add(circ, onionskin) < 0) {
        tor_free(onionskin);
        return -1;
      }
      return 0;
    }

    if (!cpuworker)
      cpuworker = connection_get_by_type_state(CONN_TYPE_CPUWORKER,
                                               CPUWORKER_STATE_IDLE);

    tor_assert(cpuworker);

    if (!circ->p_chan) {
      log_info(LD_OR,"circ->p_chan gone. Failing circ.");
      tor_free(onionskin);
      return -1;
    }

    if (connection_or_digest_is_known_relay(circ->p_chan->identity_digest))
      rep_hist_note_circuit_handshake_assigned(onionskin->handshake_type);

    should_time = should_time_request(onionskin->handshake_type);
    memset(&req, 0, sizeof(req));
    req.magic = CPUWORKER_REQUEST_MAGIC;
    tag_pack(req.tag, circ->p_chan->global_identifier,
             circ->p_circ_id);
    req.timed = should_time;

    cpuworker->state = CPUWORKER_STATE_BUSY_ONION;
    /* touch the lastwritten timestamp, since that's how we check to
     * see how long it's been since we asked the question, and sometimes
     * we check before the first call to connection_handle_write(). */
    cpuworker->timestamp_lastwritten = now;
    num_cpuworkers_busy++;

    req.task = CPUWORKER_TASK_ONION;
    memcpy(&req.create_cell, onionskin, sizeof(create_cell_t));

    tor_free(onionskin);

    if (should_time)
      tor_gettimeofday(&req.started_at);

    connection_write_to_buf((void*)&req, sizeof(req), cpuworker);
    memwipe(&req, 0, sizeof(req));
  }
  return 0;
}
예제 #15
0
/* Return a valid hs_descriptor_t object. If no_ip is set, no introduction
 * points are added. */
static hs_descriptor_t *
hs_helper_build_hs_desc_impl(unsigned int no_ip,
                             const ed25519_keypair_t *signing_kp)
{
  int ret;
  int i;
  time_t now = approx_time();
  ed25519_keypair_t blinded_kp;
  curve25519_keypair_t auth_ephemeral_kp;
  hs_descriptor_t *descp = NULL, *desc = tor_malloc_zero(sizeof(*desc));

  desc->plaintext_data.version = HS_DESC_SUPPORTED_FORMAT_VERSION_MAX;

  /* Copy only the public key into the descriptor. */
  memcpy(&desc->plaintext_data.signing_pubkey, &signing_kp->pubkey,
         sizeof(ed25519_public_key_t));

  uint64_t current_time_period = hs_get_time_period_num(0);
  hs_build_blinded_keypair(signing_kp, NULL, 0,
                           current_time_period, &blinded_kp);
  /* Copy only the public key into the descriptor. */
  memcpy(&desc->plaintext_data.blinded_pubkey, &blinded_kp.pubkey,
         sizeof(ed25519_public_key_t));

  desc->plaintext_data.signing_key_cert =
    tor_cert_create(&blinded_kp, CERT_TYPE_SIGNING_HS_DESC,
                    &signing_kp->pubkey, now, 3600,
                    CERT_FLAG_INCLUDE_SIGNING_KEY);
  tt_assert(desc->plaintext_data.signing_key_cert);
  desc->plaintext_data.revision_counter = 42;
  desc->plaintext_data.lifetime_sec = 3 * 60 * 60;

  hs_get_subcredential(&signing_kp->pubkey, &blinded_kp.pubkey,
                    desc->subcredential);

  /* Setup superencrypted data section. */
  ret = curve25519_keypair_generate(&auth_ephemeral_kp, 0);
  tt_int_op(ret, ==, 0);
  memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
         &auth_ephemeral_kp.pubkey,
         sizeof(curve25519_public_key_t));

  desc->superencrypted_data.clients = smartlist_new();
  for (i = 0; i < HS_DESC_AUTH_CLIENT_MULTIPLE; i++) {
    hs_desc_authorized_client_t *desc_client =
      hs_desc_build_fake_authorized_client();
    smartlist_add(desc->superencrypted_data.clients, desc_client);
  }

  /* Setup encrypted data section. */
  desc->encrypted_data.create2_ntor = 1;
  desc->encrypted_data.intro_auth_types = smartlist_new();
  desc->encrypted_data.single_onion_service = 1;
  smartlist_add(desc->encrypted_data.intro_auth_types, tor_strdup("ed25519"));
  desc->encrypted_data.intro_points = smartlist_new();
  if (!no_ip) {
    /* Add four intro points. */
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "1.2.3.4", 0));
/* IPv6-only introduction points are not supported yet, see #23588 */
#if 0
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "[2600::1]", 0));
#endif
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "3.2.1.4", 1));
    smartlist_add(desc->encrypted_data.intro_points,
              hs_helper_build_intro_point(signing_kp, now, "5.6.7.8", 1));
  }

  descp = desc;
 done:
  if (descp == NULL)
    tor_free(desc);

  return descp;
}
예제 #16
0
파일: command.c 프로젝트: chenglong7997/Tor
/** Process a 'create' <b>cell</b> that just arrived from <b>conn</b>. Make a
 * new circuit with the p_circ_id specified in cell. Put the circuit in state
 * onionskin_pending, and pass the onionskin to the cpuworker. Circ will get
 * picked up again when the cpuworker finishes decrypting it.
 */
static void
command_process_create_cell(cell_t *cell, or_connection_t *conn)
{
  or_circuit_t *circ;
  const or_options_t *options = get_options();
  int id_is_high;

  if (we_are_hibernating()) {
    log_info(LD_OR,
             "Received create cell but we're shutting down. Sending back "
             "destroy.");
    connection_or_send_destroy(cell->circ_id, conn,
                               END_CIRC_REASON_HIBERNATING);
    return;
  }

  if (!server_mode(options) ||
      (!public_server_mode(options) && conn->is_outgoing)) {
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Received create cell (type %d) from %s:%d, but we're connected "
           "to it as a client. "
           "Sending back a destroy.",
           (int)cell->command, conn->_base.address, conn->_base.port);
    connection_or_send_destroy(cell->circ_id, conn,
                               END_CIRC_REASON_TORPROTOCOL);
    return;
  }

  /* If the high bit of the circuit ID is not as expected, close the
   * circ. */
  id_is_high = cell->circ_id & (1<<15);
  if ((id_is_high && conn->circ_id_type == CIRC_ID_TYPE_HIGHER) ||
      (!id_is_high && conn->circ_id_type == CIRC_ID_TYPE_LOWER)) {
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Received create cell with unexpected circ_id %d. Closing.",
           cell->circ_id);
    connection_or_send_destroy(cell->circ_id, conn,
                               END_CIRC_REASON_TORPROTOCOL);
    return;
  }

  if (circuit_id_in_use_on_orconn(cell->circ_id, conn)) {
    const node_t *node = node_get_by_id(conn->identity_digest);
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Received CREATE cell (circID %d) for known circ. "
           "Dropping (age %d).",
           cell->circ_id, (int)(time(NULL) - conn->_base.timestamp_created));
    if (node) {
      char *p = esc_for_log(node_get_platform(node));
      log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
             "Details: router %s, platform %s.",
             node_describe(node), p);
      tor_free(p);
    }
    return;
  }

  circ = or_circuit_new(cell->circ_id, conn);
  circ->_base.purpose = CIRCUIT_PURPOSE_OR;
  circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
  if (cell->command == CELL_CREATE) {
    char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
    memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);

    /* hand it off to the cpuworkers, and then return. */
    if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
#define WARN_HANDOFF_FAILURE_INTERVAL (6*60*60)
      static ratelim_t handoff_warning =
        RATELIM_INIT(WARN_HANDOFF_FAILURE_INTERVAL);
      char *m;
      if ((m = rate_limit_log(&handoff_warning, approx_time()))) {
        log_warn(LD_GENERAL,"Failed to hand off onionskin. Closing.%s",m);
        tor_free(m);
      }
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      return;
    }
    log_debug(LD_OR,"success: handed off onionskin.");
  } else {
    /* This is a CREATE_FAST cell; we can handle it immediately without using
     * a CPU worker. */
    char keys[CPATH_KEY_MATERIAL_LEN];
    char reply[DIGEST_LEN*2];

    tor_assert(cell->command == CELL_CREATE_FAST);

    /* Make sure we never try to use the OR connection on which we
     * received this cell to satisfy an EXTEND request,  */
    conn->is_connection_with_client = 1;

    if (fast_server_handshake(cell->payload, (uint8_t*)reply,
                              (uint8_t*)keys, sizeof(keys))<0) {
      log_warn(LD_OR,"Failed to generate key material. Closing.");
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      return;
    }
    if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
      log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      return;
    }
  }
}
예제 #17
0
파일: bwauth.c 프로젝트: jfrazelle/tor
/**
 * Read the measured bandwidth list <b>from_file</b>:
 * - store all the headers in <b>bw_file_headers</b>,
 * - apply bandwidth lines to the list of vote_routerstatus_t in
 *   <b>routerstatuses</b>,
 * - cache bandwidth lines for dirserv_get_bandwidth_for_router(),
 * - expire old entries in the measured bandwidth cache, and
 * - store the DIGEST_SHA256 of the contents of the file in <b>digest_out</b>.
 *
 * Returns -1 on error, 0 otherwise.
 *
 * If the file can't be read, or is empty:
 * - <b>bw_file_headers</b> is empty,
 * - <b>routerstatuses</b> is not modified,
 * - the measured bandwidth cache is not modified, and
 * - <b>digest_out</b> is the zero-byte digest.
 *
 * Otherwise, if there is an error later in the file:
 * - <b>bw_file_headers</b> contains all the headers up to the error,
 * - <b>routerstatuses</b> is updated with all the relay lines up to the error,
 * - the measured bandwidth cache is updated with all the relay lines up to
 *   the error,
 * - if the timestamp is valid and recent, old entries in the  measured
 *   bandwidth cache are expired, and
 * - <b>digest_out</b> is the digest up to the first read error (if any).
 *   The digest is taken over all the readable file contents, even if the
 *   file is outdated or unparseable.
 */
int
dirserv_read_measured_bandwidths(const char *from_file,
                                 smartlist_t *routerstatuses,
                                 smartlist_t *bw_file_headers,
                                 uint8_t *digest_out)
{
  FILE *fp = tor_fopen_cloexec(from_file, "r");
  int applied_lines = 0;
  time_t file_time, now;
  int ok;
   /* This flag will be 1 only when the first successful bw measurement line
   * has been encountered, so that measured_bw_line_parse don't give warnings
   * if there are additional header lines, as introduced in Bandwidth List spec
   * version 1.1.0 */
  int line_is_after_headers = 0;
  int rv = -1;
  char *line = NULL;
  size_t n = 0;
  crypto_digest_t *digest = crypto_digest256_new(DIGEST_SHA256);

  if (fp == NULL) {
    log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
             from_file);
    goto err;
  }

  if (tor_getline(&line,&n,fp) <= 0) {
    log_warn(LD_DIRSERV, "Empty bandwidth file");
    goto err;
  }
  /* If the line could be gotten, add it to the digest */
  crypto_digest_add_bytes(digest, (const char *) line, strlen(line));

  if (!strlen(line) || line[strlen(line)-1] != '\n') {
    log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
             escaped(line));
    /* Continue adding lines to the digest. */
    goto continue_digest;
  }

  line[strlen(line)-1] = '\0';
  file_time = (time_t)tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL);
  if (!ok) {
    log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s",
             escaped(line));
    goto continue_digest;
  }

  now = approx_time();
  if ((now - file_time) > MAX_MEASUREMENT_AGE) {
    log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
             (unsigned)(time(NULL) - file_time));
    goto continue_digest;
  }

  /* If timestamp was correct and bw_file_headers is not NULL,
   * add timestamp to bw_file_headers */
  if (bw_file_headers)
    smartlist_add_asprintf(bw_file_headers, "timestamp=%lu",
                           (unsigned long)file_time);

  if (routerstatuses)
    smartlist_sort(routerstatuses, compare_vote_routerstatus_entries);

  while (!feof(fp)) {
    measured_bw_line_t parsed_line;
    if (tor_getline(&line, &n, fp) >= 0) {
      crypto_digest_add_bytes(digest, (const char *) line, strlen(line));
      if (measured_bw_line_parse(&parsed_line, line,
                                 line_is_after_headers) != -1) {
        /* This condition will be true when the first complete valid bw line
         * has been encountered, which means the end of the header lines. */
        line_is_after_headers = 1;
        /* Also cache the line for dirserv_get_bandwidth_for_router() */
        dirserv_cache_measured_bw(&parsed_line, file_time);
        if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
          applied_lines++;
      /* if the terminator is found, it is the end of header lines, set the
       * flag but do not store anything */
      } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) {
        line_is_after_headers = 1;
      /* if the line was not a correct relay line nor the terminator and
       * the end of the header lines has not been detected yet
       * and it is key_value and bw_file_headers did not reach the maximum
       * number of headers,
       * then assume this line is a header and add it to bw_file_headers */
      } else if (bw_file_headers &&
              (line_is_after_headers == 0) &&
              string_is_key_value(LOG_DEBUG, line) &&
              !strchr(line, ' ') &&
              (smartlist_len(bw_file_headers)
               < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) {
        line[strlen(line)-1] = '\0';
        smartlist_add_strdup(bw_file_headers, line);
      };
    }
  }

  /* Now would be a nice time to clean the cache, too */
  dirserv_expire_measured_bw_cache(now);

  log_info(LD_DIRSERV,
           "Bandwidth measurement file successfully read. "
           "Applied %d measurements.", applied_lines);
  rv = 0;

 continue_digest:
  /* Continue parsing lines to return the digest of the Bandwidth File. */
  while (!feof(fp)) {
    if (tor_getline(&line, &n, fp) >= 0) {
      crypto_digest_add_bytes(digest, (const char *) line, strlen(line));
    }
  }

 err:
  if (line) {
    // we need to raw_free this buffer because we got it from tor_getdelim()
    raw_free(line);
  }
  if (fp)
    fclose(fp);
  if (digest_out)
    crypto_digest_get_digest(digest, (char *) digest_out, DIGEST256_LEN);
  crypto_digest_free(digest);
  return rv;
}