commit 1db13809c6f4aa1bc9b240a4bda54066730ee75f
parent 4d642100907cb2125c23f3404d2ab907543433b6
Author: Nick Mathewson <nickm@torproject.org>
Date: Mon, 10 Feb 2025 16:42:52 -0500
Parse microdesc family-ids lines.
Diffstat:
3 files changed, 51 insertions(+), 0 deletions(-)
diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c
@@ -35,6 +35,7 @@ static token_rule_t microdesc_token_table[] = {
T0N("id", K_ID, GE(2), NO_OBJ ),
T0N("a", K_A, GE(1), NO_OBJ ),
T01("family", K_FAMILY, CONCAT_ARGS, NO_OBJ ),
+ T01("family-ids", K_FAMILY_IDS, CONCAT_ARGS, NO_OBJ ),
T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ),
A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
@@ -252,6 +253,16 @@ microdesc_parse_fields(microdesc_t *md,
NULL,
NF_WARN_MALFORMED);
}
+ if ((tok = find_opt_by_keyword(tokens, K_FAMILY_IDS))) {
+ smartlist_t *ids = smartlist_new();
+ smartlist_split_string(ids, tok->args[0], " ",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ if (smartlist_len(ids) > 0) {
+ md->family_ids = ids;
+ } else {
+ smartlist_free(ids);
+ }
+ }
if ((tok = find_opt_by_keyword(tokens, K_P))) {
md->exit_policy = parse_short_policy(tok->args[0]);
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
@@ -45,6 +45,7 @@ typedef enum {
K_UPTIME,
K_DIR_SIGNING_KEY,
K_FAMILY,
+ K_FAMILY_KEYS,
K_FINGERPRINT,
K_HIBERNATING,
K_READ_HISTORY,
diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c
@@ -789,6 +789,44 @@ test_md_parse_no_onion_key(void *arg)
teardown_capture_of_logs();
}
+static void
+test_md_parse_family_ids(void *arg)
+{
+ (void)arg;
+
+ const char GOOD_MDS[] =
+ "onion-key\n"
+ "ntor-onion-key VHlycmFueSwgbGlrZSBoZWxsLCBpcyBub3QgZWFzaWw\n"
+ "id ed25519 eSBjb25xdWVyZWQ7IHlldCB3ZSBoYXZlIHRoaXMgY28\n"
+ "family-ids\n"
+ "onion-key\n"
+ "ntor-onion-key bnNvbGF0aW9uIHdpdGggdXMsIHRoYXQgdGhlIGhhcmQ\n"
+ "id ed25519 ZXIgdGhlIGNvbmZsaWN0LCB0aGUgbW9yZSBnbG9yaW8\n"
+ "family-ids ed25519:dXMgdGhlIHRyaXVtcGguICAgIC1UaG9tYXMgUGFpbmU "
+ "other:Example\n";
+ smartlist_t *mds = NULL;
+ mds = microdescs_parse_from_string(GOOD_MDS, NULL, 1, SAVED_NOWHERE, NULL);
+ tt_assert(mds);
+ tt_int_op(smartlist_len(mds), OP_EQ, 2);
+
+ const microdesc_t *md1 = smartlist_get(mds, 0);
+ tt_ptr_op(md1->family_ids, OP_EQ, NULL);
+
+ const microdesc_t *md2 = smartlist_get(mds, 1);
+ tt_ptr_op(md2->family_ids, OP_NE, NULL);
+ tt_int_op(smartlist_len(md2->family_ids), OP_EQ, 2);
+ tt_str_op(smartlist_get(md2->family_ids, 0), OP_EQ,
+ "ed25519:dXMgdGhlIHRyaXVtcGguICAgIC1UaG9tYXMgUGFpbmU");
+ tt_str_op(smartlist_get(md2->family_ids, 1), OP_EQ,
+ "other:Example");
+
+ done:
+ if (mds) {
+ SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m));
+ smartlist_free(mds);
+ }
+}
+
static int mock_rgsbd_called = 0;
static routerstatus_t *mock_rgsbd_val_a = NULL;
static routerstatus_t *mock_rgsbd_val_b = NULL;
@@ -924,6 +962,7 @@ struct testcase_t microdesc_tests[] = {
{ "parse", test_md_parse, 0, NULL, NULL },
{ "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL },
{ "parse_no_onion_key", test_md_parse_no_onion_key, 0, NULL, NULL },
+ { "parse_family_ids", test_md_parse_family_ids, 0, NULL, NULL },
{ "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
{ "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL },
END_OF_TESTCASES