|
@@ -373,25 +373,6 @@ static token_rule_t dir_footer_token_table[] = {
|
|
|
END_OF_TABLE
|
|
|
};
|
|
|
|
|
|
-/** List of tokens recognized in v1 directory headers/footers. */
|
|
|
-static token_rule_t dir_token_table[] = {
|
|
|
- /* don't enforce counts; this is obsolete. */
|
|
|
- T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
|
|
|
- T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
|
|
|
- T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
|
|
|
- T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
|
|
|
-
|
|
|
- T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
|
|
|
- T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
|
|
|
- T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
|
|
|
- T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
|
|
|
- T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
|
|
|
- T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
|
|
|
- T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
|
|
|
-
|
|
|
- END_OF_TABLE
|
|
|
-};
|
|
|
-
|
|
|
/** List of tokens common to V3 authority certificates and V3 consensuses. */
|
|
|
#define CERTIFICATE_MEMBERS \
|
|
|
T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
|
|
@@ -576,7 +557,6 @@ static int check_signature_token(const char *digest,
|
|
|
crypto_pk_t *pkey,
|
|
|
int flags,
|
|
|
const char *doctype);
|
|
|
-static crypto_pk_t *find_dir_signing_key(const char *str, const char *eos);
|
|
|
|
|
|
#undef DEBUG_AREA_ALLOC
|
|
|
|
|
@@ -819,218 +799,6 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
|
|
|
- * Otherwise, return -1. If we're a directory cache, cache it.
|
|
|
- */
|
|
|
-int
|
|
|
-router_parse_directory(const char *str)
|
|
|
-{
|
|
|
- directory_token_t *tok;
|
|
|
- char digest[DIGEST_LEN];
|
|
|
- time_t published_on;
|
|
|
- int r;
|
|
|
- const char *end, *cp, *str_dup = str;
|
|
|
- smartlist_t *tokens = NULL;
|
|
|
- crypto_pk_t *declared_key = NULL;
|
|
|
- memarea_t *area = memarea_new();
|
|
|
-
|
|
|
- /* XXXX This could be simplified a lot, but it will all go away
|
|
|
- * once pre-0.1.1.8 is obsolete, and for now it's better not to
|
|
|
- * touch it. */
|
|
|
-
|
|
|
- if (router_get_dir_hash(str, digest)) {
|
|
|
- log_warn(LD_DIR, "Unable to compute digest of directory");
|
|
|
- goto err;
|
|
|
- }
|
|
|
- log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
|
|
|
-
|
|
|
- /* Check signature first, before we try to tokenize. */
|
|
|
- cp = str;
|
|
|
- while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
|
|
|
- cp = end;
|
|
|
- if (cp == str || !cp) {
|
|
|
- log_warn(LD_DIR, "No signature found on directory."); goto err;
|
|
|
- }
|
|
|
- ++cp;
|
|
|
- tokens = smartlist_new();
|
|
|
- if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
|
|
|
- log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
|
|
|
- }
|
|
|
- if (smartlist_len(tokens) != 1) {
|
|
|
- log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
|
|
|
- }
|
|
|
- tok=smartlist_get(tokens,0);
|
|
|
- if (tok->tp != K_DIRECTORY_SIGNATURE) {
|
|
|
- log_warn(LD_DIR,"Expected a single directory signature"); goto err;
|
|
|
- }
|
|
|
- declared_key = find_dir_signing_key(str, str+strlen(str));
|
|
|
- note_crypto_pk_op(VERIFY_DIR);
|
|
|
- if (check_signature_token(digest, DIGEST_LEN, tok, declared_key,
|
|
|
- CST_CHECK_AUTHORITY, "directory")<0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
|
|
- smartlist_clear(tokens);
|
|
|
- memarea_clear(area);
|
|
|
-
|
|
|
- /* Now try to parse the first part of the directory. */
|
|
|
- if ((end = strstr(str,"\nrouter "))) {
|
|
|
- ++end;
|
|
|
- } else if ((end = strstr(str, "\ndirectory-signature"))) {
|
|
|
- ++end;
|
|
|
- } else {
|
|
|
- end = str + strlen(str);
|
|
|
- }
|
|
|
-
|
|
|
- if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
|
|
|
- log_warn(LD_DIR, "Error tokenizing directory"); goto err;
|
|
|
- }
|
|
|
-
|
|
|
- tok = find_by_keyword(tokens, K_PUBLISHED);
|
|
|
- tor_assert(tok->n_args == 1);
|
|
|
-
|
|
|
- if (parse_iso_time(tok->args[0], &published_on) < 0) {
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- /* Now that we know the signature is okay, and we have a
|
|
|
- * publication time, cache the directory. */
|
|
|
- if (directory_caches_v1_dir_info(get_options()) &&
|
|
|
- !authdir_mode_v1(get_options()))
|
|
|
- dirserv_set_cached_directory(str, published_on, 0);
|
|
|
-
|
|
|
- r = 0;
|
|
|
- goto done;
|
|
|
- err:
|
|
|
- dump_desc(str_dup, "v1 directory");
|
|
|
- r = -1;
|
|
|
- done:
|
|
|
- if (declared_key) crypto_pk_free(declared_key);
|
|
|
- if (tokens) {
|
|
|
- SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
|
|
- smartlist_free(tokens);
|
|
|
- }
|
|
|
- if (area) {
|
|
|
- DUMP_AREA(area, "v1 directory");
|
|
|
- memarea_drop_all(area);
|
|
|
- }
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
-/** Read a signed router status statement from <b>str</b>. If it's
|
|
|
- * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
|
|
|
- * cache it.*/
|
|
|
-int
|
|
|
-router_parse_runningrouters(const char *str)
|
|
|
-{
|
|
|
- char digest[DIGEST_LEN];
|
|
|
- directory_token_t *tok;
|
|
|
- time_t published_on;
|
|
|
- int r = -1;
|
|
|
- crypto_pk_t *declared_key = NULL;
|
|
|
- smartlist_t *tokens = NULL;
|
|
|
- const char *eos = str + strlen(str), *str_dup = str;
|
|
|
- memarea_t *area = NULL;
|
|
|
-
|
|
|
- if (router_get_runningrouters_hash(str, digest)) {
|
|
|
- log_warn(LD_DIR, "Unable to compute digest of running-routers");
|
|
|
- goto err;
|
|
|
- }
|
|
|
- area = memarea_new();
|
|
|
- tokens = smartlist_new();
|
|
|
- if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
|
|
|
- log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
|
|
|
- }
|
|
|
- tok = smartlist_get(tokens,0);
|
|
|
- if (tok->tp != K_NETWORK_STATUS) {
|
|
|
- log_warn(LD_DIR, "Network-status starts with wrong token");
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- tok = find_by_keyword(tokens, K_PUBLISHED);
|
|
|
- tor_assert(tok->n_args == 1);
|
|
|
- if (parse_iso_time(tok->args[0], &published_on) < 0) {
|
|
|
- goto err;
|
|
|
- }
|
|
|
- if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
|
|
|
- log_warn(LD_DIR, "Missing signature on running-routers");
|
|
|
- goto err;
|
|
|
- }
|
|
|
- declared_key = find_dir_signing_key(str, eos);
|
|
|
- note_crypto_pk_op(VERIFY_DIR);
|
|
|
- if (check_signature_token(digest, DIGEST_LEN, tok, declared_key,
|
|
|
- CST_CHECK_AUTHORITY, "running-routers")
|
|
|
- < 0)
|
|
|
- goto err;
|
|
|
-
|
|
|
- /* Now that we know the signature is okay, and we have a
|
|
|
- * publication time, cache the list. */
|
|
|
- if (get_options()->DirPort_set && !authdir_mode_v1(get_options()))
|
|
|
- dirserv_set_cached_directory(str, published_on, 1);
|
|
|
-
|
|
|
- r = 0;
|
|
|
- err:
|
|
|
- dump_desc(str_dup, "v1 running-routers");
|
|
|
- if (declared_key) crypto_pk_free(declared_key);
|
|
|
- if (tokens) {
|
|
|
- SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
|
|
|
- smartlist_free(tokens);
|
|
|
- }
|
|
|
- if (area) {
|
|
|
- DUMP_AREA(area, "v1 running-routers");
|
|
|
- memarea_drop_all(area);
|
|
|
- }
|
|
|
- return r;
|
|
|
-}
|
|
|
-
|
|
|
-/** Given a directory or running-routers string in <b>str</b>, try to
|
|
|
- * find the its dir-signing-key token (if any). If this token is
|
|
|
- * present, extract and return the key. Return NULL on failure. */
|
|
|
-static crypto_pk_t *
|
|
|
-find_dir_signing_key(const char *str, const char *eos)
|
|
|
-{
|
|
|
- const char *cp;
|
|
|
- directory_token_t *tok;
|
|
|
- crypto_pk_t *key = NULL;
|
|
|
- memarea_t *area = NULL;
|
|
|
- tor_assert(str);
|
|
|
- tor_assert(eos);
|
|
|
-
|
|
|
- /* Is there a dir-signing-key in the directory? */
|
|
|
- cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
|
|
|
- if (!cp)
|
|
|
- cp = tor_memstr(str, eos-str, "\ndir-signing-key");
|
|
|
- if (!cp)
|
|
|
- return NULL;
|
|
|
- ++cp; /* Now cp points to the start of the token. */
|
|
|
-
|
|
|
- area = memarea_new();
|
|
|
- tok = get_next_token(area, &cp, eos, dir_token_table);
|
|
|
- if (!tok) {
|
|
|
- log_warn(LD_DIR, "Unparseable dir-signing-key token");
|
|
|
- goto done;
|
|
|
- }
|
|
|
- if (tok->tp != K_DIR_SIGNING_KEY) {
|
|
|
- log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
|
|
|
- goto done;
|
|
|
- }
|
|
|
-
|
|
|
- if (tok->key) {
|
|
|
- key = tok->key;
|
|
|
- tok->key = NULL; /* steal reference. */
|
|
|
- } else {
|
|
|
- log_warn(LD_DIR, "Dir-signing-key token contained no key");
|
|
|
- }
|
|
|
-
|
|
|
- done:
|
|
|
- if (tok) token_clear(tok);
|
|
|
- if (area) {
|
|
|
- DUMP_AREA(area, "dir-signing-key token");
|
|
|
- memarea_drop_all(area);
|
|
|
- }
|
|
|
- return key;
|
|
|
-}
|
|
|
-
|
|
|
/** Return true iff <b>key</b> is allowed to sign directories.
|
|
|
*/
|
|
|
static int
|