Browse Source

prop224: Add test for parsing RENDEZVOUS1 cell.

Just making sure that added padding does not screw up cell parsing.
George Kadianakis 6 years ago
parent
commit
03b3f5486a
5 changed files with 148 additions and 4 deletions
  1. 4 2
      src/or/hs_circuit.c
  2. 10 0
      src/or/hs_circuit.h
  3. 1 1
      src/or/hs_client.c
  4. 3 0
      src/or/hs_client.h
  5. 130 1
      src/test/test_hs_service.c

+ 4 - 2
src/or/hs_circuit.c

@@ -5,6 +5,8 @@
  * \file hs_circuit.c
  **/
 
+#define HS_CIRCUIT_PRIVATE
+
 #include "or.h"
 #include "circpathbias.h"
 #include "circuitbuild.h"
@@ -18,10 +20,10 @@
 #include "router.h"
 
 #include "hs_cell.h"
-#include "hs_circuit.h"
 #include "hs_ident.h"
 #include "hs_ntor.h"
 #include "hs_service.h"
+#include "hs_circuit.h"
 
 /* Trunnel. */
 #include "ed25519_cert.h"
@@ -235,7 +237,7 @@ count_opened_desc_intro_point_circuits(const hs_service_t *service,
 
 /* From a given service, rendezvous cookie and handshake info, create a
  * rendezvous point circuit identifier. This can't fail. */
-static hs_ident_circuit_t *
+STATIC hs_ident_circuit_t *
 create_rp_circuit_identifier(const hs_service_t *service,
                              const uint8_t *rendezvous_cookie,
                              const curve25519_public_key_t *server_pk,

+ 10 - 0
src/or/hs_circuit.h

@@ -59,5 +59,15 @@ int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
 int hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
                                           const uint8_t *rend_cell_body);
 
+#ifdef HS_CIRCUIT_PRIVATE
+
+STATIC hs_ident_circuit_t *
+create_rp_circuit_identifier(const hs_service_t *service,
+                             const uint8_t *rendezvous_cookie,
+                             const curve25519_public_key_t *server_pk,
+                             const hs_ntor_rend_cell_keys_t *keys);
+
+#endif
+
 #endif /* !defined(TOR_HS_CIRCUIT_H) */
 

+ 1 - 1
src/or/hs_client.c

@@ -845,7 +845,7 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
 /* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
  * encoded cell is in payload of length payload_len. Return 0 on success or a
  * negative value on error. On error, the circuit is marked for close. */
-static int
+STATIC int
 handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
                    size_t payload_len)
 {

+ 3 - 0
src/or/hs_client.h

@@ -77,6 +77,9 @@ client_get_random_intro(const ed25519_public_key_t *service_pk);
 STATIC extend_info_t *
 desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip);
 
+STATIC int handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
+                              size_t payload_len);
+
 #endif /* defined(HS_CLIENT_PRIVATE) */
 
 #endif /* !defined(TOR_HS_CLIENT_H) */

+ 130 - 1
src/test/test_hs_service.c

@@ -14,10 +14,12 @@
 #define HS_COMMON_PRIVATE
 #define HS_SERVICE_PRIVATE
 #define HS_INTROPOINT_PRIVATE
+#define HS_CIRCUIT_PRIVATE
 #define MAIN_PRIVATE
 #define NETWORKSTATUS_PRIVATE
 #define STATEFILE_PRIVATE
 #define TOR_CHANNEL_INTERNAL_
+#define HS_CLIENT_PRIVATE
 
 #include "test.h"
 #include "test_helpers.h"
@@ -37,11 +39,12 @@
 
 #include "hs_common.h"
 #include "hs_config.h"
-#include "hs_circuit.h"
 #include "hs_ident.h"
 #include "hs_intropoint.h"
 #include "hs_ntor.h"
+#include "hs_circuit.h"
 #include "hs_service.h"
+#include "hs_client.h"
 #include "main.h"
 #include "rendservice.h"
 #include "statefile.h"
@@ -1366,6 +1369,130 @@ test_revision_counter_state(void *arg)
   service_descriptor_free(desc_two);
 }
 
+/** Global vars used by test_rendezvous1_parsing() */
+char rend1_payload[RELAY_PAYLOAD_SIZE];
+size_t rend1_payload_len = 0;
+
+/** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead
+ *  of sending it to the network, instead save it to the global `rend1_payload`
+ *  variable so that we can inspect it in the test_rendezvous1_parsing()
+ *  test. */
+static int
+mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ,
+                            uint8_t relay_command, const char *payload,
+                            size_t payload_len,
+                            crypt_path_t *cpath_layer,
+                            const char *filename, int lineno)
+{
+  (void) stream_id;
+  (void) circ;
+  (void) relay_command;
+  (void) cpath_layer;
+  (void) filename;
+  (void) lineno;
+
+  memcpy(rend1_payload, payload, payload_len);
+  rend1_payload_len = payload_len;
+
+  return 0;
+}
+
+/** Send a RENDEZVOUS1 as a service, and parse it as a client. */
+static void
+test_rendezvous1_parsing(void *arg)
+{
+  int retval;
+  static const char *test_addr =
+    "4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion";
+  hs_service_t *service = NULL;
+  origin_circuit_t *service_circ = NULL;
+  origin_circuit_t *client_circ = NULL;
+  ed25519_keypair_t ip_auth_kp;
+  curve25519_keypair_t ephemeral_kp;
+  curve25519_keypair_t client_kp;
+  curve25519_keypair_t ip_enc_kp;
+  int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
+
+  (void) arg;
+
+  MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1);
+
+  {
+    /* Let's start by setting up the service that will start the rend */
+    service = tor_malloc_zero(sizeof(hs_service_t));
+    ed25519_secret_key_generate(&service->keys.identity_sk, 0);
+    ed25519_public_key_generate(&service->keys.identity_pk,
+                                &service->keys.identity_sk);
+    memcpy(service->onion_address, test_addr, sizeof(service->onion_address));
+    tt_assert(service);
+  }
+
+  {
+    /* Now let's set up the service rendezvous circuit and its keys. */
+    service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND,
+                                                flags);
+    tor_free(service_circ->hs_ident);
+    hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
+    uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
+    curve25519_keypair_generate(&ip_enc_kp, 0);
+    curve25519_keypair_generate(&ephemeral_kp, 0);
+    curve25519_keypair_generate(&client_kp, 0);
+    ed25519_keypair_generate(&ip_auth_kp, 0);
+    retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey,
+                                                  &ip_enc_kp,
+                                                  &ephemeral_kp,
+                                                  &client_kp.pubkey,
+                                                  &hs_ntor_rend_cell_keys);
+    tt_int_op(retval, OP_EQ, 0);
+
+    memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie));
+    service_circ->hs_ident =
+      create_rp_circuit_identifier(service, rendezvous_cookie,
+                                   &ephemeral_kp.pubkey,
+                                   &hs_ntor_rend_cell_keys);
+  }
+
+  /* Send out the RENDEZVOUS1 and make sure that our mock func worked */
+  tt_assert(tor_mem_is_zero(rend1_payload, 32));
+  hs_circ_service_rp_has_opened(service, service_circ);
+  tt_assert(!tor_mem_is_zero(rend1_payload, 32));
+  tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE);
+
+  /******************************/
+
+  /** Now let's create the client rendezvous circuit */
+  client_circ =
+    helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED,
+                                 flags);
+  /* fix up its circ ident */
+  ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk,
+                      &ip_auth_kp.pubkey);
+  memcpy(&client_circ->hs_ident->rendezvous_client_kp,
+         &client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp));
+  memcpy(&client_circ->hs_ident->intro_enc_pk.public_key,
+         &ip_enc_kp.pubkey.public_key,
+         sizeof(client_circ->hs_ident->intro_enc_pk.public_key));
+
+  /* Now parse the rendezvous2 circuit and make sure it was fine. We are
+   * skipping 20 bytes off its payload, since that's the rendezvous cookie
+   * which is only present in REND1. */
+  retval = handle_rendezvous2(client_circ,
+                              (uint8_t*)rend1_payload+20,
+                              rend1_payload_len-20);
+  tt_int_op(retval, OP_EQ, 0);
+
+  /* TODO: We are only simulating client/service here. We could also simulate
+   * the rendezvous point by plugging in rend_mid_establish_rendezvous(). We
+   * would need an extra circuit and some more stuff but it's doable. */
+
+ done:
+  circuit_free(TO_CIRCUIT(service_circ));
+  circuit_free(TO_CIRCUIT(client_circ));
+  hs_service_free(service);
+  hs_free_all();
+  UNMOCK(relay_send_command_from_edge_);
+}
+
 struct testcase_t hs_service_tests[] = {
   { "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
     NULL, NULL },
@@ -1395,6 +1522,8 @@ struct testcase_t hs_service_tests[] = {
     NULL, NULL },
   { "revision_counter_state", test_revision_counter_state, TT_FORK,
     NULL, NULL },
+  { "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK,
+    NULL, NULL },
 
   END_OF_TESTCASES
 };