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-2011, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to parse and validate router descriptors and directories.
15 /****************************************************************************/
17 /** Enumeration of possible token types. The ones starting with K_ correspond
18 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
19 * is an end-of-file marker, and _NIL is used to encode not-a-token.
24 K_DIRECTORY_SIGNATURE
,
25 K_RECOMMENDED_SOFTWARE
,
48 K_NETWORK_STATUS_VERSION
,
63 K_ALLOW_SINGLE_HOP_EXITS
,
65 K_DIR_KEY_CERTIFICATE_VERSION
,
69 K_DIR_KEY_CERTIFICATION
,
90 R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
96 R_INTRODUCTION_POINTS
,
114 #define MIN_ANNOTATION A_PURPOSE
115 #define MAX_ANNOTATION _A_UNKNOWN
117 /** Structure to hold a single directory token.
119 * We parse a directory by breaking it into "tokens", each consisting
120 * of a keyword, a line full of arguments, and a binary object. The
121 * arguments and object are both optional, depending on the keyword
124 * This structure is only allocated in memareas; do not allocate it on
125 * the heap, or token_free() won't work.
127 typedef struct directory_token_t
{
128 directory_keyword tp
; /**< Type of the token. */
129 int n_args
:30; /**< Number of elements in args */
130 char **args
; /**< Array of arguments from keyword line. */
132 char *object_type
; /**< -----BEGIN [object_type]-----*/
133 size_t object_size
; /**< Bytes in object_body */
134 char *object_body
; /**< Contents of object, base64-decoded. */
136 crypto_pk_env_t
*key
; /**< For public keys only. Heap-allocated. */
138 char *error
; /**< For _ERR tokens only. */
141 /* ********************************************************************** */
143 /** We use a table of rules to decide how to parse each token type. */
145 /** Rules for whether the keyword needs an object. */
147 NO_OBJ
, /**< No object, ever. */
148 NEED_OBJ
, /**< Object is required. */
149 NEED_SKEY_1024
,/**< Object is required, and must be a 1024 bit private key */
150 NEED_KEY_1024
, /**< Object is required, and must be a 1024 bit public key */
151 NEED_KEY
, /**< Object is required, and must be a public key. */
152 OBJ_OK
, /**< Object is optional. */
158 /** Determines the parsing rules for a single token type. */
159 typedef struct token_rule_t
{
160 /** The string value of the keyword identifying the type of item. */
162 /** The corresponding directory_keyword enum. */
164 /** Minimum number of arguments for this item */
166 /** Maximum number of arguments for this item */
168 /** If true, we concatenate all arguments for this item into a single
171 /** Requirements on object syntax for this item. */
173 /** Lowest number of times this item may appear in a document. */
175 /** Highest number of times this item may appear in a document. */
177 /** One or more of AT_START/AT_END to limit where the item may appear in a
180 /** True iff this token is an annotation. */
185 * Helper macros to define token tables. 's' is a string, 't' is a
186 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
191 /** Appears to indicate the end of a table. */
192 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
193 /** An item with no restrictions: used for obsolete document types */
194 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
195 /** An item with no restrictions on multiplicity or location. */
196 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
197 /** An item that must appear exactly once */
198 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
199 /** An item that must appear exactly once, at the start of the document */
200 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
201 /** An item that must appear exactly once, at the end of the document */
202 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
203 /** An item that must appear one or more times */
204 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
205 /** An item that must appear no more than once */
206 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
207 /** An annotation that must appear no more than once */
208 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
210 /* Argument multiplicity: any number of arguments. */
211 #define ARGS 0,INT_MAX,0
212 /* Argument multiplicity: no arguments. */
213 #define NO_ARGS 0,0,0
214 /* Argument multiplicity: concatenate all arguments. */
215 #define CONCAT_ARGS 1,1,1
216 /* Argument multiplicity: at least <b>n</b> arguments. */
217 #define GE(n) n,INT_MAX,0
218 /* Argument multiplicity: exactly <b>n</b> arguments. */
221 /** List of tokens allowable in router descriptors */
222 static token_rule_t routerdesc_token_table
[] = {
223 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
224 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
225 T0N("reject6", K_REJECT6
, ARGS
, NO_OBJ
),
226 T0N("accept6", K_ACCEPT6
, ARGS
, NO_OBJ
),
227 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
228 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
229 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
230 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
231 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
232 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
233 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
234 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
235 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
236 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
237 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
238 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
239 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
240 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR
, NO_ARGS
, NO_OBJ
),
241 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS
, NO_ARGS
, NO_OBJ
),
243 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
244 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
245 T01("eventdns", K_EVENTDNS
, ARGS
, NO_OBJ
),
247 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
248 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
249 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
254 /** List of tokens allowable in extra-info documents. */
255 static token_rule_t extrainfo_token_table
[] = {
256 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
257 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
258 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
259 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
260 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
261 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
266 /** List of tokens allowable in the body part of v2 and v3 networkstatus
268 static token_rule_t rtrstatus_token_table
[] = {
269 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
270 T1( "r", K_R
, GE(8), NO_OBJ
),
271 T1( "s", K_S
, ARGS
, NO_OBJ
),
272 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
273 T01("w", K_W
, ARGS
, NO_OBJ
),
274 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
278 /** List of tokens allowable in the header part of v2 networkstatus documents.
280 static token_rule_t netstatus_token_table
[] = {
281 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
282 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
283 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
284 T1( "dir-signing-key", K_DIR_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
285 T1( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
286 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
288 T1( "dir-source", K_DIR_SOURCE
, GE(3), NO_OBJ
),
289 T01("dir-options", K_DIR_OPTIONS
, ARGS
, NO_OBJ
),
290 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
291 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
296 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
298 static token_rule_t dir_footer_token_table
[] = {
299 T1("directory-signature", K_DIRECTORY_SIGNATURE
, EQ(1), NEED_OBJ
),
303 /** List of tokens allowable in v1 directory headers/footers. */
304 static token_rule_t dir_token_table
[] = {
305 /* don't enforce counts; this is obsolete. */
306 T( "network-status", K_NETWORK_STATUS
, NO_ARGS
, NO_OBJ
),
307 T( "directory-signature", K_DIRECTORY_SIGNATURE
, ARGS
, NEED_OBJ
),
308 T( "recommended-software",K_RECOMMENDED_SOFTWARE
,CONCAT_ARGS
, NO_OBJ
),
309 T( "signed-directory", K_SIGNED_DIRECTORY
, NO_ARGS
, NO_OBJ
),
311 T( "running-routers", K_RUNNING_ROUTERS
, ARGS
, NO_OBJ
),
312 T( "router-status", K_ROUTER_STATUS
, ARGS
, NO_OBJ
),
313 T( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
314 T( "opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
315 T( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
316 T( "dir-signing-key", K_DIR_SIGNING_KEY
, ARGS
, OBJ_OK
),
317 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
322 /** List of tokens common to V3 authority certificates and V3 consensuses. */
323 #define CERTIFICATE_MEMBERS \
324 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
326 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
327 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
328 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
329 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
330 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
331 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
332 NO_ARGS, NEED_OBJ), \
333 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
335 /** List of tokens allowable in V3 authority certificates. */
336 static token_rule_t dir_key_certificate_table
[] = {
338 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
342 /** List of tokens allowable in rendezvous service descriptors */
343 static token_rule_t desc_token_table
[] = {
344 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
346 T1("version", R_VERSION
, EQ(1), NO_OBJ
),
347 T1("permanent-key", R_PERMANENT_KEY
, NO_ARGS
, NEED_KEY_1024
),
348 T1("secret-id-part", R_SECRET_ID_PART
, EQ(1), NO_OBJ
),
349 T1("publication-time", R_PUBLICATION_TIME
, CONCAT_ARGS
, NO_OBJ
),
350 T1("protocol-versions", R_PROTOCOL_VERSIONS
, EQ(1), NO_OBJ
),
351 T01("introduction-points", R_INTRODUCTION_POINTS
, NO_ARGS
, NEED_OBJ
),
352 T1_END("signature", R_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
356 /** List of tokens allowed in the (encrypted) list of introduction points of
357 * rendezvous service descriptors */
358 static token_rule_t ipo_token_table
[] = {
359 T1_START("introduction-point", R_IPO_IDENTIFIER
, EQ(1), NO_OBJ
),
360 T1("ip-address", R_IPO_IP_ADDRESS
, EQ(1), NO_OBJ
),
361 T1("onion-port", R_IPO_ONION_PORT
, EQ(1), NO_OBJ
),
362 T1("onion-key", R_IPO_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
363 T1("service-key", R_IPO_SERVICE_KEY
, NO_ARGS
, NEED_KEY_1024
),
367 /** List of tokens allowed in the (possibly encrypted) list of introduction
368 * points of rendezvous service descriptors */
369 static token_rule_t client_keys_token_table
[] = {
370 T1_START("client-name", C_CLIENT_NAME
, CONCAT_ARGS
, NO_OBJ
),
371 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE
, EQ(1), NO_OBJ
),
372 T01("client-key", C_CLIENT_KEY
, NO_ARGS
, NEED_SKEY_1024
),
376 /** List of tokens allowed in V3 networkstatus votes. */
377 static token_rule_t networkstatus_token_table
[] = {
378 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
380 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
381 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
382 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
383 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
384 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
385 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
386 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
387 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
388 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
392 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
393 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
394 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
395 T01("legacy-dir-key", K_LEGACY_DIR_KEY
, GE(1), NO_OBJ
),
396 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
397 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
398 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
399 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
404 /** List of tokens allowed in V3 networkstatus consensuses. */
405 static token_rule_t networkstatus_consensus_token_table
[] = {
406 T1("network-status-version", K_NETWORK_STATUS_VERSION
,
408 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
409 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
410 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
411 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
412 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
414 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
416 T1N("dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
417 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
418 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
420 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
422 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
423 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
424 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
425 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
430 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
432 static token_rule_t networkstatus_vote_footer_token_table
[] = {
433 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
437 /** List of tokens allowable in detached networkstatus signature documents. */
438 static token_rule_t networkstatus_detached_signature_token_table
[] = {
439 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
440 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
441 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
442 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
443 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
449 /* static function prototypes */
450 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
451 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
);
452 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
454 static int router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
455 const char *start_str
, const char *end_str
,
458 static void token_free(directory_token_t
*tok
);
459 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
460 static directory_token_t
*_find_by_keyword(smartlist_t
*s
,
461 directory_keyword keyword
,
462 const char *keyword_str
);
463 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
464 static directory_token_t
*find_opt_by_keyword(smartlist_t
*s
,
465 directory_keyword keyword
);
467 #define TS_ANNOTATIONS_OK 1
469 #define TS_NO_NEW_ANNOTATIONS 4
470 static int tokenize_string(memarea_t
*area
,
471 const char *start
, const char *end
,
475 static directory_token_t
*get_next_token(memarea_t
*area
,
478 token_rule_t
*table
);
479 #define CST_CHECK_AUTHORITY (1<<0)
480 #define CST_NO_CHECK_OBJTYPE (1<<1)
481 static int check_signature_token(const char *digest
,
482 directory_token_t
*tok
,
483 crypto_pk_env_t
*pkey
,
485 const char *doctype
);
486 static crypto_pk_env_t
*find_dir_signing_key(const char *str
, const char *eos
);
487 static int tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
);
489 #undef DEBUG_AREA_ALLOC
491 #ifdef DEBUG_AREA_ALLOC
492 #define DUMP_AREA(a,name) STMT_BEGIN \
493 size_t alloc=0, used=0; \
494 memarea_get_stats((a),&alloc,&used); \
495 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
496 name, (unsigned long)alloc, (unsigned long)used); \
499 #define DUMP_AREA(a,name) STMT_NIL
502 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
503 * <b>s</b>. Return 0 on success, -1 on failure.
506 router_get_dir_hash(const char *s
, char *digest
)
508 return router_get_hash_impl(s
, strlen(s
), digest
,
509 "signed-directory","\ndirectory-signature",'\n');
512 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
513 * <b>s</b>. Return 0 on success, -1 on failure.
516 router_get_router_hash(const char *s
, size_t s_len
, char *digest
)
518 return router_get_hash_impl(s
, s_len
, digest
,
519 "router ","\nrouter-signature", '\n');
522 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
523 * string in <b>s</b>. Return 0 on success, -1 on failure.
526 router_get_runningrouters_hash(const char *s
, char *digest
)
528 return router_get_hash_impl(s
, strlen(s
), digest
,
529 "network-status","\ndirectory-signature", '\n');
532 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
533 * string in <b>s</b>. Return 0 on success, -1 on failure. */
535 router_get_networkstatus_v2_hash(const char *s
, char *digest
)
537 return router_get_hash_impl(s
, strlen(s
), digest
,
538 "network-status-version","\ndirectory-signature",
542 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
543 * string in <b>s</b>. Return 0 on success, -1 on failure. */
545 router_get_networkstatus_v3_hash(const char *s
, char *digest
)
547 return router_get_hash_impl(s
, strlen(s
), digest
,
548 "network-status-version",
549 "\ndirectory-signature",
553 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
554 * string in <b>s</b>. Return 0 on success, -1 on failure. */
556 router_get_extrainfo_hash(const char *s
, char *digest
)
558 return router_get_hash_impl(s
, strlen(s
), digest
, "extra-info",
559 "\nrouter-signature",'\n');
562 /** Helper: used to generate signatures for routers, directories and
563 * network-status objects. Given a digest in <b>digest</b> and a secret
564 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
565 * surround it with -----BEGIN/END----- pairs, and write it to the
566 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
570 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
571 crypto_pk_env_t
*private_key
)
576 keysize
= crypto_pk_keysize(private_key
);
577 signature
= tor_malloc(keysize
);
578 if (crypto_pk_private_sign(private_key
, signature
, keysize
,
579 digest
, DIGEST_LEN
) < 0) {
581 log_warn(LD_BUG
,"Couldn't sign digest.");
584 if (strlcat(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
588 if (base64_encode(buf
+i
, buf_len
-i
, signature
, 128) < 0) {
589 log_warn(LD_BUG
,"couldn't base64-encode signature");
593 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
600 log_warn(LD_BUG
,"tried to exceed string length.");
606 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
607 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
608 * entries. Else, return VS_OLD if every member of
609 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
610 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
611 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
612 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
613 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
616 * (versionlist is a comma-separated list of version strings,
617 * optionally prefixed with "Tor". Versions that can't be parsed are
621 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
623 tor_version_t mine
, other
;
624 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
625 found_any_in_series
= 0, r
, same
;
626 version_status_t ret
= VS_UNRECOMMENDED
;
627 smartlist_t
*version_sl
;
629 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
630 myversion
, versionlist
);
632 if (tor_version_parse(myversion
, &mine
)) {
633 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
636 version_sl
= smartlist_create();
637 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
639 if (!strlen(versionlist
)) { /* no authorities cared or agreed */
644 SMARTLIST_FOREACH(version_sl
, const char *, cp
, {
645 if (!strcmpstart(cp
, "Tor "))
648 if (tor_version_parse(cp
, &other
)) {
649 /* Couldn't parse other; it can't be a match. */
651 same
= tor_version_same_series(&mine
, &other
);
653 found_any_in_series
= 1;
654 r
= tor_version_compare(&mine
, &other
);
656 ret
= VS_RECOMMENDED
;
661 found_newer_in_series
= 1;
668 /* We didn't find the listed version. Is it new or old? */
669 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
670 ret
= VS_NEW_IN_SERIES
;
671 } else if (found_newer
&& !found_older
) {
673 } else if (found_older
&& !found_newer
) {
676 ret
= VS_UNRECOMMENDED
;
680 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
681 smartlist_free(version_sl
);
685 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
686 * Otherwise, return -1. If we're a directory cache, cache it.
689 router_parse_directory(const char *str
)
691 directory_token_t
*tok
;
692 char digest
[DIGEST_LEN
];
695 const char *end
, *cp
;
696 smartlist_t
*tokens
= NULL
;
697 crypto_pk_env_t
*declared_key
= NULL
;
698 memarea_t
*area
= memarea_new();
700 /* XXXX This could be simplified a lot, but it will all go away
701 * once pre-0.1.1.8 is obsolete, and for now it's better not to
704 if (router_get_dir_hash(str
, digest
)) {
705 log_warn(LD_DIR
, "Unable to compute digest of directory");
708 log_debug(LD_DIR
,"Received directory hashes to %s",hex_str(digest
,4));
710 /* Check signature first, before we try to tokenize. */
712 while (cp
&& (end
= strstr(cp
+1, "\ndirectory-signature")))
714 if (cp
== str
|| !cp
) {
715 log_warn(LD_DIR
, "No signature found on directory."); goto err
;
718 tokens
= smartlist_create();
719 if (tokenize_string(area
,cp
,strchr(cp
,'\0'),tokens
,dir_token_table
,0)) {
720 log_warn(LD_DIR
, "Error tokenizing directory signature"); goto err
;
722 if (smartlist_len(tokens
) != 1) {
723 log_warn(LD_DIR
, "Unexpected number of tokens in signature"); goto err
;
725 tok
=smartlist_get(tokens
,0);
726 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
727 log_warn(LD_DIR
,"Expected a single directory signature"); goto err
;
729 declared_key
= find_dir_signing_key(str
, str
+strlen(str
));
730 note_crypto_pk_op(VERIFY_DIR
);
731 if (check_signature_token(digest
, tok
, declared_key
,
732 CST_CHECK_AUTHORITY
, "directory")<0)
735 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
736 smartlist_clear(tokens
);
739 /* Now try to parse the first part of the directory. */
740 if ((end
= strstr(str
,"\nrouter "))) {
742 } else if ((end
= strstr(str
, "\ndirectory-signature"))) {
745 end
= str
+ strlen(str
);
748 if (tokenize_string(area
,str
,end
,tokens
,dir_token_table
,0)) {
749 log_warn(LD_DIR
, "Error tokenizing directory"); goto err
;
752 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
753 tor_assert(tok
->n_args
== 1);
755 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
759 /* Now that we know the signature is okay, and we have a
760 * publication time, cache the directory. */
761 if (directory_caches_v1_dir_info(get_options()) &&
762 !authdir_mode_v1(get_options()))
763 dirserv_set_cached_directory(str
, published_on
, 0);
770 if (declared_key
) crypto_free_pk_env(declared_key
);
772 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
773 smartlist_free(tokens
);
776 DUMP_AREA(area
, "v1 directory");
777 memarea_drop_all(area
);
782 /** Read a signed router status statement from <b>str</b>. If it's
783 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
786 router_parse_runningrouters(const char *str
)
788 char digest
[DIGEST_LEN
];
789 directory_token_t
*tok
;
792 crypto_pk_env_t
*declared_key
= NULL
;
793 smartlist_t
*tokens
= NULL
;
794 const char *eos
= str
+ strlen(str
);
795 memarea_t
*area
= NULL
;
797 if (router_get_runningrouters_hash(str
, digest
)) {
798 log_warn(LD_DIR
, "Unable to compute digest of running-routers");
801 area
= memarea_new();
802 tokens
= smartlist_create();
803 if (tokenize_string(area
,str
,eos
,tokens
,dir_token_table
,0)) {
804 log_warn(LD_DIR
, "Error tokenizing running-routers"); goto err
;
806 tok
= smartlist_get(tokens
,0);
807 if (tok
->tp
!= K_NETWORK_STATUS
) {
808 log_warn(LD_DIR
, "Network-status starts with wrong token");
812 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
813 tor_assert(tok
->n_args
== 1);
814 if (parse_iso_time(tok
->args
[0], &published_on
) < 0) {
817 if (!(tok
= find_opt_by_keyword(tokens
, K_DIRECTORY_SIGNATURE
))) {
818 log_warn(LD_DIR
, "Missing signature on running-routers");
821 declared_key
= find_dir_signing_key(str
, eos
);
822 note_crypto_pk_op(VERIFY_DIR
);
823 if (check_signature_token(digest
, tok
, declared_key
,
824 CST_CHECK_AUTHORITY
, "running-routers")
828 /* Now that we know the signature is okay, and we have a
829 * publication time, cache the list. */
830 if (get_options()->DirPort
&& !authdir_mode_v1(get_options()))
831 dirserv_set_cached_directory(str
, published_on
, 1);
835 if (declared_key
) crypto_free_pk_env(declared_key
);
837 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
838 smartlist_free(tokens
);
841 DUMP_AREA(area
, "v1 running-routers");
842 memarea_drop_all(area
);
847 /** Given a directory or running-routers string in <b>str</b>, try to
848 * find the its dir-signing-key token (if any). If this token is
849 * present, extract and return the key. Return NULL on failure. */
850 static crypto_pk_env_t
*
851 find_dir_signing_key(const char *str
, const char *eos
)
854 directory_token_t
*tok
;
855 crypto_pk_env_t
*key
= NULL
;
856 memarea_t
*area
= NULL
;
860 /* Is there a dir-signing-key in the directory? */
861 cp
= tor_memstr(str
, eos
-str
, "\nopt dir-signing-key");
863 cp
= tor_memstr(str
, eos
-str
, "\ndir-signing-key");
866 ++cp
; /* Now cp points to the start of the token. */
868 area
= memarea_new();
869 tok
= get_next_token(area
, &cp
, eos
, dir_token_table
);
871 log_warn(LD_DIR
, "Unparseable dir-signing-key token");
874 if (tok
->tp
!= K_DIR_SIGNING_KEY
) {
875 log_warn(LD_DIR
, "Dir-signing-key token did not parse as expected");
881 tok
->key
= NULL
; /* steal reference. */
883 log_warn(LD_DIR
, "Dir-signing-key token contained no key");
887 if (tok
) token_free(tok
);
889 DUMP_AREA(area
, "dir-signing-key token");
890 memarea_drop_all(area
);
895 /** Return true iff <b>key</b> is allowed to sign directories.
898 dir_signing_key_is_trusted(crypto_pk_env_t
*key
)
900 char digest
[DIGEST_LEN
];
902 if (crypto_pk_get_digest(key
, digest
) < 0) {
903 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
906 if (!router_digest_is_trusted_dir(digest
)) {
907 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
913 /** Check whether the object body of the token in <b>tok</b> has a good
914 * signature for <b>digest</b> using key <b>pkey</b>. If
915 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
916 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
917 * the object type of the signature object. Use <b>doctype</b> as the type of
918 * the document when generating log messages. Return 0 on success, negative
922 check_signature_token(const char *digest
,
923 directory_token_t
*tok
,
924 crypto_pk_env_t
*pkey
,
930 const int check_authority
= (flags
& CST_CHECK_AUTHORITY
);
931 const int check_objtype
= ! (flags
& CST_NO_CHECK_OBJTYPE
);
938 if (check_authority
&& !dir_signing_key_is_trusted(pkey
)) {
939 log_warn(LD_DIR
, "Key on %s did not come from an authority; rejecting",
945 if (strcmp(tok
->object_type
, "SIGNATURE")) {
946 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
951 keysize
= crypto_pk_keysize(pkey
);
952 signed_digest
= tor_malloc(keysize
);
953 if (crypto_pk_public_checksig(pkey
, signed_digest
, keysize
,
954 tok
->object_body
, tok
->object_size
)
956 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
957 tor_free(signed_digest
);
960 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
961 // hex_str(signed_digest,4));
962 if (memcmp(digest
, signed_digest
, DIGEST_LEN
)) {
963 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
964 tor_free(signed_digest
);
967 tor_free(signed_digest
);
971 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
972 * or to the first of the annotations proceeding the next router or
973 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
974 * we found an extrainfo, or false if found a router. Do not scan beyond
975 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
977 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
979 int *is_extrainfo_out
)
981 const char *annotations
= NULL
;
982 const char *s
= *s_ptr
;
984 s
= eat_whitespace_eos(s
, eos
);
986 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
987 /* We're at the start of a line. */
988 tor_assert(*s
!= '\n');
990 if (*s
== '@' && !annotations
) {
992 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
993 *s_ptr
= annotations
? annotations
: s
;
994 *is_extrainfo_out
= 0;
996 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
997 *s_ptr
= annotations
? annotations
: s
;
998 *is_extrainfo_out
= 1;
1002 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
1004 s
= eat_whitespace_eos(s
, eos
);
1009 /** Given a string *<b>s</b> containing a concatenated sequence of router
1010 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1011 * them and stores the result in <b>dest</b>. All routers are marked running
1012 * and valid. Advances *s to a point immediately following the last router
1013 * entry. Ignore any trailing router entries that are not complete.
1015 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1016 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1017 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1019 * Returns 0 on success and -1 on failure.
1022 router_parse_list_from_string(const char **s
, const char *eos
,
1024 saved_location_t saved_location
,
1026 int allow_annotations
,
1027 const char *prepend_annotations
)
1029 routerinfo_t
*router
;
1030 extrainfo_t
*extrainfo
;
1031 signed_descriptor_t
*signed_desc
;
1033 const char *end
, *start
;
1042 eos
= *s
+ strlen(*s
);
1044 tor_assert(eos
>= *s
);
1047 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
1050 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
1052 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
1054 end
+= strlen("\n-----END SIGNATURE-----\n");
1061 if (have_extrainfo
&& want_extrainfo
) {
1062 routerlist_t
*rl
= router_get_routerlist();
1063 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
1064 saved_location
!= SAVED_IN_CACHE
,
1067 signed_desc
= &extrainfo
->cache_info
;
1070 } else if (!have_extrainfo
&& !want_extrainfo
) {
1071 router
= router_parse_entry_from_string(*s
, end
,
1072 saved_location
!= SAVED_IN_CACHE
,
1074 prepend_annotations
);
1076 log_debug(LD_DIR
, "Read router '%s', purpose '%s'",
1077 router
->nickname
, router_purpose_to_string(router
->purpose
));
1078 signed_desc
= &router
->cache_info
;
1086 if (saved_location
!= SAVED_NOWHERE
) {
1087 signed_desc
->saved_location
= saved_location
;
1088 signed_desc
->saved_offset
= *s
- start
;
1091 smartlist_add(dest
, elt
);
1097 /* For debugging: define to count every descriptor digest we've seen so we
1098 * know if we need to try harder to avoid duplicate verifies. */
1099 #undef COUNT_DISTINCT_DIGESTS
1101 #ifdef COUNT_DISTINCT_DIGESTS
1102 static digestmap_t
*verified_digests
= NULL
;
1105 /** Log the total count of the number of distinct router digests we've ever
1106 * verified. When compared to the number of times we've verified routerdesc
1107 * signatures <i>in toto</i>, this will tell us if we're doing too much
1108 * multiple-verification. */
1110 dump_distinct_digest_count(int severity
)
1112 #ifdef COUNT_DISTINCT_DIGESTS
1113 if (!verified_digests
)
1114 verified_digests
= digestmap_new();
1115 log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
1116 digestmap_size(verified_digests
));
1118 (void)severity
; /* suppress "unused parameter" warning */
1122 /** Helper function: reads a single router entry from *<b>s</b> ...
1123 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1124 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1125 * s through end into the signed_descriptor_body of the resulting
1128 * If <b>end</b> is NULL, <b>s</b> must be properly NULL-terminated.
1130 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1131 * before the router; if it's false, reject the router if it's annotated. If
1132 * <b>prepend_annotations</b> is set, it should contain some annotations:
1133 * append them to the front of the router before parsing it, and keep them
1134 * around when caching the router.
1136 * Only one of allow_annotations and prepend_annotations may be set.
1139 router_parse_entry_from_string(const char *s
, const char *end
,
1140 int cache_copy
, int allow_annotations
,
1141 const char *prepend_annotations
)
1143 routerinfo_t
*router
= NULL
;
1145 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1146 directory_token_t
*tok
;
1148 const char *start_of_annotations
, *cp
;
1149 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1151 memarea_t
*area
= NULL
;
1153 tor_assert(!allow_annotations
|| !prepend_annotations
);
1156 end
= s
+ strlen(s
);
1159 /* point 'end' to a point immediately after the final newline. */
1160 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1163 area
= memarea_new();
1164 tokens
= smartlist_create();
1165 if (prepend_annotations
) {
1166 if (tokenize_string(area
,prepend_annotations
,NULL
,tokens
,
1167 routerdesc_token_table
,TS_NOCHECK
)) {
1168 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1173 start_of_annotations
= s
;
1174 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1176 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1177 log_warn(LD_DIR
, "No router keyword found.");
1184 if (start_of_annotations
!= s
) { /* We have annotations */
1185 if (allow_annotations
) {
1186 if (tokenize_string(area
,start_of_annotations
,s
,tokens
,
1187 routerdesc_token_table
,TS_NOCHECK
)) {
1188 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1192 log_warn(LD_DIR
, "Found unexpected annotations on router descriptor not "
1193 "loaded from disk. Dropping it.");
1198 if (router_get_router_hash(s
, end
- s
, digest
) < 0) {
1199 log_warn(LD_DIR
, "Couldn't compute router hash.");
1204 if (allow_annotations
)
1205 flags
|= TS_ANNOTATIONS_OK
;
1206 if (prepend_annotations
)
1207 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1209 if (tokenize_string(area
,s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1210 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1215 if (smartlist_len(tokens
) < 2) {
1216 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1220 tok
= find_by_keyword(tokens
, K_ROUTER
);
1221 tor_assert(tok
->n_args
>= 5);
1223 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1224 router
->country
= -1;
1225 router
->cache_info
.routerlist_index
= -1;
1226 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1227 router
->cache_info
.signed_descriptor_len
= end
-s
;
1229 size_t len
= router
->cache_info
.signed_descriptor_len
+
1230 router
->cache_info
.annotations_len
;
1232 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1233 if (prepend_annotations
) {
1234 memcpy(cp
, prepend_annotations
, prepend_len
);
1237 /* This assertion will always succeed.
1238 * len == signed_desc_len + annotations_len
1239 * == end-s + s-start_of_annotations + prepend_len
1240 * == end-start_of_annotations + prepend_len
1241 * We already wrote prepend_len bytes into the buffer; now we're
1242 * writing end-start_of_annotations -NM. */
1243 tor_assert(cp
+(end
-start_of_annotations
) ==
1244 router
->cache_info
.signed_descriptor_body
+len
);
1245 memcpy(cp
, start_of_annotations
, end
-start_of_annotations
);
1246 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1247 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1249 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1251 router
->nickname
= tor_strdup(tok
->args
[0]);
1252 if (!is_legal_nickname(router
->nickname
)) {
1253 log_warn(LD_DIR
,"Router nickname is invalid");
1256 router
->address
= tor_strdup(tok
->args
[1]);
1257 if (!tor_inet_aton(router
->address
, &in
)) {
1258 log_warn(LD_DIR
,"Router address is not an IP address.");
1261 router
->addr
= ntohl(in
.s_addr
);
1264 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,&ok
,NULL
);
1266 log_warn(LD_DIR
,"Invalid OR port %s", escaped(tok
->args
[2]));
1270 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,&ok
,NULL
);
1272 log_warn(LD_DIR
,"Invalid dir port %s", escaped(tok
->args
[4]));
1276 tok
= find_by_keyword(tokens
, K_BANDWIDTH
);
1277 tor_assert(tok
->n_args
>= 3);
1278 router
->bandwidthrate
= (int)
1279 tor_parse_long(tok
->args
[0],10,1,INT_MAX
,&ok
,NULL
);
1282 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1283 escaped(tok
->args
[0]));
1286 router
->bandwidthburst
=
1287 (int) tor_parse_long(tok
->args
[1],10,0,INT_MAX
,&ok
,NULL
);
1289 log_warn(LD_DIR
, "Invalid bandwidthburst %s", escaped(tok
->args
[1]));
1292 router
->bandwidthcapacity
= (int)
1293 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,&ok
,NULL
);
1295 log_warn(LD_DIR
, "Invalid bandwidthcapacity %s", escaped(tok
->args
[1]));
1299 if ((tok
= find_opt_by_keyword(tokens
, A_PURPOSE
))) {
1300 tor_assert(tok
->n_args
);
1301 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1303 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1305 router
->cache_info
.send_unencrypted
=
1306 (router
->purpose
== ROUTER_PURPOSE_GENERAL
) ? 1 : 0;
1308 if ((tok
= find_opt_by_keyword(tokens
, K_UPTIME
))) {
1309 tor_assert(tok
->n_args
>= 1);
1310 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,&ok
,NULL
);
1312 log_warn(LD_DIR
, "Invalid uptime %s", escaped(tok
->args
[0]));
1317 if ((tok
= find_opt_by_keyword(tokens
, K_HIBERNATING
))) {
1318 tor_assert(tok
->n_args
>= 1);
1319 router
->is_hibernating
1320 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1323 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1324 tor_assert(tok
->n_args
== 1);
1325 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1328 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
1329 router
->onion_pkey
= tok
->key
;
1330 tok
->key
= NULL
; /* Prevent free */
1332 tok
= find_by_keyword(tokens
, K_SIGNING_KEY
);
1333 router
->identity_pkey
= tok
->key
;
1334 tok
->key
= NULL
; /* Prevent free */
1335 if (crypto_pk_get_digest(router
->identity_pkey
,
1336 router
->cache_info
.identity_digest
)) {
1337 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1340 if ((tok
= find_opt_by_keyword(tokens
, K_FINGERPRINT
))) {
1341 /* If there's a fingerprint line, it must match the identity digest. */
1343 tor_assert(tok
->n_args
== 1);
1344 tor_strstrip(tok
->args
[0], " ");
1345 if (base16_decode(d
, DIGEST_LEN
, tok
->args
[0], strlen(tok
->args
[0]))) {
1346 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1347 escaped(tok
->args
[0]));
1350 if (memcmp(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)!=0) {
1351 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1357 if ((tok
= find_opt_by_keyword(tokens
, K_PLATFORM
))) {
1358 router
->platform
= tor_strdup(tok
->args
[0]);
1361 if ((tok
= find_opt_by_keyword(tokens
, K_CONTACT
))) {
1362 router
->contact_info
= tor_strdup(tok
->args
[0]);
1365 if ((tok
= find_opt_by_keyword(tokens
, K_EVENTDNS
))) {
1366 router
->has_old_dnsworkers
= tok
->n_args
&& !strcmp(tok
->args
[0], "0");
1367 } else if (router
->platform
) {
1368 if (! tor_version_as_new_as(router
->platform
, "0.1.2.2-alpha"))
1369 router
->has_old_dnsworkers
= 1;
1372 if (find_opt_by_keyword(tokens
, K_REJECT6
) ||
1373 find_opt_by_keyword(tokens
, K_ACCEPT6
)) {
1374 log_warn(LD_DIR
, "Rejecting router with reject6/accept6 line: they crash "
1378 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1379 if (!smartlist_len(exit_policy_tokens
)) {
1380 log_warn(LD_DIR
, "No exit policy tokens in descriptor.");
1383 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1384 if (router_add_exit_policy(router
,t
)<0) {
1385 log_warn(LD_DIR
,"Error in exit policy");
1388 policy_expand_private(&router
->exit_policy
);
1389 if (policy_is_reject_star(router
->exit_policy
))
1390 router
->policy_is_reject_star
= 1;
1392 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1394 router
->declared_family
= smartlist_create();
1395 for (i
=0;i
<tok
->n_args
;++i
) {
1396 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1397 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1398 escaped(tok
->args
[i
]));
1401 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
1405 if ((tok
= find_opt_by_keyword(tokens
, K_CACHES_EXTRA_INFO
)))
1406 router
->caches_extra_info
= 1;
1408 if ((tok
= find_opt_by_keyword(tokens
, K_ALLOW_SINGLE_HOP_EXITS
)))
1409 router
->allow_single_hop_exits
= 1;
1411 if ((tok
= find_opt_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1412 tor_assert(tok
->n_args
>= 1);
1413 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1414 base16_decode(router
->cache_info
.extra_info_digest
,
1415 DIGEST_LEN
, tok
->args
[0], HEX_DIGEST_LEN
);
1417 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1421 if ((tok
= find_opt_by_keyword(tokens
, K_HIDDEN_SERVICE_DIR
))) {
1422 router
->wants_to_be_hs_dir
= 1;
1425 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1426 note_crypto_pk_op(VERIFY_RTR
);
1427 #ifdef COUNT_DISTINCT_DIGESTS
1428 if (!verified_digests
)
1429 verified_digests
= digestmap_new();
1430 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
1432 if (check_signature_token(digest
, tok
, router
->identity_pkey
, 0,
1433 "router descriptor") < 0)
1436 routerinfo_set_country(router
);
1438 if (!router
->or_port
) {
1439 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
1443 if (!router
->platform
) {
1444 router
->platform
= tor_strdup("<unknown>");
1450 routerinfo_free(router
);
1454 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1455 smartlist_free(tokens
);
1457 if (exit_policy_tokens
) {
1458 smartlist_free(exit_policy_tokens
);
1461 DUMP_AREA(area
, "routerinfo");
1462 memarea_drop_all(area
);
1467 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1468 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1469 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1470 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1471 * as a map from router identity to routerinfo_t when looking up signing keys.
1474 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
1475 int cache_copy
, struct digest_ri_map_t
*routermap
)
1477 extrainfo_t
*extrainfo
= NULL
;
1479 smartlist_t
*tokens
= NULL
;
1480 directory_token_t
*tok
;
1481 crypto_pk_env_t
*key
= NULL
;
1482 routerinfo_t
*router
= NULL
;
1483 memarea_t
*area
= NULL
;
1486 end
= s
+ strlen(s
);
1489 /* point 'end' to a point immediately after the final newline. */
1490 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1493 if (router_get_extrainfo_hash(s
, digest
) < 0) {
1494 log_warn(LD_DIR
, "Couldn't compute router hash.");
1497 tokens
= smartlist_create();
1498 area
= memarea_new();
1499 if (tokenize_string(area
,s
,end
,tokens
,extrainfo_token_table
,0)) {
1500 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
1504 if (smartlist_len(tokens
) < 2) {
1505 log_warn(LD_DIR
, "Impossibly short extra-info document.");
1509 tok
= smartlist_get(tokens
,0);
1510 if (tok
->tp
!= K_EXTRA_INFO
) {
1511 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
1515 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
1516 extrainfo
->cache_info
.is_extrainfo
= 1;
1518 extrainfo
->cache_info
.signed_descriptor_body
= tor_strndup(s
, end
-s
);
1519 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
1520 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1522 tor_assert(tok
->n_args
>= 2);
1523 if (!is_legal_nickname(tok
->args
[0])) {
1524 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
1527 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
1528 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
1529 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
1530 tok
->args
[1], HEX_DIGEST_LEN
)) {
1531 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
1532 escaped(tok
->args
[1]));
1536 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1537 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
1538 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
1539 escaped(tok
->args
[0]));
1544 (router
= digestmap_get((digestmap_t
*)routermap
,
1545 extrainfo
->cache_info
.identity_digest
))) {
1546 key
= router
->identity_pkey
;
1549 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1550 if (strcmp(tok
->object_type
, "SIGNATURE") ||
1551 tok
->object_size
< 128 || tok
->object_size
> 512) {
1552 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
1557 note_crypto_pk_op(VERIFY_RTR
);
1558 if (check_signature_token(digest
, tok
, key
, 0, "extra-info") < 0)
1562 extrainfo
->cache_info
.send_unencrypted
=
1563 router
->cache_info
.send_unencrypted
;
1565 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
1567 extrainfo
->pending_sig_len
= tok
->object_size
;
1573 extrainfo_free(extrainfo
);
1577 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1578 smartlist_free(tokens
);
1581 DUMP_AREA(area
, "extrainfo");
1582 memarea_drop_all(area
);
1587 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1588 * the first character after the certificate. */
1590 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
1592 /** Reject any certificate at least this big; it is probably an overflow, an
1593 * attack, a bug, or some other nonsense. */
1594 #define MAX_CERT_SIZE (128*1024)
1596 authority_cert_t
*cert
= NULL
, *old_cert
;
1597 smartlist_t
*tokens
= NULL
;
1598 char digest
[DIGEST_LEN
];
1599 directory_token_t
*tok
;
1600 char fp_declared
[DIGEST_LEN
];
1604 memarea_t
*area
= NULL
;
1606 s
= eat_whitespace(s
);
1607 eos
= strstr(s
, "\ndir-key-certification");
1609 log_warn(LD_DIR
, "No signature found on key certificate");
1612 eos
= strstr(eos
, "\n-----END SIGNATURE-----\n");
1614 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
1617 eos
= strchr(eos
+2, '\n');
1622 if (len
> MAX_CERT_SIZE
) {
1623 log_warn(LD_DIR
, "Certificate is far too big (at %lu bytes long); "
1624 "rejecting", (unsigned long)len
);
1628 tokens
= smartlist_create();
1629 area
= memarea_new();
1630 if (tokenize_string(area
,s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
1631 log_warn(LD_DIR
, "Error tokenizing key certificate");
1634 if (router_get_hash_impl(s
, strlen(s
), digest
, "dir-key-certificate-version",
1635 "\ndir-key-certification", '\n') < 0)
1637 tok
= smartlist_get(tokens
, 0);
1638 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
1640 "Key certificate does not begin with a recognized version (3).");
1644 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
1645 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1647 tok
= find_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1648 tor_assert(tok
->key
);
1649 cert
->signing_key
= tok
->key
;
1651 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
1654 tok
= find_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
1655 tor_assert(tok
->key
);
1656 cert
->identity_key
= tok
->key
;
1659 tok
= find_by_keyword(tokens
, K_FINGERPRINT
);
1660 tor_assert(tok
->n_args
);
1661 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
1662 strlen(tok
->args
[0]))) {
1663 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
1664 escaped(tok
->args
[0]));
1668 if (crypto_pk_get_digest(cert
->identity_key
,
1669 cert
->cache_info
.identity_digest
))
1672 if (memcmp(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
1673 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
1678 tok
= find_opt_by_keyword(tokens
, K_DIR_ADDRESS
);
1681 char *address
= NULL
;
1682 tor_assert(tok
->n_args
);
1683 /* XXX021 use tor_addr_port_parse() below instead. -RD */
1684 if (parse_addr_port(LOG_WARN
, tok
->args
[0], &address
, NULL
,
1685 &cert
->dir_port
)<0 ||
1686 tor_inet_aton(address
, &in
) == 0) {
1687 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
1691 cert
->addr
= ntohl(in
.s_addr
);
1695 tok
= find_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
1696 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
1699 tok
= find_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
1700 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
1704 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
1705 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
1706 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
1710 /* If we already have this cert, don't bother checking the signature. */
1711 old_cert
= authority_cert_get_by_digests(
1712 cert
->cache_info
.identity_digest
,
1713 cert
->signing_key_digest
);
1716 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1718 if (old_cert
->cache_info
.signed_descriptor_len
== len
&&
1719 old_cert
->cache_info
.signed_descriptor_body
&&
1720 !memcmp(s
, old_cert
->cache_info
.signed_descriptor_body
, len
)) {
1721 log_debug(LD_DIR
, "We already checked the signature on this "
1722 "certificate; no need to do so again.");
1724 cert
->is_cross_certified
= old_cert
->is_cross_certified
;
1728 if (check_signature_token(digest
, tok
, cert
->identity_key
, 0,
1729 "key certificate")) {
1733 if ((tok
= find_opt_by_keyword(tokens
, K_DIR_KEY_CROSSCERT
))) {
1734 /* XXXX Once all authorities generate cross-certified certificates,
1735 * make this field mandatory. */
1736 if (check_signature_token(cert
->cache_info
.identity_digest
,
1739 CST_NO_CHECK_OBJTYPE
,
1740 "key cross-certification")) {
1743 cert
->is_cross_certified
= 1;
1747 cert
->cache_info
.signed_descriptor_len
= len
;
1748 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1749 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
1750 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
1751 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
1753 if (end_of_string
) {
1754 *end_of_string
= eat_whitespace(eos
);
1756 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1757 smartlist_free(tokens
);
1759 DUMP_AREA(area
, "authority cert");
1760 memarea_drop_all(area
);
1764 authority_cert_free(cert
);
1765 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1766 smartlist_free(tokens
);
1768 DUMP_AREA(area
, "authority cert");
1769 memarea_drop_all(area
);
1774 /** Helper: given a string <b>s</b>, return the start of the next router-status
1775 * object (starting with "r " at the start of a line). If none is found,
1776 * return the start of the next directory signature. If none is found, return
1777 * the end of the string. */
1778 static INLINE
const char *
1779 find_start_of_next_routerstatus(const char *s
)
1781 const char *eos
= strstr(s
, "\nr ");
1783 const char *eos2
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
1784 if (eos2
&& eos2
< eos
)
1789 if ((eos
= strstr(s
, "\ndirectory-signature")))
1791 return s
+ strlen(s
);
1795 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1796 * empty smartlist at <b>tokens</b>, parse and return the first router status
1797 * object in the string, and advance *<b>s</b> to just after the end of the
1798 * router status. Return NULL and advance *<b>s</b> on error.
1800 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1801 * routerstatus but use <b>vote_rs</b> instead.
1803 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1804 * consensus, and we should parse it according to the method used to
1805 * make that consensus.
1807 static routerstatus_t
*
1808 routerstatus_parse_entry_from_string(memarea_t
*area
,
1809 const char **s
, smartlist_t
*tokens
,
1810 networkstatus_t
*vote
,
1811 vote_routerstatus_t
*vote_rs
,
1812 int consensus_method
)
1815 routerstatus_t
*rs
= NULL
;
1816 directory_token_t
*tok
;
1817 char timebuf
[ISO_TIME_LEN
+1];
1820 tor_assert(bool_eq(vote
, vote_rs
));
1822 eos
= find_start_of_next_routerstatus(*s
);
1824 if (tokenize_string(area
,*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
1825 log_warn(LD_DIR
, "Error tokenizing router status");
1828 if (smartlist_len(tokens
) < 1) {
1829 log_warn(LD_DIR
, "Impossibly short router status");
1832 tok
= find_by_keyword(tokens
, K_R
);
1833 tor_assert(tok
->n_args
>= 8);
1835 rs
= &vote_rs
->status
;
1837 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
1840 if (!is_legal_nickname(tok
->args
[0])) {
1842 "Invalid nickname %s in router status; skipping.",
1843 escaped(tok
->args
[0]));
1846 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
1848 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
1849 log_warn(LD_DIR
, "Error decoding identity digest %s",
1850 escaped(tok
->args
[1]));
1854 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
1855 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
1856 escaped(tok
->args
[2]));
1860 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
1861 tok
->args
[3], tok
->args
[4]) < 0 ||
1862 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
1863 log_warn(LD_DIR
, "Error parsing time '%s %s'",
1864 tok
->args
[3], tok
->args
[4]);
1868 if (tor_inet_aton(tok
->args
[5], &in
) == 0) {
1869 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
1870 escaped(tok
->args
[5]));
1873 rs
->addr
= ntohl(in
.s_addr
);
1875 rs
->or_port
=(uint16_t) tor_parse_long(tok
->args
[6],10,0,65535,NULL
,NULL
);
1876 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7],10,0,65535,NULL
,NULL
);
1878 tok
= find_opt_by_keyword(tokens
, K_S
);
1882 for (i
=0; i
< tok
->n_args
; ++i
) {
1883 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
1885 vote_rs
->flags
|= (1<<p
);
1887 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
1888 escaped(tok
->args
[i
]));
1894 for (i
=0; i
< tok
->n_args
; ++i
) {
1895 if (!strcmp(tok
->args
[i
], "Exit"))
1897 else if (!strcmp(tok
->args
[i
], "Stable"))
1899 else if (!strcmp(tok
->args
[i
], "Fast"))
1901 else if (!strcmp(tok
->args
[i
], "Running"))
1903 else if (!strcmp(tok
->args
[i
], "Named"))
1905 else if (!strcmp(tok
->args
[i
], "Valid"))
1907 else if (!strcmp(tok
->args
[i
], "V2Dir"))
1909 else if (!strcmp(tok
->args
[i
], "Guard"))
1910 rs
->is_possible_guard
= 1;
1911 else if (!strcmp(tok
->args
[i
], "BadExit"))
1912 rs
->is_bad_exit
= 1;
1913 else if (!strcmp(tok
->args
[i
], "BadDirectory"))
1914 rs
->is_bad_directory
= 1;
1915 else if (!strcmp(tok
->args
[i
], "Authority"))
1916 rs
->is_authority
= 1;
1917 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
1918 consensus_method
>= 2) {
1919 /* Unnamed is computed right by consensus method 2 and later. */
1921 } else if (!strcmp(tok
->args
[i
], "HSDir")) {
1926 if ((tok
= find_opt_by_keyword(tokens
, K_V
))) {
1927 tor_assert(tok
->n_args
== 1);
1928 rs
->version_known
= 1;
1929 if (strcmpstart(tok
->args
[0], "Tor ")) {
1930 rs
->version_supports_begindir
= 1;
1931 rs
->version_supports_extrainfo_upload
= 1;
1932 rs
->version_supports_conditional_consensus
= 1;
1934 rs
->version_supports_begindir
=
1935 tor_version_as_new_as(tok
->args
[0], "0.2.0.1-alpha");
1936 rs
->version_supports_extrainfo_upload
=
1937 tor_version_as_new_as(tok
->args
[0], "0.2.0.0-alpha-dev (r10070)");
1938 rs
->version_supports_v3_dir
=
1939 tor_version_as_new_as(tok
->args
[0], "0.2.0.8-alpha");
1940 rs
->version_supports_conditional_consensus
=
1941 tor_version_as_new_as(tok
->args
[0], "0.2.1.1-alpha");
1944 vote_rs
->version
= tor_strdup(tok
->args
[0]);
1948 /* handle weighting/bandwidth info */
1949 if ((tok
= find_opt_by_keyword(tokens
, K_W
))) {
1951 for (i
=0; i
< tok
->n_args
; ++i
) {
1952 if (!strcmpstart(tok
->args
[i
], "Bandwidth=")) {
1954 rs
->bandwidth
= (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
1958 log_warn(LD_DIR
, "Invalid Bandwidth %s", escaped(tok
->args
[i
]));
1961 rs
->has_bandwidth
= 1;
1966 /* parse exit policy summaries */
1967 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
1968 tor_assert(tok
->n_args
== 1);
1969 if (strcmpstart(tok
->args
[0], "accept ") &&
1970 strcmpstart(tok
->args
[0], "reject ")) {
1971 log_warn(LD_DIR
, "Unknown exit policy summary type %s.",
1972 escaped(tok
->args
[0]));
1975 /* XXX weasel: parse this into ports and represent them somehow smart,
1976 * maybe not here but somewhere on if we need it for the client.
1977 * we should still parse it here to check it's valid tho.
1979 rs
->exitsummary
= tor_strdup(tok
->args
[0]);
1980 rs
->has_exitsummary
= 1;
1983 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
1989 routerstatus_free(rs
);
1992 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
1993 smartlist_clear(tokens
);
1995 DUMP_AREA(area
, "routerstatus entry");
1996 memarea_clear(area
);
2003 /** Helper to sort a smartlist of pointers to routerstatus_t */
2005 _compare_routerstatus_entries(const void **_a
, const void **_b
)
2007 const routerstatus_t
*a
= *_a
, *b
= *_b
;
2008 return memcmp(a
->identity_digest
, b
->identity_digest
, DIGEST_LEN
);
2011 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
2013 _free_duplicate_routerstatus_entry(void *e
)
2016 "Network-status has two entries for the same router. "
2018 routerstatus_free(e
);
2021 /** Given a v2 network-status object in <b>s</b>, try to
2022 * parse it and return the result. Return NULL on failure. Check the
2023 * signature of the network status, but do not (yet) check the signing key for
2026 networkstatus_v2_t
*
2027 networkstatus_v2_parse_from_string(const char *s
)
2030 smartlist_t
*tokens
= smartlist_create();
2031 smartlist_t
*footer_tokens
= smartlist_create();
2032 networkstatus_v2_t
*ns
= NULL
;
2033 char ns_digest
[DIGEST_LEN
];
2034 char tmp_digest
[DIGEST_LEN
];
2036 directory_token_t
*tok
;
2038 memarea_t
*area
= NULL
;
2040 if (router_get_networkstatus_v2_hash(s
, ns_digest
)) {
2041 log_warn(LD_DIR
, "Unable to compute digest of network-status");
2045 area
= memarea_new();
2046 eos
= find_start_of_next_routerstatus(s
);
2047 if (tokenize_string(area
, s
, eos
, tokens
, netstatus_token_table
,0)) {
2048 log_warn(LD_DIR
, "Error tokenizing network-status header.");
2051 ns
= tor_malloc_zero(sizeof(networkstatus_v2_t
));
2052 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
2054 tok
= find_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
2055 tor_assert(tok
->n_args
>= 1);
2056 if (strcmp(tok
->args
[0], "2")) {
2057 log_warn(LD_BUG
, "Got a non-v2 networkstatus. Version was "
2058 "%s", escaped(tok
->args
[0]));
2062 tok
= find_by_keyword(tokens
, K_DIR_SOURCE
);
2063 tor_assert(tok
->n_args
>= 3);
2064 ns
->source_address
= tor_strdup(tok
->args
[0]);
2065 if (tor_inet_aton(tok
->args
[1], &in
) == 0) {
2066 log_warn(LD_DIR
, "Error parsing network-status source address %s",
2067 escaped(tok
->args
[1]));
2070 ns
->source_addr
= ntohl(in
.s_addr
);
2071 ns
->source_dirport
=
2072 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,NULL
,NULL
);
2073 if (ns
->source_dirport
== 0) {
2074 log_warn(LD_DIR
, "Directory source without dirport; skipping.");
2078 tok
= find_by_keyword(tokens
, K_FINGERPRINT
);
2079 tor_assert(tok
->n_args
);
2080 if (base16_decode(ns
->identity_digest
, DIGEST_LEN
, tok
->args
[0],
2081 strlen(tok
->args
[0]))) {
2082 log_warn(LD_DIR
, "Couldn't decode networkstatus fingerprint %s",
2083 escaped(tok
->args
[0]));
2087 if ((tok
= find_opt_by_keyword(tokens
, K_CONTACT
))) {
2088 tor_assert(tok
->n_args
);
2089 ns
->contact
= tor_strdup(tok
->args
[0]);
2092 tok
= find_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
2093 tor_assert(tok
->key
);
2094 ns
->signing_key
= tok
->key
;
2097 if (crypto_pk_get_digest(ns
->signing_key
, tmp_digest
)<0) {
2098 log_warn(LD_DIR
, "Couldn't compute signing key digest");
2101 if (memcmp(tmp_digest
, ns
->identity_digest
, DIGEST_LEN
)) {
2103 "network-status fingerprint did not match dir-signing-key");
2107 if ((tok
= find_opt_by_keyword(tokens
, K_DIR_OPTIONS
))) {
2108 for (i
=0; i
< tok
->n_args
; ++i
) {
2109 if (!strcmp(tok
->args
[i
], "Names"))
2110 ns
->binds_names
= 1;
2111 if (!strcmp(tok
->args
[i
], "Versions"))
2112 ns
->recommends_versions
= 1;
2113 if (!strcmp(tok
->args
[i
], "BadExits"))
2114 ns
->lists_bad_exits
= 1;
2115 if (!strcmp(tok
->args
[i
], "BadDirectories"))
2116 ns
->lists_bad_directories
= 1;
2120 if (ns
->recommends_versions
) {
2121 if (!(tok
= find_opt_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
2122 log_warn(LD_DIR
, "Missing client-versions on versioning directory");
2125 ns
->client_versions
= tor_strdup(tok
->args
[0]);
2127 if (!(tok
= find_opt_by_keyword(tokens
, K_SERVER_VERSIONS
)) ||
2129 log_warn(LD_DIR
, "Missing server-versions on versioning directory");
2132 ns
->server_versions
= tor_strdup(tok
->args
[0]);
2135 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
2136 tor_assert(tok
->n_args
== 1);
2137 if (parse_iso_time(tok
->args
[0], &ns
->published_on
) < 0) {
2141 ns
->entries
= smartlist_create();
2143 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2144 smartlist_clear(tokens
);
2145 memarea_clear(area
);
2146 while (!strcmpstart(s
, "r ")) {
2148 if ((rs
= routerstatus_parse_entry_from_string(area
, &s
, tokens
,
2150 smartlist_add(ns
->entries
, rs
);
2152 smartlist_sort(ns
->entries
, _compare_routerstatus_entries
);
2153 smartlist_uniq(ns
->entries
, _compare_routerstatus_entries
,
2154 _free_duplicate_routerstatus_entry
);
2156 if (tokenize_string(area
,s
, NULL
, footer_tokens
, dir_footer_token_table
,0)) {
2157 log_warn(LD_DIR
, "Error tokenizing network-status footer.");
2160 if (smartlist_len(footer_tokens
) < 1) {
2161 log_warn(LD_DIR
, "Too few items in network-status footer.");
2164 tok
= smartlist_get(footer_tokens
, smartlist_len(footer_tokens
)-1);
2165 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
) {
2167 "Expected network-status footer to end with a signature.");
2171 note_crypto_pk_op(VERIFY_DIR
);
2172 if (check_signature_token(ns_digest
, tok
, ns
->signing_key
, 0,
2173 "network-status") < 0)
2179 networkstatus_v2_free(ns
);
2182 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2183 smartlist_free(tokens
);
2184 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
2185 smartlist_free(footer_tokens
);
2187 DUMP_AREA(area
, "v2 networkstatus");
2188 memarea_drop_all(area
);
2193 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2194 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2196 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
2197 networkstatus_type_t ns_type
)
2199 smartlist_t
*tokens
= smartlist_create();
2200 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
2201 networkstatus_voter_info_t
*voter
= NULL
;
2202 networkstatus_t
*ns
= NULL
;
2203 char ns_digest
[DIGEST_LEN
];
2204 const char *cert
, *end_of_header
, *end_of_footer
;
2205 directory_token_t
*tok
;
2208 int i
, inorder
, n_signatures
= 0;
2209 memarea_t
*area
= NULL
, *rs_area
= NULL
;
2215 if (router_get_networkstatus_v3_hash(s
, ns_digest
)) {
2216 log_warn(LD_DIR
, "Unable to compute digest of network-status");
2220 area
= memarea_new();
2221 end_of_header
= find_start_of_next_routerstatus(s
);
2222 if (tokenize_string(area
, s
, end_of_header
, tokens
,
2223 (ns_type
== NS_TYPE_CONSENSUS
) ?
2224 networkstatus_consensus_token_table
:
2225 networkstatus_token_table
, 0)) {
2226 log_warn(LD_DIR
, "Error tokenizing network-status vote header");
2230 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
2231 memcpy(ns
->networkstatus_digest
, ns_digest
, DIGEST_LEN
);
2233 if (ns_type
!= NS_TYPE_CONSENSUS
) {
2234 const char *end_of_cert
= NULL
;
2235 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
2238 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
2239 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
2243 tok
= find_by_keyword(tokens
, K_VOTE_STATUS
);
2244 tor_assert(tok
->n_args
);
2245 if (!strcmp(tok
->args
[0], "vote")) {
2246 ns
->type
= NS_TYPE_VOTE
;
2247 } else if (!strcmp(tok
->args
[0], "consensus")) {
2248 ns
->type
= NS_TYPE_CONSENSUS
;
2249 } else if (!strcmp(tok
->args
[0], "opinion")) {
2250 ns
->type
= NS_TYPE_OPINION
;
2252 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
2253 escaped(tok
->args
[0]));
2256 if (ns_type
!= ns
->type
) {
2257 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
2261 if (ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_OPINION
) {
2262 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
2263 if (parse_iso_time(tok
->args
[0], &ns
->published
))
2266 ns
->supported_methods
= smartlist_create();
2267 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHODS
);
2269 for (i
=0; i
< tok
->n_args
; ++i
)
2270 smartlist_add(ns
->supported_methods
, tor_strdup(tok
->args
[i
]));
2272 smartlist_add(ns
->supported_methods
, tor_strdup("1"));
2275 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHOD
);
2277 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
2282 ns
->consensus_method
= 1;
2286 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
2287 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
2290 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
2291 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
2294 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
2295 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
2298 tok
= find_by_keyword(tokens
, K_VOTING_DELAY
);
2299 tor_assert(tok
->n_args
>= 2);
2301 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
2305 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
2308 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
> ns
->fresh_until
) {
2309 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
2312 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
*2 > ns
->valid_until
) {
2313 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
2316 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
2317 log_warn(LD_DIR
, "Vote seconds is too short");
2320 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
2321 log_warn(LD_DIR
, "Dist seconds is too short");
2325 if ((tok
= find_opt_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
2326 ns
->client_versions
= tor_strdup(tok
->args
[0]);
2328 if ((tok
= find_opt_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
2329 ns
->server_versions
= tor_strdup(tok
->args
[0]);
2332 tok
= find_by_keyword(tokens
, K_KNOWN_FLAGS
);
2333 ns
->known_flags
= smartlist_create();
2335 for (i
= 0; i
< tok
->n_args
; ++i
) {
2336 smartlist_add(ns
->known_flags
, tor_strdup(tok
->args
[i
]));
2337 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
2338 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2343 log_warn(LD_DIR
, "known-flags not in order");
2347 tok
= find_opt_by_keyword(tokens
, K_PARAMS
);
2350 ns
->net_params
= smartlist_create();
2351 for (i
= 0; i
< tok
->n_args
; ++i
) {
2353 char *eq
= strchr(tok
->args
[i
], '=');
2355 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
2358 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
2360 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
2363 if (i
> 0 && strcmp(tok
->args
[i
-1], tok
->args
[i
]) >= 0) {
2364 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2367 smartlist_add(ns
->net_params
, tor_strdup(tok
->args
[i
]));
2370 log_warn(LD_DIR
, "params not in order");
2375 ns
->voters
= smartlist_create();
2377 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
2379 if (tok
->tp
== K_DIR_SOURCE
) {
2380 tor_assert(tok
->n_args
>= 6);
2383 smartlist_add(ns
->voters
, voter
);
2384 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2385 if (ns
->type
!= NS_TYPE_CONSENSUS
)
2386 memcpy(voter
->vote_digest
, ns_digest
, DIGEST_LEN
);
2388 voter
->nickname
= tor_strdup(tok
->args
[0]);
2389 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2390 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
2391 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2392 log_warn(LD_DIR
, "Error decoding identity digest %s in "
2393 "network-status vote.", escaped(tok
->args
[1]));
2396 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
2397 memcmp(ns
->cert
->cache_info
.identity_digest
,
2398 voter
->identity_digest
, DIGEST_LEN
)) {
2399 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
2402 voter
->address
= tor_strdup(tok
->args
[2]);
2403 if (!tor_inet_aton(tok
->args
[3], &in
)) {
2404 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
2405 escaped(tok
->args
[3]));
2408 voter
->addr
= ntohl(in
.s_addr
);
2409 voter
->dir_port
= (uint16_t)
2410 tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
2413 voter
->or_port
= (uint16_t)
2414 tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
2417 } else if (tok
->tp
== K_CONTACT
) {
2418 if (!voter
|| voter
->contact
) {
2419 log_warn(LD_DIR
, "contact element is out of place.");
2422 voter
->contact
= tor_strdup(tok
->args
[0]);
2423 } else if (tok
->tp
== K_VOTE_DIGEST
) {
2424 tor_assert(ns
->type
== NS_TYPE_CONSENSUS
);
2425 tor_assert(tok
->n_args
>= 1);
2426 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
2427 log_warn(LD_DIR
, "vote-digest element is out of place.");
2430 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2431 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
2432 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2433 log_warn(LD_DIR
, "Error decoding vote digest %s in "
2434 "network-status consensus.", escaped(tok
->args
[0]));
2438 } SMARTLIST_FOREACH_END(_tok
);
2440 smartlist_add(ns
->voters
, voter
);
2443 if (smartlist_len(ns
->voters
) == 0) {
2444 log_warn(LD_DIR
, "Missing dir-source elements in a vote networkstatus.");
2446 } else if (ns
->type
!= NS_TYPE_CONSENSUS
&& smartlist_len(ns
->voters
) != 1) {
2447 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
2451 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
2452 (tok
= find_opt_by_keyword(tokens
, K_LEGACY_DIR_KEY
))) {
2454 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
2455 networkstatus_voter_info_t
*voter
= smartlist_get(ns
->voters
, 0);
2456 if (base16_decode(voter
->legacy_id_digest
, DIGEST_LEN
,
2457 tok
->args
[0], HEX_DIGEST_LEN
)<0)
2463 log_warn(LD_DIR
, "Invalid legacy key digest %s on vote.",
2464 escaped(tok
->args
[0]));
2468 /* Parse routerstatus lines. */
2469 rs_tokens
= smartlist_create();
2470 rs_area
= memarea_new();
2472 ns
->routerstatus_list
= smartlist_create();
2474 while (!strcmpstart(s
, "r ")) {
2475 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2476 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
2477 if (routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
, ns
,
2479 smartlist_add(ns
->routerstatus_list
, rs
);
2481 tor_free(rs
->version
);
2486 if ((rs
= routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
,
2488 ns
->consensus_method
)))
2489 smartlist_add(ns
->routerstatus_list
, rs
);
2492 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
2493 routerstatus_t
*rs1
, *rs2
;
2494 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2495 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
2496 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
2497 rs1
= &a
->status
; rs2
= &b
->status
;
2499 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
2500 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
2502 if (memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
) >= 0) {
2503 log_warn(LD_DIR
, "Vote networkstatus entries not sorted by identity "
2509 /* Parse footer; check signature. */
2510 footer_tokens
= smartlist_create();
2511 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
2514 end_of_footer
= s
+ strlen(s
);
2515 if (tokenize_string(area
,s
, end_of_footer
, footer_tokens
,
2516 networkstatus_vote_footer_token_table
, 0)) {
2517 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
2521 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, _tok
,
2523 char declared_identity
[DIGEST_LEN
];
2524 networkstatus_voter_info_t
*v
;
2526 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2528 tor_assert(tok
->n_args
>= 2);
2530 if (!tok
->object_type
||
2531 strcmp(tok
->object_type
, "SIGNATURE") ||
2532 tok
->object_size
< 128 || tok
->object_size
> 512) {
2533 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2537 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2538 base16_decode(declared_identity
, sizeof(declared_identity
),
2539 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2540 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2541 "network-status vote.", escaped(tok
->args
[0]));
2544 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
2545 log_warn(LD_DIR
, "ID on signature on network-status vote does not match "
2546 "any declared directory source.");
2549 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2550 base16_decode(v
->signing_key_digest
, sizeof(v
->signing_key_digest
),
2551 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2552 log_warn(LD_DIR
, "Error decoding declared digest %s in "
2553 "network-status vote.", escaped(tok
->args
[1]));
2557 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2558 if (memcmp(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
2560 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
2561 "network-status vote.");
2566 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2567 if (check_signature_token(ns_digest
, tok
, ns
->cert
->signing_key
, 0,
2568 "network-status vote"))
2570 v
->good_signature
= 1;
2572 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
)
2574 /* We already parsed a vote from this voter. Use the first one. */
2576 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "We received a networkstatus "
2577 "that contains two votes from the same voter. Ignoring "
2578 "the second vote.");
2582 v
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2583 v
->signature_len
= (int) tok
->object_size
;
2588 if (! n_signatures
) {
2589 log_warn(LD_DIR
, "No signatures on networkstatus vote.");
2594 *eos_out
= end_of_footer
;
2599 networkstatus_vote_free(ns
);
2603 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2604 smartlist_free(tokens
);
2607 tor_free(voter
->nickname
);
2608 tor_free(voter
->address
);
2609 tor_free(voter
->contact
);
2610 tor_free(voter
->signature
);
2614 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_free(t
));
2615 smartlist_free(rs_tokens
);
2617 if (footer_tokens
) {
2618 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_free(t
));
2619 smartlist_free(footer_tokens
);
2622 DUMP_AREA(area
, "v3 networkstatus");
2623 memarea_drop_all(area
);
2626 memarea_drop_all(rs_area
);
2631 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2632 * <b>eos</b> and return the result. Return -1 on failure. */
2633 ns_detached_signatures_t
*
2634 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
2636 /* XXXX there is too much duplicate shared between this function and
2637 * networkstatus_parse_vote_from_string(). */
2638 directory_token_t
*tok
;
2639 memarea_t
*area
= NULL
;
2641 smartlist_t
*tokens
= smartlist_create();
2642 ns_detached_signatures_t
*sigs
=
2643 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
2646 eos
= s
+ strlen(s
);
2648 area
= memarea_new();
2649 if (tokenize_string(area
,s
, eos
, tokens
,
2650 networkstatus_detached_signature_token_table
, 0)) {
2651 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
2655 tok
= find_by_keyword(tokens
, K_CONSENSUS_DIGEST
);
2656 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
) {
2657 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
2658 "networkstatus signatures");
2661 if (base16_decode(sigs
->networkstatus_digest
, DIGEST_LEN
,
2662 tok
->args
[0], strlen(tok
->args
[0])) < 0) {
2663 log_warn(LD_DIR
, "Bad encoding on on consensus-digest in detached "
2664 "networkstatus signatures");
2668 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
2669 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
2670 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
2674 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
2675 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
2676 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
2680 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
2681 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
2682 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
2686 sigs
->signatures
= smartlist_create();
2687 SMARTLIST_FOREACH(tokens
, directory_token_t
*, _tok
,
2689 char id_digest
[DIGEST_LEN
];
2690 char sk_digest
[DIGEST_LEN
];
2691 networkstatus_voter_info_t
*voter
;
2694 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2696 tor_assert(tok
->n_args
>= 2);
2698 if (!tok
->object_type
||
2699 strcmp(tok
->object_type
, "SIGNATURE") ||
2700 tok
->object_size
< 128 || tok
->object_size
> 512) {
2701 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2705 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2706 base16_decode(id_digest
, sizeof(id_digest
),
2707 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2708 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2709 "network-status vote.", escaped(tok
->args
[0]));
2712 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2713 base16_decode(sk_digest
, sizeof(sk_digest
),
2714 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2715 log_warn(LD_DIR
, "Error decoding declared digest %s in "
2716 "network-status vote.", escaped(tok
->args
[1]));
2720 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2721 memcpy(voter
->identity_digest
, id_digest
, DIGEST_LEN
);
2722 memcpy(voter
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
2723 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
)
2725 voter
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2726 voter
->signature_len
= (int) tok
->object_size
;
2728 smartlist_add(sigs
->signatures
, voter
);
2733 ns_detached_signatures_free(sigs
);
2736 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
2737 smartlist_free(tokens
);
2739 DUMP_AREA(area
, "detached signatures");
2740 memarea_drop_all(area
);
2745 /** Parse the addr policy in the string <b>s</b> and return it. If
2746 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2747 * ADDR_POLICY_REJECT) for items that specify no action.
2750 router_parse_addr_policy_item_from_string(const char *s
, int assume_action
)
2752 directory_token_t
*tok
= NULL
;
2753 const char *cp
, *eos
;
2754 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2755 * But note that there can be an arbitrary amount of space between the
2756 * accept and the address:mask/port element. */
2757 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
2759 memarea_t
*area
= NULL
;
2761 s
= eat_whitespace(s
);
2762 if ((*s
== '*' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
2763 if (tor_snprintf(line
, sizeof(line
), "%s %s",
2764 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
2765 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
2770 } else { /* assume an already well-formed address policy line */
2774 eos
= cp
+ strlen(cp
);
2775 area
= memarea_new();
2776 tok
= get_next_token(area
, &cp
, eos
, routerdesc_token_table
);
2777 if (tok
->tp
== _ERR
) {
2778 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
2781 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_ACCEPT6
&&
2782 tok
->tp
!= K_REJECT
&& tok
->tp
!= K_REJECT6
) {
2783 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
2787 r
= router_parse_addr_policy(tok
);
2794 DUMP_AREA(area
, "policy item");
2795 memarea_drop_all(area
);
2800 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2801 * <b>router</b>. Return 0 on success, -1 on failure. */
2803 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
2805 addr_policy_t
*newe
;
2806 newe
= router_parse_addr_policy(tok
);
2809 if (! router
->exit_policy
)
2810 router
->exit_policy
= smartlist_create();
2812 if (((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
2813 tor_addr_family(&newe
->addr
) == AF_INET
)
2815 ((tok
->tp
== K_ACCEPT
|| tok
->tp
== K_REJECT
) &&
2816 tor_addr_family(&newe
->addr
) == AF_INET6
)) {
2817 log_warn(LD_DIR
, "Mismatch between field type and address type in exit "
2819 addr_policy_free(newe
);
2823 smartlist_add(router
->exit_policy
, newe
);
2828 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2829 * a new exit_policy_t corresponding to the token. */
2830 static addr_policy_t
*
2831 router_parse_addr_policy(directory_token_t
*tok
)
2836 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
||
2837 tok
->tp
== K_ACCEPT
|| tok
->tp
== K_ACCEPT6
);
2839 if (tok
->n_args
!= 1)
2843 if (!strcmpstart(arg
,"private"))
2844 return router_parse_addr_policy_private(tok
);
2846 memset(&newe
, 0, sizeof(newe
));
2848 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
2849 newe
.policy_type
= ADDR_POLICY_REJECT
;
2851 newe
.policy_type
= ADDR_POLICY_ACCEPT
;
2853 if (tor_addr_parse_mask_ports(arg
, &newe
.addr
, &newe
.maskbits
,
2854 &newe
.prt_min
, &newe
.prt_max
) < 0) {
2855 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
2859 return addr_policy_get_canonical_entry(&newe
);
2862 /** Parse an exit policy line of the format "accept/reject private:...".
2863 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2864 * router descriptors until earlier versions are obsolete.
2866 static addr_policy_t
*
2867 router_parse_addr_policy_private(directory_token_t
*tok
)
2870 uint16_t port_min
, port_max
;
2871 addr_policy_t result
;
2874 if (strcmpstart(arg
, "private"))
2877 arg
+= strlen("private");
2878 arg
= (char*) eat_whitespace(arg
);
2879 if (!arg
|| *arg
!= ':')
2882 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
2885 memset(&result
, 0, sizeof(result
));
2886 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
2887 result
.policy_type
= ADDR_POLICY_REJECT
;
2889 result
.policy_type
= ADDR_POLICY_ACCEPT
;
2890 result
.is_private
= 1;
2891 result
.prt_min
= port_min
;
2892 result
.prt_max
= port_max
;
2894 return addr_policy_get_canonical_entry(&result
);
2897 /** Log and exit if <b>t</b> is malformed */
2899 assert_addr_policy_ok(smartlist_t
*lst
)
2902 SMARTLIST_FOREACH(lst
, addr_policy_t
*, t
, {
2903 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
2904 t
->policy_type
== ADDR_POLICY_ACCEPT
);
2905 tor_assert(t
->prt_min
<= t
->prt_max
);
2910 * Low-level tokenizer for router descriptors and directories.
2913 /** Free all resources allocated for <b>tok</b> */
2915 token_free(directory_token_t
*tok
)
2919 crypto_free_pk_env(tok
->key
);
2922 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
2923 #define ALLOC(sz) memarea_alloc(area,sz)
2924 #define STRDUP(str) memarea_strdup(area,str)
2925 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
2927 #define RET_ERR(msg) \
2929 if (tok) token_free(tok); \
2930 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
2932 tok->error = STRDUP(msg); \
2933 goto done_tokenizing; \
2936 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
2937 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
2938 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
2939 * conform to the syntax we wanted.
2941 static INLINE directory_token_t
*
2942 token_check_object(memarea_t
*area
, const char *kwd
,
2943 directory_token_t
*tok
, obj_syntax o_syn
)
2948 /* No object is allowed for this token. */
2949 if (tok
->object_body
) {
2950 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected object for %s", kwd
);
2954 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected public key for %s", kwd
);
2959 /* There must be a (non-key) object. */
2960 if (!tok
->object_body
) {
2961 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing object for %s", kwd
);
2965 case NEED_KEY_1024
: /* There must be a 1024-bit public key. */
2966 case NEED_SKEY_1024
: /* There must be a 1024-bit private key. */
2967 if (tok
->key
&& crypto_pk_keysize(tok
->key
) != PK_BYTES
) {
2968 tor_snprintf(ebuf
, sizeof(ebuf
), "Wrong size on key for %s: %d bits",
2969 kwd
, (int)crypto_pk_keysize(tok
->key
));
2973 case NEED_KEY
: /* There must be some kind of key. */
2975 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing public key for %s", kwd
);
2978 if (o_syn
!= NEED_SKEY_1024
) {
2979 if (crypto_pk_key_is_private(tok
->key
)) {
2980 tor_snprintf(ebuf
, sizeof(ebuf
),
2981 "Private key given for %s, which wants a public key", kwd
);
2984 } else { /* o_syn == NEED_SKEY_1024 */
2985 if (!crypto_pk_key_is_private(tok
->key
)) {
2986 tor_snprintf(ebuf
, sizeof(ebuf
),
2987 "Public key given for %s, which wants a private key", kwd
);
2993 /* Anything goes with this token. */
3001 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3002 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3003 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3004 * all storage in <b>area</b>. Return the number of arguments parsed, or
3005 * return -1 if there was an insanely high number of arguments. */
3007 get_token_arguments(memarea_t
*area
, directory_token_t
*tok
,
3008 const char *s
, const char *eol
)
3010 /** Largest number of arguments we'll accept to any token, ever. */
3011 #define MAX_ARGS 512
3012 char *mem
= memarea_strndup(area
, s
, eol
-s
);
3015 char *args
[MAX_ARGS
];
3020 cp
= (char*)find_whitespace(cp
);
3022 break; /* End of the line. */
3024 cp
= (char*)eat_whitespace(cp
);
3027 tok
->args
= memarea_memdup(area
, args
, j
*sizeof(char*));
3032 /** Helper function: read the next token from *s, advance *s to the end of the
3033 * token, and return the parsed token. Parse *<b>s</b> according to the list
3034 * of tokens in <b>table</b>.
3036 static directory_token_t
*
3037 get_next_token(memarea_t
*area
,
3038 const char **s
, const char *eos
, token_rule_t
*table
)
3040 /** Reject any object at least this big; it is probably an overflow, an
3041 * attack, a bug, or some other nonsense. */
3042 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
3043 /** Reject any line at least this big; it is probably an overflow, an
3044 * attack, a bug, or some other nonsense. */
3045 #define MAX_LINE_LENGTH (128*1024)
3047 const char *next
, *eol
, *obstart
;
3050 directory_token_t
*tok
;
3051 obj_syntax o_syn
= NO_OBJ
;
3053 const char *kwd
= "";
3056 tok
= ALLOC_ZERO(sizeof(directory_token_t
));
3059 /* Set *s to first token, eol to end-of-line, next to after first token */
3060 *s
= eat_whitespace_eos(*s
, eos
); /* eat multi-line whitespace */
3061 tor_assert(eos
>= *s
);
3062 eol
= memchr(*s
, '\n', eos
-*s
);
3065 if (eol
- *s
> MAX_LINE_LENGTH
) {
3066 RET_ERR("Line far too long");
3069 next
= find_whitespace_eos(*s
, eol
);
3071 if (!strcmp_len(*s
, "opt", next
-*s
)) {
3072 /* Skip past an "opt" at the start of the line. */
3073 *s
= eat_whitespace_eos_no_nl(next
, eol
);
3074 next
= find_whitespace_eos(*s
, eol
);
3075 } else if (*s
== eos
) { /* If no "opt", and end-of-line, line is invalid */
3076 RET_ERR("Unexpected EOF");
3079 /* Search the table for the appropriate entry. (I tried a binary search
3080 * instead, but it wasn't any faster.) */
3081 for (i
= 0; table
[i
].t
; ++i
) {
3082 if (!strcmp_len(*s
, table
[i
].t
, next
-*s
)) {
3083 /* We've found the keyword. */
3085 tok
->tp
= table
[i
].v
;
3086 o_syn
= table
[i
].os
;
3087 *s
= eat_whitespace_eos_no_nl(next
, eol
);
3088 /* We go ahead whether there are arguments or not, so that tok->args is
3089 * always set if we want arguments. */
3090 if (table
[i
].concat_args
) {
3091 /* The keyword takes the line as a single argument */
3092 tok
->args
= ALLOC(sizeof(char*));
3093 tok
->args
[0] = STRNDUP(*s
,eol
-*s
); /* Grab everything on line */
3096 /* This keyword takes multiple arguments. */
3097 if (get_token_arguments(area
, tok
, *s
, eol
)<0) {
3098 tor_snprintf(ebuf
, sizeof(ebuf
),"Far too many arguments to %s", kwd
);
3103 if (tok
->n_args
< table
[i
].min_args
) {
3104 tor_snprintf(ebuf
, sizeof(ebuf
), "Too few arguments to %s", kwd
);
3106 } else if (tok
->n_args
> table
[i
].max_args
) {
3107 tor_snprintf(ebuf
, sizeof(ebuf
), "Too many arguments to %s", kwd
);
3114 if (tok
->tp
== _ERR
) {
3115 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3117 tok
->tp
= _A_UNKNOWN
;
3120 tok
->args
= ALLOC(sizeof(char*));
3121 tok
->args
[0] = STRNDUP(*s
, eol
-*s
);
3126 /* Check whether there's an object present */
3127 *s
= eat_whitespace_eos(eol
, eos
); /* Scan from end of first line */
3128 tor_assert(eos
>= *s
);
3129 eol
= memchr(*s
, '\n', eos
-*s
);
3130 if (!eol
|| eol
-*s
<11 || strcmpstart(*s
, "-----BEGIN ")) /* No object. */
3133 obstart
= *s
; /* Set obstart to start of object spec */
3134 if (*s
+16 >= eol
|| memchr(*s
+11,'\0',eol
-*s
-16) || /* no short lines, */
3135 strcmp_len(eol
-5, "-----", 5) || /* nuls or invalid endings */
3136 (eol
-*s
) > MAX_UNPARSED_OBJECT_SIZE
) { /* name too long */
3137 RET_ERR("Malformed object: bad begin line");
3139 tok
->object_type
= STRNDUP(*s
+11, eol
-*s
-16);
3140 obname_len
= eol
-*s
-16; /* store objname length here to avoid a strlen() */
3141 *s
= eol
+1; /* Set *s to possible start of object data (could be eos) */
3143 /* Go to the end of the object */
3144 next
= tor_memstr(*s
, eos
-*s
, "-----END ");
3146 RET_ERR("Malformed object: missing object end line");
3148 tor_assert(eos
>= next
);
3149 eol
= memchr(next
, '\n', eos
-next
);
3150 if (!eol
) /* end-of-line marker, or eos if there's no '\n' */
3152 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3153 if ((size_t)(eol
-next
) != 9+obname_len
+5 ||
3154 strcmp_len(next
+9, tok
->object_type
, obname_len
) ||
3155 strcmp_len(eol
-5, "-----", 5)) {
3156 snprintf(ebuf
, sizeof(ebuf
), "Malformed object: mismatched end tag %s",
3158 ebuf
[sizeof(ebuf
)-1] = '\0';
3161 if (next
- *s
> MAX_UNPARSED_OBJECT_SIZE
)
3162 RET_ERR("Couldn't parse object: missing footer or object much too big.");
3164 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) { /* If it's a public key */
3165 tok
->key
= crypto_new_pk_env();
3166 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, eol
-obstart
))
3167 RET_ERR("Couldn't parse public key.");
3168 } else if (!strcmp(tok
->object_type
, "RSA PRIVATE KEY")) { /* private key */
3169 tok
->key
= crypto_new_pk_env();
3170 if (crypto_pk_read_private_key_from_string(tok
->key
, obstart
, eol
-obstart
))
3171 RET_ERR("Couldn't parse private key.");
3172 } else { /* If it's something else, try to base64-decode it */
3174 tok
->object_body
= ALLOC(next
-*s
); /* really, this is too much RAM. */
3175 r
= base64_decode(tok
->object_body
, next
-*s
, *s
, next
-*s
);
3177 RET_ERR("Malformed object: bad base64-encoded data");
3178 tok
->object_size
= r
;
3183 tok
= token_check_object(area
, kwd
, tok
, o_syn
);
3195 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3196 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3197 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3201 tokenize_string(memarea_t
*area
,
3202 const char *start
, const char *end
, smartlist_t
*out
,
3203 token_rule_t
*table
, int flags
)
3206 directory_token_t
*tok
= NULL
;
3209 int first_nonannotation
;
3210 int prev_len
= smartlist_len(out
);
3215 end
= start
+strlen(start
);
3216 for (i
= 0; i
< _NIL
; ++i
)
3219 SMARTLIST_FOREACH(out
, const directory_token_t
*, t
, ++counts
[t
->tp
]);
3221 while (*s
< end
&& (!tok
|| tok
->tp
!= _EOF
)) {
3222 tok
= get_next_token(area
, s
, end
, table
);
3223 if (tok
->tp
== _ERR
) {
3224 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
3229 smartlist_add(out
, tok
);
3230 *s
= eat_whitespace_eos(*s
, end
);
3233 if (flags
& TS_NOCHECK
)
3236 if ((flags
& TS_ANNOTATIONS_OK
)) {
3237 first_nonannotation
= -1;
3238 for (i
= 0; i
< smartlist_len(out
); ++i
) {
3239 tok
= smartlist_get(out
, i
);
3240 if (tok
->tp
< MIN_ANNOTATION
|| tok
->tp
> MAX_ANNOTATION
) {
3241 first_nonannotation
= i
;
3245 if (first_nonannotation
< 0) {
3246 log_warn(LD_DIR
, "parse error: item contains only annotations");
3249 for (i
=first_nonannotation
; i
< smartlist_len(out
); ++i
) {
3250 tok
= smartlist_get(out
, i
);
3251 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
3252 log_warn(LD_DIR
, "parse error: Annotations mixed with keywords");
3256 if ((flags
& TS_NO_NEW_ANNOTATIONS
)) {
3257 if (first_nonannotation
!= prev_len
) {
3258 log_warn(LD_DIR
, "parse error: Unexpected annotations.");
3263 for (i
=0; i
< smartlist_len(out
); ++i
) {
3264 tok
= smartlist_get(out
, i
);
3265 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
3266 log_warn(LD_DIR
, "parse error: no annotations allowed.");
3270 first_nonannotation
= 0;
3272 for (i
= 0; table
[i
].t
; ++i
) {
3273 if (counts
[table
[i
].v
] < table
[i
].min_cnt
) {
3274 log_warn(LD_DIR
, "Parse error: missing %s element.", table
[i
].t
);
3277 if (counts
[table
[i
].v
] > table
[i
].max_cnt
) {
3278 log_warn(LD_DIR
, "Parse error: too many %s elements.", table
[i
].t
);
3281 if (table
[i
].pos
& AT_START
) {
3282 if (smartlist_len(out
) < 1 ||
3283 (tok
= smartlist_get(out
, first_nonannotation
))->tp
!= table
[i
].v
) {
3284 log_warn(LD_DIR
, "Parse error: first item is not %s.", table
[i
].t
);
3288 if (table
[i
].pos
& AT_END
) {
3289 if (smartlist_len(out
) < 1 ||
3290 (tok
= smartlist_get(out
, smartlist_len(out
)-1))->tp
!= table
[i
].v
) {
3291 log_warn(LD_DIR
, "Parse error: last item is not %s.", table
[i
].t
);
3299 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3300 * NULL if no such keyword is found.
3302 static directory_token_t
*
3303 find_opt_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
3305 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
3309 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3310 * with an assert if no such keyword is found.
3312 static directory_token_t
*
3313 _find_by_keyword(smartlist_t
*s
, directory_keyword keyword
,
3314 const char *keyword_as_string
)
3316 directory_token_t
*tok
= find_opt_by_keyword(s
, keyword
);
3317 if (PREDICT_UNLIKELY(!tok
)) {
3318 log_err(LD_BUG
, "Missing %s [%d] in directory object that should have "
3319 "been validated. Internal error.", keyword_as_string
, (int)keyword
);
3325 /** Return a newly allocated smartlist of all accept or reject tokens in
3328 static smartlist_t
*
3329 find_all_exitpolicy(smartlist_t
*s
)
3331 smartlist_t
*out
= smartlist_create();
3332 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
3333 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_ACCEPT6
||
3334 t
->tp
== K_REJECT
|| t
->tp
== K_REJECT6
)
3335 smartlist_add(out
,t
));
3339 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
3340 * occurrence of <b>start_str</b> through the first instance of c after the
3341 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
3342 * <b>digest</b>; return 0 on success.
3344 * If no such substring exists, return -1.
3347 router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
3348 const char *start_str
,
3349 const char *end_str
, char end_c
)
3351 const char *start
, *end
;
3352 start
= tor_memstr(s
, s_len
, start_str
);
3354 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
3357 if (start
!= s
&& *(start
-1) != '\n') {
3359 "first occurrence of \"%s\" is not at the start of a line",
3363 end
= tor_memstr(start
+strlen(start_str
),
3364 s_len
- (start
-s
) - strlen(start_str
), end_str
);
3366 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
3369 end
= memchr(end
+strlen(end_str
), end_c
, s_len
- (end
-s
) - strlen(end_str
));
3371 log_warn(LD_DIR
,"couldn't find EOL");
3376 if (crypto_digest(digest
, start
, end
-start
)) {
3377 log_warn(LD_BUG
,"couldn't compute digest");
3384 /** Parse the Tor version of the platform string <b>platform</b>,
3385 * and compare it to the version in <b>cutoff</b>. Return 1 if
3386 * the router is at least as new as the cutoff, else return 0.
3389 tor_version_as_new_as(const char *platform
, const char *cutoff
)
3391 tor_version_t cutoff_version
, router_version
;
3392 char *s
, *s2
, *start
;
3395 tor_assert(platform
);
3397 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
3398 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
3401 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
3404 start
= (char *)eat_whitespace(platform
+3);
3405 if (!*start
) return 0;
3406 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
3407 s2
= (char*)eat_whitespace(s
);
3408 if (!strcmpstart(s2
, "(r"))
3409 s
= (char*)find_whitespace(s2
);
3411 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
3413 strlcpy(tmp
, start
, s
-start
+1);
3415 if (tor_version_parse(tmp
, &router_version
)<0) {
3416 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
3417 return 1; /* be safe and say yes */
3420 /* Here's why we don't need to do any special handling for svn revisions:
3421 * - If neither has an svn revision, we're fine.
3422 * - If the router doesn't have an svn revision, we can't assume that it
3423 * is "at least" any svn revision, so we need to return 0.
3424 * - If the target version doesn't have an svn revision, any svn revision
3425 * (or none at all) is good enough, so return 1.
3426 * - If both target and router have an svn revision, we compare them.
3429 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
3432 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3433 * Return 0 on success, -1 on failure. */
3435 tor_version_parse(const char *s
, tor_version_t
*out
)
3438 const char *cp
=NULL
;
3440 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3445 memset(out
, 0, sizeof(tor_version_t
));
3447 if (!strcasecmpstart(s
, "Tor "))
3451 out
->major
= (int)strtol(s
,&eos
,10);
3452 if (!eos
|| eos
==s
|| *eos
!= '.') return -1;
3456 out
->minor
= (int) strtol(cp
,&eos
,10);
3457 if (!eos
|| eos
==cp
|| *eos
!= '.') return -1;
3461 out
->micro
= (int) strtol(cp
,&eos
,10);
3462 if (!eos
|| eos
==cp
) return -1;
3464 out
->status
= VER_RELEASE
;
3465 out
->patchlevel
= 0;
3472 out
->status
= VER_RELEASE
;
3474 } else if (0==strncmp(cp
, "pre", 3)) {
3475 out
->status
= VER_PRE
;
3477 } else if (0==strncmp(cp
, "rc", 2)) {
3478 out
->status
= VER_RC
;
3484 /* Get patchlevel */
3485 out
->patchlevel
= (int) strtol(cp
,&eos
,10);
3486 if (!eos
|| eos
==cp
) return -1;
3489 /* Get status tag. */
3490 if (*cp
== '-' || *cp
== '.')
3492 eos
= (char*) find_whitespace(cp
);
3493 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
3494 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
3496 memcpy(out
->status_tag
, cp
, eos
-cp
);
3497 out
->status_tag
[eos
-cp
] = 0;
3499 cp
= eat_whitespace(eos
);
3501 if (!strcmpstart(cp
, "(r")) {
3503 out
->svn_revision
= (int) strtol(cp
,&eos
,10);
3509 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3512 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
3517 if ((i
= a
->major
- b
->major
))
3519 else if ((i
= a
->minor
- b
->minor
))
3521 else if ((i
= a
->micro
- b
->micro
))
3523 else if ((i
= a
->status
- b
->status
))
3525 else if ((i
= a
->patchlevel
- b
->patchlevel
))
3527 else if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
3530 return a
->svn_revision
- b
->svn_revision
;
3533 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3536 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
3540 return ((a
->major
== b
->major
) &&
3541 (a
->minor
== b
->minor
) &&
3542 (a
->micro
== b
->micro
));
3545 /** Helper: Given pointers to two strings describing tor versions, return -1
3546 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
3547 * Used to sort a list of versions. */
3549 _compare_tor_version_str_ptr(const void **_a
, const void **_b
)
3551 const char *a
= *_a
, *b
= *_b
;
3553 tor_version_t va
, vb
;
3554 ca
= tor_version_parse(a
, &va
);
3555 cb
= tor_version_parse(b
, &vb
);
3556 /* If they both parse, compare them. */
3558 return tor_version_compare(&va
,&vb
);
3559 /* If one parses, it comes first. */
3564 /* If neither parses, compare strings. Also, the directory server admin
3565 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3569 /** Sort a list of string-representations of versions in ascending order. */
3571 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
3573 smartlist_sort(versions
, _compare_tor_version_str_ptr
);
3575 if (remove_duplicates
)
3576 smartlist_uniq(versions
, _compare_tor_version_str_ptr
, _tor_free
);
3579 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3580 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3581 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3582 * encrypted introduction points to the newly allocated
3583 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3584 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3585 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3586 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3587 * and -1 for failure.
3590 rend_parse_v2_service_descriptor(rend_service_descriptor_t
**parsed_out
,
3592 char **intro_points_encrypted_out
,
3593 size_t *intro_points_encrypted_size_out
,
3594 size_t *encoded_size_out
,
3595 const char **next_out
, const char *desc
)
3597 rend_service_descriptor_t
*result
=
3598 tor_malloc_zero(sizeof(rend_service_descriptor_t
));
3599 char desc_hash
[DIGEST_LEN
];
3601 smartlist_t
*tokens
= smartlist_create();
3602 directory_token_t
*tok
;
3603 char secret_id_part
[DIGEST_LEN
];
3604 int i
, version
, num_ok
=1;
3605 smartlist_t
*versions
;
3606 char public_key_hash
[DIGEST_LEN
];
3607 char test_desc_id
[DIGEST_LEN
];
3608 memarea_t
*area
= NULL
;
3610 /* Check if desc starts correctly. */
3611 if (strncmp(desc
, "rendezvous-service-descriptor ",
3612 strlen("rendezvous-service-descriptor "))) {
3613 log_info(LD_REND
, "Descriptor does not start correctly.");
3616 /* Compute descriptor hash for later validation. */
3617 if (router_get_hash_impl(desc
, strlen(desc
), desc_hash
,
3618 "rendezvous-service-descriptor ",
3619 "\nsignature", '\n') < 0) {
3620 log_warn(LD_REND
, "Couldn't compute descriptor hash.");
3623 /* Determine end of string. */
3624 eos
= strstr(desc
, "\nrendezvous-service-descriptor ");
3626 eos
= desc
+ strlen(desc
);
3630 if (strlen(desc
) > REND_DESC_MAX_SIZE
) {
3631 log_warn(LD_REND
, "Descriptor length is %i which exceeds "
3632 "maximum rendezvous descriptor size of %i kilobytes.",
3633 (int)strlen(desc
), REND_DESC_MAX_SIZE
);
3636 /* Tokenize descriptor. */
3637 area
= memarea_new();
3638 if (tokenize_string(area
, desc
, eos
, tokens
, desc_token_table
, 0)) {
3639 log_warn(LD_REND
, "Error tokenizing descriptor.");
3642 /* Set next to next descriptor, if available. */
3644 /* Set length of encoded descriptor. */
3645 *encoded_size_out
= eos
- desc
;
3646 /* Check min allowed length of token list. */
3647 if (smartlist_len(tokens
) < 7) {
3648 log_warn(LD_REND
, "Impossibly short descriptor.");
3651 /* Parse base32-encoded descriptor ID. */
3652 tok
= find_by_keyword(tokens
, R_RENDEZVOUS_SERVICE_DESCRIPTOR
);
3653 tor_assert(tok
== smartlist_get(tokens
, 0));
3654 tor_assert(tok
->n_args
== 1);
3655 if (strlen(tok
->args
[0]) != REND_DESC_ID_V2_LEN_BASE32
||
3656 strspn(tok
->args
[0], BASE32_CHARS
) != REND_DESC_ID_V2_LEN_BASE32
) {
3657 log_warn(LD_REND
, "Invalid descriptor ID: '%s'", tok
->args
[0]);
3660 if (base32_decode(desc_id_out
, DIGEST_LEN
,
3661 tok
->args
[0], REND_DESC_ID_V2_LEN_BASE32
) < 0) {
3662 log_warn(LD_REND
, "Descriptor ID contains illegal characters: %s",
3666 /* Parse descriptor version. */
3667 tok
= find_by_keyword(tokens
, R_VERSION
);
3668 tor_assert(tok
->n_args
== 1);
3670 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &num_ok
, NULL
);
3671 if (result
->version
!= 2 || !num_ok
) {
3672 /* If it's <2, it shouldn't be under this format. If the number
3673 * is greater than 2, we bumped it because we broke backward
3674 * compatibility. See how version numbers in our other formats
3676 log_warn(LD_REND
, "Unrecognized descriptor version: %s",
3677 escaped(tok
->args
[0]));
3680 /* Parse public key. */
3681 tok
= find_by_keyword(tokens
, R_PERMANENT_KEY
);
3682 result
->pk
= tok
->key
;
3683 tok
->key
= NULL
; /* Prevent free */
3684 /* Parse secret ID part. */
3685 tok
= find_by_keyword(tokens
, R_SECRET_ID_PART
);
3686 tor_assert(tok
->n_args
== 1);
3687 if (strlen(tok
->args
[0]) != REND_SECRET_ID_PART_LEN_BASE32
||
3688 strspn(tok
->args
[0], BASE32_CHARS
) != REND_SECRET_ID_PART_LEN_BASE32
) {
3689 log_warn(LD_REND
, "Invalid secret ID part: '%s'", tok
->args
[0]);
3692 if (base32_decode(secret_id_part
, DIGEST_LEN
, tok
->args
[0], 32) < 0) {
3693 log_warn(LD_REND
, "Secret ID part contains illegal characters: %s",
3697 /* Parse publication time -- up-to-date check is done when storing the
3699 tok
= find_by_keyword(tokens
, R_PUBLICATION_TIME
);
3700 tor_assert(tok
->n_args
== 1);
3701 if (parse_iso_time(tok
->args
[0], &result
->timestamp
) < 0) {
3702 log_warn(LD_REND
, "Invalid publication time: '%s'", tok
->args
[0]);
3705 /* Parse protocol versions. */
3706 tok
= find_by_keyword(tokens
, R_PROTOCOL_VERSIONS
);
3707 tor_assert(tok
->n_args
== 1);
3708 versions
= smartlist_create();
3709 smartlist_split_string(versions
, tok
->args
[0], ",",
3710 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
3711 for (i
= 0; i
< smartlist_len(versions
); i
++) {
3712 version
= (int) tor_parse_long(smartlist_get(versions
, i
),
3713 10, 0, INT_MAX
, &num_ok
, NULL
);
3714 if (!num_ok
) /* It's a string; let's ignore it. */
3716 result
->protocols
|= 1 << version
;
3718 SMARTLIST_FOREACH(versions
, char *, cp
, tor_free(cp
));
3719 smartlist_free(versions
);
3720 /* Parse encrypted introduction points. Don't verify. */
3721 tok
= find_opt_by_keyword(tokens
, R_INTRODUCTION_POINTS
);
3723 if (strcmp(tok
->object_type
, "MESSAGE")) {
3724 log_warn(LD_DIR
, "Bad object type: introduction points should be of "
3728 *intro_points_encrypted_out
= tor_memdup(tok
->object_body
,
3730 *intro_points_encrypted_size_out
= tok
->object_size
;
3732 *intro_points_encrypted_out
= NULL
;
3733 *intro_points_encrypted_size_out
= 0;
3735 /* Parse and verify signature. */
3736 tok
= find_by_keyword(tokens
, R_SIGNATURE
);
3737 note_crypto_pk_op(VERIFY_RTR
);
3738 if (check_signature_token(desc_hash
, tok
, result
->pk
, 0,
3739 "v2 rendezvous service descriptor") < 0)
3741 /* Verify that descriptor ID belongs to public key and secret ID part. */
3742 crypto_pk_get_digest(result
->pk
, public_key_hash
);
3743 rend_get_descriptor_id_bytes(test_desc_id
, public_key_hash
,
3745 if (memcmp(desc_id_out
, test_desc_id
, DIGEST_LEN
)) {
3746 log_warn(LD_REND
, "Parsed descriptor ID does not match "
3747 "computed descriptor ID.");
3753 rend_service_descriptor_free(result
);
3757 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3758 smartlist_free(tokens
);
3761 memarea_drop_all(area
);
3762 *parsed_out
= result
;
3768 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
3769 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
3770 * write the result to a newly allocated string that is pointed to by
3771 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
3772 * Return 0 if decryption was successful and -1 otherwise. */
3774 rend_decrypt_introduction_points(char **ipos_decrypted
,
3775 size_t *ipos_decrypted_size
,
3776 const char *descriptor_cookie
,
3777 const char *ipos_encrypted
,
3778 size_t ipos_encrypted_size
)
3780 tor_assert(ipos_encrypted
);
3781 tor_assert(descriptor_cookie
);
3782 if (ipos_encrypted_size
< 2) {
3783 log_warn(LD_REND
, "Size of encrypted introduction points is too "
3787 if (ipos_encrypted
[0] == (int)REND_BASIC_AUTH
) {
3788 char iv
[CIPHER_IV_LEN
], client_id
[REND_BASIC_AUTH_CLIENT_ID_LEN
],
3789 session_key
[CIPHER_KEY_LEN
], *dec
;
3790 int declen
, client_blocks
;
3791 size_t pos
= 0, len
, client_entries_len
;
3792 crypto_digest_env_t
*digest
;
3793 crypto_cipher_env_t
*cipher
;
3794 client_blocks
= (int) ipos_encrypted
[1];
3795 client_entries_len
= client_blocks
* REND_BASIC_AUTH_CLIENT_MULTIPLE
*
3796 REND_BASIC_AUTH_CLIENT_ENTRY_LEN
;
3797 if (ipos_encrypted_size
< 2 + client_entries_len
+ CIPHER_IV_LEN
+ 1) {
3798 log_warn(LD_REND
, "Size of encrypted introduction points is too "
3802 memcpy(iv
, ipos_encrypted
+ 2 + client_entries_len
, CIPHER_IV_LEN
);
3803 digest
= crypto_new_digest_env();
3804 crypto_digest_add_bytes(digest
, descriptor_cookie
, REND_DESC_COOKIE_LEN
);
3805 crypto_digest_add_bytes(digest
, iv
, CIPHER_IV_LEN
);
3806 crypto_digest_get_digest(digest
, client_id
,
3807 REND_BASIC_AUTH_CLIENT_ID_LEN
);
3808 crypto_free_digest_env(digest
);
3809 for (pos
= 2; pos
< 2 + client_entries_len
;
3810 pos
+= REND_BASIC_AUTH_CLIENT_ENTRY_LEN
) {
3811 if (!memcmp(ipos_encrypted
+ pos
, client_id
,
3812 REND_BASIC_AUTH_CLIENT_ID_LEN
)) {
3813 /* Attempt to decrypt introduction points. */
3814 cipher
= crypto_create_init_cipher(descriptor_cookie
, 0);
3815 if (crypto_cipher_decrypt(cipher
, session_key
, ipos_encrypted
3816 + pos
+ REND_BASIC_AUTH_CLIENT_ID_LEN
,
3817 CIPHER_KEY_LEN
) < 0) {
3818 log_warn(LD_REND
, "Could not decrypt session key for client.");
3819 crypto_free_cipher_env(cipher
);
3822 crypto_free_cipher_env(cipher
);
3823 cipher
= crypto_create_init_cipher(session_key
, 0);
3824 len
= ipos_encrypted_size
- 2 - client_entries_len
- CIPHER_IV_LEN
;
3825 dec
= tor_malloc(len
);
3826 declen
= crypto_cipher_decrypt_with_iv(cipher
, dec
, len
,
3827 ipos_encrypted
+ 2 + client_entries_len
,
3828 ipos_encrypted_size
- 2 - client_entries_len
);
3829 crypto_free_cipher_env(cipher
);
3831 log_warn(LD_REND
, "Could not decrypt introduction point string.");
3835 if (memcmpstart(dec
, declen
, "introduction-point ")) {
3836 log_warn(LD_REND
, "Decrypted introduction points don't "
3837 "look like we could parse them.");
3841 *ipos_decrypted
= dec
;
3842 *ipos_decrypted_size
= declen
;
3846 log_warn(LD_REND
, "Could not decrypt introduction points. Please "
3847 "check your authorization for this service!");
3849 } else if (ipos_encrypted
[0] == (int)REND_STEALTH_AUTH
) {
3850 crypto_cipher_env_t
*cipher
;
3853 dec
= tor_malloc_zero(ipos_encrypted_size
- CIPHER_IV_LEN
- 1);
3854 cipher
= crypto_create_init_cipher(descriptor_cookie
, 0);
3855 declen
= crypto_cipher_decrypt_with_iv(cipher
, dec
,
3856 ipos_encrypted_size
-
3859 ipos_encrypted_size
- 1);
3860 crypto_free_cipher_env(cipher
);
3862 log_warn(LD_REND
, "Decrypting introduction points failed!");
3866 *ipos_decrypted
= dec
;
3867 *ipos_decrypted_size
= declen
;
3870 log_warn(LD_REND
, "Unknown authorization type number: %d",
3876 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
3877 * length <b>intro_points_encoded_size</b> and write the result to the
3878 * descriptor in <b>parsed</b>; return the number of successfully parsed
3879 * introduction points or -1 in case of a failure. */
3881 rend_parse_introduction_points(rend_service_descriptor_t
*parsed
,
3882 const char *intro_points_encoded
,
3883 size_t intro_points_encoded_size
)
3885 const char *current_ipo
, *end_of_intro_points
;
3886 smartlist_t
*tokens
;
3887 directory_token_t
*tok
;
3888 rend_intro_point_t
*intro
;
3889 extend_info_t
*info
;
3890 int result
, num_ok
=1;
3891 memarea_t
*area
= NULL
;
3893 /** Function may only be invoked once. */
3894 tor_assert(!parsed
->intro_nodes
);
3895 tor_assert(intro_points_encoded
);
3896 tor_assert(intro_points_encoded_size
> 0);
3897 /* Consider one intro point after the other. */
3898 current_ipo
= intro_points_encoded
;
3899 end_of_intro_points
= intro_points_encoded
+ intro_points_encoded_size
;
3900 tokens
= smartlist_create();
3901 parsed
->intro_nodes
= smartlist_create();
3902 area
= memarea_new();
3904 while (!memcmpstart(current_ipo
, end_of_intro_points
-current_ipo
,
3905 "introduction-point ")) {
3906 /* Determine end of string. */
3907 const char *eos
= tor_memstr(current_ipo
, end_of_intro_points
-current_ipo
,
3908 "\nintroduction-point ");
3910 eos
= end_of_intro_points
;
3913 tor_assert(eos
<= intro_points_encoded
+intro_points_encoded_size
);
3914 /* Free tokens and clear token list. */
3915 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3916 smartlist_clear(tokens
);
3917 memarea_clear(area
);
3918 /* Tokenize string. */
3919 if (tokenize_string(area
, current_ipo
, eos
, tokens
, ipo_token_table
, 0)) {
3920 log_warn(LD_REND
, "Error tokenizing introduction point");
3923 /* Advance to next introduction point, if available. */
3925 /* Check minimum allowed length of introduction point. */
3926 if (smartlist_len(tokens
) < 5) {
3927 log_warn(LD_REND
, "Impossibly short introduction point.");
3930 /* Allocate new intro point and extend info. */
3931 intro
= tor_malloc_zero(sizeof(rend_intro_point_t
));
3932 info
= intro
->extend_info
= tor_malloc_zero(sizeof(extend_info_t
));
3933 /* Parse identifier. */
3934 tok
= find_by_keyword(tokens
, R_IPO_IDENTIFIER
);
3935 if (base32_decode(info
->identity_digest
, DIGEST_LEN
,
3936 tok
->args
[0], REND_INTRO_POINT_ID_LEN_BASE32
) < 0) {
3937 log_warn(LD_REND
, "Identity digest contains illegal characters: %s",
3939 rend_intro_point_free(intro
);
3942 /* Write identifier to nickname. */
3943 info
->nickname
[0] = '$';
3944 base16_encode(info
->nickname
+ 1, sizeof(info
->nickname
) - 1,
3945 info
->identity_digest
, DIGEST_LEN
);
3946 /* Parse IP address. */
3947 tok
= find_by_keyword(tokens
, R_IPO_IP_ADDRESS
);
3948 if (tor_addr_from_str(&info
->addr
, tok
->args
[0])<0) {
3949 log_warn(LD_REND
, "Could not parse introduction point address.");
3950 rend_intro_point_free(intro
);
3953 if (tor_addr_family(&info
->addr
) != AF_INET
) {
3954 log_warn(LD_REND
, "Introduction point address was not ipv4.");
3955 rend_intro_point_free(intro
);
3959 /* Parse onion port. */
3960 tok
= find_by_keyword(tokens
, R_IPO_ONION_PORT
);
3961 info
->port
= (uint16_t) tor_parse_long(tok
->args
[0],10,1,65535,
3963 if (!info
->port
|| !num_ok
) {
3964 log_warn(LD_REND
, "Introduction point onion port %s is invalid",
3965 escaped(tok
->args
[0]));
3966 rend_intro_point_free(intro
);
3969 /* Parse onion key. */
3970 tok
= find_by_keyword(tokens
, R_IPO_ONION_KEY
);
3971 info
->onion_key
= tok
->key
;
3972 tok
->key
= NULL
; /* Prevent free */
3973 /* Parse service key. */
3974 tok
= find_by_keyword(tokens
, R_IPO_SERVICE_KEY
);
3975 intro
->intro_key
= tok
->key
;
3976 tok
->key
= NULL
; /* Prevent free */
3977 /* Add extend info to list of introduction points. */
3978 smartlist_add(parsed
->intro_nodes
, intro
);
3980 result
= smartlist_len(parsed
->intro_nodes
);
3987 /* Free tokens and clear token list. */
3988 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
3989 smartlist_free(tokens
);
3991 memarea_drop_all(area
);
3996 /** Parse the content of a client_key file in <b>ckstr</b> and add
3997 * rend_authorized_client_t's for each parsed client to
3998 * <b>parsed_clients</b>. Return the number of parsed clients as result
3999 * or -1 for failure. */
4001 rend_parse_client_keys(strmap_t
*parsed_clients
, const char *ckstr
)
4004 smartlist_t
*tokens
;
4005 directory_token_t
*tok
;
4006 const char *current_entry
= NULL
;
4007 memarea_t
*area
= NULL
;
4008 if (!ckstr
|| strlen(ckstr
) == 0)
4010 tokens
= smartlist_create();
4011 /* Begin parsing with first entry, skipping comments or whitespace at the
4013 area
= memarea_new();
4014 current_entry
= eat_whitespace(ckstr
);
4015 while (!strcmpstart(current_entry
, "client-name ")) {
4016 rend_authorized_client_t
*parsed_entry
;
4018 char descriptor_cookie_base64
[REND_DESC_COOKIE_LEN_BASE64
+2+1];
4019 char descriptor_cookie_tmp
[REND_DESC_COOKIE_LEN
+2];
4020 /* Determine end of string. */
4021 const char *eos
= strstr(current_entry
, "\nclient-name ");
4023 eos
= current_entry
+ strlen(current_entry
);
4026 /* Free tokens and clear token list. */
4027 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
4028 smartlist_clear(tokens
);
4029 memarea_clear(area
);
4030 /* Tokenize string. */
4031 if (tokenize_string(area
, current_entry
, eos
, tokens
,
4032 client_keys_token_table
, 0)) {
4033 log_warn(LD_REND
, "Error tokenizing client keys file.");
4036 /* Advance to next entry, if available. */
4037 current_entry
= eos
;
4038 /* Check minimum allowed length of token list. */
4039 if (smartlist_len(tokens
) < 2) {
4040 log_warn(LD_REND
, "Impossibly short client key entry.");
4043 /* Parse client name. */
4044 tok
= find_by_keyword(tokens
, C_CLIENT_NAME
);
4045 tor_assert(tok
== smartlist_get(tokens
, 0));
4046 tor_assert(tok
->n_args
== 1);
4048 len
= strlen(tok
->args
[0]);
4049 if (len
< 1 || len
> 19 ||
4050 strspn(tok
->args
[0], REND_LEGAL_CLIENTNAME_CHARACTERS
) != len
) {
4051 log_warn(LD_CONFIG
, "Illegal client name: %s. (Length must be "
4052 "between 1 and 19, and valid characters are "
4053 "[A-Za-z0-9+-_].)", tok
->args
[0]);
4056 /* Check if client name is duplicate. */
4057 if (strmap_get(parsed_clients
, tok
->args
[0])) {
4058 log_warn(LD_CONFIG
, "HiddenServiceAuthorizeClient contains a "
4059 "duplicate client name: '%s'. Ignoring.", tok
->args
[0]);
4062 parsed_entry
= tor_malloc_zero(sizeof(rend_authorized_client_t
));
4063 parsed_entry
->client_name
= tor_strdup(tok
->args
[0]);
4064 strmap_set(parsed_clients
, parsed_entry
->client_name
, parsed_entry
);
4065 /* Parse client key. */
4066 tok
= find_opt_by_keyword(tokens
, C_CLIENT_KEY
);
4068 parsed_entry
->client_key
= tok
->key
;
4069 tok
->key
= NULL
; /* Prevent free */
4072 /* Parse descriptor cookie. */
4073 tok
= find_by_keyword(tokens
, C_DESCRIPTOR_COOKIE
);
4074 tor_assert(tok
->n_args
== 1);
4075 if (strlen(tok
->args
[0]) != REND_DESC_COOKIE_LEN_BASE64
+ 2) {
4076 log_warn(LD_REND
, "Descriptor cookie has illegal length: %s",
4077 escaped(tok
->args
[0]));
4080 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
4081 * because a base64 encoding of length 24 does not fit into 16 bytes in all
4083 if ((base64_decode(descriptor_cookie_tmp
, REND_DESC_COOKIE_LEN
+2,
4084 tok
->args
[0], REND_DESC_COOKIE_LEN_BASE64
+2+1)
4085 != REND_DESC_COOKIE_LEN
)) {
4086 log_warn(LD_REND
, "Descriptor cookie contains illegal characters: "
4087 "%s", descriptor_cookie_base64
);
4090 memcpy(parsed_entry
->descriptor_cookie
, descriptor_cookie_tmp
,
4091 REND_DESC_COOKIE_LEN
);
4093 result
= strmap_size(parsed_clients
);
4098 /* Free tokens and clear token list. */
4099 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_free(t
));
4100 smartlist_free(tokens
);
4102 memarea_drop_all(area
);