1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 const char routerparse_c_id
[] =
12 * \brief Code to parse and validate router descriptors and directories.
17 /****************************************************************************/
19 /** Enumeration of possible token types. The ones starting with K_ correspond
20 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
21 * is an end-of-file marker, and _NIL is used to encode not-a-token.
25 K_DIRECTORY_SIGNATURE
,
26 K_RECOMMENDED_SOFTWARE
,
49 K_NETWORK_STATUS_VERSION
,
63 K_DIR_KEY_CERTIFICATE_VERSION
,
67 K_DIR_KEY_CERTIFICATION
,
85 R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
91 R_INTRODUCTION_POINTS
,
106 #define MIN_ANNOTATION A_PURPOSE
107 #define MAX_ANNOTATION _A_UNKNOWN
109 /** Structure to hold a single directory token.
111 * We parse a directory by breaking it into "tokens", each consisting
112 * of a keyword, a line full of arguments, and a binary object. The
113 * arguments and object are both optional, depending on the keyword
116 typedef struct directory_token_t
{
117 directory_keyword tp
; /**< Type of the token. */
118 int n_args
; /**< Number of elements in args */
119 char **args
; /**< Array of arguments from keyword line. */
120 char *object_type
; /**< -----BEGIN [object_type]-----*/
121 size_t object_size
; /**< Bytes in object_body */
122 char *object_body
; /**< Contents of object, base64-decoded. */
123 crypto_pk_env_t
*key
; /**< For public keys only. */
124 char *error
; /**< For _ERR tokens only. */
127 /* ********************************************************************** */
129 /** We use a table of rules to decide how to parse each token type. */
131 /** Rules for whether the keyword needs an object. */
133 NO_OBJ
, /**< No object, ever. */
134 NEED_OBJ
, /**< Object is required. */
135 NEED_KEY_1024
, /**< Object is required, and must be a 1024 bit public key */
136 NEED_KEY
, /**< Object is required, and must be a public key. */
137 OBJ_OK
, /**< Object is optional. */
143 /** Determines the parsing rules for a single token type. */
144 typedef struct token_rule_t
{
145 /** The string value of the keyword identifying the type of item. */
147 /** The corresponding directory_keyword enum. */
149 /** Minimum number of arguments for this item */
151 /** Maximum number of arguments for this item */
153 /** If true, we concatenate all arguments for this item into a single
156 /** Requirments on object syntax for this item. */
158 /** Lowest number of times this item may appear in a document. */
160 /** Highest number of times this item may appear in a document. */
162 /** One or more of AT_START/AT_END to limit where the item may appear in a
165 /** True iff this token is an annotation. */
170 * Helper macros to define token tables. 's' is a string, 't' is a
171 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
176 /** Appears to indicate the end of a table. */
177 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
178 /** An item with no restrictions: used for obsolete document types */
179 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
180 /** An item with no restrictions on multiplicity or location. */
181 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
182 /** An item that must appear exactly once */
183 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
184 /** An item that must appear exactly once, at the start of the document */
185 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
186 /** An item that must appear exactly once, at the end of the document */
187 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
188 /** An item that must appear one or more times */
189 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
190 /** An item that must appear no more than once */
191 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
192 /** An annotation that must appear no more than once */
193 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
195 /* Argument multiplicity: any number of arguments. */
196 #define ARGS 0,INT_MAX,0
197 /* Argument multiplicity: no arguments. */
198 #define NO_ARGS 0,0,0
199 /* Argument multiplicity: concatenate all arguments. */
200 #define CONCAT_ARGS 1,1,1
201 /* Argument multiplicity: at least <b>n</b> arguments. */
202 #define GE(n) n,INT_MAX,0
203 /* Argument multiplicity: exactly <b>n</b> arguments. */
206 /** List of tokens allowable in router derscriptors */
207 static token_rule_t routerdesc_token_table
[] = {
208 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
209 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
210 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
211 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
212 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
213 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
214 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
215 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
216 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
217 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
218 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
219 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
220 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
221 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
222 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
223 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR
, NO_ARGS
, NO_OBJ
),
225 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
226 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
227 T01("eventdns", K_EVENTDNS
, ARGS
, NO_OBJ
),
229 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
230 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
231 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
236 /** List of tokens allowable in extra-info documents. */
237 static token_rule_t extrainfo_token_table
[] = {
238 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
239 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
240 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
241 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
242 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
243 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
248 /** List of tokens allowable in the body part of v2 and v3 networkstatus
250 static token_rule_t rtrstatus_token_table
[] = {
251 T1( "r", K_R
, GE(8), NO_OBJ
),
252 T1( "s", K_S
, ARGS
, NO_OBJ
),
253 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
254 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
258 /** List of tokens allowable in the header part of v2 networkstatus documents.
260 static token_rule_t netstatus_token_table
[] = {
261 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
262 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
263 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
264 T1( "dir-signing-key", K_DIR_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
265 T1( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
266 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
268 T1( "dir-source", K_DIR_SOURCE
, GE(3), NO_OBJ
),
269 T01("dir-options", K_DIR_OPTIONS
, ARGS
, NO_OBJ
),
270 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
271 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
276 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
278 static token_rule_t dir_footer_token_table
[] = {
279 T1("directory-signature", K_DIRECTORY_SIGNATURE
, EQ(1), NEED_OBJ
),
283 /** List of tokens allowable in v1 directory headers/footers. */
284 static token_rule_t dir_token_table
[] = {
285 /* don't enforce counts; this is obsolete. */
286 T( "network-status", K_NETWORK_STATUS
, NO_ARGS
, NO_OBJ
),
287 T( "directory-signature", K_DIRECTORY_SIGNATURE
, ARGS
, NEED_OBJ
),
288 T( "recommended-software",K_RECOMMENDED_SOFTWARE
,CONCAT_ARGS
, NO_OBJ
),
289 T( "signed-directory", K_SIGNED_DIRECTORY
, NO_ARGS
, NO_OBJ
),
291 T( "running-routers", K_RUNNING_ROUTERS
, ARGS
, NO_OBJ
),
292 T( "router-status", K_ROUTER_STATUS
, ARGS
, NO_OBJ
),
293 T( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
294 T( "opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
295 T( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
296 T( "dir-signing-key", K_DIR_SIGNING_KEY
, ARGS
, OBJ_OK
),
297 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
302 #define CERTIFICATE_MEMBERS \
303 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
305 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
306 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
307 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
308 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
309 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
310 NO_ARGS, NEED_OBJ), \
311 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
313 static token_rule_t dir_key_certificate_table
[] = {
315 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
319 /** List of tokens allowable in rendezvous service descriptors */
320 static token_rule_t desc_token_table
[] = {
321 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
323 T1("version", R_VERSION
, EQ(1), NO_OBJ
),
324 T1("permanent-key", R_PERMANENT_KEY
, NO_ARGS
, NEED_KEY_1024
),
325 T1("secret-id-part", R_SECRET_ID_PART
, EQ(1), NO_OBJ
),
326 T1("publication-time", R_PUBLICATION_TIME
, CONCAT_ARGS
, NO_OBJ
),
327 T1("protocol-versions", R_PROTOCOL_VERSIONS
, EQ(1), NO_OBJ
),
328 T01("introduction-points", R_INTRODUCTION_POINTS
, NO_ARGS
, NEED_OBJ
),
329 T1_END("signature", R_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
333 /** List of tokens allowed in the (encrypted) list of introduction points of
334 * rendezvous service descriptors */
335 static token_rule_t ipo_token_table
[] = {
336 T1_START("introduction-point", R_IPO_IDENTIFIER
, EQ(1), NO_OBJ
),
337 T1("ip-address", R_IPO_IP_ADDRESS
, EQ(1), NO_OBJ
),
338 T1("onion-port", R_IPO_ONION_PORT
, EQ(1), NO_OBJ
),
339 T1("onion-key", R_IPO_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
340 T1("service-key", R_IPO_SERVICE_KEY
, NO_ARGS
, NEED_KEY_1024
),
344 static token_rule_t networkstatus_token_table
[] = {
345 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
347 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
348 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
349 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
350 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
351 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
352 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
353 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
354 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
358 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
359 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
360 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
361 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
362 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
363 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
364 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
368 static token_rule_t networkstatus_consensus_token_table
[] = {
369 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
371 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
372 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
373 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
374 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
375 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
377 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
379 T1N("dir-source", K_DIR_SOURCE
, GE(3), NO_OBJ
),
380 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
381 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
383 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
385 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
386 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
387 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
392 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
394 static token_rule_t networkstatus_vote_footer_token_table
[] = {
395 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
399 static token_rule_t networkstatus_detached_signature_token_table
[] = {
400 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
401 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
402 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
403 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
404 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
410 /* static function prototypes */
411 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
412 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
);
413 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
415 static int router_get_hash_impl(const char *s
, char *digest
,
416 const char *start_str
, const char *end_str
,
418 static void token_free(directory_token_t
*tok
);
419 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
420 static directory_token_t
*find_first_by_keyword(smartlist_t
*s
,
421 directory_keyword keyword
);
422 #define TS_ANNOTATIONS_OK 1
424 #define TS_NO_NEW_ANNOTATIONS 4
425 static int tokenize_string(const char *start
, const char *end
,
429 static directory_token_t
*get_next_token(const char **s
,
431 token_rule_t
*table
);
432 static int check_signature_token(const char *digest
,
433 directory_token_t
*tok
,
434 crypto_pk_env_t
*pkey
,
436 const char *doctype
);
437 static crypto_pk_env_t
*find_dir_signing_key(const char *str
, const char *eos
);
438 static int tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
);
440 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
441 * <b>s</b>. Return 0 on success, -1 on failure.
444 router_get_dir_hash(const char *s
, char *digest
)
446 return router_get_hash_impl(s
,digest
,
447 "signed-directory","\ndirectory-signature",'\n');
450 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
451 * <b>s</b>. Return 0 on success, -1 on failure.
454 router_get_router_hash(const char *s
, char *digest
)
456 return router_get_hash_impl(s
,digest
,
457 "router ","\nrouter-signature", '\n');
460 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
461 * string in <b>s</b>. Return 0 on success, -1 on failure.
464 router_get_runningrouters_hash(const char *s
, char *digest
)
466 return router_get_hash_impl(s
,digest
,
467 "network-status","\ndirectory-signature", '\n');
470 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
471 * string in <b>s</b>. Return 0 on success, -1 on failure. */
473 router_get_networkstatus_v2_hash(const char *s
, char *digest
)
475 return router_get_hash_impl(s
,digest
,
476 "network-status-version","\ndirectory-signature",
480 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
481 * string in <b>s</b>. Return 0 on success, -1 on failure. */
483 router_get_networkstatus_v3_hash(const char *s
, char *digest
)
485 return router_get_hash_impl(s
,digest
,
486 "network-status-version","\ndirectory-signature",
490 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
491 * string in <b>s</b>. Return 0 on success, -1 on failure. */
493 router_get_extrainfo_hash(const char *s
, char *digest
)
495 return router_get_hash_impl(s
,digest
,"extra-info","\nrouter-signature",'\n');
498 /** Helper: used to generate signatures for routers, directories and
499 * network-status objects. Given a digest in <b>digest</b> and a secret
500 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
501 * surround it with -----BEGIN/END----- pairs, and write it to the
502 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
506 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
507 crypto_pk_env_t
*private_key
)
512 signature
= tor_malloc(crypto_pk_keysize(private_key
));
513 if (crypto_pk_private_sign(private_key
, signature
, digest
, DIGEST_LEN
) < 0) {
515 log_warn(LD_BUG
,"Couldn't sign digest.");
518 if (strlcat(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
522 if (base64_encode(buf
+i
, buf_len
-i
, signature
, 128) < 0) {
523 log_warn(LD_BUG
,"couldn't base64-encode signature");
527 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
534 log_warn(LD_BUG
,"tried to exceed string length.");
540 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
541 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
542 * entries. Else, return VS_OLD if every member of
543 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
544 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
545 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
546 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
547 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
550 * (versionlist is a comma-separated list of version strings,
551 * optionally prefixed with "Tor". Versions that can't be parsed are
555 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
557 tor_version_t mine
, other
;
558 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
559 found_any_in_series
= 0, r
, same
;
560 version_status_t ret
= VS_UNRECOMMENDED
;
561 smartlist_t
*version_sl
;
563 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
564 myversion
, versionlist
);
566 if (tor_version_parse(myversion
, &mine
)) {
567 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
570 version_sl
= smartlist_create();
571 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
573 if (!strlen(versionlist
)) { /* no authorities cared or agreed */
578 SMARTLIST_FOREACH(version_sl
, const char *, cp
, {
579 if (!strcmpstart(cp
, "Tor "))
582 if (tor_version_parse(cp
, &other
)) {
583 /* Couldn't parse other; it can't be a match. */
585 same
= tor_version_same_series(&mine
, &other
);
587 found_any_in_series
= 1;
588 r
= tor_version_compare(&mine
, &other
);
590 ret
= VS_RECOMMENDED
;
595 found_newer_in_series
= 1;
602 /* We didn't find the listed version. Is it new or old? */
603 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
604 ret
= VS_NEW_IN_SERIES
;
605 } else if (found_newer
&& !found_older
) {
607 } else if (found_older
&& !found_newer
) {
610 ret
= VS_UNRECOMMENDED
;
614 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
615 smartlist_free(version_sl
);
619 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
620 * Otherwise, return -1. If we're a directory cache, cache it.
623 router_parse_directory(const char *str
)
625 directory_token_t
*tok
;
626 char digest
[DIGEST_LEN
];
629 const char *end
, *cp
;
630 smartlist_t
*tokens
= NULL
;
631 crypto_pk_env_t
*declared_key
= NULL
;
633 /* XXXX This could be simplified a lot, but it will all go away
634 * once pre-0.1.1.8 is obsolete, and for now it's better not to
637 if (router_get_dir_hash(str
, digest
)) {
638 log_warn(LD_DIR
, "Unable to compute digest of directory");
641 log_debug(LD_DIR
,"Received directory hashes to %s",hex_str(digest
,4));
643 /* Check signature first, before we try to tokenize. */
645 while (cp
&& (end
= strstr(cp
+1, "\ndirectory-signature")))
647 if (cp
== str
|| !cp
) {
648 log_warn(LD_DIR
, "No signature found on directory."); goto err
;
651 tokens
= smartlist_create();
652 if (tokenize_string(cp
,strchr(cp
,'\0'),tokens
,dir_token_table
,0)) {
653 log_warn(LD_DIR
, "Error tokenizing directory signature"); goto err
;
655 if (smartlist_len(tokens
) != 1) {
656 log_warn(LD_DIR
, "Unexpected number of tokens in signature"); goto err
;
658 tok
=smartlist_get(tokens
,0);
659 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
660 log_warn(LD_DIR
,"Expected a single directory signature"); goto err
;
662 declared_key
= find_dir_signing_key(str
, str
+strlen(str
));
663 note_crypto_pk_op(VERIFY_DIR
);
664 if (check_signature_token(digest
, tok
, declared_key
, 1, "directory")<0)
667 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
668 smartlist_free(tokens
);
671 /* Now try to parse the first part of the directory. */
672 if ((end
= strstr(str
,"\nrouter "))) {
674 } else if ((end
= strstr(str
, "\ndirectory-signature"))) {
677 end
= str
+ strlen(str
);
680 tokens
= smartlist_create();
681 if (tokenize_string(str
,end
,tokens
,dir_token_table
,0)) {
682 log_warn(LD_DIR
, "Error tokenizing directory"); goto err
;
685 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
687 tor_assert(tok
->n_args
== 1);
689 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
693 /* Now that we know the signature is okay, and we have a
694 * publication time, cache the directory. */
695 if (directory_caches_v1_dir_info(get_options()) &&
696 !authdir_mode_v1(get_options()))
697 dirserv_set_cached_directory(str
, published_on
, 0);
704 if (declared_key
) crypto_free_pk_env(declared_key
);
706 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
707 smartlist_free(tokens
);
712 /** Read a signed router status statement from <b>str</b>. If it's
713 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
716 router_parse_runningrouters(const char *str
)
718 char digest
[DIGEST_LEN
];
719 directory_token_t
*tok
;
722 crypto_pk_env_t
*declared_key
= NULL
;
723 smartlist_t
*tokens
= NULL
;
724 const char *eos
= str
+ strlen(str
);
726 if (router_get_runningrouters_hash(str
, digest
)) {
727 log_warn(LD_DIR
, "Unable to compute digest of running-routers");
730 tokens
= smartlist_create();
731 if (tokenize_string(str
,eos
,tokens
,dir_token_table
,0)) {
732 log_warn(LD_DIR
, "Error tokenizing running-routers"); goto err
;
734 tok
= smartlist_get(tokens
,0);
735 if (tok
->tp
!= K_NETWORK_STATUS
) {
736 log_warn(LD_DIR
, "Network-status starts with wrong token");
740 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
742 tor_assert(tok
->n_args
== 1);
743 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
746 if (!(tok
= find_first_by_keyword(tokens
, K_DIRECTORY_SIGNATURE
))) {
747 log_warn(LD_DIR
, "Missing signature on running-routers");
750 declared_key
= find_dir_signing_key(str
, eos
);
751 note_crypto_pk_op(VERIFY_DIR
);
752 if (check_signature_token(digest
, tok
, declared_key
, 1, "running-routers")
756 /* Now that we know the signature is okay, and we have a
757 * publication time, cache the list. */
758 if (get_options()->DirPort
&& !authdir_mode_v1(get_options()))
759 dirserv_set_cached_directory(str
, published_on
, 1);
763 if (declared_key
) crypto_free_pk_env(declared_key
);
765 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
766 smartlist_free(tokens
);
771 /** Given a directory or running-routers string in <b>str</b>, try to
772 * find the its dir-signing-key token (if any). If this token is
773 * present, extract and return the key. Return NULL on failure. */
774 static crypto_pk_env_t
*
775 find_dir_signing_key(const char *str
, const char *eos
)
778 directory_token_t
*tok
;
779 crypto_pk_env_t
*key
= NULL
;
783 /* Is there a dir-signing-key in the directory? */
784 cp
= tor_memstr(str
, eos
-str
, "\nopt dir-signing-key");
786 cp
= tor_memstr(str
, eos
-str
, "\ndir-signing-key");
789 ++cp
; /* Now cp points to the start of the token. */
791 tok
= get_next_token(&cp
, eos
, dir_token_table
);
793 log_warn(LD_DIR
, "Unparseable dir-signing-key token");
796 if (tok
->tp
!= K_DIR_SIGNING_KEY
) {
797 log_warn(LD_DIR
, "Dir-signing-key token did not parse as expected");
803 tok
->key
= NULL
; /* steal reference. */
805 log_warn(LD_DIR
, "Dir-signing-key token contained no key");
809 if (tok
) token_free(tok
);
813 /** Return true iff <b>key</b> is allowed to sign directories.
816 dir_signing_key_is_trusted(crypto_pk_env_t
*key
)
818 char digest
[DIGEST_LEN
];
820 if (crypto_pk_get_digest(key
, digest
) < 0) {
821 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
824 if (!router_digest_is_trusted_dir(digest
)) {
825 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
831 /** Check whether the object body of the token in <b>tok</b> has a good
832 * signature for <b>digest</b> using key <b>pkey</b>. If
833 * <b>check_authority</b> is set, make sure that <b>pkey</b> is the key of a
834 * directory authority. Use <b>doctype</b> as the type of the document when
835 * generating log messages. Return 0 on success, negative on failure.
838 check_signature_token(const char *digest
,
839 directory_token_t
*tok
,
840 crypto_pk_env_t
*pkey
,
851 if (check_authority
&& !dir_signing_key_is_trusted(pkey
)) {
852 log_warn(LD_DIR
, "Key on %s did not come from an authority; rejecting",
857 if (strcmp(tok
->object_type
, "SIGNATURE")) {
858 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
862 signed_digest
= tor_malloc(tok
->object_size
);
863 if (crypto_pk_public_checksig(pkey
, signed_digest
, tok
->object_body
,
866 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
867 tor_free(signed_digest
);
870 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
871 // hex_str(signed_digest,4));
872 if (memcmp(digest
, signed_digest
, DIGEST_LEN
)) {
873 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
874 tor_free(signed_digest
);
877 tor_free(signed_digest
);
881 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
882 * or to the first of the annotations proceeding the next router or
883 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
884 * we found an extrainfo, or false if found a router. Do not scan beyond
885 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
887 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
889 int *is_extrainfo_out
)
891 const char *annotations
= NULL
;
892 const char *s
= *s_ptr
;
894 s
= eat_whitespace_eos(s
, eos
);
896 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
897 /* We're at the start of a line. */
898 tor_assert(*s
!= '\n');
900 if (*s
== '@' && !annotations
) {
902 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
903 *s_ptr
= annotations
? annotations
: s
;
904 *is_extrainfo_out
= 0;
906 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
907 *s_ptr
= annotations
? annotations
: s
;
908 *is_extrainfo_out
= 1;
912 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
914 s
= eat_whitespace_eos(s
, eos
);
919 /** Given a string *<b>s</b> containing a concatenated sequence of router
920 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
921 * them and stores the result in <b>dest</b>. All routers are marked running
922 * and valid. Advances *s to a point immediately following the last router
923 * entry. Ignore any trailing router entries that are not complete.
925 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
926 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
927 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
929 * Returns 0 on success and -1 on failure.
932 router_parse_list_from_string(const char **s
, const char *eos
,
934 saved_location_t saved_location
,
936 int allow_annotations
,
937 const char *prepend_annotations
)
939 routerinfo_t
*router
;
940 extrainfo_t
*extrainfo
;
941 signed_descriptor_t
*signed_desc
;
943 const char *end
, *start
;
952 eos
= *s
+ strlen(*s
);
954 tor_assert(eos
>= *s
);
957 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
960 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
962 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
964 end
+= strlen("\n-----END SIGNATURE-----\n");
971 if (have_extrainfo
&& want_extrainfo
) {
972 routerlist_t
*rl
= router_get_routerlist();
973 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
974 saved_location
!= SAVED_IN_CACHE
,
977 signed_desc
= &extrainfo
->cache_info
;
980 } else if (!have_extrainfo
&& !want_extrainfo
) {
981 router
= router_parse_entry_from_string(*s
, end
,
982 saved_location
!= SAVED_IN_CACHE
,
984 prepend_annotations
);
986 log_debug(LD_DIR
, "Read router '%s', purpose '%s'",
987 router
->nickname
, router_purpose_to_string(router
->purpose
));
988 signed_desc
= &router
->cache_info
;
996 if (saved_location
!= SAVED_NOWHERE
) {
997 signed_desc
->saved_location
= saved_location
;
998 signed_desc
->saved_offset
= *s
- start
;
1001 smartlist_add(dest
, elt
);
1007 /* For debugging: define to count every descriptor digest we've seen so we
1008 * know if we need to try harder to avoid duplicate verifies. */
1009 #undef COUNT_DISTINCT_DIGESTS
1011 #ifdef COUNT_DISTINCT_DIGESTS
1012 static digestmap_t
*verified_digests
= NULL
;
1015 /** Log the total count of the number of distinct router digests we've ever
1016 * verified. When compared to the number of times we've verified routerdesc
1017 * signatures <i>in toto</i>, this will tell us if we're doing too much
1018 * multiple-verification. */
1020 dump_distinct_digest_count(int severity
)
1022 #ifdef COUNT_DISTINCT_DIGESTS
1023 if (!verified_digests
)
1024 verified_digests
= digestmap_new();
1025 log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
1026 digestmap_size(verified_digests
));
1028 (void)severity
; /* suppress "unused parameter" warning */
1032 /** Helper function: reads a single router entry from *<b>s</b> ...
1033 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1034 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1035 * s through end into the signed_descriptor_body of the resulting
1038 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1039 * before the router; if it's false, reject the router if it's annotated. If
1040 * <b>prepend_annotations</b> is set, it should contain some annotations:
1041 * append them to the front of the router before parsing it, and keep them
1042 * around when caching the router.
1044 * Only one of allow_annotations and prepend_annotations may be set.
1047 router_parse_entry_from_string(const char *s
, const char *end
,
1048 int cache_copy
, int allow_annotations
,
1049 const char *prepend_annotations
)
1051 routerinfo_t
*router
= NULL
;
1053 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1054 directory_token_t
*tok
;
1056 const char *start_of_annotations
, *cp
;
1057 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1060 tor_assert(!allow_annotations
|| !prepend_annotations
);
1063 end
= s
+ strlen(s
);
1066 /* point 'end' to a point immediately after the final newline. */
1067 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1070 tokens
= smartlist_create();
1071 if (prepend_annotations
) {
1072 if (tokenize_string(prepend_annotations
,NULL
,tokens
,
1073 routerdesc_token_table
,TS_NOCHECK
)) {
1074 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1079 start_of_annotations
= s
;
1080 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1082 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1083 log_warn(LD_DIR
, "No router keyword found.");
1090 if (allow_annotations
&& start_of_annotations
!= s
) {
1091 if (tokenize_string(start_of_annotations
,s
,tokens
,
1092 routerdesc_token_table
,TS_NOCHECK
)) {
1093 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1098 if (router_get_router_hash(s
, digest
) < 0) {
1099 log_warn(LD_DIR
, "Couldn't compute router hash.");
1104 if (allow_annotations
)
1105 flags
|= TS_ANNOTATIONS_OK
;
1106 if (prepend_annotations
)
1107 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1109 if (tokenize_string(s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1110 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1115 if (smartlist_len(tokens
) < 2) {
1116 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1120 tok
= find_first_by_keyword(tokens
, K_ROUTER
);
1121 tor_assert(tok
->n_args
>= 5);
1123 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1124 router
->cache_info
.routerlist_index
= -1;
1125 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1126 router
->cache_info
.signed_descriptor_len
= end
-s
;
1128 size_t len
= router
->cache_info
.signed_descriptor_len
+
1129 router
->cache_info
.annotations_len
;
1131 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1132 if (prepend_annotations
) {
1133 memcpy(cp
, prepend_annotations
, prepend_len
);
1136 memcpy(cp
, start_of_annotations
, end
-start_of_annotations
);
1137 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1138 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1140 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1142 router
->nickname
= tor_strdup(tok
->args
[0]);
1143 if (!is_legal_nickname(router
->nickname
)) {
1144 log_warn(LD_DIR
,"Router nickname is invalid");
1147 router
->address
= tor_strdup(tok
->args
[1]);
1148 if (!tor_inet_aton(router
->address
, &in
)) {
1149 log_warn(LD_DIR
,"Router address is not an IP address.");
1152 router
->addr
= ntohl(in
.s_addr
);
1155 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,&ok
,NULL
);
1157 log_warn(LD_DIR
,"Invalid OR port %s", escaped(tok
->args
[2]));
1161 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,&ok
,NULL
);
1163 log_warn(LD_DIR
,"Invalid dir port %s", escaped(tok
->args
[4]));
1167 tok
= find_first_by_keyword(tokens
, K_BANDWIDTH
);
1168 tor_assert(tok
&& tok
->n_args
>= 3);
1169 router
->bandwidthrate
=
1170 tor_parse_long(tok
->args
[0],10,1,INT_MAX
,&ok
,NULL
);
1173 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1174 escaped(tok
->args
[0]));
1177 router
->bandwidthburst
= tor_parse_long(tok
->args
[1],10,0,INT_MAX
,&ok
,NULL
);
1179 log_warn(LD_DIR
, "Invalid bandwidthburst %s", escaped(tok
->args
[1]));
1182 router
->bandwidthcapacity
=
1183 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,&ok
,NULL
);
1185 log_warn(LD_DIR
, "Invalid bandwidthcapacity %s", escaped(tok
->args
[1]));
1189 if ((tok
= find_first_by_keyword(tokens
, A_PURPOSE
))) {
1190 tor_assert(tok
->n_args
);
1191 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1193 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1195 router
->cache_info
.send_unencrypted
=
1196 (router
->purpose
== ROUTER_PURPOSE_GENERAL
) ? 1 : 0;
1198 if ((tok
= find_first_by_keyword(tokens
, K_UPTIME
))) {
1199 tor_assert(tok
->n_args
>= 1);
1200 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,&ok
,NULL
);
1202 log_warn(LD_DIR
, "Invalid uptime %s", escaped(tok
->args
[0]));
1207 if ((tok
= find_first_by_keyword(tokens
, K_HIBERNATING
))) {
1208 tor_assert(tok
->n_args
>= 1);
1209 router
->is_hibernating
1210 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1213 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1215 tor_assert(tok
->n_args
== 1);
1216 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1219 tok
= find_first_by_keyword(tokens
, K_ONION_KEY
);
1221 router
->onion_pkey
= tok
->key
;
1222 tok
->key
= NULL
; /* Prevent free */
1224 tok
= find_first_by_keyword(tokens
, K_SIGNING_KEY
);
1226 router
->identity_pkey
= tok
->key
;
1227 tok
->key
= NULL
; /* Prevent free */
1228 if (crypto_pk_get_digest(router
->identity_pkey
,
1229 router
->cache_info
.identity_digest
)) {
1230 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1233 if ((tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
))) {
1234 /* If there's a fingerprint line, it must match the identity digest. */
1236 tor_assert(tok
->n_args
== 1);
1237 tor_strstrip(tok
->args
[0], " ");
1238 if (base16_decode(d
, DIGEST_LEN
, tok
->args
[0], strlen(tok
->args
[0]))) {
1239 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1240 escaped(tok
->args
[0]));
1243 if (memcmp(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)!=0) {
1244 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1250 if ((tok
= find_first_by_keyword(tokens
, K_PLATFORM
))) {
1251 router
->platform
= tor_strdup(tok
->args
[0]);
1254 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
))) {
1255 router
->contact_info
= tor_strdup(tok
->args
[0]);
1258 if ((tok
= find_first_by_keyword(tokens
, K_EVENTDNS
))) {
1259 router
->has_old_dnsworkers
= tok
->n_args
&& !strcmp(tok
->args
[0], "0");
1260 } else if (router
->platform
) {
1261 if (! tor_version_as_new_as(router
->platform
, "0.1.2.2-alpha"))
1262 router
->has_old_dnsworkers
= 1;
1265 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1266 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1267 if (router_add_exit_policy(router
,t
)<0) {
1268 log_warn(LD_DIR
,"Error in exit policy");
1271 policy_expand_private(&router
->exit_policy
);
1273 if ((tok
= find_first_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1275 router
->declared_family
= smartlist_create();
1276 for (i
=0;i
<tok
->n_args
;++i
) {
1277 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1278 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1279 escaped(tok
->args
[i
]));
1282 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
1286 if ((tok
= find_first_by_keyword(tokens
, K_CACHES_EXTRA_INFO
)))
1287 router
->caches_extra_info
= 1;
1289 if ((tok
= find_first_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1290 tor_assert(tok
->n_args
>= 1);
1291 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1292 base16_decode(router
->cache_info
.extra_info_digest
,
1293 DIGEST_LEN
, tok
->args
[0], HEX_DIGEST_LEN
);
1295 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1299 if ((tok
= find_first_by_keyword(tokens
, K_HIDDEN_SERVICE_DIR
))) {
1300 router
->wants_to_be_hs_dir
= 1;
1303 tok
= find_first_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1305 note_crypto_pk_op(VERIFY_RTR
);
1306 #ifdef COUNT_DISTINCT_DIGESTS
1307 if (!verified_digests
)
1308 verified_digests
= digestmap_new();
1309 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
1311 if (check_signature_token(digest
, tok
, router
->identity_pkey
, 0,
1312 "router descriptor") < 0)
1315 if (!router
->or_port
) {
1316 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
1320 if (!router
->platform
) {
1321 router
->platform
= tor_strdup("<unknown>");
1327 routerinfo_free(router
);
1331 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1332 smartlist_free(tokens
);
1334 if (exit_policy_tokens
) {
1335 smartlist_free(exit_policy_tokens
);
1340 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1341 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1342 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1343 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1344 * as a map from router identity to routerinfo_t when looking up signing keys.
1347 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
1348 int cache_copy
, struct digest_ri_map_t
*routermap
)
1350 extrainfo_t
*extrainfo
= NULL
;
1352 smartlist_t
*tokens
= NULL
;
1353 directory_token_t
*tok
;
1354 crypto_pk_env_t
*key
= NULL
;
1355 routerinfo_t
*router
= NULL
;
1358 end
= s
+ strlen(s
);
1361 /* point 'end' to a point immediately after the final newline. */
1362 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1365 if (router_get_extrainfo_hash(s
, digest
) < 0) {
1366 log_warn(LD_DIR
, "Couldn't compute router hash.");
1369 tokens
= smartlist_create();
1370 if (tokenize_string(s
,end
,tokens
,extrainfo_token_table
,0)) {
1371 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
1375 if (smartlist_len(tokens
) < 2) {
1376 log_warn(LD_DIR
, "Impossibly short extra-info document.");
1380 tok
= smartlist_get(tokens
,0);
1381 if (tok
->tp
!= K_EXTRA_INFO
) {
1382 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
1386 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
1387 extrainfo
->cache_info
.is_extrainfo
= 1;
1389 extrainfo
->cache_info
.signed_descriptor_body
= tor_strndup(s
, end
-s
);
1390 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
1391 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1393 tor_assert(tok
->n_args
>= 2);
1394 if (!is_legal_nickname(tok
->args
[0])) {
1395 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
1398 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
1399 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
1400 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
1401 tok
->args
[1], HEX_DIGEST_LEN
)) {
1402 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
1403 escaped(tok
->args
[1]));
1407 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1409 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
1410 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
1411 escaped(tok
->args
[0]));
1416 (router
= digestmap_get((digestmap_t
*)routermap
,
1417 extrainfo
->cache_info
.identity_digest
))) {
1418 key
= router
->identity_pkey
;
1421 tok
= find_first_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1423 if (strcmp(tok
->object_type
, "SIGNATURE") ||
1424 tok
->object_size
< 128 || tok
->object_size
> 512) {
1425 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
1430 note_crypto_pk_op(VERIFY_RTR
);
1431 if (check_signature_token(digest
, tok
, key
, 0, "extra-info") < 0)
1435 extrainfo
->cache_info
.send_unencrypted
=
1436 router
->cache_info
.send_unencrypted
;
1438 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
1440 extrainfo
->pending_sig_len
= tok
->object_size
;
1446 extrainfo_free(extrainfo
);
1450 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1451 smartlist_free(tokens
);
1456 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1457 * the first character after the certificate. */
1459 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
1461 authority_cert_t
*cert
= NULL
, *old_cert
;
1462 smartlist_t
*tokens
= NULL
;
1463 char digest
[DIGEST_LEN
];
1464 directory_token_t
*tok
;
1465 char fp_declared
[DIGEST_LEN
];
1470 s
= eat_whitespace(s
);
1471 eos
= strstr(s
, "\n-----END SIGNATURE-----\n");
1473 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
1476 eos
= strchr(eos
+2, '\n');
1481 tokens
= smartlist_create();
1482 if (tokenize_string(s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
1483 log_warn(LD_DIR
, "Error tokenizing key certificate");
1486 if (router_get_hash_impl(s
, digest
, "dir-key-certificate-version",
1487 "\ndir-key-certification", '\n') < 0)
1489 tok
= smartlist_get(tokens
, 0);
1490 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
1492 "Key certificate does not begin with a recognized version (3).");
1496 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
1497 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1499 tok
= find_first_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1500 tor_assert(tok
&& tok
->key
);
1501 cert
->signing_key
= tok
->key
;
1503 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
1506 tok
= find_first_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
1507 tor_assert(tok
&& tok
->key
);
1508 cert
->identity_key
= tok
->key
;
1511 tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
);
1512 tor_assert(tok
&& tok
->n_args
);
1513 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
1514 strlen(tok
->args
[0]))) {
1515 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
1516 escaped(tok
->args
[0]));
1520 if (crypto_pk_get_digest(cert
->identity_key
,
1521 cert
->cache_info
.identity_digest
))
1524 if (memcmp(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
1525 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
1530 tok
= find_first_by_keyword(tokens
, K_DIR_ADDRESS
);
1532 tor_assert(tok
->n_args
);
1533 if (parse_addr_port(LOG_WARN
, tok
->args
[0], NULL
, &cert
->addr
,
1534 &cert
->dir_port
)<0) {
1535 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
1540 tok
= find_first_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
1542 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
1545 tok
= find_first_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
1547 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
1551 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
1552 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
1553 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
1557 /* If we already have this cert, don't bother checking the signature. */
1558 old_cert
= authority_cert_get_by_digests(
1559 cert
->cache_info
.identity_digest
,
1560 cert
->signing_key_digest
);
1563 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1565 if (old_cert
->cache_info
.signed_descriptor_len
== len
&&
1566 old_cert
->cache_info
.signed_descriptor_body
&&
1567 !memcmp(s
, old_cert
->cache_info
.signed_descriptor_body
, len
)) {
1568 log_debug(LD_DIR
, "We already checked the signature on this "
1569 "certificate; no need to do so again.");
1574 if (check_signature_token(digest
, tok
, cert
->identity_key
, 0,
1575 "key certificate")) {
1580 cert
->cache_info
.signed_descriptor_len
= len
;
1581 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1582 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
1583 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
1584 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
1586 if (end_of_string
) {
1587 *end_of_string
= eat_whitespace(eos
);
1589 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1590 smartlist_free(tokens
);
1593 authority_cert_free(cert
);
1594 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1595 smartlist_free(tokens
);
1599 /** Helper: given a string <b>s</b>, return the start of the next router-status
1600 * object (starting with "r " at the start of a line). If none is found,
1601 * return the start of the next directory signature. If none is found, return
1602 * the end of the string. */
1603 static INLINE
const char *
1604 find_start_of_next_routerstatus(const char *s
)
1606 const char *eos
= strstr(s
, "\nr ");
1608 const char *eos2
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
1609 if (eos2
&& eos2
< eos
)
1614 if ((eos
= strstr(s
, "\ndirectory-signature")))
1616 return s
+ strlen(s
);
1620 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1621 * empty smartlist at <b>tokens</b>, parse and return the first router status
1622 * object in the string, and advance *<b>s</b> to just after the end of the
1623 * router status. Return NULL and advance *<b>s</b> on error.
1625 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1626 * routerstatus but use <b>vote_rs</b> instead.
1628 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1629 * consensus, and we should parse it according to the method used to
1630 * make that consensus.
1632 static routerstatus_t
*
1633 routerstatus_parse_entry_from_string(const char **s
, smartlist_t
*tokens
,
1634 networkstatus_t
*vote
,
1635 vote_routerstatus_t
*vote_rs
,
1636 int consensus_method
)
1639 routerstatus_t
*rs
= NULL
;
1640 directory_token_t
*tok
;
1641 char timebuf
[ISO_TIME_LEN
+1];
1644 tor_assert(bool_eq(vote
, vote_rs
));
1646 eos
= find_start_of_next_routerstatus(*s
);
1648 if (tokenize_string(*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
1649 log_warn(LD_DIR
, "Error tokenizing router status");
1652 if (smartlist_len(tokens
) < 1) {
1653 log_warn(LD_DIR
, "Impossibly short router status");
1656 tok
= find_first_by_keyword(tokens
, K_R
);
1658 tor_assert(tok
->n_args
>= 8);
1660 rs
= &vote_rs
->status
;
1662 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
1665 if (!is_legal_nickname(tok
->args
[0])) {
1667 "Invalid nickname %s in router status; skipping.",
1668 escaped(tok
->args
[0]));
1671 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
1673 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
1674 log_warn(LD_DIR
, "Error decoding identity digest %s",
1675 escaped(tok
->args
[1]));
1679 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
1680 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
1681 escaped(tok
->args
[2]));
1685 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
1686 tok
->args
[3], tok
->args
[4]) < 0 ||
1687 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
1688 log_warn(LD_DIR
, "Error parsing time '%s %s'",
1689 tok
->args
[3], tok
->args
[4]);
1693 if (tor_inet_aton(tok
->args
[5], &in
) == 0) {
1694 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
1695 escaped(tok
->args
[5]));
1698 rs
->addr
= ntohl(in
.s_addr
);
1700 rs
->or_port
=(uint16_t) tor_parse_long(tok
->args
[6],10,0,65535,NULL
,NULL
);
1701 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7],10,0,65535,NULL
,NULL
);
1703 tok
= find_first_by_keyword(tokens
, K_S
);
1707 for (i
=0; i
< tok
->n_args
; ++i
) {
1708 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
1710 vote_rs
->flags
|= (1<<p
);
1712 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
1713 escaped(tok
->args
[i
]));
1719 for (i
=0; i
< tok
->n_args
; ++i
) {
1720 if (!strcmp(tok
->args
[i
], "Exit"))
1722 else if (!strcmp(tok
->args
[i
], "Stable"))
1724 else if (!strcmp(tok
->args
[i
], "Fast"))
1726 else if (!strcmp(tok
->args
[i
], "Running"))
1728 else if (!strcmp(tok
->args
[i
], "Named"))
1730 else if (!strcmp(tok
->args
[i
], "Valid"))
1732 else if (!strcmp(tok
->args
[i
], "V2Dir"))
1734 else if (!strcmp(tok
->args
[i
], "Guard"))
1735 rs
->is_possible_guard
= 1;
1736 else if (!strcmp(tok
->args
[i
], "BadExit"))
1737 rs
->is_bad_exit
= 1;
1738 else if (!strcmp(tok
->args
[i
], "BadDirectory"))
1739 rs
->is_bad_directory
= 1;
1740 else if (!strcmp(tok
->args
[i
], "Authority"))
1741 rs
->is_authority
= 1;
1742 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
1743 consensus_method
>= 2) {
1744 /* Unnamed is computed right by consensus method 2 and later. */
1746 } else if (!strcmp(tok
->args
[i
], "HSDir")) {
1751 if ((tok
= find_first_by_keyword(tokens
, K_V
))) {
1752 tor_assert(tok
->n_args
== 1);
1753 rs
->version_known
= 1;
1754 if (strcmpstart(tok
->args
[0], "Tor ")) {
1755 rs
->version_supports_begindir
= 1;
1756 rs
->version_supports_extrainfo_upload
= 1;
1758 rs
->version_supports_begindir
=
1759 tor_version_as_new_as(tok
->args
[0], "0.2.0.1-alpha");
1760 rs
->version_supports_extrainfo_upload
=
1761 tor_version_as_new_as(tok
->args
[0], "0.2.0.0-alpha-dev (r10070)");
1762 rs
->version_supports_v3_dir
=
1763 tor_version_as_new_as(tok
->args
[0], "0.2.0.8-alpha");
1766 vote_rs
->version
= tok
->args
[0];
1767 tok
->args
[0] = NULL
; /* suppress free() */
1771 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
1777 routerstatus_free(rs
);
1780 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1781 smartlist_clear(tokens
);
1787 /** Helper to sort a smartlist of pointers to routerstatus_t */
1789 _compare_routerstatus_entries(const void **_a
, const void **_b
)
1791 const routerstatus_t
*a
= *_a
, *b
= *_b
;
1792 return memcmp(a
->identity_digest
, b
->identity_digest
, DIGEST_LEN
);
1795 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1797 _free_duplicate_routerstatus_entry(void *e
)
1800 "Network-status has two entries for the same router. "
1802 routerstatus_free(e
);
1805 /** Given a v2 network-status object in <b>s</b>, try to
1806 * parse it and return the result. Return NULL on failure. Check the
1807 * signature of the network status, but do not (yet) check the signing key for
1810 networkstatus_v2_t
*
1811 networkstatus_v2_parse_from_string(const char *s
)
1814 smartlist_t
*tokens
= smartlist_create();
1815 smartlist_t
*footer_tokens
= smartlist_create();
1816 networkstatus_v2_t
*ns
= NULL
;
1817 char ns_digest
[DIGEST_LEN
];
1818 char tmp_digest
[DIGEST_LEN
];
1820 directory_token_t
*tok
;
1823 if (router_get_networkstatus_v2_hash(s
, ns_digest
)) {
1824 log_warn(LD_DIR
, "Unable to compute digest of network-status");
1828 eos
= find_start_of_next_routerstatus(s
);
1829 if (tokenize_string(s
, eos
, tokens
, netstatus_token_table
,0)) {
1830 log_warn(LD_DIR
, "Error tokenizing network-status header.");
1833 ns
= tor_malloc_zero(sizeof(networkstatus_v2_t
));
1834 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
1836 tok
= find_first_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
1837 tor_assert(tok
&& tok
->n_args
>= 1);
1838 if (strcmp(tok
->args
[0], "2")) {
1839 log_warn(LD_BUG
, "Got a non-v2 networkstatus. Version was "
1840 "%s", escaped(tok
->args
[0]));
1844 tok
= find_first_by_keyword(tokens
, K_DIR_SOURCE
);
1846 tor_assert(tok
->n_args
>= 3);
1847 ns
->source_address
= tok
->args
[0]; tok
->args
[0] = NULL
;
1848 if (tor_inet_aton(tok
->args
[1], &in
) == 0) {
1849 log_warn(LD_DIR
, "Error parsing network-status source address %s",
1850 escaped(tok
->args
[1]));
1853 ns
->source_addr
= ntohl(in
.s_addr
);
1854 ns
->source_dirport
=
1855 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
1856 if (ns
->source_dirport
== 0) {
1857 log_warn(LD_DIR
, "Directory source without dirport; skipping.");
1861 tok
= find_first_by_keyword(tokens
, K_FINGERPRINT
);
1863 tor_assert(tok
->n_args
);
1864 if (base16_decode(ns
->identity_digest
, DIGEST_LEN
, tok
->args
[0],
1865 strlen(tok
->args
[0]))) {
1866 log_warn(LD_DIR
, "Couldn't decode networkstatus fingerprint %s",
1867 escaped(tok
->args
[0]));
1871 if ((tok
= find_first_by_keyword(tokens
, K_CONTACT
))) {
1872 tor_assert(tok
->n_args
);
1873 ns
->contact
= tok
->args
[0];
1874 tok
->args
[0] = NULL
;
1877 tok
= find_first_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1878 tor_assert(tok
&& tok
->key
);
1879 ns
->signing_key
= tok
->key
;
1882 if (crypto_pk_get_digest(ns
->signing_key
, tmp_digest
)<0) {
1883 log_warn(LD_DIR
, "Couldn't compute signing key digest");
1886 if (memcmp(tmp_digest
, ns
->identity_digest
, DIGEST_LEN
)) {
1888 "network-status fingerprint did not match dir-signing-key");
1892 if ((tok
= find_first_by_keyword(tokens
, K_DIR_OPTIONS
))) {
1893 for (i
=0; i
< tok
->n_args
; ++i
) {
1894 if (!strcmp(tok
->args
[i
], "Names"))
1895 ns
->binds_names
= 1;
1896 if (!strcmp(tok
->args
[i
], "Versions"))
1897 ns
->recommends_versions
= 1;
1898 if (!strcmp(tok
->args
[i
], "BadExits"))
1899 ns
->lists_bad_exits
= 1;
1900 if (!strcmp(tok
->args
[i
], "BadDirectories"))
1901 ns
->lists_bad_directories
= 1;
1905 if (ns
->recommends_versions
) {
1906 if (!(tok
= find_first_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
1907 log_warn(LD_DIR
, "Missing client-versions on versioning directory");
1910 ns
->client_versions
= tok
->args
[0];
1911 tok
->args
[0] = NULL
;
1913 if (!(tok
= find_first_by_keyword(tokens
, K_SERVER_VERSIONS
)) ||
1915 log_warn(LD_DIR
, "Missing server-versions on versioning directory");
1918 ns
->server_versions
= tok
->args
[0];
1919 tok
->args
[0] = NULL
;
1922 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
1924 tor_assert(tok
->n_args
== 1);
1925 if (parse_iso_time(tok
->args
[0], &ns
->published_on
) < 0) {
1929 ns
->entries
= smartlist_create();
1931 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1932 smartlist_clear(tokens
);
1933 while (!strcmpstart(s
, "r ")) {
1935 if ((rs
= routerstatus_parse_entry_from_string(&s
, tokens
, NULL
, NULL
, 0)))
1936 smartlist_add(ns
->entries
, rs
);
1938 smartlist_sort(ns
->entries
, _compare_routerstatus_entries
);
1939 smartlist_uniq(ns
->entries
, _compare_routerstatus_entries
,
1940 _free_duplicate_routerstatus_entry
);
1942 if (tokenize_string(s
, NULL
, footer_tokens
, dir_footer_token_table
,0)) {
1943 log_warn(LD_DIR
, "Error tokenizing network-status footer.");
1946 if (smartlist_len(footer_tokens
) < 1) {
1947 log_warn(LD_DIR
, "Too few items in network-status footer.");
1950 tok
= smartlist_get(footer_tokens
, smartlist_len(footer_tokens
)-1);
1951 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
1953 "Expected network-status footer to end with a signature.");
1957 note_crypto_pk_op(VERIFY_DIR
);
1958 if (check_signature_token(ns_digest
, tok
, ns
->signing_key
, 0,
1959 "network-status") < 0)
1965 networkstatus_v2_free(ns
);
1968 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1969 smartlist_free(tokens
);
1970 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
1971 smartlist_free(footer_tokens
);
1976 /** Parse a v3 networkstatus vote (if <b>is_vote</b> is true) or a v3
1977 * networkstatus consensus (if <b>is_vote</b> is false) from <b>s</b>, and
1978 * return the result. Return NULL on failure. */
1980 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
1983 smartlist_t
*tokens
= smartlist_create();
1984 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
1985 networkstatus_voter_info_t
*voter
= NULL
;
1986 networkstatus_t
*ns
= NULL
;
1987 char ns_digest
[DIGEST_LEN
];
1988 const char *cert
, *end_of_header
, *end_of_footer
;
1989 directory_token_t
*tok
;
1992 int i
, inorder
, n_signatures
= 0;
1994 if (router_get_networkstatus_v3_hash(s
, ns_digest
)) {
1995 log_warn(LD_DIR
, "Unable to compute digest of network-status");
1999 end_of_header
= find_start_of_next_routerstatus(s
);
2000 if (tokenize_string(s
, end_of_header
, tokens
,
2001 is_vote
? networkstatus_token_table
:
2002 networkstatus_consensus_token_table
, 0)) {
2003 log_warn(LD_DIR
, "Error tokenizing network-status vote header.");
2007 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
2008 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
2011 const char *end_of_cert
= NULL
;
2012 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
2015 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
2016 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
2020 tok
= find_first_by_keyword(tokens
, K_VOTE_STATUS
);
2022 tor_assert(tok
->n_args
);
2023 if (!strcmp(tok
->args
[0], "vote")) {
2025 } else if (!strcmp(tok
->args
[0], "consensus")) {
2028 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
2029 escaped(tok
->args
[0]));
2032 if (!bool_eq(ns
->is_vote
, is_vote
)) {
2033 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
2038 tok
= find_first_by_keyword(tokens
, K_PUBLISHED
);
2039 if (parse_iso_time(tok
->args
[0], &ns
->published
))
2042 ns
->supported_methods
= smartlist_create();
2043 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_METHODS
);
2045 for (i
=0; i
< tok
->n_args
; ++i
)
2046 smartlist_add(ns
->supported_methods
, tok
->args
[i
]);
2047 tok
->n_args
= 0; /* Prevent double free. */
2049 smartlist_add(ns
->supported_methods
, tor_strdup("1"));
2052 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_METHOD
);
2054 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
2059 ns
->consensus_method
= 1;
2063 tok
= find_first_by_keyword(tokens
, K_VALID_AFTER
);
2064 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
2067 tok
= find_first_by_keyword(tokens
, K_FRESH_UNTIL
);
2068 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
2071 tok
= find_first_by_keyword(tokens
, K_VALID_UNTIL
);
2072 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
2075 tok
= find_first_by_keyword(tokens
, K_VOTING_DELAY
);
2076 tor_assert(tok
->n_args
>= 2);
2078 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
2082 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
2085 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
> ns
->fresh_until
) {
2086 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
2089 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
*2 > ns
->valid_until
) {
2090 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
2093 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
2094 log_warn(LD_DIR
, "Vote seconds is too short");
2097 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
2098 log_warn(LD_DIR
, "Dist seconds is too short");
2102 if ((tok
= find_first_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
2103 ns
->client_versions
= tok
->args
[0];
2104 tok
->args
[0] = NULL
;
2106 if ((tok
= find_first_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
2107 ns
->server_versions
= tok
->args
[0];
2108 tok
->args
[0] = NULL
;
2111 tok
= find_first_by_keyword(tokens
, K_KNOWN_FLAGS
);
2112 ns
->known_flags
= smartlist_create();
2114 for (i
= 0; i
< tok
->n_args
; ++i
) {
2115 smartlist_add(ns
->known_flags
, tok
->args
[i
]);
2116 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
2117 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2121 tok
->n_args
= 0; /* suppress free of args members, but not of args itself. */
2123 log_warn(LD_DIR
, "known-flags not in order");
2127 ns
->voters
= smartlist_create();
2129 SMARTLIST_FOREACH(tokens
, directory_token_t
*, _tok
,
2132 if (tok
->tp
== K_DIR_SOURCE
) {
2133 tor_assert(tok
->n_args
>= 6);
2136 smartlist_add(ns
->voters
, voter
);
2137 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2139 memcpy(voter
->vote_digest
, ns_digest
, DIGEST_LEN
);
2141 voter
->nickname
= tor_strdup(tok
->args
[0]);
2142 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2143 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
2144 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2145 log_warn(LD_DIR
, "Error decoding identity digest %s in "
2146 "network-status vote.", escaped(tok
->args
[1]));
2149 if (is_vote
&& memcmp(ns
->cert
->cache_info
.identity_digest
,
2150 voter
->identity_digest
, DIGEST_LEN
)) {
2151 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
2154 voter
->address
= tor_strdup(tok
->args
[2]);
2155 if (!tor_inet_aton(tok
->args
[3], &in
)) {
2156 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
2157 escaped(tok
->args
[3]));
2160 voter
->addr
= ntohl(in
.s_addr
);
2161 voter
->dir_port
= (uint64_t)
2162 (int) tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
2165 voter
->or_port
= (uint64_t)
2166 (int) tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
2169 } else if (tok
->tp
== K_CONTACT
) {
2170 if (!voter
|| voter
->contact
) {
2171 log_warn(LD_DIR
, "contact element is out of place.");
2174 voter
->contact
= tor_strdup(tok
->args
[0]);
2175 } else if (tok
->tp
== K_VOTE_DIGEST
) {
2176 tor_assert(!is_vote
);
2177 tor_assert(tok
->n_args
>= 1);
2178 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
2179 log_warn(LD_DIR
, "vote-digest element is out of place.");
2182 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2183 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
2184 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2185 log_warn(LD_DIR
, "Error decoding vote digest %s in "
2186 "network-status consensus.", escaped(tok
->args
[1]));
2192 smartlist_add(ns
->voters
, voter
);
2195 if (smartlist_len(ns
->voters
) == 0) {
2196 log_warn(LD_DIR
, "Missing dir-source elements in a vote networkstatus.");
2198 } else if (is_vote
&& smartlist_len(ns
->voters
) != 1) {
2199 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
2203 /* Parse routerstatus lines. */
2204 rs_tokens
= smartlist_create();
2206 ns
->routerstatus_list
= smartlist_create();
2208 while (!strcmpstart(s
, "r ")) {
2210 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
2211 if (routerstatus_parse_entry_from_string(&s
, tokens
, ns
, rs
, 0))
2212 smartlist_add(ns
->routerstatus_list
, rs
);
2214 tor_free(rs
->version
);
2219 if ((rs
= routerstatus_parse_entry_from_string(&s
, tokens
, NULL
, NULL
,
2220 ns
->consensus_method
)))
2221 smartlist_add(ns
->routerstatus_list
, rs
);
2224 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
2225 routerstatus_t
*rs1
, *rs2
;
2227 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
2228 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
2229 rs1
= &a
->status
; rs2
= &b
->status
;
2231 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
2232 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
2234 if (memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
) >= 0) {
2235 log_warn(LD_DIR
, "Vote networkstatus entries not sorted by identity "
2241 /* Parse footer; check signature. */
2242 footer_tokens
= smartlist_create();
2243 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
2246 end_of_footer
= s
+ strlen(s
);
2247 if (tokenize_string(s
, end_of_footer
, footer_tokens
,
2248 networkstatus_vote_footer_token_table
, 0)) {
2249 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
2253 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, _tok
,
2255 char declared_identity
[DIGEST_LEN
];
2256 networkstatus_voter_info_t
*v
;
2258 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2260 tor_assert(tok
->n_args
>= 2);
2262 if (!tok
->object_type
||
2263 strcmp(tok
->object_type
, "SIGNATURE") ||
2264 tok
->object_size
< 128 || tok
->object_size
> 512) {
2265 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2269 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2270 base16_decode(declared_identity
, sizeof(declared_identity
),
2271 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2272 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2273 "network-status vote.", escaped(tok
->args
[0]));
2276 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
2277 log_warn(LD_DIR
, "ID on signature on network-status vote does not match "
2278 "any declared directory source.");
2281 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2282 base16_decode(v
->signing_key_digest
, sizeof(v
->signing_key_digest
),
2283 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2284 log_warn(LD_DIR
, "Error decoding declared digest %s in "
2285 "network-status vote.", escaped(tok
->args
[1]));
2290 if (memcmp(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
2292 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
2293 "network-status vote.");
2299 if (check_signature_token(ns_digest
, tok
, ns
->cert
->signing_key
, 0,
2300 "network-status vote"))
2302 v
->good_signature
= 1;
2304 v
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2305 v
->signature_len
= tok
->object_size
;
2310 if (! n_signatures
) {
2311 log_warn(LD_DIR
, "No signatures on networkstatus vote.");
2316 *eos_out
= end_of_footer
;
2321 networkstatus_vote_free(ns
);
2325 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2326 smartlist_free(tokens
);
2329 tor_free(voter
->nickname
);
2330 tor_free(voter
->address
);
2331 tor_free(voter
->contact
);
2332 tor_free(voter
->signature
);
2336 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_free(t
));
2337 smartlist_free(rs_tokens
);
2339 if (footer_tokens
) {
2340 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
2341 smartlist_free(footer_tokens
);
2347 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2348 * <b>eos</b> and return the result. Return -1 on failure. */
2349 ns_detached_signatures_t
*
2350 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
2352 /* XXXX there is too much duplicate code here. */
2353 directory_token_t
*tok
;
2355 smartlist_t
*tokens
= smartlist_create();
2356 ns_detached_signatures_t
*sigs
=
2357 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
2360 eos
= s
+ strlen(s
);
2362 if (tokenize_string(s
, eos
, tokens
,
2363 networkstatus_detached_signature_token_table
, 0)) {
2364 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
2368 tok
= find_first_by_keyword(tokens
, K_CONSENSUS_DIGEST
);
2369 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
) {
2370 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
2371 "networkstatus signatures");
2374 if (base16_decode(sigs
->networkstatus_digest
, DIGEST_LEN
,
2375 tok
->args
[0], strlen(tok
->args
[0])) < 0) {
2376 log_warn(LD_DIR
, "Bad encoding on on consensus-digest in detached "
2377 "networkstatus signatures");
2381 tok
= find_first_by_keyword(tokens
, K_VALID_AFTER
);
2382 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
2383 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
2387 tok
= find_first_by_keyword(tokens
, K_FRESH_UNTIL
);
2388 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
2389 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
2393 tok
= find_first_by_keyword(tokens
, K_VALID_UNTIL
);
2394 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
2395 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
2399 sigs
->signatures
= smartlist_create();
2400 SMARTLIST_FOREACH(tokens
, directory_token_t
*, _tok
,
2402 char id_digest
[DIGEST_LEN
];
2403 char sk_digest
[DIGEST_LEN
];
2404 networkstatus_voter_info_t
*voter
;
2407 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2409 tor_assert(tok
->n_args
>= 2);
2411 if (!tok
->object_type
||
2412 strcmp(tok
->object_type
, "SIGNATURE") ||
2413 tok
->object_size
< 128 || tok
->object_size
> 512) {
2414 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2418 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2419 base16_decode(id_digest
, sizeof(id_digest
),
2420 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2421 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2422 "network-status vote.", escaped(tok
->args
[0]));
2425 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2426 base16_decode(sk_digest
, sizeof(sk_digest
),
2427 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2428 log_warn(LD_DIR
, "Error decoding declared digest %s in "
2429 "network-status vote.", escaped(tok
->args
[1]));
2433 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2434 memcpy(voter
->identity_digest
, id_digest
, DIGEST_LEN
);
2435 memcpy(voter
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
2436 voter
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2437 voter
->signature_len
= tok
->object_size
;
2439 smartlist_add(sigs
->signatures
, voter
);
2444 ns_detached_signatures_free(sigs
);
2447 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2448 smartlist_free(tokens
);
2452 /** Parse the addr policy in the string <b>s</b> and return it. If
2453 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2454 * ADDR_POLICY_REJECT) for items that specify no action.
2457 router_parse_addr_policy_item_from_string(const char *s
, int assume_action
)
2459 directory_token_t
*tok
= NULL
;
2460 const char *cp
, *eos
;
2461 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2462 * But note that there can be an arbitrary amount of space between the
2463 * accept and the address:mask/port element. */
2464 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
2467 s
= eat_whitespace(s
);
2468 if ((*s
== '*' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
2469 if (tor_snprintf(line
, sizeof(line
), "%s %s",
2470 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
2471 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
2476 } else { /* assume an already well-formed address policy line */
2480 eos
= cp
+ strlen(cp
);
2481 tok
= get_next_token(&cp
, eos
, routerdesc_token_table
);
2482 if (tok
->tp
== _ERR
) {
2483 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
2486 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_REJECT
) {
2487 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
2491 /* Now that we've gotten an addr policy, add it to the router. */
2492 r
= router_parse_addr_policy(tok
);
2501 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2502 * <b>router</b>. Return 0 on success, -1 on failure. */
2504 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
2506 addr_policy_t
*newe
;
2507 newe
= router_parse_addr_policy(tok
);
2510 if (! router
->exit_policy
)
2511 router
->exit_policy
= smartlist_create();
2513 smartlist_add(router
->exit_policy
, newe
);
2518 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2519 * a new exit_policy_t corresponding to the token. */
2520 static addr_policy_t
*
2521 router_parse_addr_policy(directory_token_t
*tok
)
2526 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_ACCEPT
);
2528 if (tok
->n_args
!= 1)
2532 if (!strcmpstart(arg
,"private"))
2533 return router_parse_addr_policy_private(tok
);
2535 memset(&newe
, 0, sizeof(newe
));
2537 newe
.policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
2538 : ADDR_POLICY_ACCEPT
;
2540 if (parse_addr_and_port_range(arg
, &newe
.addr
, &newe
.maskbits
,
2541 &newe
.prt_min
, &newe
.prt_max
))
2542 goto policy_read_failed
;
2544 return addr_policy_get_canonical_entry(&newe
);
2547 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
2551 /** Parse an exit policy line of the format "accept/reject private:...".
2552 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2553 * router descriptors until earlier versions are obsolete.
2555 static addr_policy_t
*
2556 router_parse_addr_policy_private(directory_token_t
*tok
)
2559 uint16_t port_min
, port_max
;
2560 addr_policy_t result
;
2563 if (strcmpstart(arg
, "private"))
2566 arg
+= strlen("private");
2567 arg
= (char*) eat_whitespace(arg
);
2568 if (!arg
|| *arg
!= ':')
2571 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
2574 memset(&result
, 0, sizeof(result
));
2575 result
.policy_type
= (tok
->tp
== K_REJECT
) ? ADDR_POLICY_REJECT
2576 : ADDR_POLICY_ACCEPT
;
2577 result
.is_private
= 1;
2578 result
.prt_min
= port_min
;
2579 result
.prt_max
= port_max
;
2581 return addr_policy_get_canonical_entry(&result
);
2584 /** Log and exit if <b>t</b> is malformed */
2586 assert_addr_policy_ok(smartlist_t
*lst
)
2589 SMARTLIST_FOREACH(lst
, addr_policy_t
*, t
, {
2590 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
2591 t
->policy_type
== ADDR_POLICY_ACCEPT
);
2592 tor_assert(t
->prt_min
<= t
->prt_max
);
2597 * Low-level tokenizer for router descriptors and directories.
2600 /** Free all resources allocated for <b>tok</b> */
2602 token_free(directory_token_t
*tok
)
2607 for (i
= 0; i
< tok
->n_args
; ++i
) {
2608 tor_free(tok
->args
[i
]);
2610 tor_free(tok
->args
);
2612 tor_free(tok
->object_type
);
2613 tor_free(tok
->object_body
);
2614 tor_free(tok
->error
);
2616 crypto_free_pk_env(tok
->key
);
2620 #define RET_ERR(msg) \
2622 if (tok) token_free(tok); \
2623 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2625 tok->error = tor_strdup(msg); \
2626 goto done_tokenizing; \
2629 static INLINE directory_token_t
*
2630 token_check_object(const char *kwd
,
2631 directory_token_t
*tok
, obj_syntax o_syn
)
2636 if (tok
->object_body
) {
2637 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected object for %s", kwd
);
2641 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected public key for %s", kwd
);
2646 if (!tok
->object_body
) {
2647 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing object for %s", kwd
);
2652 if (tok
->key
&& crypto_pk_keysize(tok
->key
) != PK_BYTES
) {
2653 tor_snprintf(ebuf
, sizeof(ebuf
), "Wrong size on key for %s: %d bits",
2654 kwd
, (int)crypto_pk_keysize(tok
->key
));
2660 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing public key for %s", kwd
);
2671 /** Helper function: read the next token from *s, advance *s to the end of the
2672 * token, and return the parsed token. Parse *<b>s</b> according to the list
2673 * of tokens in <b>table</b>.
2675 static directory_token_t
*
2676 get_next_token(const char **s
, const char *eos
, token_rule_t
*table
)
2678 const char *next
, *eol
, *obstart
;
2679 int i
, j
, allocated
, obname_len
;
2680 directory_token_t
*tok
;
2681 obj_syntax o_syn
= NO_OBJ
;
2683 const char *kwd
= "";
2685 #define RET_ERR(msg) \
2687 if (tok) token_free(tok); \
2688 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2690 tok->error = tor_strdup(msg); \
2691 goto done_tokenizing; \
2694 tok
= tor_malloc_zero(sizeof(directory_token_t
));
2697 /* Set *s to first token, eol to end-of-line, next to after first token */
2698 *s
= eat_whitespace_eos(*s
, eos
); /* eat multi-line whitespace */
2699 eol
= memchr(*s
, '\n', eos
-*s
);
2702 next
= find_whitespace_eos(*s
, eol
);
2704 if (!strcmp_len(*s
, "opt", next
-*s
)) {
2705 /* Skip past an "opt" at the start of the line. */
2706 *s
= eat_whitespace_eos_no_nl(next
, eol
);
2707 next
= find_whitespace_eos(*s
, eol
);
2708 } else if (*s
== eos
) { /* If no "opt", and end-of-line, line is invalid */
2709 RET_ERR("Unexpected EOF");
2712 /* Search the table for the appropriate entry. (I tried a binary search
2713 * instead, but it wasn't any faster.) */
2714 for (i
= 0; table
[i
].t
; ++i
) {
2715 if (!strcmp_len(*s
, table
[i
].t
, next
-*s
)) {
2716 /* We've found the keyword. */
2718 tok
->tp
= table
[i
].v
;
2719 o_syn
= table
[i
].os
;
2720 *s
= eat_whitespace_eos_no_nl(next
, eol
);
2721 next
= find_whitespace_eos(*s
, eol
);
2722 /* We go ahead whether there are arguments or not, so that tok->args is
2723 * always set if we want arguments. */
2724 if (table
[i
].concat_args
) {
2725 /* The keyword takes the line as a single argument */
2726 tok
->args
= tor_malloc(sizeof(char*));
2727 tok
->args
[0] = tor_strndup(*s
,eol
-*s
); /* Grab everything on line */
2730 /* This keyword takes multiple arguments. */
2733 tok
->args
= tor_malloc(sizeof(char*)*allocated
);
2734 while (*s
< eol
) { /* While not at eol, store the next token */
2735 if (j
== allocated
) {
2737 tok
->args
= tor_realloc(tok
->args
,sizeof(char*)*allocated
);
2739 tok
->args
[j
++] = tor_strndup(*s
, next
-*s
);
2740 *s
= eat_whitespace_eos_no_nl(next
, eol
); /* eat intra-line ws */
2741 next
= find_whitespace_eos(*s
, eol
); /* find end of token at *s */
2745 if (tok
->n_args
< table
[i
].min_args
) {
2746 tor_snprintf(ebuf
, sizeof(ebuf
), "Too few arguments to %s", kwd
);
2748 } else if (tok
->n_args
> table
[i
].max_args
) {
2749 tor_snprintf(ebuf
, sizeof(ebuf
), "Too many arguments to %s", kwd
);
2756 if (tok
->tp
== _ERR
) {
2757 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
2759 tok
->tp
= _A_UNKNOWN
;
2762 tok
->args
= tor_malloc(sizeof(char*));
2763 tok
->args
[0] = tor_strndup(*s
, eol
-*s
);
2768 /* Check whether there's an object present */
2769 *s
= eat_whitespace_eos(eol
, eos
); /* Scan from end of first line */
2770 eol
= memchr(*s
, '\n', eos
-*s
);
2771 if (!eol
|| eol
-*s
<11 || strcmpstart(*s
, "-----BEGIN ")) /* No object. */
2774 obstart
= *s
; /* Set obstart to start of object spec */
2775 if (*s
+11 >= eol
-5 || memchr(*s
+11,'\0',eol
-*s
-16) || /* no short lines, */
2776 strcmp_len(eol
-5, "-----", 5)) { /* nuls or invalid endings */
2777 RET_ERR("Malformed object: bad begin line");
2779 tok
->object_type
= tor_strndup(*s
+11, eol
-*s
-16);
2780 obname_len
= eol
-*s
-16; /* store objname length here to avoid a strlen() */
2781 *s
= eol
+1; /* Set *s to possible start of object data (could be eos) */
2783 /* Go to the end of the object */
2784 next
= tor_memstr(*s
, eos
-*s
, "-----END ");
2786 RET_ERR("Malformed object: missing object end line");
2788 eol
= memchr(next
, '\n', eos
-next
);
2789 if (!eol
) /* end-of-line marker, or eos if there's no '\n' */
2791 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
2792 if (eol
-next
!= 9+obname_len
+5 ||
2793 strcmp_len(next
+9, tok
->object_type
, obname_len
) ||
2794 strcmp_len(eol
-5, "-----", 5)) {
2795 snprintf(ebuf
, sizeof(ebuf
), "Malformed object: mismatched end tag %s",
2797 ebuf
[sizeof(ebuf
)-1] = '\0';
2800 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) { /* If it's a key... */
2801 tok
->key
= crypto_new_pk_env();
2802 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, eol
-obstart
))
2803 RET_ERR("Couldn't parse public key.");
2804 } else { /* If it's something else, try to base64-decode it */
2806 tok
->object_body
= tor_malloc(next
-*s
); /* really, this is too much RAM. */
2807 r
= base64_decode(tok
->object_body
, next
-*s
, *s
, next
-*s
);
2809 RET_ERR("Malformed object: bad base64-encoded data");
2810 tok
->object_size
= r
;
2815 tok
= token_check_object(kwd
, tok
, o_syn
);
2823 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
2824 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
2825 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
2829 tokenize_string(const char *start
, const char *end
, smartlist_t
*out
,
2830 token_rule_t
*table
, int flags
)
2833 directory_token_t
*tok
= NULL
;
2836 int first_nonannotation
;
2837 int prev_len
= smartlist_len(out
);
2841 end
= start
+strlen(start
);
2842 for (i
= 0; i
< _NIL
; ++i
)
2844 while (*s
< end
&& (!tok
|| tok
->tp
!= _EOF
)) {
2845 tok
= get_next_token(s
, end
, table
);
2846 if (tok
->tp
== _ERR
) {
2847 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
2852 smartlist_add(out
, tok
);
2853 *s
= eat_whitespace_eos(*s
, end
);
2856 if (flags
& TS_NOCHECK
)
2859 if ((flags
& TS_ANNOTATIONS_OK
)) {
2860 first_nonannotation
= -1;
2861 for (i
= 0; i
< smartlist_len(out
); ++i
) {
2862 tok
= smartlist_get(out
, i
);
2863 if (tok
->tp
< MIN_ANNOTATION
|| tok
->tp
> MAX_ANNOTATION
) {
2864 first_nonannotation
= i
;
2868 if (first_nonannotation
< 0) {
2869 log_warn(LD_DIR
, "parse error: item contains only annotations");
2872 for (i
=first_nonannotation
; i
< smartlist_len(out
); ++i
) {
2873 tok
= smartlist_get(out
, i
);
2874 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
2875 log_warn(LD_DIR
, "parse error: Annotations mixed with keywords");
2879 if ((flags
& TS_NO_NEW_ANNOTATIONS
)) {
2880 if (first_nonannotation
!= prev_len
) {
2881 log_warn(LD_DIR
, "parse error: Unexpectd annotations.");
2886 for (i
=0; i
< smartlist_len(out
); ++i
) {
2887 tok
= smartlist_get(out
, i
);
2888 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
2889 log_warn(LD_DIR
, "parse error: no annotations allowed.");
2893 first_nonannotation
= 0;
2895 for (i
= 0; table
[i
].t
; ++i
) {
2896 if (counts
[table
[i
].v
] < table
[i
].min_cnt
) {
2897 log_warn(LD_DIR
, "Parse error: missing %s element.", table
[i
].t
);
2900 if (counts
[table
[i
].v
] > table
[i
].max_cnt
) {
2901 log_warn(LD_DIR
, "Parse error: too many %s elements.", table
[i
].t
);
2904 if (table
[i
].pos
& AT_START
) {
2905 if (smartlist_len(out
) < 1 ||
2906 (tok
= smartlist_get(out
, first_nonannotation
))->tp
!= table
[i
].v
) {
2907 log_warn(LD_DIR
, "Parse error: first item is not %s.", table
[i
].t
);
2911 if (table
[i
].pos
& AT_END
) {
2912 if (smartlist_len(out
) < 1 ||
2913 (tok
= smartlist_get(out
, smartlist_len(out
)-1))->tp
!= table
[i
].v
) {
2914 log_warn(LD_DIR
, "Parse error: last item is not %s.", table
[i
].t
);
2922 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
2923 * NULL if no such keyword is found.
2925 static directory_token_t
*
2926 find_first_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
2928 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
2932 /** Return a newly allocated smartlist of all accept or reject tokens in
2935 static smartlist_t
*
2936 find_all_exitpolicy(smartlist_t
*s
)
2938 smartlist_t
*out
= smartlist_create();
2939 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
2940 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_REJECT
)
2941 smartlist_add(out
,t
));
2945 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
2946 * occurrence of <b>start_str</b> through the first instance of c after the
2947 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
2948 * <b>digest</b>; return 0 on success.
2950 * If no such substring exists, return -1.
2953 router_get_hash_impl(const char *s
, char *digest
,
2954 const char *start_str
,
2955 const char *end_str
, char end_c
)
2958 start
= strstr(s
, start_str
);
2960 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
2963 if (start
!= s
&& *(start
-1) != '\n') {
2965 "first occurrence of \"%s\" is not at the start of a line",
2969 end
= strstr(start
+strlen(start_str
), end_str
);
2971 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
2974 end
= strchr(end
+strlen(end_str
), end_c
);
2976 log_warn(LD_DIR
,"couldn't find EOL");
2981 if (crypto_digest(digest
, start
, end
-start
)) {
2982 log_warn(LD_BUG
,"couldn't compute digest");
2989 /** Parse the Tor version of the platform string <b>platform</b>,
2990 * and compare it to the version in <b>cutoff</b>. Return 1 if
2991 * the router is at least as new as the cutoff, else return 0.
2994 tor_version_as_new_as(const char *platform
, const char *cutoff
)
2996 tor_version_t cutoff_version
, router_version
;
2997 char *s
, *s2
, *start
;
3000 tor_assert(platform
);
3002 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
3003 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
3006 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
3009 start
= (char *)eat_whitespace(platform
+3);
3010 if (!*start
) return 0;
3011 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
3012 s2
= (char*)eat_whitespace(s
);
3013 if (!strcmpstart(s2
, "(r"))
3014 s
= (char*)find_whitespace(s2
);
3016 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
3018 strlcpy(tmp
, start
, s
-start
+1);
3020 if (tor_version_parse(tmp
, &router_version
)<0) {
3021 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
3022 return 1; /* be safe and say yes */
3025 /* Here's why we don't need to do any special handling for svn revisions:
3026 * - If neither has an svn revision, we're fine.
3027 * - If the router doesn't have an svn revision, we can't assume that it
3028 * is "at least" any svn revision, so we need to return 0.
3029 * - If the target version doesn't have an svn revision, any svn revision
3030 * (or none at all) is good enough, so return 1.
3031 * - If both target and router have an svn revision, we compare them.
3034 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
3037 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3038 * Return 0 on success, -1 on failure. */
3040 tor_version_parse(const char *s
, tor_version_t
*out
)
3043 const char *cp
=NULL
;
3045 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3050 memset(out
, 0, sizeof(tor_version_t
));
3052 if (!strcasecmpstart(s
, "Tor "))
3056 out
->major
= strtol(s
,&eos
,10);
3057 if (!eos
|| eos
==s
|| *eos
!= '.') return -1;
3061 out
->minor
= strtol(cp
,&eos
,10);
3062 if (!eos
|| eos
==cp
|| *eos
!= '.') return -1;
3066 out
->micro
= strtol(cp
,&eos
,10);
3067 if (!eos
|| eos
==cp
) return -1;
3069 out
->status
= VER_RELEASE
;
3070 out
->patchlevel
= 0;
3077 out
->status
= VER_RELEASE
;
3079 } else if (0==strncmp(cp
, "pre", 3)) {
3080 out
->status
= VER_PRE
;
3082 } else if (0==strncmp(cp
, "rc", 2)) {
3083 out
->status
= VER_RC
;
3089 /* Get patchlevel */
3090 out
->patchlevel
= strtol(cp
,&eos
,10);
3091 if (!eos
|| eos
==cp
) return -1;
3094 /* Get status tag. */
3095 if (*cp
== '-' || *cp
== '.')
3097 eos
= (char*) find_whitespace(cp
);
3098 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
3099 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
3101 memcpy(out
->status_tag
, cp
, eos
-cp
);
3102 out
->status_tag
[eos
-cp
] = 0;
3104 cp
= eat_whitespace(eos
);
3106 if (!strcmpstart(cp
, "(r")) {
3108 out
->svn_revision
= strtol(cp
,&eos
,10);
3114 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3117 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
3122 if ((i
= a
->major
- b
->major
))
3124 else if ((i
= a
->minor
- b
->minor
))
3126 else if ((i
= a
->micro
- b
->micro
))
3128 else if ((i
= a
->status
- b
->status
))
3130 else if ((i
= a
->patchlevel
- b
->patchlevel
))
3132 else if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
3135 return a
->svn_revision
- b
->svn_revision
;
3138 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3141 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
3145 return ((a
->major
== b
->major
) &&
3146 (a
->minor
== b
->minor
) &&
3147 (a
->micro
== b
->micro
));
3150 /** Helper: Given pointers to two strings describing tor versions, return -1
3151 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
3152 * Used to sort a list of versions. */
3154 _compare_tor_version_str_ptr(const void **_a
, const void **_b
)
3156 const char *a
= *_a
, *b
= *_b
;
3158 tor_version_t va
, vb
;
3159 ca
= tor_version_parse(a
, &va
);
3160 cb
= tor_version_parse(b
, &vb
);
3161 /* If they both parse, compare them. */
3163 return tor_version_compare(&va
,&vb
);
3164 /* If one parses, it comes first. */
3169 /* If neither parses, compare strings. Also, the directory server admin
3170 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3174 /** Sort a list of string-representations of versions in ascending order. */
3176 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
3178 smartlist_sort(versions
, _compare_tor_version_str_ptr
);
3180 if (remove_duplicates
)
3181 smartlist_uniq(versions
, _compare_tor_version_str_ptr
, _tor_free
);
3184 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3185 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3186 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3187 * encrypted introduction points to the newly allocated
3188 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3189 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3190 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3191 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3192 * and -1 for failure.
3195 rend_parse_v2_service_descriptor(rend_service_descriptor_t
**parsed_out
,
3197 char **intro_points_encrypted_out
,
3198 size_t *intro_points_encrypted_size_out
,
3199 size_t *encoded_size_out
,
3200 const char **next_out
, const char *desc
)
3202 rend_service_descriptor_t
*result
=
3203 tor_malloc_zero(sizeof(rend_service_descriptor_t
));
3204 char desc_hash
[DIGEST_LEN
];
3206 smartlist_t
*tokens
= smartlist_create();
3207 directory_token_t
*tok
;
3208 char secret_id_part
[DIGEST_LEN
];
3209 int i
, version
, num_ok
=1;
3210 smartlist_t
*versions
;
3211 char public_key_hash
[DIGEST_LEN
];
3212 char test_desc_id
[DIGEST_LEN
];
3214 /* Check if desc starts correctly. */
3215 if (strncmp(desc
, "rendezvous-service-descriptor ",
3216 strlen("rendezvous-service-descriptor "))) {
3217 log_info(LD_REND
, "Descriptor does not start correctly.");
3220 /* Compute descriptor hash for later validation. */
3221 if (router_get_hash_impl(desc
, desc_hash
,
3222 "rendezvous-service-descriptor ",
3223 "\nsignature", '\n') < 0) {
3224 log_warn(LD_REND
, "Couldn't compute descriptor hash.");
3227 /* Determine end of string. */
3228 eos
= strstr(desc
, "\nrendezvous-service-descriptor ");
3230 eos
= desc
+ strlen(desc
);
3233 /* Tokenize descriptor. */
3234 if (tokenize_string(desc
, eos
, tokens
, desc_token_table
, 0)) {
3235 log_warn(LD_REND
, "Error tokenizing descriptor.");
3238 /* Set next to next descriptor, if available. */
3240 /* Set length of encoded descriptor. */
3241 *encoded_size_out
= eos
- desc
;
3242 /* Check min allowed length of token list. */
3243 if (smartlist_len(tokens
) < 7) {
3244 log_warn(LD_REND
, "Impossibly short descriptor.");
3247 /* Parse base32-encoded descriptor ID. */
3248 tok
= find_first_by_keyword(tokens
, R_RENDEZVOUS_SERVICE_DESCRIPTOR
);
3250 tor_assert(tok
== smartlist_get(tokens
, 0));
3251 tor_assert(tok
->n_args
== 1);
3252 if (strlen(tok
->args
[0]) != REND_DESC_ID_V2_LEN_BASE32
||
3253 strspn(tok
->args
[0], BASE32_CHARS
) != REND_DESC_ID_V2_LEN_BASE32
) {
3254 log_warn(LD_REND
, "Invalid descriptor ID: '%s'", tok
->args
[0]);
3257 if (base32_decode(desc_id_out
, DIGEST_LEN
,
3258 tok
->args
[0], REND_DESC_ID_V2_LEN_BASE32
) < 0) {
3259 log_warn(LD_REND
, "Descriptor ID contains illegal characters: %s",
3263 /* Parse descriptor version. */
3264 tok
= find_first_by_keyword(tokens
, R_VERSION
);
3266 tor_assert(tok
->n_args
== 1);
3268 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &num_ok
, NULL
);
3269 if (result
->version
!= 2 || !num_ok
) {
3270 /* If it's <2, it shouldn't be under this format. If the number
3271 * is greater than 2, we bumped it because we broke backward
3272 * compatibility. See how version numbers in our other formats
3274 log_warn(LD_REND
, "Unrecognized descriptor version: %s",
3275 escaped(tok
->args
[0]));
3278 /* Parse public key. */
3279 tok
= find_first_by_keyword(tokens
, R_PERMANENT_KEY
);
3281 result
->pk
= tok
->key
;
3282 tok
->key
= NULL
; /* Prevent free */
3283 /* Parse secret ID part. */
3284 tok
= find_first_by_keyword(tokens
, R_SECRET_ID_PART
);
3286 tor_assert(tok
->n_args
== 1);
3287 if (strlen(tok
->args
[0]) != REND_SECRET_ID_PART_LEN_BASE32
||
3288 strspn(tok
->args
[0], BASE32_CHARS
) != REND_SECRET_ID_PART_LEN_BASE32
) {
3289 log_warn(LD_REND
, "Invalid secret ID part: '%s'", tok
->args
[0]);
3292 if (base32_decode(secret_id_part
, DIGEST_LEN
, tok
->args
[0], 32) < 0) {
3293 log_warn(LD_REND
, "Secret ID part contains illegal characters: %s",
3297 /* Parse publication time -- up-to-date check is done when storing the
3299 tok
= find_first_by_keyword(tokens
, R_PUBLICATION_TIME
);
3301 tor_assert(tok
->n_args
== 1);
3302 if (parse_iso_time(tok
->args
[0], &result
->timestamp
) < 0) {
3303 log_warn(LD_REND
, "Invalid publication time: '%s'", tok
->args
[0]);
3306 /* Parse protocol versions. */
3307 tok
= find_first_by_keyword(tokens
, R_PROTOCOL_VERSIONS
);
3309 tor_assert(tok
->n_args
== 1);
3310 versions
= smartlist_create();
3311 smartlist_split_string(versions
, tok
->args
[0], ",",
3312 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
3313 for (i
= 0; i
< smartlist_len(versions
); i
++) {
3314 version
= (int) tor_parse_long(smartlist_get(versions
, i
),
3315 10, 0, INT_MAX
, &num_ok
, NULL
);
3316 if (!num_ok
) /* It's a string; let's ignore it. */
3318 result
->protocols
|= 1 << version
;
3320 SMARTLIST_FOREACH(versions
, char *, cp
, tor_free(cp
));
3321 smartlist_free(versions
);
3322 /* Parse encrypted introduction points. Don't verify. */
3323 tok
= find_first_by_keyword(tokens
, R_INTRODUCTION_POINTS
);
3325 if (strcmp(tok
->object_type
, "MESSAGE")) {
3326 log_warn(LD_DIR
, "Bad object type: introduction points should be of "
3330 *intro_points_encrypted_out
= tok
->object_body
;
3331 *intro_points_encrypted_size_out
= tok
->object_size
;
3332 tok
->object_body
= NULL
; /* Prevent free. */
3334 *intro_points_encrypted_out
= NULL
;
3335 *intro_points_encrypted_size_out
= 0;
3337 /* Parse and verify signature. */
3338 tok
= find_first_by_keyword(tokens
, R_SIGNATURE
);
3340 note_crypto_pk_op(VERIFY_RTR
);
3341 if (check_signature_token(desc_hash
, tok
, result
->pk
, 0,
3342 "v2 rendezvous service descriptor") < 0)
3344 /* Verify that descriptor ID belongs to public key and secret ID part. */
3345 crypto_pk_get_digest(result
->pk
, public_key_hash
);
3346 rend_get_descriptor_id_bytes(test_desc_id
, public_key_hash
,
3348 if (memcmp(desc_id_out
, test_desc_id
, DIGEST_LEN
)) {
3349 log_warn(LD_REND
, "Parsed descriptor ID does not match "
3350 "computed descriptor ID.");
3356 rend_service_descriptor_free(result
);
3360 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3361 smartlist_free(tokens
);
3363 *parsed_out
= result
;
3369 /** Decrypt and decode the introduction points in
3370 * <b>intro_points_encrypted</b> of length
3371 * <b>intro_points_encrypted_size</b> using <b>descriptor_cookie</b>
3372 * (which may also be <b>NULL</b> if no decryption, but only parsing is
3373 * required), parse the introduction points, and write the result to
3374 * <b>parsed</b>; return the number of successfully parsed introduction
3375 * points or -1 in case of a failure.
3378 rend_decrypt_introduction_points(rend_service_descriptor_t
*parsed
,
3379 const char *descriptor_cookie
,
3380 const char *intro_points_encrypted
,
3381 size_t intro_points_encrypted_size
)
3383 char *ipos_decrypted
= NULL
;
3384 const char **current_ipo
;
3385 smartlist_t
*tokens
;
3386 directory_token_t
*tok
;
3387 rend_intro_point_t
*intro
;
3388 extend_info_t
*info
;
3390 int result
, num_ok
=1;
3392 /** Function may only be invoked once. */
3393 tor_assert(!parsed
->intro_nodes
);
3394 tor_assert(intro_points_encrypted
);
3395 tor_assert(intro_points_encrypted_size
> 0);
3396 /* Decrypt introduction points, if required. */
3397 if (descriptor_cookie
) {
3398 crypto_cipher_env_t
*cipher
;
3400 ipos_decrypted
= tor_malloc_zero(intro_points_encrypted_size
- 16);
3401 cipher
= crypto_create_init_cipher(descriptor_cookie
, 0);
3402 unenclen
= crypto_cipher_decrypt_with_iv(cipher
, ipos_decrypted
,
3403 intro_points_encrypted_size
- 16,
3404 intro_points_encrypted
,
3405 intro_points_encrypted_size
);
3406 crypto_free_cipher_env(cipher
);
3408 tor_free(ipos_decrypted
);
3411 intro_points_encrypted
= ipos_decrypted
;
3412 intro_points_encrypted_size
= unenclen
;
3414 /* Consider one intro point after the other. */
3415 current_ipo
= &intro_points_encrypted
;
3416 tokens
= smartlist_create();
3417 parsed
->intro_nodes
= smartlist_create();
3418 while (!strcmpstart(*current_ipo
, "introduction-point ")) {
3419 /* Determine end of string. */
3420 const char *eos
= strstr(*current_ipo
, "\nintroduction-point ");
3422 eos
= *current_ipo
+strlen(*current_ipo
);
3425 /* Free tokens and clear token list. */
3426 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3427 smartlist_clear(tokens
);
3428 /* Tokenize string. */
3429 if (tokenize_string(*current_ipo
, eos
, tokens
, ipo_token_table
, 0)) {
3430 log_warn(LD_REND
, "Error tokenizing introduction point.");
3433 /* Advance to next introduction point, if available. */
3435 /* Check minimum allowed length of introduction point. */
3436 if (smartlist_len(tokens
) < 5) {
3437 log_warn(LD_REND
, "Impossibly short introduction point.");
3440 /* Allocate new intro point and extend info. */
3441 intro
= tor_malloc_zero(sizeof(rend_intro_point_t
));
3442 info
= intro
->extend_info
= tor_malloc_zero(sizeof(extend_info_t
));
3443 /* Parse identifier. */
3444 tok
= find_first_by_keyword(tokens
, R_IPO_IDENTIFIER
);
3446 if (base32_decode(info
->identity_digest
, DIGEST_LEN
,
3447 tok
->args
[0], REND_INTRO_POINT_ID_LEN_BASE32
) < 0) {
3448 log_warn(LD_REND
, "Identity digest contains illegal characters: %s",
3450 rend_intro_point_free(intro
);
3453 /* Write identifier to nickname. */
3454 info
->nickname
[0] = '$';
3455 base16_encode(info
->nickname
+ 1, sizeof(info
->nickname
) - 1,
3456 info
->identity_digest
, DIGEST_LEN
);
3457 /* Parse IP address. */
3458 tok
= find_first_by_keyword(tokens
, R_IPO_IP_ADDRESS
);
3459 if (tor_inet_aton(tok
->args
[0], &ip
) == 0) {
3460 log_warn(LD_REND
, "Could not parse IP address.");
3461 rend_intro_point_free(intro
);
3464 info
->addr
= ntohl(ip
.s_addr
);
3465 /* Parse onion port. */
3466 tok
= find_first_by_keyword(tokens
, R_IPO_ONION_PORT
);
3467 info
->port
= (uint16_t) tor_parse_long(tok
->args
[0],10,1,65535,
3469 if (!info
->port
|| !num_ok
) {
3470 log_warn(LD_REND
, "Introduction point onion port %s is invalid",
3471 escaped(tok
->args
[0]));
3472 rend_intro_point_free(intro
);
3475 /* Parse onion key. */
3476 tok
= find_first_by_keyword(tokens
, R_IPO_ONION_KEY
);
3477 info
->onion_key
= tok
->key
;
3478 tok
->key
= NULL
; /* Prevent free */
3479 /* Parse service key. */
3480 tok
= find_first_by_keyword(tokens
, R_IPO_SERVICE_KEY
);
3481 intro
->intro_key
= tok
->key
;
3482 tok
->key
= NULL
; /* Prevent free */
3483 /* Add extend info to list of introduction points. */
3484 smartlist_add(parsed
->intro_nodes
, intro
);
3486 result
= smartlist_len(parsed
->intro_nodes
);
3493 /* Free tokens and clear token list. */
3494 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3495 smartlist_free(tokens
);