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_
19 * correspond to directory 'keywords'. _UNRECOGNIZED is for an
20 * unrecognized keyword; _ERR is an error in the tokenizing process,
21 * _EOF is an end-of-file marker, and _NIL is used to encode
26 K_DIRECTORY_SIGNATURE
,
27 K_RECOMMENDED_SOFTWARE
,
50 K_NETWORK_STATUS_VERSION
,
65 /** Structure to hold a single directory token.
67 * We parse a directory by breaking it into "tokens", each consisting
68 * of a keyword, a line full of arguments, and a binary object. The
69 * arguments and object are both optional, depending on the keyword
72 typedef struct directory_token_t
{
73 directory_keyword tp
; /**< Type of the token. */
74 int n_args
; /**< Number of elements in args */
75 char **args
; /**< Array of arguments from keyword line. */
76 char *object_type
; /**< -----BEGIN [object_type]-----*/
77 size_t object_size
; /**< Bytes in object_body */
78 char *object_body
; /**< Contents of object, base64-decoded. */
79 crypto_pk_env_t
*key
; /**< For public keys only. */
80 const char *error
; /**< For _ERR tokens only. */
83 /* ********************************************************************** */
85 /** We use a table of rules to decide how to parse each token type. */
87 /** Rules for how many arguments a keyword can take. */
89 NO_ARGS
, /**< No arguments, ever. */
90 ARGS
, /**< A list of arguments separated by spaces. */
91 CONCAT_ARGS
, /**< The rest of the line, treated as a single argument. */
94 /** Rules for whether the keyword needs an object. */
96 NO_OBJ
, /**< No object, ever. */
97 NEED_OBJ
, /**< Object is required. */
98 NEED_KEY
, /**< Object is required, and must be a public key. */
99 OBJ_OK
, /**< Object is optional. */
102 /** Rules for where a keyword can appear. */
104 DIR = 1, /**< Appears only in directory. */
105 RTR
= 2, /**< Appears only in router descriptor or runningrouters. */
106 NETSTATUS
= 4, /**< v2 or later ("versioned") network status. */
107 ANYSIGNED
= 7, /**< Any "full" document (that is, not a router status.) */
108 RTRSTATUS
= 8, /**< Router-status portion of a versioned network status. */
109 ANY
= 15, /**< Appears in any document type. */
112 /** Table mapping keywords to token value and to argument rules. */
114 const char *t
; directory_keyword v
; arg_syntax s
; obj_syntax os
; int ws
;
116 { "accept", K_ACCEPT
, ARGS
, NO_OBJ
, RTR
},
117 { "directory-signature", K_DIRECTORY_SIGNATURE
, ARGS
, NEED_OBJ
,
119 { "r", K_R
, ARGS
, NO_OBJ
, RTRSTATUS
},
120 { "s", K_S
, ARGS
, NO_OBJ
, RTRSTATUS
},
121 { "v", K_V
, CONCAT_ARGS
, NO_OBJ
, RTRSTATUS
},
122 { "reject", K_REJECT
, ARGS
, NO_OBJ
, RTR
},
123 { "router", K_ROUTER
, ARGS
, NO_OBJ
, RTR
},
124 { "recommended-software",K_RECOMMENDED_SOFTWARE
,ARGS
, NO_OBJ
, DIR },
125 { "signed-directory", K_SIGNED_DIRECTORY
, NO_ARGS
, NO_OBJ
, DIR },
126 { "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY
,RTR
},
127 { "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY
,RTR
},
128 { "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
,RTR
},
129 { "running-routers", K_RUNNING_ROUTERS
, ARGS
, NO_OBJ
, DIR },
130 { "router-status", K_ROUTER_STATUS
, ARGS
, NO_OBJ
, DIR },
131 { "bandwidth", K_BANDWIDTH
, ARGS
, NO_OBJ
, RTR
},
132 { "platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
, RTR
},
133 { "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
, ANYSIGNED
},
134 { "opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
, ANY
},
135 { "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
, ANYSIGNED
},
136 { "network-status", K_NETWORK_STATUS
, NO_ARGS
, NO_OBJ
, DIR },
137 { "uptime", K_UPTIME
, ARGS
, NO_OBJ
, RTR
},
138 { "dir-signing-key", K_DIR_SIGNING_KEY
, ARGS
, OBJ_OK
,
140 { "family", K_FAMILY
, ARGS
, NO_OBJ
, RTR
},
141 { "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
, ANYSIGNED
},
142 { "hibernating", K_HIBERNATING
, ARGS
, NO_OBJ
, RTR
},
143 { "read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
, RTR
},
144 { "write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
, RTR
},
145 { "network-status-version", K_NETWORK_STATUS_VERSION
,
146 ARGS
, NO_OBJ
, NETSTATUS
},
147 { "dir-source", K_DIR_SOURCE
, ARGS
, NO_OBJ
, NETSTATUS
},
148 { "dir-options", K_DIR_OPTIONS
, ARGS
, NO_OBJ
, NETSTATUS
},
149 { "client-versions", K_CLIENT_VERSIONS
, ARGS
, NO_OBJ
, NETSTATUS
},
150 { "server-versions", K_SERVER_VERSIONS
, ARGS
, NO_OBJ
, NETSTATUS
},
151 { "eventdns", K_EVENTDNS
, ARGS
, NO_OBJ
, RTR
},
152 { NULL
, _NIL
, NO_ARGS
, NO_OBJ
, ANY
}
155 /* static function prototypes */
156 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
157 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
);
158 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
160 static int router_get_hash_impl(const char *s
, char *digest
,
161 const char *start_str
, const char *end_str
);
162 static void token_free(directory_token_t
*tok
);
163 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
164 static directory_token_t
*find_first_by_keyword(smartlist_t
*s
,
165 directory_keyword keyword
);
166 static directory_token_t
*find_last_by_keyword(smartlist_t
*s
,
167 directory_keyword keyword
);
168 static int tokenize_string(const char *start
, const char *end
,
169 smartlist_t
*out
, where_syntax where
);
170 static directory_token_t
*get_next_token(const char **s
, where_syntax where
);
171 static int check_directory_signature(const char *digest
,
172 directory_token_t
*tok
,
173 crypto_pk_env_t
*pkey
,
174 crypto_pk_env_t
*declared_key
,
175 int check_authority
);
176 static crypto_pk_env_t
*find_dir_signing_key(const char *str
);
177 static int tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
);
179 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
180 * <b>s</b>. Return 0 on success, -1 on failure.
183 router_get_dir_hash(const char *s
, char *digest
)
185 return router_get_hash_impl(s
,digest
,
186 "signed-directory","\ndirectory-signature");
189 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
190 * <b>s</b>. Return 0 on success, -1 on failure.
193 router_get_router_hash(const char *s
, char *digest
)
195 return router_get_hash_impl(s
,digest
,
196 "router ","\nrouter-signature");
199 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
200 * string in <b>s</b>. Return 0 on success, -1 on failure.
203 router_get_runningrouters_hash(const char *s
, char *digest
)
205 return router_get_hash_impl(s
,digest
,
206 "network-status","\ndirectory-signature");
209 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
210 * string in <b>s</b>. Return 0 on success, -1 on failure. */
212 router_get_networkstatus_v2_hash(const char *s
, char *digest
)
214 return router_get_hash_impl(s
,digest
,
215 "network-status-version","\ndirectory-signature");
218 /** Helper: used to generate signatures for routers, directories and
219 * network-status objects. Given a digest in <b>digest</b> and a secret
220 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
221 * surround it with -----BEGIN/END----- pairs, and write it to the
222 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
226 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
227 crypto_pk_env_t
*private_key
)
229 char signature
[PK_BYTES
];
232 if (crypto_pk_private_sign(private_key
, signature
, digest
, DIGEST_LEN
) < 0) {
234 log_warn(LD_BUG
,"Couldn't sign digest.");
237 if (strlcat(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
241 if (base64_encode(buf
+i
, buf_len
-i
, signature
, 128) < 0) {
242 log_warn(LD_BUG
,"couldn't base64-encode signature");
247 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
252 log_warn(LD_BUG
,"tried to exceed string length.");
256 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
257 * <b>versionlist</b>. Else, return VS_OLD if every member of
258 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
259 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
260 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
261 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
262 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
265 * (versionlist is a comma-separated list of version strings,
266 * optionally prefixed with "Tor". Versions that can't be parsed are
270 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
272 tor_version_t mine
, other
;
273 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
274 found_any_in_series
= 0, r
, same
;
275 version_status_t ret
= VS_UNRECOMMENDED
;
276 smartlist_t
*version_sl
;
278 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
279 myversion
, versionlist
);
281 if (tor_version_parse(myversion
, &mine
)) {
282 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
285 version_sl
= smartlist_create();
286 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
288 SMARTLIST_FOREACH(version_sl
, const char *, cp
, {
289 if (!strcmpstart(cp
, "Tor "))
292 if (tor_version_parse(cp
, &other
)) {
293 /* Couldn't parse other; it can't be a match. */
295 same
= tor_version_same_series(&mine
, &other
);
297 found_any_in_series
= 1;
298 r
= tor_version_compare(&mine
, &other
);
300 ret
= VS_RECOMMENDED
;
305 found_newer_in_series
= 1;
312 /* We didn't find the listed version. Is it new or old? */
313 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
314 ret
= VS_NEW_IN_SERIES
;
315 } else if (found_newer
&& !found_older
) {
317 } else if (found_older
&& !found_newer
) {
320 ret
= VS_UNRECOMMENDED
;
324 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
325 smartlist_free(version_sl
);
329 /** Return the combined status of the current version, given that we know of
330 * one set of networkstatuses that give us status <b>a</b>, and another that
331 * gives us status <b>b</b>.
333 * For example, if one authority thinks that we're NEW, and another thinks
334 * we're OLD, we're simply UNRECOMMENDED.
336 * This function does not handle calculating whether we're RECOMMENDED; that
337 * follows a simple majority rule. This function simply calculates *why*
338 * we're not recommended (if we're not).
341 version_status_join(version_status_t a
, version_status_t b
)
345 else if (a
== VS_UNRECOMMENDED
|| b
== VS_UNRECOMMENDED
)
346 return VS_UNRECOMMENDED
;
347 else if (a
== VS_RECOMMENDED
)
349 else if (b
== VS_RECOMMENDED
)
351 /* Okay. Neither is 'recommended' or 'unrecommended', and they differ. */
352 else if (a
== VS_OLD
|| b
== VS_OLD
)
353 return VS_UNRECOMMENDED
;
354 /* One is VS_NEW, the other is VS_NEW_IN_SERIES */
356 return VS_NEW_IN_SERIES
;
359 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
360 * Otherwise, return -1. If we're a directory cache, cache it.
363 router_parse_directory(const char *str
)
365 directory_token_t
*tok
;
366 char digest
[DIGEST_LEN
];
369 const char *end
, *cp
;
370 smartlist_t
*tokens
= NULL
;
371 crypto_pk_env_t
*declared_key
= NULL
;
373 /* XXXX This could be simplified a lot, but it will all go away
374 * once pre-0.1.1.8 is obsolete, and for now it's better not to
377 if (router_get_dir_hash(str
, digest
)) {
378 log_warn(LD_DIR
, "Unable to compute digest of directory");
381 log_debug(LD_DIR
,"Received directory hashes to %s",hex_str(digest
,4));
383 /* Check signature first, before we try to tokenize. */
385 while (cp
&& (end
= strstr(cp
+1, "\ndirectory-signature")))
387 if (cp
== str
|| !cp
) {
388 log_warn(LD_DIR
, "No signature found on directory."); goto err
;
391 tokens
= smartlist_create();
392 if (tokenize_string(cp
,strchr(cp
,'\0'),tokens
,DIR)) {
393 log_warn(LD_DIR
, "Error tokenizing directory signature"); goto err
;
395 if (smartlist_len(tokens
) != 1) {
396 log_warn(LD_DIR
, "Unexpected number of tokens in signature"); goto err
;
398 tok
=smartlist_get(tokens
,0);
399 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
400 log_warn(LD_DIR
,"Expected a single directory signature"); goto err
;
402 declared_key
= find_dir_signing_key(str
);
403 note_crypto_pk_op(VERIFY_DIR
);
404 if (check_directory_signature(digest
, tok
, NULL
, declared_key
, 1)<0)
407 SMARTLIST_FOREACH(tokens
, directory_token_t
*, tok
, token_free(tok
));
408 smartlist_free(tokens
);
411 /* Now try to parse the first part of the directory. */
412 if ((end
= strstr(str
,"\nrouter "))) {
414 } else if ((end
= strstr(str
, "\ndirectory-signature"))) {
417 end
= str
+ strlen(str
);
420 tokens
= smartlist_create();
421 if (tokenize_string(str
,end
,tokens
,DIR)) {
422 log_warn(LD_DIR
, "Error tokenizing directory"); goto err
;
425 if (!(tok
= find_first_by_keyword(tokens
, K_PUBLISHED
))) {
426 log_warn(LD_DIR
, "Missing published time on directory.");
429 tor_assert(tok
->n_args
== 1);
431 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
435 /* Now that we know the signature is okay, and we have a
436 * publication time, cache the directory. */
437 if (get_options()->DirPort
&& !get_options()->V1AuthoritativeDir
)
438 dirserv_set_cached_directory(str
, published_on
, 0);
445 if (declared_key
) crypto_free_pk_env(declared_key
);
447 SMARTLIST_FOREACH(tokens
, directory_token_t
*, tok
, token_free(tok
));
448 smartlist_free(tokens
);
453 /** Read a signed router status statement from <b>str</b>. If it's
454 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
457 router_parse_runningrouters(const char *str
)
459 char digest
[DIGEST_LEN
];
460 directory_token_t
*tok
;
463 crypto_pk_env_t
*declared_key
= NULL
;
464 smartlist_t
*tokens
= NULL
;
466 if (router_get_runningrouters_hash(str
, digest
)) {
467 log_warn(LD_DIR
, "Unable to compute digest of running-routers");
470 tokens
= smartlist_create();
471 if (tokenize_string(str
,str
+strlen(str
),tokens
,DIR)) {
472 log_warn(LD_DIR
, "Error tokenizing running-routers"); goto err
;
474 tok
= smartlist_get(tokens
,0);
475 if (tok
->tp
!= K_NETWORK_STATUS
) {
476 log_warn(LD_DIR
, "Network-status starts with wrong token");
480 if (!(tok
= find_first_by_keyword(tokens
, K_PUBLISHED
))) {
481 log_warn(LD_DIR
, "Missing published time on running-routers.");
484 tor_assert(tok
->n_args
== 1);
485 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
488 if (!(tok
= find_first_by_keyword(tokens
, K_DIRECTORY_SIGNATURE
))) {
489 log_warn(LD_DIR
, "Missing signature on running-routers");
492 declared_key
= find_dir_signing_key(str
);
493 note_crypto_pk_op(VERIFY_DIR
);
494 if (check_directory_signature(digest
, tok
, NULL
, declared_key
, 1) < 0)
497 /* Now that we know the signature is okay, and we have a
498 * publication time, cache the list. */
499 if (get_options()->DirPort
&& !get_options()->V1AuthoritativeDir
)
500 dirserv_set_cached_directory(str
, published_on
, 1);
504 if (declared_key
) crypto_free_pk_env(declared_key
);
506 SMARTLIST_FOREACH(tokens
, directory_token_t
*, tok
, token_free(tok
));
507 smartlist_free(tokens
);
512 /** Given a directory or running-routers string in <b>str</b>, try to
513 * find the its dir-signing-key token (if any). If this token is
514 * present, extract and return the key. Return NULL on failure. */
515 static crypto_pk_env_t
*
516 find_dir_signing_key(const char *str
)
519 directory_token_t
*tok
;
520 crypto_pk_env_t
*key
= NULL
;
522 /* Is there a dir-signing-key in the directory? */
523 cp
= strstr(str
, "\nopt dir-signing-key");
525 cp
= strstr(str
, "\ndir-signing-key");
528 ++cp
; /* Now cp points to the start of the token. */
530 tok
= get_next_token(&cp
, DIR);
532 log_warn(LD_DIR
, "Unparseable dir-signing-key token");
535 if (tok
->tp
!= K_DIR_SIGNING_KEY
) {
536 log_warn(LD_DIR
, "Dir-signing-key token did not parse as expected");
542 tok
->key
= NULL
; /* steal reference. */
544 log_warn(LD_DIR
, "Dir-signing-key token contained no key");
552 /** Return true iff <b>key</b> is allowed to sign directories.
555 dir_signing_key_is_trusted(crypto_pk_env_t
*key
)
557 char digest
[DIGEST_LEN
];
559 if (crypto_pk_get_digest(key
, digest
) < 0) {
560 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
563 if (!router_digest_is_trusted_dir(digest
)) {
564 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
570 /** Check whether the K_DIRECTORY_SIGNATURE token in <b>tok</b> has a
571 * good signature for <b>digest</b>.
573 * If <b>declared_key</b> is set, the directory has declared what key
574 * was used to sign it, so we will use that key only if it is an
575 * authoritative directory signing key or if check_authority is 0.
577 * Otherwise, if pkey is provided, try to use it.
579 * (New callers should always use <b>declared_key</b> when possible;
580 * <b>pkey</b> is only for debugging.)
583 check_directory_signature(const char *digest
,
584 directory_token_t
*tok
,
585 crypto_pk_env_t
*pkey
,
586 crypto_pk_env_t
*declared_key
,
589 char signed_digest
[PK_BYTES
];
590 crypto_pk_env_t
*_pkey
= NULL
;
592 if (tok
->n_args
!= 1) {
593 log_warn(LD_DIR
, "Too many or too few arguments to directory-signature");
598 if (!check_authority
|| dir_signing_key_is_trusted(declared_key
))
599 _pkey
= declared_key
;
601 if (!_pkey
&& pkey
) {
602 /* pkey provided for debugging purposes */
607 "Obsolete directory format (dir signing key not present) or "
608 "signing key not trusted--rejecting.");
612 if (strcmp(tok
->object_type
, "SIGNATURE") || tok
->object_size
!= 128) {
613 log_warn(LD_DIR
, "Bad object type or length on directory signature");
619 if (crypto_pk_public_checksig(_pkey
, signed_digest
, tok
->object_body
, 128)
621 log_warn(LD_DIR
, "Error reading directory: invalid signature.");
624 log_debug(LD_DIR
,"Signed directory hash starts %s",
625 hex_str(signed_digest
,4));
626 if (memcmp(digest
, signed_digest
, DIGEST_LEN
)) {
627 log_warn(LD_DIR
, "Error reading directory: signature does not match.");
633 /** Given a string *<b>s</b> containing a concatenated sequence of router
634 * descriptors, parses them and stores the result in <b>dest</b>. All routers
635 * are marked running and valid. Advances *s to a point immediately
636 * following the last router entry. Ignore any trailing router entries that
639 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
640 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
641 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
643 * Returns 0 on success and -1 on failure.
646 router_parse_list_from_string(const char **s
, const char *eos
,
648 saved_location_t saved_location
)
650 routerinfo_t
*router
;
651 const char *end
, *cp
, *start
;
659 eos
= *s
+ strlen(*s
);
662 *s
= eat_whitespace_eos(*s
, eos
);
663 if (eos
- *s
< 32) /* not long enough to hold a descriptor. */
666 /* Don't start parsing the rest of *s unless it contains a router. */
667 if (strcmpstart(*s
, "router ")!=0)
669 if ((end
= tor_memstr(*s
+1, eos
-(*s
+1), "\nrouter "))) {
672 } else if ((end
= tor_memstr(*s
+1, eos
-(*s
+1), "\ndirectory-signature"))) {
679 /* Start by backing up a character. If we were at eos, we'll now point
680 * to a valid character. If we were at a \nrouter or \ndirectory-signature,
681 * we'll back up to before the \n. */
684 while (cp
> *s
&& (!*cp
|| TOR_ISSPACE(*cp
)))
686 /* cp now points to the last non-space character in this descriptor. */
688 while (cp
> *s
&& *cp
!= '\n')
690 /* cp now points to the first \n before the last non-blank line in this
693 if (strcmpstart(cp
, "\n-----END SIGNATURE-----\n")) {
694 log_info(LD_DIR
, "Ignoring truncated router descriptor.");
699 router
= router_parse_entry_from_string(*s
, end
,
700 saved_location
!= SAVED_IN_CACHE
);
703 log_warn(LD_DIR
, "Error reading router; skipping");
707 if (saved_location
!= SAVED_NOWHERE
) {
708 router
->cache_info
.saved_location
= saved_location
;
709 router
->cache_info
.saved_offset
= *s
- start
;
712 smartlist_add(dest
, router
);
718 /* For debugging: define to count every descriptor digest we've seen so we
719 * know if we need to try harder to avoid duplicate verifies. */
720 #undef COUNT_DISTINCT_DIGESTS
722 #ifdef COUNT_DISTINCT_DIGESTS
723 static digestmap_t
*verified_digests
= NULL
;
726 /** Log the total count of the number of distinct router digests we've ever
727 * verified. When compared to the number of times we've verified routerdesc
728 * signatures <i>in toto</i>, this will tell us if we're doing too much
729 * multiple-verification. */
731 dump_distinct_digest_count(int severity
)
733 #ifdef COUNT_DISTINCT_DIGESTS
734 if (!verified_digests
)
735 verified_digests
= digestmap_new();
736 log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
737 digestmap_size(verified_digests
));
739 (void)severity
; /* suppress "unused parameter" warning */
743 /** Helper function: reads a single router entry from *<b>s</b> ...
744 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
745 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
746 * s through end into the signed_descriptor_body of the resulting
750 router_parse_entry_from_string(const char *s
, const char *end
,
753 routerinfo_t
*router
= NULL
;
754 char signed_digest
[128];
756 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
757 directory_token_t
*tok
;
765 /* point 'end' to a point immediately after the final newline. */
766 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
769 if (router_get_router_hash(s
, digest
) < 0) {
770 log_warn(LD_DIR
, "Couldn't compute router hash.");
773 tokens
= smartlist_create();
774 if (tokenize_string(s
,end
,tokens
,RTR
)) {
775 log_warn(LD_DIR
, "Error tokeninzing router descriptor.");
779 if (smartlist_len(tokens
) < 2) {
780 log_warn(LD_DIR
, "Impossibly short router descriptor.");
784 tok
= smartlist_get(tokens
,0);
785 if (tok
->tp
!= K_ROUTER
) {
786 log_warn(LD_DIR
,"Entry does not start with \"router\"");
790 router
= tor_malloc_zero(sizeof(routerinfo_t
));
791 router
->routerlist_index
= -1;
793 router
->cache_info
.signed_descriptor_body
= tor_strndup(s
, end
-s
);
794 router
->cache_info
.signed_descriptor_len
= end
-s
;
795 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
797 if (tok
->n_args
>= 5) {
798 router
->nickname
= tor_strdup(tok
->args
[0]);
799 if (!is_legal_nickname(router
->nickname
)) {
800 log_warn(LD_DIR
,"Router nickname is invalid");
803 router
->address
= tor_strdup(tok
->args
[1]);
804 if (!tor_inet_aton(router
->address
, &in
)) {
805 log_warn(LD_DIR
,"Router address is not an IP.");
808 router
->addr
= ntohl(in
.s_addr
);
811 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
813 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,NULL
,NULL
);
815 log_warn(LD_DIR
,"Wrong # of arguments to \"router\" (%d)",tok
->n_args
);
819 tok
= find_first_by_keyword(tokens
, K_BANDWIDTH
);
821 log_warn(LD_DIR
,"No bandwidth declared; failing.");
824 if (tok
->n_args
< 3) {
826 "Not enough arguments to \"bandwidth\" in server descriptor.");
829 router
->bandwidthrate
=
830 tor_parse_long(tok
->args
[0],10,0,INT_MAX
,NULL
,NULL
);
832 if (!router
->bandwidthrate
) {
833 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
834 escaped(tok
->args
[0]));
838 router
->bandwidthburst
=
839 tor_parse_long(tok
->args
[1],10,0,INT_MAX
,NULL
,NULL
);
840 router
->bandwidthcapacity
=
841 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,NULL
,NULL
);
843 /* XXX we don't error-check these values? -RD */
846 if ((tok
= find_first_by_keyword(tokens
, K_UPTIME
))) {
847 if (tok
->n_args
!= 1) {
848 log_warn(LD_DIR
, "Unrecognized number of args on K_UPTIME; skipping.");
850 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
);
854 if ((tok
= find_first_by_keyword(tokens
, K_HIBERNATING
))) {
855 if (tok
->n_args
< 1) {
856 log_warn(LD_DIR
, "Too few args on 'hibernating' keyword. Skipping.");
858 router
->is_hibernating
859 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
863 if (!(tok
= find_first_by_keyword(tokens
, K_PUBLISHED
))) {
864 log_warn(LD_DIR
, "Missing published time on router descriptor"); goto err
;
866 tor_assert(tok
->n_args
== 1);
867 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
870 if (!(tok
= find_first_by_keyword(tokens
, K_ONION_KEY
))) {
871 log_warn(LD_DIR
, "Missing onion key"); goto err
;
873 if (crypto_pk_keysize(tok
->key
) != PK_BYTES
) {
874 log_warn(LD_DIR
, "Wrong size on onion key: %d bits!",
875 (int)crypto_pk_keysize(tok
->key
)*8);
878 router
->onion_pkey
= tok
->key
;
879 tok
->key
= NULL
; /* Prevent free */
881 if (!(tok
= find_first_by_keyword(tokens
, K_SIGNING_KEY
))) {
882 log_warn(LD_DIR
, "Missing identity key"); goto err
;
884 if (crypto_pk_keysize(tok
->key
) != PK_BYTES
) {
885 log_warn(LD_DIR
, "Wrong size on identity key: %d bits!",
886 (int)crypto_pk_keysize(tok
->key
)*8);
889 router
->identity_pkey
= tok
->key
;
890 tok
->key
= NULL
; /* Prevent free */
891 if (crypto_pk_get_digest(router
->identity_pkey
,
892 router
->cache_info
.identity_digest
)) {
893 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
896 if ((tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
))) {
897 /* If there's a fingerprint line, it must match the identity digest. */
899 if (tok
->n_args
< 1) {
900 log_warn(LD_DIR
, "Too few arguments to router fingerprint");
903 tor_strstrip(tok
->args
[0], " ");
904 if (base16_decode(d
, DIGEST_LEN
, tok
->args
[0], strlen(tok
->args
[0]))) {
905 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
906 escaped(tok
->args
[0]));
909 if (memcmp(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)!=0) {
910 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
916 if ((tok
= find_first_by_keyword(tokens
, K_PLATFORM
))) {
917 router
->platform
= tor_strdup(tok
->args
[0]);
920 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
))) {
921 router
->contact_info
= tor_strdup(tok
->args
[0]);
924 if ((tok
= find_first_by_keyword(tokens
, K_EVENTDNS
))) {
925 router
->has_old_dnsworkers
= tok
->n_args
&& !strcmp(tok
->args
[0], "0");
926 } else if (router
->platform
) {
927 if (! tor_version_as_new_as(router
->platform
, "0.1.2.2-alpha"))
928 router
->has_old_dnsworkers
= 1;
931 exit_policy_tokens
= find_all_exitpolicy(tokens
);
932 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
933 if (router_add_exit_policy(router
,t
)<0) {
934 log_warn(LD_DIR
,"Error in exit policy");
938 if ((tok
= find_first_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
940 router
->declared_family
= smartlist_create();
941 for (i
=0;i
<tok
->n_args
;++i
) {
942 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
943 log_warn(LD_DIR
, "Illegal nickname %s in family line",
944 escaped(tok
->args
[i
]));
947 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
951 if (!(tok
= find_first_by_keyword(tokens
, K_ROUTER_SIGNATURE
))) {
952 log_warn(LD_DIR
, "Missing router signature");
955 if (tok
!= find_last_by_keyword(tokens
, K_ROUTER_SIGNATURE
)) {
956 log_warn(LD_DIR
, "Multiple signatures on one router. Ignoring.");
959 if (!tok
->object_type
||
960 strcmp(tok
->object_type
, "SIGNATURE") || tok
->object_size
!= 128) {
961 log_warn(LD_DIR
, "Bad object type or length on router signature");
964 note_crypto_pk_op(VERIFY_RTR
);
965 #ifdef COUNT_DISTINCT_DIGESTS
966 if (!verified_digests
)
967 verified_digests
= digestmap_new();
968 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
970 if ((t
=crypto_pk_public_checksig(router
->identity_pkey
, signed_digest
,
971 tok
->object_body
, 128)) != 20) {
972 log_warn(LD_DIR
, "Invalid signature %d",t
);
975 if (memcmp(digest
, signed_digest
, DIGEST_LEN
)) {
976 log_warn(LD_DIR
, "Mismatched signature");
980 if (!router
->or_port
) {
981 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
985 if (!router
->platform
) {
986 router
->platform
= tor_strdup("<unknown>");
992 routerinfo_free(router
);
996 SMARTLIST_FOREACH(tokens
, directory_token_t
*, tok
, token_free(tok
));
997 smartlist_free(tokens
);
999 if (exit_policy_tokens
) {
1000 smartlist_free(exit_policy_tokens
);
1005 /** Helper: given a string <b>s</b>, return the start of the next router-status
1006 * object (starting with "r " at the start of a line). If none is found,
1007 * return the start of the next directory signature. If none is found, return
1008 * the end of the string. */
1009 static INLINE
const char *
1010 find_start_of_next_routerstatus(const char *s
)
1012 const char *eos
= strstr(s
, "\nr ");
1014 eos
= strstr(s
, "\ndirectory-signature");
1018 return s
+ strlen(s
);
1021 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1022 * empty smartlist at <b>tokens</b>, parse and return the first router status
1023 * object in the string, and advance *<b>s</b> to just after the end of the
1024 * router status. Return NULL and advance *<b>s</b> on error. */
1025 static routerstatus_t
*
1026 routerstatus_parse_entry_from_string(const char **s
, smartlist_t
*tokens
)
1029 routerstatus_t
*rs
= NULL
;
1030 directory_token_t
*tok
;
1031 char timebuf
[ISO_TIME_LEN
+1];
1036 eos
= find_start_of_next_routerstatus(*s
);
1038 if (tokenize_string(*s
, eos
, tokens
, RTRSTATUS
)) {
1039 log_warn(LD_DIR
, "Error tokenizing router status");
1042 if (smartlist_len(tokens
) < 1) {
1043 log_warn(LD_DIR
, "Impossibly short router status");
1046 if (!(tok
= find_first_by_keyword(tokens
, K_R
))) {
1047 log_warn(LD_DIR
, "Missing 'r' keywork in router status; skipping.");
1050 if (tok
->n_args
< 8) {
1052 "Too few arguments to 'r' keywork in router status; skipping.");
1054 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
1056 if (!is_legal_nickname(tok
->args
[0])) {
1058 "Invalid nickname %s in router status; skipping.",
1059 escaped(tok
->args
[0]));
1062 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
1064 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
1065 log_warn(LD_DIR
, "Error decoding identity digest %s",
1066 escaped(tok
->args
[1]));
1070 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
1071 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
1072 escaped(tok
->args
[2]));
1076 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
1077 tok
->args
[3], tok
->args
[4]) < 0 ||
1078 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
1079 log_warn(LD_DIR
, "Error parsing time '%s %s'",
1080 tok
->args
[3], tok
->args
[4]);
1084 if (tor_inet_aton(tok
->args
[5], &in
) == 0) {
1085 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
1086 escaped(tok
->args
[5]));
1089 rs
->addr
= ntohl(in
.s_addr
);
1091 rs
->or_port
=(uint16_t) tor_parse_long(tok
->args
[6],10,0,65535,NULL
,NULL
);
1092 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7],10,0,65535,NULL
,NULL
);
1094 if ((tok
= find_first_by_keyword(tokens
, K_S
))) {
1096 for (i
=0; i
< tok
->n_args
; ++i
) {
1097 if (!strcmp(tok
->args
[i
], "Exit"))
1099 else if (!strcmp(tok
->args
[i
], "Stable"))
1101 else if (!strcmp(tok
->args
[i
], "Fast"))
1103 else if (!strcmp(tok
->args
[i
], "Running"))
1105 else if (!strcmp(tok
->args
[i
], "Named"))
1107 else if (!strcmp(tok
->args
[i
], "Valid"))
1109 else if (!strcmp(tok
->args
[i
], "V2Dir"))
1111 else if (!strcmp(tok
->args
[i
], "Guard"))
1112 rs
->is_possible_guard
= 1;
1113 else if (!strcmp(tok
->args
[i
], "BadExit"))
1114 rs
->is_bad_exit
= 1;
1115 else if (!strcmp(tok
->args
[i
], "BadDirectory"))
1116 rs
->is_bad_directory
= 1;
1119 if ((tok
= find_first_by_keyword(tokens
, K_V
)) && tok
->n_args
) {
1120 rs
->version_known
= 1;
1121 if (strcmpstart(tok
->args
[0], "Tor ")) {
1122 rs
->version_supports_begindir
= 1;
1124 rs
->version_supports_begindir
=
1125 tor_version_as_new_as(tok
->args
[0], "0.1.2.2-alpha");
1129 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
1135 routerstatus_free(rs
);
1138 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1139 smartlist_clear(tokens
);
1145 /** Helper to sort a smartlist of pointers to routerstatus_t */
1147 _compare_routerstatus_entries(const void **_a
, const void **_b
)
1149 const routerstatus_t
*a
= *_a
, *b
= *_b
;
1150 return memcmp(a
->identity_digest
, b
->identity_digest
, DIGEST_LEN
);
1153 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1155 _free_duplicate_routerstatus_entry(void *e
)
1158 "Network-status has two entries for the same router. "
1160 routerstatus_free(e
);
1163 /** Given a versioned (v2 or later) network-status object in <b>s</b>, try to
1164 * parse it and return the result. Return NULL on failure. Check the
1165 * signature of the network status, but do not (yet) check the signing key for
1169 networkstatus_parse_from_string(const char *s
)
1172 smartlist_t
*tokens
= smartlist_create();
1173 networkstatus_t
*ns
= NULL
;
1174 char ns_digest
[DIGEST_LEN
];
1175 char tmp_digest
[DIGEST_LEN
];
1177 directory_token_t
*tok
;
1180 if (router_get_networkstatus_v2_hash(s
, ns_digest
)) {
1181 log_warn(LD_DIR
, "Unable to compute digest of network-status");
1185 eos
= find_start_of_next_routerstatus(s
);
1186 if (tokenize_string(s
, eos
, tokens
, NETSTATUS
)) {
1187 log_warn(LD_DIR
, "Error tokenizing network-status header.");
1190 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
1191 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
1193 if (!(tok
= find_first_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
))) {
1194 log_warn(LD_DIR
, "Couldn't find network-status-version keyword");
1198 if (!(tok
= find_first_by_keyword(tokens
, K_DIR_SOURCE
))) {
1199 log_warn(LD_DIR
, "Couldn't find dir-source keyword");
1202 if (tok
->n_args
< 3) {
1203 log_warn(LD_DIR
, "Too few arguments to dir-source keyword");
1206 ns
->source_address
= tok
->args
[0]; tok
->args
[0] = NULL
;
1207 if (tor_inet_aton(tok
->args
[1], &in
) == 0) {
1208 log_warn(LD_DIR
, "Error parsing network-status source address %s",
1209 escaped(tok
->args
[1]));
1212 ns
->source_addr
= ntohl(in
.s_addr
);
1213 ns
->source_dirport
=
1214 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
1215 if (ns
->source_dirport
== 0) {
1216 log_warn(LD_DIR
, "Directory source without dirport; skipping.");
1220 if (!(tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
))) {
1221 log_warn(LD_DIR
, "Couldn't find fingerprint keyword");
1224 if (tok
->n_args
< 1) {
1225 log_warn(LD_DIR
, "Too few arguments to networkstatus fingerprint");
1228 if (base16_decode(ns
->identity_digest
, DIGEST_LEN
, tok
->args
[0],
1229 strlen(tok
->args
[0]))) {
1230 log_warn(LD_DIR
, "Couldn't decode networkstatus fingerprint %s",
1231 escaped(tok
->args
[0]));
1235 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
)) && tok
->n_args
) {
1236 ns
->contact
= tok
->args
[0];
1237 tok
->args
[0] = NULL
;
1240 if (!(tok
= find_first_by_keyword(tokens
, K_DIR_SIGNING_KEY
)) || !tok
->key
) {
1241 log_warn(LD_DIR
, "Missing dir-signing-key");
1244 ns
->signing_key
= tok
->key
;
1247 if (crypto_pk_get_digest(ns
->signing_key
, tmp_digest
)<0) {
1248 log_warn(LD_DIR
, "Couldn't compute signing key digest");
1251 if (memcmp(tmp_digest
, ns
->identity_digest
, DIGEST_LEN
)) {
1253 "network-status fingerprint did not match dir-signing-key");
1257 if ((tok
= find_first_by_keyword(tokens
, K_DIR_OPTIONS
))) {
1258 for (i
=0; i
< tok
->n_args
; ++i
) {
1259 if (!strcmp(tok
->args
[i
], "Names"))
1260 ns
->binds_names
= 1;
1261 if (!strcmp(tok
->args
[i
], "Versions"))
1262 ns
->recommends_versions
= 1;
1263 if (!strcmp(tok
->args
[i
], "BadExits"))
1264 ns
->lists_bad_exits
= 1;
1265 if (!strcmp(tok
->args
[i
], "BadDirectories"))
1266 ns
->lists_bad_directories
= 1;
1270 if (ns
->recommends_versions
) {
1271 if (!(tok
= find_first_by_keyword(tokens
, K_CLIENT_VERSIONS
)) ||
1273 log_warn(LD_DIR
, "Missing client-versions");
1275 ns
->client_versions
= tok
->args
[0];
1276 tok
->args
[0] = NULL
;
1278 if (!(tok
= find_first_by_keyword(tokens
, K_SERVER_VERSIONS
)) ||
1280 log_warn(LD_DIR
, "Missing server-versions on versioning directory");
1283 ns
->server_versions
= tok
->args
[0];
1284 tok
->args
[0] = NULL
;
1287 if (!(tok
= find_first_by_keyword(tokens
, K_PUBLISHED
))) {
1288 log_warn(LD_DIR
, "Missing published time on network-status.");
1291 tor_assert(tok
->n_args
== 1);
1292 if (parse_iso_time(tok
->args
[0], &ns
->published_on
) < 0) {
1296 ns
->entries
= smartlist_create();
1298 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1299 smartlist_clear(tokens
);
1300 while (!strcmpstart(s
, "r ")) {
1302 if ((rs
= routerstatus_parse_entry_from_string(&s
, tokens
)))
1303 smartlist_add(ns
->entries
, rs
);
1305 smartlist_sort(ns
->entries
, _compare_routerstatus_entries
);
1306 smartlist_uniq(ns
->entries
, _compare_routerstatus_entries
,
1307 _free_duplicate_routerstatus_entry
);
1309 if (tokenize_string(s
, NULL
, tokens
, NETSTATUS
)) {
1310 log_warn(LD_DIR
, "Error tokenizing network-status footer.");
1313 if (smartlist_len(tokens
) < 1) {
1314 log_warn(LD_DIR
, "Too few items in network-status footer.");
1317 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
1318 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
1320 "Expected network-status footer to end with a signature.");
1324 note_crypto_pk_op(VERIFY_DIR
);
1325 if (check_directory_signature(ns_digest
, tok
, NULL
, ns
->signing_key
, 0))
1331 networkstatus_free(ns
);
1334 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1335 smartlist_free(tokens
);
1340 /** Parse the addr policy in the string <b>s</b> and return it. If
1341 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
1342 * ADDR_POLICY_REJECT) for items that specify no action.
1345 router_parse_addr_policy_from_string(const char *s
, int assume_action
)
1347 directory_token_t
*tok
= NULL
;
1353 /* *s might not end with \n, so we need to extend it with one. */
1355 cp
= tmp
= tor_malloc(len
+2);
1356 for (idx
= 0; idx
< len
; ++idx
) {
1357 tmp
[idx
] = TOR_TOLOWER(s
[idx
]);
1361 while (TOR_ISSPACE(*cp
))
1363 if ((*cp
== '*' || TOR_ISDIGIT(*cp
)) && assume_action
>= 0) {
1364 char *new_str
= tor_malloc(len
+10);
1365 tor_snprintf(new_str
, len
+10, "%s %s\n",
1366 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", cp
);
1370 tok
= get_next_token(&cp
, RTR
);
1371 if (tok
->tp
== _ERR
) {
1372 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
1375 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_REJECT
) {
1376 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
1380 /* Now that we've gotten an addr policy, add it to the router. */
1381 r
= router_parse_addr_policy(tok
);
1391 /** Add an exit policy stored in the token <b>tok</b> to the router info in
1392 * <b>router</b>. Return 0 on success, -1 on failure. */
1394 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
1396 addr_policy_t
*newe
, **tmpe
;
1397 newe
= router_parse_addr_policy(tok
);
1400 for (tmpe
= &router
->exit_policy
; *tmpe
; tmpe
=&((*tmpe
)->next
))
1407 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
1408 * a new exit_policy_t corresponding to the token. */
1409 static addr_policy_t
*
1410 router_parse_addr_policy(directory_token_t
*tok
)
1412 addr_policy_t
*newe
;
1414 char buf
[POLICY_BUF_LEN
];
1416 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_ACCEPT
);
1418 if (tok
->n_args
!= 1)
1422 if (!strcmpstart(arg
,"private"))
1423 return router_parse_addr_policy_private(tok
);
1425 newe
= tor_malloc_zero(sizeof(addr_policy_t
));
1427 newe
->policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
1428 : ADDR_POLICY_ACCEPT
;
1430 if (parse_addr_and_port_range(arg
, &newe
->addr
, &newe
->msk
,
1431 &newe
->prt_min
, &newe
->prt_max
))
1432 goto policy_read_failed
;
1434 if (policy_write_item(buf
, sizeof(buf
), newe
) < 0)
1435 goto policy_read_failed
;
1437 newe
->string
= tor_strdup(buf
);
1441 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
1446 /** Parse an exit policy line of the format "accept/reject private:...".
1447 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
1448 * router descriptors until earlier versions are obsolete.
1450 static addr_policy_t
*
1451 router_parse_addr_policy_private(directory_token_t
*tok
)
1453 static const char *private_nets
[] = {
1454 "0.0.0.0/8", "169.254.0.0/16",
1455 "127.0.0.0/8", "192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12",NULL
};
1457 addr_policy_t
*result
, **nextp
;
1459 uint16_t port_min
, port_max
;
1462 if (strcmpstart(arg
, "private"))
1464 arg
+= strlen("private");
1465 arg
= (char*) eat_whitespace(arg
);
1466 if (!arg
|| *arg
!= ':')
1469 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
1473 for (net
= 0; private_nets
[net
]; ++net
) {
1475 *nextp
= tor_malloc_zero(sizeof(addr_policy_t
));
1476 (*nextp
)->policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
1477 : ADDR_POLICY_ACCEPT
;
1478 len
= strlen(arg
)+strlen(private_nets
[net
])+16;
1479 (*nextp
)->string
= tor_malloc(len
+1);
1480 tor_snprintf((*nextp
)->string
, len
, "%s %s%s",
1481 tok
->tp
== K_REJECT
? "reject" : "accept",
1482 private_nets
[net
], arg
);
1483 if (parse_addr_and_port_range((*nextp
)->string
+ 7,
1484 &(*nextp
)->addr
, &(*nextp
)->msk
,
1485 &(*nextp
)->prt_min
, &(*nextp
)->prt_max
)) {
1486 log_warn(LD_BUG
, "Couldn't parse an address range we generated!");
1489 nextp
= &(*nextp
)->next
;
1495 /** Log and exit if <b>t</b> is malformed */
1497 assert_addr_policy_ok(addr_policy_t
*t
)
1501 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
1502 t
->policy_type
== ADDR_POLICY_ACCEPT
);
1503 tor_assert(t
->prt_min
<= t
->prt_max
);
1504 t2
= router_parse_addr_policy_from_string(t
->string
, -1);
1506 tor_assert(t2
->policy_type
== t
->policy_type
);
1507 tor_assert(t2
->addr
== t
->addr
);
1508 tor_assert(t2
->msk
== t
->msk
);
1509 tor_assert(t2
->prt_min
== t
->prt_min
);
1510 tor_assert(t2
->prt_max
== t
->prt_max
);
1511 tor_assert(!strcmp(t2
->string
, t
->string
));
1512 tor_assert(t2
->next
== NULL
);
1513 addr_policy_free(t2
);
1521 * Low-level tokenizer for router descriptors and directories.
1524 /** Free all resources allocated for <b>tok</b> */
1526 token_free(directory_token_t
*tok
)
1531 for (i
= 0; i
< tok
->n_args
; ++i
) {
1532 tor_free(tok
->args
[i
]);
1534 tor_free(tok
->args
);
1536 tor_free(tok
->object_type
);
1537 tor_free(tok
->object_body
);
1539 crypto_free_pk_env(tok
->key
);
1543 /** Helper function: read the next token from *s, advance *s to the end
1544 * of the token, and return the parsed token. If 'where' is DIR
1545 * or RTR, reject all tokens of the wrong type.
1547 static directory_token_t
*
1548 get_next_token(const char **s
, where_syntax where
)
1550 const char *next
, *obstart
;
1551 int i
, done
, allocated
, is_opt
;
1552 directory_token_t
*tok
;
1554 obj_syntax o_syn
= NO_OBJ
;
1556 #define RET_ERR(msg) \
1557 do { if (tok) token_free(tok); \
1558 tok = tor_malloc_zero(sizeof(directory_token_t));\
1561 goto done_tokenizing; } while (0)
1563 tok
= tor_malloc_zero(sizeof(directory_token_t
));
1566 *s
= eat_whitespace(*s
);
1571 next
= find_whitespace(*s
);
1573 tok
->error
= "Unexpected EOF"; return tok
;
1575 /* It's a keyword... but which one? */
1576 is_opt
= !strncmp("opt", *s
, next
-*s
);
1578 *s
= eat_whitespace(next
);
1581 next
= find_whitespace(*s
);
1582 if (!**s
|| !next
) {
1583 RET_ERR("opt without keyword");
1586 for (i
= 0; token_table
[i
].t
; ++i
) {
1587 if (!strncmp(token_table
[i
].t
, *s
, next
-*s
)) {
1588 /* We've found the keyword. */
1589 tok
->tp
= token_table
[i
].v
;
1590 a_syn
= token_table
[i
].s
;
1591 o_syn
= token_table
[i
].os
;
1592 if (!(token_table
[i
].ws
& where
)) {
1594 RET_ERR("Found an out-of-place token in a directory section");
1595 } else if (where
== RTR
) {
1596 RET_ERR("Found an out-of-place token in a router descriptor");
1597 } else if (where
== NETSTATUS
) {
1598 RET_ERR("Found an out-of-place token in a network-status header");
1600 RET_ERR("Found an out-of-place token in a router status body");
1603 if (a_syn
== ARGS
) {
1604 /* This keyword takes multiple arguments. */
1606 done
= (*next
== '\n');
1608 tok
->args
= tor_malloc(sizeof(char*)*32);
1609 *s
= eat_whitespace_no_nl(next
);
1610 while (**s
!= '\n' && !done
) {
1611 next
= find_whitespace(*s
);
1614 if (i
== allocated
) {
1616 tok
->args
= tor_realloc(tok
->args
,sizeof(char*)*allocated
);
1618 tok
->args
[i
++] = tor_strndup(*s
,next
-*s
);
1619 *s
= eat_whitespace_no_nl(next
+1);
1622 } else if (a_syn
== CONCAT_ARGS
) {
1623 /* The keyword takes the line as a single argument */
1624 *s
= eat_whitespace_no_nl(next
);
1625 next
= strchr(*s
, '\n');
1627 RET_ERR("Unexpected EOF");
1628 tok
->args
= tor_malloc(sizeof(char*));
1629 tok
->args
[0] = tor_strndup(*s
,next
-*s
);
1631 *s
= eat_whitespace_no_nl(next
+1);
1633 /* The keyword takes no arguments. */
1634 tor_assert(a_syn
== NO_ARGS
);
1635 *s
= eat_whitespace_no_nl(next
);
1637 RET_ERR("Unexpected arguments");
1640 *s
= eat_whitespace_no_nl(*s
+1);
1645 if (tok
->tp
== _ERR
) {
1647 *s
= eat_whitespace_no_nl(next
);
1648 next
= strchr(*s
,'\n');
1650 RET_ERR("Unexpected EOF");
1651 tok
->args
= tor_malloc(sizeof(char*));
1652 tok
->args
[0] = tor_strndup(*s
,next
-*s
);
1654 *s
= eat_whitespace_no_nl(next
+1);
1657 *s
= eat_whitespace(*s
);
1658 if (strcmpstart(*s
, "-----BEGIN ")) {
1662 *s
+= 11; /* length of "-----BEGIN ". */
1663 next
= strchr(*s
, '\n');
1664 if (next
-*s
< 6 || strcmpstart(next
-5, "-----\n")) {
1665 RET_ERR("Malformed object: bad begin line");
1667 tok
->object_type
= tor_strndup(*s
, next
-*s
-5);
1669 next
= strstr(*s
, "-----END ");
1671 RET_ERR("Malformed object: missing end line");
1673 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) {
1674 if (strcmpstart(next
, "-----END RSA PUBLIC KEY-----\n"))
1675 RET_ERR("Malformed object: mismatched end line");
1676 next
= strchr(next
,'\n')+1;
1677 tok
->key
= crypto_new_pk_env();
1678 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, next
-obstart
))
1679 RET_ERR("Couldn't parse public key.");
1682 tok
->object_body
= tor_malloc(next
-*s
); /* really, this is too much RAM. */
1683 i
= base64_decode(tok
->object_body
, 256, *s
, next
-*s
);
1685 RET_ERR("Malformed object: bad base64-encoded data");
1687 tok
->object_size
= i
;
1688 *s
= next
+ 9; /* length of "-----END ". */
1689 i
= strlen(tok
->object_type
);
1690 if (strncmp(*s
, tok
->object_type
, i
) || strcmpstart(*s
+i
, "-----\n")) {
1691 RET_ERR("Malformed object: mismatched end tag");
1699 if (tok
->object_body
)
1700 RET_ERR("Unexpected object for keyword");
1702 RET_ERR("Unexpected public key for keyword");
1705 if (!tok
->object_body
)
1706 RET_ERR("Missing object for keyword");
1710 RET_ERR("Missing public key for keyword");
1722 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
1723 * them to <b>out</b>. If <b>is_dir</b> is true, reject all non-directory
1724 * tokens; else reject all non-routerdescriptor tokens.
1727 tokenize_string(const char *start
, const char *end
, smartlist_t
*out
,
1731 directory_token_t
*tok
= NULL
;
1734 end
= start
+strlen(start
);
1735 while (*s
< end
&& (!tok
|| tok
->tp
!= _EOF
)) {
1736 tok
= get_next_token(s
, where
);
1737 if (tok
->tp
== _ERR
) {
1738 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
1741 smartlist_add(out
, tok
);
1742 *s
= eat_whitespace(*s
);
1748 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
1749 * NULL if no such keyword is found.
1751 static directory_token_t
*
1752 find_first_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
1754 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
1758 /** Find the last token in <b>s</b> whose keyword is <b>keyword</b>; return
1759 * NULL if no such keyword is found.
1761 static directory_token_t
*
1762 find_last_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
1764 directory_token_t
*last
= NULL
;
1765 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) last
= t
);
1769 /** Return a newly allocated smartlist of all accept or reject tokens in
1772 static smartlist_t
*
1773 find_all_exitpolicy(smartlist_t
*s
)
1775 smartlist_t
*out
= smartlist_create();
1776 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
1777 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_REJECT
)
1778 smartlist_add(out
,t
));
1782 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
1783 * occurrence of <b>start_str</b> through the first newline after the first
1784 * subsequent occurrence of <b>end_str</b>; store the 20-byte result in
1785 * <b>digest</b>; return 0 on success.
1787 * If no such substring exists, return -1.
1790 router_get_hash_impl(const char *s
, char *digest
,
1791 const char *start_str
,
1792 const char *end_str
)
1795 start
= strstr(s
, start_str
);
1797 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
1800 if (start
!= s
&& *(start
-1) != '\n') {
1802 "first occurrence of \"%s\" is not at the start of a line",
1806 end
= strstr(start
+strlen(start_str
), end_str
);
1808 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
1811 end
= strchr(end
+strlen(end_str
), '\n');
1813 log_warn(LD_DIR
,"couldn't find EOL");
1818 if (crypto_digest(digest
, start
, end
-start
)) {
1819 log_warn(LD_BUG
,"couldn't compute digest");
1826 /** Parse the Tor version of the platform string <b>platform</b>,
1827 * and compare it to the version in <b>cutoff</b>. Return 1 if
1828 * the router is at least as new as the cutoff, else return 0.
1831 tor_version_as_new_as(const char *platform
, const char *cutoff
)
1833 tor_version_t cutoff_version
, router_version
;
1837 tor_assert(platform
);
1839 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
1840 log_warn(LD_DIR
,"Bug: cutoff version '%s' unparseable.",cutoff
);
1843 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
1846 start
= (char *)eat_whitespace(platform
+3);
1847 if (!*start
) return 0;
1848 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
1849 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
1851 strlcpy(tmp
, start
, s
-start
+1);
1853 if (tor_version_parse(tmp
, &router_version
)<0) {
1854 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
1855 return 1; /* be safe and say yes */
1858 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
1861 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
1862 * Return 0 on success, -1 on failure. */
1864 tor_version_parse(const char *s
, tor_version_t
*out
)
1866 char *eos
=NULL
, *cp
=NULL
;
1868 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
1873 memset(out
, 0, sizeof(tor_version_t
));
1875 if (!strcasecmpstart(s
, "Tor "))
1879 out
->major
= strtol(s
,&eos
,10);
1880 if (!eos
|| eos
==s
|| *eos
!= '.') return -1;
1884 out
->minor
= strtol(cp
,&eos
,10);
1885 if (!eos
|| eos
==cp
|| *eos
!= '.') return -1;
1889 out
->micro
= strtol(cp
,&eos
,10);
1890 if (!eos
|| eos
==cp
) return -1;
1892 out
->status
= VER_RELEASE
;
1893 out
->patchlevel
= 0;
1900 out
->status
= VER_RELEASE
;
1902 } else if (0==strncmp(cp
, "pre", 3)) {
1903 out
->status
= VER_PRE
;
1905 } else if (0==strncmp(cp
, "rc", 2)) {
1906 out
->status
= VER_RC
;
1912 /* Get patchlevel */
1913 out
->patchlevel
= strtol(cp
,&eos
,10);
1914 if (!eos
|| eos
==cp
) return -1;
1917 /* Get status tag. */
1918 if (*cp
== '-' || *cp
== '.')
1920 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
1925 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
1928 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
1933 if ((i
= a
->major
- b
->major
))
1935 else if ((i
= a
->minor
- b
->minor
))
1937 else if ((i
= a
->micro
- b
->micro
))
1939 else if ((i
= a
->status
- b
->status
))
1941 else if ((i
= a
->patchlevel
- b
->patchlevel
))
1944 return strcmp(a
->status_tag
, b
->status_tag
);
1947 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
1950 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
1954 return ((a
->major
== b
->major
) &&
1955 (a
->minor
== b
->minor
) &&
1956 (a
->micro
== b
->micro
));
1959 /** Helper: Given pointers to two strings describing tor versions, return -1
1960 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
1961 * Used to sort a list of versions. */
1963 _compare_tor_version_str_ptr(const void **_a
, const void **_b
)
1965 const char *a
= *_a
, *b
= *_b
;
1967 tor_version_t va
, vb
;
1968 ca
= tor_version_parse(a
, &va
);
1969 cb
= tor_version_parse(b
, &vb
);
1970 /* If they both parse, compare them. */
1972 return tor_version_compare(&va
,&vb
);
1973 /* If one parses, it comes first. */
1978 /* If neither parses, compare strings. Also, the directory server admin
1979 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
1983 /** Sort a list of string-representations of versions in ascending order. */
1985 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
1987 smartlist_sort(versions
, _compare_tor_version_str_ptr
);
1989 if (remove_duplicates
)
1990 smartlist_uniq(versions
, _compare_tor_version_str_ptr
, NULL
);