Merge remote-tracking branch 'public/bug11243_squashed'

This commit is contained in:
Nick Mathewson 2014-10-13 14:32:43 -04:00
commit d950e24332
19 changed files with 2168 additions and 78 deletions

7
changes/ticket11243 Normal file
View File

@ -0,0 +1,7 @@
o Major features (downloading):
- Upon receiving a server descriptor, microdescriptor, extrainfo
document, or other object that is unparseable, if its digest
matches what we expected, then mark it as not to be downloaded
again. Previously, when we got a descriptor we didn't like, we
would keep trying to download it over and over. Closes ticket
11243.

218
scripts/codegen/makedesc.py Normal file
View File

@ -0,0 +1,218 @@
#!/usr/bin/python
# Copyright 2014, The Tor Project, Inc.
# See LICENSE for license information
# This is a kludgey python script that uses ctypes and openssl to sign
# router descriptors and extrainfo documents and put all the keys in
# the right places. There are examples at the end of the file.
# I've used this to make inputs for unit tests. I wouldn't suggest
# using it for anything else.
import base64
import binascii
import ctypes
import ctypes.util
import hashlib
crypt = ctypes.CDLL(ctypes.util.find_library('crypto'))
BIO_s_mem = crypt.BIO_s_mem
BIO_s_mem.argtypes = []
BIO_s_mem.restype = ctypes.c_void_p
BIO_new = crypt.BIO_new
BIO_new.argtypes = [ctypes.c_void_p]
BIO_new.restype = ctypes.c_void_p
RSA_generate_key = crypt.RSA_generate_key
RSA_generate_key.argtypes = [ctypes.c_int, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_void_p]
RSA_generate_key.restype = ctypes.c_void_p
RSA_private_encrypt = crypt.RSA_private_encrypt
RSA_private_encrypt.argtypes = [
ctypes.c_int, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int ]
RSA_private_encrypt.restype = ctypes.c_int
i2d_RSAPublicKey = crypt.i2d_RSAPublicKey
i2d_RSAPublicKey.argtypes = [
ctypes.c_void_p, ctypes.POINTER(ctypes.c_char_p)
]
i2d_RSAPublicKey.restype = ctypes.c_int
def b64(x):
x = base64.b64encode(x)
res = []
for i in xrange(0, len(x), 64):
res.append(x[i:i+64]+"\n")
return "".join(res)
def bio_extract(bio):
buf = ctypes.c_char_p()
length = crypt.BIO_ctrl(bio, 3, 0, ctypes.byref(buf))
return ctypes.string_at(buf, length)
def make_key(e=65537):
rsa = crypt.RSA_generate_key(1024, e, None, None)
bio = BIO_new(BIO_s_mem())
crypt.PEM_write_bio_RSAPublicKey(bio, rsa)
pem = bio_extract(bio).rstrip()
crypt.BIO_free(bio)
buf = ctypes.create_string_buffer(1024)
pBuf = ctypes.c_char_p(ctypes.addressof(buf))
n = crypt.i2d_RSAPublicKey(rsa, ctypes.byref(pBuf))
s = buf.raw[:n]
digest = hashlib.sha1(s).digest()
return (rsa,pem,digest)
def signdesc(body, args_out=None):
rsa, ident_pem, id_digest = make_key()
_, onion_pem, _ = make_key()
hexdigest = binascii.b2a_hex(id_digest).upper()
fingerprint = " ".join(hexdigest[i:i+4] for i in range(0,len(hexdigest),4))
MAGIC = "<<<<<<MAGIC>>>>>>"
args = {
"RSA-IDENTITY" : ident_pem,
"ONION-KEY" : onion_pem,
"FINGERPRINT" : fingerprint,
"FINGERPRINT-NOSPACE" : hexdigest,
"RSA-SIGNATURE" : MAGIC
}
if args_out:
args_out.update(args)
body = body.format(**args)
idx = body.rindex("\nrouter-signature")
end_of_sig = body.index("\n", idx+1)
signed_part = body[:end_of_sig+1]
digest = hashlib.sha1(signed_part).digest()
assert len(digest) == 20
buf = ctypes.create_string_buffer(1024)
n = RSA_private_encrypt(20, digest, buf, rsa, 1)
sig = buf.raw[:n]
sig = """-----BEGIN SIGNATURE-----
%s
-----END SIGNATURE-----""" % b64(sig).rstrip()
body = body.replace(MAGIC, sig)
return body.rstrip()
def emit_ri(name, body, args_out=None):
print "const char %s[] ="%name
body = "\n".join(line.rstrip() for line in body.split("\n"))+"\n"
b = signdesc(body, args_out)
for line in b.split("\n"):
print ' "%s\\n"'%line
print " ;"
def emit_ei(name, body):
args = { 'NAME' : name }
emit_ri(name, body, args)
args['key'] = "\n".join(
' "%s\\n"'%line for line in args['RSA-IDENTITY'].split("\n"))
print """
const char {NAME}_fp[] = "{FINGERPRINT-NOSPACE}";
const char {NAME}_key[] =
{key};""".format(**args)
if 0:
emit_ri("minimal",
"""\
router fred 127.0.0.1 9001 0 9002
signing-key
{RSA-IDENTITY}
onion-key
{ONION-KEY}
published 2014-10-05 12:00:00
bandwidth 1000 1000 1000
reject *:*
router-signature
{RSA-SIGNATURE}
""")
if 0:
emit_ri("maximal",
"""\
router fred 127.0.0.1 9001 0 9002
signing-key
{RSA-IDENTITY}
onion-key
{ONION-KEY}
published 2014-10-05 12:00:00
bandwidth 1000 1000 1000
reject 127.0.0.1:*
accept *:80
reject *:*
ipv6-policy accept 80,100,101
ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw
uptime 1000
hibernating 0
unrecognized-keywords are just dandy in this format
platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series
contact O.W.Jones
fingerprint {FINGERPRINT}
read-history 900 1,2,3,4
write-history 900 1,2,3,4
extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
hidden-service-dir
allow-single-hop-exits
family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
caches-extra-info
or-address [::1:2:3:4]:9999
or-address 127.0.0.99:10000
opt fred is a fine router
router-signature
{RSA-SIGNATURE}
""")
if 0:
emit_ei("maximal",
"""\
extra-info bob {FINGERPRINT-NOSPACE}
published 2014-10-05 20:07:00
opt foobarbaz
read-history 900 1,2,3
write-history 900 1,2,3
dirreq-v2-ips 1
dirreq-v3-ips 100
dirreq-v3-reqs blahblah
dirreq-v2-share blahblah
dirreq-v3-share blahblah
dirreq-v2-resp djfkdj
dirreq-v3-resp djfkdj
dirreq-v2-direct-dl djfkdj
dirreq-v3-direct-dl djfkdj
dirreq-v2-tunneled-dl djfkdj
dirreq-v3-tunneled-dl djfkdj
dirreq-stats-end foobar
entry-ips jfsdfds
entry-stats-end ksdflkjfdkf
cell-stats-end FOO
cell-processed-cells FOO
cell-queued-cells FOO
cell-time-in-queue FOO
cell-circuits-per-decile FOO
exit-stats-end FOO
exit-kibibytes-written FOO
exit-kibibytes-read FOO
exit-streams-opened FOO
router-signature
{RSA-SIGNATURE}
""")
if 0:
emit_ei("minimal",
"""\
extra-info bob {FINGERPRINT-NOSPACE}
published 2014-10-05 20:07:00
router-signature
{RSA-SIGNATURE}
""")

View File

@ -3442,6 +3442,9 @@ download_status_increment_failure(download_status_t *dls, int status_code,
void
download_status_reset(download_status_t *dls)
{
if (dls->n_download_failures == IMPOSSIBLE_TO_DOWNLOAD)
return; /* Don't reset this. */
const smartlist_t *schedule = find_dl_schedule_and_len(
dls, get_options()->DirPort_set);

View File

@ -478,7 +478,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
list = smartlist_new();
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 0, 0,
annotation_buf)) {
annotation_buf, NULL)) {
SMARTLIST_FOREACH(list, routerinfo_t *, ri, {
msg_out = NULL;
tor_assert(ri->purpose == purpose);
@ -494,7 +494,7 @@ dirserv_add_multiple_descriptors(const char *desc, uint8_t purpose,
s = desc;
if (!router_parse_list_from_string(&s, NULL, list, SAVED_NOWHERE, 1, 0,
NULL)) {
NULL, NULL)) {
SMARTLIST_FOREACH(list, extrainfo_t *, ei, {
msg_out = NULL;

View File

@ -3288,8 +3288,8 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method)
{
smartlist_t *lst = microdescs_parse_from_string(output,
output+strlen(output), 0,
SAVED_NOWHERE);
output+strlen(output), 0,
SAVED_NOWHERE, NULL);
if (smartlist_len(lst) != 1) {
log_warn(LD_DIR, "We generated a microdescriptor we couldn't parse.");
SMARTLIST_FOREACH(lst, microdesc_t *, md, microdesc_free(md));

View File

@ -147,12 +147,17 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
int no_save, time_t listed_at,
smartlist_t *requested_digests256)
{
void * const DIGEST_REQUESTED = (void*)1;
void * const DIGEST_RECEIVED = (void*)2;
void * const DIGEST_INVALID = (void*)3;
smartlist_t *descriptors, *added;
const int allow_annotations = (where != SAVED_NOWHERE);
smartlist_t *invalid_digests = smartlist_new();
descriptors = microdescs_parse_from_string(s, eos,
allow_annotations,
where);
where, invalid_digests);
if (listed_at != (time_t)-1) {
SMARTLIST_FOREACH(descriptors, microdesc_t *, md,
md->last_listed = listed_at);
@ -161,19 +166,38 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_t *requested; /* XXXX actually we should just use a
digest256map */
requested = digestmap_new();
/* Set requested[d] to DIGEST_REQUESTED for every md we requested. */
SMARTLIST_FOREACH(requested_digests256, const char *, cp,
digestmap_set(requested, cp, (void*)1));
digestmap_set(requested, cp, DIGEST_REQUESTED));
/* Set requested[d] to DIGEST_INVALID for every md we requested which we
* will never be able to parse. Remove the ones we didn't request from
* invalid_digests.
*/
SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, cp) {
if (digestmap_get(requested, cp)) {
digestmap_set(requested, cp, DIGEST_INVALID);
} else {
tor_free(cp);
SMARTLIST_DEL_CURRENT(invalid_digests, cp);
}
} SMARTLIST_FOREACH_END(cp);
/* Update requested[d] to 2 for the mds we asked for and got. Delete the
* ones we never requested from the 'descriptors' smartlist.
*/
SMARTLIST_FOREACH_BEGIN(descriptors, microdesc_t *, md) {
if (digestmap_get(requested, md->digest)) {
digestmap_set(requested, md->digest, (void*)2);
digestmap_set(requested, md->digest, DIGEST_RECEIVED);
} else {
log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Received non-requested microdesc");
microdesc_free(md);
SMARTLIST_DEL_CURRENT(descriptors, md);
}
} SMARTLIST_FOREACH_END(md);
/* Remove the ones we got or the invalid ones from requested_digests256.
*/
SMARTLIST_FOREACH_BEGIN(requested_digests256, char *, cp) {
if (digestmap_get(requested, cp) == (void*)2) {
void *status = digestmap_get(requested, cp);
if (status == DIGEST_RECEIVED || status == DIGEST_INVALID) {
tor_free(cp);
SMARTLIST_DEL_CURRENT(requested_digests256, cp);
}
@ -181,6 +205,24 @@ microdescs_add_to_cache(microdesc_cache_t *cache,
digestmap_free(requested, NULL);
}
/* For every requested microdescriptor that was unparseable, mark it
* as not to be retried. */
if (smartlist_len(invalid_digests)) {
networkstatus_t *ns =
networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
if (ns) {
SMARTLIST_FOREACH_BEGIN(invalid_digests, char *, d) {
routerstatus_t *rs =
router_get_mutable_consensus_status_by_descriptor_digest(ns, d);
if (rs && tor_memeq(d, rs->descriptor_digest, DIGEST256_LEN)) {
download_status_mark_impossible(&rs->dl_status);
}
} SMARTLIST_FOREACH_END(d);
}
}
SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
smartlist_free(invalid_digests);
added = microdescs_add_list_to_cache(cache, descriptors, where, no_save);
smartlist_free(descriptors);
return added;

View File

@ -595,10 +595,10 @@ networkstatus_vote_find_entry_idx(networkstatus_t *ns,
/** As router_get_consensus_status_by_descriptor_digest, but does not return
* a const pointer. */
routerstatus_t *
router_get_mutable_consensus_status_by_descriptor_digest(
MOCK_IMPL(routerstatus_t *,
router_get_mutable_consensus_status_by_descriptor_digest,(
networkstatus_t *consensus,
const char *digest)
const char *digest))
{
if (!consensus)
consensus = current_consensus;
@ -628,8 +628,8 @@ router_get_consensus_status_by_descriptor_digest(networkstatus_t *consensus,
/** Given the digest of a router descriptor, return its current download
* status, or NULL if the digest is unrecognized. */
download_status_t *
router_get_dl_status_by_descriptor_digest(const char *d)
MOCK_IMPL(download_status_t *,
router_get_dl_status_by_descriptor_digest,(const char *d))
{
routerstatus_t *rs;
if (!current_ns_consensus)
@ -995,8 +995,8 @@ networkstatus_get_latest_consensus(void)
/** Return the latest consensus we have whose flavor matches <b>f</b>, or NULL
* if we don't have one. */
networkstatus_t *
networkstatus_get_latest_consensus_by_flavor(consensus_flavor_t f)
MOCK_IMPL(networkstatus_t *,
networkstatus_get_latest_consensus_by_flavor,(consensus_flavor_t f))
{
if (f == FLAV_NS)
return current_ns_consensus;
@ -1123,7 +1123,7 @@ networkstatus_copy_old_consensus_info(networkstatus_t *new_c,
rs_new->last_dir_503_at = rs_old->last_dir_503_at;
if (tor_memeq(rs_old->descriptor_digest, rs_new->descriptor_digest,
DIGEST_LEN)) {
DIGEST_LEN)) { /* XXXX Change this to digest256_len */
/* And the same descriptor too! */
memcpy(&rs_new->dl_status, &rs_old->dl_status,sizeof(download_status_t));
}

View File

@ -12,6 +12,8 @@
#ifndef TOR_NETWORKSTATUS_H
#define TOR_NETWORKSTATUS_H
#include "testsupport.h"
void networkstatus_reset_warnings(void);
void networkstatus_reset_download_failures(void);
int router_reload_consensus_networkstatus(void);
@ -35,16 +37,19 @@ routerstatus_t *networkstatus_vote_find_mutable_entry(networkstatus_t *ns,
const char *digest);
int networkstatus_vote_find_entry_idx(networkstatus_t *ns,
const char *digest, int *found_out);
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
MOCK_DECL(download_status_t *,router_get_dl_status_by_descriptor_digest,
(const char *d));
const routerstatus_t *router_get_consensus_status_by_id(const char *digest);
routerstatus_t *router_get_mutable_consensus_status_by_id(
const char *digest);
const routerstatus_t *router_get_consensus_status_by_descriptor_digest(
networkstatus_t *consensus,
const char *digest);
routerstatus_t *router_get_mutable_consensus_status_by_descriptor_digest(
networkstatus_t *consensus,
const char *digest);
MOCK_DECL(routerstatus_t *,
router_get_mutable_consensus_status_by_descriptor_digest,
(networkstatus_t *consensus, const char *digest));
const routerstatus_t *router_get_consensus_status_by_nickname(
const char *nickname,
int warn_if_unnamed);
@ -60,8 +65,8 @@ int consensus_is_waiting_for_certs(void);
int client_would_use_router(const routerstatus_t *rs, time_t now,
const or_options_t *options);
networkstatus_t *networkstatus_get_latest_consensus(void);
networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
consensus_flavor_t f);
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
(consensus_flavor_t f));
networkstatus_t *networkstatus_get_live_consensus(time_t now);
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
int flavor);

View File

@ -1958,6 +1958,7 @@ typedef struct download_status_t {
uint8_t n_download_failures; /**< Number of failures trying to download the
* most recent descriptor. */
download_schedule_bitfield_t schedule : 8;
} download_status_t;
/** If n_download_failures is this high, the download can never happen. */
@ -4997,7 +4998,8 @@ typedef enum was_router_added_t {
ROUTER_NOT_IN_CONSENSUS = -3,
ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS = -4,
ROUTER_AUTHDIR_REJECTS = -5,
ROUTER_WAS_NOT_WANTED = -6
ROUTER_WAS_NOT_WANTED = -6,
ROUTER_WAS_TOO_OLD = -7,
} was_router_added_t;
/********************************* routerparse.c ************************/

View File

@ -917,7 +917,7 @@ init_keys(void)
}
if (mydesc) {
was_router_added_t added;
ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL);
ri = router_parse_entry_from_string(mydesc, NULL, 1, 0, NULL, NULL);
if (!ri) {
log_err(LD_GENERAL,"Generated a routerinfo we couldn't parse.");
return -1;
@ -2447,7 +2447,7 @@ router_dump_router_to_string(routerinfo_t *router,
const char *cp;
routerinfo_t *ri_tmp;
cp = s_dup = tor_strdup(output);
ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL);
ri_tmp = router_parse_entry_from_string(cp, NULL, 1, 0, NULL, NULL);
if (!ri_tmp) {
log_err(LD_BUG,
"We just generated a router descriptor we can't parse.");
@ -2729,7 +2729,7 @@ extrainfo_dump_to_string(char **s_out, extrainfo_t *extrainfo,
s = smartlist_join_strings(chunks, "", 0, NULL);
cp = s_dup = tor_strdup(s);
ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL);
ei_tmp = extrainfo_parse_entry_from_string(cp, NULL, 1, NULL, NULL);
if (!ei_tmp) {
if (write_stats_to_extrainfo) {
log_warn(LD_GENERAL, "We just generated an extra-info descriptor "

View File

@ -2615,8 +2615,8 @@ router_get_by_descriptor_digest(const char *digest)
/** Return the signed descriptor for the router in our routerlist whose
* 20-byte extra-info digest is <b>digest</b>. Return NULL if no such router
* is known. */
signed_descriptor_t *
router_get_by_extrainfo_digest(const char *digest)
MOCK_IMPL(signed_descriptor_t *,
router_get_by_extrainfo_digest,(const char *digest))
{
tor_assert(digest);
@ -2937,12 +2937,12 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
}
/** Adds the extrainfo_t <b>ei</b> to the routerlist <b>rl</b>, if there is a
* corresponding router in rl-\>routers or rl-\>old_routers. Return true iff
* we actually inserted <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
static int
extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
* corresponding router in rl-\>routers or rl-\>old_routers. Return the status
* of inserting <b>ei</b>. Free <b>ei</b> if it isn't inserted. */
MOCK_IMPL(STATIC was_router_added_t,
extrainfo_insert,(routerlist_t *rl, extrainfo_t *ei))
{
int r = 0;
was_router_added_t r;
routerinfo_t *ri = rimap_get(rl->identity_map,
ei->cache_info.identity_digest);
signed_descriptor_t *sd =
@ -2956,9 +2956,11 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
if (!ri) {
/* This router is unknown; we can't even verify the signature. Give up.*/
r = ROUTER_NOT_IN_CONSENSUS;
goto done;
}
if (routerinfo_incompatible_with_extrainfo(ri, ei, sd, NULL)) {
r = (sd->extrainfo_is_bogus) ? ROUTER_BAD_EI : ROUTER_NOT_IN_CONSENSUS;
goto done;
}
@ -2968,7 +2970,7 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
ei_tmp = eimap_set(rl->extra_info_map,
ei->cache_info.signed_descriptor_digest,
ei);
r = 1;
r = ROUTER_ADDED_SUCCESSFULLY;
if (ei_tmp) {
rl->extrainfo_store.bytes_dropped +=
ei_tmp->cache_info.signed_descriptor_len;
@ -2976,7 +2978,7 @@ extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
}
done:
if (r == 0)
if (r != ROUTER_ADDED_SUCCESSFULLY)
extrainfo_free(ei);
#ifdef DEBUG_ROUTERLIST
@ -3251,7 +3253,7 @@ routerlist_reparse_old(routerlist_t *rl, signed_descriptor_t *sd)
ri = router_parse_entry_from_string(body,
body+sd->signed_descriptor_len+sd->annotations_len,
0, 1, NULL);
0, 1, NULL, NULL);
if (!ri)
return NULL;
memcpy(&ri->cache_info, sd, sizeof(signed_descriptor_t));
@ -3302,7 +3304,7 @@ routerlist_reset_warnings(void)
MOCK_IMPL(int,
router_descriptor_is_older_than,(const routerinfo_t *router, int seconds))
{
return router->cache_info.published_on < time(NULL) - seconds;
return router->cache_info.published_on < approx_time() - seconds;
}
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
@ -3477,7 +3479,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
router_descriptor_is_older_than(router, OLD_ROUTER_DESC_MAX_AGE)) {
*msg = "Router descriptor was really old.";
routerinfo_free(router);
return ROUTER_WAS_NOT_NEW;
return ROUTER_WAS_TOO_OLD;
}
/* We haven't seen a router with this identity before. Add it to the end of
@ -3498,21 +3500,18 @@ was_router_added_t
router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
int from_cache, int from_fetch)
{
int inserted;
was_router_added_t inserted;
(void)from_fetch;
if (msg) *msg = NULL;
/*XXXX023 Do something with msg */
inserted = extrainfo_insert(router_get_routerlist(), ei);
if (inserted && !from_cache)
if (WRA_WAS_ADDED(inserted) && !from_cache)
signed_desc_append_to_journal(&ei->cache_info,
&routerlist->extrainfo_store);
if (inserted)
return ROUTER_ADDED_SUCCESSFULLY;
else
return ROUTER_BAD_EI;
return inserted;
}
/** Sorting helper: return &lt;0, 0, or &gt;0 depending on whether the
@ -3807,7 +3806,8 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
"@source controller\n"
"@purpose %s\n", router_purpose_to_string(purpose));
if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0, annotation_buf))) {
if (!(ri = router_parse_entry_from_string(s, NULL, 1, 0,
annotation_buf, NULL))) {
log_warn(LD_DIR, "Error parsing router descriptor; dropping.");
*msg = "Couldn't parse router descriptor.";
return -1;
@ -3871,9 +3871,11 @@ router_load_routers_from_string(const char *s, const char *eos,
int from_cache = (saved_location != SAVED_NOWHERE);
int allow_annotations = (saved_location != SAVED_NOWHERE);
int any_changed = 0;
smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, routers, saved_location, 0,
allow_annotations, prepend_annotations);
allow_annotations, prepend_annotations,
invalid_digests);
routers_update_status_from_consensus_networkstatus(routers, !from_cache);
@ -3909,7 +3911,7 @@ router_load_routers_from_string(const char *s, const char *eos,
smartlist_add(changed, ri);
routerlist_descriptors_added(changed, from_cache);
smartlist_clear(changed);
} else if (WRA_WAS_REJECTED(r)) {
} else if (WRA_NEVER_DOWNLOADABLE(r)) {
download_status_t *dl_status;
dl_status = router_get_dl_status_by_descriptor_digest(d);
if (dl_status) {
@ -3920,6 +3922,27 @@ router_load_routers_from_string(const char *s, const char *eos,
}
} SMARTLIST_FOREACH_END(ri);
SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
/* This digest is never going to be parseable. */
base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
if (requested_fingerprints && descriptor_digests) {
if (! smartlist_contains_string(requested_fingerprints, fp)) {
/* But we didn't ask for it, so we should assume shennanegans. */
continue;
}
smartlist_string_remove(requested_fingerprints, fp);
}
download_status_t *dls;
dls = router_get_dl_status_by_descriptor_digest((char*)bad_digest);
if (dls) {
log_info(LD_GENERAL, "Marking router with descriptor %s as unparseable, "
"and therefore undownloadable", fp);
download_status_mark_impossible(dls);
}
} SMARTLIST_FOREACH_END(bad_digest);
SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
smartlist_free(invalid_digests);
routerlist_assert_ok(routerlist);
if (any_changed)
@ -3943,15 +3966,18 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
smartlist_t *extrainfo_list = smartlist_new();
const char *msg;
int from_cache = (saved_location != SAVED_NOWHERE);
smartlist_t *invalid_digests = smartlist_new();
router_parse_list_from_string(&s, eos, extrainfo_list, saved_location, 1, 0,
NULL);
NULL, invalid_digests);
log_info(LD_DIR, "%d elements to add", smartlist_len(extrainfo_list));
SMARTLIST_FOREACH_BEGIN(extrainfo_list, extrainfo_t *, ei) {
was_router_added_t added =
router_add_extrainfo_to_routerlist(ei, &msg, from_cache, !from_cache);
uint8_t d[DIGEST_LEN];
memcpy(d, ei->cache_info.signed_descriptor_digest, DIGEST_LEN);
if (WRA_WAS_ADDED(added) && requested_fingerprints) {
char fp[HEX_DIGEST_LEN+1];
base16_encode(fp, sizeof(fp), descriptor_digests ?
@ -3963,9 +3989,39 @@ router_load_extrainfo_from_string(const char *s, const char *eos,
* so long as we would have wanted them anyway. Since we always fetch
* all the extrainfos we want, and we never actually act on them
* inside Tor, this should be harmless. */
} else if (WRA_NEVER_DOWNLOADABLE(added)) {
signed_descriptor_t *sd = router_get_by_extrainfo_digest((char*)d);
if (sd) {
log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
"unparseable, and therefore undownloadable",
hex_str((char*)d,DIGEST_LEN));
download_status_mark_impossible(&sd->ei_dl_status);
}
}
} SMARTLIST_FOREACH_END(ei);
SMARTLIST_FOREACH_BEGIN(invalid_digests, const uint8_t *, bad_digest) {
/* This digest is never going to be parseable. */
char fp[HEX_DIGEST_LEN+1];
base16_encode(fp, sizeof(fp), (char*)bad_digest, DIGEST_LEN);
if (requested_fingerprints) {
if (! smartlist_contains_string(requested_fingerprints, fp)) {
/* But we didn't ask for it, so we should assume shennanegans. */
continue;
}
smartlist_string_remove(requested_fingerprints, fp);
}
signed_descriptor_t *sd =
router_get_by_extrainfo_digest((char*)bad_digest);
if (sd) {
log_info(LD_GENERAL, "Marking extrainfo with descriptor %s as "
"unparseable, and therefore undownloadable", fp);
download_status_mark_impossible(&sd->ei_dl_status);
}
} SMARTLIST_FOREACH_END(bad_digest);
SMARTLIST_FOREACH(invalid_digests, uint8_t *, d, tor_free(d));
smartlist_free(invalid_digests);
routerlist_assert_ok(routerlist);
router_rebuild_store(0, &router_get_routerlist()->extrainfo_store);

View File

@ -82,7 +82,8 @@ int hexdigest_to_digest(const char *hexdigest, char *digest);
const routerinfo_t *router_get_by_id_digest(const char *digest);
routerinfo_t *router_get_mutable_by_digest(const char *digest);
signed_descriptor_t *router_get_by_descriptor_digest(const char *digest);
signed_descriptor_t *router_get_by_extrainfo_digest(const char *digest);
MOCK_DECL(signed_descriptor_t *,router_get_by_extrainfo_digest,
(const char *digest));
signed_descriptor_t *extrainfo_get_by_descriptor_digest(const char *digest);
const char *signed_descriptor_get_body(const signed_descriptor_t *desc);
const char *signed_descriptor_get_annotations(const signed_descriptor_t *desc);
@ -99,6 +100,7 @@ void routerlist_reset_warnings(void);
static int WRA_WAS_ADDED(was_router_added_t s);
static int WRA_WAS_OUTDATED(was_router_added_t s);
static int WRA_WAS_REJECTED(was_router_added_t s);
static int WRA_NEVER_DOWNLOADABLE(was_router_added_t s);
/** Return true iff the outcome code in <b>s</b> indicates that the descriptor
* was added. It might still be necessary to check whether the descriptor
* generator should be notified.
@ -115,7 +117,8 @@ WRA_WAS_ADDED(was_router_added_t s) {
*/
static INLINE int WRA_WAS_OUTDATED(was_router_added_t s)
{
return (s == ROUTER_WAS_NOT_NEW ||
return (s == ROUTER_WAS_TOO_OLD ||
s == ROUTER_WAS_NOT_NEW ||
s == ROUTER_NOT_IN_CONSENSUS ||
s == ROUTER_NOT_IN_CONSENSUS_OR_NETWORKSTATUS);
}
@ -125,6 +128,14 @@ static INLINE int WRA_WAS_REJECTED(was_router_added_t s)
{
return (s == ROUTER_AUTHDIR_REJECTS);
}
/** Return true iff the outcome code in <b>s</b> indicates that the descriptor
* was flat-out rejected. */
static INLINE int WRA_NEVER_DOWNLOADABLE(was_router_added_t s)
{
return (s == ROUTER_AUTHDIR_REJECTS ||
s == ROUTER_BAD_EI ||
s == ROUTER_WAS_TOO_OLD);
}
was_router_added_t router_add_to_routerlist(routerinfo_t *router,
const char **msg,
int from_cache,
@ -215,6 +226,9 @@ STATIC void scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
MOCK_DECL(int, router_descriptor_is_older_than, (const routerinfo_t *router,
int seconds));
MOCK_DECL(STATIC was_router_added_t, extrainfo_insert,
(routerlist_t *rl, extrainfo_t *ei));
#endif
#endif

View File

@ -911,7 +911,9 @@ find_start_of_next_router_or_extrainfo(const char **s_ptr,
* descriptor in the signed_descriptor_body field of each routerinfo_t. If it
* isn't SAVED_NOWHERE, remember the offset of each descriptor.
*
* Returns 0 on success and -1 on failure.
* Returns 0 on success and -1 on failure. Adds a digest to
* <b>invalid_digests_out</b> for every entry that was unparseable or
* invalid. (This may cause duplicate entries.)
*/
int
router_parse_list_from_string(const char **s, const char *eos,
@ -919,7 +921,8 @@ router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int want_extrainfo,
int allow_annotations,
const char *prepend_annotations)
const char *prepend_annotations,
smartlist_t *invalid_digests_out)
{
routerinfo_t *router;
extrainfo_t *extrainfo;
@ -939,6 +942,9 @@ router_parse_list_from_string(const char **s, const char *eos,
tor_assert(eos >= *s);
while (1) {
char raw_digest[DIGEST_LEN];
int have_raw_digest = 0;
int dl_again = 0;
if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
break;
@ -955,18 +961,20 @@ router_parse_list_from_string(const char **s, const char *eos,
if (have_extrainfo && want_extrainfo) {
routerlist_t *rl = router_get_routerlist();
have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
extrainfo = extrainfo_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
rl->identity_map);
rl->identity_map, &dl_again);
if (extrainfo) {
signed_desc = &extrainfo->cache_info;
elt = extrainfo;
}
} else if (!have_extrainfo && !want_extrainfo) {
have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
router = router_parse_entry_from_string(*s, end,
saved_location != SAVED_IN_CACHE,
allow_annotations,
prepend_annotations);
prepend_annotations, &dl_again);
if (router) {
log_debug(LD_DIR, "Read router '%s', purpose '%s'",
router_describe(router),
@ -975,6 +983,9 @@ router_parse_list_from_string(const char **s, const char *eos,
elt = router;
}
}
if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
}
if (!elt) {
*s = end;
continue;
@ -1068,11 +1079,17 @@ find_single_ipv6_orport(const smartlist_t *list,
* around when caching the router.
*
* Only one of allow_annotations and prepend_annotations may be set.
*
* If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
* if it's okay to try to download a descriptor with this same digest again,
* and 0 if it isn't. (It might not be okay to download it again if part of
* the part covered by the digest is invalid.)
*/
routerinfo_t *
router_parse_entry_from_string(const char *s, const char *end,
int cache_copy, int allow_annotations,
const char *prepend_annotations)
const char *prepend_annotations,
int *can_dl_again_out)
{
routerinfo_t *router = NULL;
char digest[128];
@ -1083,6 +1100,9 @@ router_parse_entry_from_string(const char *s, const char *end,
size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
int ok = 1;
memarea_t *area = NULL;
/* Do not set this to '1' until we have parsed everything that we intend to
* parse that's covered by the hash. */
int can_dl_again = 0;
tor_assert(!allow_annotations || !prepend_annotations);
@ -1389,19 +1409,21 @@ router_parse_entry_from_string(const char *s, const char *end,
verified_digests = digestmap_new();
digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
#endif
if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
"router descriptor") < 0)
goto err;
if (!router->or_port) {
log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
goto err;
}
/* We've checked everything that's covered by the hash. */
can_dl_again = 1;
if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
"router descriptor") < 0)
goto err;
if (!router->platform) {
router->platform = tor_strdup("<unknown>");
}
goto done;
err:
@ -1418,6 +1440,8 @@ router_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "routerinfo");
memarea_drop_all(area);
}
if (can_dl_again_out)
*can_dl_again_out = can_dl_again;
return router;
}
@ -1426,10 +1450,16 @@ router_parse_entry_from_string(const char *s, const char *end,
* <b>cache_copy</b> is true, make a copy of the extra-info document in the
* cache_info fields of the result. If <b>routermap</b> is provided, use it
* as a map from router identity to routerinfo_t when looking up signing keys.
*
* If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
* if it's okay to try to download an extrainfo with this same digest again,
* and 0 if it isn't. (It might not be okay to download it again if part of
* the part covered by the digest is invalid.)
*/
extrainfo_t *
extrainfo_parse_entry_from_string(const char *s, const char *end,
int cache_copy, struct digest_ri_map_t *routermap)
int cache_copy, struct digest_ri_map_t *routermap,
int *can_dl_again_out)
{
extrainfo_t *extrainfo = NULL;
char digest[128];
@ -1439,6 +1469,9 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
routerinfo_t *router = NULL;
memarea_t *area = NULL;
const char *s_dup = s;
/* Do not set this to '1' until we have parsed everything that we intend to
* parse that's covered by the hash. */
int can_dl_again = 0;
if (!end) {
end = s + strlen(s);
@ -1498,6 +1531,9 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
goto err;
}
/* We've checked everything that's covered by the hash. */
can_dl_again = 1;
if (routermap &&
(router = digestmap_get((digestmap_t*)routermap,
extrainfo->cache_info.identity_digest))) {
@ -1540,6 +1576,8 @@ extrainfo_parse_entry_from_string(const char *s, const char *end,
DUMP_AREA(area, "extrainfo");
memarea_drop_all(area);
}
if (can_dl_again_out)
*can_dl_again_out = can_dl_again;
return extrainfo;
}
@ -4006,12 +4044,15 @@ find_start_of_next_microdesc(const char *s, const char *eos)
* If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
* descriptor in the body field of each microdesc_t.
*
* Return all newly
* parsed microdescriptors in a newly allocated smartlist_t. */
* Return all newly parsed microdescriptors in a newly allocated
* smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
* microdesc digest to it for every microdesc that we found to be badly
* formed. (This may cause duplicates) */
smartlist_t *
microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
saved_location_t where)
saved_location_t where,
smartlist_t *invalid_digests_out)
{
smartlist_t *tokens;
smartlist_t *result;
@ -4033,16 +4074,12 @@ microdescs_parse_from_string(const char *s, const char *eos,
tokens = smartlist_new();
while (s < eos) {
int okay = 0;
start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
if (!start_of_next_microdesc)
start_of_next_microdesc = eos;
if (tokenize_string(area, s, start_of_next_microdesc, tokens,
microdesc_token_table, flags)) {
log_warn(LD_DIR, "Unparseable microdescriptor");
goto next;
}
md = tor_malloc_zero(sizeof(microdesc_t));
{
const char *cp = tor_memstr(s, start_of_next_microdesc-s,
@ -4057,6 +4094,13 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->body = (char*)cp;
md->off = cp - start;
}
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
if (tokenize_string(area, s, start_of_next_microdesc, tokens,
microdesc_token_table, flags)) {
log_warn(LD_DIR, "Unparseable microdescriptor");
goto next;
}
if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
if (parse_iso_time(tok->args[0], &md->last_listed)) {
@ -4113,12 +4157,15 @@ microdescs_parse_from_string(const char *s, const char *eos,
md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
}
crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
smartlist_add(result, md);
okay = 1;
md = NULL;
next:
if (! okay && invalid_digests_out) {
smartlist_add(invalid_digests_out,
tor_memdup(md->digest, DIGEST256_LEN));
}
microdesc_free(md);
md = NULL;

View File

@ -29,14 +29,17 @@ int router_parse_list_from_string(const char **s, const char *eos,
saved_location_t saved_location,
int is_extrainfo,
int allow_annotations,
const char *prepend_annotations);
const char *prepend_annotations,
smartlist_t *invalid_digests_out);
routerinfo_t *router_parse_entry_from_string(const char *s, const char *end,
int cache_copy,
int allow_annotations,
const char *prepend_annotations);
const char *prepend_annotations,
int *can_dl_again_out);
extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end,
int cache_copy, struct digest_ri_map_t *routermap);
int cache_copy, struct digest_ri_map_t *routermap,
int *can_dl_again_out);
MOCK_DECL(addr_policy_t *, router_parse_addr_policy_item_from_string,
(const char *s, int assume_action));
version_status_t tor_version_is_obsolete(const char *myversion,
@ -60,7 +63,8 @@ ns_detached_signatures_t *networkstatus_parse_detached_signatures(
smartlist_t *microdescs_parse_from_string(const char *s, const char *eos,
int allow_annotations,
saved_location_t where);
saved_location_t where,
smartlist_t *invalid_digests_out);
authority_cert_t *authority_cert_parse_from_string(const char *s,
const char **end_of_string);

View File

@ -0,0 +1,192 @@
static const char EX_EI_MINIMAL[] =
"extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
"V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
"zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_MINIMAL_FP[] = "3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B";
static const char EX_EI_MINIMAL_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALSppIF3t3wOAm4fzxRvK+q/wh1gGAWwS0JEn8d+c/x+rt1oQabGkqsB\n"
"GU6rz1z1AN02W0P2+EcyJQVBjGR3gHQNoDGx0KIdnr3caGAw3XmQXrJLPaViEk28\n"
"RJMxx6umpP27YKSyEMHgVTDXblKImT0mE7fVOx8tD0EWRYazmp4NAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_MAXIMAL[] =
"extra-info bob FF8248FE780A7236D3FA5D62DEA642055135F942\n"
"published 2014-10-05 20:07:00\n"
"opt foobarbaz\n"
"read-history 900 1,2,3\n"
"write-history 900 1,2,3\n"
"dirreq-v2-ips 1\n"
"dirreq-v3-ips 100\n"
"dirreq-v3-reqs blahblah\n"
"dirreq-v2-share blahblah\n"
"dirreq-v3-share blahblah\n"
"dirreq-v2-resp djfkdj\n"
"dirreq-v3-resp djfkdj\n"
"dirreq-v2-direct-dl djfkdj\n"
"dirreq-v3-direct-dl djfkdj\n"
"dirreq-v2-tunneled-dl djfkdj\n"
"dirreq-v3-tunneled-dl djfkdj\n"
"dirreq-stats-end foobar\n"
"entry-ips jfsdfds\n"
"entry-stats-end ksdflkjfdkf\n"
"cell-stats-end FOO\n"
"cell-processed-cells FOO\n"
"cell-queued-cells FOO\n"
"cell-time-in-queue FOO\n"
"cell-circuits-per-decile FOO\n"
"exit-stats-end FOO\n"
"exit-kibibytes-written FOO\n"
"exit-kibibytes-read FOO\n"
"exit-streams-opened FOO\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"ZO79bLlWVNIruCnWW9duDcOKydPWbL5DfrpUv5IRLF4MMFoacMUdJPDUs9e+wY2C\n"
"zndHe6i2JK7yKJj+uCOSC8cx61OLG+kVxMLJ/qhA4H5thrYb+GpzMKwbHzQc3PTH\n"
"zHRzj041iWXTL7/DMaQlpJOBoac/wTSIKzoV2B00jBw=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_MAXIMAL_FP[] = "FF8248FE780A7236D3FA5D62DEA642055135F942";
static const char EX_EI_MAXIMAL_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANSpkYhHUW1EqodY4d3JRbvEM1vjjR/vEE8gjONiJ5t2Sten53jzt8bh\n"
"8/VJn7pQGs8zR5CIxCw4P68xMtZJJedS3hhjqubheOE/yW1DtpkiCf+zVEaLpeA8\n"
"fYQChkRICnR/BZd4W9bbohLVII5ym2PaJt2ihB3FeVZIsGXm4wxhAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_BAD_SIG1[] =
"extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
"V3l9u1uUdGiUPOl8j+hXXw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
"zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_SIG2[] =
"extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
"published 2014-10-06 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
"V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
"zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2R3EA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_SIG3[] =
"extra-info bob 3E1B2DC141F2B7C6A0F3C4ED9A14A9C35762E24B\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"K5GAkVjpUlofL78NIOE1VDxFn8yYbHK50rVuZG2HxqG/727bon+uMprv4MHjfDcP\n"
"V3l9u1uUdGiUPOl8j+hRNw4z/ODeCj/24r2+L32MTjyfUhK49Ld2IlK9iZKlgKYi\n"
"zyoatxdAjU8Xc5WPX692HO4/R9CGLsUfYcEEFU2=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_FP[] =
"extra-info bob C34293303F0F1E42CB14E593717B834E8E53797D8888\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"IDA8ryUYeMx7+Au/xQmX7Y8fXksoHUOXmePND2JYM4rPfishQJ1LpQ15KrolOZDH\n"
"FVIk3RmCefNlJeS1/UgWPcU8u2nGw1YQuRBHF4ViTmZ0OevI1pTsSApl4+oIx2dy\n"
"DGgCQmKfMbaOixIK8Ioh1Z2NUfMkjbUUE2WWgFTAsac=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_FP_FP[] = "C34293303F0F1E42CB14E593717B834E8E53797D";
static const char EX_EI_BAD_FP_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKXMSbif4fG+BW/5lIq5V1tMRondIUfKiNizp0E6EcBw5LvYfQV6zrj8\n"
"HmMFbB/WGf9XGVMxIBzxzeQBRvCQJh+0QH7+ju5/isIHJZsACMILepr6ywmCcjVU\n"
"iYRtC8zGQLqfkf2cNoo7AhcI5i/YzyW2u1zmbPX5J+8sUErfxydbAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_BAD_NICKNAME[] =
"extra-info bobhasaverylongnameandidontthinkweshouldlethim A4EA2389A52459B3F7C7121A46012F098BDFC2A4\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"e2wLJFThRMGawxKrQPuH2XCLek/LJsg4XOB8waAjE0xdHOrzjur9x1jIxy7DVU6t\n"
"z1edbIoL24qucMJvFy2xjSQhFRX4OsyNc0nWr3LfJnTW9aEmxuwXM+mltUD2uFN1\n"
"2vYOIQjUmJwS2yfeSKnhXEl2PWVUmgzYL3r4S5kHco4=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_NICKNAME_FP[] = "A4EA2389A52459B3F7C7121A46012F098BDFC2A4";
static const char EX_EI_BAD_NICKNAME_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKfq7oxD1kMu1+zeG2UVXN4vOu6FDp0V/olA3ttmXpUCgCiBxWTgtwNl\n"
"nPf0HcKMaCp/0D9XrbhvIoOsg0OTf1TcJfGsA/zPG7jrWYa4xhD50KYvty9EINK9\n"
"/UBWNSyXCFDMqnddb/LZ8+VgttmxfYkpeRzSSmDijN3RbOvYJhhBAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
const char EX_EI_BAD_TOKENS[] =
"extra-info bob 6F314FB01A31162BD5E473D4977AC570DC5B86BB\n"
"published 2014-10-05 20:07:00\n"
"published 2014-10-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"lhRIafrkKoQmnUoBLiq4XC8XKXrleGJZ5vefkLcgjOJ5IffsvVdIA7Vqq/ISbPrG\n"
"b/Zs0sJNL6naHPxJBglgHJqksSyiYHaeOetXg2Rb+vZ1v2S5BrVgk1nPMDhyIzqc\n"
"zU7eCxFf/1sXKtWlEKxGdX4LmVfnIln5aI31Bc4xRrE=\n"
"-----END SIGNATURE-----\n"
;
const char EX_EI_BAD_TOKENS_FP[] = "6F314FB01A31162BD5E473D4977AC570DC5B86BB";
const char EX_EI_BAD_TOKENS_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAL7Z8tz45Tb4tnEFS2sAyjubBV/giSfZdmXRkDV8Jo4xqWqhWFJn7+zN\n"
"AXBWBThGeVH2WXrpz5seNJXgZJPxMTMsrnSCGcRXZw0Npti2MkLuQ6+prZa+OPwE\n"
"OyC6jivtAaY/o9iYQjDC2avLXD3N4LvoygyF418KnNcjbzuFygffAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_BAD_START[] =
"published 2014-10-05 20:07:00\n"
"extra-info bob 5CCCACE71A9BDB5E8E0C942AB3407452350434C0\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"BOiWgexqCAMZ8uyJ7jwBwRkz7Ox8cT4BImkmkV3bQiZgcWvPiYA3EnCm2ye48Ldg\n"
"zBST2p6zJM5o4MEDYGMxfViS86Abj/z7DOY1gtLhjmAaVjIIpXc3koxEZtzCecqy\n"
"JQz6xEg9/KoEuoT0DRrfYQ+KtQfzBDWrotfOvEa1rvc=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_START_FP[] = "5CCCACE71A9BDB5E8E0C942AB3407452350434C0";
static const char EX_EI_BAD_START_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAK2OCIfM6Cin/lq99Z3w9tl6HeyGlkBZu9MQEPHxqGIHTq78lIC1UkrC\n"
"6NTqlrHBV9dmfzdwJn4GgMWsCZafL0FPIH3HNyNKUxLgyjixyKljHx2rfErSfOxI\n"
"bMoOGBKv7m1EZZ0O5uG9ly9MBiNGdJyLdlnVvH7wSCnYciizpO4lAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";
static const char EX_EI_BAD_PUBLISHED[] =
"extra-info bob E67C477E3536BDE348BD407426D9679E5AE0BC16\n"
"published 2014-99-05 20:07:00\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"l45IziBaXRKIjPAIUogMFNjQgH6k6Vm0+6r5+oByr4sP+B3ufNdUA6+WqBs43F0Z\n"
"IqcJiT9nFn0DuNd/liOyOCixppDLx5h5NrhoGqcT3ySADEEXhzjlmc35TI3YBNVO\n"
"v98fotmwIEg9YRWVGPg6XuIn2PRyiboFyjUpaYGCV0Q=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_EI_BAD_PUBLISHED_FP[] = "E67C477E3536BDE348BD407426D9679E5AE0BC16";
static const char EX_EI_BAD_PUBLISHED_KEY[] =
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAL7q8GEI18iv8Fo0QbNHmFatQ2FNacalPldpmKUdMJYEVZtdOR0nhcrY\n"
"BvG6303md3INygg+KP49RvWEJR/cU4RZ9QfHpORxH2OocMyRedw2rLex2E7jNNSi\n"
"52yd1sHFYI8ZQ4aff+ZHUjJUGKRyqpbc8okVbq/Rl7vug0dd12eHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n";

View File

@ -0,0 +1,668 @@
/* This one actually succeeds */
static const char EX_RI_MINIMAL[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
"SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
"LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
"ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
"h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
"fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
"CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
"-----END SIGNATURE-----\n";
/* So does this, and it's bigger. */
static const char EX_RI_MAXIMAL[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANNI56H+b7SW5LMzvXyY5NJzXszsHZZ4O1CPm4CePhBsAz1r0s1JYJ1F\n"
"Anrc0mEcLtmj0c5+HnhPBNrfpjO6G94Wp3NZMVykHDhfNVDBRyFZMroG8/GlysYB\n"
"MQPGQYR0xBgiuclNHoyk/vygQhZekumamu2O86EIPcfg9LhGIgEbAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALvuNVSmg6R9USFbQcNbRjMCJAV0Rwdv0DlS6Rl02ibJgb01G7v391xE\n"
"d9Njzgf93n8gOrE195bkUbvS6k/DM3HFGgArq6q9AZ2LTbu3KbAYy1YPsSIh07kB\n"
"/8kkvRRGx37X9WGZU3j5VUEuzqI//xDE9lbanlnnFXpnb6ymehDJAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject 127.0.0.1:*\n"
"accept *:80\n"
"reject *:*\n"
"ipv6-policy accept 80,100,101\n"
"ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVw\n"
"uptime 1000\n"
"hibernating 0\n"
"unrecognized-keywords are just dandy in this format\n"
"platform Tor 0.2.4.23 on a Banana PC Jr 6000 Series\n"
"contact O.W.Jones\n"
"fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
"read-history 900 1,2,3,4\n"
"write-history 900 1,2,3,4\n"
"extra-info-digest AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"
"hidden-service-dir\n"
"allow-single-hop-exits\n"
"family $AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA $BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"
"caches-extra-info\n"
"or-address [::1:2:3:4]:9999\n"
"or-address 127.0.0.99:10000\n"
"opt fred is a fine router\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"x5cxL2h2UsEKk2OVnCTxOF8a89HAe/HwQnSlrBy8+l0YdVCcePDJhm1WyWU7ToHZ\n"
"K8auwreuw+u/n14sQHPYrM9NQE689hP4LC9AYOnrCnMHysfVqKuou+DSKYYRgs0D\n"
"ySCmJ9p+xekfmms+JBmS5o5DVo48VGlG0VksegoB264=\n"
"-----END SIGNATURE-----\n"
;
/* I've messed with 12 bits of the signature on this one */
static const char EX_RI_BAD_SIG1[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
"SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
"LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
"ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
"h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
"fkIprv9UXqkv5iY+pXSYXX12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
"CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
"-----END SIGNATURE-----\n";
/* This is a good signature of the wrong data: I changed 'published' */
static const char EX_RI_BAD_SIG2[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAObzT4opT9uaThByupbb96tYxVpGxzL9CRPKUcU0beGpHyognD9USHWc\n"
"SpSpKfBL5P3xr2i/XTs34M4UTbT9PE7bVyxv7RD/BZmI4gc8R3PMU77xxbpEU5bK\n"
"LF3QUPpuB88m/2fXUGgMNVDc5MIq6pod2NRoDpeU7WA8T3ewXzK5AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM1QKsQiup9DNMCgNeE2FkAhCWzpMZKCn1nNlZbDGfE3Z22ex6bdWWY6\n"
"ocEZ3JZDsZsnaZrdYxrL3Mquq7MbHdfx90EdlOvDRP1SAIbZ55mLR77fZTu4BKd/\n"
"h9BC6I26uZE0QavFq3+BhoVVhVn5Mqv05nR9CeUMSSZLxw/RJm4DAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:01\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Ft/y3JXowjItgfTHwYcZzuUgXrskluoINW5sr+GQoNYE2F4sT8o0tBBJwqJ6FwKd\n"
"fkIprv9UXqkv5iY+pXSYSI12mY1K5GMNkXiObk46NjuoNNP9l8oidhO6eNfcE+k3\n"
"CRIYS4FbBaD0fWUSwgMuo0Bp83/Wzp3B9ytEBh0/624=\n"
"-----END SIGNATURE-----\n";
/* This one will fail while tokenizing the first line. */
static const char EX_RI_BAD_TOKENS[] =
"router bob\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANGCgvZc+JRtAzuzk3gBD2rH9SHrXzjJ1wqdU3tLKr7FamKCMI2pLwSA\n"
"FZUpTuSqB9wJ/iVcYws+/kA3FjLqgPtzJFI0SVLvQcz5oIC1rEWpuP6t88duMlO9\n"
"flOUzmYu29sBffrXkQr8pesYvakyXArOJVeRR7fSvouneV5aDYWrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAML+pYZoYc+whKLijupd63xn0gzlEQqe7k07x/lWMqWFT37FfG6YeNr5\n"
"fpFoo77FDfuFaL+VfPfI8i88g157hcPKBVX6OyRH54+l5By0tN91S0H+abXjXQpv\n"
"U/Bvmul+5QpUeVJa1nPg71HRIauoDnBNexUQ7Xf/Bwb2xCt+IJ6DAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"tbxtYYzyVqi6w6jz1k8NPjFvZaSNR0WzixVTTvKKGoMPx/6+Z8QAFK1ILzRUVucB\n"
"nRhmZMFaPr3vREMErLRE47ODAzwoBCE9C+vYFvROhgfzuQ3cYXla+4sMaRXYZzjH\n"
"PQ82bTwvSbHsR8fTTgePD/Ac082WxXTGpx6HOLBfNsQ=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_PUBLISHED[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMoipSwZgTG6SpSOm6ENbyALS1Ljqqa1LSGmtHSRfGYgUQGWZXERXKQj\n"
"P5ql6o7EbGr1wnispGW/KB8Age09jGDvd/oGhQ9TDFluhLZon3obkZSFw7f9iA7Q\n"
"s29rNxoeXXLZVyS7+sux70b8x2Dt4CeG8GA8nQLljy1euwU+qYYJAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAPzfzQ+2WFMUvnB3z0xD+zwczWcFyYYNW8Lj7/aRGSNN2DICp5uzSjKq\n"
"qkYQ+C8jG21+MR2PE+ZBmq6CL5mvlFKlWKouXUlN7BejwWf2gw0UYag0SYctae1b\n"
"bu8NuUEvdeGWg5Odgs+abH7U9S0hEtjKrmE5vvJS5L841IcaPLCFAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 99:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"G92pnwCIXGJ9Q0fI9y4m/fHpWCsD0Hnk81/6T4TmRH3jt77fc0uRdomUOC5id4kz\n"
"J2M4vqXwRs5OK+eaPbtxf8Yv6FPmB3OBNCIhwNHIIqzKQStHUhPxD3P6j8uJFwot\n"
"/CNGciDN+owZ2DzwrXpszDfzcyp/nmwhApbi3W601vY=\n"
"-----END SIGNATURE-----\n"
;
/* Bandwidth field isn't an integer. */
static const char EX_RI_BAD_BANDWIDTH[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAN32LAvXQaq0p554FcL4LVwnxyiZvscfuFnfpXwWTDRJJHd2+JCttWIx\n"
"v+eW7dNq+rq/tzSzaZwnp8b4V2skLRojSt6UUHD234eZcsPwUNhSr0y1eMuoZbnV\n"
"UBBPevpuXea85aSFEXXRlIpQfvFc43y3/UFoRzo5iMPqReo2uQ4BAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMBuF1GvOyVcRDNjzlEmGHJkTA7qkaWgTp33NSY/DPEJoahg0Qswuh2w\n"
"1YCBqem6Txp+/Vl9hoUoUGwb7Vwq0+YDMSyr0z3Ih2NcNjOMZPVtjJuv+3wXrQC8\n"
"LPpCpfU9m9QvhQ7f9zprEqUHOQTT0v5j2a5bpfd++6LFxrMUNwbfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth hello world today\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
"SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
"ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
"-----END SIGNATURE-----\n"
;
/* Onion key is actually a signature. */
static const char EX_RI_BAD_ONIONKEY1[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANByIdFOKA3r2nnWyLjdZE8oGHqJE62T1zjW/nsCzCJQ8/kBMRYeGDu4\n"
"SeUJJ2rsh2t3PNzkqJM14f4DKmc2q76STsOW0Zcj70Bjhxb9r/OfyELVsi+x3CsE\n"
"Zo/W4JtdlVFjqevhODJdyFNLKOvqwG7sZo/K++Hx01Iu0zXLeg8nAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"svABTGDNJOgaiPLqDlkRU6ldYJcoEe2qHlr4O30lVM2hS3Gg6o4QARL7QRt7VepT\n"
"SruR6pE83xOr7/5Ijq5PlamS4WtODMJSH3DXT2hM5dYYrEX5jsJNZTQ+cYwPQI3y\n"
"ykuvQIutH6ipz5MYc9n0GWAzDjLq1G8wlcEfFXQLD10=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Cc/Y22KFvxXPXZtjvGIyQdjm4EMhXVXJEBwt8PvK7qlO1AgiVjEBPkUrTQQ/paLQ\n"
"lmeCN6jEVcZ8lNiVZgzRQ/2mTO3xLBPj26UNSDuouUwZ01tZ4wPENylNYnLKv5hg\n"
"gYARg/nXEJiTVe9LHl99Hr9EWWruRG2wFQjjTILaWzI=\n"
"-----END SIGNATURE-----\n"
;
/* Onion key has exponent 3 */
static const char EX_RI_BAD_ONIONKEY2[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKP1kWHsH/BZhNSZmn0FyzIrAHtMl1IVPzc7ABbx+kK+IIEMD9k1fy2h\n"
"AP2JTm2UmJDUwutVxPsxmndI+9QsRDpu33E5Ai4U1Rb6Qu+2BRj43YAyg414caIu\n"
"J5LLn6bOzt7gtz0+q69WHbnwgI4zUgUbwYpwoB7k0dRY97xip9fHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGHAoGBANBKlyoqApWzG7UzmXcxhXM4T370FbN1edPbw4WAczBDXJslXCU9Xk1r\n"
"fKfoi/+WiTGvH7RcZWPm7wnThq2u2EAO/IPPcLE9cshLBkK28EvDg5K/WsYedbY9\n"
"1Gou+7ZSwMEPv2b13c7eWnSW1YvFa64pVDKu2sKnIjX6Bm0HZGbXAgED\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"cYcBOlapA+R4xq3nn5CjpnzNXdDArMlHuXv4MairjleF1n755ecH8A/R8YIc2ioV\n"
"n/C1TACzFVQ12Q9P3iikVOjIXNxYzaz4Lm/L/Lq4sEOPRJC38QEXeIHEaeM51lE6\n"
"p6kCqXcGu/51p5vAFCSiXI1ciucmx93N+TH1yGKRLV0=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_PORTS[] =
"router fred 127.0.0.1 900001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANVi/MVWhzT5uo3Jxw4ElS7UGmA24dnckdkCLetMhZOcE9e9mg4WcImL\n"
"NuBe2L/9YaL4PFVchCGlq73phKG6yFdqJdjDV8Qh9MJdAYWW2ORrjRvCrspPaYPN\n"
"BGJrkD2Gd4u3sq7f26TIkzmBx0Acd/FD4PQf8+XOt9YYd36ooS4vAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALtP4cIpAYp9nqo1ak4SxALcndFw4o51U36R4oa+uJS/lYQPHkMMOj6K\n"
"+AVnj9sxkDJ1POaU5lsCQ5JPG1t+Tkh7vDlJb6RCUy25vJOuaQCb9GVVY7KQTJqA\n"
"E0fU73JdKACNjMlbF36aliQhrG4Fq2Uv+y7yp8qsRxQ8jvzEMES/AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"xzu2T+pMZtdsS5q1cwXM2hMIH2c8mpAV31G2hKIuiQRwtPD1ne4iJsnoVCXhFakd\n"
"QTq7eTXM174fGWyIT93wvQx/Uqnp29dGZp/VaNOsxHFdYVB4VIVqkBh757h+PSJ+\n"
"VNV5JUm4XQ1QbmniJGdTQp4PLBM++fOXMR3ZNd6rt4o=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_NEG_BANDWIDTH[] =
"router fred 100.127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMCG/ZCXNCF02uXRSCP7qWBN75jDMQZ363ubnQWhF9KDDNWWiwj3UiZR\n"
"zqsM4zKRgjtarWZvp2qxKABFAODd+j9iq5DvUGRbbXv+aR8TT/ifMtwwxHZQBk1F\n"
"1hbsLdwWzGIiyz5k2MVhXnt6JTlklH2hgT++gt9YTHYKxkssaq5TAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM3vk/4kOTB1VXrve29JeHOzNUsPwKruBcjxJf+aatxjf6KO2/RW41bM\n"
"gRYq9V7VAYeZTsbS727fy03F5rk3QIBhMJxm9FHatQ6rT/iEDD4Q1UZQsNtm+OLf\n"
"/TkZZhgfB3MiDQ4ld/+GKd7qww8HXTE+m/g1rXNyZPKozn8K7YUHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 -1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"bUBBZYZWqCbsH4/7fNXtC/HgIZNGOfDF9v4d9YfKaDs5xDYf2o67hRcwx5imhrgC\n"
"IU7n9AI4AGxkFoN6g3Y/t4pqebxdkF678rRDCtrlwwreAiUktgrwnetp9Tpo16xj\n"
"V7Uf6LcqQdvu78lRh1dsrY78sf7sb90vusFMPLXGUKM=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_IP[] =
"router fred 100.127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMtMrM24AJpJCevxnseIpRlSuAIMksfkfky2+noe7Rok8xn6AMQzMrwx\n"
"AiCJ8Jy4DBzIKUiJK4/y1FimyM08qZGR0xeqblCxZ1lbSiXv6OYxoaD2xmWw8zEP\n"
"Zgu4jKReHh+gan1D+XpAbFNY0KrANhjRo96ZZ3AQsZQcWBiPKCynAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAOPclmBO/amw1RWTSI1y80qY/EPjc0I+sk9HKr0BQOovxqJ0lmy9Gaue\n"
"y+MOejQ9H2hNev0nd7z1fPxEogt7SCe22qJHHX3xDf+D9RpKsvVzDYZsk7hVL7T1\n"
"mwHzuiV/dtRa7yAMp7+q0vTUGesU2PYFYMOyPvz5skNLSWrXOm05AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"g6besL/zxOp0N6Q5/7QZgai2kmCU5EAWJlvZrf5jyrjKhsv2a4LDkap07m9QRFqW\n"
"GGe7g5iiABIqnl0kzv7NLX7ah+d/xxv+IILXyZfVTxSw0e+zFb3uPlQ7f9JsGJ8i\n"
"a+w8wyyDBpOAmi8Ny866Cnp9ojVzCyIErUYHFaPvKao=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_DIRPORT[] =
"router fred 127.0.0.1 9001 0 bob\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANKcD6DJ16X3yvdq05jatdwgjO+hyoIpckW9sV/OkdfIZwf+S6Q4pZGC\n"
"doMw5XeOM52gjpx42kUp6M2WlTGDFEpaNU0VyeZYG/M1CM1xvfj3+1PoebioAGdf\n"
"GuhNBCHZdaYNiOGnh9t2GgUomgpE6njdS/lovSrDeTL469hfcUghAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANWeGHig5wE9UijaNnEW5au3B3hZKSlzCi+T6MYDPbbYhm8qJaVoXUXF\n"
"EP1EUgzDcX3dPEo9upUA1+91GkjGQCo9eOYlqGib8kHIwKnHZK+hernBc/DnOeUp\n"
"Wyk9SW5s+fi12OQhr3NGjbSn76FMY9XU3Qt7m3EviTwWpI3Jr5eRAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"t77wEoLjyfMf9LKgBfjveosgwvJ8Go0nb27Ae3Ng9tGtR4qaJQfmwZ5fOOuVU9QC\n"
"3s8ww3aY91KD3NTcN3v3FKngxWtRM8AIfwh4pqT3zW6OSP4+nO3xml7ql0Zf6wfj\n"
"TPFV2941O3yplAsmBJ41sRSWizF04wTtZAIgzY7dMLA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_NAME2[] =
"router verylongnamethatnevereverendsandgoesontoolong 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAL0mcUxg7GJ6oxgciLiBCbo+NuZ/OVKRrERCSM6j6iHERcB9+ciSRgQ5\n"
"H6o6FUX2LoRmHYzBk1x7kIjHa9kx9g6CAbBamdZrQbdVnc1y2NrdHB/jvwLj3C48\n"
"PgzFIrLg9OlkuoWck/E+YpPllONfF65e0+ualgVjPgpQpXwmz+ktAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAOgHvvTAxyjJtHx9W2X7aOI05H9sYDDY+sxhovT/8EpAHrioex54tsMT\n"
"ifgtoXTjGIBEOTDi/1ry39nEW5WPbowqvyzRfR2M43pc96WV7e1nhmD/JrnTYgtR\n"
"5/15KxcMJxoDhod7WZ/wlXBnHc2VevX8JTaeOe9KYORCj5iNbtVZAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"j/nFT5gyj20cLHWv94O1jmnqy3n6qkO8Av0OdvvfNeXsMK2UHxk84vzFvEwpUF/Y\n"
"i+VR3LXY4CjTpuliMtjt7BQGtmJSvB8W0CeIUenIGzfwDxW9dG2o7spDldKDB/OU\n"
"C1wyHvKaA6Yss/02RIDa4AxyjsfbgdJ91qK+aAnYAtA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_BANDWIDTH2[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALQDCm9VEopiYILmt4X9kP6DQazfgKnLXv+6rHbc4qtmvQQD3TVYbxMP\n"
"F4sEUaz+YHAPnomfDVW3a0YFRYXwDzUm1n47YYCyhUzEaD2f69Mcl/gLpKdg+QOy\n"
"boGB1oD4CStWL3y05KhxxTNiTrg+veMzXTqNwryCYm+GoihIAM9fAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALYHwdx6bmYy09AW5ElN/DWh0fHh3mBK97ryiIMi8FImYfzbw2BR6xuT\n"
"aQT5omqS3PNJJcNWZt5gOyDtA9kLh03cch7t1PenXSYJshbME2bDrZDJKVJMN6vV\n"
"B1v/9HjXsVF50jBzZsJo3j26XCPT5s6u9wqUFWW09QR3E/1HInHVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 -1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"p09ijyuvcW+WKRj4mJA/nkLCvZkRcMzykAWheJi1IHCoqhXFdkFLiIRqjaeDVHRr\n"
"zBtD+YCQiGvFcaQJ9IUhh7IleHcyyljmDYlvuBAxWiKvVZstJac0kclCU4W+g8yK\n"
"0Qug3PmGKk115x2TllHaCZqMo5OkK4I/WAsKp+DnJ1A=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_UPTIME[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMM0Nubr1VXQ/FcgIQTFxZpZDlAEh2XN8FoJ8d+X5S46VDGijmMoYmyN\n"
"oLXqMTGmOaR0RGZOeGLgDzeY8tLrfF821IjfkXeAANZibUjdsHwqHO3wlWD2v+GN\n"
"0GBocWXEdAp/os229mQQKgYAATJ0Ib3jKhBdtgm5R444u8VX5XnbAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMpyOr4kEtSTZw4H9eSkH2+WmwIlO4VBpY2HkPS00l6L5fM2REjt50Xi\n"
"lsNOz8Q6mAn5cMYmsGlv61kg01mCvYc7Z715jGh+1hhVAxMaNS3ED/nSPnslyjhq\n"
"BUm51LhYNHD4ktISIqPMurx6aC8B68UYgKzLgCYNzkathFXSBpjRAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"uptime forever-and-a-day\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"NHYeiQOu0nZdrhSy31Xz4F0T6OTU23hPQDzoLax1/zq6iTVrz9xi3HGm7HhOMW1j\n"
"YgFGK3+Xm4iJL+DwriunsAIuL5axr3z2hlmFDQHYItP//KyPpOqSrfEOhwcuj/PE\n"
"VbWsiVYwz9VJLO8SfHoBeHI6PsjQRQFt2REBKZhYdxA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_BANDWIDTH3[] =
"router lucy 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAO6HrITQTEjV/v/rInQ2REmCFZa4dZg8zIh6+B51U/I6hDiZaKGwpNey\n"
"9OfjoRqT2DwyLEe3ORm9A2RAz2twLBixrpt5IvC0sbGustmW964BHW7k9VvRupwl\n"
"ovujHpLIj5dkLxD15jGXHoTp1yHUVk9NkMGN+ahg6y+QhTbIrWbRAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAOEpciJFXauEqs31GMTUTzu6edBj9WtV+sIflhGKvU1KKRfwCgOcuKMx\n"
"QiLHHD9AjhMAFGT/qtNbPFkzfYxHKLHw+NLJsxmNtdkYM26FX3ButPiX+69sq9fI\n"
"PCHqQy6z/A7hHwtEk6niWgK2PLhAZCg9duAv+mqFVXe2QEBjax/lAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 electric\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Jk0Xk1RMJSjEflNRcp4qznaHKcfe2r0kOc7TdLAnM8zyNDVj6+Bn8HWmyp/oFmf6\n"
"xtWKKgkKxriAVIJgqZMchPbr9RuZS+i+cad++FCwpTVkyBP920XWC47jA3ZXSBee\n"
"HK6FaoK5LfmUm8XEU9BVhiwISXaUfTdkR8HfzugFbWk=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_NTOR_KEY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKYDCSr0Jh9d/mJKjnGYAHKNBcxR3EJk6GGLwKUrRpN8z/aHRxdWlZF2\n"
"lBml6yQNK/VPftcvOekxrKq3/dISrIFBzFYj6XHNtg31d09UgitVkk0VfRarZiGu\n"
"O6Yv55GSJ9a3AZDE4YmIp5eBjVuChyVkeDFYKVn0ed4sj9gg35rjAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALXdUQuq1pYHyYP0qU6Ik+oOmwl0eOsuwiLWf9Vd+dsgEszICX4DRWPx\n"
"syDxfxyA/g9FEPvlI7Nglx6cKe2MT0AutSRLbbML4smfuRZNIF35Cnfu5qTGVVzL\n"
"GWVSA2Ip7p+9S9xLhLBdc6qmrxEXCPL6anEhCR4f8AeybXAsz2JLAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"ntor-onion-key s7rSohmz9SXn8WWh1EefTHIsWePthsEntQi0WL+ScVfjdklsdfjkf\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Yf9axWyzPudnRvQstNdbtBYo7pGpUEIdECMGcJtFb6v/00pxk4Tt3RiOKa84cOBV\n"
"7V9NjOLdqlx88pGz0DNCJKqToIrwjZDeQ8Q1yi9XClLDkC32fQRX4y6vNBZ3LXLe\n"
"ayVrdRrb41/DP+E7FP4RNPA5czujTfs8xLBMbGew8AA=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_FINGERPRINT[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM0wDWF2dBLzsmoIDHRugzosCSR9TSvEE0TkvKu6+agfogGtkQJwQ5zO\n"
"sGzZbRR+okO7d+QCED2i3rUs1iikoMUT+pwgvOm8Bxg9R64GK7fl9K5WuAiG11Uj\n"
"DQAfSx5Fo30+rhOhe16c9CT7xJhj//ZKDbXUW7BrJI8zpuOnvgD5AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKACg1nWM/WjpUiGwlLQsY3Tq1h0RTz/HmOMx/6rTRxS5HLz0KnLg5zV\n"
"dvmfhxqQVKBkt1N2+y+qO7x71oFzIsFMfHYWSxOCEo8Nkff1BqAPqxxUHvM0HwJo\n"
"d7lswJ/UT1j4+WZNZ4sFIujsIW2/zZqKlxG9xaw0GXJ082Cj9XkPAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"fingerprint 5555\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"mlqyJ/ZGBINKwSNEi7GpNBCMqIVbL0pGAOBYHJF1GbRlU28uRyNyeELIxIK5ZIet\n"
"ZzKr7KPvlBxlyolScPhTJfP98TFSubrwYz7NnQv0vLI0bD0OyoBf/9/1GYlzgTso\n"
"3mKfnV7THUalpxe9EjQ/x61Yqf26Co0+jYpt8/Ck6tg=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_MISMATCHED_FINGERPRINT[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANUAvwbpGbsAyA+mBwjFkvurtRzdw9btDqNKtPImufIE+q+AFTaCnwPr\n"
"kA7vm/O6h6OhgfdYEC2GfYJfwPGM7MDuz+NnuKxUb3qb2DQN2laqow6qWs9La/if\n"
"oHKUjC5mNeAgHcbWapx9CygwaFeVW6FBPl6Db6GIRAlywPSX+XMJAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANlSGd+Vm9nLiUk6zgu8dPnSFfw4F0R2GYfmzncIGJWtRFTF9ThW/0av\n"
"/9vZAWyVBjjtnpAP5R1BzdJYV2RwimC/6tqoHtkSbCBhdq5Cb/EHG7Xgb8KwNWVJ\n"
"NV1EESDwvWnRfSPGTreRw9+2LkdXri17FhDo2GjRxAq/N7YkLK5hAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"fingerprint CC43 DC8E 8C9E 3E6D 59CD 0399 2491 0C8C E1E4 50D2\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Y8MwYBeEfMhoAABK/FgpVRYolZ7jQ2BJL+8Lb6i4yAuk+HeVmPKTX7MqQoekUuin\n"
"/HdPKP+g/9HPMS5pCiW4FMwnXAF0ZocPXF0ndmsTuh0/7VWVOUGgvBpPbIW6guvt\n"
"sLLQ3Cq9a4Kwmd+koatfLB6xSZjhXmOn7nRy7gOdwJ8=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_HAS_ACCEPT6[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAJfPJNA3zZ77v2nlX2j5dXImcB/NhRtkG8XQgF7z+3H17sqoXgBgZ1dq\n"
"IbyJmAy2Lrvk/8VkXNFrT5/ErThn1B98V/PsJOOW1x7jGcix6X4zDYn/MvwC+AxA\n"
"zNP0ozNcVZ6BzVYq8w4I1V4O3Cd6VJesxRVX6mUeSeNawOb7fBY7AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKBzfB4mDEJjFTnmtqZxDG8G1yAiccVgAtq9ECEREL/BOQyukixUBeBe\n"
"j/FgXzbMJ7DZAuopuJZU2ma6h14G63fZs7eNFceDtmdLpuCOsFuvJ5Mlkf3hDZ1u\n"
"1KK5q+tiG7MKxgnGrqjPBUO2uubs2Cpx0HmsqBNUalXd/KAkFJbXAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"accept6 *:80\n"
"reject6 *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"Dp9dLgs9s5beMPxfD0m96as9gNBvlmKhH1RQ/kcOKscia4R8Q42CnUtIqLkCdjOu\n"
"zErc2Vj9QzjKOvlqUqHxP+J+l+ZJez6F+E1tcmK/Ydz3exL8cg9f4sAOCSXcpBey\n"
"llTFDibz6GkQ2j3/Uc4bN/uLzoyZKunpJbSKZP5nt8Q=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_NO_EXIT_POLICY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAK4fbjTKYqv2fygfjzY53sVTdtbNMjq293/uffKKxFYnOVvPzrHlP6Go\n"
"2S19ZcyDxOuH1unbBChPnV0GpxXX6+bgfDkaFh7+jef0RQ3fpJl84hSvdM8J8SCt\n"
"Q/F4Oqk3NeKKs+zAHDjhAU1G4LkF9/SZ9WZVXlH4a4pf7xgQtaShAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKahvyDkmh33ob/bLVO1icgz2ntOZN6ZQUfgpMU4Cd6DQtOEwFUGhbVt\n"
"gvtMHv2+VbxM31ZfUsyBqJ1rJBLpOqlPvSoYwSac2+twa+w/qjfGqcJYhBjP9TV9\n"
"n9y8DzBX85p6vRcCzcuZ4qUJ2nRzdLHwjdgzeLmmCHuPO2dQxQhXAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"ntgCtMC0VrsY42dKts8igGQ2Nu1BpuzUltisIsJz75dDx2LCqTn7p4VpWbTrj1sH\n"
"MRNOvEPFxVMs0Lu50ZUGRzeV6GrHmzIRnOIWanb3I/jyrJLM0jTIjCOLwdMRA298\n"
"tw8Y9Hnwj4K7K6VvgU8LP4l7MAJNfR6UT46AJ6vkgL0=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_IPV6_EXIT_POLICY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKHJKLHqjYoW9M+1q0CGHJRT5u2CnZWb8Qr1DpLkkusQ6ru+cDAG12so\n"
"IpDQh7IyB2JosVJi9ogekYxJ3O1p5WlFUi0X19DMoer9FJ9J7/3s4enGJ/yMBeuu\n"
"jLVRkjMJhsfhj3Cykon+8Rrf520wSmBg1dpJQCXTwtb7DARgYRpZAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAPJH61Ir6XSu9/Q9tXGaINbXO1GWQQUXtwh6TX9lxnaCNDLGnxiY+ZZw\n"
"+Vqj3LAQoMrz1PpPsF5e0VIxok10Vc8y4cWC+kIitcecut4vWC5FYTtVVP9wtlyg\n"
"YCcVOVhtFQxtLiGqprl84+EVxrR7RQVCMLNDUXIgxAfdnS24eBPDAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"ipv6-policy kfdslfdfj sdjfk sdfjsdf\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"XWorzVT5Owg+QcsBtksiUNtpQQ5+IdvbsN+0O9FbFtGZeaeBAbPJ3Poz+KFCUjZY\n"
"DeDAiu1cVgODx2St+99LpwEuIBx78HaD8RYU8tHx8LoA+mGC43ogQQS9lmfxzvP5\n"
"eT5WXhkOS5AZ8LZOCOmT+tj/LkSXev2x/NC9+Vc1HPo=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_FAMILY[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM62QoRxSPnm+ZM4fv9p03Qqbz5SzhXYSNjKWqylBruaofTw6oIM8DtX\n"
"7QnrEe/ou/WtfB+swV/2rt/r0EzmeWBWuDmuSUrN5TC2AdOi9brSJMgXVW6VW77X\n"
"fuIlLd5DVSId2zs3cKLDqp36CUsooA9sS6I5HrvW9QDf3VS3pGBtAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANg1trpnRzkCi4t4Z4qnBKF612H5A3Zrjg7Jo2b3ajUnON/KEuLPTc3t\n"
"PPN0W4qqeCMmVQEuxf3DRbTPS20ycy4B/JDWYfxCNwuj5YAx04REf7T0Hlx7Aee/\n"
"sHEQBhIBfasA2idhTh3cAm4DMYn+00BqjxF6jmyRA0hyntEABabrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"family aaaa,bbbb\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"xOgP3liKF/WEvwbbGzUUVRZ5WPrOI7jex8pZU/02UEnHjit7vCf9fsUcvkeo0xjz\n"
"n3FQHIO1iAJS7dEaEM4nz6wtPUb2iXSU9QajkGBkJ9/V7NHMFIU3FGfP47PIJJkd\n"
"nz5INoS+AsE7PmnDjUMm1H45TCCl8N8y4FO6TtN7p8I=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_BAD_EI_DIGEST[] =
"router fred 127.0.0.1 9001 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAJ8Sn8AxBRbeIAHUvaKjqmcYOvXz7YFlpYFiVHp/cn+l+KUkIYTOFQXf\n"
"K8AtwjmJ4R2qJIbNlY/6oZGFbizt/B+WPuWsTj+8ACEEDlxx0ibg3EJRB8AZYiWv\n"
"0zC/loiUvHm6fXF5ghvDr9BQzEUo9kBk5haoHwROtGawr1+vOEiNAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMzok3ZJtLjXOC8RKltXI8xulwn/ctCvQFHImR0+ccA1uBxaZNYgiIcc\n"
"q8XngROfV8xEgDbYPiWiLXJOMSwOd7hfs3YzRWF+LKftYs8PuRyMJcCoBjOPZ4QX\n"
"HRfTetEvu2SijZMby+lkqpZg2nuF/ipsXUjrabRZdNiIGhC451vdAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"extra-info-digest not-a-digest\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"c/6zAxO04izQvqdM4bZVGE+ak0nna5pz9XZizFkieZEDWGzWQuVMhXyL5sbsFbsx\n"
"6Hn7DvNRYR/2nA0teDeRyIHMoMHi76te5X9OFDgaeUVCbyJ8h/KZYfPnN86IDbsR\n"
"dCSmj9kX55keu64ccCAH1CqwcN/UsbplXiJJVG5pTfI=\n"
"-----END SIGNATURE-----\n"
;
static const char EX_RI_ZERO_ORPORT[] =
"router fred 127.0.0.1 0 0 9002\n"
"signing-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMc4MOhLG3PKPgc+xYVf4eScWzeOf8wq7Cb/JxZm50G0LuvVbhHtHEZX\n"
"VOSHI7mLE1ifakJvCFJRLobMU7lU0yhn18/nKl2Cu5NfFHHeF/NieUBSxBGb2wD6\n"
"aM1azheXrRqvDVVfbI0DLc/XfQC/YNiohOsQ/c9C6wuffA4+Sg85AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALBWdl9/Vft+NQKQlg5kgvZo+krnhNTRVQojWtUEzom4TFIT+NNKJyMG\n"
"reQXcNdzNptTB0aOBGGwqAesqzsZ2Hje699NsDe7hdl7Sb5yhKDqtdQY6yDXJUFt\n"
"zqpAUkmYMLe2p3kPiWefNso56KYXrZrlNAiIS/FhQ5cmuMC2jPydAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"published 2014-10-05 12:00:00\n"
"bandwidth 1000 1000 1000\n"
"reject *:*\n"
"router-signature\n"
"-----BEGIN SIGNATURE-----\n"
"gFg08P9A6QNQjURlebfdhU3DSV0BeM0j2SFza1jF9JcBOWDRmT8FvYFK1B3js6jK\n"
"8LNV8JOUssv14z5CnUY9CO1BD0xSl+vGlSS4VOXD7rxui8IoWgnqnZsitq+Qzs95\n"
"wgFKhHI/49NHyWHX5IMQpeicg0T7Qa6qwnUvspH62p8=\n"
"-----END SIGNATURE-----\n"
;

View File

@ -76,6 +76,8 @@ src_test_bench_LDADD = src/or/libtor.a src/common/libor.a \
noinst_HEADERS+= \
src/test/test.h \
src/test/test_descriptors.inc \
src/test/example_extrainfo.inc \
src/test/failing_routerdescs.inc \
src/test/ed25519_vectors.inc
if CURVE25519_ENABLED

View File

@ -186,7 +186,7 @@ test_dir_formats(void *arg)
buf = router_dump_router_to_string(r1, pk2);
tt_assert(buf);
cp = buf;
rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
rp1 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp1);
tt_int_op(rp1->addr,==, r1->addr);
tt_int_op(rp1->or_port,==, r1->or_port);
@ -231,7 +231,7 @@ test_dir_formats(void *arg)
buf = router_dump_router_to_string(r2, pk1);
cp = buf;
rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL);
rp2 = router_parse_entry_from_string((const char*)cp,NULL,1,0,NULL,NULL);
tt_assert(rp2);
tt_int_op(rp2->addr,==, r2->addr);
tt_int_op(rp2->or_port,==, r2->or_port);
@ -294,6 +294,506 @@ test_dir_formats(void *arg)
tor_free(dir2); /* And more !*/
}
#include "failing_routerdescs.inc"
static void
test_dir_routerparse_bad(void *arg)
{
(void) arg;
int again;
routerinfo_t *ri = NULL;
#define CHECK_OK(s) \
do { \
routerinfo_free(ri); \
ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, NULL); \
tt_assert(ri); \
} while (0)
#define CHECK_FAIL(s, againval) \
do { \
routerinfo_free(ri); \
again = 999; \
ri = router_parse_entry_from_string((s), NULL, 0, 0, NULL, &again); \
tt_assert(ri == NULL); \
tt_int_op(again, ==, (againval)); \
} while (0)
CHECK_OK(EX_RI_MINIMAL);
CHECK_OK(EX_RI_MAXIMAL);
/* good annotations prepended */
routerinfo_free(ri);
ri = router_parse_entry_from_string(EX_RI_MINIMAL, NULL, 0, 0,
"@purpose bridge\n", NULL);
tt_assert(ri != NULL);
tt_assert(ri->purpose == ROUTER_PURPOSE_BRIDGE);
routerinfo_free(ri);
/* bad annotations prepended. */
ri = router_parse_entry_from_string(EX_RI_MINIMAL,
NULL, 0, 0, "@purpose\n", NULL);
tt_assert(ri == NULL);
/* bad annotations on router. */
ri = router_parse_entry_from_string("@purpose\nrouter x\n", NULL, 0, 1,
NULL, NULL);
tt_assert(ri == NULL);
/* unwanted annotations on router. */
ri = router_parse_entry_from_string("@purpose foo\nrouter x\n", NULL, 0, 0,
NULL, NULL);
tt_assert(ri == NULL);
/* No signature. */
ri = router_parse_entry_from_string("router x\n", NULL, 0, 0,
NULL, NULL);
tt_assert(ri == NULL);
/* Not a router */
routerinfo_free(ri);
ri = router_parse_entry_from_string("hello\n", NULL, 0, 0, NULL, NULL);
tt_assert(ri == NULL);
CHECK_FAIL(EX_RI_BAD_SIG1, 1);
CHECK_FAIL(EX_RI_BAD_SIG2, 1);
CHECK_FAIL(EX_RI_BAD_TOKENS, 0);
CHECK_FAIL(EX_RI_BAD_PUBLISHED, 0);
CHECK_FAIL(EX_RI_NEG_BANDWIDTH, 0);
CHECK_FAIL(EX_RI_BAD_BANDWIDTH, 0);
CHECK_FAIL(EX_RI_BAD_BANDWIDTH2, 0);
CHECK_FAIL(EX_RI_BAD_ONIONKEY1, 0);
CHECK_FAIL(EX_RI_BAD_ONIONKEY2, 0);
CHECK_FAIL(EX_RI_BAD_PORTS, 0);
CHECK_FAIL(EX_RI_BAD_IP, 0);
CHECK_FAIL(EX_RI_BAD_DIRPORT, 0);
CHECK_FAIL(EX_RI_BAD_NAME2, 0);
CHECK_FAIL(EX_RI_BAD_UPTIME, 0);
CHECK_FAIL(EX_RI_BAD_BANDWIDTH3, 0);
CHECK_FAIL(EX_RI_BAD_NTOR_KEY, 0);
CHECK_FAIL(EX_RI_BAD_FINGERPRINT, 0);
CHECK_FAIL(EX_RI_MISMATCHED_FINGERPRINT, 0);
CHECK_FAIL(EX_RI_BAD_HAS_ACCEPT6, 0);
CHECK_FAIL(EX_RI_BAD_NO_EXIT_POLICY, 0);
CHECK_FAIL(EX_RI_BAD_IPV6_EXIT_POLICY, 0);
CHECK_FAIL(EX_RI_BAD_FAMILY, 0);
CHECK_FAIL(EX_RI_ZERO_ORPORT, 0);
/* This is allowed; we just ignore it. */
CHECK_OK(EX_RI_BAD_EI_DIGEST);
#undef CHECK_FAIL
#undef CHECK_OK
done:
routerinfo_free(ri);
}
#include "example_extrainfo.inc"
static void
test_dir_extrainfo_parsing(void *arg)
{
(void) arg;
#define CHECK_OK(s) \
do { \
extrainfo_free(ei); \
ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, NULL); \
tt_assert(ei); \
} while (0)
#define CHECK_FAIL(s, againval) \
do { \
extrainfo_free(ei); \
again = 999; \
ei = extrainfo_parse_entry_from_string((s), NULL, 0, map, &again); \
tt_assert(ei == NULL); \
tt_int_op(again, ==, (againval)); \
} while (0)
#define ADD(name) \
do { \
ri = tor_malloc_zero(sizeof(routerinfo_t)); \
crypto_pk_t *pk = ri->identity_pkey = crypto_pk_new(); \
tt_assert(! crypto_pk_read_public_key_from_string(pk, \
name##_KEY, strlen(name##_KEY))); \
tt_int_op(0,==,base16_decode(d, 20, name##_FP, strlen(name##_FP))); \
digestmap_set((digestmap_t*)map, d, ri); \
ri = NULL; \
} while (0)
routerinfo_t *ri = NULL;
char d[20];
struct digest_ri_map_t *map = NULL;
extrainfo_t *ei = NULL;
int again;
CHECK_OK(EX_EI_MINIMAL);
tt_assert(ei->pending_sig);
CHECK_OK(EX_EI_MAXIMAL);
tt_assert(ei->pending_sig);
map = (struct digest_ri_map_t *)digestmap_new();
ADD(EX_EI_MINIMAL);
ADD(EX_EI_MAXIMAL);
ADD(EX_EI_BAD_FP);
ADD(EX_EI_BAD_NICKNAME);
ADD(EX_EI_BAD_TOKENS);
ADD(EX_EI_BAD_START);
ADD(EX_EI_BAD_PUBLISHED);
CHECK_OK(EX_EI_MINIMAL);
tt_assert(!ei->pending_sig);
CHECK_OK(EX_EI_MAXIMAL);
tt_assert(!ei->pending_sig);
CHECK_FAIL(EX_EI_BAD_SIG1,1);
CHECK_FAIL(EX_EI_BAD_SIG2,1);
CHECK_FAIL(EX_EI_BAD_SIG3,1);
CHECK_FAIL(EX_EI_BAD_FP,0);
CHECK_FAIL(EX_EI_BAD_NICKNAME,0);
CHECK_FAIL(EX_EI_BAD_TOKENS,0);
CHECK_FAIL(EX_EI_BAD_START,0);
CHECK_FAIL(EX_EI_BAD_PUBLISHED,0);
#undef CHECK_OK
#undef CHECK_FAIL
done:
routerinfo_free(ri);
/* XXXX elements should get freed too */
digestmap_free((digestmap_t*)map, NULL);
}
static void
test_dir_parse_router_list(void *arg)
{
(void) arg;
smartlist_t *invalid = smartlist_new();
smartlist_t *dest = smartlist_new();
smartlist_t *chunks = smartlist_new();
int dest_has_ri = 1;
char *list = NULL;
const char *cp;
digestmap_t *map = NULL;
char *mem_op_hex_tmp = NULL;
routerinfo_t *ri = NULL;
char d[DIGEST_LEN];
smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL)); // ri 0
smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS)); // bad ri 0
smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL)); // ei 0
smartlist_add(chunks, tor_strdup(EX_EI_BAD_SIG2)); // bad ei --
smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));// bad ei 0
smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG1)); // bad ri --
smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED)); // bad ei 1
smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL)); // ri 1
smartlist_add(chunks, tor_strdup(EX_RI_BAD_FAMILY)); // bad ri 1
smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL)); // ei 1
list = smartlist_join_strings(chunks, "", 0, NULL);
/* First, parse the routers. */
cp = list;
tt_int_op(0,==,
router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
0, 0, NULL, invalid));
tt_int_op(2, ==, smartlist_len(dest));
tt_ptr_op(cp, ==, list + strlen(list));
routerinfo_t *r = smartlist_get(dest, 0);
tt_mem_op(r->cache_info.signed_descriptor_body, ==,
EX_RI_MINIMAL, strlen(EX_RI_MINIMAL));
r = smartlist_get(dest, 1);
tt_mem_op(r->cache_info.signed_descriptor_body, ==,
EX_RI_MAXIMAL, strlen(EX_RI_MAXIMAL));
tt_int_op(2, ==, smartlist_len(invalid));
test_memeq_hex(smartlist_get(invalid, 0),
"ab9eeaa95e7d45740185b4e519c76ead756277a9");
test_memeq_hex(smartlist_get(invalid, 1),
"9a651ee03b64325959e8f1b46f2b689b30750b4c");
/* Now tidy up */
SMARTLIST_FOREACH(dest, routerinfo_t *, ri, routerinfo_free(ri));
SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
smartlist_clear(dest);
smartlist_clear(invalid);
/* And check extrainfos. */
dest_has_ri = 0;
map = (digestmap_t*)router_get_routerlist()->identity_map;
ADD(EX_EI_MINIMAL);
ADD(EX_EI_MAXIMAL);
ADD(EX_EI_BAD_NICKNAME);
ADD(EX_EI_BAD_PUBLISHED);
cp = list;
tt_int_op(0,==,
router_parse_list_from_string(&cp, NULL, dest, SAVED_NOWHERE,
1, 0, NULL, invalid));
tt_int_op(2, ==, smartlist_len(dest));
extrainfo_t *e = smartlist_get(dest, 0);
tt_mem_op(e->cache_info.signed_descriptor_body, ==,
EX_EI_MAXIMAL, strlen(EX_EI_MAXIMAL));
e = smartlist_get(dest, 1);
tt_mem_op(e->cache_info.signed_descriptor_body, ==,
EX_EI_MINIMAL, strlen(EX_EI_MINIMAL));
tt_int_op(2, ==, smartlist_len(invalid));
test_memeq_hex(smartlist_get(invalid, 0),
"d5df4aa62ee9ffc9543d41150c9864908e0390af");
test_memeq_hex(smartlist_get(invalid, 1),
"f61efd2a7f4531f3687a9043e0de90a862ec64ba");
done:
tor_free(list);
if (dest_has_ri)
SMARTLIST_FOREACH(dest, routerinfo_t *, rt, routerinfo_free(rt));
else
SMARTLIST_FOREACH(dest, extrainfo_t *, ei, extrainfo_free(ei));
smartlist_free(dest);
SMARTLIST_FOREACH(invalid, uint8_t *, d, tor_free(d));
smartlist_free(invalid);
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
routerinfo_free(ri);
/* XXXX this leaks: */
if (map) {
digestmap_free((digestmap_t*)map, NULL);
router_get_routerlist()->identity_map =
(struct digest_ri_map_t*)digestmap_new();
}
tor_free(mem_op_hex_tmp);
#undef ADD
}
static download_status_t dls_minimal;
static download_status_t dls_maximal;
static download_status_t dls_bad_fingerprint;
static download_status_t dls_bad_sig2;
static download_status_t dls_bad_ports;
static download_status_t dls_bad_tokens;
static int mock_router_get_dl_status_unrecognized = 0;
static int mock_router_get_dl_status_calls = 0;
static download_status_t *
mock_router_get_dl_status(const char *d)
{
++mock_router_get_dl_status_calls;
char hex[HEX_DIGEST_LEN+1];
base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
if (!strcmp(hex, "3E31D19A69EB719C00B02EC60D13356E3F7A3452")) {
return &dls_minimal;
} else if (!strcmp(hex, "581D8A368A0FA854ECDBFAB841D88B3F1B004038")) {
return &dls_maximal;
} else if (!strcmp(hex, "2578AE227C6116CDE29B3F0E95709B9872DEE5F1")) {
return &dls_bad_fingerprint;
} else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
return &dls_bad_sig2;
} else if (!strcmp(hex, "AB9EEAA95E7D45740185B4E519C76EAD756277A9")) {
return &dls_bad_ports;
} else if (!strcmp(hex, "A0CC2CEFAD59DBF19F468BFEE60E0868C804B422")) {
return &dls_bad_tokens;
} else {
++mock_router_get_dl_status_unrecognized;
return NULL;
}
}
static void
test_dir_load_routers(void *arg)
{
(void) arg;
smartlist_t *chunks = smartlist_new();
smartlist_t *wanted = smartlist_new();
char buf[DIGEST_LEN];
char *mem_op_hex_tmp = NULL;
#define ADD(str) \
do { \
tt_int_op(0,==,router_get_router_hash(str, strlen(str), buf)); \
smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
} while (0)
MOCK(router_get_dl_status_by_descriptor_digest, mock_router_get_dl_status);
update_approx_time(1412510400);
smartlist_add(chunks, tor_strdup(EX_RI_MINIMAL));
smartlist_add(chunks, tor_strdup(EX_RI_BAD_FINGERPRINT));
smartlist_add(chunks, tor_strdup(EX_RI_BAD_SIG2));
smartlist_add(chunks, tor_strdup(EX_RI_MAXIMAL));
smartlist_add(chunks, tor_strdup(EX_RI_BAD_PORTS));
smartlist_add(chunks, tor_strdup(EX_RI_BAD_TOKENS));
/* not ADDing MINIMIAL */
ADD(EX_RI_MAXIMAL);
ADD(EX_RI_BAD_FINGERPRINT);
ADD(EX_RI_BAD_SIG2);
/* Not ADDing BAD_PORTS */
ADD(EX_RI_BAD_TOKENS);
char *list = smartlist_join_strings(chunks, "", 0, NULL);
tt_int_op(1, ==,
router_load_routers_from_string(list, NULL, SAVED_IN_JOURNAL,
wanted, 1, NULL));
/* The "maximal" router was added. */
/* "minimal" was not. */
tt_int_op(smartlist_len(router_get_routerlist()->routers),==,1);
routerinfo_t *r = smartlist_get(router_get_routerlist()->routers, 0);
test_memeq_hex(r->cache_info.signed_descriptor_digest,
"581D8A368A0FA854ECDBFAB841D88B3F1B004038");
tt_int_op(dls_minimal.n_download_failures, ==, 0);
tt_int_op(dls_maximal.n_download_failures, ==, 0);
/* "Bad fingerprint" and "Bad tokens" should have gotten marked
* non-retriable. */
tt_want_int_op(mock_router_get_dl_status_calls, ==, 2);
tt_want_int_op(mock_router_get_dl_status_unrecognized, ==, 0);
tt_int_op(dls_bad_fingerprint.n_download_failures, ==, 255);
tt_int_op(dls_bad_tokens.n_download_failures, ==, 255);
/* bad_sig2 and bad ports" are retriable -- one since only the signature
* was bad, and one because we didn't ask for it. */
tt_int_op(dls_bad_sig2.n_download_failures, ==, 0);
tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
/* Wanted still contains "BAD_SIG2" */
tt_int_op(smartlist_len(wanted), ==, 1);
tt_str_op(smartlist_get(wanted, 0), ==,
"E0A3753CEFD54128EAB239F294954121DB23D2EF");
#undef ADD
done:
tor_free(mem_op_hex_tmp);
UNMOCK(router_get_dl_status_by_descriptor_digest);
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
smartlist_free(wanted);
}
static int mock_get_by_ei_dd_calls = 0;
static int mock_get_by_ei_dd_unrecognized = 0;
static signed_descriptor_t sd_ei_minimal;
static signed_descriptor_t sd_ei_bad_nickname;
static signed_descriptor_t sd_ei_maximal;
static signed_descriptor_t sd_ei_bad_tokens;
static signed_descriptor_t sd_ei_bad_sig2;
static signed_descriptor_t *
mock_get_by_ei_desc_digest(const char *d)
{
++mock_get_by_ei_dd_calls;
char hex[HEX_DIGEST_LEN+1];
base16_encode(hex, sizeof(hex), d, DIGEST_LEN);
if (!strcmp(hex, "11E0EDF526950739F7769810FCACAB8C882FAEEE")) {
return &sd_ei_minimal;
} else if (!strcmp(hex, "47803B02A0E70E9E8BDA226CB1D74DE354D67DFF")) {
return &sd_ei_maximal;
} else if (!strcmp(hex, "D5DF4AA62EE9FFC9543D41150C9864908E0390AF")) {
return &sd_ei_bad_nickname;
} else if (!strcmp(hex, "16D387D3A58F7DB3CF46638F8D0B90C45C7D769C")) {
return &sd_ei_bad_sig2;
} else if (!strcmp(hex, "9D90F8C42955BBC57D54FB05E54A3F083AF42E8B")) {
return &sd_ei_bad_tokens;
} else {
++mock_get_by_ei_dd_unrecognized;
return NULL;
}
}
static smartlist_t *mock_ei_insert_list = NULL;
static was_router_added_t
mock_ei_insert(routerlist_t *rl, extrainfo_t *ei)
{
(void) rl;
smartlist_add(mock_ei_insert_list, ei);
return ROUTER_ADDED_SUCCESSFULLY;
}
static void
test_dir_load_extrainfo(void *arg)
{
(void) arg;
smartlist_t *chunks = smartlist_new();
smartlist_t *wanted = smartlist_new();
char buf[DIGEST_LEN];
char *mem_op_hex_tmp = NULL;
#define ADD(str) \
do { \
tt_int_op(0,==,router_get_extrainfo_hash(str, strlen(str), buf)); \
smartlist_add(wanted, tor_strdup(hex_str(buf, DIGEST_LEN))); \
} while (0)
mock_ei_insert_list = smartlist_new();
MOCK(router_get_by_extrainfo_digest, mock_get_by_ei_desc_digest);
MOCK(extrainfo_insert, mock_ei_insert);
smartlist_add(chunks, tor_strdup(EX_EI_MINIMAL));
smartlist_add(chunks, tor_strdup(EX_EI_BAD_NICKNAME));
smartlist_add(chunks, tor_strdup(EX_EI_MAXIMAL));
smartlist_add(chunks, tor_strdup(EX_EI_BAD_PUBLISHED));
smartlist_add(chunks, tor_strdup(EX_EI_BAD_TOKENS));
/* not ADDing MINIMIAL */
ADD(EX_EI_MAXIMAL);
ADD(EX_EI_BAD_NICKNAME);
/* Not ADDing BAD_PUBLISHED */
ADD(EX_EI_BAD_TOKENS);
ADD(EX_EI_BAD_SIG2);
char *list = smartlist_join_strings(chunks, "", 0, NULL);
router_load_extrainfo_from_string(list, NULL, SAVED_IN_JOURNAL, wanted, 1);
/* The "maximal" router was added. */
/* "minimal" was also added, even though we didn't ask for it, since
* that's what we do with extrainfos. */
tt_int_op(smartlist_len(mock_ei_insert_list),==,2);
extrainfo_t *e = smartlist_get(mock_ei_insert_list, 0);
test_memeq_hex(e->cache_info.signed_descriptor_digest,
"11E0EDF526950739F7769810FCACAB8C882FAEEE");
e = smartlist_get(mock_ei_insert_list, 1);
test_memeq_hex(e->cache_info.signed_descriptor_digest,
"47803B02A0E70E9E8BDA226CB1D74DE354D67DFF");
tt_int_op(dls_minimal.n_download_failures, ==, 0);
tt_int_op(dls_maximal.n_download_failures, ==, 0);
/* "Bad nickname" and "Bad tokens" should have gotten marked
* non-retriable. */
tt_want_int_op(mock_get_by_ei_dd_calls, ==, 2);
tt_want_int_op(mock_get_by_ei_dd_unrecognized, ==, 0);
tt_int_op(sd_ei_bad_nickname.ei_dl_status.n_download_failures, ==, 255);
tt_int_op(sd_ei_bad_tokens.ei_dl_status.n_download_failures, ==, 255);
/* bad_ports is retriable -- because we didn't ask for it. */
tt_int_op(dls_bad_ports.n_download_failures, ==, 0);
/* Wanted still contains "BAD_SIG2" */
tt_int_op(smartlist_len(wanted), ==, 1);
tt_str_op(smartlist_get(wanted, 0), ==,
"16D387D3A58F7DB3CF46638F8D0B90C45C7D769C");
#undef ADD
done:
tor_free(mem_op_hex_tmp);
UNMOCK(router_get_by_extrainfo_digest);
SMARTLIST_FOREACH(chunks, char *, cp, tor_free(cp));
smartlist_free(chunks);
SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
smartlist_free(wanted);
}
static void
test_dir_versions(void *arg)
{
@ -2393,6 +2893,11 @@ test_dir_http_handling(void *args)
struct testcase_t dir_tests[] = {
DIR_LEGACY(nicknames),
DIR_LEGACY(formats),
DIR(routerparse_bad, 0),
DIR(extrainfo_parsing, 0),
DIR(parse_router_list, TT_FORK),
DIR(load_routers, TT_FORK),
DIR(load_extrainfo, TT_FORK),
DIR_LEGACY(versions),
DIR_LEGACY(fp_pairs),
DIR(split_fps, 0),

View File

@ -7,11 +7,16 @@
#include "config.h"
#include "dirvote.h"
#include "microdesc.h"
#include "networkstatus.h"
#include "routerlist.h"
#include "routerparse.h"
#include "test.h"
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/pem.h>
#ifdef _WIN32
/* For mkdir() */
#include <direct.h>
@ -367,7 +372,7 @@ test_md_generate(void *arg)
microdesc_t *md = NULL;
(void)arg;
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL);
ri = router_parse_entry_from_string(test_ri, NULL, 0, 0, NULL, NULL);
tt_assert(ri);
md = dirvote_create_microdescriptor(ri, 8);
tt_str_op(md->body, ==, test_md_8);
@ -391,10 +396,330 @@ test_md_generate(void *arg)
routerinfo_free(ri);
}
/* Taken at random from my ~/.tor/cached-microdescs file and then
* hand-munged */
static const char MD_PARSE_TEST_DATA[] =
/* Good 0 */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANsKd1GRfOuSR1MkcwKqs6SVy4Gi/JXplt/bHDkIGm6Q96TeJ5uyVgUL\n"
"DBr/ij6+JqgVFeriuiMzHKREytzjdaTuKsKBFFpLwb+Ppcjr5nMIH/AR6/aHO8hW\n"
"T3B9lx5T6Kl7CqZ4yqXxYRHzn50EPTIZuz0y9se4J4gi9mLmL+pHAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"p accept 20-23,43,53,79-81,88,110,143,194,220,443,464,531,543-544\n"
"id rsa1024 GEo59/iR1GWSIWZDzXTd5QxtqnU\n"
/* Bad 0: I've messed with the onion-key in the second one. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMr4o/pflVwscx11vC1AKEADlKEqnhpvCIjAEzNEenMhvGQHRlA0EXLC\n"
"7G7O5bhnCwEHqK8Pvg8cuX/fD8v08TF1EVPhwPa0UI6ab8KnPP2F!!!!!!b92DG7EQIk3q\n"
"d68Uxp7E9/t3v1WWZjzDqvEe0par6ul+DKW6HMlTGebFo5Q4e8R1AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key 761Dmm27via7lXygNHM3l+oJLrYU2Nye0Uz4pkpipyY=\n"
"p accept 53\n"
"id rsa1024 3Y4fwXhtgkdGDZ5ef5mtb6TJRQQ\n"
/* Good 1 */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANsMSjVi3EX8ZHfm/dvPF6KdVR66k1tVul7Jp+dDbDajBYNhgKRzVCxy\n"
"Yac1CBuQjOqK89tKap9PQBnhF087eDrfaZDqYTLwB2W2sBJncVej15WEPXPRBifo\n"
"iFZ8337kgczkaY+IOfSuhtbOUyDOoDpRJheIKBNq0ZiTqtLbbadVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key ncfiHJjSgdDEW/gc6q6/7idac7j+x7ejQrRm6i75pGA=\n"
"p accept 443,6660-6669,6697,7000-7001\n"
"id rsa1024 XXuLzw3mfBELEq3veXoNhdehwD4\n"
/* Good 2 */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANQfBlrHrh9F/CAOytrNFgi0ikWMW/HZxuoszF9X+AQ+MudR8bcxxOGl\n"
"1RFwb74s8E3uuzrCkNFvSw9Ar1L02F2DOX0gLsxEGuYC4Ave9NUteGqSqDyEJQUJ\n"
"KlfxCPn2qC9nvNT7wR/Dg2WRvAEKnJmkpb57N3+WSAOPLjKOFEz3AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n"
"id rsa1024 6y60AEI9a1PUUlRPO0YQT9WzrjI\n"
/* Bad 1: Here I've messed with the ntor key */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAPjy2HacU3jDNO5nTOFGSwNa0qKCNn4yhtrDVcAJ5alIQeBWZZGJLZ0q\n"
"Cqylw1vYqxu8E09g+QXXFbAgBv1U9TICaATxrIJhIJzc8TJPhqJemp1kq0DvHLDx\n"
"mxwlkNnCD/P5NS+JYB3EjOlU9EnSKUWNU61+Co344m2JqhEau40vAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key 4i2Fp9JHTUr1uQs0pxD5j5spl4/RG56S2P0gQxU=\n"
"id rsa1024 nMRmNEGysA0NmlALVaUmI7D5jLU\n"
/* Good 3: I've added a weird token in this one. This shouldn't prevent
* it parsing */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKmosxudyNA/yJNz3S890VqV/ebylzoD11Sc0b/d5tyNNaNZjcYy5vRD\n"
"kwyxFRMbP2TLZQ1zRfNwY7IDnYjU2SbW0pxuM6M8WRtsmx/YOE3kHMVAFJNrTUqU\n"
"6D1zB3IiRDS5q5+NoRxwqo+hYUck60O3WTwEoqb+l3lvXeu7z9rFAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"flux-capacitor 1.21 GW\n"
"ntor-onion-key MWBoEkl+RlBiGX44XKIvTSqbznTNZStOmUYtcYRQQyY=\n"
"id rsa1024 R+A5O9qRvRac4FT3C4L2QnFyxsc\n"
/* Good 4: Here I've made the 'id rsa' token odd. It should still parse
* just fine. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAOh+WMkdNe/Pkjb8UjQyfLOlFgpuVFrxAIGnJsmWWx0yBE97DQxGyh2n\n"
"h8G5OJZHRarJQyCIf7vpZQAi0oP0OkGGaCaDQsM+D8TnqhnU++RWGnMqY/cXxPrL\n"
"MEq+n6aGiLmzkO7ah8yorZpoREk4GqLUIN89/tHHGOhJL3c4CPGjAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
"id rsa1234 jlqAKFD2E7uMKv+8TmKSeo7NBho\n"
/* Good 5: Extra id type. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAMdgPPc5uaw4y/q+SUTN/I8Y+Gvdx9kKgWV4dmDGJ0mxsVZmo1v6+v3F\n"
"12M2f9m99G3WB8F8now29C+9XyEv8MBHj1lHRdUFHSQes3YTFvDNlgj+FjLqO5TJ\n"
"adOOmfu4DCUUtUEDyQKbNVL4EkMTXY73omTVsjcH3xxFjTx5wixhAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key AAVnWZcnDbxasdZwKqb4fL6O9sZV+XsRNHTpNd1YMz8=\n"
"id rsa1024 72EfBL11QuwX2vU8y+p9ExGfGEg\n"
"id expolding hedgehog 0+A5O9qRvRac4FT3C4L2QnFyxsc\n"
/* Good 6: I've given this a bogus policy. It should parse. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALNuufwhPMF8BooxYMNvhYJMPqUB8hQDt8wGmPKphJcD1sVD1i4gAZM2\n"
"HIo+zUBlljDrRWL5NzVzd1yxUJAiQxvXS5dRRFY3B70M7wTVpXw53xe0/BM5t1AX\n"
"n0MFk7Jl6XIKMlzRalZvmMvE/odtyWXkP4Nd1MyZ1QcIwrQ2iwyrAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"p condone 1-10\n"
"ntor-onion-key 2/nMJ+L4dd/2GpMyTYjz3zC59MvQy4MIzJZhdzKHekg=\n"
"id rsa1024 FHyh10glEMA6MCmBb5R9Y+X/MhQ\n"
/* Good 7: I've given this one another sort of odd policy. Should parse. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAKcd3FmQ8iAADghyvX8eca0ePqtJ2w1IDdUdTlf5Y/8+OMdp//sD01yC\n"
"YmiX45LK5ge1O3AzcakYCO6fb3pyIqvXdvm24OjyYZELQ40cmKSLjdhcSf4Fr/N9\n"
"uR/CkknR9cEePu1wZ5WBIGmGdXI6s7t3LB+e7XFyBYAx6wMGlnX7AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"p accept frogs-mice\n"
"ntor-onion-key AMxvhaQ1Qg7jBJFoyHuPRgETvLbFmJ194hExV24FuAI=\n"
"family $D8CFEA0D996F5D1473D2063C041B7910DB23981E\n"
"id rsa1024 d0VVZC/cHh1P3y4MMbfKlQHFycc\n"
/* Good 8: This one has the ntor-onion-key without terminating =. That's
* allowed. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAL438YfjrJE2SPqkkXeQwICygu8KNO54Juj6sjqk5hgsiazIWMOBgbaX\n"
"LIRqPNGaiSq01xSqwjwCBCfwZYT/nSdDBqj1h9aoR8rnjxZjyQ+m3rWpdDqeCDMx\n"
"I3NgZ5w4bNX4poRb42lrV6NmQiFdjzpqszVbv5Lpn2CSKu32CwKVAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key UKL6Dnj2KwYsFlkCvOkXVatxvOPB4MaxqwPQQgZMTwI\n"
"id rsa1024 FPIXc6k++JnKCtSKWUxaR6oXEKs\n"
/* Good 9: Another totally normal one.*/
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBANNGIKRd8PFNXkJ2JPV1ohDMFNbJwKbwybeieaQFjtU9KWedHCbr+QD4\n"
"B6zNY5ysguNjHNnlq2f6D09+uhnfDBON8tAz0mPQH/6JqnOXm+EiUn+8bN0E8Nke\n"
"/i3GEgDeaxJJMNQcpsJvmmSmKFOlYy9Fy7ejAjTGqtAnqOte7BnTAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key gUsq3e5iYgsQQvyxINtLzBpHxmIt5rtuFlEbKfI4gFk=\n"
"id rsa1024 jv+LdatDzsMfEW6pLBeL/5uzwCc\n"
/* Bad 2: RSA key has bad exponent of 3. */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGHAoGBAMMTWtvPxYnUNJ5Y7B+XENcpxzPoGstrdiUszCBS+/42xvluLJ+JDSdR\n"
"qJaMD6ax8vKAeLS5C6O17MNdG2VldlPRbtgl41MXsOoUqEJ+nY9e3WG9Snjp47xC\n"
"zmWIfeduXSavIsb3a43/MLIz/9qO0TkgAAiuQr79JlwKhLdzCqTLAgED\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key NkRB4wTUFogiVp5jYmjGORe2ffb/y5Kk8Itw8jdzMjA=\n"
"p reject 25,119,135-139,445,563,1214,4661-4666,6346-6429,6699,6881-6999\n"
"id rsa1024 fKvYjP7TAjCC1FzYee5bYAwYkoDg\n"
/* Bad 3: Bogus annotation */
"@last-listed with strange aeons\n"
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBALcRBFNCZtpd2TFJysU77/fJMFzKisRQEBOtDGtTZ2Bg4aEGosssa0Id\n"
"YtUagRLYle08QVGvGB+EHBI5qf6Ah2yPH7k5QiN2a3Sq+nyh85dXKPazBGBBbM+C\n"
"DOfDauV02CAnADNMLJEf1voY3oBVvYyIsmHxn5i1R19ZYIiR8NX5AgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"ntor-onion-key m4xcFXMWMjCvZDXq8FT3XmS0EHYseGOeu+fV+6FYDlk=\n"
"p accept 20-23,43,53,79-81,88,110,143,194,220,389,443,464,531,543-544\n"
"id rsa1024 SSbfNE9vmaiwRKH+eqNAkiKQhds\n"
/* Good 10: Normal, with added ipv6 address and added other address */
"onion-key\n"
"-----BEGIN RSA PUBLIC KEY-----\n"
"MIGJAoGBAM7uUtq5F6h63QNYIvC+4NcWaD0DjtnrOORZMkdpJhinXUOwce3cD5Dj\n"
"sgdN1wJpWpTQMXJ2DssfSgmOVXETP7qJuZyRprxalQhaEATMDNJA/66Ml1jSO9mZ\n"
"+8Xb7m/4q778lNtkSbsvMaYD2Dq6k2QQ3kMhr9z8oUtX0XA23+pfAgMBAAE=\n"
"-----END RSA PUBLIC KEY-----\n"
"a [::1:2:3:4]:9090\n"
"a 18.0.0.1:9999\n"
"ntor-onion-key k2yFqTU2vzMCQDEiE/j9UcEHxKrXMLpB3IL0or09sik=\n"
"id rsa1024 2A8wYpHxnkKJ92orocvIQBzeHlE\n"
"p6 allow 80\n"
;
/** More tests for parsing different kinds of microdescriptors, and getting
* invalid digests trackd from them. */
static void
test_md_parse(void *arg)
{
(void) arg;
char *mem_op_hex_tmp = NULL;
smartlist_t *invalid = smartlist_new();
smartlist_t *mds = microdescs_parse_from_string(MD_PARSE_TEST_DATA,
NULL, 1, SAVED_NOWHERE,
invalid);
tt_int_op(smartlist_len(mds), ==, 11);
tt_int_op(smartlist_len(invalid), ==, 4);
test_memeq_hex(smartlist_get(invalid,0),
"5d76bf1c6614e885614a1e0ad074e1ab"
"4ea14655ebeefb1736a71b5ed8a15a51");
test_memeq_hex(smartlist_get(invalid,1),
"2fde0ee3343669c2444cd9d53cbd39c6"
"a7d1fc0513513e840ca7f6e68864b36c");
test_memeq_hex(smartlist_get(invalid,2),
"20d1576c5ab11bbcff0dedb1db4a3cfc"
"c8bc8dd839d8cbfef92d00a1a7d7b294");
test_memeq_hex(smartlist_get(invalid,3),
"074770f394c73dbde7b44412e9692add"
"691a478d4727f9804b77646c95420a96");
/* Spot-check the valid ones. */
const microdesc_t *md = smartlist_get(mds, 5);
test_memeq_hex(md->digest,
"54bb6d733ddeb375d2456c79ae103961"
"da0cae29620375ac4cf13d54da4d92b3");
tt_int_op(md->last_listed, ==, 0);
tt_int_op(md->saved_location, ==, SAVED_NOWHERE);
tt_int_op(md->no_save, ==, 0);
tt_uint_op(md->held_in_map, ==, 0);
tt_uint_op(md->held_by_nodes, ==, 0);
tt_assert(md->onion_curve25519_pkey);
md = smartlist_get(mds, 6);
test_memeq_hex(md->digest,
"53f740bd222ab37f19f604b1d3759aa6"
"5eff1fbce9ac254bd0fa50d4af9b1bae");
tt_assert(! md->exit_policy);
md = smartlist_get(mds, 8);
test_memeq_hex(md->digest,
"a0a155562d8093d8fd0feb7b93b7226e"
"17f056c2142aab7a4ea8c5867a0376d5");
tt_assert(md->onion_curve25519_pkey);
md = smartlist_get(mds, 10);
test_memeq_hex(md->digest,
"409ebd87d23925a2732bd467a92813c9"
"21ca378fcb9ca193d354c51550b6d5e9");
tt_assert(tor_addr_family(&md->ipv6_addr) == AF_INET6);
tt_int_op(md->ipv6_orport, ==, 9090);
done:
SMARTLIST_FOREACH(mds, microdesc_t *, md, microdesc_free(md));
smartlist_free(mds);
SMARTLIST_FOREACH(invalid, char *, cp, tor_free(cp));
smartlist_free(invalid);
tor_free(mem_op_hex_tmp);
}
static int mock_rgsbd_called = 0;
static routerstatus_t *mock_rgsbd_val_a = NULL;
static routerstatus_t *mock_rgsbd_val_b = NULL;
static routerstatus_t *
mock_router_get_status_by_digest(networkstatus_t *c, const char *d)
{
(void) c;
++mock_rgsbd_called;
if (fast_memeq(d, "\x5d\x76", 2)) {
memcpy(mock_rgsbd_val_a->descriptor_digest, d, 32);
return mock_rgsbd_val_a;
} else if (fast_memeq(d, "\x20\xd1", 2)) {
memcpy(mock_rgsbd_val_b->descriptor_digest, d, 32);
return mock_rgsbd_val_b;
} else {
return NULL;
}
}
static networkstatus_t *mock_ns_val = NULL;
static networkstatus_t *
mock_ns_get_by_flavor(consensus_flavor_t f)
{
(void)f;
return mock_ns_val;
}
static void
test_md_reject_cache(void *arg)
{
(void) arg;
microdesc_cache_t *mc = NULL ;
smartlist_t *added = NULL, *wanted = smartlist_new();
or_options_t *options = get_options_mutable();
char buf[DIGEST256_LEN];
tor_free(options->DataDirectory);
options->DataDirectory = tor_strdup(get_fname("md_datadir_test_rej"));
mock_rgsbd_val_a = tor_malloc_zero(sizeof(routerstatus_t));
mock_rgsbd_val_b = tor_malloc_zero(sizeof(routerstatus_t));
mock_ns_val = tor_malloc_zero(sizeof(networkstatus_t));
mock_ns_val->valid_after = time(NULL) - 86400;
mock_ns_val->valid_until = time(NULL) + 86400;
mock_ns_val->flavor = FLAV_MICRODESC;
#ifdef _WIN32
tt_int_op(0, ==, mkdir(options->DataDirectory));
#else
tt_int_op(0, ==, mkdir(options->DataDirectory, 0700));
#endif
MOCK(router_get_mutable_consensus_status_by_descriptor_digest,
mock_router_get_status_by_digest);
MOCK(networkstatus_get_latest_consensus_by_flavor, mock_ns_get_by_flavor);
mc = get_microdesc_cache();
#define ADD(hex) \
do { \
tt_int_op(0,==,base16_decode(buf,sizeof(buf),hex,strlen(hex))); \
smartlist_add(wanted, tor_memdup(buf, DIGEST256_LEN)); \
} while (0)
/* invalid,0 */
ADD("5d76bf1c6614e885614a1e0ad074e1ab4ea14655ebeefb1736a71b5ed8a15a51");
/* invalid,2 */
ADD("20d1576c5ab11bbcff0dedb1db4a3cfcc8bc8dd839d8cbfef92d00a1a7d7b294");
/* valid, 6 */
ADD("53f740bd222ab37f19f604b1d3759aa65eff1fbce9ac254bd0fa50d4af9b1bae");
/* valid, 8 */
ADD("a0a155562d8093d8fd0feb7b93b7226e17f056c2142aab7a4ea8c5867a0376d5");
added = microdescs_add_to_cache(mc, MD_PARSE_TEST_DATA, NULL,
SAVED_NOWHERE, 0, time(NULL), wanted);
tt_int_op(smartlist_len(added), ==, 2);
tt_int_op(mock_rgsbd_called, ==, 2);
tt_int_op(mock_rgsbd_val_a->dl_status.n_download_failures, ==, 255);
tt_int_op(mock_rgsbd_val_b->dl_status.n_download_failures, ==, 255);
done:
UNMOCK(networkstatus_get_latest_consensus_by_flavor);
UNMOCK(router_get_mutable_consensus_status_by_descriptor_digest);
if (options)
tor_free(options->DataDirectory);
microdesc_free_all();
smartlist_free(added);
SMARTLIST_FOREACH(wanted, char *, cp, tor_free(cp));
smartlist_free(wanted);
tor_free(mock_rgsbd_val_a);
tor_free(mock_rgsbd_val_b);
tor_free(mock_ns_val);
}
struct testcase_t microdesc_tests[] = {
{ "cache", test_md_cache, TT_FORK, NULL, NULL },
{ "broken_cache", test_md_cache_broken, TT_FORK, NULL, NULL },
{ "generate", test_md_generate, 0, NULL, NULL },
{ "parse", test_md_parse, 0, NULL, NULL },
{ "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL },
END_OF_TESTCASES
};