summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-09-23 10:44:38 -0400
committerNick Mathewson <nickm@torproject.org>2015-09-23 11:02:21 -0400
commitc5e87e33c7a3bf0f3d6b289814d303bcb4c63fe2 (patch)
tree697388196be5e2808ccfec0ec6096d99cf049009
parent81724d5a001575e3f25da665b8bdedf287ace765 (diff)
downloadtor-c5e87e33c7a3bf0f3d6b289814d303bcb4c63fe2.tar.gz
tor-c5e87e33c7a3bf0f3d6b289814d303bcb4c63fe2.zip
Allow conflicts to occur in keypinning journal
When we find a conflict in the keypinning journal, treat the new entry as superseding all old entries that overlap either of its keys. Also add a (not-yet-used) configuration option to disable keypinning enforcement.
-rw-r--r--src/or/config.c1
-rw-r--r--src/or/keypin.c42
-rw-r--r--src/or/or.h1
-rw-r--r--src/test/test_keypin.c10
4 files changed, 39 insertions, 15 deletions
diff --git a/src/or/config.c b/src/or/config.c
index 44fb4ecec6..fa860af337 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -162,6 +162,7 @@ static config_var_t option_vars_[] = {
V(AuthDirInvalidCCs, CSV, ""),
V(AuthDirFastGuarantee, MEMUNIT, "100 KB"),
V(AuthDirGuardBWGuarantee, MEMUNIT, "2 MB"),
+ V(AuthDirPinKeys, BOOL, "0"),
V(AuthDirReject, LINELIST, NULL),
V(AuthDirRejectCCs, CSV, ""),
OBSOLETE("AuthDirRejectUnlisted"),
diff --git a/src/or/keypin.c b/src/or/keypin.c
index ebe83b35d2..cab6c9dc37 100644
--- a/src/or/keypin.c
+++ b/src/or/keypin.c
@@ -321,19 +321,41 @@ keypin_load_journal_impl(const char *data, size_t size)
continue;
}
- const keypin_ent_t *ent2;
- if ((ent2 = HT_FIND(rsamap, &the_rsa_map, ent))) {
- if (fast_memeq(ent2->ed25519_key, ent->ed25519_key, DIGEST256_LEN)) {
- ++n_duplicates;
- } else {
- ++n_conflicts;
- }
+ keypin_ent_t *ent2 = HT_FIND(rsamap, &the_rsa_map, ent);
+ keypin_ent_t *ent3 = HT_FIND(edmap, &the_ed_map, ent);
+ if (ent2 &&
+ fast_memeq(ent2->ed25519_key, ent->ed25519_key, DIGEST256_LEN)) {
+ /* We already have this mapping stored. Ignore it. */
tor_free(ent);
+ ++n_duplicates;
continue;
- } else if (HT_FIND(edmap, &the_ed_map, ent)) {
- tor_free(ent);
+ } else if (ent2 || ent3) {
+ /* We have a conflict. (If we had no entry, we would have ent2 == ent3
+ * == NULL. If we had a non-conflicting duplicate, we would have found
+ * it above.)
+ *
+ * We respond by having this entry (ent) supersede all entries that it
+ * contradicts (ent2 and/or ent3). In other words, if we receive
+ * <rsa,ed>, we remove all <rsa,ed'> and all <rsa',ed>, for rsa'!=rsa
+ * and ed'!= ed.
+ */
+ const keypin_ent_t *t;
+ if (ent2) {
+ t = HT_REMOVE(rsamap, &the_rsa_map, ent2);
+ tor_assert(ent2 == t);
+ t = HT_REMOVE(edmap, &the_ed_map, ent2);
+ tor_assert(ent2 == t);
+ }
+ if (ent3 && ent2 != ent3) {
+ t = HT_REMOVE(rsamap, &the_rsa_map, ent3);
+ tor_assert(ent3 == t);
+ t = HT_REMOVE(edmap, &the_ed_map, ent3);
+ tor_assert(ent3 == t);
+ tor_free(ent3);
+ }
+ tor_free(ent2);
++n_conflicts;
- continue;
+ /* Fall through */
}
keypin_add_entry_to_map(ent);
diff --git a/src/or/or.h b/src/or/or.h
index bec39b2b37..4496cbcec3 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3790,6 +3790,7 @@ typedef struct {
* number of servers per IP address shared
* with an authority. */
int AuthDirHasIPv6Connectivity; /**< Boolean: are we on IPv6? */
+ int AuthDirPinKeys; /**< Boolean: Do we enforce key-pinning? */
/** If non-zero, always vote the Fast flag for any relay advertising
* this amount of capacity or more. */
diff --git a/src/test/test_keypin.c b/src/test/test_keypin.c
index afd4ca201d..033578cae8 100644
--- a/src/test/test_keypin.c
+++ b/src/test/test_keypin.c
@@ -108,21 +108,21 @@ test_keypin_parse_file(void *arg)
;
tt_int_op(0, ==, keypin_load_journal_impl(data2, strlen(data2)));
- tt_int_op(11, ==, smartlist_len(mock_addent_got));
+ tt_int_op(13, ==, smartlist_len(mock_addent_got));
ent = smartlist_get(mock_addent_got, 9);
tt_mem_op(ent->rsa_id, ==, "\"You have made a goo", 20);
tt_mem_op(ent->ed25519_key, ==, "d beginning.\" But no more. Wizar", 32);
- ent = smartlist_get(mock_addent_got, 10);
+ ent = smartlist_get(mock_addent_got, 12);
tt_mem_op(ent->rsa_id, ==, "ds speak truth, and ", 20);
- tt_mem_op(ent->ed25519_key, ==, "it was true that all the master\n", 32);
+ tt_mem_op(ent->ed25519_key, ==, "it was tru\xa5 that all the master\n", 32);
/* File truncated before NL */
const char data3[] =
"Tm8gZHJhZ29uIGNhbiByZXNpc3Q IHRoZSBmYXNjaW5hdGlvbiBvZiByaWRkbGluZyB0YWw";
tt_int_op(0, ==, keypin_load_journal_impl(data3, strlen(data3)));
- tt_int_op(12, ==, smartlist_len(mock_addent_got));
- ent = smartlist_get(mock_addent_got, 11);
+ tt_int_op(14, ==, smartlist_len(mock_addent_got));
+ ent = smartlist_get(mock_addent_got, 13);
tt_mem_op(ent->rsa_id, ==, "No dragon can resist", 20);
tt_mem_op(ent->ed25519_key, ==, " the fascination of riddling tal", 32);