mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-23 22:47:12 +01:00
r12385@catbus: nickm | 2007-04-15 22:55:58 -0400
Initial code to parse extra-info documents as described in proposal 104. This is making me realize that the parsing code in routerparse.c is a little daft. svn:r9963
This commit is contained in:
parent
785c59e468
commit
5b220f65c8
5 changed files with 187 additions and 9 deletions
8
doc/TODO
8
doc/TODO
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
14
src/or/or.h
14
src/or/or.h
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
@ -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. */
|
||||
|
@ -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 },
|
||||
|
@ -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 },
|
||||
|
@ -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 }
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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…
Add table
Reference in a new issue