Ver código fonte

Merge branch 'bug15880_027_03'

Nick Mathewson 9 anos atrás
pai
commit
d05d21c89a
9 arquivos alterados com 144 adições e 42 exclusões
  1. 3 0
      changes/bug15881
  2. 71 16
      src/or/control.c
  3. 3 4
      src/or/control.h
  4. 2 3
      src/or/directory.c
  5. 4 0
      src/or/or.h
  6. 7 0
      src/or/rendclient.c
  7. 8 1
      src/or/rendcommon.c
  8. 6 0
      src/or/rendcommon.h
  9. 40 18
      src/test/test_hs.c

+ 3 - 0
changes/bug15881

@@ -0,0 +1,3 @@
+  o Controller fixes:
+    - Add the descriptor ID in each HS_DESC control event. It was missing
+      but specified in control-spec.txt. Fixes ticket 15881.

+ 71 - 16
src/or/control.c

@@ -5904,6 +5904,44 @@ control_event_hs_descriptor_requested(const rend_data_t *rend_query,
                      desc_id_base32);
 }
 
+/** For an HS descriptor query <b>rend_data</b>, using the
+ * <b>onion_address</b> and HSDir fingerprint <b>hsdir_fp</b>, find out
+ * which descriptor ID in the query is the right one.
+ *
+ * Return a pointer of the binary descriptor ID found in the query's object
+ * or NULL if not found. */
+static const char *
+get_desc_id_from_query(const rend_data_t *rend_data, const char *hsdir_fp)
+{
+  int replica;
+  const char *desc_id = NULL;
+
+  /* Possible if the fetch was done using a descriptor ID. This means that
+   * the HSFETCH command was used. */
+  if (!tor_digest_is_zero(rend_data->desc_id_fetch)) {
+    desc_id = rend_data->desc_id_fetch;
+    goto end;
+  }
+
+  /* OK, we have an onion address so now let's find which descriptor ID
+   * is the one associated with the HSDir fingerprint. */
+  for (replica = 0; replica < REND_NUMBER_OF_NON_CONSECUTIVE_REPLICAS;
+       replica++) {
+    const char *digest = rend_data->descriptor_id[replica];
+
+    SMARTLIST_FOREACH_BEGIN(rend_data->hsdirs_fp, char *, fingerprint) {
+      if (tor_memcmp(fingerprint, hsdir_fp, DIGEST_LEN) == 0) {
+        /* Found it! This descriptor ID is the right one. */
+        desc_id = digest;
+        goto end;
+      }
+    } SMARTLIST_FOREACH_END(fingerprint);
+  }
+
+end:
+  return desc_id;
+}
+
 /** send HS_DESC upload event.
  *
  * <b>service_id</b> is the descriptor onion address.
@@ -5940,30 +5978,45 @@ control_event_hs_descriptor_upload(const char *service_id,
 void
 control_event_hs_descriptor_receive_end(const char *action,
                                         const char *onion_address,
-                                        rend_auth_type_t auth_type,
+                                        const rend_data_t *rend_data,
                                         const char *id_digest,
                                         const char *reason)
 {
+  char *desc_id_field = NULL;
   char *reason_field = NULL;
+  char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
+  const char *desc_id = NULL;
 
-  if (!action || !id_digest || !onion_address) {
-    log_warn(LD_BUG, "Called with action==%p, id_digest==%p "
-             "onion_address==%p", action, id_digest, onion_address);
+  if (!action || !id_digest || !rend_data || !onion_address) {
+    log_warn(LD_BUG, "Called with action==%p, id_digest==%p, "
+             "rend_data==%p, onion_address==%p", action, id_digest,
+             rend_data, onion_address);
     return;
   }
 
+  desc_id = get_desc_id_from_query(rend_data, id_digest);
+  if (desc_id != NULL) {
+    /* Set the descriptor ID digest to base32 so we can send it. */
+    base32_encode(desc_id_base32, sizeof(desc_id_base32), desc_id,
+                  DIGEST_LEN);
+    /* Extra whitespace is needed before the value. */
+    tor_asprintf(&desc_id_field, " %s", desc_id_base32);
+  }
+
   if (reason) {
     tor_asprintf(&reason_field, " REASON=%s", reason);
   }
 
   send_control_event(EVENT_HS_DESC, ALL_FORMATS,
-                     "650 HS_DESC %s %s %s %s%s\r\n",
+                     "650 HS_DESC %s %s %s %s%s%s\r\n",
                      action,
                      rend_hsaddress_str_or_unknown(onion_address),
-                     rend_auth_type_to_string(auth_type),
+                     rend_auth_type_to_string(rend_data->auth_type),
                      node_describe_longname_by_id(id_digest),
+                     desc_id_field ? desc_id_field : "",
                      reason_field ? reason_field : "");
 
+  tor_free(desc_id_field);
   tor_free(reason_field);
 }
 
@@ -6007,15 +6060,16 @@ control_event_hs_descriptor_upload_end(const char *action,
  */
 void
 control_event_hs_descriptor_received(const char *onion_address,
-                                     rend_auth_type_t auth_type,
+                                     const rend_data_t *rend_data,
                                      const char *id_digest)
 {
-  if (!id_digest) {
-    log_warn(LD_BUG, "Called with id_digest==%p", id_digest);
+  if (!rend_data || !id_digest || !onion_address) {
+    log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p, "
+             "onion_address==%p", rend_data, id_digest, onion_address);
     return;
   }
   control_event_hs_descriptor_receive_end("RECEIVED", onion_address,
-                                          auth_type, id_digest, NULL);
+                                          rend_data, id_digest, NULL);
 }
 
 /** send HS_DESC UPLOADED event
@@ -6039,17 +6093,18 @@ control_event_hs_descriptor_uploaded(const char *id_digest)
  * field.
  */
 void
-control_event_hs_descriptor_failed(const char *onion_address,
-                                   rend_auth_type_t auth_type,
+control_event_hs_descriptor_failed(const rend_data_t *rend_data,
                                    const char *id_digest,
                                    const char *reason)
 {
-  if (!id_digest) {
-    log_warn(LD_BUG, "Called with id_digest==%p", id_digest);
+  if (!rend_data || !id_digest) {
+    log_warn(LD_BUG, "Called with rend_data==%p, id_digest==%p",
+             rend_data, id_digest);
     return;
   }
-  control_event_hs_descriptor_receive_end("FAILED", onion_address, auth_type,
-                                          id_digest, reason);
+  control_event_hs_descriptor_receive_end("FAILED",
+                                          rend_data->onion_address,
+                                          rend_data, id_digest, reason);
 }
 
 /** send HS_DESC_CONTENT event after completion of a successful fetch from

+ 3 - 4
src/or/control.h

@@ -111,18 +111,17 @@ void control_event_hs_descriptor_upload(const char *service_id,
                                         const char *hs_dir);
 void control_event_hs_descriptor_receive_end(const char *action,
                                              const char *onion_address,
-                                             rend_auth_type_t auth_type,
+                                             const rend_data_t *rend_data,
                                              const char *id_digest,
                                              const char *reason);
 void control_event_hs_descriptor_upload_end(const char *action,
                                             const char *hs_dir,
                                             const char *reason);
 void control_event_hs_descriptor_received(const char *onion_address,
-                                          rend_auth_type_t auth_type,
+                                          const rend_data_t *rend_data,
                                           const char *id_digest);
 void control_event_hs_descriptor_uploaded(const char *hs_dir);
-void control_event_hs_descriptor_failed(const char *onion_address,
-                                        rend_auth_type_t auth_type,
+void control_event_hs_descriptor_failed(const rend_data_t *rend_data,
                                         const char *id_digest,
                                         const char *reason);
 void control_event_hs_descriptor_upload_failed(const char *hs_dir,

+ 2 - 3
src/or/directory.c

@@ -2099,8 +2099,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
 
   if (conn->base_.purpose == DIR_PURPOSE_FETCH_RENDDESC_V2) {
     #define SEND_HS_DESC_FAILED_EVENT(reason) ( \
-      control_event_hs_descriptor_failed(conn->rend_data->onion_address, \
-                                         conn->rend_data->auth_type, \
+      control_event_hs_descriptor_failed(conn->rend_data, \
                                          conn->identity_digest, \
                                          reason) )
     #define SEND_HS_DESC_FAILED_CONTENT() ( \
@@ -2141,7 +2140,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
             log_info(LD_REND, "Successfully fetched v2 rendezvous "
                      "descriptor.");
             control_event_hs_descriptor_received(service_id,
-                                                 conn->rend_data->auth_type,
+                                                 conn->rend_data,
                                                  conn->identity_digest);
             control_event_hs_descriptor_content(service_id,
                                                 conn->requested_resource,

+ 4 - 0
src/or/or.h

@@ -814,6 +814,10 @@ typedef struct rend_data_t {
 
   /** Rendezvous cookie used by both, client and service. */
   char rend_cookie[REND_COOKIE_LEN];
+
+  /** List of HSDir fingerprints on which this request has been sent to.
+   * This contains binary identity digest of the directory. */
+  smartlist_t *hsdirs_fp;
 } rend_data_t;
 
 /** Time interval for tracking replays of DH public keys received in

+ 7 - 0
src/or/rendclient.c

@@ -686,6 +686,7 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
                           routerstatus_t *rs_hsdir)
 {
   routerstatus_t *hs_dir = rs_hsdir;
+  char *hsdir_fp;
   char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
   char descriptor_cookie_base64[3*REND_DESC_COOKIE_LEN_BASE64];
 #ifdef ENABLE_TOR2WEB_MODE
@@ -709,6 +710,12 @@ directory_get_from_hs_dir(const char *desc_id, const rend_data_t *rend_query,
     }
   }
 
+  /* Add a copy of the HSDir identity digest to the query so we can track it
+   * on the control port. */
+  hsdir_fp = tor_memdup(hs_dir->identity_digest,
+                        sizeof(hs_dir->identity_digest));
+  smartlist_add(rend_query->hsdirs_fp, hsdir_fp);
+
   /* Encode descriptor cookie for logging purposes. Also, if the cookie is
    * malformed, no fetch is triggered thus this needs to be done before the
    * fetch request. */

+ 8 - 1
src/or/rendcommon.c

@@ -1400,8 +1400,14 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
 rend_data_t *
 rend_data_dup(const rend_data_t *data)
 {
+  rend_data_t *data_dup;
   tor_assert(data);
-  return tor_memdup(data, sizeof(rend_data_t));
+  data_dup = tor_memdup(data, sizeof(rend_data_t));
+  data_dup->hsdirs_fp = smartlist_new();
+  SMARTLIST_FOREACH(data->hsdirs_fp, char *, fp,
+                    smartlist_add(data_dup->hsdirs_fp,
+                                  tor_memdup(fp, DIGEST_LEN)));
+  return data_dup;
 }
 
 /** Compute descriptor ID for each replicas and save them. A valid onion
@@ -1495,6 +1501,7 @@ rend_data_client_create(const char *onion_address, const char *desc_id,
   }
 
   rend_data->auth_type = auth_type;
+  rend_data->hsdirs_fp = smartlist_new();
 
   return rend_data;
 

+ 6 - 0
src/or/rendcommon.h

@@ -16,6 +16,12 @@
 static INLINE void
 rend_data_free(rend_data_t *data)
 {
+  if (!data) {
+    return;
+  }
+  /* Cleanup the HSDir identity digest. */
+  SMARTLIST_FOREACH(data->hsdirs_fp, char *, d, tor_free(d));
+  smartlist_free(data->hsdirs_fp);
   tor_free(data);
 }
 

+ 40 - 18
src/test/test_hs.c

@@ -13,6 +13,7 @@
 #include "test.h"
 #include "control.h"
 #include "config.h"
+#include "rendcommon.h"
 #include "routerset.h"
 #include "circuitbuild.h"
 #include "test_helpers.h"
@@ -131,11 +132,13 @@ static void
 test_hs_desc_event(void *arg)
 {
   #define STR_HS_ADDR "ajhb7kljbiru65qo"
-  #define STR_HS_ID "b3oeducbhjmbqmgw2i3jtz4fekkrinwj"
-  #define STR_DESC_ID "g5ojobzupf275beh5ra72uyhb3dkpxwg"
+  #define STR_HS_CONTENT_DESC_ID "g5ojobzupf275beh5ra72uyhb3dkpxwg"
+  #define STR_DESC_ID_BASE32 "hba3gmcgpfivzfhx5rtfqkfdhv65yrj3"
 
+  int ret;
   rend_data_t rend_query;
   const char *expected_msg;
+  char desc_id_base32[REND_DESC_ID_V2_LEN_BASE32 + 1];
 
   (void) arg;
   MOCK(send_control_event_string,
@@ -144,33 +147,48 @@ test_hs_desc_event(void *arg)
        node_describe_longname_by_id_replacement);
 
   /* setup rend_query struct */
+  memset(&rend_query, 0, sizeof(rend_query));
   strncpy(rend_query.onion_address, STR_HS_ADDR,
           REND_SERVICE_ID_LEN_BASE32+1);
-  rend_query.auth_type = 0;
+  rend_query.auth_type = REND_NO_AUTH;
+  rend_query.hsdirs_fp = smartlist_new();
+  smartlist_add(rend_query.hsdirs_fp, tor_memdup(HSDIR_EXIST_ID,
+                                                 DIGEST_LEN));
+
+  /* Compute descriptor ID for replica 0, should be STR_DESC_ID_BASE32. */
+  ret = rend_compute_v2_desc_id(rend_query.descriptor_id[0],
+                                rend_query.onion_address,
+                                NULL, 0, 0);
+  tt_int_op(ret, ==, 0);
+  base32_encode(desc_id_base32, sizeof(desc_id_base32),
+                rend_query.descriptor_id[0], DIGEST_LEN);
+  /* Make sure rend_compute_v2_desc_id works properly. */
+  tt_mem_op(desc_id_base32, OP_EQ, STR_DESC_ID_BASE32,
+            sizeof(desc_id_base32));
 
   /* test request event */
   control_event_hs_descriptor_requested(&rend_query, HSDIR_EXIST_ID,
-                                        STR_HS_ID);
+                                        STR_DESC_ID_BASE32);
   expected_msg = "650 HS_DESC REQUESTED "STR_HS_ADDR" NO_AUTH "\
-                  STR_HSDIR_EXIST_LONGNAME" "STR_HS_ID"\r\n";
+                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32 "\r\n";
   tt_assert(received_msg);
   tt_str_op(received_msg,OP_EQ, expected_msg);
   tor_free(received_msg);
 
   /* test received event */
-  rend_query.auth_type = 1;
+  rend_query.auth_type = REND_BASIC_AUTH;
   control_event_hs_descriptor_received(rend_query.onion_address,
-                                       rend_query.auth_type, HSDIR_EXIST_ID);
+                                       &rend_query, HSDIR_EXIST_ID);
   expected_msg = "650 HS_DESC RECEIVED "STR_HS_ADDR" BASIC_AUTH "\
-                  STR_HSDIR_EXIST_LONGNAME"\r\n";
+                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32"\r\n";
   tt_assert(received_msg);
   tt_str_op(received_msg,OP_EQ, expected_msg);
   tor_free(received_msg);
 
   /* test failed event */
-  rend_query.auth_type = 2;
-  control_event_hs_descriptor_failed(rend_query.onion_address,
-                                     rend_query.auth_type, HSDIR_NONE_EXIST_ID,
+  rend_query.auth_type = REND_STEALTH_AUTH;
+  control_event_hs_descriptor_failed(&rend_query,
+                                     HSDIR_NONE_EXIST_ID,
                                      "QUERY_REJECTED");
   expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" STEALTH_AUTH "\
                   STR_HSDIR_NONE_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n";
@@ -180,26 +198,30 @@ test_hs_desc_event(void *arg)
 
   /* test invalid auth type */
   rend_query.auth_type = 999;
-  control_event_hs_descriptor_failed(rend_query.onion_address,
-                                     rend_query.auth_type, HSDIR_EXIST_ID,
+  control_event_hs_descriptor_failed(&rend_query,
+                                     HSDIR_EXIST_ID,
                                      "QUERY_REJECTED");
   expected_msg = "650 HS_DESC FAILED "STR_HS_ADDR" UNKNOWN "\
-                  STR_HSDIR_EXIST_LONGNAME" REASON=QUERY_REJECTED\r\n";
+                  STR_HSDIR_EXIST_LONGNAME " " STR_DESC_ID_BASE32\
+                  " REASON=QUERY_REJECTED\r\n";
   tt_assert(received_msg);
   tt_str_op(received_msg,OP_EQ, expected_msg);
   tor_free(received_msg);
 
   /* test valid content. */
   char *exp_msg;
-  control_event_hs_descriptor_content(rend_query.onion_address, STR_DESC_ID,
+  control_event_hs_descriptor_content(rend_query.onion_address, STR_HS_CONTENT_DESC_ID,
                                       HSDIR_EXIST_ID, hs_desc_content);
-  tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " " STR_DESC_ID \
-               " " STR_HSDIR_EXIST_LONGNAME "\r\n%s\r\n.\r\n650 OK\r\n",
-               hs_desc_content);
+  tor_asprintf(&exp_msg, "650+HS_DESC_CONTENT " STR_HS_ADDR " "\
+               STR_HS_CONTENT_DESC_ID " " STR_HSDIR_EXIST_LONGNAME\
+               "\r\n%s\r\n.\r\n650 OK\r\n", hs_desc_content);
+
   tt_assert(received_msg);
   tt_str_op(received_msg, OP_EQ, exp_msg);
   tor_free(received_msg);
   tor_free(exp_msg);
+  SMARTLIST_FOREACH(rend_query.hsdirs_fp, char *, d, tor_free(d));
+  smartlist_free(rend_query.hsdirs_fp);
 
  done:
   UNMOCK(send_control_event_string);