Commit 31324f3e authored by Roger Dingledine's avatar Roger Dingledine
Browse files

apply karsten's "patch 12"


svn:r12825
parent 5864b43e
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -547,8 +547,10 @@ $Id$
   6 nodes. If the request is unsuccessful, Alice retries the other
   remaining responsible hidden service directories in a random order.
   Alice relies on Bob to care about a potential clock skew between the two
   by possibly storing two sets of descriptors. [XXX what does this mean
   Bob does in practice, if anything? -RD]
   by possibly storing two sets of descriptors (see section 1.4).
   [XXX what does this mean Bob does in practice, if anything? -RD]
   [Cf. last sentence of 1.4. Maybe this reference would be helpful here,
    so I added it. -KL]

   Alice's OP opens a stream via Tor to the chosen v2 hidden service
   directory. (She may re-use old circuits for this.) Over this stream,
+14 −21
Original line number Diff line number Diff line
@@ -3104,33 +3104,26 @@ dir_split_resource_into_fingerprints(const char *resource,
  return 0;
}

/** Determine the responsible hidden service directories for
 * <b>desc_ids</b> and upload the appropriate descriptor from
 * <b>desc_strs</b> to them; each smartlist must contain
 * REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS entries; <b>service_id</b> and
 * <b>seconds_valid</b> are only passed for logging purposes.*/
/** Determine the responsible hidden service directories for the
 * rend_encoded_v2_service_descriptor_t's in <b>descs</b> and upload them;
 * <b>service_id</b> and <b>seconds_valid</b> are only passed for logging
 * purposes.*/
/* XXXX020 desc_ids and desc_strs could be merged.  Should they? */
/* I guess they should. -KL */
/* And now they are. -KL */
void
directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs,
                         const char *service_id, int seconds_valid)
directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
                         int seconds_valid)
{
  int i, j;
  smartlist_t *responsible_dirs;
  routerstatus_t *hs_dir;
  if (smartlist_len(desc_ids) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS ||
      smartlist_len(desc_strs) != REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS) {
    log_warn(LD_BUG, "Could not post descriptors to hidden service "
                      "directories: Illegal number of descriptor "
                      "IDs/strings");
    return;
  }
  responsible_dirs = smartlist_create();
  for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
    const char *desc_id = smartlist_get(desc_ids, i);
    const char *desc_str = smartlist_get(desc_strs, i);
  for (i = 0; i < smartlist_len(descs); i++) {
    rend_encoded_v2_service_descriptor_t *desc = smartlist_get(descs, i);
    /* Determine responsible dirs. */
    if (hid_serv_get_responsible_directories(responsible_dirs, desc_id) < 0) {
    if (hid_serv_get_responsible_directories(responsible_dirs,
                                             desc->desc_id) < 0) {
      log_warn(LD_REND, "Could not determine the responsible hidden service "
                        "directories to post descriptors to.");
      smartlist_free(responsible_dirs);
@@ -3145,10 +3138,10 @@ directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *desc_strs,
      directory_initiate_command_routerstatus(hs_dir,
                                              DIR_PURPOSE_UPLOAD_RENDDESC_V2,
                                              ROUTER_PURPOSE_GENERAL,
                                              1, NULL, desc_str,
                                              strlen(desc_str), 0);
                                              1, NULL, desc->desc_str,
                                              strlen(desc->desc_str), 0);
      base32_encode(desc_id_base32, sizeof(desc_id_base32),
                    desc_id, DIGEST_LEN);
                    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 "
+11 −4
Original line number Diff line number Diff line
@@ -3007,8 +3007,8 @@ int dir_split_resource_into_fingerprints(const char *resource,
char *directory_dump_request_log(void);
int router_supports_extrainfo(const char *identity_digest, int is_authority);

void directory_post_to_hs_dir(smartlist_t *desc_ids, smartlist_t *descs,
                              const char *service_id, int seconds_valid);
void directory_post_to_hs_dir(smartlist_t *descs, const char *service_id,
                              int seconds_valid);
void directory_get_from_hs_dir(const char *desc_id, const char *query);

time_t download_status_increment_failure(download_status_t *dls,
@@ -3550,6 +3550,12 @@ int rend_client_send_introduction(origin_circuit_t *introcirc,

/********************************* rendcommon.c ***************************/

/** ASCII-encoded v2 hidden service descriptor. */
typedef struct rend_encoded_v2_service_descriptor_t {
  char desc_id[DIGEST_LEN]; /**< Descriptor ID. */
  char *desc_str; /**< Descriptor string. */
} rend_encoded_v2_service_descriptor_t;

/** Information used to connect to a hidden service. */
typedef struct rend_service_descriptor_t {
  crypto_pk_env_t *pk; /**< This service's public key. */
@@ -3587,6 +3593,8 @@ int rend_encode_service_descriptor(rend_service_descriptor_t *desc,
rend_service_descriptor_t *rend_parse_service_descriptor(const char *str,
                                                         size_t len);
int rend_get_service_id(crypto_pk_env_t *pk, char *out);
void rend_encoded_v2_service_descriptor_free(
                               rend_encoded_v2_service_descriptor_t *desc);

/** A cached rendezvous descriptor. */
typedef struct rend_cache_entry_t {
@@ -3611,8 +3619,7 @@ int rend_cache_store_v2_desc_as_client(const char *desc,
                               const char *descriptor_cookie);
int rend_cache_store_v2_desc_as_dir(const char *desc);
int rend_cache_size(void);
int rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
                               smartlist_t *desc_ids_out,
int rend_encode_v2_descriptors(smartlist_t *descs_out,
                               rend_service_descriptor_t *desc, time_t now,
                               const char *descriptor_cookie, uint8_t period);
int rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
+35 −30
Original line number Diff line number Diff line
@@ -296,7 +296,7 @@ rend_encode_v2_intro_points(char **ipos_base64,
/** Attempt to parse the given <b>desc_str</b> and return true if this
 * succeeds, false otherwise. */
static int
rend_desc_v2_is_parsable(const char *desc_str)
rend_desc_v2_is_parsable(rend_encoded_v2_service_descriptor_t *desc)
{
  rend_service_descriptor_t *test_parsed = NULL;
  char test_desc_id[DIGEST_LEN];
@@ -308,25 +308,31 @@ rend_desc_v2_is_parsable(const char *desc_str)
                                         &test_intro_content,
                                         &test_intro_size,
                                         &test_encoded_size,
                                         &test_next, desc_str);
                                         &test_next, desc->desc_str);
  if (test_parsed)
    rend_service_descriptor_free(test_parsed);
  tor_free(test_intro_content);
  return (res >= 0);
}

/** Encode a set of new service descriptors for <b>desc</b> at time
 * <b>now</b> using <b>descriptor_cookie</b> (may be <b>NULL</b> if
/** Free the storage held by an encoded v2 service descriptor. */
void
rend_encoded_v2_service_descriptor_free(
  rend_encoded_v2_service_descriptor_t *desc)
{
  if (desc->desc_str) tor_free(desc->desc_str);
  tor_free(desc);
}

/** Encode a set of rend_encoded_v2_service_descriptor_t's for <b>desc</b>
 * at time <b>now</b> using <b>descriptor_cookie</b> (may be <b>NULL</b> if
 * introduction points shall not be encrypted) and <b>period</b> (e.g. 0
 * for the current period, 1 for the next period, etc.), write the
 * ASCII-encoded outputs to newly allocated strings and add them to the
 * existing <b>desc_strs</b>, and write the descriptor IDs to newly
 * allocated strings and add them to the existing <b>desc_ids</b>; return
 * the number of seconds that the descriptors will be found under those
 * <b>desc_ids</b> by clients, or -1 if the encoding was not successful. */
 * for the current period, 1 for the next period, etc.) and add them to
 * the existing list <b>descs_out</b>; return the number of seconds that
 * the descriptors will be found by clients, or -1 if the encoding was not
 * successful. */
int
rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
                           smartlist_t *desc_ids_out,
rend_encode_v2_descriptors(smartlist_t *descs_out,
                           rend_service_descriptor_t *desc, time_t now,
                           const char *descriptor_cookie, uint8_t period)
{
@@ -356,7 +362,6 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
  for (k = 0; k < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; k++) {
    char secret_id_part[DIGEST_LEN];
    char secret_id_part_base32[REND_SECRET_ID_PART_LEN_BASE32 + 1];
    char *desc_id;
    char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
    char *permanent_key = NULL;
    size_t permanent_key_len;
@@ -369,21 +374,22 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
    int result = 0;
    size_t written = 0;
    char desc_digest[DIGEST_LEN];
    rend_encoded_v2_service_descriptor_t *enc =
      tor_malloc_zero(sizeof(rend_encoded_v2_service_descriptor_t));
    /* Calculate secret-id-part = h(time-period + cookie + replica). */
    get_secret_id_part_bytes(secret_id_part, time_period, descriptor_cookie,
                             k);
    base32_encode(secret_id_part_base32, sizeof(secret_id_part_base32),
                  secret_id_part, DIGEST_LEN);
    /* Calculate descriptor ID. */
    desc_id = tor_malloc_zero(DIGEST_LEN);
    rend_get_descriptor_id_bytes(desc_id, service_id, secret_id_part);
    smartlist_add(desc_ids_out, desc_id);
    rend_get_descriptor_id_bytes(enc->desc_id, service_id, secret_id_part);
    base32_encode(desc_id_base32, sizeof(desc_id_base32),
                  desc_id, DIGEST_LEN);
                  enc->desc_id, DIGEST_LEN);
    /* PEM-encode the public key */
    if (crypto_pk_write_public_key_to_string(desc->pk, &permanent_key,
                                             &permanent_key_len) < 0) {
      log_warn(LD_BUG, "Could not write public key to string.");
      rend_encoded_v2_service_descriptor_free(enc);
      goto err;
    }
    /* Encode timestamp. */
@@ -403,7 +409,7 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
      protocol_versions_string[0]= '\0';
    /* Assemble complete descriptor. */
    desc_len = 2000 + desc->n_intro_points * 1000; /* far too long, but ok. */
    desc_str = tor_malloc_zero(desc_len);
    enc->desc_str = desc_str = tor_malloc_zero(desc_len);
    result = tor_snprintf(desc_str, desc_len,
             "rendezvous-service-descriptor %s\n"
             "version 2\n"
@@ -419,7 +425,7 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
    tor_free(permanent_key);
    if (result < 0) {
      log_warn(LD_BUG, "Descriptor ran out of room.");
      tor_free(desc_str);
      rend_encoded_v2_service_descriptor_free(enc);
      goto err;
    }
    written = result;
@@ -432,7 +438,7 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
                            ipos_base64);
      if (result < 0) {
        log_warn(LD_BUG, "could not write introduction points.");
        tor_free(desc_str);
        rend_encoded_v2_service_descriptor_free(enc);
        goto err;
      }
      written += result;
@@ -442,31 +448,31 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
    written += strlen(desc_str + written);
    if (crypto_digest(desc_digest, desc_str, written) < 0) {
      log_warn(LD_BUG, "could not create digest.");
      tor_free(desc_str);
      rend_encoded_v2_service_descriptor_free(enc);
      goto err;
    }
    if (router_append_dirobj_signature(desc_str + written,
                                       desc_len - written,
                                       desc_digest, desc->pk) < 0) {
      log_warn(LD_BUG, "Couldn't sign desc.");
      tor_free(desc_str);
      rend_encoded_v2_service_descriptor_free(enc);
      goto err;
    }
    written += strlen(desc_str+written);
    if (written+2 > desc_len) {
        log_warn(LD_BUG, "Could not finish desc.");
        tor_free(desc_str);
        rend_encoded_v2_service_descriptor_free(enc);
        goto err;
    }
    desc_str[written++] = '\n';
    desc_str[written++] = 0;
    /* Check if we can parse our own descriptor. */
    if (!rend_desc_v2_is_parsable(desc_str)) {
    if (!rend_desc_v2_is_parsable(enc)) {
      log_warn(LD_BUG, "Could not parse my own descriptor: %s", desc_str);
      tor_free(desc_str);
      rend_encoded_v2_service_descriptor_free(enc);
      goto err;
    }
    smartlist_add(desc_strs_out, desc_str);
    smartlist_add(descs_out, enc);
  }

  log_info(LD_REND, "Successfully encoded a v2 descriptor and "
@@ -474,10 +480,9 @@ rend_encode_v2_descriptors(smartlist_t *desc_strs_out,
  goto done;

 err:
  SMARTLIST_FOREACH(desc_ids_out, void *, id, tor_free(id));
  smartlist_clear(desc_ids_out);
  SMARTLIST_FOREACH(desc_strs_out, void *, str, tor_free(str));
  smartlist_clear(desc_strs_out);
  SMARTLIST_FOREACH(descs_out, rend_encoded_v2_service_descriptor_t *, d,
                    rend_encoded_v2_service_descriptor_free(d););
  smartlist_clear(descs_out);
  seconds_valid = -1;

 done:
+18 −22
Original line number Diff line number Diff line
@@ -328,6 +328,11 @@ rend_config_services(or_options_t *options, int validate_only)
      /* XXX020 Karsten: do you really want to overwrite the
       * descriptor_version in the second line? Perhaps if both bits
       * are set you want to leave it at -1? -RD */
      /* If both bits are set, versions_bitmask will be (1<<0) + (1<<2),
       * so that neither condition will be true, leaving descriptor_version
       * set to -1. Does the following comment make it less confusing? -KL */
      /* If version 0 XOR 2 was set, change descriptor_version to that
       * value; otherwise leave it at -1. */
      if (versions_bitmask == 1 << 0) service->descriptor_version = 0;
      if (versions_bitmask == 1 << 2) service->descriptor_version = 2;
    }
@@ -1101,12 +1106,11 @@ upload_service_descriptor(rend_service_t *service)
      get_options()->PublishHidServDescriptors) {
    if (hid_serv_have_enough_directories()) {
      int seconds_valid;
      smartlist_t *desc_strs = smartlist_create();
      smartlist_t *desc_ids = smartlist_create();
      smartlist_t *descs = smartlist_create();
      int i;
      /* Encode the current descriptor. */
      seconds_valid = rend_encode_v2_descriptors(desc_strs, desc_ids,
                      service->desc, now, NULL, 0);
      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.");
@@ -1116,14 +1120,11 @@ upload_service_descriptor(rend_service_t *service)
      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(desc_ids, desc_strs, serviceid, seconds_valid);
      directory_post_to_hs_dir(descs, serviceid, seconds_valid);
      /* Free memory for descriptors. */
      for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
        tor_free(smartlist_get(desc_strs, i));
        tor_free(smartlist_get(desc_ids, i));
      }
      smartlist_clear(desc_strs);
      smartlist_clear(desc_ids);
      for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; 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)
@@ -1135,23 +1136,18 @@ upload_service_descriptor(rend_service_t *service)
            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(desc_strs, desc_ids,
                                                   service->desc, now,
                                                   NULL, 1);
        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.");
          return;
        }
        directory_post_to_hs_dir(desc_ids, desc_strs, serviceid,
                                 seconds_valid);
        directory_post_to_hs_dir(descs, serviceid, seconds_valid);
        /* Free memory for descriptors. */
        for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; i++) {
          tor_free(smartlist_get(desc_strs, i));
          tor_free(smartlist_get(desc_ids, i));
        }
        smartlist_free(desc_strs);
        smartlist_free(desc_ids);
        for (i = 0; i < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; 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!");
Loading