[or-cvs] r16380: Implement most of the more scalable client authorization pro (tor/branches/121-hs-authorization/src/or)

kloesing at seul.org kloesing at seul.org
Mon Aug 4 12:40:08 UTC 2008


Author: kloesing
Date: 2008-08-04 08:40:07 -0400 (Mon, 04 Aug 2008)
New Revision: 16380

Modified:
   tor/branches/121-hs-authorization/src/or/circuitlist.c
   tor/branches/121-hs-authorization/src/or/circuituse.c
   tor/branches/121-hs-authorization/src/or/connection.c
   tor/branches/121-hs-authorization/src/or/connection_edge.c
   tor/branches/121-hs-authorization/src/or/directory.c
   tor/branches/121-hs-authorization/src/or/or.h
   tor/branches/121-hs-authorization/src/or/rendclient.c
   tor/branches/121-hs-authorization/src/or/rendcommon.c
   tor/branches/121-hs-authorization/src/or/rendservice.c
   tor/branches/121-hs-authorization/src/or/routerparse.c
   tor/branches/121-hs-authorization/src/or/test.c
Log:
Implement most of the more scalable client authorization protocol as specified in proposal 121.

Modified: tor/branches/121-hs-authorization/src/or/circuitlist.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/circuitlist.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/circuitlist.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -1019,9 +1019,8 @@
              safe_str(ocirc->rend_query),
              safe_str(build_state_get_exit_nickname(ocirc->build_state)));
     rend_client_remove_intro_point(ocirc->build_state->chosen_exit,
-                                   ocirc->rend_query,
-                                   (ocirc->has_desc_cookie ?
-                                    ocirc->rend_desc_cookie : NULL));
+                                   ocirc->rend_query, ocirc->auth_type,
+                                   ocirc->rend_desc_cookie);
   }
   if (circ->n_conn)
     connection_or_send_destroy(circ->n_circ_id, circ->n_conn, reason);

Modified: tor/branches/121-hs-authorization/src/or/circuituse.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/circuituse.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/circuituse.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -1051,10 +1051,9 @@
         /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever
          * arrives first. Exception: When using a descriptor cookie, only
          * fetch v2 descriptors.*/
-        rend_client_refetch_v2_renddesc(conn->rend_query,
-                                        (conn->has_desc_cookie ?
-                                         conn->rend_desc_cookie : NULL));
-        if (!conn->has_desc_cookie)
+        rend_client_refetch_v2_renddesc(conn->rend_query, conn->auth_type,
+                                        conn->rend_desc_cookie);
+        if (!conn->auth_type)
           rend_client_refetch_renddesc(conn->rend_query);
         conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
         return 0;
@@ -1136,10 +1135,10 @@
       if (circ) {
         /* write the service_id (and descriptor cookie?) into circ */
         strlcpy(circ->rend_query, conn->rend_query, sizeof(circ->rend_query));
-        if (conn->has_desc_cookie) {
+        if (conn->auth_type) {
           memcpy(circ->rend_desc_cookie, conn->rend_desc_cookie,
                  REND_DESC_COOKIE_LEN);
-          circ->has_desc_cookie = 1;
+          circ->auth_type = conn->auth_type;
         }
         if (circ->_base.purpose == CIRCUIT_PURPOSE_C_ESTABLISH_REND &&
             circ->_base.state == CIRCUIT_STATE_OPEN)

Modified: tor/branches/121-hs-authorization/src/or/connection.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/connection.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/connection.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -489,8 +489,8 @@
            dir_conn->rend_query &&
            strlen(dir_conn->rend_query) == REND_SERVICE_ID_LEN_BASE32)
         rend_client_refetch_v2_renddesc(dir_conn->rend_query,
-                                        (dir_conn->has_desc_cookie ?
-                                         dir_conn->rend_desc_cookie : NULL));
+                                        dir_conn->auth_type,
+                                        dir_conn->rend_desc_cookie);
       break;
     case CONN_TYPE_OR:
       or_conn = TO_OR_CONN(conn);

Modified: tor/branches/121-hs-authorization/src/or/connection_edge.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/connection_edge.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/connection_edge.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -1607,7 +1607,7 @@
                "for hidden service.");
       memcpy(conn->rend_desc_cookie, client_auth->descriptor_cookie,
              REND_DESC_COOKIE_LEN);
-      conn->has_desc_cookie = 1;
+      conn->auth_type = client_auth->auth_type;
     }
     if (r==0) {
       conn->_base.state = AP_CONN_STATE_RENDDESC_WAIT;
@@ -1616,10 +1616,9 @@
       /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever
        * arrives first. Exception: When using a descriptor cookie, only
        * fetch v2 descriptors.*/
-      rend_client_refetch_v2_renddesc(conn->rend_query,
-                                      (conn->has_desc_cookie ?
-                                       conn->rend_desc_cookie : NULL));
-      if (!conn->has_desc_cookie)
+      rend_client_refetch_v2_renddesc(conn->rend_query, conn->auth_type,
+                                      conn->rend_desc_cookie);
+      if (!conn->auth_type)
         rend_client_refetch_renddesc(conn->rend_query);
     } else { /* r > 0 */
 /** How long after we receive a hidden service descriptor do we consider
@@ -1639,10 +1638,9 @@
         /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever
          * arrives first. Exception: When using a descriptor cookie, only
          * fetch v2 descriptors.*/
-        rend_client_refetch_v2_renddesc(conn->rend_query,
-                                        (conn->has_desc_cookie ?
-                                         conn->rend_desc_cookie : NULL));
-        if (!conn->has_desc_cookie)
+        rend_client_refetch_v2_renddesc(conn->rend_query, conn->auth_type,
+                                        conn->rend_desc_cookie);
+        if (!conn->auth_type)
           rend_client_refetch_renddesc(conn->rend_query);
       }
     }

Modified: tor/branches/121-hs-authorization/src/or/directory.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/directory.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/directory.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -1008,9 +1008,9 @@
       strlcpy(conn->rend_query, payload, sizeof(conn->rend_query));
       if (strlen(payload) > REND_SERVICE_ID_LEN_BASE32) {
         memcpy(conn->rend_desc_cookie,
-               payload + REND_SERVICE_ID_LEN_BASE32 + 1,
+               payload + REND_SERVICE_ID_LEN_BASE32 + 1 + 1,
                REND_DESC_COOKIE_LEN);
-        conn->has_desc_cookie = 1;
+        conn->auth_type = payload[REND_SERVICE_ID_LEN_BASE32 + 1];
       }
       conn->rend_version = 2;
       payload = NULL;
@@ -1910,8 +1910,8 @@
              (int)body_len, status_code, escaped(reason));
     switch (status_code) {
       case 200:
-        switch (rend_cache_store_v2_desc_as_client(body,
-                (conn->has_desc_cookie ? conn->rend_desc_cookie : NULL))) {
+        switch (rend_cache_store_v2_desc_as_client(body, conn->auth_type,
+                conn->rend_desc_cookie)) {
           case -2:
             log_warn(LD_REND,"Fetching v2 rendezvous descriptor failed. "
                      "Retrying at another directory.");

Modified: tor/branches/121-hs-authorization/src/or/or.h
===================================================================
--- tor/branches/121-hs-authorization/src/or/or.h	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/or.h	2008-08-04 12:40:07 UTC (rev 16380)
@@ -1021,8 +1021,9 @@
    * hidden service. */
   char rend_desc_cookie[REND_DESC_COOKIE_LEN];
 
-  /** True iff this connection contains a descriptor cookie. */
-  int has_desc_cookie:1;
+  /** Client authorization type that is used for this hidden-service
+   * request, if any. */
+  int auth_type;
 
   /** Number of times we've reassigned this application connection to
    * a new circuit. We keep track because the timeout is longer if we've
@@ -1086,8 +1087,9 @@
    * hidden service. */
   char rend_desc_cookie[REND_DESC_COOKIE_LEN];
 
-  /** True iff this connection contains a descriptor cookie. */
-  int has_desc_cookie:1;
+  /** Client authorization type that is used for this hidden-service
+   * request, if any. */
+  int auth_type;
 
   char identity_digest[DIGEST_LEN]; /**< Hash of the public RSA key for
                                      * the directory server's signing key. */
@@ -1896,8 +1898,9 @@
    * hidden service. */
   char rend_desc_cookie[REND_DESC_COOKIE_LEN];
 
-  /** True iff this circuit contains a descriptor cookie. */
-  int has_desc_cookie:1;
+  /** Client authorization type that is used for this hidden-service
+   * request, if any. */
+  int auth_type;
 
   /** Stores the rendezvous descriptor version if purpose is S_*. Used to
    * distinguish introduction and rendezvous points belonging to the same
@@ -3783,10 +3786,10 @@
 int rend_client_introduction_acked(origin_circuit_t *circ, const char *request,
                                    size_t request_len);
 void rend_client_refetch_renddesc(const char *query);
-void rend_client_refetch_v2_renddesc(const char *query,
+void rend_client_refetch_v2_renddesc(const char *query, int auth_type,
                                      const char *descriptor_cookie);
 int rend_client_remove_intro_point(extend_info_t *failed_intro,
-                                   const char *query,
+                                   const char *query, int auth_type,
                                    const char *descriptor_cookie);
 int rend_client_rendezvous_acked(origin_circuit_t *circ, const char *request,
                                  size_t request_len);
@@ -3814,6 +3817,7 @@
   char *service_name;
   char descriptor_cookie[REND_DESC_COOKIE_LEN];
   char onion_address[REND_SERVICE_ID_LEN_BASE32+1+5+1];
+  int auth_type;
 } rend_service_authorization_t;
 
 rend_service_authorization_t *lookup_client_auth(char *onion_address);
@@ -3879,14 +3883,15 @@
                             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);
-int rend_cache_store_v2_desc_as_client(const char *desc,
-                               const char *descriptor_cookie);
+int rend_cache_store_v2_desc_as_client(const char *desc, int auth_type,
+                                       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 *descs_out,
                                rend_service_descriptor_t *desc, time_t now,
-                               crypto_pk_env_t *client_key,
-                               const char *descriptor_cookie, uint8_t period);
+                               crypto_pk_env_t *service_key, int auth_type,
+                               const char *descriptor_cookie,
+                               smartlist_t *client_cookies, uint8_t period);
 int rend_compute_v2_desc_id(char *desc_id_out, const char *service_id,
                             const char *descriptor_cookie,
                             time_t now, uint8_t replica);
@@ -4247,8 +4252,12 @@
                                      size_t *intro_points_encrypted_size_out,
                                      size_t *encoded_size_out,
                                      const char **next_out, const char *desc);
-int rend_decrypt_introduction_points(rend_service_descriptor_t *parsed,
+int rend_decrypt_introduction_points(char **ipos_decrypted,
+                                     size_t *ipos_decrypted_size,
                                      const char *descriptor_cookie,
+                                     const char *ipos_encrypted,
+                                     size_t ipos_encrypted_size);
+int rend_parse_introduction_points(rend_service_descriptor_t *parsed,
                                      const char *intro_content,
                                      size_t intro_size);
 int rend_parse_client_keys(strmap_t *parsed_clients, const char *str);

Modified: tor/branches/121-hs-authorization/src/or/rendclient.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/rendclient.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/rendclient.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -121,7 +121,7 @@
   if (entry->parsed->protocols & (1<<3)) {
     tmp[0] = 3; /* version 3 of the cell format */
     auth_shift = 1;
-    if (introcirc->has_desc_cookie) {
+    if (introcirc->auth_type) {
       tmp[1] = 1;
       set_uint16(tmp+2, htons(REND_DESC_COOKIE_LEN));
       memcpy(tmp+4, introcirc->rend_desc_cookie, REND_DESC_COOKIE_LEN);
@@ -261,8 +261,8 @@
      */
     if (rend_client_remove_intro_point(circ->build_state->chosen_exit,
                                        circ->rend_query,
-                                       (circ->has_desc_cookie ?
-                                        circ->rend_desc_cookie : NULL)) > 0) {
+                                       circ->auth_type,
+                                       circ->rend_desc_cookie) > 0) {
       /* There are introduction points left. Re-extend the circuit to
        * another intro point and try again. */
       extend_info_t *extend_info;
@@ -359,13 +359,13 @@
  * passed for pretty log statements. */
 static int
 directory_get_from_hs_dir(const char *desc_id, const char *query,
-                          const char *descriptor_cookie)
+                          int auth_type, const char *descriptor_cookie)
 {
   smartlist_t *responsible_dirs = smartlist_create();
   routerstatus_t *hs_dir;
   char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
   time_t now = time(NULL);
-  char payload[REND_SERVICE_ID_LEN_BASE32 + 1 + REND_DESC_COOKIE_LEN];
+  char payload[REND_SERVICE_ID_LEN_BASE32 + 1 + 1 + REND_DESC_COOKIE_LEN];
   char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
   tor_assert(desc_id);
   tor_assert(query);
@@ -408,23 +408,26 @@
   strlcpy(payload, query, REND_SERVICE_ID_LEN_BASE32+1);
   if (descriptor_cookie) {
     payload[REND_SERVICE_ID_LEN_BASE32] = ':';
-    memcpy(payload + REND_SERVICE_ID_LEN_BASE32 + 1, descriptor_cookie,
+    payload[REND_SERVICE_ID_LEN_BASE32 + 1] = auth_type;
+    memcpy(payload + REND_SERVICE_ID_LEN_BASE32 + 1 + 1, descriptor_cookie,
            REND_DESC_COOKIE_LEN);
     if (base64_encode(descriptor_cookie_base64, 3*REND_DESC_COOKIE_LEN_BASE64,
                       descriptor_cookie, REND_DESC_COOKIE_LEN) < 0) {
       log_warn(LD_BUG, "Could not base64-encode descriptor cookie.");
       return 0;
     }
+    /* Remove == signs and newline. */
+    descriptor_cookie_base64[strlen(descriptor_cookie_base64)-3] = '\0';
   }
   directory_initiate_command_routerstatus(hs_dir,
                                           DIR_PURPOSE_FETCH_RENDDESC_V2,
                                           ROUTER_PURPOSE_GENERAL,
                                           1, desc_id_base32, payload, 0, 0);
   log_info(LD_REND, "Sending fetch request for v2 descriptor for "
-                    "service '%s' with descriptor ID '%s' and descriptor "
-                    "cookie '%s' to hidden "
-                    "service directory '%s' on port %d.",
-           query, desc_id_base32,
+                    "service '%s' with descriptor ID '%s', auth type %d, "
+                    "and descriptor cookie '%s' to hidden service "
+                    "directory '%s' on port %d.",
+           query, desc_id_base32, auth_type,
            (descriptor_cookie == NULL ? "NULL" :
            escaped_safe_str(descriptor_cookie_base64)),
            hs_dir->nickname, hs_dir->dir_port);
@@ -457,7 +460,7 @@
  * <b>query</b>.
  */
 void
-rend_client_refetch_v2_renddesc(const char *query,
+rend_client_refetch_v2_renddesc(const char *query, int auth_type,
                                 const char *descriptor_cookie)
 {
   char descriptor_id[DIGEST_LEN];
@@ -490,13 +493,14 @@
     int chosen_replica = replicas_left_to_try[rand];
     replicas_left_to_try[rand] = replicas_left_to_try[--tries_left];
 
-    if (rend_compute_v2_desc_id(descriptor_id, query, descriptor_cookie,
+    if (rend_compute_v2_desc_id(descriptor_id, query,
+                                auth_type == 2 ? descriptor_cookie : NULL,
                                 time(NULL), chosen_replica) < 0) {
       log_warn(LD_REND, "Internal error: Computing v2 rendezvous "
                         "descriptor ID did not succeed.");
       return;
     }
-    if (directory_get_from_hs_dir(descriptor_id, query,
+    if (directory_get_from_hs_dir(descriptor_id, query, auth_type,
                                   descriptor_cookie) != 0)
       return; /* either success or failure, but we're done */
   }
@@ -515,7 +519,7 @@
  */
 int
 rend_client_remove_intro_point(extend_info_t *failed_intro, const char *query,
-                               const char *descriptor_cookie)
+                               int auth_type, const char *descriptor_cookie)
 {
   int i, r;
   rend_cache_entry_t *ent;
@@ -530,10 +534,10 @@
     log_info(LD_REND, "Unknown service %s. Re-fetching descriptor.",
              escaped_safe_str(query));
     /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever
-     * arrives first. Exception: When using a descriptor cookie, only
-     * fetch v2 descriptors.*/
-    rend_client_refetch_v2_renddesc(query, descriptor_cookie);
-    if (!descriptor_cookie)
+     * arrives first. Exception: When using any kind of client
+     * authorization, only fetch v2 descriptors.*/
+    rend_client_refetch_v2_renddesc(query, auth_type, descriptor_cookie);
+    if (!auth_type)
       rend_client_refetch_renddesc(query);
     return 0;
   }
@@ -553,10 +557,10 @@
              "No more intro points remain for %s. Re-fetching descriptor.",
              escaped_safe_str(query));
     /* Fetch both, v0 and v2 rend descriptors in parallel. Use whichever
-     * arrives first. Exception: When using a descriptor cookie, only
-     * fetch v2 descriptors.*/
-    rend_client_refetch_v2_renddesc(query, descriptor_cookie);
-    if (!descriptor_cookie)
+     * arrives first. Exception: When using any kind of client
+     * authorization, only fetch v2 descriptors.*/
+    rend_client_refetch_v2_renddesc(query, auth_type, descriptor_cookie);
+    if (!auth_type)
       rend_client_refetch_renddesc(query);
 
     /* move all pending streams back to renddesc_wait */
@@ -782,9 +786,10 @@
 {
   char *service_name, *onion_address, *descriptor_cookie;
   char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
+  char descriptor_cookie_base64ext[REND_DESC_COOKIE_LEN_BASE64+2+1];
   smartlist_t *sl = smartlist_create();
   rend_service_authorization_t *auth = NULL;
-  int res = 0;
+  int res = 0, auth_type = 0;
   size_t len;
   tor_assert(config_line);
   smartlist_split_string(sl, config_line, " ",
@@ -834,12 +839,24 @@
              descriptor_cookie);
     goto free;
   }
+  /* Add trailing zero bytes (AA) to make base64-decoding happy. */
+  tor_snprintf(descriptor_cookie_base64ext,
+               REND_DESC_COOKIE_LEN_BASE64+2+1,
+               "%sAA", descriptor_cookie);
   if (base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
-                    descriptor_cookie, strlen(descriptor_cookie)) < 0) {
+                    descriptor_cookie_base64ext,
+                    strlen(descriptor_cookie_base64ext)) < 0) {
     log_warn(LD_CONFIG, "Decoding descriptor cookie failed: '%s'",
              descriptor_cookie);
     goto free;
   }
+  auth_type = (descriptor_cookie_tmp[16] >> 4) + 1;
+  if (auth_type < 1 || auth_type > 2) {
+    log_warn(LD_CONFIG, "Descriptor cookie has unknown authorization type "
+             "encoded.");
+    goto free;
+  }
+  auth->auth_type = auth_type;
   memcpy(auth->descriptor_cookie, descriptor_cookie_tmp,
          REND_DESC_COOKIE_LEN);
   /* Add parsed client authorization to local map. */

Modified: tor/branches/121-hs-authorization/src/or/rendcommon.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/rendcommon.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/rendcommon.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -150,25 +150,20 @@
   return 0;
 }
 
-/* Encode the introduction points in <b>desc</b>, optionally encrypt them with
- * an optional <b>descriptor_cookie</b> of length REND_DESC_COOKIE_LEN,
- * encode it in base64, and write it to a newly allocated string, and write a
- * pointer to it to *<b>ipos_base64</b>. Return 0 for success, -1
- * otherwise. */
+/** Encode the introduction points in <b>desc</b> and write the result to a
+ * newly allocated string pointed to by <b>encoded</b>. Return 0 for
+ * success, -1 otherwise. */
 static int
-rend_encode_v2_intro_points(char **ipos_base64,
-                            rend_service_descriptor_t *desc,
-                            const char *descriptor_cookie)
+rend_encode_v2_intro_points(char **encoded, rend_service_descriptor_t *desc)
 {
-  size_t unenc_len;
-  char *unenc = NULL;
-  size_t unenc_written = 0;
+  size_t enc_len;
+  char *enc = NULL;
+  size_t enc_written = 0;
   int i;
   int r = -1;
-  /* Assemble unencrypted list of introduction points. */
-  *ipos_base64 = NULL;
-  unenc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */
-  unenc = tor_malloc_zero(unenc_len);
+  /* Assemble list of introduction points. */
+  enc_len = smartlist_len(desc->intro_nodes) * 1000; /* too long, but ok. */
+  enc = tor_malloc_zero(enc_len);
   for (i = 0; i < smartlist_len(desc->intro_nodes); i++) {
     char id_base32[REND_INTRO_POINT_ID_LEN_BASE32 + 1];
     char *onion_key = NULL;
@@ -201,7 +196,7 @@
     }
     /* Assemble everything for this introduction point. */
     address = tor_dup_addr(info->addr);
-    res = tor_snprintf(unenc + unenc_written, unenc_len - unenc_written,
+    res = tor_snprintf(enc + enc_written, enc_len - enc_written,
                          "introduction-point %s\n"
                          "ip-address %s\n"
                          "onion-port %d\n"
@@ -220,48 +215,167 @@
                         "string.");
       goto done;
     }
-    /* Update total number of written bytes for unencrypted intro points. */
-    unenc_written += res;
+    /* Update total number of written bytes for intro points. */
+    enc_written += res;
   }
-  /* Finalize unencrypted introduction points. */
-  if (unenc_len < unenc_written + 2) {
+  /* Finalize encrypted introduction points. */
+  if (enc_len < enc_written + 2) {
     log_warn(LD_REND, "Not enough space for finalizing introduction point "
                       "string.");
     goto done;
   }
-  unenc[unenc_written++] = '\n';
-  unenc[unenc_written++] = 0;
-  /* If a descriptor cookie is passed, encrypt introduction points. */
-  if (descriptor_cookie) {
-    char *enc = tor_malloc_zero(unenc_written + CIPHER_IV_LEN);
-    crypto_cipher_env_t *cipher =
-      crypto_create_init_cipher(descriptor_cookie, 1);
-    int enclen = crypto_cipher_encrypt_with_iv(cipher, enc,
-                                               unenc_written + CIPHER_IV_LEN,
-                                               unenc, unenc_written);
+  enc[enc_written++] = '\n';
+  enc[enc_written++] = 0;
+  *encoded = enc;
+  r = 0;
+ done:
+  if (r<0)
+    tor_free(enc);
+  return r;
+}
+
+/** Encrypt the encoded introduction points in <b>encoded</b> using
+ * <b>descriptor_cookie</b> of length REND_DESC_COOKIE_LEN and write the
+ * result to <b>encrypted</b> of length <b>encrypted_len</b>. Return 0 for
+ * success, -1 otherwise. */
+static int
+rend_encrypt_v2_intro_points_auth1(char **encrypted, size_t *encrypted_len,
+                                   const char *encoded,
+                                   smartlist_t *client_cookies)
+{
+  int r = -1, i, pos;
+  size_t len, client_entries_len;
+  int enclen, client_blocks;
+  char *enc = NULL;
+  smartlist_t *encrypted_session_keys = NULL;
+  char iv[CIPHER_IV_LEN];
+  char *client_part = NULL;
+  crypto_digest_env_t *digest;
+  crypto_cipher_env_t *cipher;
+
+  /* Generate session key. */
+  char session_key[CIPHER_IV_LEN];
+  log_debug(LD_REND, "Encoding (hopefully a string) '%s'", encoded);
+
+  if (crypto_rand(session_key, CIPHER_IV_LEN) < 0) {
+    log_warn(LD_REND, "Unable to generate random session key to encrypt "
+             "introduction point string.");
+    goto done;
+  }
+  log_debug(LD_REND, "Generated session key is '%s'",
+            hex_str(session_key, CIPHER_IV_LEN));
+
+  /* Determine length of encrypted introduction points including session
+   * keys. */
+  client_blocks = 1 + (smartlist_len(client_cookies) - 1) / 16;
+  client_entries_len = client_blocks * 16 * 20;
+  len = 2 + client_entries_len + CIPHER_IV_LEN + strlen(encoded);
+  enc = tor_malloc_zero(len);
+  enc[0] = 0x01;
+  enc[1] = (uint8_t) client_blocks;
+  log_debug(LD_REND, "We have %d clients which means the introduction "
+                     "point part will be 2 + 320 * (1 + (%d - 1) / 16) "
+                     "+ %d + %d = %d octets long.",
+           smartlist_len(client_cookies), smartlist_len(client_cookies),
+           CIPHER_IV_LEN, strlen(encoded), len);
+  /* Encrypt with random session key (instead of descriptor cookie). */
+  log_debug(LD_REND, "Writing encrypted part beginning at %d",
+           2 + client_entries_len);
+  cipher = crypto_create_init_cipher(session_key, 1);
+  enclen = crypto_cipher_encrypt_with_iv(cipher,
+      enc + 2 + client_entries_len,
+      CIPHER_IV_LEN + strlen(encoded), encoded, strlen(encoded));
+  crypto_free_cipher_env(cipher);
+  if (enclen < 0) {
+    log_warn(LD_REND, "Could not encrypt introduction point string.");
+    tor_free(enc);
+    goto done;
+  }
+  memcpy(iv, enc + 2 + client_entries_len, sizeof(iv));
+  log_debug(LD_REND, "Initialization vector: '%s'", hex_str(iv, 16));
+  /* Encrypt session key for cookies, determine client IDs, and put both
+   * in a smartlist. */
+  encrypted_session_keys = smartlist_create();
+  SMARTLIST_FOREACH(client_cookies, char *, cookie, {
+    client_part = tor_malloc_zero(4 + 16);
+    /* Encrypt session key. */
+    cipher = crypto_create_init_cipher(cookie, 1);
+    if (crypto_cipher_encrypt(cipher, client_part + 4, session_key, 16) < 0) {
+      log_warn(LD_REND, "Could not encrypt session key for client.");
+      crypto_free_cipher_env(cipher);
+      tor_free(client_part);
+      goto done;
+    }
     crypto_free_cipher_env(cipher);
-    if (enclen < 0) {
-      log_warn(LD_REND, "Could not encrypt introduction point string.");
-      tor_free(enc);
+    /* Determine client ID. */
+    digest = crypto_new_digest_env();
+    crypto_digest_add_bytes(digest, cookie, 16);
+    crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
+    crypto_digest_get_digest(digest, client_part, 4);
+    crypto_free_digest_env(digest);
+    /* Put both together. */
+    smartlist_add(encrypted_session_keys, client_part);
+  });
+  /* Add some fake client IDs and encrypted session keys. */
+  for (i = (smartlist_len(client_cookies) - 1) % 16; i < 15; i++) {
+    client_part = tor_malloc_zero(4 + 16);
+    if (crypto_rand(client_part, 20) < 0) {
+      log_warn(LD_REND, "Unable to generate fake client entry.");
       goto done;
     }
-    /* Replace original string with the encrypted one. */
-    tor_free(unenc);
-    unenc = enc;
-    unenc_written = enclen;
+    smartlist_add(encrypted_session_keys, client_part);
+    log_debug(LD_REND, "Fake client part '%s'", hex_str(client_part, 20));
   }
-  /* Base64-encode introduction points. */
-  *ipos_base64 = tor_malloc_zero(unenc_written * 2);
-  if (base64_encode(*ipos_base64, unenc_written * 2, unenc, unenc_written)<0) {
-    log_warn(LD_REND, "Could not encode introduction point string to "
-             "base64.");
+  /* Sort smartlist. */
+  smartlist_sort_digests(encrypted_session_keys);
+  /* put elements in results in order. */
+  pos = 2;
+  SMARTLIST_FOREACH(encrypted_session_keys, char *, entry, {
+    memcpy(enc + pos, entry, 20);
+    pos += 20;
+    log_debug(LD_REND, "Putting in client part '%s'", hex_str(entry, 20));
+  });
+  *encrypted = enc;
+  *encrypted_len = len;
+  r = 0;
+ done:
+  if (r<0)
+    tor_free(enc);
+  if (encrypted_session_keys)
+    SMARTLIST_FOREACH(encrypted_session_keys, char *, d, tor_free(d););
+  tor_free(encrypted_session_keys);
+  return r;
+}
+
+/** Encrypt the encoded introduction points in <b>encoded</b> using
+ * <b>descriptor_cookie</b> of length REND_DESC_COOKIE_LEN and write the
+ * result to <b>encrypted</b> of length <b>encrypted_len</b>. Return 0 for
+ * success, -1 otherwise. */
+static int
+rend_encrypt_v2_intro_points_auth2(char **encrypted, size_t *encrypted_len,
+                                   const char *encoded,
+                                   const char *descriptor_cookie)
+{
+  int r = -1;
+  char *enc = tor_malloc_zero(1 + CIPHER_IV_LEN + strlen(encoded));
+  crypto_cipher_env_t *cipher =
+      crypto_create_init_cipher(descriptor_cookie, 1);
+  int enclen = crypto_cipher_encrypt_with_iv(cipher, enc + 1,
+                                             CIPHER_IV_LEN + strlen(encoded),
+                                             encoded, strlen(encoded));
+  crypto_free_cipher_env(cipher);
+  if (enclen < 0) {
+    log_warn(LD_REND, "Could not encrypt introduction point string.");
+    tor_free(enc);
     goto done;
   }
+  enc[0] = 0x02;
+  *encrypted = enc;
+  *encrypted_len = enclen;
   r = 0;
  done:
   if (r<0)
-    tor_free(*ipos_base64);
-  tor_free(unenc);
+    tor_free(enc);
   return r;
 }
 
@@ -316,12 +430,14 @@
 int
 rend_encode_v2_descriptors(smartlist_t *descs_out,
                            rend_service_descriptor_t *desc, time_t now,
-                           crypto_pk_env_t *service_key,
-                           const char *descriptor_cookie, uint8_t period)
+                           crypto_pk_env_t *service_key, int auth_type,
+                           const char *descriptor_cookie,
+                           smartlist_t *client_cookies, uint8_t period)
 {
   char service_id[DIGEST_LEN];
   uint32_t time_period;
-  char *ipos_base64 = NULL;
+  char *ipos_base64 = NULL, *ipos = NULL, *ipos_encrypted = NULL;
+  size_t ipos_len = 0, ipos_encrypted_len = 0;
   int k;
   uint32_t seconds_valid;
   if (!desc) {
@@ -336,10 +452,45 @@
   seconds_valid = period * REND_TIME_PERIOD_V2_DESC_VALIDITY +
                   get_seconds_valid(now, service_id);
   /* Assemble, possibly encrypt, and encode introduction points. */
-  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;
+  if (smartlist_len(desc->intro_nodes) > 0) {
+    if (rend_encode_v2_intro_points(&ipos, desc) < 0) {
+      log_warn(LD_REND, "Encoding of introduction points did not succeed.");
+      return -1;
+    }
+    ipos_len = strlen(ipos);
+    if (auth_type == 1) {
+      if (rend_encrypt_v2_intro_points_auth1(&ipos_encrypted,
+                                             &ipos_encrypted_len,
+                                             ipos, client_cookies) < 0) {
+        log_warn(LD_REND, "Encrypting of introduction points did not "
+                 "succeed.");
+        tor_free(ipos);
+        return -1;
+      }
+      tor_free(ipos);
+      ipos = ipos_encrypted;
+      ipos_len = ipos_encrypted_len;
+    } else if (auth_type == 2) {
+      if (rend_encrypt_v2_intro_points_auth2(&ipos_encrypted,
+                                             &ipos_encrypted_len,
+                                             ipos, descriptor_cookie) < 0) {
+        log_warn(LD_REND, "Encrypting of introduction points did not "
+                 "succeed.");
+        tor_free(ipos);
+        return -1;
+      }
+      tor_free(ipos);
+      ipos = ipos_encrypted;
+      ipos_len = ipos_encrypted_len;
+    }
+    /* Base64-encode introduction points. */
+    ipos_base64 = tor_malloc_zero(ipos_len * 2);
+    if (base64_encode(ipos_base64, ipos_len * 2, ipos, ipos_len)<0) {
+      log_warn(LD_REND, "Could not encode introduction point string to "
+               "base64. length=%d", ipos_len);
+      tor_free(ipos);
+      return -1;
+    }
   }
   /* Encode REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS descriptors. */
   for (k = 0; k < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS; k++) {
@@ -1055,7 +1206,7 @@
  * than one we've already got; return 1 if it's novel.
  */
 int
-rend_cache_store_v2_desc_as_client(const char *desc,
+rend_cache_store_v2_desc_as_client(const char *desc, int auth_type,
                                    const char *descriptor_cookie)
 {
   /*XXXX this seems to have a bit of duplicate code with
@@ -1103,14 +1254,36 @@
   }
   /* Decode/decrypt introduction points. */
   if (intro_content) {
-    if (rend_decrypt_introduction_points(parsed, descriptor_cookie,
-                                         intro_content, intro_size) < 0) {
-      log_warn(LD_PROTOCOL,"Couldn't decode/decrypt introduction points.");
-      rend_service_descriptor_free(parsed);
+    if (auth_type && descriptor_cookie) {
+      char *ipos_decrypted;
+      size_t ipos_decrypted_size;
+      if (rend_decrypt_introduction_points(&ipos_decrypted,
+                                           &ipos_decrypted_size,
+                                           descriptor_cookie,
+                                           intro_content,
+                                           intro_size) < 0) {
+        log_warn(LD_REND, "Failed to decrypt introduction points. We are "
+                 "probably unable to parse the encoded introduction points.");
+      } else {
+        /* Replace encrypted with decrypted introduction points. */
+        log_info(LD_REND, "Successfully decrypted introduction points.");
+        tor_free(intro_content);
+        intro_content = ipos_decrypted;
+        intro_size = ipos_decrypted_size;
+      }
+    }
+    if (rend_parse_introduction_points(parsed, intro_content,
+                                       intro_size) <= 0) {
+      log_warn(LD_REND, "Failed to parse introduction points. Either the "
+               "service has published a corrupt descriptor or you have "
+               "provided invalid authorization data.");
+      if (parsed)
+        rend_service_descriptor_free(parsed);
       tor_free(intro_content);
       return -2;
     }
   } else {
+    log_info(LD_REND, "Descriptor does not contain any introduction points.");
     parsed->intro_nodes = smartlist_create();
   }
   /* We don't need the encoded/encrypted introduction points any longer. */

Modified: tor/branches/121-hs-authorization/src/or/rendservice.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/rendservice.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/rendservice.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -607,8 +607,6 @@
           strmap_free(parsed_clients, rend_authorized_client_free);
           return -1;
         }
-        desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove == signs
-                                                          and newline. */
         /* Copy client key from parsed entry or create new one if required. */
         if (parsed && parsed->client_key) {
           client->client_key = crypto_pk_dup_key(parsed->client_key);
@@ -667,7 +665,7 @@
           char extended_desc_cookie[REND_DESC_COOKIE_LEN+1];
           memcpy(extended_desc_cookie, client->descriptor_cookie,
                  REND_DESC_COOKIE_LEN);
-          extended_desc_cookie[REND_DESC_COOKIE_LEN] = (s->auth_type-1)<<4;
+          extended_desc_cookie[REND_DESC_COOKIE_LEN] = (s->auth_type - 1) << 4;
           if (base64_encode(desc_cook_out, 3*REND_DESC_COOKIE_LEN_BASE64+1,
                             extended_desc_cookie,
                             REND_DESC_COOKIE_LEN+1) < 0) {
@@ -680,6 +678,8 @@
           tor_snprintf(buf, sizeof(buf),"%s.onion %s # client: %s\n",
                        service_id, desc_cook_out, client->client_name);
         } else {
+          desc_cook_out[strlen(desc_cook_out)-3] = '\0'; /* Remove == signs
+                                                            and newline. */
           tor_snprintf(buf, sizeof(buf),"%s # client: %s\n",
             desc_cook_out, client->client_name);
         }
@@ -1539,26 +1539,36 @@
     if (c && smartlist_len(c->routerstatus_list) > 0) {
       int seconds_valid;
       smartlist_t *descs = smartlist_create();
+      smartlist_t *client_cookies = smartlist_create();
       int i, j;
       /* Either upload a single descriptors (including replicas) or one
        * descriptor for each authorized client. */
-      int num_descs = (service->clients ?
+      int num_descs = (service->auth_type == 2 ?
                        smartlist_len(service->clients) : 1);
       for (j = 0; j < num_descs; j++) {
         char *descriptor_cookie = NULL;
         crypto_pk_env_t *service_key = NULL;
-        if (service->clients) {
+        if (service->auth_type == 1) {
+          service_key = service->private_key;
+          descriptor_cookie = NULL;
+          SMARTLIST_FOREACH(service->clients, rend_authorized_client_t *, cl, {
+            smartlist_add(client_cookies, cl->descriptor_cookie);
+          });
+        } else if (service->auth_type == 2) {
           rend_authorized_client_t *client =
             smartlist_get(service->clients, j);
+          service_key = client->client_key;
           descriptor_cookie = client->descriptor_cookie;
-          service_key = client->client_key;
         } else {
           service_key = service->private_key;
+          descriptor_cookie = NULL;
         }
         /* Encode the current descriptor. */
         seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
                                                    now, service_key,
-                                                   descriptor_cookie, 0);
+                                                   service->auth_type,
+                                                   descriptor_cookie,
+                                                   client_cookies, 0);
         if (seconds_valid < 0) {
           log_warn(LD_BUG, "Internal error: couldn't encode service "
                    "descriptor; not uploading.");
@@ -1587,7 +1597,9 @@
         if (seconds_valid < REND_TIME_PERIOD_OVERLAPPING_V2_DESCS) {
           seconds_valid = rend_encode_v2_descriptors(descs, service->desc,
                                                      now, service_key,
-                                                     descriptor_cookie, 1);
+                                                     service->auth_type,
+                                                     descriptor_cookie,
+                                                     client_cookies, 1);
           if (seconds_valid < 0) {
             log_warn(LD_BUG, "Internal error: couldn't encode service "
                      "descriptor; not uploading.");

Modified: tor/branches/121-hs-authorization/src/or/routerparse.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/routerparse.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/routerparse.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -3533,21 +3533,129 @@
   return -1;
 }
 
-/** Decrypt and decode the introduction points in
- * <b>intro_points_encrypted</b> of length
- * <b>intro_points_encrypted_size</b> using <b>descriptor_cookie</b>
- * (which may also be <b>NULL</b> if no decryption, but only parsing is
- * required), parse the introduction points, and write the result to
- * <b>parsed</b>; return the number of successfully parsed introduction
- * points or -1 in case of a failure.
- */
+/** Decrypt the encoded introduction points in <b>ipos_encrypted</b> of
+ * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
+ * write the result to <b>ipos_decrypted</b> and its length to
+ * <b>ipos_decrypted_size</b>; return 0 if decryption was successful and -1
+ * otherwise. */
 int
-rend_decrypt_introduction_points(rend_service_descriptor_t *parsed,
+rend_decrypt_introduction_points(char **ipos_decrypted,
+                                 size_t *ipos_decrypted_size,
                                  const char *descriptor_cookie,
-                                 const char *intro_points_encrypted,
-                                 size_t intro_points_encrypted_size)
+                                 const char *ipos_encrypted,
+                                 size_t ipos_encrypted_size)
 {
-  char *ipos_decrypted = NULL;
+  size_t client_entries_len;
+  if (ipos_encrypted_size < 2) {
+    log_warn(LD_REND, "Size of encrypted introduction points is too "
+             "small.");
+    return -1;
+  }
+  if (ipos_encrypted[0] == 1) {
+    char iv[CIPHER_IV_LEN], client_id[4], session_key[16], *dec;
+    int declen;
+    size_t pos = 0, len;
+    crypto_digest_env_t *digest;
+    crypto_cipher_env_t *cipher;
+    log_debug(LD_REND, "Introduction points are encrypted for "
+             "authorization type 1. There are %d client blocks containing "
+             "16 client entries each.", (int) ipos_encrypted[1]);
+    client_entries_len = (int)ipos_encrypted[1] * 16 * 20;
+    if (ipos_encrypted_size < 2 + client_entries_len + 17) {
+      log_warn(LD_REND, "Size of encrypted introduction points is too "
+               "small.");
+      return -1;
+    }
+    memcpy(iv, ipos_encrypted + 2 + client_entries_len, sizeof(iv));
+    digest = crypto_new_digest_env();
+    crypto_digest_add_bytes(digest, descriptor_cookie, 16);
+    crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
+    crypto_digest_get_digest(digest, client_id, 4);
+    crypto_free_digest_env(digest);
+    log_debug(LD_REND, "Our client ID with this initialization vector "
+              "is '%s'.", hex_str(client_id, 4));
+    for (pos = 2; pos < 2 + client_entries_len; pos += 20) {
+      log_debug(LD_REND, "Comparing with client ID '%s'...",
+               hex_str(ipos_encrypted + pos, 4));
+      if (!memcmp(ipos_encrypted + pos, client_id, 4)) {
+        cipher = crypto_create_init_cipher(descriptor_cookie, 0);
+        log_debug(LD_REND, "Match found!");
+        if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
+                                  + pos + 4, 16) < 0) {
+          log_warn(LD_REND, "Could not decrypt session key for client.");
+          crypto_free_cipher_env(cipher);
+          return -1;
+        }
+        crypto_free_cipher_env(cipher);
+        log_debug(LD_REND, "Decrypted session key is '%s'",
+                  hex_str(session_key, 16));
+        /* Attempt to decrypt introduction points. */
+        cipher = crypto_create_init_cipher(session_key, 0);
+        len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
+        dec = tor_malloc_zero(len);
+        declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
+            ipos_encrypted + 2 + client_entries_len,
+            ipos_encrypted_size - 2 - client_entries_len);
+        crypto_free_cipher_env(cipher);
+        if (declen < 0) {
+          log_warn(LD_REND, "Could not decrypt introduction point string.");
+          tor_free(dec);
+          return -1;
+        }
+        log_debug(LD_REND, "Decrypted %d bytes, resulting in "
+                  "(hopefully a string) '%s'.",
+                  declen, dec);
+        if (strcmpstart(dec, "introduction-point ")) {
+          log_warn(LD_REND, "Decrypted introduction points don't "
+                            "look like we could parse them.");
+          continue;
+        }
+        log_debug(LD_REND, "Decrypted introduction points look good.");
+        *ipos_decrypted = dec;
+        *ipos_decrypted_size = declen;
+        return 0;
+      }
+    }
+    log_warn(LD_REND, "Could not decrypt introduction points. Please "
+             "check your authorization for this service!");
+    return -1;
+  } else if (ipos_encrypted[0] == 2) {
+    crypto_cipher_env_t *cipher;
+    char *dec;
+    int declen;
+    log_debug(LD_REND, "Introduction points are encrypted for "
+                       "authorization type 2.");
+    dec = tor_malloc_zero(ipos_encrypted_size - 16);
+    cipher = crypto_create_init_cipher(descriptor_cookie, 0);
+    declen = crypto_cipher_decrypt_with_iv(cipher, dec,
+                                           ipos_encrypted_size - 16,
+                                           ipos_encrypted,
+                                           ipos_encrypted_size);
+    crypto_free_cipher_env(cipher);
+    if (declen < 0) {
+      log_warn(LD_REND, "Decrypting introduction points failed!");
+      tor_free(ipos_decrypted);
+      return -1;
+    }
+    *ipos_decrypted = dec;
+    *ipos_decrypted_size = declen;
+    return 0;
+  } else {
+    log_warn(LD_REND, "Unknown authorization type: %d", ipos_encrypted[0]);
+    return -1;
+  }
+}
+
+/** Parse the encoded introduction points in <b>ipos_encoded</b> of length
+ * <b>ipos_encoded_size</b> and write the result to <b>parsed</b>; return
+ * the number of successfully parsed introduction points or -1 in case of a
+ * failure.
+ */
+int
+rend_parse_introduction_points(rend_service_descriptor_t *parsed,
+                               const char *ipos_encoded,
+                               size_t ipos_encoded_size)
+{
   const char **current_ipo;
   smartlist_t *tokens;
   directory_token_t *tok;
@@ -3559,29 +3667,10 @@
   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. */
-  if (descriptor_cookie) {
-    crypto_cipher_env_t *cipher;
-    int unenclen;
-    ipos_decrypted = tor_malloc_zero(intro_points_encrypted_size - 16);
-    cipher = crypto_create_init_cipher(descriptor_cookie, 0);
-    unenclen = crypto_cipher_decrypt_with_iv(cipher, ipos_decrypted,
-                                             intro_points_encrypted_size - 16,
-                                             intro_points_encrypted,
-                                             intro_points_encrypted_size);
-    crypto_free_cipher_env(cipher);
-    if (unenclen < 0) {
-      log_warn(LD_REND, "Decrypting introduction points failed!");
-      tor_free(ipos_decrypted);
-      return -1;
-    }
-    intro_points_encrypted = ipos_decrypted;
-    intro_points_encrypted_size = unenclen;
-  }
+  tor_assert(ipos_encoded);
+  tor_assert(ipos_encoded_size > 0);
   /* Consider one intro point after the other. */
-  current_ipo = &intro_points_encrypted;
+  current_ipo = &ipos_encoded;
   tokens = smartlist_create();
   parsed->intro_nodes = smartlist_create();
   area = memarea_new(4096);
@@ -3751,20 +3840,16 @@
     tok = find_first_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
     tor_assert(tok);
     tor_assert(tok->n_args == 1);
-    if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64) {
+    if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
       log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
                tok->args[0]);
       goto err;
     }
-    /* Add trailing == signs to make base64-decoding happy. */
-    tor_snprintf(descriptor_cookie_base64, REND_DESC_COOKIE_LEN_BASE64+2+1,
-                 "%s==", tok->args[0]);
     /* The size of descriptor_cookie_tmp needs to REND_DESC_COOKIE_LEN+2,
      * because a base64 of length 24 does not fit into 16 bytes in all
      * cases. */
     if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
-                       descriptor_cookie_base64,
-                       REND_DESC_COOKIE_LEN_BASE64+2+1)
+                       tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
            != REND_DESC_COOKIE_LEN)) {
       log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
                         "%s", descriptor_cookie_base64);

Modified: tor/branches/121-hs-authorization/src/or/test.c
===================================================================
--- tor/branches/121-hs-authorization/src/or/test.c	2008-08-04 10:27:05 UTC (rev 16379)
+++ tor/branches/121-hs-authorization/src/or/test.c	2008-08-04 12:40:07 UTC (rev 16380)
@@ -3846,7 +3846,8 @@
     smartlist_add(generated->intro_nodes, intro);
   }
   test_assert(rend_encode_v2_descriptors(descs, generated, now,
-                                         generated->pk, NULL, 0) > 0);
+                                         generated->pk, 0, NULL, NULL,
+                                         0) > 0);
   test_assert(rend_compute_v2_desc_id(computed_desc_id, service_id_base32,
                                       NULL, now, 0) == 0);
   test_memeq(((rend_encoded_v2_service_descriptor_t *)
@@ -3861,9 +3862,8 @@
   test_assert(parsed);
   test_memeq(((rend_encoded_v2_service_descriptor_t *)
              smartlist_get(descs, 0))->desc_id, parsed_desc_id, DIGEST_LEN);
-  test_assert(rend_decrypt_introduction_points(parsed, NULL,
-                                               intro_points_encrypted,
-                                               intro_points_size) == 3);
+  test_assert(rend_parse_introduction_points(parsed, intro_points_encrypted,
+                                             intro_points_size) == 3);
   test_assert(!crypto_pk_cmp_keys(generated->pk, parsed->pk));
   test_eq(parsed->timestamp, now);
   test_eq(parsed->version, 2);



More information about the tor-commits mailing list