]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Allow pow-params to appear multiple times.
authorNick Mathewson <nickm@torproject.org>
Mon, 12 May 2025 12:27:34 +0000 (08:27 -0400)
committerNick Mathewson <nickm@torproject.org>
Mon, 12 May 2025 12:44:15 +0000 (08:44 -0400)
Relatedly, we only require that a pow-params line has _1_ argument
(since future versions might have nothing but a scheme).

See torspec#272 for discussion;
also see proposal 356 for why the fingerprinting opportunity here
isn't a big deal.

We probably shouldn't merge this until torspec!390 is in,
just in case we decide _not_ to take this approach.

(I haven't reindented some code here yet, to make the diff easier to read.)

changes/torspec_272 [new file with mode: 0644]
src/feature/hs/hs_descriptor.c

diff --git a/changes/torspec_272 b/changes/torspec_272
new file mode 100644 (file)
index 0000000..78a23ff
--- /dev/null
@@ -0,0 +1,4 @@
+  o Minor features (hsdesc POW):
+    - Tolerate multiple PoW schemes in onion service descriptors,
+      for future extensibility.
+      Implements torspec ticket 272.
index da7bb662e102feefc5bd85bdfc0faa9eedfba801..5131ae0720db5103be52883d2c16dc390e5d130d 100644 (file)
@@ -155,7 +155,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
   T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, GE(1), NO_OBJ),
   T01(str_single_onion, R3_SINGLE_ONION_SERVICE, ARGS, NO_OBJ),
   T01(str_flow_control, R3_FLOW_CONTROL, GE(2), NO_OBJ),
-  T01(str_pow_params, R3_POW_PARAMS, GE(4), NO_OBJ),
+  T0N(str_pow_params, R3_POW_PARAMS, GE(1), NO_OBJ),
   END_OF_TABLE
 };
 
@@ -2098,33 +2098,49 @@ desc_sig_is_valid(const char *b64_sig,
   return ret;
 }
 
-/** Given the token tok for PoW params, decode it as hs_pow_desc_params_t.
- * tok->args MUST contain at least 4 elements Return 0 on success else -1 on
- * failure. */
+/** Given a list of tokens for PoW params, decode it as a v1
+ * hs_pow_desc_params_t.
+ *
+ * Each token's args MUST contain at least 1 element.
+ *
+ * On success, return 0, and set <b>pow_params_out</b> to a new set of
+ * parameters (or to NULL if there were no v1 parameters).  Return -1 on
+ * failure.
+ */
 static int
-decode_pow_params(const directory_token_t *tok,
-                  hs_pow_desc_params_t *pow_params)
+decode_pow_params(const smartlist_t *toks,
+                  hs_pow_desc_params_t **pow_params_out)
 {
+  bool found_v1 = false;
   int ret = -1;
+  tor_assert(pow_params_out);
+  *pow_params_out = NULL;
 
-  tor_assert(tok);
-  tor_assert(tok->n_args >= 4);
-  tor_assert(pow_params);
+  if (!toks)
+    return 0;
 
-  /* Find the type of PoW system being used. */
-  int match = 0;
-  for (int idx = 0; pow_types[idx].identifier; idx++) {
-    if (!strncmp(tok->args[0], pow_types[idx].identifier,
-                 strlen(pow_types[idx].identifier))) {
-      pow_params->type = pow_types[idx].type;
-      match = 1;
-      break;
+  // XXXX reindent.
+  SMARTLIST_FOREACH_BEGIN(toks, const directory_token_t *, tok) {
+    tor_assert(tok->n_args >= 1);
+
+    if (strcmp(tok->args[0], "v1")) {
+      // Unrecognized type; skip it.
+      continue;
     }
-  }
-  if (!match) {
-    log_warn(LD_REND, "Unknown PoW type from descriptor.");
-    goto done;
-  }
+
+    if (found_v1) {
+      log_warn(LD_REND, "Duplicate v1 PoW entries in descriptor.");
+      goto done;
+    }
+    found_v1 = true;
+    if (tok->n_args < 4) {
+      log_warn(LD_REND, "Insufficient arguments for v1 PoW entry.");
+      goto done;
+    }
+
+    hs_pow_desc_params_t *pow_params = tor_malloc_zero(sizeof(*pow_params));
+    *pow_params_out = pow_params;
+    pow_params->type = HS_POW_DESC_V1;
 
   if (base64_decode((char *)pow_params->seed, sizeof(pow_params->seed),
                     tok->args[1], strlen(tok->args[1])) !=
@@ -2155,10 +2171,16 @@ decode_pow_params(const directory_token_t *tok,
    * trigger a fetch if expired. */
   pow_params->expiration_time = expiration_time;
 
+  } SMARTLIST_FOREACH_END(tok);
+
   /* Success. */
   ret = 0;
 
  done:
+  if (ret < 0 && *pow_params_out) {
+    tor_free(*pow_params_out); // sets it to NULL
+  }
+
   return ret;
 }
 
@@ -2474,15 +2496,13 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
   }
 
   /* Get PoW if any. */
-  tok = find_opt_by_keyword(tokens, R3_POW_PARAMS);
-  if (tok) {
-    hs_pow_desc_params_t *pow_params =
-      tor_malloc_zero(sizeof(hs_pow_desc_params_t));
-    if (decode_pow_params(tok, pow_params)) {
-      tor_free(pow_params);
+  {
+    smartlist_t *pow_toks = find_all_by_keyword(tokens, R3_POW_PARAMS);
+    int r = decode_pow_params(pow_toks, &desc_encrypted_out->pow_params);
+    smartlist_free(pow_toks);
+    if (r < 0) {
       goto err;
     }
-    desc_encrypted_out->pow_params = pow_params;
   }
 
   /* Initialize the descriptor's introduction point list before we start