[tor-commits] [tor/master] prop224: Support legacy INTRODUCE2 cell

nickm at torproject.org nickm at torproject.org
Wed Aug 9 00:36:37 UTC 2017


commit 100386e659533cfa92c5bfff93a15fb3535f7970
Author: David Goulet <dgoulet at torproject.org>
Date:   Wed Apr 5 12:26:02 2017 -0400

    prop224: Support legacy INTRODUCE2 cell
    
    Also rename some function to follow a bit more the naming convention in that
    file.
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/hs_cell.c     | 119 ++++++++++++++++++++++++++++++++++++++++++++++-----
 src/or/hs_cell.h     |   2 +
 src/or/hs_circuit.c  |   2 +
 src/or/hs_service.c  |   4 +-
 src/or/rendservice.h |   4 +-
 5 files changed, 116 insertions(+), 15 deletions(-)

diff --git a/src/or/hs_cell.c b/src/or/hs_cell.c
index 68c201b89..9ab83525d 100644
--- a/src/or/hs_cell.c
+++ b/src/or/hs_cell.c
@@ -207,6 +207,105 @@ build_legacy_establish_intro(const char *circ_nonce, crypto_pk_t *enc_key,
   return cell_len;
 }
 
+/* Free the given cell pointer. If is_legacy_cell is set, cell_ptr is cast to
+ * a rend_intro_cell_t else to a trn_cell_introduce1_t. */
+static void
+introduce2_free_cell(void *cell_ptr, unsigned int is_legacy_cell)
+{
+  if (cell_ptr == NULL) {
+    return;
+  }
+  if (is_legacy_cell) {
+    rend_intro_cell_t *legacy_cell = cell_ptr;
+    rend_service_free_intro(legacy_cell);
+  } else {
+    trn_cell_introduce1_free((trn_cell_introduce1_t *) cell_ptr);
+  }
+}
+
+/* Return the length of the encrypted section of the cell_ptr. If
+ * is_legacy_cell is set, cell_ptr is cast to a rend_intro_cell_t else to a
+ * trn_cell_introduce1_t. */
+static size_t
+get_introduce2_encrypted_section_len(const void *cell_ptr,
+                                     unsigned int is_legacy_cell)
+{
+  tor_assert(cell_ptr);
+  if (is_legacy_cell) {
+    return ((const rend_intro_cell_t *) cell_ptr)->ciphertext_len;
+  }
+  return trn_cell_introduce1_getlen_encrypted(
+                             (const trn_cell_introduce1_t *) cell_ptr);
+}
+
+/* Return the encrypted section pointer from the the cell_ptr. If
+ * is_legacy_cell is set, cell_ptr is cast to a rend_intro_cell_t else to a
+ * trn_cell_introduce1_t. */
+static const uint8_t *
+get_introduce2_encrypted_section(const void *cell_ptr,
+                                 unsigned int is_legacy_cell)
+{
+  tor_assert(cell_ptr);
+  if (is_legacy_cell) {
+    return ((const rend_intro_cell_t *) cell_ptr)->ciphertext;
+  }
+  return trn_cell_introduce1_getconstarray_encrypted(
+                             (const trn_cell_introduce1_t *) cell_ptr);
+}
+
+/* Parse an INTRODUCE2 cell from payload of size payload_len for the given
+ * service and circuit which are used only for logging purposes. The resulting
+ * parsed cell is put in cell_ptr_out. If is_legacy_cell is set, the type of
+ * the returned cell is rend_intro_cell_t else trn_cell_introduce1_t.
+ *
+ * Return 0 on success else a negative value and cell_ptr_out is untouched. */
+static int
+parse_introduce2_cell(const hs_service_t *service,
+                      const origin_circuit_t *circ, const uint8_t *payload,
+                      size_t payload_len, unsigned int is_legacy_cell,
+                      void **cell_ptr_out)
+{
+  tor_assert(service);
+  tor_assert(circ);
+  tor_assert(payload);
+  tor_assert(cell_ptr_out);
+
+  /* We parse the cell differently for legacy. */
+  if (is_legacy_cell) {
+    char *err_msg;
+    rend_intro_cell_t *legacy_cell = NULL;
+
+    legacy_cell = rend_service_begin_parse_intro(payload, payload_len, 2,
+                                                 &err_msg);
+    if (legacy_cell == NULL) {
+      log_info(LD_REND, "Unable to parse legacy INTRODUCE2 cell on "
+                        "circuit %u for service %s: %s",
+               TO_CIRCUIT(circ)->n_circ_id, err_msg,
+               safe_str_client(service->onion_address));
+      tor_free(err_msg);
+      goto err;
+    }
+    *cell_ptr_out = legacy_cell;
+  } else {
+    trn_cell_introduce1_t *cell = NULL;
+    /* Parse the cell so we can start cell validation. */
+    if (trn_cell_introduce1_parse(&cell, payload, payload_len) < 0) {
+      log_info(LD_PROTOCOL, "Unable to parse INTRODUCE2 cell on circuit %u "
+                            "for service %s",
+               TO_CIRCUIT(circ)->n_circ_id,
+               safe_str_client(service->onion_address));
+      goto err;
+    }
+    *cell_ptr_out = cell;
+  }
+
+  /* On success, we must have set the cell pointer. */
+  tor_assert(*cell_ptr_out);
+  return 0;
+ err:
+  return -1;
+}
+
 /* ========== */
 /* Public API */
 /* ========== */
@@ -364,21 +463,17 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
   uint8_t *decrypted = NULL;
   size_t encrypted_section_len;
   const uint8_t *encrypted_section;
-  trn_cell_introduce1_t *cell = NULL;
   trn_cell_introduce_encrypted_t *enc_cell = NULL;
   hs_ntor_intro_cell_keys_t *intro_keys = NULL;
+  void *cell_ptr = NULL;
 
   tor_assert(data);
   tor_assert(circ);
   tor_assert(service);
 
-  /* Parse the cell so we can start cell validation. */
-  if (trn_cell_introduce1_parse(&cell, data->payload,
-                                data->payload_len) < 0) {
-    log_info(LD_PROTOCOL, "Unable to parse INTRODUCE2 cell on circuit %u "
-                          "for service %s",
-             TO_CIRCUIT(circ)->n_circ_id,
-             safe_str_client(service->onion_address));
+  /* Parse the cell into a decoded data structure pointed by cell_ptr. */
+  if (parse_introduce2_cell(service, circ, data->payload, data->payload_len,
+                            data->is_legacy, &cell_ptr) < 0) {
     goto done;
   }
 
@@ -389,8 +484,10 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
            TO_CIRCUIT(circ)->n_circ_id,
            safe_str_client(service->onion_address));
 
-  encrypted_section = trn_cell_introduce1_getconstarray_encrypted(cell);
-  encrypted_section_len = trn_cell_introduce1_getlen_encrypted(cell);
+  encrypted_section =
+    get_introduce2_encrypted_section(cell_ptr, data->is_legacy);
+  encrypted_section_len =
+    get_introduce2_encrypted_section_len(cell_ptr, data->is_legacy);
 
   /* Encrypted section must at least contain the CLIENT_PK and MAC which is
    * defined in section 3.3.2 of the specification. */
@@ -496,8 +593,8 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
     tor_free(intro_keys);
   }
   tor_free(decrypted);
-  trn_cell_introduce1_free(cell);
   trn_cell_introduce_encrypted_free(enc_cell);
+  introduce2_free_cell(cell_ptr, data->is_legacy);
   return ret;
 }
 
diff --git a/src/or/hs_cell.h b/src/or/hs_cell.h
index fb4950d51..611418243 100644
--- a/src/or/hs_cell.h
+++ b/src/or/hs_cell.h
@@ -34,6 +34,8 @@ typedef struct hs_cell_introduce2_data_t {
   const uint8_t *payload;
   /* Size of the payload of the received encoded cell. */
   size_t payload_len;
+  /* Is this a legacy introduction point? */
+  unsigned int is_legacy : 1;
 
   /*** Muttable Section. ***/
 
diff --git a/src/or/hs_circuit.c b/src/or/hs_circuit.c
index 22a2c3347..543cbac6d 100644
--- a/src/or/hs_circuit.c
+++ b/src/or/hs_circuit.c
@@ -13,6 +13,7 @@
 #include "config.h"
 #include "policies.h"
 #include "relay.h"
+#include "rendservice.h"
 #include "rephist.h"
 #include "router.h"
 
@@ -809,6 +810,7 @@ hs_circ_handle_introduce2(const hs_service_t *service,
   data.payload = payload;
   data.payload_len = payload_len;
   data.link_specifiers = smartlist_new();
+  data.is_legacy = ip->base.is_only_legacy;
 
   if (hs_cell_parse_introduce2(&data, circ, service) < 0) {
     goto done;
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index a2ab0629a..48724e45c 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -1914,8 +1914,8 @@ service_handle_introduce2(origin_circuit_t *circ, const uint8_t *payload,
   /* If we have an IP object, we MUST have a descriptor object. */
   tor_assert(desc);
 
-  /* XXX: Handle legacy IP connection. */
-
+  /* The following will parse, decode and launch the rendezvous point circuit.
+   * Both current and legacy cells are handled. */
   if (hs_circ_handle_introduce2(service, circ, ip, desc->desc->subcredential,
                                 payload, payload_len) < 0) {
     goto err;
diff --git a/src/or/rendservice.h b/src/or/rendservice.h
index a6d6ec6a4..819dfc176 100644
--- a/src/or/rendservice.h
+++ b/src/or/rendservice.h
@@ -17,8 +17,6 @@
 
 typedef struct rend_intro_cell_s rend_intro_cell_t;
 
-#ifdef RENDSERVICE_PRIVATE
-
 /* This can be used for both INTRODUCE1 and INTRODUCE2 */
 
 struct rend_intro_cell_s {
@@ -63,6 +61,8 @@ struct rend_intro_cell_s {
   uint8_t dh[DH_KEY_LEN];
 };
 
+#ifdef RENDSERVICE_PRIVATE
+
 /** Represents a single hidden service running at this OP. */
 typedef struct rend_service_t {
   /* Fields specified in config file */





More information about the tor-commits mailing list