1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2007, Roger Dingledine, Nick Mathewson. */
4 /* See LICENSE for licensing information */
6 const char routerparse_c_id
[] =
11 * \brief Code to parse and validate router descriptors and directories.
16 /****************************************************************************/
18 /** Enumeration of possible token types. The ones starting with K_ correspond
19 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
20 * is an end-of-file marker, and _NIL is used to encode not-a-token.
24 K_DIRECTORY_SIGNATURE
,
25 K_RECOMMENDED_SOFTWARE
,
48 K_NETWORK_STATUS_VERSION
,
61 K_DIR_KEY_CERTIFICATE_VERSION
,
65 K_DIR_KEY_CERTIFICATION
,
89 #define MIN_ANNOTATION A_PURPOSE
90 #define MAX_ANNOTATION _A_UNKNOWN
92 /** Structure to hold a single directory token.
94 * We parse a directory by breaking it into "tokens", each consisting
95 * of a keyword, a line full of arguments, and a binary object. The
96 * arguments and object are both optional, depending on the keyword
99 typedef struct directory_token_t
{
100 directory_keyword tp
; /**< Type of the token. */
101 int n_args
; /**< Number of elements in args */
102 char **args
; /**< Array of arguments from keyword line. */
103 char *object_type
; /**< -----BEGIN [object_type]-----*/
104 size_t object_size
; /**< Bytes in object_body */
105 char *object_body
; /**< Contents of object, base64-decoded. */
106 crypto_pk_env_t
*key
; /**< For public keys only. */
107 char *error
; /**< For _ERR tokens only. */
110 /* ********************************************************************** */
112 /** We use a table of rules to decide how to parse each token type. */
114 /** Rules for whether the keyword needs an object. */
116 NO_OBJ
, /**< No object, ever. */
117 NEED_OBJ
, /**< Object is required. */
118 NEED_KEY_1024
, /**< Object is required, and must be a 1024 bit public key */
119 NEED_KEY
, /**< Object is required, and must be a public key. */
120 OBJ_OK
, /**< Object is optional. */
126 /** Determines the parsing rules for a single token type. */
127 typedef struct token_rule_t
{
128 /** The string value of the keyword identifying the type of item. */
130 /** The corresponding directory_keyword enum. */
132 /** Minimum number of arguments for this item */
134 /** Maximum number of arguments for this item */
136 /** If true, we concatenate all arguments for this item into a single
139 /** Requirments on object syntax for this item. */
141 /** Lowest number of times this item may appear in a document. */
143 /** Highest number of times this item may appear in a document. */
145 /** One or more of AT_START/AT_END to limit where the item may appear in a
148 /** True iff this token is an annotation. */
153 * Helper macros to define token tables. 's' is a string, 't' is a
154 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
159 /** Appears to indicate the end of a table. */
160 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
161 /** An item with no restrictions: used for obsolete document types */
162 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
163 /** An item with no restrictions on multiplicity or location. */
164 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
165 /** An item that must appear exactly once */
166 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
167 /** An item that must appear exactly once, at the start of the document */
168 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
169 /** An item that must appear exactly once, at the end of the document */
170 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
171 /** An item that must appear one or more times */
172 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
173 /** An item that must appear no more than once */
174 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
175 /** An annotation that must appear no more than once */
176 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
178 /* Argument multiplicity: any number of arguments. */
179 #define ARGS 0,INT_MAX,0
180 /* Argument multiplicity: no arguments. */
181 #define NO_ARGS 0,0,0
182 /* Argument multiplicity: concatenate all arguments. */
183 #define CONCAT_ARGS 1,1,1
184 /* Argument multiplicity: at least <b>n</b> arguments. */
185 #define GE(n) n,INT_MAX,0
186 /* Argument multiplicity: exactly <b>n</b> arguments. */
189 /** List of tokens allowable in router derscriptors */
190 static token_rule_t routerdesc_token_table
[] = {
191 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
192 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
193 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
194 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
195 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
196 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
197 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
198 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
199 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
200 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
201 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
202 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
203 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
204 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
205 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
207 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
208 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
209 T01("eventdns", K_EVENTDNS
, ARGS
, NO_OBJ
),
211 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
212 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
213 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
218 /** List of tokens allowable in extra-info documents. */
219 static token_rule_t extrainfo_token_table
[] = {
220 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
221 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
222 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
223 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
224 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
225 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
230 /** List of tokens allowable in the body part of v2 and v3 networkstatus
232 static token_rule_t rtrstatus_token_table
[] = {
233 T1( "r", K_R
, GE(8), NO_OBJ
),
234 T1( "s", K_S
, ARGS
, NO_OBJ
),
235 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
236 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
240 /** List of tokens allowable in the header part of v2 networkstatus documents.
242 static token_rule_t netstatus_token_table
[] = {
243 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
244 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
245 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
246 T1( "dir-signing-key", K_DIR_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
247 T1( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
248 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
250 T1( "dir-source", K_DIR_SOURCE
, GE(3), NO_OBJ
),
251 T01("dir-options", K_DIR_OPTIONS
, ARGS
, NO_OBJ
),
252 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
253 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
258 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
260 static token_rule_t dir_footer_token_table
[] = {
261 T1("directory-signature", K_DIRECTORY_SIGNATURE
, EQ(1), NEED_OBJ
),
265 /** List of tokens allowable in v1 diectory headers/footers. */
266 static token_rule_t dir_token_table
[] = {
267 /* don't enforce counts; this is obsolete. */
268 T( "network-status", K_NETWORK_STATUS
, NO_ARGS
, NO_OBJ
),
269 T( "directory-signature", K_DIRECTORY_SIGNATURE
, ARGS
, NEED_OBJ
),
270 T( "recommended-software",K_RECOMMENDED_SOFTWARE
,CONCAT_ARGS
, NO_OBJ
),
271 T( "signed-directory", K_SIGNED_DIRECTORY
, NO_ARGS
, NO_OBJ
),
273 T( "running-routers", K_RUNNING_ROUTERS
, ARGS
, NO_OBJ
),
274 T( "router-status", K_ROUTER_STATUS
, ARGS
, NO_OBJ
),
275 T( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
276 T( "opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
277 T( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
278 T( "dir-signing-key", K_DIR_SIGNING_KEY
, ARGS
, OBJ_OK
),
279 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
284 #define CERTIFICATE_MEMBERS \
285 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
287 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
288 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
289 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
290 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
291 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
292 NO_ARGS, NEED_OBJ), \
293 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
295 static token_rule_t dir_key_certificate_table
[] = {
297 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
301 static token_rule_t networkstatus_vote_token_table
[] = {
302 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
304 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
305 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
306 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
307 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
308 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
309 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
310 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
311 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
315 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
316 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
317 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
318 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
319 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
320 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
321 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
325 static token_rule_t networkstatus_consensus_token_table
[] = {
326 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
328 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
329 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
330 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
331 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
332 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
334 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
336 T1N("dir-source", K_DIR_SOURCE
, GE(3), NO_OBJ
),
337 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
338 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
340 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
342 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
343 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
344 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
349 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
351 static token_rule_t networkstatus_vote_footer_token_table
[] = {
352 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
356 static token_rule_t networkstatus_detached_signature_token_table
[] = {
357 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
358 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
359 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
360 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
361 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
367 /* static function prototypes */
368 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
369 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
);
370 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
372 static int router_get_hash_impl(const char *s
, char *digest
,
373 const char *start_str
, const char *end_str
,
375 static void token_free(directory_token_t
*tok
);
376 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
377 static directory_token_t
*find_first_by_keyword(smartlist_t
*s
,
378 directory_keyword keyword
);
379 #define TS_ANNOTATIONS_OK 1
381 #define TS_NO_NEW_ANNOTATIONS 4
382 static int tokenize_string(const char *start
, const char *end
,
386 static directory_token_t
*get_next_token(const char **s
,
388 token_rule_t
*table
);
389 static int check_signature_token(const char *digest
,
390 directory_token_t
*tok
,
391 crypto_pk_env_t
*pkey
,
393 const char *doctype
);
394 static crypto_pk_env_t
*find_dir_signing_key(const char *str
, const char *eos
);
395 static int tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
);
397 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
398 * <b>s</b>. Return 0 on success, -1 on failure.
401 router_get_dir_hash(const char *s
, char *digest
)
403 return router_get_hash_impl(s
,digest
,
404 "signed-directory","\ndirectory-signature",'\n');
407 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
408 * <b>s</b>. Return 0 on success, -1 on failure.
411 router_get_router_hash(const char *s
, char *digest
)
413 return router_get_hash_impl(s
,digest
,
414 "router ","\nrouter-signature", '\n');
417 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
418 * string in <b>s</b>. Return 0 on success, -1 on failure.
421 router_get_runningrouters_hash(const char *s
, char *digest
)
423 return router_get_hash_impl(s
,digest
,
424 "network-status","\ndirectory-signature", '\n');
427 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
428 * string in <b>s</b>. Return 0 on success, -1 on failure. */
430 router_get_networkstatus_v2_hash(const char *s
, char *digest
)
432 return router_get_hash_impl(s
,digest
,
433 "network-status-version","\ndirectory-signature",
437 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
438 * string in <b>s</b>. Return 0 on success, -1 on failure. */
440 router_get_networkstatus_v3_hash(const char *s
, char *digest
)
442 return router_get_hash_impl(s
,digest
,
443 "network-status-version","\ndirectory-signature",
447 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
448 * string in <b>s</b>. Return 0 on success, -1 on failure. */
450 router_get_extrainfo_hash(const char *s
, char *digest
)
452 return router_get_hash_impl(s
,digest
,"extra-info","\nrouter-signature",'\n');
455 /** Helper: used to generate signatures for routers, directories and
456 * network-status objects. Given a digest in <b>digest</b> and a secret
457 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
458 * surround it with -----BEGIN/END----- pairs, and write it to the
459 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
463 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
464 crypto_pk_env_t
*private_key
)
469 signature
= tor_malloc(crypto_pk_keysize(private_key
));
470 if (crypto_pk_private_sign(private_key
, signature
, digest
, DIGEST_LEN
) < 0) {
472 log_warn(LD_BUG
,"Couldn't sign digest.");
475 if (strlcat(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
479 if (base64_encode(buf
+i
, buf_len
-i
, signature
, 128) < 0) {
480 log_warn(LD_BUG
,"couldn't base64-encode signature");
485 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
492 log_warn(LD_BUG
,"tried to exceed string length.");
498 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
499 * <b>versionlist</b>. Else, return VS_OLD if every member of
500 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
501 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
502 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
503 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
504 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
507 * (versionlist is a comma-separated list of version strings,
508 * optionally prefixed with "Tor". Versions that can't be parsed are
512 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
514 tor_version_t mine
, other
;
515 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
516 found_any_in_series
= 0, r
, same
;
517 version_status_t ret
= VS_UNRECOMMENDED
;
518 smartlist_t
*version_sl
;
520 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
521 myversion
, versionlist
);
523 if (tor_version_parse(myversion
, &mine
)) {
524 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
527 version_sl
= smartlist_create();
528 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
530 SMARTLIST_FOREACH(version_sl
, const char *, cp
, {
531 if (!strcmpstart(cp
, "Tor "))
534 if (tor_version_parse(cp
, &other
)) {
535 /* Couldn't parse other; it can't be a match. */
537 same
= tor_version_same_series(&mine
, &other
);
539 found_any_in_series
= 1;
540 r
= tor_version_compare(&mine
, &other
);
542 ret
= VS_RECOMMENDED
;
547 found_newer_in_series
= 1;
554 /* We didn't find the listed version. Is it new or old? */
555 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
556 ret
= VS_NEW_IN_SERIES
;
557 } else if (found_newer
&& !found_older
) {
559 } else if (found_older
&& !found_newer
) {
562 ret
= VS_UNRECOMMENDED
;
566 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
567 smartlist_free(version_sl
);
571 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
572 * Otherwise, return -1. If we're a directory cache, cache it.
575 router_parse_directory(const char *str
)
577 directory_token_t
*tok
;
578 char digest
[DIGEST_LEN
];
581 const char *end
, *cp
;
582 smartlist_t
*tokens
= NULL
;
583 crypto_pk_env_t
*declared_key
= NULL
;
585 /* XXXX This could be simplified a lot, but it will all go away
586 * once pre-0.1.1.8 is obsolete, and for now it's better not to
589 if (router_get_dir_hash(str
, digest
)) {
590 log_warn(LD_DIR
, "Unable to compute digest of directory");
593 log_debug(LD_DIR
,"Received directory hashes to %s",hex_str(digest
,4));
595 /* Check signature first, before we try to tokenize. */
597 while (cp
&& (end
= strstr(cp
+1, "\ndirectory-signature")))
599 if (cp
== str
|| !cp
) {
600 log_warn(LD_DIR
, "No signature found on directory."); goto err
;
603 tokens
= smartlist_create();
604 if (tokenize_string(cp
,strchr(cp
,'\0'),tokens
,dir_token_table
,0)) {
605 log_warn(LD_DIR
, "Error tokenizing directory signature"); goto err
;
607 if (smartlist_len(tokens
) != 1) {
608 log_warn(LD_DIR
, "Unexpected number of tokens in signature"); goto err
;
610 tok
=smartlist_get(tokens
,0);
611 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
612 log_warn(LD_DIR
,"Expected a single directory signature"); goto err
;
614 declared_key
= find_dir_signing_key(str
, str
+strlen(str
));
615 note_crypto_pk_op(VERIFY_DIR
);
616 if (check_signature_token(digest
, tok
, declared_key
, 1, "directory")<0)
619 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
620 smartlist_free(tokens
);
623 /* Now try to parse the first part of the directory. */
624 if ((end
= strstr(str
,"\nrouter "))) {
626 } else if ((end
= strstr(str
, "\ndirectory-signature"))) {
629 end
= str
+ strlen(str
);
632 tokens
= smartlist_create();
633 if (tokenize_string(str
,end
,tokens
,dir_token_table
,0)) {
634 log_warn(LD_DIR
, "Error tokenizing directory"); goto err
;
637 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
639 tor_assert(tok
->n_args
== 1);
641 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
645 /* Now that we know the signature is okay, and we have a
646 * publication time, cache the directory. */
647 if (dirserver_mode(get_options()) && !authdir_mode_v1(get_options()))
648 dirserv_set_cached_directory(str
, published_on
, 0);
655 if (declared_key
) crypto_free_pk_env(declared_key
);
657 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
658 smartlist_free(tokens
);
663 /** Read a signed router status statement from <b>str</b>. If it's
664 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
667 router_parse_runningrouters(const char *str
)
669 char digest
[DIGEST_LEN
];
670 directory_token_t
*tok
;
673 crypto_pk_env_t
*declared_key
= NULL
;
674 smartlist_t
*tokens
= NULL
;
675 const char *eos
= str
+ strlen(str
);
677 if (router_get_runningrouters_hash(str
, digest
)) {
678 log_warn(LD_DIR
, "Unable to compute digest of running-routers");
681 tokens
= smartlist_create();
682 if (tokenize_string(str
,eos
,tokens
,dir_token_table
,0)) {
683 log_warn(LD_DIR
, "Error tokenizing running-routers"); goto err
;
685 tok
= smartlist_get(tokens
,0);
686 if (tok
->tp
!= K_NETWORK_STATUS
) {
687 log_warn(LD_DIR
, "Network-status starts with wrong token");
691 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
693 tor_assert(tok
->n_args
== 1);
694 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
697 if (!(tok
= find_first_by_keyword(tokens
, K_DIRECTORY_SIGNATURE
))) {
698 log_warn(LD_DIR
, "Missing signature on running-routers");
701 declared_key
= find_dir_signing_key(str
, eos
);
702 note_crypto_pk_op(VERIFY_DIR
);
703 if (check_signature_token(digest
, tok
, declared_key
, 1, "running-routers")
707 /* Now that we know the signature is okay, and we have a
708 * publication time, cache the list. */
709 if (get_options()->DirPort
&& !authdir_mode_v1(get_options()))
710 dirserv_set_cached_directory(str
, published_on
, 1);
714 if (declared_key
) crypto_free_pk_env(declared_key
);
716 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
717 smartlist_free(tokens
);
722 /** Given a directory or running-routers string in <b>str</b>, try to
723 * find the its dir-signing-key token (if any). If this token is
724 * present, extract and return the key. Return NULL on failure. */
725 static crypto_pk_env_t
*
726 find_dir_signing_key(const char *str
, const char *eos
)
729 directory_token_t
*tok
;
730 crypto_pk_env_t
*key
= NULL
;
734 /* Is there a dir-signing-key in the directory? */
735 cp
= tor_memstr(str
, eos
-str
, "\nopt dir-signing-key");
737 cp
= tor_memstr(str
, eos
-str
, "\ndir-signing-key");
740 ++cp
; /* Now cp points to the start of the token. */
742 tok
= get_next_token(&cp
, eos
, dir_token_table
);
744 log_warn(LD_DIR
, "Unparseable dir-signing-key token");
747 if (tok
->tp
!= K_DIR_SIGNING_KEY
) {
748 log_warn(LD_DIR
, "Dir-signing-key token did not parse as expected");
754 tok
->key
= NULL
; /* steal reference. */
756 log_warn(LD_DIR
, "Dir-signing-key token contained no key");
764 /** Return true iff <b>key</b> is allowed to sign directories.
767 dir_signing_key_is_trusted(crypto_pk_env_t
*key
)
769 char digest
[DIGEST_LEN
];
771 if (crypto_pk_get_digest(key
, digest
) < 0) {
772 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
775 if (!router_digest_is_trusted_dir(digest
)) {
776 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
782 /** Check whether the object body of the token in <b>tok</b> has a good
783 * signature for <b>digest</b> using key <b>pkey</b>. If
784 * <b>check_authority</b> is set, make sure that <b>pkey</b> is the key of a
785 * directory authority. Use <b>doctype</b> as the type of the document when
786 * generating log messages. Return 0 on success, negative on failure.
789 check_signature_token(const char *digest
,
790 directory_token_t
*tok
,
791 crypto_pk_env_t
*pkey
,
802 if (check_authority
&& !dir_signing_key_is_trusted(pkey
)) {
803 log_warn(LD_DIR
, "Key on %s did not come from an authority; rejecting",
808 if (strcmp(tok
->object_type
, "SIGNATURE")) {
809 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
813 signed_digest
= tor_malloc(tok
->object_size
);
814 if (crypto_pk_public_checksig(pkey
, signed_digest
, tok
->object_body
,
817 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
818 tor_free(signed_digest
);
821 log_debug(LD_DIR
,"Signed %s hash starts %s", doctype
,
822 hex_str(signed_digest
,4));
823 if (memcmp(digest
, signed_digest
, DIGEST_LEN
)) {
824 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
825 tor_free(signed_digest
);
828 tor_free(signed_digest
);
832 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
833 * or to the first of the annotations proceeding the next router or
834 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
835 * we found an extrainfo, or false if found a router. Do not scan beyond
836 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
838 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
840 int *is_extrainfo_out
)
842 const char *annotations
= NULL
;
843 const char *s
= *s_ptr
;
845 s
= eat_whitespace_eos(s
, eos
);
847 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
848 /* We're at the start of a line. */
849 tor_assert(*s
!= '\n');
851 if (*s
== '@' && !annotations
) {
853 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
854 *s_ptr
= annotations
? annotations
: s
;
855 *is_extrainfo_out
= 0;
857 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
858 *s_ptr
= annotations
? annotations
: s
;
859 *is_extrainfo_out
= 1;
863 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
865 s
= eat_whitespace_eos(s
, eos
);
870 /** Given a string *<b>s</b> containing a concatenated sequence of router
871 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
872 * them and stores the result in <b>dest</b>. All routers are marked running
873 * and valid. Advances *s to a point immediately following the last router
874 * entry. Ignore any trailing router entries that are not complete.
876 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
877 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
878 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
880 * Returns 0 on success and -1 on failure.
883 router_parse_list_from_string(const char **s
, const char *eos
,
885 saved_location_t saved_location
,
887 int allow_annotations
,
888 const char *prepend_annotations
)
890 routerinfo_t
*router
;
891 extrainfo_t
*extrainfo
;
892 signed_descriptor_t
*signed_desc
;
894 const char *end
, *start
;
903 eos
= *s
+ strlen(*s
);
905 tor_assert(eos
>= *s
);
908 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
911 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
913 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
915 end
+= strlen("\n-----END SIGNATURE-----\n");
922 if (have_extrainfo
&& want_extrainfo
) {
923 routerlist_t
*rl
= router_get_routerlist();
924 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
925 saved_location
!= SAVED_IN_CACHE
,
928 signed_desc
= &extrainfo
->cache_info
;
931 } else if (!have_extrainfo
&& !want_extrainfo
) {
932 router
= router_parse_entry_from_string(*s
, end
,
933 saved_location
!= SAVED_IN_CACHE
,
935 prepend_annotations
);
937 signed_desc
= &router
->cache_info
;
945 if (saved_location
!= SAVED_NOWHERE
) {
946 signed_desc
->saved_location
= saved_location
;
947 signed_desc
->saved_offset
= *s
- start
;
950 smartlist_add(dest
, elt
);
956 /* For debugging: define to count every descriptor digest we've seen so we
957 * know if we need to try harder to avoid duplicate verifies. */
958 #undef COUNT_DISTINCT_DIGESTS
960 #ifdef COUNT_DISTINCT_DIGESTS
961 static digestmap_t
*verified_digests
= NULL
;
964 /** Log the total count of the number of distinct router digests we've ever
965 * verified. When compared to the number of times we've verified routerdesc
966 * signatures <i>in toto</i>, this will tell us if we're doing too much
967 * multiple-verification. */
969 dump_distinct_digest_count(int severity
)
971 #ifdef COUNT_DISTINCT_DIGESTS
972 if (!verified_digests
)
973 verified_digests
= digestmap_new();
974 log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
975 digestmap_size(verified_digests
));
977 (void)severity
; /* suppress "unused parameter" warning */
981 /** Helper function: reads a single router entry from *<b>s</b> ...
982 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
983 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
984 * s through end into the signed_descriptor_body of the resulting
987 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
988 * before the router; if it's false, reject the router if it's annotated. If
989 * <b>prepend_annotations</b> is set, it should contain some annotations:
990 * append them to the front of the router before parsing it, and keep them
991 * around when caching the router.
993 * Only one of allow_annotations and prepend_annotations may be set.
996 router_parse_entry_from_string(const char *s
, const char *end
,
997 int cache_copy
, int allow_annotations
,
998 const char *prepend_annotations
)
1000 routerinfo_t
*router
= NULL
;
1002 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1003 directory_token_t
*tok
;
1005 const char *start_of_annotations
, *cp
;
1006 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1008 tor_assert(!allow_annotations
|| !prepend_annotations
);
1011 end
= s
+ strlen(s
);
1014 /* point 'end' to a point immediately after the final newline. */
1015 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1018 tokens
= smartlist_create();
1019 if (prepend_annotations
) {
1020 if (tokenize_string(prepend_annotations
,NULL
,tokens
,
1021 routerdesc_token_table
,TS_NOCHECK
)) {
1022 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1027 start_of_annotations
= s
;
1028 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1030 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1031 log_warn(LD_DIR
, "No router keyword found.");
1038 if (router_get_router_hash(s
, digest
) < 0) {
1039 log_warn(LD_DIR
, "Couldn't compute router hash.");
1044 if (allow_annotations
)
1045 flags
|= TS_ANNOTATIONS_OK
;
1046 if (prepend_annotations
)
1047 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1049 if (tokenize_string(s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1050 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1055 if (smartlist_len(tokens
) < 2) {
1056 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1060 tok
= find_first_by_keyword(tokens
, K_ROUTER
);
1061 tor_assert(tok
->n_args
>= 5);
1063 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1064 router
->routerlist_index
= -1;
1065 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1066 router
->cache_info
.signed_descriptor_len
= end
-s
;
1068 size_t len
= router
->cache_info
.signed_descriptor_len
+
1069 router
->cache_info
.annotations_len
;
1071 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1072 if (prepend_annotations
) {
1073 memcpy(cp
, prepend_annotations
, prepend_len
);
1076 memcpy(cp
, start_of_annotations
, end
-start_of_annotations
);
1077 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1078 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1080 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1082 router
->nickname
= tor_strdup(tok
->args
[0]);
1083 if (!is_legal_nickname(router
->nickname
)) {
1084 log_warn(LD_DIR
,"Router nickname is invalid");
1087 router
->address
= tor_strdup(tok
->args
[1]);
1088 if (!tor_inet_aton(router
->address
, &in
)) {
1089 log_warn(LD_DIR
,"Router address is not an IP.");
1092 router
->addr
= ntohl(in
.s_addr
);
1095 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
1097 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,NULL
,NULL
);
1099 tok
= find_first_by_keyword(tokens
, K_BANDWIDTH
);
1100 tor_assert(tok
&& tok
->n_args
>= 3);
1101 router
->bandwidthrate
=
1102 tor_parse_long(tok
->args
[0],10,0,INT_MAX
,NULL
,NULL
);
1104 if (!router
->bandwidthrate
) {
1105 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1106 escaped(tok
->args
[0]));
1109 router
->bandwidthburst
=
1110 tor_parse_long(tok
->args
[1],10,0,INT_MAX
,NULL
,NULL
);
1111 router
->bandwidthcapacity
=
1112 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,NULL
,NULL
);
1113 /* XXXX020 we don't error-check these values? -RD */
1115 if ((tok
= find_first_by_keyword(tokens
, A_PURPOSE
))) {
1116 tor_assert(tok
->n_args
);
1117 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1119 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1122 if ((tok
= find_first_by_keyword(tokens
, K_UPTIME
))) {
1123 tor_assert(tok
->n_args
>= 1);
1124 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
);
1127 if ((tok
= find_first_by_keyword(tokens
, K_HIBERNATING
))) {
1128 tor_assert(tok
->n_args
>= 1);
1129 router
->is_hibernating
1130 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1133 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1135 tor_assert(tok
->n_args
== 1);
1136 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1139 tok
= find_first_by_keyword(tokens
, K_ONION_KEY
);
1141 router
->onion_pkey
= tok
->key
;
1142 tok
->key
= NULL
; /* Prevent free */
1144 tok
= find_first_by_keyword(tokens
, K_SIGNING_KEY
);
1146 router
->identity_pkey
= tok
->key
;
1147 tok
->key
= NULL
; /* Prevent free */
1148 if (crypto_pk_get_digest(router
->identity_pkey
,
1149 router
->cache_info
.identity_digest
)) {
1150 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1153 if ((tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
))) {
1154 /* If there's a fingerprint line, it must match the identity digest. */
1156 tor_assert(tok
->n_args
== 1);
1157 tor_strstrip(tok
->args
[0], " ");
1158 if (base16_decode(d
, DIGEST_LEN
, tok
->args
[0], strlen(tok
->args
[0]))) {
1159 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1160 escaped(tok
->args
[0]));
1163 if (memcmp(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)!=0) {
1164 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1170 if ((tok
= find_first_by_keyword(tokens
, K_PLATFORM
))) {
1171 router
->platform
= tor_strdup(tok
->args
[0]);
1174 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
))) {
1175 router
->contact_info
= tor_strdup(tok
->args
[0]);
1178 if ((tok
= find_first_by_keyword(tokens
, K_EVENTDNS
))) {
1179 router
->has_old_dnsworkers
= tok
->n_args
&& !strcmp(tok
->args
[0], "0");
1180 } else if (router
->platform
) {
1181 if (! tor_version_as_new_as(router
->platform
, "0.1.2.2-alpha"))
1182 router
->has_old_dnsworkers
= 1;
1185 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1186 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1187 if (router_add_exit_policy(router
,t
)<0) {
1188 log_warn(LD_DIR
,"Error in exit policy");
1192 if ((tok
= find_first_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1194 router
->declared_family
= smartlist_create();
1195 for (i
=0;i
<tok
->n_args
;++i
) {
1196 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1197 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1198 escaped(tok
->args
[i
]));
1201 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
1205 if ((tok
= find_first_by_keyword(tokens
, K_CACHES_EXTRA_INFO
)))
1206 router
->caches_extra_info
= 1;
1208 if ((tok
= find_first_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1209 tor_assert(tok
->n_args
>= 1);
1210 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1211 base16_decode(router
->cache_info
.extra_info_digest
,
1212 DIGEST_LEN
, tok
->args
[0], HEX_DIGEST_LEN
);
1214 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1218 tok
= find_first_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1220 note_crypto_pk_op(VERIFY_RTR
);
1221 #ifdef COUNT_DISTINCT_DIGESTS
1222 if (!verified_digests
)
1223 verified_digests
= digestmap_new();
1224 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
1226 if (check_signature_token(digest
, tok
, router
->identity_pkey
, 0,
1227 "router descriptor") < 0)
1230 if (!router
->or_port
) {
1231 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
1235 if (!router
->platform
) {
1236 router
->platform
= tor_strdup("<unknown>");
1242 routerinfo_free(router
);
1246 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1247 smartlist_free(tokens
);
1249 if (exit_policy_tokens
) {
1250 smartlist_free(exit_policy_tokens
);
1255 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1256 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1257 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1258 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1259 * as a map from router identity to routerinfo_t when looking up signing keys.
1262 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
1263 int cache_copy
, struct digest_ri_map_t
*routermap
)
1265 extrainfo_t
*extrainfo
= NULL
;
1267 smartlist_t
*tokens
= NULL
;
1268 directory_token_t
*tok
;
1269 crypto_pk_env_t
*key
= NULL
;
1270 routerinfo_t
*router
;
1273 end
= s
+ strlen(s
);
1276 /* point 'end' to a point immediately after the final newline. */
1277 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1280 if (router_get_extrainfo_hash(s
, digest
) < 0) {
1281 log_warn(LD_DIR
, "Couldn't compute router hash.");
1284 tokens
= smartlist_create();
1285 if (tokenize_string(s
,end
,tokens
,extrainfo_token_table
,0)) {
1286 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
1290 if (smartlist_len(tokens
) < 2) {
1291 log_warn(LD_DIR
, "Impossibly short extra-info document.");
1295 tok
= smartlist_get(tokens
,0);
1296 if (tok
->tp
!= K_EXTRA_INFO
) {
1297 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
1301 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
1302 extrainfo
->cache_info
.is_extrainfo
= 1;
1304 extrainfo
->cache_info
.signed_descriptor_body
= tor_strndup(s
, end
-s
);
1305 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
1306 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1308 tor_assert(tok
->n_args
>= 2);
1309 if (!is_legal_nickname(tok
->args
[0])) {
1310 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
1313 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
1314 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
1315 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
1316 tok
->args
[1], HEX_DIGEST_LEN
)) {
1317 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
1318 escaped(tok
->args
[1]));
1322 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1324 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
1325 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
1326 escaped(tok
->args
[0]));
1331 (router
= digestmap_get((digestmap_t
*)routermap
,
1332 extrainfo
->cache_info
.identity_digest
))) {
1333 key
= router
->identity_pkey
;
1336 tok
= find_first_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1338 if (strcmp(tok
->object_type
, "SIGNATURE") ||
1339 tok
->object_size
< 128 || tok
->object_size
> 512) {
1340 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
1345 note_crypto_pk_op(VERIFY_RTR
);
1346 if (check_signature_token(digest
, tok
, key
, 0, "extra-info") < 0)
1350 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
1352 extrainfo
->pending_sig_len
= tok
->object_size
;
1358 extrainfo_free(extrainfo
);
1362 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1363 smartlist_free(tokens
);
1368 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1369 * the first character after the certificate. */
1371 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
1373 authority_cert_t
*cert
= NULL
;
1374 smartlist_t
*tokens
= NULL
;
1375 char digest
[DIGEST_LEN
];
1376 directory_token_t
*tok
;
1377 char fp_declared
[DIGEST_LEN
];
1380 trusted_dir_server_t
*ds
;
1383 s
= eat_whitespace(s
);
1384 eos
= strstr(s
, "\n-----END SIGNATURE-----\n");
1386 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
1389 eos
= strchr(eos
+2, '\n');
1394 tokens
= smartlist_create();
1395 if (tokenize_string(s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
1396 log_warn(LD_DIR
, "Error tokenizing key certificate");
1399 if (router_get_hash_impl(s
, digest
, "dir-key-certificate-version",
1400 "\ndir-key-certification", '\n') < 0)
1402 tok
= smartlist_get(tokens
, 0);
1403 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
1405 "Key certificate does not begin with a recognized version (3).");
1409 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
1410 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1412 tok
= find_first_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1413 tor_assert(tok
&& tok
->key
);
1414 cert
->signing_key
= tok
->key
;
1416 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
1419 tok
= find_first_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
1420 tor_assert(tok
&& tok
->key
);
1421 cert
->identity_key
= tok
->key
;
1424 tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
);
1425 tor_assert(tok
&& tok
->n_args
);
1426 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
1427 strlen(tok
->args
[0]))) {
1428 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
1429 escaped(tok
->args
[0]));
1433 if (crypto_pk_get_digest(cert
->identity_key
,
1434 cert
->cache_info
.identity_digest
))
1437 if (memcmp(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
1438 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
1443 tok
= find_first_by_keyword(tokens
, K_DIR_ADDRESS
);
1445 tor_assert(tok
->n_args
);
1446 if (parse_addr_port(LOG_WARN
, tok
->args
[0], NULL
, &cert
->addr
,
1447 &cert
->dir_port
)<0) {
1448 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
1453 tok
= find_first_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
1455 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
1458 tok
= find_first_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
1460 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
1464 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
1465 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
1466 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
1470 /* If we already have this cert, don't bother checking the signature. */
1471 ds
= trusteddirserver_get_by_v3_auth_digest(
1472 cert
->cache_info
.identity_digest
);
1474 if (ds
&& ds
->v3_certs
) {
1475 SMARTLIST_FOREACH(ds
->v3_certs
, authority_cert_t
*, c
,
1477 /* XXXX020 can we just compare signed_descriptor_digest ? */
1478 if (c
->cache_info
.signed_descriptor_len
== len
&&
1479 c
->cache_info
.signed_descriptor_body
&&
1480 !memcmp(s
, c
->cache_info
.signed_descriptor_body
, len
)) {
1481 log_debug(LD_DIR
, "We already checked the signature on this "
1482 "certificate; no need to do so again.");
1489 if (check_signature_token(digest
, tok
, cert
->identity_key
, 0,
1490 "key certificate")) {
1495 cert
->cache_info
.signed_descriptor_len
= len
;
1496 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1497 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
1498 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
1499 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
1501 if (end_of_string
) {
1502 *end_of_string
= eat_whitespace(eos
);
1504 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1505 smartlist_free(tokens
);
1508 authority_cert_free(cert
);
1509 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1510 smartlist_free(tokens
);
1514 /** Helper: given a string <b>s</b>, return the start of the next router-status
1515 * object (starting with "r " at the start of a line). If none is found,
1516 * return the start of the next directory signature. If none is found, return
1517 * the end of the string. */
1518 static INLINE
const char *
1519 find_start_of_next_routerstatus(const char *s
)
1521 const char *eos
= strstr(s
, "\nr ");
1523 const char *eos2
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
1524 if (eos2
&& eos2
< eos
)
1529 if ((eos
= strstr(s
, "\ndirectory-signature")))
1531 return s
+ strlen(s
);
1535 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1536 * empty smartlist at <b>tokens</b>, parse and return the first router status
1537 * object in the string, and advance *<b>s</b> to just after the end of the
1538 * router status. Return NULL and advance *<b>s</b> on error.
1540 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1541 * routerstatus but use <b>vote_rs</b> instead.
1543 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1544 * consensus, and we should parse it according to the method used to
1545 * make that consensus.
1547 static routerstatus_t
*
1548 routerstatus_parse_entry_from_string(const char **s
, smartlist_t
*tokens
,
1549 networkstatus_vote_t
*vote
,
1550 vote_routerstatus_t
*vote_rs
,
1551 int consensus_method
)
1554 routerstatus_t
*rs
= NULL
;
1555 directory_token_t
*tok
;
1556 char timebuf
[ISO_TIME_LEN
+1];
1559 tor_assert(bool_eq(vote
, vote_rs
));
1561 eos
= find_start_of_next_routerstatus(*s
);
1563 if (tokenize_string(*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
1564 log_warn(LD_DIR
, "Error tokenizing router status");
1567 if (smartlist_len(tokens
) < 1) {
1568 log_warn(LD_DIR
, "Impossibly short router status");
1571 tok
= find_first_by_keyword(tokens
, K_R
);
1573 tor_assert(tok
->n_args
>= 8);
1575 rs
= &vote_rs
->status
;
1577 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
1580 if (!is_legal_nickname(tok
->args
[0])) {
1582 "Invalid nickname %s in router status; skipping.",
1583 escaped(tok
->args
[0]));
1586 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
1588 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
1589 log_warn(LD_DIR
, "Error decoding identity digest %s",
1590 escaped(tok
->args
[1]));
1594 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
1595 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
1596 escaped(tok
->args
[2]));
1600 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
1601 tok
->args
[3], tok
->args
[4]) < 0 ||
1602 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
1603 log_warn(LD_DIR
, "Error parsing time '%s %s'",
1604 tok
->args
[3], tok
->args
[4]);
1608 if (tor_inet_aton(tok
->args
[5], &in
) == 0) {
1609 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
1610 escaped(tok
->args
[5]));
1613 rs
->addr
= ntohl(in
.s_addr
);
1615 rs
->or_port
=(uint16_t) tor_parse_long(tok
->args
[6],10,0,65535,NULL
,NULL
);
1616 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7],10,0,65535,NULL
,NULL
);
1618 tok
= find_first_by_keyword(tokens
, K_S
);
1622 for (i
=0; i
< tok
->n_args
; ++i
) {
1623 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
1625 vote_rs
->flags
|= (1<<p
);
1627 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
1628 escaped(tok
->args
[i
]));
1634 for (i
=0; i
< tok
->n_args
; ++i
) {
1635 if (!strcmp(tok
->args
[i
], "Exit"))
1637 else if (!strcmp(tok
->args
[i
], "Stable"))
1639 else if (!strcmp(tok
->args
[i
], "Fast"))
1641 else if (!strcmp(tok
->args
[i
], "Running"))
1643 else if (!strcmp(tok
->args
[i
], "Named"))
1645 else if (!strcmp(tok
->args
[i
], "Valid"))
1647 else if (!strcmp(tok
->args
[i
], "V2Dir"))
1649 else if (!strcmp(tok
->args
[i
], "Guard"))
1650 rs
->is_possible_guard
= 1;
1651 else if (!strcmp(tok
->args
[i
], "BadExit"))
1652 rs
->is_bad_exit
= 1;
1653 else if (!strcmp(tok
->args
[i
], "BadDirectory"))
1654 rs
->is_bad_directory
= 1;
1655 else if (!strcmp(tok
->args
[i
], "Authority"))
1656 rs
->is_authority
= 1;
1657 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
1658 consensus_method
>= 2) {
1659 /* Unnamed is computed right by consensus method 2 and later. */
1664 if ((tok
= find_first_by_keyword(tokens
, K_V
))) {
1665 tor_assert(tok
->n_args
== 1);
1666 rs
->version_known
= 1;
1667 if (strcmpstart(tok
->args
[0], "Tor ")) {
1668 rs
->version_supports_begindir
= 1;
1669 rs
->version_supports_extrainfo_upload
= 1;
1671 rs
->version_supports_begindir
=
1672 tor_version_as_new_as(tok
->args
[0], "0.1.2.2-alpha");
1673 rs
->version_supports_extrainfo_upload
=
1674 tor_version_as_new_as(tok
->args
[0], "0.2.0.0-alpha-dev (r10070)");
1675 rs
->version_supports_v3_dir
=
1676 tor_version_as_new_as(tok
->args
[0], "0.2.0.8-alpha");
1679 vote_rs
->version
= tok
->args
[0];
1680 tok
->args
[0] = NULL
; /* suppress free() */
1684 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
1690 routerstatus_free(rs
);
1693 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1694 smartlist_clear(tokens
);
1700 /** Helper to sort a smartlist of pointers to routerstatus_t */
1702 _compare_routerstatus_entries(const void **_a
, const void **_b
)
1704 const routerstatus_t
*a
= *_a
, *b
= *_b
;
1705 return memcmp(a
->identity_digest
, b
->identity_digest
, DIGEST_LEN
);
1708 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1710 _free_duplicate_routerstatus_entry(void *e
)
1713 "Network-status has two entries for the same router. "
1715 routerstatus_free(e
);
1718 /** Given a v2 network-status object in <b>s</b>, try to
1719 * parse it and return the result. Return NULL on failure. Check the
1720 * signature of the network status, but do not (yet) check the signing key for
1723 networkstatus_v2_t
*
1724 networkstatus_v2_parse_from_string(const char *s
)
1727 smartlist_t
*tokens
= smartlist_create();
1728 smartlist_t
*footer_tokens
= smartlist_create();
1729 networkstatus_v2_t
*ns
= NULL
;
1730 char ns_digest
[DIGEST_LEN
];
1731 char tmp_digest
[DIGEST_LEN
];
1733 directory_token_t
*tok
;
1736 if (router_get_networkstatus_v2_hash(s
, ns_digest
)) {
1737 log_warn(LD_DIR
, "Unable to compute digest of network-status");
1741 eos
= find_start_of_next_routerstatus(s
);
1742 if (tokenize_string(s
, eos
, tokens
, netstatus_token_table
,0)) {
1743 log_warn(LD_DIR
, "Error tokenizing network-status header.");
1746 ns
= tor_malloc_zero(sizeof(networkstatus_v2_t
));
1747 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
1749 tok
= find_first_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
1750 tor_assert(tok
&& tok
->n_args
>= 1);
1751 if (strcmp(tok
->args
[0], "2")) {
1752 log_warn(LD_BUG
, "Got a non-v2 networkstatus. Version was "
1753 "%s", escaped(tok
->args
[0]));
1757 tok
= find_first_by_keyword(tokens
, K_DIR_SOURCE
);
1759 tor_assert(tok
->n_args
>= 3);
1760 ns
->source_address
= tok
->args
[0]; tok
->args
[0] = NULL
;
1761 if (tor_inet_aton(tok
->args
[1], &in
) == 0) {
1762 log_warn(LD_DIR
, "Error parsing network-status source address %s",
1763 escaped(tok
->args
[1]));
1766 ns
->source_addr
= ntohl(in
.s_addr
);
1767 ns
->source_dirport
=
1768 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
1769 if (ns
->source_dirport
== 0) {
1770 log_warn(LD_DIR
, "Directory source without dirport; skipping.");
1774 tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
);
1776 tor_assert(tok
->n_args
);
1777 if (base16_decode(ns
->identity_digest
, DIGEST_LEN
, tok
->args
[0],
1778 strlen(tok
->args
[0]))) {
1779 log_warn(LD_DIR
, "Couldn't decode networkstatus fingerprint %s",
1780 escaped(tok
->args
[0]));
1784 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
))) {
1785 tor_assert(tok
->n_args
);
1786 ns
->contact
= tok
->args
[0];
1787 tok
->args
[0] = NULL
;
1790 tok
= find_first_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1791 tor_assert(tok
&& tok
->key
);
1792 ns
->signing_key
= tok
->key
;
1795 if (crypto_pk_get_digest(ns
->signing_key
, tmp_digest
)<0) {
1796 log_warn(LD_DIR
, "Couldn't compute signing key digest");
1799 if (memcmp(tmp_digest
, ns
->identity_digest
, DIGEST_LEN
)) {
1801 "network-status fingerprint did not match dir-signing-key");
1805 if ((tok
= find_first_by_keyword(tokens
, K_DIR_OPTIONS
))) {
1806 for (i
=0; i
< tok
->n_args
; ++i
) {
1807 if (!strcmp(tok
->args
[i
], "Names"))
1808 ns
->binds_names
= 1;
1809 if (!strcmp(tok
->args
[i
], "Versions"))
1810 ns
->recommends_versions
= 1;
1811 if (!strcmp(tok
->args
[i
], "BadExits"))
1812 ns
->lists_bad_exits
= 1;
1813 if (!strcmp(tok
->args
[i
], "BadDirectories"))
1814 ns
->lists_bad_directories
= 1;
1818 if (ns
->recommends_versions
) {
1819 if (!(tok
= find_first_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
1820 log_warn(LD_DIR
, "Missing client-versions");
1822 ns
->client_versions
= tok
->args
[0];
1823 tok
->args
[0] = NULL
;
1825 if (!(tok
= find_first_by_keyword(tokens
, K_SERVER_VERSIONS
)) ||
1827 log_warn(LD_DIR
, "Missing server-versions on versioning directory");
1830 ns
->server_versions
= tok
->args
[0];
1831 tok
->args
[0] = NULL
;
1834 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1836 tor_assert(tok
->n_args
== 1);
1837 if (parse_iso_time(tok
->args
[0], &ns
->published_on
) < 0) {
1841 ns
->entries
= smartlist_create();
1843 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1844 smartlist_clear(tokens
);
1845 while (!strcmpstart(s
, "r ")) {
1847 if ((rs
= routerstatus_parse_entry_from_string(&s
, tokens
, NULL
, NULL
, 0)))
1848 smartlist_add(ns
->entries
, rs
);
1850 smartlist_sort(ns
->entries
, _compare_routerstatus_entries
);
1851 smartlist_uniq(ns
->entries
, _compare_routerstatus_entries
,
1852 _free_duplicate_routerstatus_entry
);
1854 if (tokenize_string(s
, NULL
, footer_tokens
, dir_footer_token_table
,0)) {
1855 log_warn(LD_DIR
, "Error tokenizing network-status footer.");
1858 if (smartlist_len(footer_tokens
) < 1) {
1859 log_warn(LD_DIR
, "Too few items in network-status footer.");
1862 tok
= smartlist_get(footer_tokens
, smartlist_len(footer_tokens
)-1);
1863 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
1865 "Expected network-status footer to end with a signature.");
1869 note_crypto_pk_op(VERIFY_DIR
);
1870 if (check_signature_token(ns_digest
, tok
, ns
->signing_key
, 0,
1871 "network-status") < 0)
1877 networkstatus_v2_free(ns
);
1880 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1881 smartlist_free(tokens
);
1882 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
1883 smartlist_free(footer_tokens
);
1888 /** Parse a v3 networkstatus vote (if <b>is_vote</b> is true) or a v3
1889 * networkstatus consensus (if <b>is_vote</b> is false) from <b>s</b>, and
1890 * return the result. Return NULL on failure. */
1891 networkstatus_vote_t
*
1892 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
1895 smartlist_t
*tokens
= smartlist_create();
1896 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
1897 networkstatus_voter_info_t
*voter
= NULL
;
1898 networkstatus_vote_t
*ns
= NULL
;
1899 char ns_digest
[DIGEST_LEN
];
1900 const char *cert
, *end_of_header
, *end_of_footer
;
1901 directory_token_t
*tok
;
1904 int i
, inorder
, n_signatures
= 0;
1906 if (router_get_networkstatus_v3_hash(s
, ns_digest
)) {
1907 log_warn(LD_DIR
, "Unable to compute digest of network-status");
1911 end_of_header
= find_start_of_next_routerstatus(s
);
1912 if (tokenize_string(s
, end_of_header
, tokens
,
1913 is_vote
? networkstatus_vote_token_table
:
1914 networkstatus_consensus_token_table
, 0)) {
1915 log_warn(LD_DIR
, "Error tokenizing network-status vote header.");
1919 ns
= tor_malloc_zero(sizeof(networkstatus_vote_t
));
1920 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
1923 const char *end_of_cert
= NULL
;
1924 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
1927 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
1928 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
1932 tok
= find_first_by_keyword(tokens
, K_VOTE_STATUS
);
1934 tor_assert(tok
->n_args
);
1935 if (!strcmp(tok
->args
[0], "vote")) {
1937 } else if (!strcmp(tok
->args
[0], "consensus")) {
1940 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
1941 escaped(tok
->args
[0]));
1944 if (!bool_eq(ns
->is_vote
, is_vote
)) {
1945 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
1950 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1951 if (parse_iso_time(tok
->args
[0], &ns
->published
))
1954 ns
->supported_methods
= smartlist_create();
1955 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_METHODS
);
1957 for (i
=0; i
< tok
->n_args
; ++i
)
1958 smartlist_add(ns
->supported_methods
, tok
->args
[i
]);
1959 tok
->n_args
= 0; /* Prevent double free. */
1961 smartlist_add(ns
->supported_methods
, tor_strdup("1"));
1964 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_METHOD
);
1966 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
1971 ns
->consensus_method
= 1;
1975 tok
= find_first_by_keyword(tokens
, K_VALID_AFTER
);
1976 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
1979 tok
= find_first_by_keyword(tokens
, K_FRESH_UNTIL
);
1980 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
1983 tok
= find_first_by_keyword(tokens
, K_VALID_UNTIL
);
1984 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
1987 tok
= find_first_by_keyword(tokens
, K_VOTING_DELAY
);
1988 tor_assert(tok
->n_args
>= 2);
1990 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
1994 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
1997 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
> ns
->fresh_until
) {
1998 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
2001 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
*2 > ns
->valid_until
) {
2002 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
2005 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
2006 log_warn(LD_DIR
, "Vote seconds is too short");
2009 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
2010 log_warn(LD_DIR
, "Dist seconds is too short");
2014 if ((tok
= find_first_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
2015 ns
->client_versions
= tok
->args
[0];
2016 tok
->args
[0] = NULL
;
2018 if ((tok
= find_first_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
2019 ns
->server_versions
= tok
->args
[0];
2020 tok
->args
[0] = NULL
;
2023 tok
= find_first_by_keyword(tokens
, K_KNOWN_FLAGS
);
2024 ns
->known_flags
= smartlist_create();
2026 for (i
= 0; i
< tok
->n_args
; ++i
) {
2027 smartlist_add(ns
->known_flags
, tok
->args
[i
]);
2028 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
2029 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2033 tok
->n_args
= 0; /* suppress free of args members, but not of args itself. */
2035 log_warn(LD_DIR
, "known-flags not in order");
2039 ns
->voters
= smartlist_create();
2041 SMARTLIST_FOREACH(tokens
, directory_token_t
*, _tok
,
2044 if (tok
->tp
== K_DIR_SOURCE
) {
2045 tor_assert(tok
->n_args
>= 6);
2048 smartlist_add(ns
->voters
, voter
);
2049 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2051 memcpy(voter
->vote_digest
, ns_digest
, DIGEST_LEN
);
2053 voter
->nickname
= tor_strdup(tok
->args
[0]);
2054 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2055 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
2056 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2057 log_warn(LD_DIR
, "Error decoding identity digest %s in "
2058 "network-status vote.", escaped(tok
->args
[1]));
2061 if (is_vote
&& memcmp(ns
->cert
->cache_info
.identity_digest
,
2062 voter
->identity_digest
, DIGEST_LEN
)) {
2063 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
2066 voter
->address
= tor_strdup(tok
->args
[2]);
2067 if (!tor_inet_aton(tok
->args
[3], &in
)) {
2068 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
2069 escaped(tok
->args
[3]));
2072 voter
->addr
= ntohl(in
.s_addr
);
2073 voter
->dir_port
= (uint64_t)
2074 (int) tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
2077 voter
->or_port
= (uint64_t)
2078 (int) tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
2081 } else if (tok
->tp
== K_CONTACT
) {
2082 if (!voter
|| voter
->contact
) {
2083 log_warn(LD_DIR
, "contact element is out of place.");
2086 voter
->contact
= tor_strdup(tok
->args
[0]);
2087 } else if (tok
->tp
== K_VOTE_DIGEST
) {
2088 tor_assert(!is_vote
);
2089 tor_assert(tok
->n_args
>= 1);
2090 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
2091 log_warn(LD_DIR
, "vote-digest element is out of place.");
2094 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2095 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
2096 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2097 log_warn(LD_DIR
, "Error decoding vote digest %s in "
2098 "network-status consensus.", escaped(tok
->args
[1]));
2104 smartlist_add(ns
->voters
, voter
);
2107 if (smartlist_len(ns
->voters
) == 0) {
2108 log_warn(LD_DIR
, "Missing dir-source elements in a vote networkstatus.");
2110 } else if (is_vote
&& smartlist_len(ns
->voters
) != 1) {
2111 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
2115 /* Parse routerstatus lines. */
2116 rs_tokens
= smartlist_create();
2118 ns
->routerstatus_list
= smartlist_create();
2120 while (!strcmpstart(s
, "r ")) {
2122 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
2123 if (routerstatus_parse_entry_from_string(&s
, tokens
, ns
, rs
, 0))
2124 smartlist_add(ns
->routerstatus_list
, rs
);
2126 tor_free(rs
->version
);
2131 if ((rs
= routerstatus_parse_entry_from_string(&s
, tokens
, NULL
, NULL
,
2132 ns
->consensus_method
)))
2133 smartlist_add(ns
->routerstatus_list
, rs
);
2136 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
2137 routerstatus_t
*rs1
, *rs2
;
2139 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
2140 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
2141 rs1
= &a
->status
; rs2
= &b
->status
;
2143 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
2144 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
2146 if (memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
) >= 0) {
2147 log_warn(LD_DIR
, "Vote networkstatus entries not sorted by identity "
2153 /* Parse footer; check signature. */
2154 footer_tokens
= smartlist_create();
2155 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
2158 end_of_footer
= s
+ strlen(s
);
2159 if (tokenize_string(s
, end_of_footer
, footer_tokens
,
2160 networkstatus_vote_footer_token_table
, 0)) {
2161 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
2165 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, _tok
,
2167 char declared_identity
[DIGEST_LEN
];
2168 networkstatus_voter_info_t
*v
;
2170 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2172 tor_assert(tok
->n_args
>= 2);
2174 if (!tok
->object_type
||
2175 strcmp(tok
->object_type
, "SIGNATURE") ||
2176 tok
->object_size
< 128 || tok
->object_size
> 512) {
2177 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2181 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2182 base16_decode(declared_identity
, sizeof(declared_identity
),
2183 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2184 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2185 "network-status vote.", escaped(tok
->args
[0]));
2188 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
2189 log_warn(LD_DIR
, "ID on signature on network-status vote does not match"
2190 "any declared directory source.");
2193 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2194 base16_decode(v
->signing_key_digest
, sizeof(v
->signing_key_digest
),
2195 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2196 log_warn(LD_DIR
, "Error decoding declared digest %s in "
2197 "network-status vote.", escaped(tok
->args
[1]));
2202 if (memcmp(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
2204 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
2205 "network-status vote.");
2211 if (check_signature_token(ns_digest
, tok
, ns
->cert
->signing_key
, 0,
2212 "network-status vote"))
2214 v
->good_signature
= 1;
2216 v
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2217 v
->signature_len
= tok
->object_size
;
2222 if (! n_signatures
) {
2223 log_warn(LD_DIR
, "No signatures on networkstatus vote.");
2228 *eos_out
= end_of_footer
;
2233 networkstatus_vote_free(ns
);
2237 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2238 smartlist_free(tokens
);
2241 tor_free(voter
->nickname
);
2242 tor_free(voter
->address
);
2243 tor_free(voter
->contact
);
2247 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_free(t
));
2248 smartlist_free(rs_tokens
);
2250 if (footer_tokens
) {
2251 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
2252 smartlist_free(footer_tokens
);
2258 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2259 * <b>eos</b> and return the result. Return -1 on failure. */
2260 ns_detached_signatures_t
*
2261 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
2263 /* XXXX020 there is too much duplicate code here. */
2264 directory_token_t
*tok
;
2266 smartlist_t
*tokens
= smartlist_create();
2267 ns_detached_signatures_t
*sigs
=
2268 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
2271 eos
= s
+ strlen(s
);
2273 if (tokenize_string(s
, eos
, tokens
,
2274 networkstatus_detached_signature_token_table
, 0)) {
2275 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
2279 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_DIGEST
);
2280 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
) {
2281 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
2282 "networkstatus signatures");
2285 if (base16_decode(sigs
->networkstatus_digest
, DIGEST_LEN
,
2286 tok
->args
[0], strlen(tok
->args
[0])) < 0) {
2287 log_warn(LD_DIR
, "Bad encoding on on consensus-digest in detached "
2288 "networkstatus signatures");
2292 tok
= find_first_by_keyword(tokens
, K_VALID_AFTER
);
2293 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
2294 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
2298 tok
= find_first_by_keyword(tokens
, K_FRESH_UNTIL
);
2299 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
2300 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
2304 tok
= find_first_by_keyword(tokens
, K_VALID_UNTIL
);
2305 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
2306 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
2310 sigs
->signatures
= smartlist_create();
2311 SMARTLIST_FOREACH(tokens
, directory_token_t
*, _tok
,
2313 char id_digest
[DIGEST_LEN
];
2314 char sk_digest
[DIGEST_LEN
];
2315 networkstatus_voter_info_t
*voter
;
2318 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2320 tor_assert(tok
->n_args
>= 2);
2322 if (!tok
->object_type
||
2323 strcmp(tok
->object_type
, "SIGNATURE") ||
2324 tok
->object_size
< 128 || tok
->object_size
> 512) {
2325 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2329 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2330 base16_decode(id_digest
, sizeof(id_digest
),
2331 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2332 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2333 "network-status vote.", escaped(tok
->args
[0]));
2336 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2337 base16_decode(sk_digest
, sizeof(sk_digest
),
2338 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2339 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2340 "network-status vote.", escaped(tok
->args
[1]));
2344 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2345 memcpy(voter
->identity_digest
, id_digest
, DIGEST_LEN
);
2346 memcpy(voter
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
2347 voter
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2348 voter
->signature_len
= tok
->object_size
;
2350 smartlist_add(sigs
->signatures
, voter
);
2355 ns_detached_signatures_free(sigs
);
2358 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2362 /** Parse the addr policy in the string <b>s</b> and return it. If
2363 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2364 * ADDR_POLICY_REJECT) for items that specify no action.
2367 router_parse_addr_policy_from_string(const char *s
, int assume_action
)
2369 directory_token_t
*tok
= NULL
;
2370 const char *cp
, *eos
;
2371 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2372 * But note that there can be an arbitrary amount of space between the
2373 * accept and the address:mask/port element. */
2374 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
2377 s
= eat_whitespace(s
);
2378 if ((*s
== '*' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
2379 if (tor_snprintf(line
, sizeof(line
), "%s %s",
2380 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
2381 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
2386 } else { /* assume an already well-formed address policy line */
2390 eos
= cp
+ strlen(cp
);
2391 tok
= get_next_token(&cp
, eos
, routerdesc_token_table
);
2392 if (tok
->tp
== _ERR
) {
2393 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
2396 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_REJECT
) {
2397 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
2401 /* Now that we've gotten an addr policy, add it to the router. */
2402 r
= router_parse_addr_policy(tok
);
2411 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2412 * <b>router</b>. Return 0 on success, -1 on failure. */
2414 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
2416 addr_policy_t
*newe
, **tmpe
;
2417 newe
= router_parse_addr_policy(tok
);
2420 for (tmpe
= &router
->exit_policy
; *tmpe
; tmpe
=&((*tmpe
)->next
))
2427 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2428 * a new exit_policy_t corresponding to the token. */
2429 static addr_policy_t
*
2430 router_parse_addr_policy(directory_token_t
*tok
)
2432 addr_policy_t
*newe
;
2434 char buf
[POLICY_BUF_LEN
];
2436 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_ACCEPT
);
2438 if (tok
->n_args
!= 1)
2442 if (!strcmpstart(arg
,"private"))
2443 return router_parse_addr_policy_private(tok
);
2445 newe
= tor_malloc_zero(sizeof(addr_policy_t
));
2447 newe
->policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
2448 : ADDR_POLICY_ACCEPT
;
2450 if (parse_addr_and_port_range(arg
, &newe
->addr
, &newe
->maskbits
,
2451 &newe
->prt_min
, &newe
->prt_max
))
2452 goto policy_read_failed
;
2454 if (policy_write_item(buf
, sizeof(buf
), newe
) < 0)
2455 goto policy_read_failed
;
2457 newe
->string
= tor_strdup(buf
);
2461 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
2466 /** Parse an exit policy line of the format "accept/reject private:...".
2467 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2468 * router descriptors until earlier versions are obsolete.
2470 static addr_policy_t
*
2471 router_parse_addr_policy_private(directory_token_t
*tok
)
2473 static const char *private_nets
[] = {
2474 "0.0.0.0/8", "169.254.0.0/16",
2475 "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12",NULL
};
2477 addr_policy_t
*result
, **nextp
;
2479 uint16_t port_min
, port_max
;
2482 if (strcmpstart(arg
, "private"))
2484 arg
+= strlen("private");
2485 arg
= (char*) eat_whitespace(arg
);
2486 if (!arg
|| *arg
!= ':')
2489 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
2493 for (net
= 0; private_nets
[net
]; ++net
) {
2495 *nextp
= tor_malloc_zero(sizeof(addr_policy_t
));
2496 (*nextp
)->policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
2497 : ADDR_POLICY_ACCEPT
;
2498 len
= strlen(arg
)+strlen(private_nets
[net
])+16;
2499 (*nextp
)->string
= tor_malloc(len
+1);
2500 tor_snprintf((*nextp
)->string
, len
, "%s %s%s",
2501 tok
->tp
== K_REJECT
? "reject" : "accept",
2502 private_nets
[net
], arg
);
2503 if (parse_addr_and_port_range((*nextp
)->string
+ 7,
2504 &(*nextp
)->addr
, &(*nextp
)->maskbits
,
2505 &(*nextp
)->prt_min
, &(*nextp
)->prt_max
)) {
2506 log_warn(LD_BUG
, "Couldn't parse an address range we generated!");
2509 nextp
= &(*nextp
)->next
;
2515 /** Log and exit if <b>t</b> is malformed */
2517 assert_addr_policy_ok(addr_policy_t
*t
)
2521 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
2522 t
->policy_type
== ADDR_POLICY_ACCEPT
);
2523 tor_assert(t
->prt_min
<= t
->prt_max
);
2524 t2
= router_parse_addr_policy_from_string(t
->string
, -1);
2526 tor_assert(t2
->policy_type
== t
->policy_type
);
2527 tor_assert(t2
->addr
== t
->addr
);
2528 tor_assert(t2
->maskbits
== t
->maskbits
);
2529 tor_assert(t2
->prt_min
== t
->prt_min
);
2530 tor_assert(t2
->prt_max
== t
->prt_max
);
2531 tor_assert(!strcmp(t2
->string
, t
->string
));
2532 tor_assert(t2
->next
== NULL
);
2533 addr_policy_free(t2
);
2541 * Low-level tokenizer for router descriptors and directories.
2544 /** Free all resources allocated for <b>tok</b> */
2546 token_free(directory_token_t
*tok
)
2551 for (i
= 0; i
< tok
->n_args
; ++i
) {
2552 tor_free(tok
->args
[i
]);
2554 tor_free(tok
->args
);
2556 tor_free(tok
->object_type
);
2557 tor_free(tok
->object_body
);
2558 tor_free(tok
->error
);
2560 crypto_free_pk_env(tok
->key
);
2564 #define RET_ERR(msg) \
2566 if (tok) token_free(tok); \
2567 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2569 tok->error = tor_strdup(msg); \
2570 goto done_tokenizing; \
2573 static INLINE directory_token_t
*
2574 token_check_object(const char *kwd
,
2575 directory_token_t
*tok
, obj_syntax o_syn
)
2580 if (tok
->object_body
) {
2581 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected object for %s", kwd
);
2585 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected public key for %s", kwd
);
2590 if (!tok
->object_body
) {
2591 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing object for %s", kwd
);
2596 if (tok
->key
&& crypto_pk_keysize(tok
->key
) != PK_BYTES
) {
2597 tor_snprintf(ebuf
, sizeof(ebuf
), "Wrong size on key for %s: %d bits",
2598 kwd
, (int)crypto_pk_keysize(tok
->key
));
2604 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing public key for %s", kwd
);
2615 /** Helper function: read the next token from *s, advance *s to the end of the
2616 * token, and return the parsed token. Parse *<b>s</b> according to the list
2617 * of tokens in <b>table</b>.
2619 static directory_token_t
*
2620 get_next_token(const char **s
, const char *eos
, token_rule_t
*table
)
2622 const char *next
, *eol
, *obstart
;
2623 int i
, j
, allocated
, obname_len
;
2624 directory_token_t
*tok
;
2625 obj_syntax o_syn
= NO_OBJ
;
2627 const char *kwd
= "";
2629 #define RET_ERR(msg) \
2631 if (tok) token_free(tok); \
2632 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2634 tok->error = tor_strdup(msg); \
2635 goto done_tokenizing; \
2638 tok
= tor_malloc_zero(sizeof(directory_token_t
));
2641 /* Set *s to first token, eol to end-of-line, next to after first token */
2642 *s
= eat_whitespace_eos(*s
, eos
); /* eat multi-line whitespace */
2643 eol
= memchr(*s
, '\n', eos
-*s
);
2646 next
= find_whitespace_eos(*s
, eol
);
2648 if (!strcmp_len(*s
, "opt", next
-*s
)) {
2649 /* Skip past an "opt" at the start of the line. */
2650 *s
= eat_whitespace_eos_no_nl(next
, eol
);
2651 next
= find_whitespace_eos(*s
, eol
);
2652 } else if (*s
== eos
) { /* If no "opt", and end-of-line, line is invalid */
2653 RET_ERR("Unexpected EOF");
2656 /* Search the table for the appropriate entry. (I tried a binary search
2657 * instead, but it wasn't any faster.) */
2658 for (i
= 0; table
[i
].t
; ++i
) {
2659 if (!strcmp_len(*s
, table
[i
].t
, next
-*s
)) {
2660 /* We've found the keyword. */
2662 tok
->tp
= table
[i
].v
;
2663 o_syn
= table
[i
].os
;
2664 *s
= eat_whitespace_eos_no_nl(next
, eol
);
2665 next
= find_whitespace_eos(*s
, eol
);
2666 /* We go ahead whether there are arguments or not, so that tok->args is
2667 * always set if we want arguments. */
2668 if (table
[i
].concat_args
) {
2669 /* The keyword takes the line as a single argument */
2670 tok
->args
= tor_malloc(sizeof(char*));
2671 tok
->args
[0] = tor_strndup(*s
,eol
-*s
); /* Grab everything on line */
2674 /* This keyword takes multiple arguments. */
2677 tok
->args
= tor_malloc(sizeof(char*)*allocated
);
2678 while (*s
< eol
) { /* While not at eol, store the next token */
2679 if (j
== allocated
) {
2681 tok
->args
= tor_realloc(tok
->args
,sizeof(char*)*allocated
);
2683 tok
->args
[j
++] = tor_strndup(*s
, next
-*s
);
2684 *s
= eat_whitespace_eos_no_nl(next
, eol
); /* eat intra-line ws */
2685 next
= find_whitespace_eos(*s
, eol
); /* find end of token at *s */
2689 if (tok
->n_args
< table
[i
].min_args
) {
2690 tor_snprintf(ebuf
, sizeof(ebuf
), "Too few arguments to %s", kwd
);
2692 } else if (tok
->n_args
> table
[i
].max_args
) {
2693 tor_snprintf(ebuf
, sizeof(ebuf
), "Too many arguments to %s", kwd
);
2700 if (tok
->tp
== _ERR
) {
2701 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
2703 tok
->tp
= _A_UNKNOWN
;
2706 tok
->args
= tor_malloc(sizeof(char*));
2707 tok
->args
[0] = tor_strndup(*s
, eol
-*s
);
2712 /* Check whether there's an object present */
2713 *s
= eat_whitespace_eos(eol
, eos
); /* Scan from end of first line */
2714 eol
= memchr(*s
, '\n', eos
-*s
);
2715 if (!eol
|| eol
-*s
<11 || strcmpstart(*s
, "-----BEGIN ")) /* No object. */
2718 obstart
= *s
; /* Set obstart to start of object spec */
2719 if (*s
+11 >= eol
-5 || memchr(*s
+11,'\0',eol
-*s
-16) || /* no short lines, */
2720 strcmp_len(eol
-5, "-----", 5)) { /* nuls or invalid endings */
2721 RET_ERR("Malformed object: bad begin line");
2723 tok
->object_type
= tor_strndup(*s
+11, eol
-*s
-16);
2724 obname_len
= eol
-*s
-16; /* store objname length here to avoid a strlen() */
2725 *s
= eol
+1; /* Set *s to possible start of object data (could be eos) */
2727 /* Go to the end of the object */
2728 next
= tor_memstr(*s
, eos
-*s
, "-----END ");
2730 RET_ERR("Malformed object: missing object end line");
2732 eol
= memchr(next
, '\n', eos
-next
);
2733 if (!eol
) /* end-of-line marker, or eos if there's no '\n' */
2735 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
2736 if (eol
-next
!= 9+obname_len
+5 ||
2737 strcmp_len(next
+9, tok
->object_type
, obname_len
) ||
2738 strcmp_len(eol
-5, "-----", 5)) {
2739 snprintf(ebuf
, sizeof(ebuf
), "Malformed object: mismatched end tag %s",
2741 ebuf
[sizeof(ebuf
)-1] = '\0';
2744 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) { /* If it's a key... */
2745 tok
->key
= crypto_new_pk_env();
2746 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, eol
-obstart
))
2747 RET_ERR("Couldn't parse public key.");
2748 } else { /* If it's something else, try to base64-decode it */
2750 tok
->object_body
= tor_malloc(next
-*s
); /* really, this is too much RAM. */
2751 r
= base64_decode(tok
->object_body
, next
-*s
, *s
, next
-*s
);
2753 RET_ERR("Malformed object: bad base64-encoded data");
2754 tok
->object_size
= r
;
2759 tok
= token_check_object(kwd
, tok
, o_syn
);
2767 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
2768 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
2769 * Caller must free tokens in <b>out</b>.
2772 tokenize_string(const char *start
, const char *end
, smartlist_t
*out
,
2773 token_rule_t
*table
, int flags
)
2776 directory_token_t
*tok
= NULL
;
2779 int first_nonannotation
;
2780 int prev_len
= smartlist_len(out
);
2784 end
= start
+strlen(start
);
2785 for (i
= 0; i
< _NIL
; ++i
)
2787 while (*s
< end
&& (!tok
|| tok
->tp
!= _EOF
)) {
2788 tok
= get_next_token(s
, end
, table
);
2789 if (tok
->tp
== _ERR
) {
2790 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
2795 smartlist_add(out
, tok
);
2796 *s
= eat_whitespace_eos(*s
, end
);
2799 if (flags
& TS_NOCHECK
)
2802 if ((flags
& TS_ANNOTATIONS_OK
)) {
2803 first_nonannotation
= -1;
2804 for (i
= 0; i
< smartlist_len(out
); ++i
) {
2805 tok
= smartlist_get(out
, i
);
2806 if (tok
->tp
< MIN_ANNOTATION
|| tok
->tp
> MAX_ANNOTATION
) {
2807 first_nonannotation
= i
;
2811 if (first_nonannotation
< 0) {
2812 log_warn(LD_DIR
, "parse error: item contains only annotations");
2815 for (i
=first_nonannotation
; i
< smartlist_len(out
); ++i
) {
2816 tok
= smartlist_get(out
, i
);
2817 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
2818 log_warn(LD_DIR
, "parse error: Annotations mixed with keywords");
2822 if ((flags
& TS_NO_NEW_ANNOTATIONS
)) {
2823 if (first_nonannotation
!= prev_len
) {
2824 log_warn(LD_DIR
, "parse error: Unexpectd annotations.");
2829 for (i
=0; i
< smartlist_len(out
); ++i
) {
2830 tok
= smartlist_get(out
, i
);
2831 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
2832 log_warn(LD_DIR
, "parse error: no annotations allowed.");
2836 first_nonannotation
= 0;
2838 for (i
= 0; table
[i
].t
; ++i
) {
2839 if (counts
[table
[i
].v
] < table
[i
].min_cnt
) {
2840 log_warn(LD_DIR
, "Parse error: missing %s element.", table
[i
].t
);
2843 if (counts
[table
[i
].v
] > table
[i
].max_cnt
) {
2844 log_warn(LD_DIR
, "Parse error: too many %s elements.", table
[i
].t
);
2847 if (table
[i
].pos
& AT_START
) {
2848 if (smartlist_len(out
) < 1 ||
2849 (tok
= smartlist_get(out
, first_nonannotation
))->tp
!= table
[i
].v
) {
2850 log_warn(LD_DIR
, "Parse error: first item is not %s.", table
[i
].t
);
2854 if (table
[i
].pos
& AT_END
) {
2855 if (smartlist_len(out
) < 1 ||
2856 (tok
= smartlist_get(out
, smartlist_len(out
)-1))->tp
!= table
[i
].v
) {
2857 log_warn(LD_DIR
, "Parse error: last item is not %s.", table
[i
].t
);
2865 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
2866 * NULL if no such keyword is found.
2868 static directory_token_t
*
2869 find_first_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
2871 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
2875 /** Return a newly allocated smartlist of all accept or reject tokens in
2878 static smartlist_t
*
2879 find_all_exitpolicy(smartlist_t
*s
)
2881 smartlist_t
*out
= smartlist_create();
2882 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
2883 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_REJECT
)
2884 smartlist_add(out
,t
));
2888 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
2889 * occurrence of <b>start_str</b> through the first instance of c after the
2890 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
2891 * <b>digest</b>; return 0 on success.
2893 * If no such substring exists, return -1.
2896 router_get_hash_impl(const char *s
, char *digest
,
2897 const char *start_str
,
2898 const char *end_str
, char end_c
)
2901 start
= strstr(s
, start_str
);
2903 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
2906 if (start
!= s
&& *(start
-1) != '\n') {
2908 "first occurrence of \"%s\" is not at the start of a line",
2912 end
= strstr(start
+strlen(start_str
), end_str
);
2914 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
2917 end
= strchr(end
+strlen(end_str
), end_c
);
2919 log_warn(LD_DIR
,"couldn't find EOL");
2924 if (crypto_digest(digest
, start
, end
-start
)) {
2925 log_warn(LD_BUG
,"couldn't compute digest");
2932 /** Parse the Tor version of the platform string <b>platform</b>,
2933 * and compare it to the version in <b>cutoff</b>. Return 1 if
2934 * the router is at least as new as the cutoff, else return 0.
2937 tor_version_as_new_as(const char *platform
, const char *cutoff
)
2939 tor_version_t cutoff_version
, router_version
;
2940 char *s
, *s2
, *start
;
2943 tor_assert(platform
);
2945 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
2946 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
2949 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
2952 start
= (char *)eat_whitespace(platform
+3);
2953 if (!*start
) return 0;
2954 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
2955 s2
= (char*)eat_whitespace(s
);
2956 if (!strcmpstart(s2
, "(r"))
2957 s
= (char*)find_whitespace(s2
);
2959 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
2961 strlcpy(tmp
, start
, s
-start
+1);
2963 if (tor_version_parse(tmp
, &router_version
)<0) {
2964 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
2965 return 1; /* be safe and say yes */
2968 /* Here's why we don't need to do any special handling for svn revisions:
2969 * - If neither has an svn revision, we're fine.
2970 * - If the router doesn't have an svn revision, we can't assume that it
2971 * is "at least" any svn revision, so we need to return 0.
2972 * - If the target version doesn't have an svn revision, any svn revision
2973 * (or none at all) is good enough, so return 1.
2974 * - If both target and router have an svn revision, we compare them.
2977 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
2980 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
2981 * Return 0 on success, -1 on failure. */
2983 tor_version_parse(const char *s
, tor_version_t
*out
)
2986 const char *cp
=NULL
;
2988 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
2993 memset(out
, 0, sizeof(tor_version_t
));
2995 if (!strcasecmpstart(s
, "Tor "))
2999 out
->major
= strtol(s
,&eos
,10);
3000 if (!eos
|| eos
==s
|| *eos
!= '.') return -1;
3004 out
->minor
= strtol(cp
,&eos
,10);
3005 if (!eos
|| eos
==cp
|| *eos
!= '.') return -1;
3009 out
->micro
= strtol(cp
,&eos
,10);
3010 if (!eos
|| eos
==cp
) return -1;
3012 out
->status
= VER_RELEASE
;
3013 out
->patchlevel
= 0;
3020 out
->status
= VER_RELEASE
;
3022 } else if (0==strncmp(cp
, "pre", 3)) {
3023 out
->status
= VER_PRE
;
3025 } else if (0==strncmp(cp
, "rc", 2)) {
3026 out
->status
= VER_RC
;
3032 /* Get patchlevel */
3033 out
->patchlevel
= strtol(cp
,&eos
,10);
3034 if (!eos
|| eos
==cp
) return -1;
3037 /* Get status tag. */
3038 if (*cp
== '-' || *cp
== '.')
3040 eos
= (char*) find_whitespace(cp
);
3041 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
3042 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
3044 memcpy(out
->status_tag
, cp
, eos
-cp
);
3045 out
->status_tag
[eos
-cp
] = 0;
3047 cp
= eat_whitespace(eos
);
3049 if (!strcmpstart(cp
, "(r")) {
3051 out
->svn_revision
= strtol(cp
,&eos
,10);
3057 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3060 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
3065 if ((i
= a
->major
- b
->major
))
3067 else if ((i
= a
->minor
- b
->minor
))
3069 else if ((i
= a
->micro
- b
->micro
))
3071 else if ((i
= a
->status
- b
->status
))
3073 else if ((i
= a
->patchlevel
- b
->patchlevel
))
3075 else if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
3078 return a
->svn_revision
- b
->svn_revision
;
3081 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3084 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
3088 return ((a
->major
== b
->major
) &&
3089 (a
->minor
== b
->minor
) &&
3090 (a
->micro
== b
->micro
));
3093 /** Helper: Given pointers to two strings describing tor versions, return -1
3094 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
3095 * Used to sort a list of versions. */
3097 _compare_tor_version_str_ptr(const void **_a
, const void **_b
)
3099 const char *a
= *_a
, *b
= *_b
;
3101 tor_version_t va
, vb
;
3102 ca
= tor_version_parse(a
, &va
);
3103 cb
= tor_version_parse(b
, &vb
);
3104 /* If they both parse, compare them. */
3106 return tor_version_compare(&va
,&vb
);
3107 /* If one parses, it comes first. */
3112 /* If neither parses, compare strings. Also, the directory server admin
3113 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3117 /** Sort a list of string-representations of versions in ascending order. */
3119 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
3121 smartlist_sort(versions
, _compare_tor_version_str_ptr
);
3123 if (remove_duplicates
)
3124 smartlist_uniq(versions
, _compare_tor_version_str_ptr
, _tor_free
);