]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
prop346: Support Relay=5 and negotiate if available
authorDavid Goulet <dgoulet@torproject.org>
Mon, 22 Jan 2024 20:36:25 +0000 (15:36 -0500)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 31 Jan 2024 15:15:07 +0000 (10:15 -0500)
Signed-off-by: David Goulet <dgoulet@torproject.org>
src/core/crypto/onion_crypto.h
src/core/or/circuitbuild.c
src/core/or/extend_info_st.h
src/core/or/extendinfo.c
src/core/or/or.h
src/core/or/protover.c
src/core/or/protover.h
src/core/or/versions.c
src/feature/nodelist/nodelist.c

index 8251111c37ccbe617c7d24a3230b61a71e34569e..233df9a1a010481f83558d60952356915bed3e7d 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef TOR_ONION_CRYPTO_H
 #define TOR_ONION_CRYPTO_H
 
+#include "core/or/or.h"
 #include "lib/crypt_ops/crypto_ed25519.h"
 
 typedef struct server_onion_keys_t {
index 87dd81eae4d21fa57e71c6d2903fb62c21286376..37ed39eac762ac7a2947a6d1040c4cb41f71bd2b 100644 (file)
@@ -50,6 +50,7 @@
 #include "core/or/onion.h"
 #include "core/or/ocirc_event.h"
 #include "core/or/policies.h"
+#include "core/or/protover.h"
 #include "core/or/relay.h"
 #include "core/or/trace_probes_circuit.h"
 #include "core/or/crypt_path.h"
@@ -891,8 +892,8 @@ circuit_pick_create_handshake(uint8_t *cell_type_out,
     *cell_type_out = CELL_CREATE2;
     /* Only use ntor v3 with exits that support congestion control,
      * and only when it is enabled. */
-    if (ei->exit_supports_congestion_control &&
-        congestion_control_enabled())
+    if ((ei->exit_supports_congestion_control ||
+         ei->supports_ntorv3_subproto_req) && congestion_control_enabled())
       *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3;
     else
       *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
@@ -2716,7 +2717,17 @@ client_circ_negotiation_message(const extend_info_t *ei, uint8_t **msg_out,
 
   ext = trn_extension_new();
 
-  if (congestion_control_enabled() && ei->exit_supports_congestion_control) {
+  /* Prioritize ntorv3 subprotocol request. */
+  if (ei->supports_ntorv3_subproto_req) {
+    field = protover_build_ntor3_ext_request(ei);
+    if (field) {
+      trn_extension_add_fields(ext, field);
+      trn_extension_set_num(ext, trn_extension_get_num(ext) + 1);
+    }
+  } else if (congestion_control_enabled() &&
+             ei->exit_supports_congestion_control) {
+    /* Fallback to old CC extension if the relay doesn't support ntorv3
+     * subproto request. */
     field = congestion_control_build_ext_request();
     if (field) {
       trn_extension_add_fields(ext, field);
index 2ab0beb7e61493b03771c933283908e1f6b86cfd..44edadaf17b678f61f39b56abfd2f4e27ff0ee4e 100644 (file)
@@ -42,6 +42,9 @@ struct extend_info_t {
    * and it also supports supports NtorV3 _and_ negotiation
    * of congestion control parameters */
   bool exit_supports_congestion_control;
+  /** True iff this hop supports the ntorv3 subprotocol request which is
+   * defined by Relay=5 */
+  bool supports_ntorv3_subproto_req;
 };
 
 #endif /* !defined(EXTEND_INFO_ST_H) */
index ca623f09cedeb867d8fbf842323de1874ec2d47b..66b01c8788fb381d49aee3d0bdc50c02075983f9 100644 (file)
@@ -64,6 +64,10 @@ extend_info_new(const char *nickname,
       pv->supports_congestion_control;
   }
 
+  if (pv) {
+    info->supports_ntorv3_subproto_req = pv->supports_ntorv3_subproto;
+  }
+
   return info;
 }
 
@@ -229,7 +233,7 @@ extend_info_supports_ntor_v3(const extend_info_t *ei)
 {
   tor_assert(ei);
   return extend_info_supports_ntor(ei) &&
-    ei->exit_supports_congestion_control;
+    (ei->exit_supports_congestion_control || ei->supports_ntorv3_subproto_req);
 }
 
 /* Does ei have an onion key which it would prefer to use?
index 088c45342b673936afcf2be13c81eb06d3262d89..af3518cd5ec10ba90c37de5aee7842d6a4e7dc6c 100644 (file)
@@ -741,8 +741,12 @@ typedef struct protover_summary_flags_t {
    * Requires both FlowCtrl=2 *and* Relay=4 */
   unsigned int supports_congestion_control : 1;
 
-  /** True iff this router supports conflux. Requires Relay=5 */
+  /** True iff this router supports conflux. */
   unsigned int supports_conflux : 1;
+
+  /** True iff this router supports ntorv3 subproto request extension. Requires
+   * Relay=5. */
+  unsigned int supports_ntorv3_subproto : 1;
 } protover_summary_flags_t;
 
 typedef struct routerinfo_t routerinfo_t;
index 175bfbdab0c5383bd48e6891b3c5cc91e8cbc9fe..53c4198b48320aa2b081b214eabd255574388703 100644 (file)
 
 #define PROTOVER_PRIVATE
 
-#include "core/or/or.h"
+#include "core/or/congestion_control_common.h"
+#include "core/or/extend_info_st.h"
 #include "core/or/protover.h"
 #include "core/or/versions.h"
 #include "lib/tls/tortls.h"
 
+#include "trunnel/ntorv3.h"
+
 static const smartlist_t *get_supported_protocol_list(void);
 static int protocol_list_contains(const smartlist_t *protos,
                                   protocol_type_t pr, uint32_t ver);
@@ -893,3 +896,54 @@ protover_free_all(void)
     supported_protocol_list = NULL;
   }
 }
+
+/** Build a ntorv3 subprotocol extension request for the given hop.
+ *
+ * On success, return the extension encoded as a field else NULL. */
+trn_extension_field_t *
+protover_build_ntor3_ext_request(const extend_info_t *ei)
+{
+  ssize_t ret;
+  trn_extension_field_t *field = NULL;
+  trn_ntorv3_ext_subproto_t *req = NULL;
+
+  field = trn_extension_field_new();
+  trn_extension_field_set_field_type(field,
+                                     TRUNNEL_NTORV3_EXT_TYPE_SUBPROTO_REQ);
+
+  req = trn_ntorv3_ext_subproto_new();
+
+  /* Build the FlowCtrl version request. */
+  if (congestion_control_enabled() && ei->supports_ntorv3_subproto_req) {
+    trn_ntorv3_ext_subproto_req_t *proto_req =
+      trn_ntorv3_ext_subproto_req_new();
+    trn_ntorv3_ext_subproto_req_set_proto_id(proto_req, PRT_FLOWCTRL);
+    trn_ntorv3_ext_subproto_req_set_proto_version(proto_req,
+                                                  PROTOVER_FLOWCTRL_CC);
+    trn_ntorv3_ext_subproto_add_reqs(req, proto_req);
+  }
+
+  /* Encoding into an extension field. */
+  ret = trn_ntorv3_ext_subproto_encoded_len(req);
+  if (BUG(ret < 0)) {
+    trn_extension_field_free(field);
+    field = NULL;
+    goto err;
+  }
+  size_t field_len = ret;
+  trn_extension_field_set_field_len(field, field_len);
+  trn_extension_field_setlen_field(field, field_len);
+
+  uint8_t *field_array = trn_extension_field_getarray_field(field);
+  ret = trn_ntorv3_ext_subproto_encode(field_array,
+            trn_extension_field_getlen_field(field), req);
+  if (BUG(ret < 0)) {
+    trn_extension_field_free(field);
+    field = NULL;
+    goto err;
+  }
+
+ err:
+  trn_ntorv3_ext_subproto_free(req);
+  return field;
+}
index 9d8eb4dcc5fd15e5a55d4ca3b5a6baab84dbf083..9efa2201a76995eafd9600fe9d636c61e8977441 100644 (file)
@@ -9,9 +9,13 @@
 #ifndef TOR_PROTOVER_H
 #define TOR_PROTOVER_H
 
+#include "core/or/or.h"
 #include <stdbool.h>
 #include "lib/cc/torint.h"
 #include "lib/testsupport/testsupport.h"
+
+#include "trunnel/extension.h"
+
 struct smartlist_t;
 
 /** The first version of Tor that included "proto" entries in its
@@ -58,6 +62,9 @@ struct smartlist_t;
 /** The protover that signals support for congestion control */
 #define PROTOVER_FLOWCTRL_CC 2
 
+/** The protover that signals support for ntorv3 subprotocol request. */
+#define PROTOVER_RELAY_NTORV3_SUBPROTO 5
+
 /** List of recognized subprotocols. */
 /// C_RUST_COUPLED: src/rust/protover/ffi.rs `translate_to_rust`
 /// C_RUST_COUPLED: src/rust/protover/protover.rs `Proto`
@@ -98,6 +105,9 @@ int protocol_list_supports_protocol_or_later(const char *list,
 
 void protover_free_all(void);
 
+trn_extension_field_t *protover_build_ntor3_ext_request(
+                                            const extend_info_t *ei);
+
 #ifdef PROTOVER_PRIVATE
 /** Represents a set of ranges of subprotocols of a given type. */
 typedef struct proto_entry_t {
index 8f5503691e758ca38c68e7da237fd9a6fd615cf2..a33c5f15a59fd1ffcf8a0516dec59eafe2762fb2 100644 (file)
@@ -495,6 +495,10 @@ memoize_protover_summary(protover_summary_flags_t *out,
     protocol_list_supports_protocol(protocols, PRT_CONFLUX,
                                     PROTOVER_CONFLUX_V1);
 
+  out->supports_ntorv3_subproto =
+    protocol_list_supports_protocol(protocols, PRT_RELAY,
+                                    PROTOVER_RELAY_NTORV3_SUBPROTO);
+
   protover_summary_flags_t *new_cached = tor_memdup(out, sizeof(*out));
   cached = strmap_set(protover_summary_map, protocols, new_cached);
   tor_assert(!cached);
index bbaa51a40745dd8658ed9bcddbebe4391e838b39..efea56ed77e66c0b9b98c6048a66c1c126966a6a 100644 (file)
@@ -1205,7 +1205,7 @@ node_ed25519_id_matches(const node_t *node, const ed25519_public_key_t *id)
 /** Dummy object that should be unreturnable.  Used to ensure that
  * node_get_protover_summary_flags() always returns non-NULL. */
 static const protover_summary_flags_t zero_protover_flags = {
-  0,0,0,0,0,0,0,0,0,0,0,0,0,0
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 };
 
 /** Return the protover_summary_flags for a given node. */