Пример #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;
    }
  });
Пример #2
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)
{
  size_t payload_len;
  int r, v3_shift = 0;
  char payload[RELAY_PAYLOAD_SIZE];
  char tmp[RELAY_PAYLOAD_SIZE];
  rend_cache_entry_t *entry;
  crypt_path_t *cpath;
  off_t dh_offset;
  crypto_pk_t *intro_key = NULL;
  int status = 0;

  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(introcirc->rend_data->onion_address,
                                   rendcirc->rend_data->onion_address));
#ifndef NON_ANONYMOUS_MODE_ENABLED
  tor_assert(!(introcirc->build_state->onehop_tunnel));
  tor_assert(!(rendcirc->build_state->onehop_tunnel));
#endif

  if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
                              &entry) < 1) {
    log_info(LD_REND,
             "query %s didn't have valid rend desc in cache. "
             "Refetching descriptor.",
             safe_str_client(introcirc->rend_data->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,
                       introcirc->rend_data->onion_address))) {
        conn->state = AP_CONN_STATE_RENDDESC_WAIT;
      }
    }

    status = -1;
    goto cleanup;
  }

  /* first 20 bytes of payload are the hash of Bob'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;
    }
  });
Пример #3
0
/** Return a circ such that:
 *  - circ-\>rend_data-\>query is equal to <b>rend_query</b>, and
 *  - circ-\>purpose is equal to <b>purpose</b>.
 *
 * Return NULL if no such circuit exists.
 */
origin_circuit_t *
circuit_get_by_rend_query_and_purpose(const char *rend_query, uint8_t purpose)
{
  circuit_t *circ;

  tor_assert(CIRCUIT_PURPOSE_IS_ORIGIN(purpose));

  for (circ = global_circuitlist; circ; circ = circ->next) {
    if (!circ->marked_for_close &&
        circ->purpose == purpose) {
      origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
      if (ocirc->rend_data &&
          !rend_cmp_service_ids(rend_query,
                                ocirc->rend_data->onion_address))
        return ocirc;
    }
  }
  return NULL;
}
Пример #4
0
/** Return a circ such that
 *  - circ-\>rend_data-\>onion_address is equal to
 *    <b>rend_data</b>-\>onion_address,
 *  - circ-\>rend_data-\>rend_cookie is equal to
 *    <b>rend_data</b>-\>rend_cookie, and
 *  - circ-\>purpose is equal to CIRCUIT_PURPOSE_C_REND_READY.
 *
 * Return NULL if no such circuit exists.
 */
origin_circuit_t *
circuit_get_ready_rend_circ_by_rend_data(const rend_data_t *rend_data)
{
  circuit_t *circ;

  for (circ = global_circuitlist; circ; circ = circ->next) {
    if (!circ->marked_for_close &&
        circ->purpose == CIRCUIT_PURPOSE_C_REND_READY) {
      origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
      if (ocirc->rend_data &&
          !rend_cmp_service_ids(rend_data->onion_address,
                                ocirc->rend_data->onion_address) &&
          tor_memeq(ocirc->rend_data->rend_cookie,
                    rend_data->rend_cookie,
                    REND_COOKIE_LEN))
        return ocirc;
    }
  }
  return NULL;
}
Пример #5
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)
{
  size_t payload_len;
  int r, v3_shift = 0;
  char payload[RELAY_PAYLOAD_SIZE];
  char tmp[RELAY_PAYLOAD_SIZE];
  rend_cache_entry_t *entry;
  crypt_path_t *cpath;
  off_t dh_offset;
  crypto_pk_env_t *intro_key; /* either Bob's public key or an intro key. */

  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(introcirc->rend_data->onion_address,
                                   rendcirc->rend_data->onion_address));

  if (rend_cache_lookup_entry(introcirc->rend_data->onion_address, -1,
                              &entry) < 1) {
    log_warn(LD_REND,
             "query %s didn't have valid rend desc in cache. Failing.",
             escaped_safe_str(introcirc->rend_data->onion_address));
    goto err;
  }

  /* first 20 bytes of payload are the hash of Bob's pk */
  if (entry->parsed->version == 0) { /* un-versioned descriptor */
    intro_key = entry->parsed->pk;
  } else { /* versioned descriptor */
    intro_key = NULL;
    SMARTLIST_FOREACH(entry->parsed->intro_nodes, rend_intro_point_t *,
                      intro, {
      if (!memcmp(introcirc->build_state->chosen_exit->identity_digest,
                  intro->extend_info->identity_digest, DIGEST_LEN)) {
        intro_key = intro->intro_key;
        break;
      }
    });
    if (!intro_key) {
      /** XXX This case probably means that the intro point vanished while
       * we were building a circuit to it. In the future, we should find
       * out how that happened and whether we should kill the circuits to
       * removed intro points immediately. See task 1073. */
      int num_intro_points = smartlist_len(entry->parsed->intro_nodes);
      if (rend_cache_lookup_entry(introcirc->rend_data->onion_address,
          0, &entry) > 0) {
        log_info(LD_REND, "We have both a v0 and a v2 rend desc for this "
                 "service. The v2 desc doesn't contain the introduction "
                 "point (and key) to send an INTRODUCE1/2 cell to this "
                 "introduction point. Assuming the introduction point "
                 "is for v0 rend clients and using the service key "
                 "from the v0 desc instead. (This is probably a bug, "
                 "because we shouldn't even have both a v0 and a v2 "
                 "descriptor for the same service.)");
        /* See flyspray task 1024. */
        intro_key = entry->parsed->pk;
      } else {
        log_info(LD_REND, "Internal error: could not find intro key; we "
                 "only have a v2 rend desc with %d intro points.",
                 num_intro_points);
        goto err;
      }
    }
  }