mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-12-06 19:41:15 +01:00
r13387@catbus: nickm | 2007-06-13 14:15:49 -0400
Unit tests and debugging for vote generation and parsing code. svn:r10587
This commit is contained in:
+17
-9
@@ -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);
|
||||
|
||||
@@ -732,3 +732,4 @@ authority_cert_dup(authority_cert_t *cert)
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
+150
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user