diff options
-rw-r--r-- | ChangeLog | 2 | ||||
-rw-r--r-- | doc/spec/dir-spec.txt | 9 | ||||
-rw-r--r-- | doc/spec/proposals/157-specific-cert-download.txt | 5 | ||||
-rw-r--r-- | src/or/directory.c | 68 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/test.c | 29 |
6 files changed, 117 insertions, 2 deletions
@@ -22,6 +22,8 @@ Changes in version 0.2.1.9-alpha - 200?-??-?? - Add cross-certification to newly generated certificates, so that a signing key is enough information to use to look up a certificate. Partial implementation of proposal 157. + - Start serving certificates by <identity digest, signing key digest> + pairs. Partial implementation of proposal 157. o Minor features (controller): - New CONSENSUS_ARRIVED event to note when a new consensus has diff --git a/doc/spec/dir-spec.txt b/doc/spec/dir-spec.txt index d7e393b32a..b48f251a2e 100644 --- a/doc/spec/dir-spec.txt +++ b/doc/spec/dir-spec.txt @@ -1556,6 +1556,15 @@ $Id$ available at: http://<hostname>/tor/keys/sk/<F>.z + The key certificate whose identity key fingerprint is <F> and whose signing + key fingerprint is <S> should be available at: + + http://<hostname>/tor/keys/fp-sk/<F>-<S>.z + + (As usual, clients may request multiple certificates using: + http://<hostname>/tor/keys/fp-sk/<F1>-<S1>+<F2>-<S2>.z ) + [The above fp-sk format was not supported before Tor 0.2.1.9-alpha.] + The most recent descriptor for a server whose identity key has a fingerprint of <F> should be available at: http://<hostname>/tor/server/fp/<F>.z diff --git a/doc/spec/proposals/157-specific-cert-download.txt b/doc/spec/proposals/157-specific-cert-download.txt index 2cae13b2e9..e54a987277 100644 --- a/doc/spec/proposals/157-specific-cert-download.txt +++ b/doc/spec/proposals/157-specific-cert-download.txt @@ -15,8 +15,9 @@ History: Status: - Cross-certification is implemented for new certificates, but not yet - required. + As of 0.2.1.9-alpha: + Cross-certification is implemented for new certificates, but not yet + required. Directories support the tor/keys/fp-sk urls. Overview: diff --git a/src/or/directory.c b/src/or/directory.c index e74119c0e6..7463cd942f 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2780,6 +2780,17 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, tor_free(d); }); smartlist_free(fps); + } else if (!strcmpstart(url, "/tor/keys/fp-sk/")) { + smartlist_t *fp_sks = smartlist_create(); + dir_split_resource_into_fingerprint_pairs(url+strlen("/tor/keys/fp-sk/"), + fp_sks); + SMARTLIST_FOREACH(fp_sks, fp_pair_t *, pair, { + authority_cert_t *c = authority_cert_get_by_digests(pair->first, + pair->second); + if (c) smartlist_add(certs, c); + tor_free(pair); + }); + smartlist_free(fp_sks); } else { write_http_status_line(conn, 400, "Bad request"); goto keys_done; @@ -3383,6 +3394,63 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code, * every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */ } +static int +_compare_pairs(const void **a, const void **b) +{ + const fp_pair_t *fp1 = *a, *fp2 = *b; + int r; + if ((r = memcmp(fp1->first, fp2->first, DIGEST_LEN))) + return r; + else + return memcmp(fp1->second, fp2->second, DIGEST_LEN); +} + +/** DOCDOC */ +int +dir_split_resource_into_fingerprint_pairs(const char *res, + smartlist_t *pairs_out) +{ + smartlist_t *pairs_tmp = smartlist_create(); + smartlist_t *pairs_result = smartlist_create(); + + smartlist_split_string(pairs_tmp, res, "+", 0, 0); + if (smartlist_len(pairs_tmp)) { + char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1); + size_t last_len = strlen(last); + if (last_len > 2 && !strcmp(last+last_len-2, ".z")) { + last[last_len-2] = '\0'; + } + } + SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) { + if (strlen(cp) != HEX_DIGEST_LEN*2+1) { + log_info(LD_DIR, + "Skipping digest pair %s with non-standard length.", escaped(cp)); + } else if (cp[HEX_DIGEST_LEN] != '-') { + log_info(LD_DIR, + "Skipping digest pair %s with missing dash.", escaped(cp)); + } else { + fp_pair_t pair; + if (base16_decode(pair.first, DIGEST_LEN, cp, HEX_DIGEST_LEN)<0 || + base16_decode(pair.second, + DIGEST_LEN, cp+HEX_DIGEST_LEN+1, HEX_DIGEST_LEN)<0) { + log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp)); + } else { + smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair))); + } + } + tor_free(cp); + } SMARTLIST_FOREACH_END(cp); + smartlist_free(pairs_tmp); + + /* Uniq-and-sort */ + smartlist_sort(pairs_result, _compare_pairs); + smartlist_uniq(pairs_result, _compare_pairs, _tor_free); + + smartlist_add_all(pairs_out, pairs_result); + smartlist_free(pairs_result); + return 0; +} + /** Given a directory <b>resource</b> request, containing zero * or more strings separated by plus signs, followed optionally by ".z", store * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is diff --git a/src/or/or.h b/src/or/or.h index f61258c3db..aa5c92fa97 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -3277,6 +3277,12 @@ void directory_initiate_command(const char *address, const tor_addr_t *addr, int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compresseed_out, int decode_hex, int sort_uniq); +typedef struct { + char first[DIGEST_LEN]; + char second[DIGEST_LEN]; +} fp_pair_t; +int dir_split_resource_into_fingerprint_pairs(const char *res, + smartlist_t *pairs_out); char *directory_dump_request_log(void); void note_request(const char *key, size_t bytes); int router_supports_extrainfo(const char *identity_digest, int is_authority); diff --git a/src/or/test.c b/src/or/test.c index 6d3eba1963..33d1b5d439 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -2985,6 +2985,34 @@ test_dir_format(void) tor_free(dir2); /* And more !*/ } +static void +test_dirutil(void) +{ + smartlist_t *sl = smartlist_create(); + fp_pair_t *pair; + + dir_split_resource_into_fingerprint_pairs( + /* Two pairs, out of order, with one duplicate. */ + "73656372657420646174612E0000000000FFFFFF-" + "557365204145532d32353620696e73746561642e+" + "73656372657420646174612E0000000000FFFFFF-" + "557365204145532d32353620696e73746561642e+" + "48657861646563696d616c2069736e277420736f-" + "676f6f6420666f7220686964696e6720796f7572.z", sl); + + test_eq(smartlist_len(sl), 2); + pair = smartlist_get(sl, 0); + test_memeq(pair->first, "Hexadecimal isn't so", DIGEST_LEN); + test_memeq(pair->second, "good for hiding your", DIGEST_LEN); + pair = smartlist_get(sl, 1); + test_memeq(pair->first, "secret data.\0\0\0\0\0\xff\xff\xff", DIGEST_LEN); + test_memeq(pair->second, "Use AES-256 instead.", DIGEST_LEN); + + done: + SMARTLIST_FOREACH(sl, fp_pair_t *, pair, tor_free(pair)); + smartlist_free(sl); +} + extern const char AUTHORITY_CERT_1[]; extern const char AUTHORITY_SIGNKEY_1[]; extern const char AUTHORITY_CERT_2[]; @@ -4448,6 +4476,7 @@ static struct { SUBENT(util, order_functions), ENT(onion_handshake), ENT(dir_format), + ENT(dirutil), ENT(v3_networkstatus), ENT(policies), ENT(rend_fns), |