Browse Source

Merge remote-tracking branch 'public/bug10841'

Nick Mathewson 11 years ago
parent
commit
67749475f5
6 changed files with 56 additions and 350 deletions
  1. 6 0
      changes/bug10841
  2. 18 86
      src/or/directory.c
  3. 3 12
      src/or/or.h
  4. 1 2
      src/or/rendclient.c
  5. 18 242
      src/or/rendcommon.c
  6. 10 8
      src/or/rendcommon.h

+ 6 - 0
changes/bug10841

@@ -0,0 +1,6 @@
+  o Removed code
+    - Remove all code for hidden service authorities to accept and serve
+      version 0 descriptors and left-over code for hidden services and
+      hidden service clients to upload and fetch version 0 descriptors.
+      Version 0 descriptors are not in use anymore since 0.2.2.1-alpha.
+      Fixes the rest of bug 10841.

+ 18 - 86
src/or/directory.c

@@ -170,12 +170,8 @@ dir_conn_purpose_to_string(int purpose)
 {
   switch (purpose)
     {
-    case DIR_PURPOSE_FETCH_RENDDESC:
-      return "hidden-service descriptor fetch";
     case DIR_PURPOSE_UPLOAD_DIR:
       return "server descriptor upload";
-    case DIR_PURPOSE_UPLOAD_RENDDESC:
-      return "hidden-service descriptor upload";
     case DIR_PURPOSE_UPLOAD_VOTE:
       return "server vote upload";
     case DIR_PURPOSE_UPLOAD_SIGNATURES:
@@ -247,13 +243,13 @@ directories_have_accepted_server_descriptor(void)
 /** Start a connection to every suitable directory authority, using
  * connection purpose <b>dir_purpose</b> and uploading <b>payload</b>
  * (of length <b>payload_len</b>). The dir_purpose should be one of
- * 'DIR_PURPOSE_UPLOAD_DIR' or 'DIR_PURPOSE_UPLOAD_RENDDESC'.
+ * 'DIR_PURPOSE_UPLOAD_{DIR|VOTE|SIGNATURES}'.
  *
  * <b>router_purpose</b> describes the type of descriptor we're
  * publishing, if we're publishing a descriptor -- e.g. general or bridge.
  *
  * <b>type</b> specifies what sort of dir authorities (V1, V3,
- * HIDSERV, BRIDGE, etc) we should upload to.
+ * BRIDGE, etc) we should upload to.
  *
  * If <b>extrainfo_len</b> is nonzero, the first <b>payload_len</b> bytes of
  * <b>payload</b> hold a router descriptor, and the next <b>extrainfo_len</b>
@@ -410,9 +406,6 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
       type = (router_purpose == ROUTER_PURPOSE_BRIDGE ? BRIDGE_DIRINFO :
                                                         V3_DIRINFO);
       break;
-    case DIR_PURPOSE_FETCH_RENDDESC:
-      type = HIDSERV_DIRINFO;
-      break;
     case DIR_PURPOSE_FETCH_STATUS_VOTE:
     case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
     case DIR_PURPOSE_FETCH_CERTIFICATE:
@@ -452,7 +445,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
     }
   }
 
-  if (!options->FetchServerDescriptors && type != HIDSERV_DIRINFO)
+  if (!options->FetchServerDescriptors)
     return;
 
   if (!get_via_tor) {
@@ -523,11 +516,7 @@ directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
     }
   } else { /* get_via_tor */
     /* Never use fascistfirewall; we're going via Tor. */
-    if (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) {
-      /* only ask hidserv authorities, any of them will do */
-      pds_flags |= PDS_IGNORE_FASCISTFIREWALL|PDS_ALLOW_SELF;
-      rs = router_pick_trusteddirserver(HIDSERV_DIRINFO, pds_flags);
-    } else {
+    if (1) {
       /* anybody with a non-zero dirport will do. Disregard firewalls. */
       pds_flags |= PDS_IGNORE_FASCISTFIREWALL;
       rs = router_pick_directory_server(type, pds_flags);
@@ -649,7 +638,7 @@ directory_initiate_command_routerstatus_rend(const routerstatus_t *status,
  * upload or download a server or rendezvous
  * descriptor. <b>dir_purpose</b> determines what
  * kind of directory connection we're launching, and must be one of
- * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC|RENDDESC_V2}. <b>router_purpose</b>
+ * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC_V2}. <b>router_purpose</b>
  * specifies the descriptor purposes we have in mind (currently only
  * used for FETCH_DIR).
  *
@@ -900,9 +889,7 @@ directory_initiate_command(const char *address, const tor_addr_t *_addr,
 static int
 is_sensitive_dir_purpose(uint8_t dir_purpose)
 {
-  return ((dir_purpose == DIR_PURPOSE_FETCH_RENDDESC) ||
-          (dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC) ||
-          (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC) ||
+  return ((dir_purpose == DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2) ||
           (dir_purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) ||
           (dir_purpose == DIR_PURPOSE_FETCH_RENDDESC_V2));
 }
@@ -1267,12 +1254,6 @@ directory_send_command(dir_connection_t *conn,
       httpcommand = "GET";
       tor_asprintf(&url, "/tor/rendezvous2/%s", resource);
       break;
-    case DIR_PURPOSE_UPLOAD_RENDDESC:
-      tor_assert(!resource);
-      tor_assert(payload);
-      httpcommand = "POST";
-      url = tor_strdup("/tor/rendezvous/publish");
-      break;
     case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
       tor_assert(!resource);
       tor_assert(payload);
@@ -1532,20 +1513,18 @@ body_is_plausible(const char *body, size_t len, int purpose)
   if (purpose == DIR_PURPOSE_FETCH_MICRODESC) {
     return (!strcmpstart(body,"onion-key"));
   }
-  if (purpose != DIR_PURPOSE_FETCH_RENDDESC) {
+  if (1) {
     if (!strcmpstart(body,"router") ||
         !strcmpstart(body,"signed-directory") ||
         !strcmpstart(body,"network-status") ||
         !strcmpstart(body,"running-routers"))
-    return 1;
+      return 1;
     for (i=0;i<32;++i) {
       if (!TOR_ISPRINT(body[i]) && !TOR_ISSPACE(body[i]))
         return 0;
     }
-    return 1;
-  } else {
-    return 1;
   }
+  return 1;
 }
 
 /** Called when we've just fetched a bunch of router descriptors in
@@ -2104,46 +2083,6 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
      * dirservers down just because they don't like us. */
   }
 
-  if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
-    tor_assert(conn->rend_data);
-    log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
-             "(%s))",
-             (int)body_len, status_code, escaped(reason));
-    switch (status_code) {
-      case 200:
-        if (rend_cache_store(body, body_len, 0,
-                             conn->rend_data->onion_address) < -1) {
-          log_warn(LD_REND,"Failed to parse rendezvous descriptor.");
-          /* Any pending rendezvous attempts will notice when
-           * connection_about_to_close_connection()
-           * cleans this dir conn up. */
-          /* We could retry. But since v0 descriptors are going out of
-           * style, it isn't worth the hassle. We'll do better in v2. */
-        } else {
-          /* Success, or at least there's a v2 descriptor already
-           * present. Notify pending connections about this. */
-          conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
-          rend_client_desc_trynow(conn->rend_data->onion_address);
-        }
-        break;
-      case 404:
-        /* Not there. Pending connections will be notified when
-         * connection_about_to_close_connection() cleans this conn up. */
-        break;
-      case 400:
-        log_warn(LD_REND,
-                 "http status 400 (%s). Dirserver didn't like our "
-                 "rendezvous query?", escaped(reason));
-        break;
-      default:
-        log_warn(LD_REND,"http status %d (%s) response unexpected while "
-                 "fetching hidden service descriptor (server '%s:%d').",
-                 status_code, escaped(reason), conn->base_.address,
-                 conn->base_.port);
-        break;
-    }
-  }
-
   if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
     #define SEND_HS_DESC_FAILED_EVENT() ( \
       control_event_hs_descriptor_failed(conn->rend_data, \
@@ -2155,27 +2094,22 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
     switch (status_code) {
       case 200:
         switch (rend_cache_store_v2_desc_as_client(body, conn->rend_data)) {
-          case -2:
+          case RCS_BADDESC:
+          case RCS_NOTDIR: /* Impossible */
             log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
                      "Retrying at another directory.");
             /* We'll retry when connection_about_to_close_connection()
              * cleans this dir conn up. */
             SEND_HS_DESC_FAILED_EVENT();
             break;
-          case -1:
-            /* We already have a v0 descriptor here. Ignoring this one
-             * and _not_ performing another request. */
-            log_info(LD_REND, "Successfully fetched v2 rendezvous "
-                     "descriptor, but we already have a v0 descriptor.");
-            conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
-            break;
+          case RCS_OKAY:
           default:
             /* success. notify pending connections about this. */
             log_info(LD_REND, "Successfully fetched v2 rendezvous "
                      "descriptor.");
             control_event_hs_descriptor_received(conn->rend_data,
                                                  conn->identity_digest);
-            conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC;
+            conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
             rend_client_desc_trynow(conn->rend_data->onion_address);
             break;
         }
@@ -2206,8 +2140,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
     }
   }
 
-  if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC ||
-      conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
+  if (conn->base_.purpose == DIR_PURPOSE_UPLOAD_RENDDESC_V2) {
     log_info(LD_REND,"Uploaded rendezvous descriptor (status %d "
              "(%s))",
              status_code, escaped(reason));
@@ -2311,7 +2244,7 @@ connection_dir_about_to_close(dir_connection_t *dir_conn)
   }
   /* If we were trying to fetch a v2 rend desc and did not succeed,
    * retry as needed. (If a fetch is successful, the connection state
-   * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC to mark that
+   * is changed to DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 to mark that
    * refetching is unnecessary.) */
   if (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2 &&
       dir_conn->rend_data &&
@@ -2452,9 +2385,7 @@ note_client_request(int purpose, int compressed, size_t bytes)
     case DIR_PURPOSE_UPLOAD_DIR:          kind = "dl/ul-dir"; break;
     case DIR_PURPOSE_UPLOAD_VOTE:         kind = "dl/ul-vote"; break;
     case DIR_PURPOSE_UPLOAD_SIGNATURES:   kind = "dl/ul-sig"; break;
-    case DIR_PURPOSE_FETCH_RENDDESC:      kind = "dl/rend"; break;
     case DIR_PURPOSE_FETCH_RENDDESC_V2:   kind = "dl/rend2"; break;
-    case DIR_PURPOSE_UPLOAD_RENDDESC:     kind = "dl/ul-rend"; break;
     case DIR_PURPOSE_UPLOAD_RENDDESC_V2:  kind = "dl/ul-rend2"; break;
   }
   if (kind) {
@@ -3312,19 +3243,20 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
       connection_dir_is_encrypted(conn) &&
       !strcmpstart(url,"/tor/rendezvous2/publish")) {
     switch (rend_cache_store_v2_desc_as_dir(body)) {
-      case -2:
+      case RCS_NOTDIR:
         log_info(LD_REND, "Rejected v2 rend descriptor (length %d) from %s "
                  "since we're not currently a hidden service directory.",
                  (int)body_len, conn->base_.address);
         write_http_status_line(conn, 503, "Currently not acting as v2 "
                                "hidden service directory");
         break;
-      case -1:
+      case RCS_BADDESC:
         log_warn(LD_REND, "Rejected v2 rend descriptor (length %d) from %s.",
                  (int)body_len, conn->base_.address);
         write_http_status_line(conn, 400,
                                "Invalid v2 service descriptor rejected");
         break;
+      case RCS_OKAY:
       default:
         write_http_status_line(conn, 200, "Service descriptor (v2) stored");
         log_info(LD_REND, "Handled v2 rendezvous descriptor post: accepted");

+ 3 - 12
src/or/or.h

@@ -400,13 +400,10 @@ typedef enum {
 #define CONTROL_CONN_STATE_NEEDAUTH 2
 #define CONTROL_CONN_STATE_MAX_ 2
 
-#define DIR_PURPOSE_MIN_ 3
-/** A connection to a directory server: download a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_FETCH_RENDDESC 3
-/** A connection to a directory server: set after a rendezvous
+#define DIR_PURPOSE_MIN_ 4
+/** A connection to a directory server: set after a v2 rendezvous
  * descriptor is downloaded. */
-#define DIR_PURPOSE_HAS_FETCHED_RENDDESC 4
+#define DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2 4
 /** A connection to a directory server: download one or more server
  * descriptors. */
 #define DIR_PURPOSE_FETCH_SERVERDESC 6
@@ -415,9 +412,6 @@ typedef enum {
 #define DIR_PURPOSE_FETCH_EXTRAINFO 7
 /** A connection to a directory server: upload a server descriptor. */
 #define DIR_PURPOSE_UPLOAD_DIR 8
-/** A connection to a directory server: upload a rendezvous
- * descriptor. */
-#define DIR_PURPOSE_UPLOAD_RENDDESC 9
 /** A connection to a directory server: upload a v3 networkstatus vote. */
 #define DIR_PURPOSE_UPLOAD_VOTE 10
 /** A connection to a directory server: upload a v3 consensus signature */
@@ -451,7 +445,6 @@ typedef enum {
  * directory server. */
 #define DIR_PURPOSE_IS_UPLOAD(p)                \
   ((p)==DIR_PURPOSE_UPLOAD_DIR ||               \
-   (p)==DIR_PURPOSE_UPLOAD_RENDDESC ||          \
    (p)==DIR_PURPOSE_UPLOAD_VOTE ||              \
    (p)==DIR_PURPOSE_UPLOAD_SIGNATURES)
 
@@ -2599,8 +2592,6 @@ typedef enum {
   V1_DIRINFO      = 1 << 0,
   /** Serves/signs v3 directory information: votes, consensuses, certs */
   V3_DIRINFO      = 1 << 2,
-  /** Serves hidden service descriptors. */
-  HIDSERV_DIRINFO = 1 << 3,
   /** Serves bridge descriptors. */
   BRIDGE_DIRINFO  = 1 << 4,
   /** Serves extrainfo documents. */

+ 1 - 2
src/or/rendclient.c

@@ -796,8 +796,7 @@ rend_client_cancel_descriptor_fetches(void)
 
   SMARTLIST_FOREACH_BEGIN(connection_array, connection_t *, conn) {
     if (conn->type == CONN_TYPE_DIR &&
-        (conn->purpose == DIR_PURPOSE_FETCH_RENDDESC ||
-         conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2)) {
+        conn->purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
       /* It's a rendezvous descriptor fetch in progress -- cancel it
        * by marking the connection for close.
        *

+ 18 - 242
src/or/rendcommon.c

@@ -672,79 +672,6 @@ rend_encode_v2_descriptors(smartlist_t *descs_out,
   return seconds_valid;
 }
 
-/** Parse a service descriptor at <b>str</b> (<b>len</b> bytes).  On
- * success, return a newly alloced service_descriptor_t.  On failure,
- * return NULL.
- */
-rend_service_descriptor_t *
-rend_parse_service_descriptor(const char *str, size_t len)
-{
-  rend_service_descriptor_t *result = NULL;
-  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;
-  end = str+len;
-  if (end-cp<2) goto truncated;
-  result->version = 0;
-  if (end-cp < 2) goto truncated;
-  asn1len = ntohs(get_uint16(cp));
-  cp += 2;
-  if ((size_t)(end-cp) < asn1len) goto truncated;
-  result->pk = crypto_pk_asn1_decode(cp, asn1len);
-  if (!result->pk) goto truncated;
-  cp += asn1len;
-  if (end-cp < 4) goto truncated;
-  result->timestamp = (time_t) ntohl(get_uint32(cp));
-  cp += 4;
-  result->protocols = 1<<2; /* always use intro format 2 */
-  if (end-cp < 2) goto truncated;
-  n_intro_points = ntohs(get_uint16(cp));
-  cp += 2;
-
-  result->intro_nodes = smartlist_new();
-  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);
-  if ((size_t)(end-cp) < keylen) goto truncated;
-  if ((size_t)(end-cp) > keylen) {
-    log_warn(LD_PROTOCOL,
-             "Signature is %d bytes too long on service descriptor.",
-             (int)((size_t)(end-cp) - keylen));
-    goto error;
-  }
-  note_crypto_pk_op(REND_CLIENT);
-  if (crypto_pk_public_checksig_digest(result->pk,
-                                       (char*)str,cp-str, /* data */
-                                       (char*)cp,end-cp  /* signature*/
-                                       )<0) {
-    log_warn(LD_PROTOCOL, "Bad signature on service descriptor.");
-    goto error;
-  }
-
-  return result;
- truncated:
-  log_warn(LD_PROTOCOL, "Truncated service descriptor.");
- error:
-  rend_service_descriptor_free(result);
-  return NULL;
-}
-
 /** Sets <b>out</b> to the first 10 bytes of the digest of <b>pk</b>,
  * base32 encoded.  NUL-terminates out.  (We use this string to
  * identify services in directory requests and .onion URLs.)
@@ -843,7 +770,7 @@ void
 rend_cache_purge(void)
 {
   if (rend_cache) {
-    log_info(LD_REND, "Purging client/v0-HS-authority HS descriptor cache");
+    log_info(LD_REND, "Purging HS descriptor cache");
     strmap_free(rend_cache, rend_cache_entry_free_);
   }
   rend_cache = strmap_new();
@@ -954,27 +881,6 @@ rend_cache_lookup_entry(const char *query, int version, rend_cache_entry_t **e)
   return 1;
 }
 
-/** <b>query</b> is a base32'ed service id. If it's malformed, return -1.
- * Else look it up.
- *   - If it is found, point *desc to it, and write its length into
- *     *desc_len, and return 1.
- *   - If it is not found, return 0.
- * Note: calls to rend_cache_clean or rend_cache_store may invalidate
- * *desc.
- */
-int
-rend_cache_lookup_desc(const char *query, int version, const char **desc,
-                       size_t *desc_len)
-{
-  rend_cache_entry_t *e;
-  int r;
-  r = rend_cache_lookup_entry(query,version,&e);
-  if (r <= 0) return r;
-  *desc = e->desc;
-  *desc_len = e->len;
-  return 1;
-}
-
 /** Lookup the v2 service descriptor with base32-encoded <b>desc_id</b> and
  * copy the pointer to it to *<b>desc</b>.  Return 1 on success, 0 on
  * well-formed-but-not-found, and -1 on failure.
@@ -1006,130 +912,16 @@ rend_cache_lookup_v2_desc_as_dir(const char *desc_id, const char **desc)
  * descriptor */
 #define MAX_INTRO_POINTS 10
 
-/** Parse *desc, calculate its service id, and store it in the cache.
- * If we have a newer v0 descriptor with the same ID, ignore this one.
- * If we have an older descriptor with the same ID, replace it.
- * If we are acting as client due to the published flag and have any v2
- * descriptor with the same ID, reject this one in order to not get
- * confused with having both versions for the same service.
- *
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v2 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
- *
- * The published flag tells us if we store the descriptor
- * in our role as directory (1) or if we cache it as client (0).
- *
- * If <b>service_id</b> is non-NULL and the descriptor is not for that
- * service ID, reject it.  <b>service_id</b> must be specified if and
- * only if <b>published</b> is 0 (we fetched this descriptor).
- */
-int
-rend_cache_store(const char *desc, size_t desc_len, int published,
-                 const char *service_id)
-{
-  rend_cache_entry_t *e;
-  rend_service_descriptor_t *parsed;
-  char query[REND_SERVICE_ID_LEN_BASE32+1];
-  char key[REND_SERVICE_ID_LEN_BASE32+2]; /* 0<query>\0 */
-  time_t now;
-  tor_assert(rend_cache);
-  parsed = rend_parse_service_descriptor(desc,desc_len);
-  if (!parsed) {
-    log_warn(LD_PROTOCOL,"Couldn't parse service descriptor.");
-    return -2;
-  }
-  if (rend_get_service_id(parsed->pk, query)<0) {
-    log_warn(LD_BUG,"Couldn't compute service ID.");
-    rend_service_descriptor_free(parsed);
-    return -2;
-  }
-  if ((service_id != NULL) && strcmp(query, service_id)) {
-    log_warn(LD_REND, "Received service descriptor for service ID %s; "
-             "expected descriptor for service ID %s.",
-             query, safe_str(service_id));
-    rend_service_descriptor_free(parsed);
-    return -2;
-  }
-  now = time(NULL);
-  if (parsed->timestamp < now-REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
-    log_fn(LOG_PROTOCOL_WARN, LD_REND,
-           "Service descriptor %s is too old.",
-           safe_str_client(query));
-    rend_service_descriptor_free(parsed);
-    return -2;
-  }
-  if (parsed->timestamp > now+REND_CACHE_MAX_SKEW) {
-    log_fn(LOG_PROTOCOL_WARN, LD_REND,
-           "Service descriptor %s is too far in the future.",
-           safe_str_client(query));
-    rend_service_descriptor_free(parsed);
-    return -2;
-  }
-  /* Do we have a v2 descriptor and fetched this descriptor as a client? */
-  tor_snprintf(key, sizeof(key), "2%s", query);
-  if (!published && strmap_get_lc(rend_cache, key)) {
-    log_info(LD_REND, "We already have a v2 descriptor for service %s.",
-             safe_str_client(query));
-    rend_service_descriptor_free(parsed);
-    return -1;
-  }
-  if (parsed->intro_nodes &&
-      smartlist_len(parsed->intro_nodes) > MAX_INTRO_POINTS) {
-    log_warn(LD_REND, "Found too many introduction points on a hidden "
-             "service descriptor for %s. This is probably a (misguided) "
-             "attempt to improve reliability, but it could also be an "
-             "attempt to do a guard enumeration attack. Rejecting.",
-             safe_str_client(query));
-    rend_service_descriptor_free(parsed);
-    return -2;
-  }
-  tor_snprintf(key, sizeof(key), "0%s", query);
-  e = (rend_cache_entry_t*) strmap_get_lc(rend_cache, key);
-  if (e && e->parsed->timestamp > parsed->timestamp) {
-    log_info(LD_REND,"We already have a newer service descriptor %s with the "
-             "same ID and version.",
-             safe_str_client(query));
-    rend_service_descriptor_free(parsed);
-    return 0;
-  }
-  if (e && e->len == desc_len && tor_memeq(desc,e->desc,desc_len)) {
-    log_info(LD_REND,"We already have this service descriptor %s.",
-             safe_str_client(query));
-    e->received = time(NULL);
-    rend_service_descriptor_free(parsed);
-    return 0;
-  }
-  if (!e) {
-    e = tor_malloc_zero(sizeof(rend_cache_entry_t));
-    strmap_set_lc(rend_cache, key, e);
-  } else {
-    rend_service_descriptor_free(e->parsed);
-    tor_free(e->desc);
-  }
-  e->received = time(NULL);
-  e->parsed = parsed;
-  e->len = desc_len;
-  e->desc = tor_malloc(desc_len);
-  memcpy(e->desc, desc, desc_len);
-
-  log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
-            safe_str_client(query), (int)desc_len);
-  return 1;
-}
-
 /** Parse the v2 service descriptor(s) in <b>desc</b> and store it/them to the
  * local rend cache. Don't attempt to decrypt the included list of introduction
  * points (as we don't have a descriptor cookie for it).
  *
  * If we have a newer descriptor with the same ID, ignore this one.
  * If we have an older descriptor with the same ID, replace it.
- * Return -2 if we are not acting as hidden service directory;
- * return -1 if the descriptor(s) were not parsable; return 0 if all
- * descriptors are the same or older than those we've already got;
- * return a positive number for the number of novel stored descriptors.
+ *
+ * Return an appropriate rend_cache_store_status_t.
  */
-int
+rend_cache_store_status_t
 rend_cache_store_v2_desc_as_dir(const char *desc)
 {
   rend_service_descriptor_t *parsed;
@@ -1149,7 +941,7 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
     /* Cannot store descs, because we are (currently) not acting as
      * hidden service directory. */
     log_info(LD_REND, "Cannot store descs: Not acting as hs dir");
-    return -2;
+    return RCS_NOTDIR;
   }
   while (rend_parse_v2_service_descriptor(&parsed, desc_id, &intro_content,
                                           &intro_size, &encoded_size,
@@ -1225,11 +1017,11 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
   }
   if (!number_parsed) {
     log_info(LD_REND, "Could not parse any descriptor.");
-    return -1;
+    return RCS_BADDESC;
   }
   log_info(LD_REND, "Parsed %d and added %d descriptor%s.",
            number_parsed, number_stored, number_stored != 1 ? "s" : "");
-  return number_stored;
+  return RCS_OKAY;
 }
 
 /** Parse the v2 service descriptor in <b>desc</b>, decrypt the included list
@@ -1239,15 +1031,12 @@ rend_cache_store_v2_desc_as_dir(const char *desc)
  *
  * If we have a newer v2 descriptor with the same ID, ignore this one.
  * If we have an older descriptor with the same ID, replace it.
- * If we have any v0 descriptor with the same ID, reject this one in order
- * to not get confused with having both versions for the same service.
  * If the descriptor's service ID does not match
  * <b>rend_query</b>-\>onion_address, reject it.
- * Return -2 if it's malformed or otherwise rejected; return -1 if we
- * already have a v0 descriptor here; return 0 if it's the same or older
- * than one we've already got; return 1 if it's novel.
+ *
+ * Return an appropriate rend_cache_store_status_t.
  */
-int
+rend_cache_store_status_t
 rend_cache_store_v2_desc_as_client(const char *desc,
                                    const rend_data_t *rend_query)
 {
@@ -1276,7 +1065,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
   char key[REND_SERVICE_ID_LEN_BASE32+2];
   char service_id[REND_SERVICE_ID_LEN_BASE32+1];
   rend_cache_entry_t *e;
-  int retval;
+  rend_cache_store_status_t retval = RCS_BADDESC;
   tor_assert(rend_cache);
   tor_assert(desc);
   /* Parse the descriptor. */
@@ -1284,20 +1073,17 @@ rend_cache_store_v2_desc_as_client(const char *desc,
                                        &intro_size, &encoded_size,
                                        &next_desc, desc) < 0) {
     log_warn(LD_REND, "Could not parse descriptor.");
-    retval = -2;
     goto err;
   }
   /* Compute service ID from public key. */
   if (rend_get_service_id(parsed->pk, service_id)<0) {
     log_warn(LD_REND, "Couldn't compute service ID.");
-    retval = -2;
     goto err;
   }
   if (strcmp(rend_query->onion_address, service_id)) {
     log_warn(LD_REND, "Received service descriptor for service ID %s; "
              "expected descriptor for service ID %s.",
              service_id, safe_str(rend_query->onion_address));
-    retval = -2;
     goto err;
   }
   /* Decode/decrypt introduction points. */
@@ -1329,7 +1115,6 @@ rend_cache_store_v2_desc_as_client(const char *desc,
       log_warn(LD_REND, "Failed to parse introduction points. Either the "
                "service has published a corrupt descriptor or you have "
                "provided invalid authorization data.");
-      retval = -2;
       goto err;
     } else if (n_intro_points > MAX_INTRO_POINTS) {
       log_warn(LD_REND, "Found too many introduction points on a hidden "
@@ -1337,7 +1122,7 @@ rend_cache_store_v2_desc_as_client(const char *desc,
                "attempt to improve reliability, but it could also be an "
                "attempt to do a guard enumeration attack. Rejecting.",
                safe_str_client(rend_query->onion_address));
-      retval = -2;
+
       goto err;
     }
   } else {
@@ -1350,22 +1135,12 @@ rend_cache_store_v2_desc_as_client(const char *desc,
   if (parsed->timestamp < now - REND_CACHE_MAX_AGE-REND_CACHE_MAX_SKEW) {
     log_warn(LD_REND, "Service descriptor with service ID %s is too old.",
              safe_str_client(service_id));
-    retval = -2;
     goto err;
   }
   /* Is descriptor too far in the future? */
   if (parsed->timestamp > now + REND_CACHE_MAX_SKEW) {
     log_warn(LD_REND, "Service descriptor with service ID %s is too far in "
                       "the future.", safe_str_client(service_id));
-    retval = -2;
-    goto err;
-  }
-  /* Do we have a v0 descriptor? */
-  tor_snprintf(key, sizeof(key), "0%s", service_id);
-  if (strmap_get_lc(rend_cache, key)) {
-    log_info(LD_REND, "We already have a v0 descriptor for service ID %s.",
-             safe_str_client(service_id));
-    retval = -1;
     goto err;
   }
   /* Do we already have a newer descriptor? */
@@ -1375,16 +1150,14 @@ rend_cache_store_v2_desc_as_client(const char *desc,
     log_info(LD_REND, "We already have a newer service descriptor for "
                       "service ID %s with the same desc ID and version.",
              safe_str_client(service_id));
-    retval = 0;
-    goto err;
+    goto okay;
   }
   /* Do we already have this descriptor? */
   if (e && !strcmp(desc, e->desc)) {
     log_info(LD_REND,"We already have this service descriptor %s.",
              safe_str_client(service_id));
     e->received = time(NULL);
-    retval = 0;
-    goto err;
+    goto okay;
   }
   if (!e) {
     e = tor_malloc_zero(sizeof(rend_cache_entry_t));
@@ -1400,7 +1173,10 @@ rend_cache_store_v2_desc_as_client(const char *desc,
   e->len = encoded_size;
   log_debug(LD_REND,"Successfully stored rend desc '%s', len %d.",
             safe_str_client(service_id), (int)encoded_size);
-  return 1;
+  return RCS_OKAY;
+
+ okay:
+  retval = RCS_OKAY;
 
  err:
   rend_service_descriptor_free(parsed);

+ 10 - 8
src/or/rendcommon.h

@@ -26,8 +26,6 @@ void rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
                              const uint8_t *payload);
 
 void rend_service_descriptor_free(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_t *pk, char *out);
 void rend_encoded_v2_service_descriptor_free(
                                rend_encoded_v2_service_descriptor_t *desc);
@@ -39,16 +37,20 @@ void rend_cache_clean_v2_descs_as_dir(time_t now);
 void rend_cache_purge(void);
 void rend_cache_free_all(void);
 int rend_valid_service_id(const char *query);
-int rend_cache_lookup_desc(const char *query, int version, const char **desc,
-                           size_t *desc_len);
 int rend_cache_lookup_entry(const char *query, int version,
                             rend_cache_entry_t **entry_out);
 int rend_cache_lookup_v2_desc_as_dir(const char *query, const char **desc);
-int rend_cache_store(const char *desc, size_t desc_len, int published,
-                     const char *service_id);
-int rend_cache_store_v2_desc_as_client(const char *desc,
+/** Return value from rend_cache_store_v2_desc_as_{dir,client}. */
+typedef enum {
+  RCS_NOTDIR = -2, /**< We're not a directory */
+  RCS_BADDESC = -1, /**< This descriptor is no good. */
+  RCS_OKAY = 0 /**< All worked as expected */
+} rend_cache_store_status_t;
+
+rend_cache_store_status_t rend_cache_store_v2_desc_as_dir(const char *desc);
+rend_cache_store_status_t rend_cache_store_v2_desc_as_client(const char *desc,
                                        const rend_data_t *rend_query);
-int rend_cache_store_v2_desc_as_dir(const char *desc);
+
 int rend_encode_v2_descriptors(smartlist_t *descs_out,
                                rend_service_descriptor_t *desc, time_t now,
                                uint8_t period, rend_auth_type_t auth_type,