Browse Source

prop224: Handle RENDEZVOUS2 cell

The client can now handle RENDEZVOUS2 cell when they arrive. This consolidate
both hidden service version in one function.

Signed-off-by: David Goulet <dgoulet@torproject.org>
David Goulet 6 years ago
parent
commit
9af3116306
4 changed files with 100 additions and 12 deletions
  1. 96 0
      src/or/hs_client.c
  2. 3 0
      src/or/hs_client.h
  3. 0 11
      src/or/rendclient.c
  4. 1 1
      src/or/rendcommon.c

+ 96 - 0
src/or/hs_client.c

@@ -26,6 +26,7 @@
 #include "connection.h"
 #include "circpathbias.h"
 #include "connection.h"
+#include "hs_ntor.h"
 
 /* Get all connections that are waiting on a circuit and flag them back to
  * waiting for a hidden service descriptor for the given service key
@@ -584,6 +585,68 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
   return ret;
 }
 
+/* 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
+handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
+                   size_t payload_len)
+{
+  int ret = -1;
+  curve25519_public_key_t server_pk;
+  uint8_t auth_mac[DIGEST256_LEN] = {0};
+  uint8_t handshake_info[CURVE25519_PUBKEY_LEN + sizeof(auth_mac)] = {0};
+  hs_ntor_rend_cell_keys_t keys;
+  const hs_ident_circuit_t *ident;
+
+  tor_assert(circ);
+  tor_assert(payload);
+
+  /* Make things easier. */
+  ident = circ->hs_ident;
+  tor_assert(ident);
+
+  if (hs_cell_parse_rendezvous2(payload, payload_len, handshake_info,
+                                sizeof(handshake_info)) < 0) {
+    goto err;
+  }
+  /* Get from the handshake info the SERVER_PK and AUTH_MAC. */
+  memcpy(&server_pk, handshake_info, CURVE25519_PUBKEY_LEN);
+  memcpy(auth_mac, handshake_info + CURVE25519_PUBKEY_LEN, sizeof(auth_mac));
+
+  /* Generate the handshake info. */
+  if (hs_ntor_client_get_rendezvous1_keys(&ident->intro_auth_pk,
+                                          &ident->rendezvous_client_kp,
+                                          &ident->intro_enc_pk, &server_pk,
+                                          &keys) < 0) {
+    log_info(LD_REND, "Unable to compute the rendezvous keys.");
+    goto err;
+  }
+
+  /* Critical check, make sure that the MAC matches what we got with what we
+   * computed just above. */
+  if (!hs_ntor_client_rendezvous2_mac_is_good(&keys, auth_mac)) {
+    log_info(LD_REND, "Invalid MAC in RENDEZVOUS2. Rejecting cell.");
+    goto err;
+  }
+
+  /* Setup the e2e encryption on the circuit and finalize its state. */
+  if (hs_circuit_setup_e2e_rend_circ(circ, keys.ntor_key_seed,
+                                     sizeof(keys.ntor_key_seed), 0) < 0) {
+    log_info(LD_REND, "Unable to setup the e2e encryption.");
+    goto err;
+  }
+  /* Success. Hidden service connection finalized! */
+  ret = 0;
+  goto end;
+
+ err:
+  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
+ end:
+  memwipe(&keys, 0, sizeof(keys));
+  return ret;
+}
+
 /* ========== */
 /* Public API */
 /* ========== */
@@ -881,3 +944,36 @@ hs_client_receive_introduce_ack(origin_circuit_t *circ,
   return ret;
 }
 
+/* Called when get a RENDEZVOUS2 cell on the rendezvous circuit circ.  Return
+ * 0 on success else a negative value is returned. The circuit will be closed
+ * on error. */
+int
+hs_client_receive_rendezvous2(origin_circuit_t *circ,
+                              const uint8_t *payload, size_t payload_len)
+{
+  int ret = -1;
+
+  tor_assert(circ);
+  tor_assert(payload);
+
+  /* Circuit can possibly be in both state because we could receive a
+   * RENDEZVOUS2 cell before the INTRODUCE_ACK has been received. */
+  if (TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY &&
+      TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED) {
+    log_warn(LD_PROTOCOL, "Unexpected RENDEZVOUS2 cell on circuit %u. "
+                          "Closing circuit.",
+             (unsigned int) TO_CIRCUIT(circ)->n_circ_id);
+    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
+    goto end;
+  }
+
+  log_info(LD_REND, "Got RENDEZVOUS2 cell from hidden service on circuit %u.",
+           TO_CIRCUIT(circ)->n_circ_id);
+
+  ret = (circ->hs_ident) ? handle_rendezvous2(circ, payload, payload_len) :
+                           rend_client_receive_rendezvous(circ, payload,
+                                                          payload_len);
+ end:
+  return ret;
+}
+

+ 3 - 0
src/or/hs_client.h

@@ -34,6 +34,9 @@ int hs_client_receive_rendezvous_acked(origin_circuit_t *circ,
 int hs_client_receive_introduce_ack(origin_circuit_t *circ,
                                     const uint8_t *payload,
                                     size_t payload_len);
+int hs_client_receive_rendezvous2(origin_circuit_t *circ,
+                                  const uint8_t *payload,
+                                  size_t payload_len);
 
 void hs_client_desc_has_arrived(const hs_ident_dir_conn_t *ident);
 

+ 0 - 11
src/or/rendclient.c

@@ -932,23 +932,12 @@ int
 rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
                                size_t request_len)
 {
-  if ((circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY &&
-       circ->base_.purpose != CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED)
-      || !circ->build_state->pending_final_cpath) {
-    log_warn(LD_PROTOCOL,"Got rendezvous2 cell from hidden service, but not "
-             "expecting it. Closing.");
-    circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL);
-    return -1;
-  }
-
   if (request_len != DH_KEY_LEN+DIGEST_LEN) {
     log_warn(LD_PROTOCOL,"Incorrect length (%d) on RENDEZVOUS2 cell.",
              (int)request_len);
     goto err;
   }
 
-  log_info(LD_REND,"Got RENDEZVOUS2 cell from hidden service.");
-
   if (hs_circuit_setup_e2e_rend_circ_legacy_client(circ, request) < 0) {
     log_warn(LD_GENERAL, "Failed to setup circ");
     goto err;

+ 1 - 1
src/or/rendcommon.c

@@ -790,7 +790,7 @@ rend_process_relay_cell(circuit_t *circ, const crypt_path_t *layer_hint,
       break;
     case RELAY_COMMAND_RENDEZVOUS2:
       if (origin_circ)
-        r = rend_client_receive_rendezvous(origin_circ,payload,length);
+        r = hs_client_receive_rendezvous2(origin_circ,payload,length);
       break;
     case RELAY_COMMAND_INTRO_ESTABLISHED:
       if (origin_circ)