Loading doc/TODO +7 −1 Changes for doc/TODO: 7 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -54,7 +54,13 @@ N . Document transport and natdport Things we'd like to do in 0.2.0.x: - Proposals: - 101: Voting on the Tor Directory System - 104: Long and Short Router Descriptors (by Jun 1) . 104: Long and Short Router Descriptors (by Jun 1) . Finalize proposal - Implement parsing for extra-info documents; have authorities accept them and serve them from specified URLs - Have routers generate and upload extra-info documents. - Implement option to download and cache extra-info documents. - Drop bandwidth history from router-descriptors - 105: Version negotiation for the Tor protocol (finalize by Jun 1) - Refactoring: - Make resolves no longer use edge_connection_t unless they are actually Loading doc/spec/proposals/104-short-descriptors.txt +4 −3 Changes for doc/spec/proposals/104-short-descriptors.txt: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ Specification: An "extra info" descriptor contains the following fields: "extra-info" Nickname IP Fingerprint "extra-info" Nickname Fingerprint Identifies what router this is an extra info descriptor for. Fingerprint is encoded in hex (using upper-case letters), with no spaces. Loading @@ -67,7 +67,7 @@ Specification: "read-history" "write-history" As currently documented in dir-spec.txt. As currently documented in dir-spec.txt. Optional. "router-signature" NL Signature NL Loading Loading @@ -99,7 +99,8 @@ Specification: "caches-extra-info" Present if this router is a directory cache that provides extra-info documents. extra-info documents, or an authority that handles extra-info documents. (Since implementations before 0.1.2.5-alpha required that "opt" keyword precede any unrecognized entry with "opt", these keys MUST be preceded Loading src/or/or.h +14 −0 Changes for src/or/or.h: 14 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1080,10 +1080,12 @@ typedef struct { smartlist_t *declared_family; /**< Nicknames of router which this router * claims are its family. */ char *contact_info; /**< Declared contact info for this router. */ char extra_info_digest[DIGEST_LEN]; /**< DOCDOC */ unsigned int is_hibernating:1; /**< Whether the router claims to be * hibernating */ unsigned int has_old_dnsworkers:1; /**< Whether the router is using * dnsworker code. */ unsigned int caches_extra_info:1; /**< DOCDOC */ /* local info */ unsigned int is_running:1; /**< As far as we know, is this OR currently Loading Loading @@ -1121,6 +1123,13 @@ typedef struct { int routerlist_index; } routerinfo_t; /** DOCDOC */ typedef struct extrainfo_t { signed_descriptor_t cache_info; char nickname[MAX_NICKNAME_LEN+1]; char *pending_sig; } extrainfo_t; /** Contents of a single router entry in a network status object. */ typedef struct routerstatus_t { Loading Loading @@ -2991,6 +3000,8 @@ void dump_routerlist_mem_usage(int severity); void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old); void routerinfo_free(routerinfo_t *router); void extrainfo_free(extrainfo_t *extrainfo); void routerstatus_free(routerstatus_t *routerstatus); void networkstatus_free(networkstatus_t *networkstatus); void routerlist_free_all(void); Loading Loading @@ -3076,6 +3087,7 @@ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_get_runningrouters_hash(const char *s, char *digest); int router_get_networkstatus_v2_hash(const char *s, char *digest); int router_get_extrainfo_hash(const char *s, char *digest); int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, crypto_pk_env_t *private_key); Loading @@ -3091,6 +3103,8 @@ int router_parse_runningrouters(const char *str); int router_parse_directory(const char *str); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end, int cache_copy); extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end, int cache_copy, digestmap_t *routermap); addr_policy_t *router_parse_addr_policy_from_string(const char *s, int assume_action); version_status_t tor_version_is_obsolete(const char *myversion, Loading src/or/routerlist.c +11 −0 Changes for src/or/routerlist.c: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1506,6 +1506,17 @@ routerinfo_free(routerinfo_t *router) tor_free(router); } /** DOCDOC */ void extrainfo_free(extrainfo_t *extrainfo) { if (!extrainfo) return; tor_free(extrainfo->cache_info.signed_descriptor_body); tor_free(extrainfo->pending_sig); tor_free(extrainfo); } /** Release storage held by <b>sd</b>. */ static void signed_descriptor_free(signed_descriptor_t *sd) Loading src/or/routerparse.c +151 −5 Changes for src/or/routerparse.c: 151 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -56,6 +56,9 @@ typedef enum { K_S, K_V, K_EVENTDNS, K_EXTRA_INFO, K_EXTRA_INFO_DIGEST, K_CACHES_EXTRA_INFO, _UNRECOGNIZED, _ERR, _EOF, Loading Loading @@ -106,7 +109,8 @@ typedef enum { NETSTATUS = 4, /**< v2 or later ("versioned") network status. */ ANYSIGNED = 7, /**< Any "full" document (that is, not a router status.) */ RTRSTATUS = 8, /**< Router-status portion of a versioned network status. */ ANY = 15, /**< Appears in any document type. */ EXTRAINFO = 16, /**< DOCDOC */ ANY = 31, /**< Appears in any document type. */ } where_syntax; /** Table mapping keywords to token value and to argument rules. */ Loading @@ -125,12 +129,12 @@ static struct { { "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ, DIR }, { "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY,RTR }, { "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY,RTR }, { "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ,RTR }, { "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ,RTR|EXTRAINFO }, { "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ, DIR }, { "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ, DIR }, { "bandwidth", K_BANDWIDTH, ARGS, NO_OBJ, RTR }, { "platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ, RTR }, { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANYSIGNED|EXTRAINFO }, { "opt", K_OPT, CONCAT_ARGS, OBJ_OK, ANY }, { "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ, DIR }, Loading @@ -140,8 +144,8 @@ static struct { { "family", K_FAMILY, ARGS, NO_OBJ, RTR }, { "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "hibernating", K_HIBERNATING, ARGS, NO_OBJ, RTR }, { "read-history", K_READ_HISTORY, ARGS, NO_OBJ, RTR }, { "write-history", K_WRITE_HISTORY, ARGS, NO_OBJ, RTR }, { "read-history", K_READ_HISTORY, ARGS, NO_OBJ, RTR|EXTRAINFO }, { "write-history", K_WRITE_HISTORY, ARGS, NO_OBJ, RTR|EXTRAINFO }, { "network-status-version", K_NETWORK_STATUS_VERSION, ARGS, NO_OBJ, NETSTATUS }, { "dir-source", K_DIR_SOURCE, ARGS, NO_OBJ, NETSTATUS }, Loading @@ -149,6 +153,9 @@ static struct { { "client-versions", K_CLIENT_VERSIONS, ARGS, NO_OBJ, NETSTATUS }, { "server-versions", K_SERVER_VERSIONS, ARGS, NO_OBJ, NETSTATUS }, { "eventdns", K_EVENTDNS, ARGS, NO_OBJ, RTR }, { "extra-info", K_EXTRA_INFO, ARGS, NO_OBJ, EXTRAINFO }, { "extra-info-digest", K_EXTRA_INFO_DIGEST, ARGS, NO_OBJ, RTR }, { "caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ, RTR }, { NULL, _NIL, NO_ARGS, NO_OBJ, ANY } }; Loading Loading @@ -213,6 +220,14 @@ router_get_networkstatus_v2_hash(const char *s, char *digest) "network-status-version","\ndirectory-signature"); } /** DOCDOC */ int router_get_extrainfo_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature"); } /** Helper: used to generate signatures for routers, directories and * network-status objects. Given a digest in <b>digest</b> and a secret * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it, Loading Loading @@ -934,6 +949,19 @@ router_parse_entry_from_string(const char *s, const char *end, } } if ((tok = find_first_by_keyword(tokens, K_CACHES_EXTRA_INFO))) router->caches_extra_info = 1; if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST)) && tok->n_args) { if (strlen(tok->args[0]) == HEX_DIGEST_LEN) { base16_decode(router->extra_info_digest, DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN); } else { log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0])); } } if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) { log_warn(LD_DIR, "Missing router signature"); goto err; Loading Loading @@ -983,6 +1011,124 @@ router_parse_entry_from_string(const char *s, const char *end, return router; } /* DOCDOC */ extrainfo_t * extrainfo_parse_entry_from_string(const char *s, const char *end, int cache_copy, digestmap_t *routermap) { extrainfo_t *extrainfo = NULL; char signed_digest[128]; char digest[128]; smartlist_t *tokens = NULL; directory_token_t *tok; int t; crypto_pk_env_t *key = NULL; routerinfo_t *router; if (!end) { end = s + strlen(s); } /* point 'end' to a point immediately after the final newline. */ while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n') --end; if (router_get_extrainfo_hash(s, digest) < 0) { log_warn(LD_DIR, "Couldn't compute router hash."); return NULL; } tokens = smartlist_create(); if (tokenize_string(s,end,tokens,EXTRAINFO)) { log_warn(LD_DIR, "Error tokeninzing router descriptor."); goto err; } if (smartlist_len(tokens) < 2) { log_warn(LD_DIR, "Impossibly short router descriptor."); goto err; } tok = smartlist_get(tokens,0); if (tok->tp != K_EXTRA_INFO) { log_warn(LD_DIR,"Entry does not start with \"extra-info\""); goto err; } extrainfo = tor_malloc_zero(sizeof(extrainfo_t)); if (cache_copy) extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s); extrainfo->cache_info.signed_descriptor_len = end-s; memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); if (tok->n_args < 2) { log_warn(LD_DIR,"Insufficient arguments to \"extra-info\""); goto err; } if (!is_legal_nickname(tok->args[0])) { log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0])); goto err; } strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname)); if (strlen(tok->args[1]) != HEX_DIGEST_LEN || base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN, tok->args[1], HEX_DIGEST_LEN)) { log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"", escaped(tok->args[1])); goto err; } if (!(tok = find_first_by_keyword(tokens, K_PUBLISHED))) { log_warn(LD_DIR,"No published time on \"extra-info\""); goto err; } if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) { log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"", escaped(tok->args[0])); goto err; } if (routermap && (router = digestmap_get(routermap, extrainfo->cache_info.identity_digest))) { key = router->identity_pkey; } if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) { log_warn(LD_DIR, "Missing router signature"); goto err; } if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) { log_warn(LD_DIR, "Bad object type or length on router signature"); goto err; } if (key) { note_crypto_pk_op(VERIFY_RTR); if ((t=crypto_pk_public_checksig(key, signed_digest, tok->object_body, 128)) != 20) { log_warn(LD_DIR, "Invalid signature %d",t); goto err; } if (memcmp(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Mismatched signature"); goto err; } } else { extrainfo->pending_sig = tor_memdup(tok->object_body, 128); } goto done; err: // extrainfo_free(extrainfo); // DOCDOC extrainfo = NULL; done: if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok)); smartlist_free(tokens); } return extrainfo; } /** Helper: given a string <b>s</b>, return the start of the next router-status * object (starting with "r " at the start of a line). If none is found, * return the start of the next directory signature. If none is found, return Loading Loading
doc/TODO +7 −1 Changes for doc/TODO: 7 added lines, 1 removed line. Original line number Diff line number Diff line Loading @@ -54,7 +54,13 @@ N . Document transport and natdport Things we'd like to do in 0.2.0.x: - Proposals: - 101: Voting on the Tor Directory System - 104: Long and Short Router Descriptors (by Jun 1) . 104: Long and Short Router Descriptors (by Jun 1) . Finalize proposal - Implement parsing for extra-info documents; have authorities accept them and serve them from specified URLs - Have routers generate and upload extra-info documents. - Implement option to download and cache extra-info documents. - Drop bandwidth history from router-descriptors - 105: Version negotiation for the Tor protocol (finalize by Jun 1) - Refactoring: - Make resolves no longer use edge_connection_t unless they are actually Loading
doc/spec/proposals/104-short-descriptors.txt +4 −3 Changes for doc/spec/proposals/104-short-descriptors.txt: 4 added lines, 3 removed lines. Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ Specification: An "extra info" descriptor contains the following fields: "extra-info" Nickname IP Fingerprint "extra-info" Nickname Fingerprint Identifies what router this is an extra info descriptor for. Fingerprint is encoded in hex (using upper-case letters), with no spaces. Loading @@ -67,7 +67,7 @@ Specification: "read-history" "write-history" As currently documented in dir-spec.txt. As currently documented in dir-spec.txt. Optional. "router-signature" NL Signature NL Loading Loading @@ -99,7 +99,8 @@ Specification: "caches-extra-info" Present if this router is a directory cache that provides extra-info documents. extra-info documents, or an authority that handles extra-info documents. (Since implementations before 0.1.2.5-alpha required that "opt" keyword precede any unrecognized entry with "opt", these keys MUST be preceded Loading
src/or/or.h +14 −0 Changes for src/or/or.h: 14 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1080,10 +1080,12 @@ typedef struct { smartlist_t *declared_family; /**< Nicknames of router which this router * claims are its family. */ char *contact_info; /**< Declared contact info for this router. */ char extra_info_digest[DIGEST_LEN]; /**< DOCDOC */ unsigned int is_hibernating:1; /**< Whether the router claims to be * hibernating */ unsigned int has_old_dnsworkers:1; /**< Whether the router is using * dnsworker code. */ unsigned int caches_extra_info:1; /**< DOCDOC */ /* local info */ unsigned int is_running:1; /**< As far as we know, is this OR currently Loading Loading @@ -1121,6 +1123,13 @@ typedef struct { int routerlist_index; } routerinfo_t; /** DOCDOC */ typedef struct extrainfo_t { signed_descriptor_t cache_info; char nickname[MAX_NICKNAME_LEN+1]; char *pending_sig; } extrainfo_t; /** Contents of a single router entry in a network status object. */ typedef struct routerstatus_t { Loading Loading @@ -2991,6 +3000,8 @@ void dump_routerlist_mem_usage(int severity); void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old); void routerinfo_free(routerinfo_t *router); void extrainfo_free(extrainfo_t *extrainfo); void routerstatus_free(routerstatus_t *routerstatus); void networkstatus_free(networkstatus_t *networkstatus); void routerlist_free_all(void); Loading Loading @@ -3076,6 +3087,7 @@ int router_get_router_hash(const char *s, char *digest); int router_get_dir_hash(const char *s, char *digest); int router_get_runningrouters_hash(const char *s, char *digest); int router_get_networkstatus_v2_hash(const char *s, char *digest); int router_get_extrainfo_hash(const char *s, char *digest); int router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest, crypto_pk_env_t *private_key); Loading @@ -3091,6 +3103,8 @@ int router_parse_runningrouters(const char *str); int router_parse_directory(const char *str); routerinfo_t *router_parse_entry_from_string(const char *s, const char *end, int cache_copy); extrainfo_t *extrainfo_parse_entry_from_string(const char *s, const char *end, int cache_copy, digestmap_t *routermap); addr_policy_t *router_parse_addr_policy_from_string(const char *s, int assume_action); version_status_t tor_version_is_obsolete(const char *myversion, Loading
src/or/routerlist.c +11 −0 Changes for src/or/routerlist.c: 11 added lines, 0 removed lines. Original line number Diff line number Diff line Loading @@ -1506,6 +1506,17 @@ routerinfo_free(routerinfo_t *router) tor_free(router); } /** DOCDOC */ void extrainfo_free(extrainfo_t *extrainfo) { if (!extrainfo) return; tor_free(extrainfo->cache_info.signed_descriptor_body); tor_free(extrainfo->pending_sig); tor_free(extrainfo); } /** Release storage held by <b>sd</b>. */ static void signed_descriptor_free(signed_descriptor_t *sd) Loading
src/or/routerparse.c +151 −5 Changes for src/or/routerparse.c: 151 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -56,6 +56,9 @@ typedef enum { K_S, K_V, K_EVENTDNS, K_EXTRA_INFO, K_EXTRA_INFO_DIGEST, K_CACHES_EXTRA_INFO, _UNRECOGNIZED, _ERR, _EOF, Loading Loading @@ -106,7 +109,8 @@ typedef enum { NETSTATUS = 4, /**< v2 or later ("versioned") network status. */ ANYSIGNED = 7, /**< Any "full" document (that is, not a router status.) */ RTRSTATUS = 8, /**< Router-status portion of a versioned network status. */ ANY = 15, /**< Appears in any document type. */ EXTRAINFO = 16, /**< DOCDOC */ ANY = 31, /**< Appears in any document type. */ } where_syntax; /** Table mapping keywords to token value and to argument rules. */ Loading @@ -125,12 +129,12 @@ static struct { { "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ, DIR }, { "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY,RTR }, { "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY,RTR }, { "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ,RTR }, { "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ,RTR|EXTRAINFO }, { "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ, DIR }, { "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ, DIR }, { "bandwidth", K_BANDWIDTH, ARGS, NO_OBJ, RTR }, { "platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ, RTR }, { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ, ANYSIGNED|EXTRAINFO }, { "opt", K_OPT, CONCAT_ARGS, OBJ_OK, ANY }, { "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ, DIR }, Loading @@ -140,8 +144,8 @@ static struct { { "family", K_FAMILY, ARGS, NO_OBJ, RTR }, { "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ, ANYSIGNED }, { "hibernating", K_HIBERNATING, ARGS, NO_OBJ, RTR }, { "read-history", K_READ_HISTORY, ARGS, NO_OBJ, RTR }, { "write-history", K_WRITE_HISTORY, ARGS, NO_OBJ, RTR }, { "read-history", K_READ_HISTORY, ARGS, NO_OBJ, RTR|EXTRAINFO }, { "write-history", K_WRITE_HISTORY, ARGS, NO_OBJ, RTR|EXTRAINFO }, { "network-status-version", K_NETWORK_STATUS_VERSION, ARGS, NO_OBJ, NETSTATUS }, { "dir-source", K_DIR_SOURCE, ARGS, NO_OBJ, NETSTATUS }, Loading @@ -149,6 +153,9 @@ static struct { { "client-versions", K_CLIENT_VERSIONS, ARGS, NO_OBJ, NETSTATUS }, { "server-versions", K_SERVER_VERSIONS, ARGS, NO_OBJ, NETSTATUS }, { "eventdns", K_EVENTDNS, ARGS, NO_OBJ, RTR }, { "extra-info", K_EXTRA_INFO, ARGS, NO_OBJ, EXTRAINFO }, { "extra-info-digest", K_EXTRA_INFO_DIGEST, ARGS, NO_OBJ, RTR }, { "caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ, RTR }, { NULL, _NIL, NO_ARGS, NO_OBJ, ANY } }; Loading Loading @@ -213,6 +220,14 @@ router_get_networkstatus_v2_hash(const char *s, char *digest) "network-status-version","\ndirectory-signature"); } /** DOCDOC */ int router_get_extrainfo_hash(const char *s, char *digest) { return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature"); } /** Helper: used to generate signatures for routers, directories and * network-status objects. Given a digest in <b>digest</b> and a secret * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it, Loading Loading @@ -934,6 +949,19 @@ router_parse_entry_from_string(const char *s, const char *end, } } if ((tok = find_first_by_keyword(tokens, K_CACHES_EXTRA_INFO))) router->caches_extra_info = 1; if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST)) && tok->n_args) { if (strlen(tok->args[0]) == HEX_DIGEST_LEN) { base16_decode(router->extra_info_digest, DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN); } else { log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0])); } } if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) { log_warn(LD_DIR, "Missing router signature"); goto err; Loading Loading @@ -983,6 +1011,124 @@ router_parse_entry_from_string(const char *s, const char *end, return router; } /* DOCDOC */ extrainfo_t * extrainfo_parse_entry_from_string(const char *s, const char *end, int cache_copy, digestmap_t *routermap) { extrainfo_t *extrainfo = NULL; char signed_digest[128]; char digest[128]; smartlist_t *tokens = NULL; directory_token_t *tok; int t; crypto_pk_env_t *key = NULL; routerinfo_t *router; if (!end) { end = s + strlen(s); } /* point 'end' to a point immediately after the final newline. */ while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n') --end; if (router_get_extrainfo_hash(s, digest) < 0) { log_warn(LD_DIR, "Couldn't compute router hash."); return NULL; } tokens = smartlist_create(); if (tokenize_string(s,end,tokens,EXTRAINFO)) { log_warn(LD_DIR, "Error tokeninzing router descriptor."); goto err; } if (smartlist_len(tokens) < 2) { log_warn(LD_DIR, "Impossibly short router descriptor."); goto err; } tok = smartlist_get(tokens,0); if (tok->tp != K_EXTRA_INFO) { log_warn(LD_DIR,"Entry does not start with \"extra-info\""); goto err; } extrainfo = tor_malloc_zero(sizeof(extrainfo_t)); if (cache_copy) extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s); extrainfo->cache_info.signed_descriptor_len = end-s; memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN); if (tok->n_args < 2) { log_warn(LD_DIR,"Insufficient arguments to \"extra-info\""); goto err; } if (!is_legal_nickname(tok->args[0])) { log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0])); goto err; } strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname)); if (strlen(tok->args[1]) != HEX_DIGEST_LEN || base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN, tok->args[1], HEX_DIGEST_LEN)) { log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"", escaped(tok->args[1])); goto err; } if (!(tok = find_first_by_keyword(tokens, K_PUBLISHED))) { log_warn(LD_DIR,"No published time on \"extra-info\""); goto err; } if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) { log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"", escaped(tok->args[0])); goto err; } if (routermap && (router = digestmap_get(routermap, extrainfo->cache_info.identity_digest))) { key = router->identity_pkey; } if (!(tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE))) { log_warn(LD_DIR, "Missing router signature"); goto err; } if (strcmp(tok->object_type, "SIGNATURE") || tok->object_size != 128) { log_warn(LD_DIR, "Bad object type or length on router signature"); goto err; } if (key) { note_crypto_pk_op(VERIFY_RTR); if ((t=crypto_pk_public_checksig(key, signed_digest, tok->object_body, 128)) != 20) { log_warn(LD_DIR, "Invalid signature %d",t); goto err; } if (memcmp(digest, signed_digest, DIGEST_LEN)) { log_warn(LD_DIR, "Mismatched signature"); goto err; } } else { extrainfo->pending_sig = tor_memdup(tok->object_body, 128); } goto done; err: // extrainfo_free(extrainfo); // DOCDOC extrainfo = NULL; done: if (tokens) { SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok)); smartlist_free(tokens); } return extrainfo; } /** Helper: given a string <b>s</b>, return the start of the next router-status * object (starting with "r " at the start of a line). If none is found, * return the start of the next directory signature. If none is found, return Loading