[or-cvs] r12900: revert r12841 and r12842, and commit karsten's "patch 13" (tor/trunk/src/or)

arma at seul.org arma at seul.org
Fri Dec 21 09:28:23 UTC 2007


Author: arma
Date: 2007-12-21 04:28:22 -0500 (Fri, 21 Dec 2007)
New Revision: 12900

Modified:
   tor/trunk/src/or/or.h
   tor/trunk/src/or/rendclient.c
   tor/trunk/src/or/rendcommon.c
   tor/trunk/src/or/rendservice.c
   tor/trunk/src/or/routerparse.c
   tor/trunk/src/or/test.c
Log:
revert r12841 and r12842, and commit karsten's "patch 13"


Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/or.h	2007-12-21 09:28:22 UTC (rev 12900)
@@ -3598,6 +3598,13 @@
   char *desc_str; /**< Descriptor string. */
 } rend_encoded_v2_service_descriptor_t;
 
+/** Introduction point information. */
+typedef struct rend_intro_point_t {
+  extend_info_t *extend_info; /**< Extend info of this introduction point. */
+  crypto_pk_env_t *intro_key; /**< Introduction key that replaces the service
+                               * key, if this descriptor is V2. */
+} rend_intro_point_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. */
@@ -3605,21 +3612,9 @@
   time_t timestamp; /**< Time when the descriptor was generated. */
   uint16_t protocols; /**< Bitmask: which rendezvous protocols are supported?
                        * (We allow bits '0', '1', and '2' to be set.) */
-  int n_intro_points; /**< Number of introduction points. */
-  /** Array of n_intro_points elements for this service's introduction points'
-   * nicknames.  Elements are removed from this array if introduction attempts
-   * fail. */
-  char **intro_points;
-  /** Array of n_intro_points elements for this service's introduction points'
-   * extend_infos, or NULL if this descriptor is V0.  Elements are removed
-   * from this array if introduction attempts fail.  If this array is present,
-   * its elements correspond to the elements of intro_points. */
-  extend_info_t **intro_point_extend_info;
-  strmap_t *intro_keys; /**< map from intro node hexdigest to key; only
-                         * used for versioned hidden service descriptors. */
-
-  /* XXXX020 Refactor n_intro_points, intro_points, intro_point_extend_info,
-   * and intro_keys into a list of intro points. */
+  /** List of the service's introduction points.  Elements are removed if
+   * introduction attempts fail. */
+  smartlist_t *intro_nodes;
 } rend_service_descriptor_t;
 
 int rend_cmp_service_ids(const char *one, const char *two);
@@ -3637,6 +3632,7 @@
 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);
+void rend_intro_point_free(rend_intro_point_t *intro);
 
 /** A cached rendezvous descriptor. */
 typedef struct rend_cache_entry_t {

Modified: tor/trunk/src/or/rendclient.c
===================================================================
--- tor/trunk/src/or/rendclient.c	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/rendclient.c	2007-12-21 09:28:22 UTC (rev 12900)
@@ -82,12 +82,15 @@
   if (entry->parsed->version == 0) { /* unversioned descriptor */
     intro_key = entry->parsed->pk;
   } else { /* versioned descriptor */
-    char hex_digest[HEX_DIGEST_LEN+2];
-    hex_digest[0] = '$';
-    base16_encode(hex_digest+1, HEX_DIGEST_LEN+1,
-                  introcirc->build_state->chosen_exit->identity_digest,
-                  DIGEST_LEN);
-    intro_key = strmap_get(entry->parsed->intro_keys, hex_digest);
+    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) {
       log_warn(LD_BUG, "Internal error: could not find intro key.");
       goto err;
@@ -342,35 +345,17 @@
     return 0;
   }
 
-  if (ent->parsed->intro_point_extend_info) {
-    for (i=0; i < ent->parsed->n_intro_points; ++i) {
-      if (!memcmp(failed_intro->identity_digest,
-                  ent->parsed->intro_point_extend_info[i]->identity_digest,
-                  DIGEST_LEN)) {
-        tor_assert(!strcmp(ent->parsed->intro_points[i],
-                           ent->parsed->intro_point_extend_info[i]->nickname));
-        tor_free(ent->parsed->intro_points[i]);
-        extend_info_free(ent->parsed->intro_point_extend_info[i]);
-        --ent->parsed->n_intro_points;
-        ent->parsed->intro_points[i] =
-          ent->parsed->intro_points[ent->parsed->n_intro_points];
-        ent->parsed->intro_point_extend_info[i] =
-          ent->parsed->intro_point_extend_info[ent->parsed->n_intro_points];
-        break;
-      }
+  for (i = 0; i < smartlist_len(ent->parsed->intro_nodes); i++) {
+    rend_intro_point_t *intro = smartlist_get(ent->parsed->intro_nodes, i);
+    if (!memcmp(failed_intro->identity_digest,
+                intro->extend_info->identity_digest, DIGEST_LEN)) {
+      rend_intro_point_free(intro);
+      smartlist_del(ent->parsed->intro_nodes, i);
+      break;
     }
-  } else {
-    for (i=0; i < ent->parsed->n_intro_points; ++i) {
-      if (!strcasecmp(ent->parsed->intro_points[i], failed_intro->nickname)) {
-        tor_free(ent->parsed->intro_points[i]);
-        ent->parsed->intro_points[i] =
-          ent->parsed->intro_points[--ent->parsed->n_intro_points];
-        break;
-      }
-    }
   }
 
-  if (!ent->parsed->n_intro_points) {
+  if (smartlist_len(ent->parsed->intro_nodes) == 0) {
     log_info(LD_REND,
              "No more intro points remain for %s. Re-fetching descriptor.",
              escaped_safe_str(query));
@@ -388,7 +373,7 @@
     return 0;
   }
   log_info(LD_REND,"%d options left for %s.",
-           ent->parsed->n_intro_points, escaped_safe_str(query));
+           smartlist_len(ent->parsed->intro_nodes), escaped_safe_str(query));
   return 1;
 }
 
@@ -503,7 +488,7 @@
       continue;
     assert_connection_ok(TO_CONN(conn), now);
     if (rend_cache_lookup_entry(conn->rend_query, -1, &entry) == 1 &&
-        entry->parsed->n_intro_points > 0) {
+        smartlist_len(entry->parsed->intro_nodes) > 0) {
       /* either this fetch worked, or it failed but there was a
        * valid entry from before which we should reuse */
       log_info(LD_REND,"Rend desc is usable. Launching circuits.");
@@ -537,6 +522,8 @@
 {
   int i;
   rend_cache_entry_t *entry;
+  rend_intro_point_t *intro;
+  routerinfo_t *router;
 
   if (rend_cache_lookup_entry(query, -1, &entry) < 1) {
     log_warn(LD_REND,
@@ -546,26 +533,25 @@
   }
 
  again:
-  if (!entry->parsed->n_intro_points)
+  if (smartlist_len(entry->parsed->intro_nodes) == 0)
     return NULL;
 
-  i = crypto_rand_int(entry->parsed->n_intro_points);
-
-  if (entry->parsed->intro_point_extend_info) {
-    return extend_info_dup(entry->parsed->intro_point_extend_info[i]);
-  } else {
-    /* add the intro point nicknames */
-    char *choice = entry->parsed->intro_points[i];
-    routerinfo_t *router = router_get_by_nickname(choice, 0);
+  i = crypto_rand_int(smartlist_len(entry->parsed->intro_nodes));
+  intro = smartlist_get(entry->parsed->intro_nodes, i);
+  /* Do we need to look up the router or is the extend info complete? */
+  if (!intro->extend_info->onion_key) {
+    router = router_get_by_nickname(intro->extend_info->nickname, 0);
     if (!router) {
       log_info(LD_REND, "Unknown router with nickname '%s'; trying another.",
-               choice);
-      tor_free(choice);
-      entry->parsed->intro_points[i] =
-        entry->parsed->intro_points[--entry->parsed->n_intro_points];
+               intro->extend_info->nickname);
+      rend_intro_point_free(intro);
+      smartlist_del(entry->parsed->intro_nodes, i);
       goto again;
     }
-    return extend_info_from_router(router);
+    extend_info_free(intro->extend_info);
+    intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+    intro->extend_info = extend_info_from_router(router);
   }
+  return extend_info_dup(intro->extend_info);
 }
 

Modified: tor/trunk/src/or/rendcommon.c
===================================================================
--- tor/trunk/src/or/rendcommon.c	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/rendcommon.c	2007-12-21 09:28:22 UTC (rev 12900)
@@ -20,42 +20,18 @@
   return strcasecmp(one,two);
 }
 
-/** Helper: Release the storage held by the intro key in <b>_ent</b>.
- */
-/*XXXX020 there's also one of these in rendservice.c */
-/* Right. But the only alternative to that (which I know) would be to
- * write it to or.h. Should I do that? -KL */
-static void
-intro_key_free(void *_ent)
-{
-  crypto_pk_env_t *ent = _ent;
-  crypto_free_pk_env(ent);
-}
-
 /** Free the storage held by the service descriptor <b>desc</b>.
  */
 void
 rend_service_descriptor_free(rend_service_descriptor_t *desc)
 {
-  int i;
   if (desc->pk)
     crypto_free_pk_env(desc->pk);
-  if (desc->intro_points) {
-    for (i=0; i < desc->n_intro_points; ++i) {
-      tor_free(desc->intro_points[i]);
-    }
-    tor_free(desc->intro_points);
+  if (desc->intro_nodes) {
+    SMARTLIST_FOREACH(desc->intro_nodes, rend_intro_point_t *, intro,
+      rend_intro_point_free(intro););
+    smartlist_free(desc->intro_nodes);
   }
-  if (desc->intro_point_extend_info) {
-    for (i=0; i < desc->n_intro_points; ++i) {
-      if (desc->intro_point_extend_info[i])
-        extend_info_free(desc->intro_point_extend_info[i]);
-    }
-    tor_free(desc->intro_point_extend_info);
-  }
-  if (desc->intro_keys) {
-    strmap_free(desc->intro_keys, intro_key_free);
-  }
   tor_free(desc);
 }
 
@@ -191,9 +167,9 @@
   int r = -1;
   /* Assemble unencrypted list of introduction points. */
   *ipos_base64 = NULL;
-  unenc_len = desc->n_intro_points * 1000; /* too long, but ok. */
+  unenc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */
   unenc = tor_malloc_zero(unenc_len);
-  for (i = 0; i < desc->n_intro_points; i++) {
+  for (i = 0; i < smartlist_len(desc->intro_nodes); i++) {
     char id_base32[REND_INTRO_POINT_ID_LEN_BASE32 + 1];
     char *onion_key = NULL;
     size_t onion_key_len;
@@ -202,9 +178,9 @@
     char *address = NULL;
     size_t service_key_len;
     int res;
-    char hex_digest[HEX_DIGEST_LEN+2]; /* includes $ and NUL. */
+    rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i);
     /* Obtain extend info with introduction point details. */
-    extend_info_t *info = desc->intro_point_extend_info[i];
+    extend_info_t *info = intro->extend_info;
     /* Encode introduction point ID. */
     base32_encode(id_base32, sizeof(id_base32),
                   info->identity_digest, DIGEST_LEN);
@@ -215,11 +191,7 @@
       goto done;
     }
     /* Encode intro key. */
-    hex_digest[0] = '$';
-    base16_encode(hex_digest+1, HEX_DIGEST_LEN+1,
-                  info->identity_digest,
-                  DIGEST_LEN);
-    intro_key = strmap_get(desc->intro_keys, hex_digest);
+    intro_key = intro->intro_key;
     if (!intro_key ||
       crypto_pk_write_public_key_to_string(intro_key, &service_key,
                                            &service_key_len) < 0) {
@@ -324,6 +296,17 @@
   tor_free(desc);
 }
 
+/** Free the storage held by an introduction point info. */
+void
+rend_intro_point_free(rend_intro_point_t *intro)
+{
+  if (intro->extend_info)
+    extend_info_free(intro->extend_info);
+  if (intro->intro_key)
+    crypto_free_pk_env(intro->intro_key);
+  tor_free(intro);
+}
+
 /** 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
@@ -353,7 +336,7 @@
   seconds_valid = period * REND_TIME_PERIOD_V2_DESC_VALIDITY +
                   get_seconds_valid(now, service_id);
   /* Assemble, possibly encrypt, and encode introduction points. */
-  if (desc->n_intro_points > 0 &&
+  if (smartlist_len(desc->intro_nodes) > 0 &&
       rend_encode_v2_intro_points(&ipos_base64, desc, descriptor_cookie) < 0) {
     log_warn(LD_REND, "Encoding of introduction points did not succeed.");
     return -1;
@@ -408,7 +391,8 @@
     else
       protocol_versions_string[0]= '\0';
     /* Assemble complete descriptor. */
-    desc_len = 2000 + desc->n_intro_points * 1000; /* far too long, but ok. */
+    desc_len = 2000 + smartlist_len(desc->intro_nodes) * 1000; /* far too long,
+                                                                  but okay.*/
     enc->desc_str = desc_str = tor_malloc_zero(desc_len);
     result = tor_snprintf(desc_str, desc_len,
              "rendezvous-service-descriptor %s\n"
@@ -503,18 +487,24 @@
   char *end;
   int i;
   size_t asn1len;
-  size_t buflen = PK_BYTES*2*(desc->n_intro_points+2);/*Too long, but ok*/
+  size_t buflen =
+         PK_BYTES*2*(smartlist_len(desc->intro_nodes)+2);/*Too long, but ok*/
   cp = *str_out = tor_malloc(buflen);
-  end = cp + PK_BYTES*2*(desc->n_intro_points+1);
+  end = cp + PK_BYTES*2*(smartlist_len(desc->intro_nodes)+1);
   asn1len = crypto_pk_asn1_encode(desc->pk, cp+2, end-(cp+2));
   set_uint16(cp, htons((uint16_t)asn1len));
   cp += 2+asn1len;
   set_uint32(cp, htonl((uint32_t)desc->timestamp));
   cp += 4;
-  set_uint16(cp, htons((uint16_t)desc->n_intro_points));
+  set_uint16(cp, htons((uint16_t)smartlist_len(desc->intro_nodes)));
   cp += 2;
-  for (i=0; i < desc->n_intro_points; ++i) {
-    char *ipoint = (char*)desc->intro_points[i];
+  for (i=0; i < smartlist_len(desc->intro_nodes); ++i) {
+    rend_intro_point_t *intro = smartlist_get(desc->intro_nodes, i);
+    char ipoint[HEX_DIGEST_LEN+2];
+    ipoint[0] = '$';
+    base16_encode(ipoint+1, HEX_DIGEST_LEN+1,
+                  intro->extend_info->identity_digest,
+                  DIGEST_LEN);
     strlcpy(cp, ipoint, buflen-(cp-*str_out));
     cp += strlen(ipoint)+1;
   }
@@ -537,9 +527,10 @@
 rend_parse_service_descriptor(const char *str, size_t len)
 {
   rend_service_descriptor_t *result = NULL;
-  int i;
+  int i, n_intro_points;
   size_t keylen, asn1len;
   const char *end, *cp, *eos;
+  rend_intro_point_t *intro;
 
   result = tor_malloc_zero(sizeof(rend_service_descriptor_t));
   cp = str;
@@ -558,19 +549,22 @@
   cp += 4;
   result->protocols = 1<<2; /* always use intro format 2 */
   if (end-cp < 2) goto truncated;
-  result->n_intro_points = ntohs(get_uint16(cp));
+  n_intro_points = ntohs(get_uint16(cp));
   cp += 2;
 
-  if (result->n_intro_points != 0) {
-    result->intro_points =
-      tor_malloc_zero(sizeof(char*)*result->n_intro_points);
-    for (i=0;i<result->n_intro_points;++i) {
-      if (end-cp < 2) goto truncated;
-      eos = (const char *)memchr(cp,'\0',end-cp);
-      if (!eos) goto truncated;
-      result->intro_points[i] = tor_strdup(cp);
-      cp = eos+1;
-    }
+  result->intro_nodes = smartlist_create();
+  for (i=0;i<n_intro_points;++i) {
+    if (end-cp < 2) goto truncated;
+    eos = (const char *)memchr(cp,'\0',end-cp);
+    if (!eos) goto truncated;
+    /* Write nickname to extend info, but postpone the lookup whether
+     * we know that router. It's not part of the parsing process. */
+    intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+    intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    strlcpy(intro->extend_info->nickname, cp,
+            sizeof(intro->extend_info->nickname));
+    smartlist_add(result->intro_nodes, intro);
+    cp = eos+1;
   }
   keylen = crypto_pk_keysize(result->pk);
   tor_assert(end-cp >= 0);
@@ -1091,7 +1085,7 @@
       return -1;
     }
   } else {
-    parsed->n_intro_points = 0;
+    parsed->intro_nodes = smartlist_create();
   }
   /* We don't need the encoded/encrypted introduction points any longer. */
   tor_free(intro_content);

Modified: tor/trunk/src/or/rendservice.c
===================================================================
--- tor/trunk/src/or/rendservice.c	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/rendservice.c	2007-12-21 09:28:22 UTC (rev 12900)
@@ -12,8 +12,9 @@
 
 #include "or.h"
 
-static origin_circuit_t *find_intro_circuit(routerinfo_t *router,
-                                            const char *pk_digest);
+static origin_circuit_t *find_intro_circuit(rend_intro_point_t *intro,
+                                            const char *pk_digest,
+                                            int desc_version);
 
 /** Represents the mapping from a virtual port of a rendezvous service to
  * a real port on some IP.
@@ -50,10 +51,8 @@
   crypto_pk_env_t *private_key;
   char service_id[REND_SERVICE_ID_LEN_BASE32+1];
   char pk_digest[DIGEST_LEN];
-  smartlist_t *intro_nodes; /**< list of hexdigests for intro points we have,
+  smartlist_t *intro_nodes; /**< List of rend_intro_point_t's we have,
                              * or are trying to establish. */
-  strmap_t *intro_keys; /**< map from intro node hexdigest to key; only
-                          * used for versioned hidden service descriptors. */
   time_t intro_period_started;
   int n_intro_circuits_launched; /**< count of intro circuits we have
                                   * established in this period. */
@@ -78,15 +77,6 @@
   return smartlist_len(rend_service_list);
 }
 
-/** Helper: Release the storage held by the intro key in <b>_ent</b>.
- */
-static void
-intro_key_free(void *_ent)
-{
-  crypto_pk_env_t *ent = _ent;
-  crypto_free_pk_env(ent);
-}
-
 /** Release the storage held by <b>service</b>.
  */
 static void
@@ -98,12 +88,13 @@
   smartlist_free(service->ports);
   if (service->private_key)
     crypto_free_pk_env(service->private_key);
-  if (service->intro_keys)
-    strmap_free(service->intro_keys, intro_key_free);
+  if (service->intro_nodes) {
+    SMARTLIST_FOREACH(service->intro_nodes, rend_intro_point_t *, intro,
+      rend_intro_point_free(intro););
+    smartlist_free(service->intro_nodes);
+  }
   tor_free(service->intro_prefer_nodes);
   tor_free(service->intro_exclude_nodes);
-  SMARTLIST_FOREACH(service->intro_nodes, void*, p, tor_free(p));
-  smartlist_free(service->intro_nodes);
   if (service->desc)
     rend_service_descriptor_free(service->desc);
   tor_free(service);
@@ -137,7 +128,6 @@
   if (!service->intro_exclude_nodes)
     service->intro_exclude_nodes = tor_strdup("");
   service->intro_nodes = smartlist_create();
-  service->intro_keys = strmap_new();
 
   /* If the service is configured to publish unversioned (v0) and versioned
    * descriptors (v2 or higher), split it up into two separate services. */
@@ -151,7 +141,6 @@
       memcpy(copy, p, sizeof(rend_service_port_config_t));
       smartlist_add(v0_service->ports, copy);
     });
-    v0_service->intro_nodes = smartlist_create();
     v0_service->intro_prefer_nodes = tor_strdup(service->intro_prefer_nodes);
     v0_service->intro_exclude_nodes = tor_strdup(service->intro_exclude_nodes);
     v0_service->intro_period_started = service->intro_period_started;
@@ -273,7 +262,6 @@
       service = tor_malloc_zero(sizeof(rend_service_t));
       service->directory = tor_strdup(line->value);
       service->ports = smartlist_create();
-      service->intro_nodes = smartlist_create();
       service->intro_period_started = time(NULL);
       service->descriptor_version = -1; /**< All descriptor versions. */
       continue;
@@ -349,8 +337,7 @@
 {
   rend_service_descriptor_t *d;
   origin_circuit_t *circ;
-  int i,n;
-  routerinfo_t *router;
+  int i;
   if (service->desc) {
     rend_service_descriptor_free(service->desc);
     service->desc = NULL;
@@ -359,46 +346,24 @@
   d->pk = crypto_pk_dup_key(service->private_key);
   d->timestamp = time(NULL);
   d->version = service->descriptor_version;
-  n = smartlist_len(service->intro_nodes);
-  d->n_intro_points = 0;
-  d->intro_points = tor_malloc_zero(sizeof(char*)*n);
-  d->intro_point_extend_info = tor_malloc_zero(sizeof(extend_info_t*)*n);
+  d->intro_nodes = smartlist_create();
   /* XXXX020 Why should we support the old intro protocol 0? Whoever
    * understands descriptor version 2 also understands intro protocol 2. */
   d->protocols = 1 << 2; /*< We only support intro protocol 2. */
 
-  if (service->intro_keys) {
-    /* We need to copy keys so that they're not deleted when we free the
-     * descriptor. */
-    strmap_iter_t *iter;
-    d->intro_keys = strmap_new();
-    for (iter = strmap_iter_init(service->intro_keys); !strmap_iter_done(iter);
-         iter = strmap_iter_next(service->intro_keys, iter)) {
-      const char *key;
-      void *val;
-      crypto_pk_env_t *k;
-      strmap_iter_get(iter, &key, &val);
-      k = val;
-      strmap_set(d->intro_keys, key, crypto_pk_dup_key(k));
-    }
-  }
-
-  for (i=0; i < n; ++i) {
-    const char *name = smartlist_get(service->intro_nodes, i);
-    router = router_get_by_nickname(name, 1);
-    if (!router) {
-      log_info(LD_REND,"Router '%s' not found for intro point %d. Skipping.",
-               safe_str(name), i);
+  for (i = 0; i < smartlist_len(service->intro_nodes); ++i) {
+    rend_intro_point_t *intro_svc = smartlist_get(service->intro_nodes, i);
+    rend_intro_point_t *intro_desc;
+    circ = find_intro_circuit(intro_svc, service->pk_digest, d->version);
+    if (!circ || circ->_base.purpose != CIRCUIT_PURPOSE_S_INTRO)
       continue;
-    }
-    circ = find_intro_circuit(router, service->pk_digest);
-    if (circ && circ->_base.purpose == CIRCUIT_PURPOSE_S_INTRO) {
-      /* We have an entirely established intro circuit. */
-      d->intro_points[d->n_intro_points] = tor_strdup(name);
-      d->intro_point_extend_info[d->n_intro_points] =
-        extend_info_from_router(router);
-      d->n_intro_points++;
-    }
+
+    /* We have an entirely established intro circuit. */
+    intro_desc = tor_malloc_zero(sizeof(rend_intro_point_t));
+    intro_desc->extend_info = extend_info_dup(intro_svc->extend_info);
+    if (intro_svc->intro_key)
+      intro_desc->intro_key = crypto_pk_dup_key(intro_svc->intro_key);
+    smartlist_add(d->intro_nodes, intro_desc);
   }
 }
 
@@ -791,35 +756,32 @@
  */
 static int
 rend_service_launch_establish_intro(rend_service_t *service,
-                                    const char *nickname)
+                                    rend_intro_point_t *intro)
 {
   origin_circuit_t *launched;
 
   log_info(LD_REND,
            "Launching circuit to introduction point %s for service %s",
-           escaped_safe_str(nickname), service->service_id);
+           escaped_safe_str(intro->extend_info->nickname),
+           service->service_id);
 
   rep_hist_note_used_internal(time(NULL), 1, 0);
 
   ++service->n_intro_circuits_launched;
-  launched = circuit_launch_by_nickname(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO, 0,
-                                        nickname, 1, 0, 1);
+  launched = circuit_launch_by_extend_info(CIRCUIT_PURPOSE_S_ESTABLISH_INTRO,
+                                           0, intro->extend_info, 1, 0, 1);
   if (!launched) {
     log_info(LD_REND,
              "Can't launch circuit to establish introduction at %s.",
-             escaped_safe_str(nickname));
+             escaped_safe_str(intro->extend_info->nickname));
     return -1;
   }
   strlcpy(launched->rend_query, service->service_id,
           sizeof(launched->rend_query));
   memcpy(launched->rend_pk_digest, service->pk_digest, DIGEST_LEN);
   launched->rend_desc_version = service->descriptor_version;
-  if (service->descriptor_version == 2) {
-    launched->intro_key = crypto_new_pk_env();
-    tor_assert(!crypto_pk_generate_key(launched->intro_key));
-    strmap_set(service->intro_keys, nickname,
-               crypto_pk_dup_key(launched->intro_key));
-  }
+  if (service->descriptor_version == 2)
+    launched->intro_key = crypto_pk_dup_key(intro->intro_key);
   if (launched->_base.state == CIRCUIT_STATE_OPEN)
     rend_service_intro_has_opened(launched);
   return 0;
@@ -1024,19 +986,22 @@
  */
 
 /** Return the (possibly non-open) introduction circuit ending at
- * <b>router</b> for the service whose public key is <b>pk_digest</b>.  Return
+ * <b>intro</b> for the service whose public key is <b>pk_digest</b> and
+ * which publishes descriptor of version <b>desc_version</b>.  Return
  * NULL if no such service is found.
  */
 static origin_circuit_t *
-find_intro_circuit(routerinfo_t *router, const char *pk_digest)
+find_intro_circuit(rend_intro_point_t *intro, const char *pk_digest,
+                   int desc_version)
 {
   origin_circuit_t *circ = NULL;
 
-  tor_assert(router);
+  tor_assert(intro);
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                                   CIRCUIT_PURPOSE_S_INTRO))) {
-    if (!strcasecmp(circ->build_state->chosen_exit->nickname,
-                    router->nickname)) {
+    if (!strcasecmp(circ->build_state->chosen_exit->identity_digest,
+                    intro->extend_info->identity_digest) &&
+        circ->rend_desc_version == desc_version) {
       return circ;
     }
   }
@@ -1044,8 +1009,9 @@
   circ = NULL;
   while ((circ = circuit_get_next_by_pk_and_purpose(circ,pk_digest,
                                         CIRCUIT_PURPOSE_S_ESTABLISH_INTRO))) {
-    if (!strcasecmp(circ->build_state->chosen_exit->nickname,
-                    router->nickname)) {
+    if (!strcasecmp(circ->build_state->chosen_exit->identity_digest,
+                    intro->extend_info->identity_digest) &&
+        circ->rend_desc_version == desc_version) {
       return circ;
     }
   }
@@ -1168,7 +1134,7 @@
   int i,j,r;
   routerinfo_t *router;
   rend_service_t *service;
-  char *intro;
+  rend_intro_point_t *intro;
   int changed, prev_intro_nodes;
   smartlist_t *intro_routers, *exclude_routers;
   time_t now;
@@ -1198,12 +1164,12 @@
        service. */
     for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
       intro = smartlist_get(service->intro_nodes, j);
-      router = router_get_by_nickname(intro, 0);
-      if (!router || !find_intro_circuit(router,service->pk_digest)) {
+      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, service->service_id);
-        tor_free(intro);
-        /* XXXXX020 we could also remove the intro key here. */
+                 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;
@@ -1228,7 +1194,6 @@
     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) {
-      char *hex_digest;
       router = router_choose_random_node(service->intro_prefer_nodes,
                service->intro_exclude_nodes, exclude_routers, 1, 0, 0,
                get_options()->_AllowInvalid & ALLOW_INVALID_INTRODUCTION,
@@ -1240,14 +1205,15 @@
         break;
       }
       changed = 1;
-      hex_digest = tor_malloc_zero(HEX_DIGEST_LEN+2);
-      hex_digest[0] = '$';
-      base16_encode(hex_digest+1, HEX_DIGEST_LEN+1,
-                    router->cache_info.identity_digest,
-                    DIGEST_LEN);
       smartlist_add(intro_routers, router);
       smartlist_add(exclude_routers, router);
-      smartlist_add(service->intro_nodes, hex_digest);
+      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);
     }
@@ -1265,7 +1231,7 @@
       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, service->service_id);
+                 intro->extend_info->nickname, service->service_id);
       }
     }
   }
@@ -1315,10 +1281,9 @@
 rend_service_dump_stats(int severity)
 {
   int i,j;
-  routerinfo_t *router;
   rend_service_t *service;
-  const char *nickname, *safe_name;
-  char nn_buf[MAX_VERBOSE_NICKNAME_LEN];
+  rend_intro_point_t *intro;
+  const char *safe_name;
   origin_circuit_t *circ;
 
   for (i=0; i < smartlist_len(rend_service_list); ++i) {
@@ -1326,20 +1291,11 @@
     log(severity, LD_GENERAL, "Service configured in \"%s\":",
         service->directory);
     for (j=0; j < smartlist_len(service->intro_nodes); ++j) {
-      nickname = smartlist_get(service->intro_nodes, j);
-      router = router_get_by_nickname(nickname,1);
-      if (router) {
-        router_get_verbose_nickname(nn_buf, router);
-        nickname = nn_buf;
-      }
-      safe_name = safe_str(nickname);
+      intro = smartlist_get(service->intro_nodes, j);
+      safe_name = safe_str(intro->extend_info->nickname);
 
-      if (!router) {
-        log(severity, LD_GENERAL,
-            "  Intro point %d at %s: unrecognized router", j, safe_name);
-        continue;
-      }
-      circ = find_intro_circuit(router, service->pk_digest);
+      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);

Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/routerparse.c	2007-12-21 09:28:22 UTC (rev 12900)
@@ -862,8 +862,8 @@
     tor_free(signed_digest);
     return -1;
   }
-  log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
-            hex_str(signed_digest,4));
+//  log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
+//            hex_str(signed_digest,4));
   if (memcmp(digest, signed_digest, DIGEST_LEN)) {
     log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
     tor_free(signed_digest);
@@ -3384,14 +3384,15 @@
 {
   char *ipos_decrypted = NULL;
   const char **current_ipo;
-  smartlist_t *intropoints;
   smartlist_t *tokens;
-  int i;
   directory_token_t *tok;
+  rend_intro_point_t *intro;
   extend_info_t *info;
   struct in_addr ip;
   int result;
   tor_assert(parsed);
+  /** Function may only be invoked once. */
+  tor_assert(!parsed->intro_nodes);
   tor_assert(intro_points_encrypted);
   tor_assert(intro_points_encrypted_size > 0);
   /* Decrypt introduction points, if required. */
@@ -3413,15 +3414,9 @@
     intro_points_encrypted_size = unenclen;
   }
   /* Consider one intro point after the other. */
-  current_ipo = &intro_points_encrypted;
-  intropoints = smartlist_create();
+  current_ipo = (const char **)&intro_points_encrypted;
   tokens = smartlist_create();
-  if (parsed->intro_keys) {
-    log_warn(LD_BUG, "Parsing list of introduction points for the same "
-             "hidden service, twice.");
-  } else {
-    parsed->intro_keys = strmap_new();
-  }
+  parsed->intro_nodes = smartlist_create();
   while (!strcmpstart(*current_ipo, "introduction-point ")) {
     /* Determine end of string. */
     const char *eos = strstr(*current_ipo, "\nintroduction-point ");
@@ -3444,8 +3439,9 @@
       log_warn(LD_REND, "Impossibly short introduction point.");
       goto err;
     }
-    /* Allocate new extend info. */
-    info = tor_malloc_zero(sizeof(extend_info_t));
+    /* Allocate new intro point and extend info. */
+    intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+    info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
     /* Parse identifier. */
     tok = find_first_by_keyword(tokens, R_IPO_IDENTIFIER);
     tor_assert(tok);
@@ -3453,7 +3449,7 @@
                       tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
       log_warn(LD_REND, "Identity digest contains illegal characters: %s",
                tok->args[0]);
-      tor_free(info);
+      rend_intro_point_free(intro);
       goto err;
     }
     /* Write identifier to nickname. */
@@ -3464,7 +3460,7 @@
     tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS);
     if (tor_inet_aton(tok->args[0], &ip) == 0) {
       log_warn(LD_REND, "Could not parse IP address.");
-      tor_free(info);
+      rend_intro_point_free(intro);
       goto err;
     }
     info->addr = ntohl(ip.s_addr);
@@ -3477,7 +3473,7 @@
     if (!info->port) {
       log_warn(LD_REND, "Introduction point onion port is out of range: %d",
                info->port);
-      tor_free(info);
+      rend_intro_point_free(intro);
       goto err;
     }
     /* Parse onion key. */
@@ -3486,30 +3482,12 @@
     tok->key = NULL; /* Prevent free */
     /* Parse service key. */
     tok = find_first_by_keyword(tokens, R_IPO_SERVICE_KEY);
-    strmap_set(parsed->intro_keys, info->nickname, tok->key);
+    intro->intro_key = tok->key;
     tok->key = NULL; /* Prevent free */
     /* Add extend info to list of introduction points. */
-    smartlist_add(intropoints, info);
-    /* XXX if intropoints has items on it, but we goto err the next
-     * time through the loop, we don't free the items in the 'err'
-     * section below. -RD */
+    smartlist_add(parsed->intro_nodes, intro);
   }
-  /* Write extend infos to descriptor. */
-  /* XXXX020 what if intro_points (&tc) are already set? */
-  /* This function is not intended to be invoced multiple times for
-   * the same descriptor. Should this be asserted? -KL */
-  /* Yes. -NM */
-  parsed->n_intro_points = smartlist_len(intropoints);
-  parsed->intro_point_extend_info =
-    tor_malloc_zero(sizeof(extend_info_t *) * parsed->n_intro_points);
-  parsed->intro_points =
-    tor_malloc_zero(sizeof(char *) * parsed->n_intro_points);
-  i = 0;
-  SMARTLIST_FOREACH(intropoints, extend_info_t *, ipo, {
-      parsed->intro_points[i] = tor_strdup(ipo->nickname);
-      parsed->intro_point_extend_info[i++] = ipo;
-  });
-  result = parsed->n_intro_points;
+  result = smartlist_len(parsed->intro_nodes);
   goto done;
 
  err:
@@ -3520,8 +3498,6 @@
   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
   smartlist_free(tokens);
 
-  smartlist_free(intropoints);
-
   return result;
 }
 

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2007-12-21 07:29:55 UTC (rev 12899)
+++ tor/trunk/src/or/test.c	2007-12-21 09:28:22 UTC (rev 12900)
@@ -2984,6 +2984,7 @@
   size_t len;
   crypto_pk_env_t *pk1, *pk2;
   time_t now;
+  int i;
   pk1 = pk_generate(0);
   pk2 = pk_generate(1);
 
@@ -2992,12 +2993,17 @@
   d1->pk = crypto_pk_dup_key(pk1);
   now = time(NULL);
   d1->timestamp = now;
-  d1->n_intro_points = 3;
   d1->version = 0;
-  d1->intro_points = tor_malloc(sizeof(char*)*3);
-  d1->intro_points[0] = tor_strdup("tom");
-  d1->intro_points[1] = tor_strdup("crow");
-  d1->intro_points[2] = tor_strdup("joel");
+  d1->intro_nodes = smartlist_create();
+  for (i = 0; i < 3; i++) {
+    rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
+    intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    crypto_rand(intro->extend_info->identity_digest, DIGEST_LEN);
+    intro->extend_info->nickname[0] = '$';
+    base16_encode(intro->extend_info->nickname+1, HEX_DIGEST_LEN+1,
+                  intro->extend_info->identity_digest, DIGEST_LEN);
+    smartlist_add(d1->intro_nodes, intro);
+  }
   test_assert(! rend_encode_service_descriptor(d1, pk1, &encoded, &len));
   d2 = rend_parse_service_descriptor(encoded, len);
   test_assert(d2);
@@ -3006,11 +3012,13 @@
   test_eq(d2->timestamp, now);
   test_eq(d2->version, 0);
   test_eq(d2->protocols, 1<<2);
-  test_eq(d2->n_intro_points, 3);
-  test_streq(d2->intro_points[0], "tom");
-  test_streq(d2->intro_points[1], "crow");
-  test_streq(d2->intro_points[2], "joel");
-  test_eq(NULL, d2->intro_point_extend_info);
+  test_eq(smartlist_len(d2->intro_nodes), 3);
+  for (i = 0; i < 3; i++) {
+    rend_intro_point_t *intro1 = smartlist_get(d1->intro_nodes, i);
+    rend_intro_point_t *intro2 = smartlist_get(d2->intro_nodes, i);
+    test_streq(intro1->extend_info->nickname,
+               intro2->extend_info->nickname);
+  }
 
   rend_service_descriptor_free(d1);
   rend_service_descriptor_free(d2);
@@ -3304,28 +3312,26 @@
                 service_id, REND_SERVICE_ID_LEN);
   now = time(NULL);
   generated->timestamp = now;
-  generated->n_intro_points = 3;
   generated->version = 2;
   generated->protocols = 42;
-  generated->intro_point_extend_info =
-    tor_malloc_zero(sizeof(extend_info_t *) * generated->n_intro_points);
-  generated->intro_points =
-    tor_malloc_zero(sizeof(char *) * generated->n_intro_points);
-  generated->intro_keys = strmap_new();
-  for (i = 0; i < generated->n_intro_points; i++) {
-    extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
+  generated->intro_nodes = smartlist_create();
+  for (i = 0; i < 3; i++) {
+    rend_intro_point_t *intro = tor_malloc_zero(sizeof(rend_intro_point_t));
     crypto_pk_env_t *okey = pk_generate(2 + i);
-    info->onion_key = crypto_pk_dup_key(okey);
-    crypto_pk_get_digest(info->onion_key, info->identity_digest);
+    intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
+    intro->extend_info->onion_key = crypto_pk_dup_key(okey);
+    crypto_pk_get_digest(intro->extend_info->onion_key,
+                         intro->extend_info->identity_digest);
     //crypto_rand(info->identity_digest, DIGEST_LEN); /* Would this work? */
-    info->nickname[0] = '$';
-    base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
-                  info->identity_digest, DIGEST_LEN);
-    info->addr = crypto_rand_int(65536); /* Does not cover all IP addresses. */
-    info->port = crypto_rand_int(65536);
-    generated->intro_points[i] = tor_strdup(info->nickname);
-    generated->intro_point_extend_info[i] = info;
-    strmap_set(generated->intro_keys, info->nickname, crypto_pk_dup_key(pk2));
+    intro->extend_info->nickname[0] = '$';
+    base16_encode(intro->extend_info->nickname + 1,
+                  sizeof(intro->extend_info->nickname) - 1,
+                  intro->extend_info->identity_digest, DIGEST_LEN);
+    intro->extend_info->addr = crypto_rand_int(65536); /* Does not cover all
+                                                        * IP addresses. */
+    intro->extend_info->port = crypto_rand_int(65536);
+    intro->intro_key = pk2;
+    smartlist_add(generated->intro_nodes, intro);
   }
   test_assert(rend_encode_v2_descriptors(descs, generated, now,
                                          NULL, 0) > 0);
@@ -3350,15 +3356,16 @@
   test_eq(parsed->timestamp, now);
   test_eq(parsed->version, 2);
   test_eq(parsed->protocols, 42);
-  test_eq(parsed->n_intro_points, 3);
-  for (i = 0; i < parsed->n_intro_points; i++) {
-    extend_info_t *par_info = parsed->intro_point_extend_info[i];
-    extend_info_t *gen_info = generated->intro_point_extend_info[i];
+  test_eq(smartlist_len(parsed->intro_nodes), 3);
+  for (i = 0; i < smartlist_len(parsed->intro_nodes); i++) {
+    rend_intro_point_t *par_intro = smartlist_get(parsed->intro_nodes, i),
+      *gen_intro = smartlist_get(generated->intro_nodes, i);
+    extend_info_t *par_info = par_intro->extend_info;
+    extend_info_t *gen_info = gen_intro->extend_info;
     test_assert(!crypto_pk_cmp_keys(gen_info->onion_key, par_info->onion_key));
     test_memeq(gen_info->identity_digest, par_info->identity_digest,
                DIGEST_LEN);
     test_streq(gen_info->nickname, par_info->nickname);
-    test_streq(generated->intro_points[i], parsed->intro_points[i]);
     test_eq(gen_info->addr, par_info->addr);
     test_eq(gen_info->port, par_info->port);
   }
@@ -3367,7 +3374,6 @@
     rend_encoded_v2_service_descriptor_free(smartlist_get(descs, i));
   smartlist_free(descs);
   rend_service_descriptor_free(parsed);
-  rend_service_descriptor_free(generated);
 }
 
 static void



More information about the tor-commits mailing list