⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rendservice.c

📁 关于tor匿名通信的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
                                              ROUTER_PURPOSE_GENERAL,
                                              1, NULL, desc->desc_str,
                                              strlen(desc->desc_str), 0);
      base32_encode(desc_id_base32, sizeof(desc_id_base32),
                    desc->desc_id, DIGEST_LEN);
      log_info(LD_REND, "Sending publish request for v2 descriptor for "
                        "service '%s' with descriptor ID '%s' with validity "
                        "of %d seconds to hidden service directory '%s' on "
                        "port %d.",
               safe_str(service_id),
               safe_str(desc_id_base32),
               seconds_valid,
               hs_dir->nickname,
               hs_dir->dir_port);
    }
    smartlist_clear(responsible_dirs);
  }
  smartlist_free(responsible_dirs);
}

/** Encode and sign up-to-date v0 and/or v2 service descriptors for
 * <b>service</b>, and upload it/them to all the dirservers/to the
 * responsible hidden service directories.
 */
static void
upload_service_descriptor(rend_service_t *service)
{
  time_t now = time(NULL);
  int rendpostperiod;
  char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
  int uploaded = 0;

  /* Update the descriptor. */
  rend_service_update_descriptor(service);

  rendpostperiod = get_options()->RendPostPeriod;

  /* Upload unversioned (v0) descriptor? */
  if (service->descriptor_version == 0 &&
      get_options()->PublishHidServDescriptors) {
    char *desc;
    size_t desc_len;
    /* Encode the descriptor. */
    if (rend_encode_service_descriptor(service->desc,
                                       service->private_key,
                                       &desc, &desc_len)<0) {
      log_warn(LD_BUG, "Internal error: couldn't encode service descriptor; "
               "not uploading.");
      return;
    }

    /* Post it to the dirservers */
    rend_get_service_id(service->desc->pk, serviceid);
    log_info(LD_REND, "Sending publish request for hidden service %s",
             serviceid);
    directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_RENDDESC,
                                 ROUTER_PURPOSE_GENERAL,
                                 HIDSERV_AUTHORITY, desc, desc_len, 0);
    tor_free(desc);
    service->next_upload_time = now + rendpostperiod;
    uploaded = 1;
  }

  /* Upload v2 descriptor? */
  if (service->descriptor_version == 2 &&
      get_options()->PublishHidServDescriptors) {
    networkstatus_t *c = networkstatus_get_latest_consensus();
    if (c && smartlist_len(c->routerstatus_list) > 0) {
      int seconds_valid;
      smartlist_t *descs = smartlist_create();
      int i;
      /* Encode the current descriptor. */
      seconds_valid = rend_encode_v2_descriptors(descs, service->desc, now,
                                                 NULL, 0);
      if (seconds_valid < 0) {
        log_warn(LD_BUG, "Internal error: couldn't encode service descriptor; "
                 "not uploading.");
        smartlist_free(descs);
        return;
      }
      /* Post the current descriptors to the hidden service directories. */
      rend_get_service_id(service->desc->pk, serviceid);
      log_info(LD_REND, "Sending publish request for hidden service %s",
                   serviceid);
      directory_post_to_hs_dir(descs, serviceid, seconds_valid);
      /* Free memory for descriptors. */
      for (i = 0; i < smartlist_len(descs); i++)
        rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
      smartlist_clear(descs);
      /* Update next upload time. */
      if (seconds_valid - REND_TIME_PERIOD_OVERLAPPING_V2_DESCS
          > rendpostperiod)
        service->next_upload_time = now + rendpostperiod;
      else if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS)
        service->next_upload_time = now + seconds_valid + 1;
      else
        service->next_upload_time = now + seconds_valid -
            REND_TIME_PERIOD_OVERLAPPING_V2_DESCS + 1;
      /* Post also the next descriptors, if necessary. */
      if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
        seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
                                                   now, NULL, 1);
        if (seconds_valid < 0) {
          log_warn(LD_BUG, "Internal error: couldn't encode service "
                   "descriptor; not uploading.");
          smartlist_free(descs);
          return;
        }
        directory_post_to_hs_dir(descs, serviceid, seconds_valid);
        /* Free memory for descriptors. */
        for (i = 0; i < smartlist_len(descs); i++)
          rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
      }
      smartlist_free(descs);
      uploaded = 1;
      log_info(LD_REND, "Successfully uploaded v2 rend descriptors!");
    }
  }

  /* If not uploaded, try again in one minute. */
  if (!uploaded)
    service->next_upload_time = now + 60;

  /* Unmark dirty flag of this service. */
  service->desc_is_dirty = 0;
}

/** For every service, check how many intro points it currently has, and:
 *  - Pick new intro points as necessary.
 *  - Launch circuits to any new intro points.
 */
void
rend_services_introduce(void)
{
  int i,j,r;
  routerinfo_t *router;
  rend_service_t *service;
  rend_intro_point_t *intro;
  int changed, prev_intro_nodes;
  smartlist_t *intro_routers, *exclude_routers;
  time_t now;

  intro_routers = smartlist_create();
  exclude_routers = smartlist_create();
  now = time(NULL);

  for (i=0; i < smartlist_len(rend_service_list); ++i) {
    smartlist_clear(intro_routers);
    service = smartlist_get(rend_service_list, i);

    tor_assert(service);
    changed = 0;
    if (now > service->intro_period_started+INTRO_CIRC_RETRY_PERIOD) {
      /* One period has elapsed; we can try building circuits again. */
      service->intro_period_started = now;
      service->n_intro_circuits_launched = 0;
    } else if (service->n_intro_circuits_launched >=
               MAX_INTRO_CIRCS_PER_PERIOD) {
      /* We have failed too many times in this period; wait for the next
       * one before we try again. */
      continue;
    }

    /* Find out which introduction points we have in progress for this
       service. */
    for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
      intro = smartlist_get(service->intro_nodes, j);
      router = router_get_by_digest(intro->extend_info->identity_digest);
      if (!router || !find_intro_circuit(intro, service->pk_digest,
                                         service->descriptor_version)) {
        log_info(LD_REND,"Giving up on %s as intro point for %s.",
                 intro->extend_info->nickname, service->service_id);
        rend_intro_point_free(intro);
        smartlist_del(service->intro_nodes,j--);
        changed = 1;
        service->desc_is_dirty = now;
      }
      smartlist_add(intro_routers, router);
    }

    /* We have enough intro points, and the intro points we thought we had were
     * all connected.
     */
    if (!changed && smartlist_len(service->intro_nodes) >= NUM_INTRO_POINTS) {
      /* We have all our intro points! Start a fresh period and reset the
       * circuit count. */
      service->intro_period_started = now;
      service->n_intro_circuits_launched = 0;
      continue;
    }

    /* Remember how many introduction circuits we started with. */
    prev_intro_nodes = smartlist_len(service->intro_nodes);

    smartlist_add_all(exclude_routers, intro_routers);
    /* The directory is now here. Pick three ORs as intro points. */
    for (j=prev_intro_nodes; j < NUM_INTRO_POINTS; ++j) {
      router = router_choose_random_node(service->intro_prefer_nodes,
               service->intro_exclude_nodes, exclude_routers, 1, 0, 0,
               get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION,
               0, 0);
      if (!router) {
        log_warn(LD_REND,
                 "Could only establish %d introduction points for %s.",
                 smartlist_len(service->intro_nodes), service->service_id);
        break;
      }
      changed = 1;
      smartlist_add(intro_routers, router);
      smartlist_add(exclude_routers, router);
      intro = tor_malloc_zero(sizeof(rend_intro_point_t));
      intro->extend_info = extend_info_from_router(router);
      if (service->descriptor_version == 2) {
        intro->intro_key = crypto_new_pk_env();
        tor_assert(!crypto_pk_generate_key(intro->intro_key));
      }
      smartlist_add(service->intro_nodes, intro);
      log_info(LD_REND, "Picked router %s as an intro point for %s.",
               router->nickname, service->service_id);
    }

    /* Reset exclude_routers, for the next time around the loop. */
    smartlist_clear(exclude_routers);

    /* If there's no need to launch new circuits, stop here. */
    if (!changed)
      continue;

    /* Establish new introduction points. */
    for (j=prev_intro_nodes; j < smartlist_len(service->intro_nodes); ++j) {
      intro = smartlist_get(service->intro_nodes, j);
      r = rend_service_launch_establish_intro(service, intro);
      if (r<0) {
        log_warn(LD_REND, "Error launching circuit to node %s for service %s.",
                 intro->extend_info->nickname, service->service_id);
      }
    }
  }
  smartlist_free(intro_routers);
  smartlist_free(exclude_routers);
}

/** Regenerate and upload rendezvous service descriptors for all
 * services, if necessary. If the descriptor has been dirty enough
 * for long enough, definitely upload; else only upload when the
 * periodic timeout has expired.
 *
 * For the first upload, pick a random time between now and two periods
 * from now, and pick it independently for each service.
 */
void
rend_consider_services_upload(time_t now)
{
  int i;
  rend_service_t *service;
  int rendpostperiod = get_options()->RendPostPeriod;

  if (!get_options()->PublishHidServDescriptors)
    return;

  for (i=0; i < smartlist_len(rend_service_list); ++i) {
    service = smartlist_get(rend_service_list, i);
    if (!service->next_upload_time) { /* never been uploaded yet */
      service->next_upload_time =
        now + crypto_rand_int(2*rendpostperiod);
    }
    if (service->next_upload_time < now ||
        (service->desc_is_dirty &&
         service->desc_is_dirty < now-30)) {
      /* if it's time, or if the directory servers have a wrong service
       * descriptor and ours has been stable for 30 seconds, upload a
       * new one of each format. */
      upload_service_descriptor(service);
    }
  }
}

/** Log the status of introduction points for all rendezvous services
 * at log severity <b>severity</b>.
 */
void
rend_service_dump_stats(int severity)
{
  int i,j;
  rend_service_t *service;
  rend_intro_point_t *intro;
  const char *safe_name;
  origin_circuit_t *circ;

  for (i=0; i < smartlist_len(rend_service_list); ++i) {
    service = smartlist_get(rend_service_list, i);
    log(severity, LD_GENERAL, "Service configured in \"%s\":",
        service->directory);
    for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
      intro = smartlist_get(service->intro_nodes, j);
      safe_name = safe_str(intro->extend_info->nickname);

      circ = find_intro_circuit(intro, service->pk_digest,
                                service->descriptor_version);
      if (!circ) {
        log(severity, LD_GENERAL, "  Intro point %d at %s: no circuit",
            j, safe_name);
        continue;
      }
      log(severity, LD_GENERAL, "  Intro point %d at %s: circuit is %s",
          j, safe_name, circuit_state_to_string(circ->_base.state));
    }
  }
}

/** Given <b>conn</b>, a rendezvous exit stream, look up the hidden service for
 * 'circ', and look up the port and address based on conn-\>port.
 * Assign the actual conn-\>addr and conn-\>port. Return -1 if failure,
 * or 0 for success.
 */
int
rend_service_set_connection_addr_port(edge_connection_t *conn,
                                      origin_circuit_t *circ)
{
  rend_service_t *service;
  char serviceid[REND_SERVICE_ID_LEN_BASE32+1];
  smartlist_t *matching_ports;
  rend_service_port_config_t *chosen_port;

  tor_assert(circ->_base.purpose == CIRCUIT_PURPOSE_S_REND_JOINED);
  log_debug(LD_REND,"beginning to hunt for addr/port");
  base32_encode(serviceid, REND_SERVICE_ID_LEN_BASE32+1,
                circ->rend_pk_digest, REND_SERVICE_ID_LEN);
  service = rend_service_get_by_pk_digest_and_version(circ->rend_pk_digest,
                                                      circ->rend_desc_version);
  if (!service) {
    log_warn(LD_REND, "Couldn't find any service associated with pk %s on "
             "rendezvous circuit %d; closing.",
             serviceid, circ->_base.n_circ_id);
    return -1;
  }
  matching_ports = smartlist_create();
  SMARTLIST_FOREACH(service->ports, rend_service_port_config_t *, p,
  {
    if (conn->_base.port == p->virtual_port) {
      smartlist_add(matching_ports, p);
    }
  });
  chosen_port = smartlist_choose(matching_ports);
  smartlist_free(matching_ports);
  if (chosen_port) {
    conn->_base.addr = chosen_port->real_addr;
    conn->_base.port = chosen_port->real_port;
    return 0;
  }
  log_info(LD_REND, "No virtual port mapping exists for port %d on service %s",
           conn->_base.port,serviceid);
  return -1;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -