diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-06-13 18:16:05 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-06-13 18:16:05 +0000 |
commit | 0cf38ddef6af877a056a9c181fe2fd76d5c81ec5 (patch) | |
tree | e1e3e37f21e096e843a994922b745b38d7f10105 | |
parent | 09a370e45fce560ca23f855a5fcbe50c0d04149e (diff) | |
download | tor-0cf38ddef6af877a056a9c181fe2fd76d5c81ec5.tar.gz tor-0cf38ddef6af877a056a9c181fe2fd76d5c81ec5.zip |
r13387@catbus: nickm | 2007-06-13 14:15:49 -0400
Unit tests and debugging for vote generation and parsing code.
svn:r10587
-rw-r--r-- | src/or/dirserv.c | 26 | ||||
-rw-r--r-- | src/or/dirvote.c | 1 | ||||
-rw-r--r-- | src/or/or.h | 6 | ||||
-rw-r--r-- | src/or/routerparse.c | 13 | ||||
-rw-r--r-- | src/or/test.c | 150 |
5 files changed, 182 insertions, 14 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 974b80f502..b4fe5d49d2 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -5,6 +5,7 @@ const char dirserv_c_id[] = "$Id$"; +#define DIRSERV_PRIVATE #include "or.h" /** @@ -1592,7 +1593,6 @@ version_from_platform(const char *platform) return NULL; } - /** Helper: write the router-status information in <b>rs</b> into <b>buf</b>, * which has at least <b>buf_len</b> free characters. Do NUL-termination. * Use the same format as in network-status documents. If <b>platform</b> is @@ -1827,7 +1827,7 @@ generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, v3_out->server_versions = server_versions; v3_out->known_flags = smartlist_create(); smartlist_split_string(v3_out->known_flags, - "Authority Exit Fast Guard Running Stable Valid V2Dir", + "Authority Exit Fast Guard Running Stable V2Dir Valid", 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); if (listbadexits) smartlist_add(v3_out->known_flags, tor_strdup("BadExit")); @@ -1853,8 +1853,9 @@ generate_networkstatus_vote_obj(crypto_pk_env_t *private_key, return v3_out; } -static char * -format_networkstatus_vote(crypto_pk_env_t *private_key, +/* private DOCDOC */ +char * +format_networkstatus_vote(crypto_pk_env_t *private_signing_key, networkstatus_vote_t *v3_ns) { /** Longest status flag name that we generate. */ @@ -1890,7 +1891,7 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, networkstatus_voter_info_t *voter; /* XXX check that everything gets freed */ - tor_assert(private_key); + tor_assert(private_signing_key); voter = smartlist_get(v3_ns->voters, 0); @@ -1950,11 +1951,13 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, "valid-after %s\n" "fresh-until %s\n" "valid-until %s\n" + "voting-delay %d %d\n" "%s" /* versions */ - "known-flags %s" + "known-flags %s\n" "dir-source %s %s %s %s %d %d\n" "contact %s\n", published, va, fu, vu, + v3_ns->vote_seconds, v3_ns->dist_seconds, version_lines, flags, voter->nickname, fingerprint, voter->address, @@ -1988,7 +1991,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, } outp += strlen(outp); - if (crypto_pk_get_fingerprint(private_key, signing_key_fingerprint, 0)<0) { + if (crypto_pk_get_fingerprint(private_signing_key, + signing_key_fingerprint, 0)<0) { log_warn(LD_BUG, "Unable to get fingerprint for signing key"); goto err; } @@ -2000,8 +2004,11 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, outp += strlen(outp); } + if (router_get_networkstatus_v3_hash(status, digest)<0) + goto err; note_crypto_pk_op(SIGN_DIR); - if (router_append_dirobj_signature(outp,endp-outp,digest,private_key)<0) { + if (router_append_dirobj_signature(outp,endp-outp,digest, + private_signing_key)<0) { log_warn(LD_BUG, "Unable to sign networkstatus vote."); goto err; } @@ -2009,7 +2016,8 @@ format_networkstatus_vote(crypto_pk_env_t *private_key, { networkstatus_vote_t *v; if (!(v = networkstatus_parse_vote_from_string(status, 1))) { - log_err(LD_BUG,"Generated a networkstatus vote we couldn't parse."); + log_err(LD_BUG,"Generated a networkstatus vote we couldn't parse: " + "<<%s>>", status); goto err; } networkstatus_vote_free(v); diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 19d8ef308d..8eda6f03bb 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -732,3 +732,4 @@ authority_cert_dup(authority_cert_t *cert) return out; } + diff --git a/src/or/or.h b/src/or/or.h index cf6fe12d7d..a34a03bf93 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2747,6 +2747,12 @@ int routerstatus_format_entry(char *buf, size_t buf_len, void dirserv_free_all(void); void cached_dir_decref(cached_dir_t *d); +#ifdef DIRSERV_PRIVATE +char * +format_networkstatus_vote(crypto_pk_env_t *private_key, + networkstatus_vote_t *v3_ns); +#endif + /********************************* dirvote.c ************************/ void networkstatus_vote_free(networkstatus_vote_t *ns); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index d5670a88ad..96f4e3c542 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -296,7 +296,7 @@ static token_rule_t networkstatus_vote_token_table[] = { T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ), T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ), T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ), - T1("known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ), + T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ), T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ), CERTIFICATE_MEMBERS @@ -304,7 +304,6 @@ static token_rule_t networkstatus_vote_token_table[] = { T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ), T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ), T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ), - T1( "dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ), T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ), T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ), T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ), @@ -1842,7 +1841,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) if (!ok) goto err; ns->dist_seconds = - (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL); + (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL); if (!ok) goto err; @@ -1860,8 +1859,10 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) inorder = 1; for (i = 0; i < tok->n_args; ++i) { smartlist_add(ns->known_flags, tok->args[i]); - if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) + if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) { + log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]); inorder = 0; + } } tok->n_args = 0; /* suppress free of args members, but not of args itself. */ if (!inorder) { @@ -1895,6 +1896,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) escaped(tok->args[3])); goto err; } + voter->addr = ntohl(in.s_addr); voter->dir_port = (uint64_t) (int) tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL); if (!ok) @@ -2039,6 +2041,7 @@ networkstatus_parse_vote_from_string(const char *s, int is_vote) v->pending_signature_len = tok->object_size; } }); + /* XXXX020 enforce: vote must have at least one signature. */ /* XXXX020 check dates for plausibility. ??? */ @@ -2456,7 +2459,7 @@ get_next_token(const char **s, token_rule_t *table) *s = next; } else { tok->object_body = tor_malloc(next-*s); /* really, this is too much RAM. */ - i = base64_decode(tok->object_body, 256, *s, next-*s); + i = base64_decode(tok->object_body, next-*s, *s, next-*s); if (i<0) { RET_ERR("Malformed object: bad base64-encoded data"); } diff --git a/src/or/test.c b/src/or/test.c index 20ac1780b0..26f42f976b 100644 --- a/src/or/test.c +++ b/src/or/test.c @@ -29,6 +29,8 @@ const char tor_svn_revision[] = ""; * are typically file-private. */ #define CONFIG_PRIVATE #define CONTROL_PRIVATE +#define CRYPTO_PRIVATE +#define DIRSERV_PRIVATE #define MEMPOOL_PRIVATE #define ROUTER_PRIVATE @@ -2125,9 +2127,157 @@ test_dir_format(void) "Tor 0.2.1.0-dev (r99)")); } +extern const char AUTHORITY_CERT_1[]; +extern const char AUTHORITY_IDKEY_1[]; +extern const char AUTHORITY_SIGNKEY_1[]; +extern const char AUTHORITY_CERT_2[]; +extern const char AUTHORITY_IDKEY_2[]; +extern const char AUTHORITY_SIGNKEY_2[]; + static void test_v3_networkstatus(void) { + authority_cert_t *cert1, *cert2;//, *cert_tmp; + crypto_pk_env_t *id_skey_1, *id_skey_2; + crypto_pk_env_t *sign_skey_1, *sign_skey_2; + + time_t now = time(NULL); + networkstatus_voter_info_t *voter; + networkstatus_vote_t *vote, *v1; + vote_routerstatus_t *vrs; + routerstatus_t *rs; + char *v1_text, *cp; + + add_stream_log(LOG_NOTICE, LOG_ERR, "", stdout); + + /* Parse certificates and keys. */ + cert1 = authority_cert_parse_from_string(AUTHORITY_CERT_1, NULL); + test_assert(cert1); + cert2 = authority_cert_parse_from_string(AUTHORITY_CERT_2, NULL); + test_assert(cert2); + id_skey_1 = crypto_new_pk_env(); + id_skey_2 = crypto_new_pk_env(); + sign_skey_1 = crypto_new_pk_env(); + sign_skey_2 = crypto_new_pk_env(); + + test_assert(!crypto_pk_read_private_key_from_string(id_skey_1, + AUTHORITY_IDKEY_1)); + test_assert(!crypto_pk_read_private_key_from_string(id_skey_2, + AUTHORITY_IDKEY_2)); + test_assert(!crypto_pk_read_private_key_from_string(sign_skey_1, + AUTHORITY_SIGNKEY_1)); + test_assert(!crypto_pk_read_private_key_from_string(sign_skey_2, + AUTHORITY_SIGNKEY_2)); + + test_assert(!crypto_pk_cmp_keys(id_skey_1, cert1->identity_key)); + test_assert(!crypto_pk_cmp_keys(sign_skey_1, cert1->signing_key)); + test_assert(!crypto_pk_cmp_keys(id_skey_2, cert2->identity_key)); + test_assert(!crypto_pk_cmp_keys(sign_skey_2, cert2->signing_key)); + + /* + * Set up a vote; generate it; try to parse it. + */ + vote = tor_malloc_zero(sizeof(networkstatus_vote_t)); + vote->is_vote = 1; + vote->published = now; + vote->valid_after = now+100; + vote->fresh_until = now+200; + vote->valid_until = now+300; + vote->vote_seconds = 100; + vote->dist_seconds = 200; + vote->client_versions = tor_strdup("0.1.2.14,0.1.2.15"); + vote->server_versions = tor_strdup("0.1.2.14,0.1.2.15,0.1.2.16"); + vote->known_flags = smartlist_create(); + smartlist_split_string(vote->known_flags, + "Authority Exit Fast Guard Running Stable V2Dir Valid", + 0, SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0); + vote->voters = smartlist_create(); + voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t)); + voter->nickname = tor_strdup("Voter1"); + voter->address = tor_strdup("1.2.3.4"); + voter->addr = 0x01020304; + voter->dir_port = 80; + voter->or_port = 9000; + voter->contact = tor_strdup("voter1@example.com"); + crypto_pk_get_digest(id_skey_1, voter->identity_digest); + smartlist_add(vote->voters, voter); + vote->cert = authority_cert_dup(cert1); + vote->routerstatus_list = smartlist_create(); + /* add the first routerstatus. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.1.2.14"); + rs->published_on = now-1500; + strlcpy(rs->nickname, "router2", sizeof(rs->nickname)); + memset(rs->identity_digest, 3, DIGEST_LEN); + memset(rs->descriptor_digest, 11, DIGEST_LEN); + rs->addr = 0x99008801; + rs->or_port = 443; + rs->dir_port = 8000; + /* all flags cleared */ + smartlist_add(vote->routerstatus_list, vrs); + /* add the second routerstatus. */ + vrs = tor_malloc_zero(sizeof(vote_routerstatus_t)); + rs = &vrs->status; + vrs->version = tor_strdup("0.2.0.5"); + rs->published_on = now-1000; + strlcpy(rs->nickname, "router1", sizeof(rs->nickname)); + memset(rs->identity_digest, 5, DIGEST_LEN); + memset(rs->descriptor_digest, 2, DIGEST_LEN); + rs->addr = 0x99009901; + rs->or_port = 443; + rs->dir_port = 0; + rs->is_exit = rs->is_stable = rs->is_fast = rs->is_running = + rs->is_v2_dir = rs->is_possible_guard = 1; + // rs->named = rs->is_bad_exit = rs->is_bad_directory = 1; + smartlist_add(vote->routerstatus_list, vrs); + + /* dump the vote and try to parse it. */ + v1_text = format_networkstatus_vote(sign_skey_1, vote); + test_assert(v1_text); + v1 = networkstatus_parse_vote_from_string(v1_text, 1); + test_assert(v1); + + /* Make sure the parsed thing was right. */ + test_eq(v1->is_vote, 1); + test_eq(v1->published, vote->published); + test_eq(v1->valid_after, vote->valid_after); + test_eq(v1->fresh_until, vote->fresh_until); + test_eq(v1->valid_until, vote->valid_until); + test_eq(v1->vote_seconds, vote->vote_seconds); + test_eq(v1->dist_seconds, vote->dist_seconds); + test_streq(v1->client_versions, vote->client_versions); + test_streq(v1->server_versions, vote->server_versions); + test_assert(v1->voters && smartlist_len(v1->voters)); + voter = smartlist_get(v1->voters, 0); + test_streq(voter->nickname, "Voter1"); + test_streq(voter->address, "1.2.3.4"); + test_eq(voter->addr, 0x01020304); + test_eq(voter->dir_port, 80); + test_eq(voter->or_port, 9000); + test_streq(voter->contact, "voter1@example.com"); + test_assert(v1->cert); + test_assert(!crypto_pk_cmp_keys(id_skey_1, v1->cert->identity_key)); + test_assert(!crypto_pk_cmp_keys(sign_skey_1, v1->cert->signing_key)); + cp = smartlist_join_strings(v1->known_flags, ":", 0, NULL); + test_streq(cp, "Authority:Exit:Fast:Guard:Running:Stable:V2Dir:Valid"); + tor_free(cp); + test_eq(smartlist_len(v1->routerstatus_list), 2); + /*XXXX020 test contents of v1->routerstatus_list. */ + + /* XXXXX020 Generate 2 more votes */ + + /* XXXXX020 compute, write, and parse a consensus. */ + + tor_free(v1_text); + networkstatus_vote_free(vote); + networkstatus_vote_free(v1); + crypto_free_pk_env(id_skey_1); + crypto_free_pk_env(id_skey_2); + crypto_free_pk_env(sign_skey_1); + crypto_free_pk_env(sign_skey_2); + authority_cert_free(cert1); + authority_cert_free(cert2); } static void |