Browse Source

Control: add HS_DESC_CONTENT event

As defined in section 4.1.26 in the control-spec.txt, this new event replies
the content of a successfully fetched HS descriptor. This also adds a unit
test for the controller event.

Signed-off-by: David Goulet <dgoulet@ev0ke.net>
David Goulet 9 years ago
parent
commit
7db58445fd
4 changed files with 124 additions and 1 deletions
  1. 31 0
      src/or/control.c
  2. 6 1
      src/or/control.h
  3. 13 0
      src/or/directory.c
  4. 74 0
      src/test/test_hs.c

+ 31 - 0
src/or/control.c

@@ -943,6 +943,7 @@ static const struct control_event_t control_event_table[] = {
   { EVENT_CIRC_BANDWIDTH_USED, "CIRC_BW" },
   { EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" },
   { EVENT_HS_DESC, "HS_DESC" },
+  { EVENT_HS_DESC_CONTENT, "HS_DESC_CONTENT" },
   { 0, NULL },
 };
 
@@ -5414,6 +5415,36 @@ control_event_hs_descriptor_failed(const rend_data_t *rend_query,
                                           id_digest, reason);
 }
 
+/** send HS_DESC_CONTENT event after completion of a successful fetch from
+ * hs directory. */
+void
+control_event_hs_descriptor_content(const char *onion_address,
+                                    const char *desc_id,
+                                    const char *hsdir_id_digest,
+                                    const char *content)
+{
+  static const char *event_name = "HS_DESC_CONTENT";
+  char *esc_content = NULL;
+
+  if (!onion_address || !desc_id || !hsdir_id_digest || !content) {
+    log_warn(LD_BUG, "Called with onion_address==%p, desc_id==%p, "
+             "hsdir_id_digest==%p, content==%p", onion_address, desc_id,
+             hsdir_id_digest, content);
+    return;
+  }
+
+  write_escaped_data(content, strlen(content), &esc_content);
+
+  send_control_event(EVENT_HS_DESC_CONTENT, ALL_FORMATS,
+                     "650 %s %s %s %s\r\n%s",
+                     event_name,
+                     onion_address,
+                     desc_id,
+                     node_describe_longname_by_id(hsdir_id_digest),
+                     esc_content);
+  tor_free(esc_content);
+}
+
 /** Free any leftover allocated memory of the control.c subsystem. */
 void
 control_free_all(void)

+ 6 - 1
src/or/control.h

@@ -115,6 +115,10 @@ void control_event_hs_descriptor_received(const rend_data_t *rend_query,
 void control_event_hs_descriptor_failed(const rend_data_t *rend_query,
                                         const char *hs_dir,
                                         const char *reason);
+void control_event_hs_descriptor_content(const char *onion_address,
+                                         const char *desc_id,
+                                         const char *hsdir_fp,
+                                         const char *content);
 
 void control_free_all(void);
 
@@ -158,7 +162,8 @@ void control_free_all(void);
 #define EVENT_CIRC_BANDWIDTH_USED     0x001D
 #define EVENT_TRANSPORT_LAUNCHED      0x0020
 #define EVENT_HS_DESC                 0x0021
-#define EVENT_MAX_                    0x0021
+#define EVENT_HS_DESC_CONTENT         0x0022
+#define EVENT_MAX_                    0x0022
 
 /* sizeof(control_connection_t.event_mask) in bits, currently a uint64_t */
 #define EVENT_CAPACITY_               0x0040

+ 13 - 0
src/or/directory.c

@@ -2102,6 +2102,11 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
       control_event_hs_descriptor_failed(conn->rend_data, \
                                          conn->identity_digest, \
                                          reason) )
+    #define SEND_HS_DESC_FAILED_CONTENT() ( \
+      control_event_hs_descriptor_content(conn->rend_data->onion_address, \
+                                          conn->requested_resource, \
+                                          conn->identity_digest, \
+                                          "") )
     tor_assert(conn->rend_data);
     log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
              "(%s))",
@@ -2117,6 +2122,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
             /* We'll retry when connection_about_to_close_connection()
              * cleans this dir conn up. */
             SEND_HS_DESC_FAILED_EVENT("BAD_DESC");
+            SEND_HS_DESC_FAILED_CONTENT();
             break;
           case RCS_OKAY:
           default:
@@ -2125,6 +2131,10 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
                      "descriptor.");
             control_event_hs_descriptor_received(conn->rend_data,
                                                  conn->identity_digest);
+            control_event_hs_descriptor_content(conn->rend_data->onion_address,
+                                                conn->requested_resource,
+                                                conn->identity_digest,
+                                                body);
             conn->base_.purpose = DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2;
             rend_client_desc_trynow(conn->rend_data->onion_address);
             break;
@@ -2136,6 +2146,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
         log_info(LD_REND,"Fetching v2 rendezvous descriptor failed: "
                          "Retrying at another directory.");
         SEND_HS_DESC_FAILED_EVENT("NOT_FOUND");
+        SEND_HS_DESC_FAILED_CONTENT();
         break;
       case 400:
         log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
@@ -2143,6 +2154,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
                  "v2 rendezvous query? Retrying at another directory.",
                  escaped(reason));
         SEND_HS_DESC_FAILED_EVENT("QUERY_REJECTED");
+        SEND_HS_DESC_FAILED_CONTENT();
         break;
       default:
         log_warn(LD_REND, "Fetching v2 rendezvous descriptor failed: "
@@ -2152,6 +2164,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
                  status_code, escaped(reason), conn->base_.address,
                  conn->base_.port);
         SEND_HS_DESC_FAILED_EVENT("UNEXPECTED");
+        SEND_HS_DESC_FAILED_CONTENT();
         break;
     }
   }

+ 74 - 0
src/test/test_hs.c

@@ -28,6 +28,68 @@
 #define STR_HSDIR_NONE_EXIST_LONGNAME \
                        "$BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
 
+/* DuckDuckGo descriptor as an example. */
+static const char *hs_desc_content = "\
+rendezvous-service-descriptor g5ojobzupf275beh5ra72uyhb3dkpxwg\r\n\
+version 2\r\n\
+permanent-key\r\n\
+-----BEGIN RSA PUBLIC KEY-----\r\n\
+MIGJAoGBAJ/SzzgrXPxTlFrKVhXh3buCWv2QfcNgncUpDpKouLn3AtPH5Ocys0jE\r\n\
+aZSKdvaiQ62md2gOwj4x61cFNdi05tdQjS+2thHKEm/KsB9BGLSLBNJYY356bupg\r\n\
+I5gQozM65ENelfxYlysBjJ52xSDBd8C4f/p9umdzaaaCmzXG/nhzAgMBAAE=\r\n\
+-----END RSA PUBLIC KEY-----\r\n\
+secret-id-part anmjoxxwiupreyajjt5yasimfmwcnxlf\r\n\
+publication-time 2015-03-11 19:00:00\r\n\
+protocol-versions 2,3\r\n\
+introduction-points\r\n\
+-----BEGIN MESSAGE-----\r\n\
+aW50cm9kdWN0aW9uLXBvaW50IDd1bnd4cmg2dG5kNGh6eWt1Z3EzaGZzdHduc2ll\r\n\
+cmhyCmlwLWFkZHJlc3MgMTg4LjEzOC4xMjEuMTE4Cm9uaW9uLXBvcnQgOTAwMQpv\r\n\
+bmlvbi1rZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dC\r\n\
+QUxGRVVyeVpDbk9ROEhURmV5cDVjMTRObWVqL1BhekFLTTBxRENTNElKUWh0Y3g1\r\n\
+NXpRSFdOVWIKQ2hHZ0JqR1RjV3ZGRnA0N3FkdGF6WUZhVXE2c0lQKzVqeWZ5b0Q4\r\n\
+UmJ1bzBwQmFWclJjMmNhYUptWWM0RDh6Vgpuby9sZnhzOVVaQnZ1cWY4eHIrMDB2\r\n\
+S0JJNmFSMlA2OE1WeDhrMExqcUpUU2RKOE9idm9yQWdNQkFBRT0KLS0tLS1FTkQg\r\n\
+UlNBIFBVQkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQ\r\n\
+VUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTnJHb0ozeTlHNXQzN2F2ekI1cTlwN1hG\r\n\
+VUplRUVYMUNOaExnWmJXWGJhVk5OcXpoZFhyL0xTUQppM1Z6dW5OaUs3cndUVnE2\r\n\
+K2QyZ1lRckhMMmIvMXBBY3ZKWjJiNSs0bTRRc0NibFpjRENXTktRbHJnRWN5WXRJ\r\n\
+CkdscXJTbFFEaXA0ZnNrUFMvNDVkWTI0QmJsQ3NGU1k3RzVLVkxJck4zZFpGbmJr\r\n\
+NEZIS1hBZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJv\r\n\
+ZHVjdGlvbi1wb2ludCBiNGM3enlxNXNheGZzN2prNXFibG1wN3I1b3pwdHRvagpp\r\n\
+cC1hZGRyZXNzIDEwOS4xNjkuNDUuMjI2Cm9uaW9uLXBvcnQgOTAwMQpvbmlvbi1r\r\n\
+ZXkKLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1JR0pBb0dCQU8xSXpw\r\n\
+WFFUTUY3RXZUb1NEUXpzVnZiRVFRQUQrcGZ6NzczMVRXZzVaUEJZY1EyUkRaeVp4\r\n\
+OEQKNUVQSU1FeUE1RE83cGd0ak5LaXJvYXJGMC8yempjMkRXTUlSaXZyU29YUWVZ\r\n\
+ZXlMM1pzKzFIajJhMDlCdkYxZAp6MEswblRFdVhoNVR5V3lyMHdsbGI1SFBnTlI0\r\n\
+MS9oYkprZzkwZitPVCtIeGhKL1duUml2QWdNQkFBRT0KLS0tLS1FTkQgUlNBIFBV\r\n\
+QkxJQyBLRVktLS0tLQpzZXJ2aWNlLWtleQotLS0tLUJFR0lOIFJTQSBQVUJMSUMg\r\n\
+S0VZLS0tLS0KTUlHSkFvR0JBSzNWZEJ2ajFtQllLL3JrcHNwcm9Ub0llNUtHVmth\r\n\
+QkxvMW1tK1I2YUVJek1VZFE1SjkwNGtyRwpCd3k5NC8rV0lGNFpGYXh5Z2phejl1\r\n\
+N2pKY1k3ZGJhd1pFeG1hYXFCRlRwL2h2ZG9rcHQ4a1ByRVk4OTJPRHJ1CmJORUox\r\n\
+N1FPSmVMTVZZZk5Kcjl4TWZCQ3JQai8zOGh2RUdrbWVRNmRVWElvbVFNaUJGOVRB\r\n\
+Z01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0tLS0tCmludHJvZHVjdGlv\r\n\
+bi1wb2ludCBhdjVtcWl0Y2Q3cjJkandsYmN0c2Jlc2R3eGt0ZWtvegppcC1hZGRy\r\n\
+ZXNzIDE0NC43Ni44LjczCm9uaW9uLXBvcnQgNDQzCm9uaW9uLWtleQotLS0tLUJF\r\n\
+R0lOIFJTQSBQVUJMSUMgS0VZLS0tLS0KTUlHSkFvR0JBTzVweVZzQmpZQmNmMXBE\r\n\
+dklHUlpmWXUzQ05nNldka0ZLMGlvdTBXTGZtejZRVDN0NWhzd3cyVwpjejlHMXhx\r\n\
+MmN0Nkd6VWkrNnVkTDlITTRVOUdHTi9BbW8wRG9GV1hKWHpBQkFXd2YyMVdsd1lW\r\n\
+eFJQMHRydi9WCkN6UDkzcHc5OG5vSmdGUGRUZ05iMjdKYmVUZENLVFBrTEtscXFt\r\n\
+b3NveUN2RitRa25vUS9BZ01CQUFFPQotLS0tLUVORCBSU0EgUFVCTElDIEtFWS0t\r\n\
+LS0tCnNlcnZpY2Uta2V5Ci0tLS0tQkVHSU4gUlNBIFBVQkxJQyBLRVktLS0tLQpN\r\n\
+SUdKQW9HQkFMVjNKSmtWN3lTNU9jc1lHMHNFYzFQOTVRclFRR3ZzbGJ6Wi9zRGxl\r\n\
+RlpKYXFSOUYvYjRUVERNClNGcFMxcU1GbldkZDgxVmRGMEdYRmN2WVpLamRJdHU2\r\n\
+SndBaTRJeEhxeXZtdTRKdUxrcXNaTEFLaXRLVkx4eGsKeERlMjlDNzRWMmJrOTRJ\r\n\
+MEgybTNKS2tzTHVwc3VxWWRVUmhOVXN0SElKZmgyZmNIalF0bEFnTUJBQUU9Ci0t\r\n\
+LS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0KCg==\r\n\
+-----END MESSAGE-----\r\n\
+signature\r\n\
+-----BEGIN SIGNATURE-----\r\n\
+d4OuCE5OLAOnRB6cQN6WyMEmg/BHem144Vec+eYgeWoKwx3MxXFplUjFxgnMlmwN\r\n\
+PcftsZf2ztN0sbNCtPgDL3d0PqvxY3iHTQAI8EbaGq/IAJUZ8U4y963dD5+Bn6JQ\r\n\
+myE3ctmh0vy5+QxSiRjmQBkuEpCyks7LvWvHYrhnmcg=\r\n\
+-----END SIGNATURE-----";
+
 /* Helper global variable for hidden service descriptor event test.
  * It's used as a pointer to dynamically created message buffer in
  * send_control_event_string_replacement function, which mocks
@@ -70,6 +132,7 @@ test_hs_desc_event(void *arg)
 {
   #define STR_HS_ADDR "ajhb7kljbiru65qo"
   #define STR_HS_ID "b3oeducbhjmbqmgw2i3jtz4fekkrinwj"
+  #define STR_DESC_ID "g5ojobzupf275beh5ra72uyhb3dkpxwg"
 
   rend_data_t rend_query;
   const char *expected_msg;
@@ -123,6 +186,17 @@ test_hs_desc_event(void *arg)
   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,
+                                      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\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);
+
  done:
   UNMOCK(send_control_event_string);
   UNMOCK(node_describe_longname_by_id);