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-2016, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to parse and validate router descriptors and directories.
12 #define ROUTERPARSE_PRIVATE
16 #include "circuitstats.h"
20 #include "rendcommon.h"
22 #include "routerlist.h"
24 #include "microdesc.h"
25 #include "networkstatus.h"
27 #include "routerkeys.h"
28 #include "routerparse.h"
29 #include "entrynodes.h"
35 /****************************************************************************/
37 /** Enumeration of possible token types. The ones starting with K_ correspond
38 * to directory 'keywords'. A_ is for an annotation, R or C is related to
39 * hidden services, ERR_ is an error in the tokenizing process, EOF_ is an
40 * end-of-file marker, and NIL_ is used to encode not-a-token.
45 K_DIRECTORY_SIGNATURE
,
46 K_RECOMMENDED_SOFTWARE
,
70 K_NETWORK_STATUS_VERSION
,
89 K_ALLOW_SINGLE_HOP_EXITS
,
94 K_ONION_KEY_CROSSCERT
,
95 K_NTOR_ONION_KEY_CROSSCERT
,
122 K_DIR_KEY_CERTIFICATE_VERSION
,
126 K_DIR_KEY_CERTIFICATION
,
143 K_ADDITIONAL_SIGNATURE
,
154 R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
160 R_INTRODUCTION_POINTS
,
178 #define MIN_ANNOTATION A_PURPOSE
179 #define MAX_ANNOTATION A_UNKNOWN_
181 /** Structure to hold a single directory token.
183 * We parse a directory by breaking it into "tokens", each consisting
184 * of a keyword, a line full of arguments, and a binary object. The
185 * arguments and object are both optional, depending on the keyword
188 * This structure is only allocated in memareas; do not allocate it on
189 * the heap, or token_clear() won't work.
191 typedef struct directory_token_t
{
192 directory_keyword tp
; /**< Type of the token. */
193 int n_args
:30; /**< Number of elements in args */
194 char **args
; /**< Array of arguments from keyword line. */
196 char *object_type
; /**< -----BEGIN [object_type]-----*/
197 size_t object_size
; /**< Bytes in object_body */
198 char *object_body
; /**< Contents of object, base64-decoded. */
200 crypto_pk_t
*key
; /**< For public keys only. Heap-allocated. */
202 char *error
; /**< For ERR_ tokens only. */
205 /* ********************************************************************** */
207 /** We use a table of rules to decide how to parse each token type. */
209 /** Rules for whether the keyword needs an object. */
211 NO_OBJ
, /**< No object, ever. */
212 NEED_OBJ
, /**< Object is required. */
213 NEED_SKEY_1024
,/**< Object is required, and must be a 1024 bit private key */
214 NEED_KEY_1024
, /**< Object is required, and must be a 1024 bit public key */
215 NEED_KEY
, /**< Object is required, and must be a public key. */
216 OBJ_OK
, /**< Object is optional. */
222 /** Determines the parsing rules for a single token type. */
223 typedef struct token_rule_t
{
224 /** The string value of the keyword identifying the type of item. */
226 /** The corresponding directory_keyword enum. */
228 /** Minimum number of arguments for this item */
230 /** Maximum number of arguments for this item */
232 /** If true, we concatenate all arguments for this item into a single
235 /** Requirements on object syntax for this item. */
237 /** Lowest number of times this item may appear in a document. */
239 /** Highest number of times this item may appear in a document. */
241 /** One or more of AT_START/AT_END to limit where the item may appear in a
244 /** True iff this token is an annotation. */
249 * Helper macros to define token tables. 's' is a string, 't' is a
250 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
255 /** Appears to indicate the end of a table. */
256 #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
257 /** An item with no restrictions: used for obsolete document types */
258 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
259 /** An item with no restrictions on multiplicity or location. */
260 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
261 /** An item that must appear exactly once */
262 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
263 /** An item that must appear exactly once, at the start of the document */
264 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
265 /** An item that must appear exactly once, at the end of the document */
266 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
267 /** An item that must appear one or more times */
268 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
269 /** An item that must appear no more than once */
270 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
271 /** An annotation that must appear no more than once */
272 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
274 /* Argument multiplicity: any number of arguments. */
275 #define ARGS 0,INT_MAX,0
276 /* Argument multiplicity: no arguments. */
277 #define NO_ARGS 0,0,0
278 /* Argument multiplicity: concatenate all arguments. */
279 #define CONCAT_ARGS 1,1,1
280 /* Argument multiplicity: at least <b>n</b> arguments. */
281 #define GE(n) n,INT_MAX,0
282 /* Argument multiplicity: exactly <b>n</b> arguments. */
285 /** List of tokens recognized in router descriptors */
286 static token_rule_t routerdesc_token_table
[] = {
287 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
288 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
289 T0N("reject6", K_REJECT6
, ARGS
, NO_OBJ
),
290 T0N("accept6", K_ACCEPT6
, ARGS
, NO_OBJ
),
291 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
292 T01("ipv6-policy", K_IPV6_POLICY
, CONCAT_ARGS
, NO_OBJ
),
293 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
294 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
295 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
296 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
297 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
298 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
299 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
300 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
301 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
302 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
303 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
304 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
305 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
306 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR
, NO_ARGS
, NO_OBJ
),
307 T01("identity-ed25519", K_IDENTITY_ED25519
, NO_ARGS
, NEED_OBJ
),
308 T01("master-key-ed25519", K_MASTER_KEY_ED25519
, GE(1), NO_OBJ
),
309 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519
, GE(1), NO_OBJ
),
310 T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT
, NO_ARGS
, NEED_OBJ
),
311 T01("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT
,
314 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS
, NO_ARGS
, NO_OBJ
),
316 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
317 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
318 T0N("or-address", K_OR_ADDRESS
, GE(1), NO_OBJ
),
320 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
321 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
322 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
323 T01("tunnelled-dir-server",K_DIR_TUNNELLED
, NO_ARGS
, NO_OBJ
),
328 /** List of tokens recognized in extra-info documents. */
329 static token_rule_t extrainfo_token_table
[] = {
330 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
331 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
332 T01("identity-ed25519", K_IDENTITY_ED25519
, NO_ARGS
, NEED_OBJ
),
333 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519
, GE(1), NO_OBJ
),
334 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
335 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
336 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
337 T01("dirreq-stats-end", K_DIRREQ_END
, ARGS
, NO_OBJ
),
338 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS
, ARGS
, NO_OBJ
),
339 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS
, ARGS
, NO_OBJ
),
340 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS
, ARGS
, NO_OBJ
),
341 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS
, ARGS
, NO_OBJ
),
342 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE
, ARGS
, NO_OBJ
),
343 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE
, ARGS
, NO_OBJ
),
344 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP
, ARGS
, NO_OBJ
),
345 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP
, ARGS
, NO_OBJ
),
346 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR
, ARGS
, NO_OBJ
),
347 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR
, ARGS
, NO_OBJ
),
348 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN
, ARGS
, NO_OBJ
),
349 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN
, ARGS
, NO_OBJ
),
350 T01("entry-stats-end", K_ENTRY_END
, ARGS
, NO_OBJ
),
351 T01("entry-ips", K_ENTRY_IPS
, ARGS
, NO_OBJ
),
352 T01("cell-stats-end", K_CELL_END
, ARGS
, NO_OBJ
),
353 T01("cell-processed-cells", K_CELL_PROCESSED
, ARGS
, NO_OBJ
),
354 T01("cell-queued-cells", K_CELL_QUEUED
, ARGS
, NO_OBJ
),
355 T01("cell-time-in-queue", K_CELL_TIME
, ARGS
, NO_OBJ
),
356 T01("cell-circuits-per-decile", K_CELL_CIRCS
, ARGS
, NO_OBJ
),
357 T01("exit-stats-end", K_EXIT_END
, ARGS
, NO_OBJ
),
358 T01("exit-kibibytes-written", K_EXIT_WRITTEN
, ARGS
, NO_OBJ
),
359 T01("exit-kibibytes-read", K_EXIT_READ
, ARGS
, NO_OBJ
),
360 T01("exit-streams-opened", K_EXIT_OPENED
, ARGS
, NO_OBJ
),
362 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
367 /** List of tokens recognized in the body part of v3 networkstatus
369 static token_rule_t rtrstatus_token_table
[] = {
370 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
371 T1( "r", K_R
, GE(7), NO_OBJ
),
372 T0N("a", K_A
, GE(1), NO_OBJ
),
373 T1( "s", K_S
, ARGS
, NO_OBJ
),
374 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
375 T01("w", K_W
, ARGS
, NO_OBJ
),
376 T0N("m", K_M
, CONCAT_ARGS
, NO_OBJ
),
377 T0N("id", K_ID
, GE(2), NO_OBJ
),
378 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
382 /** List of tokens common to V3 authority certificates and V3 consensuses. */
383 #define CERTIFICATE_MEMBERS \
384 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
386 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
387 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
388 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
389 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
390 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
391 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
392 NO_ARGS, NEED_OBJ), \
393 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
395 /** List of tokens recognized in V3 authority certificates. */
396 static token_rule_t dir_key_certificate_table
[] = {
398 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
402 /** List of tokens recognized in rendezvous service descriptors */
403 static token_rule_t desc_token_table
[] = {
404 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
406 T1("version", R_VERSION
, EQ(1), NO_OBJ
),
407 T1("permanent-key", R_PERMANENT_KEY
, NO_ARGS
, NEED_KEY_1024
),
408 T1("secret-id-part", R_SECRET_ID_PART
, EQ(1), NO_OBJ
),
409 T1("publication-time", R_PUBLICATION_TIME
, CONCAT_ARGS
, NO_OBJ
),
410 T1("protocol-versions", R_PROTOCOL_VERSIONS
, EQ(1), NO_OBJ
),
411 T01("introduction-points", R_INTRODUCTION_POINTS
, NO_ARGS
, NEED_OBJ
),
412 T1_END("signature", R_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
416 /** List of tokens recognized in the (encrypted) list of introduction points of
417 * rendezvous service descriptors */
418 static token_rule_t ipo_token_table
[] = {
419 T1_START("introduction-point", R_IPO_IDENTIFIER
, EQ(1), NO_OBJ
),
420 T1("ip-address", R_IPO_IP_ADDRESS
, EQ(1), NO_OBJ
),
421 T1("onion-port", R_IPO_ONION_PORT
, EQ(1), NO_OBJ
),
422 T1("onion-key", R_IPO_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
423 T1("service-key", R_IPO_SERVICE_KEY
, NO_ARGS
, NEED_KEY_1024
),
427 /** List of tokens recognized in the (possibly encrypted) list of introduction
428 * points of rendezvous service descriptors */
429 static token_rule_t client_keys_token_table
[] = {
430 T1_START("client-name", C_CLIENT_NAME
, CONCAT_ARGS
, NO_OBJ
),
431 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE
, EQ(1), NO_OBJ
),
432 T01("client-key", C_CLIENT_KEY
, NO_ARGS
, NEED_SKEY_1024
),
436 /** List of tokens recognized in V3 networkstatus votes. */
437 static token_rule_t networkstatus_token_table
[] = {
438 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
440 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
441 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
442 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
443 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
444 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
445 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
446 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
447 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
448 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
449 T0N("package", K_PACKAGE
, CONCAT_ARGS
, NO_OBJ
),
453 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
454 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
455 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
456 T01("legacy-dir-key", K_LEGACY_DIR_KEY
, GE(1), NO_OBJ
),
457 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
458 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
459 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
460 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
465 /** List of tokens recognized in V3 networkstatus consensuses. */
466 static token_rule_t networkstatus_consensus_token_table
[] = {
467 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
469 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
470 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
471 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
472 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
473 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
475 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
477 T1N("dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
478 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
479 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
481 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
483 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
484 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
485 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
486 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
491 /** List of tokens recognized in the footer of v1 directory footers. */
492 static token_rule_t networkstatus_vote_footer_token_table
[] = {
493 T01("directory-footer", K_DIRECTORY_FOOTER
, NO_ARGS
, NO_OBJ
),
494 T01("bandwidth-weights", K_BW_WEIGHTS
, ARGS
, NO_OBJ
),
495 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
499 /** List of tokens recognized in detached networkstatus signature documents. */
500 static token_rule_t networkstatus_detached_signature_token_table
[] = {
501 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
502 T("additional-digest", K_ADDITIONAL_DIGEST
,GE(3), NO_OBJ
),
503 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
504 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
505 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
506 T("additional-signature", K_ADDITIONAL_SIGNATURE
, GE(4), NEED_OBJ
),
507 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
511 /** List of tokens recognized in microdescriptors */
512 static token_rule_t microdesc_token_table
[] = {
513 T1_START("onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
514 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
515 T0N("id", K_ID
, GE(2), NO_OBJ
),
516 T0N("a", K_A
, GE(1), NO_OBJ
),
517 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
518 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
519 T01("p6", K_P6
, CONCAT_ARGS
, NO_OBJ
),
520 A01("@last-listed", A_LAST_LISTED
, CONCAT_ARGS
, NO_OBJ
),
526 /* static function prototypes */
527 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
528 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
,
530 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
532 static int router_get_hash_impl_helper(const char *s
, size_t s_len
,
533 const char *start_str
,
534 const char *end_str
, char end_c
,
535 const char **start_out
, const char **end_out
);
536 static int router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
537 const char *start_str
, const char *end_str
,
539 digest_algorithm_t alg
);
540 static int router_get_hashes_impl(const char *s
, size_t s_len
,
541 common_digests_t
*digests
,
542 const char *start_str
, const char *end_str
,
544 static void token_clear(directory_token_t
*tok
);
545 static smartlist_t
*find_all_by_keyword(smartlist_t
*s
, directory_keyword k
);
546 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
547 static directory_token_t
*find_by_keyword_(smartlist_t
*s
,
548 directory_keyword keyword
,
549 const char *keyword_str
);
550 #define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword)
551 static directory_token_t
*find_opt_by_keyword(smartlist_t
*s
,
552 directory_keyword keyword
);
554 #define TS_ANNOTATIONS_OK 1
556 #define TS_NO_NEW_ANNOTATIONS 4
557 static int tokenize_string(memarea_t
*area
,
558 const char *start
, const char *end
,
562 static directory_token_t
*get_next_token(memarea_t
*area
,
565 token_rule_t
*table
);
566 #define CST_CHECK_AUTHORITY (1<<0)
567 #define CST_NO_CHECK_OBJTYPE (1<<1)
568 static int check_signature_token(const char *digest
,
570 directory_token_t
*tok
,
573 const char *doctype
);
575 #undef DEBUG_AREA_ALLOC
577 #ifdef DEBUG_AREA_ALLOC
578 #define DUMP_AREA(a,name) STMT_BEGIN \
579 size_t alloc=0, used=0; \
580 memarea_get_stats((a),&alloc,&used); \
581 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
582 name, (unsigned long)alloc, (unsigned long)used); \
585 #define DUMP_AREA(a,name) STMT_NIL
588 /** Last time we dumped a descriptor to disk. */
589 static time_t last_desc_dumped
= 0;
591 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
592 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
593 * than one descriptor to disk per minute. If there is already such a
594 * file in the data directory, overwrite it. */
596 dump_desc(const char *desc
, const char *type
)
598 time_t now
= time(NULL
);
601 if (!last_desc_dumped
|| last_desc_dumped
+ 60 < now
) {
602 char *debugfile
= get_datadir_fname("unparseable-desc");
603 size_t filelen
= 50 + strlen(type
) + strlen(desc
);
604 char *content
= tor_malloc_zero(filelen
);
605 tor_snprintf(content
, filelen
, "Unable to parse descriptor of type "
606 "%s:\n%s", type
, desc
);
607 write_str_to_file(debugfile
, content
, 1);
608 log_info(LD_DIR
, "Unable to parse descriptor of type %s. See file "
609 "unparseable-desc in data directory for details.", type
);
612 last_desc_dumped
= now
;
616 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
617 * <b>s</b>. Return 0 on success, -1 on failure.
620 router_get_dir_hash(const char *s
, char *digest
)
622 return router_get_hash_impl(s
, strlen(s
), digest
,
623 "signed-directory","\ndirectory-signature",'\n',
627 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
628 * <b>s</b>. Return 0 on success, -1 on failure.
631 router_get_router_hash(const char *s
, size_t s_len
, char *digest
)
633 return router_get_hash_impl(s
, s_len
, digest
,
634 "router ","\nrouter-signature", '\n',
638 /** Set <b>digests</b> to all the digests of the consensus document in
641 router_get_networkstatus_v3_hashes(const char *s
, common_digests_t
*digests
)
643 return router_get_hashes_impl(s
,strlen(s
),digests
,
644 "network-status-version",
645 "\ndirectory-signature",
649 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
650 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
652 router_get_extrainfo_hash(const char *s
, size_t s_len
, char *digest
)
654 return router_get_hash_impl(s
, s_len
, digest
, "extra-info",
655 "\nrouter-signature",'\n', DIGEST_SHA1
);
658 /** Helper: used to generate signatures for routers, directories and
659 * network-status objects. Given a <b>digest_len</b>-byte digest in
660 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
661 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
662 * and return the new signature on success or NULL on failure.
665 router_get_dirobj_signature(const char *digest
,
667 const crypto_pk_t
*private_key
)
674 /* overestimate of BEGIN/END lines total len. */
675 #define BEGIN_END_OVERHEAD_LEN 64
677 keysize
= crypto_pk_keysize(private_key
);
678 signature
= tor_malloc(keysize
);
679 siglen
= crypto_pk_private_sign(private_key
, signature
, keysize
,
682 log_warn(LD_BUG
,"Couldn't sign digest.");
686 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
687 buf_len
= (siglen
* 2) + BEGIN_END_OVERHEAD_LEN
;
688 buf
= tor_malloc(buf_len
);
690 if (strlcpy(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
694 if (base64_encode(buf
+i
, buf_len
-i
, signature
, siglen
,
695 BASE64_ENCODE_MULTILINE
) < 0) {
696 log_warn(LD_BUG
,"couldn't base64-encode signature");
700 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
707 log_warn(LD_BUG
,"tried to exceed string length.");
714 /** Helper: used to generate signatures for routers, directories and
715 * network-status objects. Given a digest in <b>digest</b> and a secret
716 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
717 * surround it with -----BEGIN/END----- pairs, and write it to the
718 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
722 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
723 size_t digest_len
, crypto_pk_t
*private_key
)
725 size_t sig_len
, s_len
;
726 char *sig
= router_get_dirobj_signature(digest
, digest_len
, private_key
);
728 log_warn(LD_BUG
, "No signature generated");
731 sig_len
= strlen(sig
);
733 if (sig_len
+ s_len
+ 1 > buf_len
) {
734 log_warn(LD_BUG
, "Not enough room for signature");
738 memcpy(buf
+s_len
, sig
, sig_len
+1);
743 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
744 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
745 * entries. Else, return VS_OLD if every member of
746 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
747 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
748 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
749 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
750 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
753 * (versionlist is a comma-separated list of version strings,
754 * optionally prefixed with "Tor". Versions that can't be parsed are
758 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
760 tor_version_t mine
, other
;
761 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
762 found_any_in_series
= 0, r
, same
;
763 version_status_t ret
= VS_UNRECOMMENDED
;
764 smartlist_t
*version_sl
;
766 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
767 myversion
, versionlist
);
769 if (tor_version_parse(myversion
, &mine
)) {
770 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
773 version_sl
= smartlist_new();
774 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
776 if (!strlen(versionlist
)) { /* no authorities cared or agreed */
781 SMARTLIST_FOREACH_BEGIN(version_sl
, const char *, cp
) {
782 if (!strcmpstart(cp
, "Tor "))
785 if (tor_version_parse(cp
, &other
)) {
786 /* Couldn't parse other; it can't be a match. */
788 same
= tor_version_same_series(&mine
, &other
);
790 found_any_in_series
= 1;
791 r
= tor_version_compare(&mine
, &other
);
793 ret
= VS_RECOMMENDED
;
798 found_newer_in_series
= 1;
803 } SMARTLIST_FOREACH_END(cp
);
805 /* We didn't find the listed version. Is it new or old? */
806 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
807 ret
= VS_NEW_IN_SERIES
;
808 } else if (found_newer
&& !found_older
) {
810 } else if (found_older
&& !found_newer
) {
813 ret
= VS_UNRECOMMENDED
;
817 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
818 smartlist_free(version_sl
);
822 /** Return true iff <b>key</b> is allowed to sign directories.
825 dir_signing_key_is_trusted(crypto_pk_t
*key
)
827 char digest
[DIGEST_LEN
];
829 if (crypto_pk_get_digest(key
, digest
) < 0) {
830 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
833 if (!router_digest_is_trusted_dir(digest
)) {
834 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
840 /** Check whether the object body of the token in <b>tok</b> has a good
841 * signature for <b>digest</b> using key <b>pkey</b>. If
842 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
843 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
844 * the object type of the signature object. Use <b>doctype</b> as the type of
845 * the document when generating log messages. Return 0 on success, negative
849 check_signature_token(const char *digest
,
851 directory_token_t
*tok
,
858 const int check_authority
= (flags
& CST_CHECK_AUTHORITY
);
859 const int check_objtype
= ! (flags
& CST_NO_CHECK_OBJTYPE
);
866 if (check_authority
&& !dir_signing_key_is_trusted(pkey
)) {
867 log_warn(LD_DIR
, "Key on %s did not come from an authority; rejecting",
873 if (strcmp(tok
->object_type
, "SIGNATURE")) {
874 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
879 keysize
= crypto_pk_keysize(pkey
);
880 signed_digest
= tor_malloc(keysize
);
881 if (crypto_pk_public_checksig(pkey
, signed_digest
, keysize
,
882 tok
->object_body
, tok
->object_size
)
884 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
885 tor_free(signed_digest
);
888 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
889 // hex_str(signed_digest,4));
890 if (tor_memneq(digest
, signed_digest
, digest_len
)) {
891 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
892 tor_free(signed_digest
);
895 tor_free(signed_digest
);
899 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
900 * or to the first of the annotations proceeding the next router or
901 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
902 * we found an extrainfo, or false if found a router. Do not scan beyond
903 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
905 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
907 int *is_extrainfo_out
)
909 const char *annotations
= NULL
;
910 const char *s
= *s_ptr
;
912 s
= eat_whitespace_eos(s
, eos
);
914 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
915 /* We're at the start of a line. */
916 tor_assert(*s
!= '\n');
918 if (*s
== '@' && !annotations
) {
920 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
921 *s_ptr
= annotations
? annotations
: s
;
922 *is_extrainfo_out
= 0;
924 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
925 *s_ptr
= annotations
? annotations
: s
;
926 *is_extrainfo_out
= 1;
930 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
932 s
= eat_whitespace_eos(s
, eos
);
937 /** Given a string *<b>s</b> containing a concatenated sequence of router
938 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
939 * them and stores the result in <b>dest</b>. All routers are marked running
940 * and valid. Advances *s to a point immediately following the last router
941 * entry. Ignore any trailing router entries that are not complete.
943 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
944 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
945 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
947 * Returns 0 on success and -1 on failure. Adds a digest to
948 * <b>invalid_digests_out</b> for every entry that was unparseable or
949 * invalid. (This may cause duplicate entries.)
952 router_parse_list_from_string(const char **s
, const char *eos
,
954 saved_location_t saved_location
,
956 int allow_annotations
,
957 const char *prepend_annotations
,
958 smartlist_t
*invalid_digests_out
)
960 routerinfo_t
*router
;
961 extrainfo_t
*extrainfo
;
962 signed_descriptor_t
*signed_desc
= NULL
;
964 const char *end
, *start
;
973 eos
= *s
+ strlen(*s
);
975 tor_assert(eos
>= *s
);
978 char raw_digest
[DIGEST_LEN
];
979 int have_raw_digest
= 0;
981 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
984 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
986 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
988 end
+= strlen("\n-----END SIGNATURE-----\n");
995 if (have_extrainfo
&& want_extrainfo
) {
996 routerlist_t
*rl
= router_get_routerlist();
997 have_raw_digest
= router_get_extrainfo_hash(*s
, end
-*s
, raw_digest
) == 0;
998 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
999 saved_location
!= SAVED_IN_CACHE
,
1000 rl
->identity_map
, &dl_again
);
1002 signed_desc
= &extrainfo
->cache_info
;
1005 } else if (!have_extrainfo
&& !want_extrainfo
) {
1006 have_raw_digest
= router_get_router_hash(*s
, end
-*s
, raw_digest
) == 0;
1007 router
= router_parse_entry_from_string(*s
, end
,
1008 saved_location
!= SAVED_IN_CACHE
,
1010 prepend_annotations
, &dl_again
);
1012 log_debug(LD_DIR
, "Read router '%s', purpose '%s'",
1013 router_describe(router
),
1014 router_purpose_to_string(router
->purpose
));
1015 signed_desc
= &router
->cache_info
;
1019 if (! elt
&& ! dl_again
&& have_raw_digest
&& invalid_digests_out
) {
1020 smartlist_add(invalid_digests_out
, tor_memdup(raw_digest
, DIGEST_LEN
));
1026 if (saved_location
!= SAVED_NOWHERE
) {
1027 tor_assert(signed_desc
);
1028 signed_desc
->saved_location
= saved_location
;
1029 signed_desc
->saved_offset
= *s
- start
;
1032 smartlist_add(dest
, elt
);
1038 /* For debugging: define to count every descriptor digest we've seen so we
1039 * know if we need to try harder to avoid duplicate verifies. */
1040 #undef COUNT_DISTINCT_DIGESTS
1042 #ifdef COUNT_DISTINCT_DIGESTS
1043 static digestmap_t
*verified_digests
= NULL
;
1046 /** Log the total count of the number of distinct router digests we've ever
1047 * verified. When compared to the number of times we've verified routerdesc
1048 * signatures <i>in toto</i>, this will tell us if we're doing too much
1049 * multiple-verification. */
1051 dump_distinct_digest_count(int severity
)
1053 #ifdef COUNT_DISTINCT_DIGESTS
1054 if (!verified_digests
)
1055 verified_digests
= digestmap_new();
1056 tor_log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
1057 digestmap_size(verified_digests
));
1059 (void)severity
; /* suppress "unused parameter" warning */
1063 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1064 * with at least one argument (use GE(1) in setup). If found, store
1065 * address and port number to <b>addr_out</b> and
1066 * <b>port_out</b>. Return number of OR ports found. */
1068 find_single_ipv6_orport(const smartlist_t
*list
,
1069 tor_addr_t
*addr_out
,
1073 tor_assert(list
!= NULL
);
1074 tor_assert(addr_out
!= NULL
);
1075 tor_assert(port_out
!= NULL
);
1077 SMARTLIST_FOREACH_BEGIN(list
, directory_token_t
*, t
) {
1080 uint16_t port_min
, port_max
;
1081 tor_assert(t
->n_args
>= 1);
1082 /* XXXX Prop186 the full spec allows much more than this. */
1083 if (tor_addr_parse_mask_ports(t
->args
[0], 0,
1084 &a
, &bits
, &port_min
,
1085 &port_max
) == AF_INET6
&&
1087 port_min
== port_max
) {
1088 /* Okay, this is one we can understand. Use it and ignore
1089 any potential more addresses in list. */
1090 tor_addr_copy(addr_out
, &a
);
1091 *port_out
= port_min
;
1095 } SMARTLIST_FOREACH_END(t
);
1100 /** Helper function: reads a single router entry from *<b>s</b> ...
1101 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1102 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1103 * s through end into the signed_descriptor_body of the resulting
1106 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1108 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1109 * before the router; if it's false, reject the router if it's annotated. If
1110 * <b>prepend_annotations</b> is set, it should contain some annotations:
1111 * append them to the front of the router before parsing it, and keep them
1112 * around when caching the router.
1114 * Only one of allow_annotations and prepend_annotations may be set.
1116 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1117 * if it's okay to try to download a descriptor with this same digest again,
1118 * and 0 if it isn't. (It might not be okay to download it again if part of
1119 * the part covered by the digest is invalid.)
1122 router_parse_entry_from_string(const char *s
, const char *end
,
1123 int cache_copy
, int allow_annotations
,
1124 const char *prepend_annotations
,
1125 int *can_dl_again_out
)
1127 routerinfo_t
*router
= NULL
;
1129 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1130 directory_token_t
*tok
;
1132 const char *start_of_annotations
, *cp
, *s_dup
= s
;
1133 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1135 memarea_t
*area
= NULL
;
1136 tor_cert_t
*ntor_cc_cert
= NULL
;
1137 /* Do not set this to '1' until we have parsed everything that we intend to
1138 * parse that's covered by the hash. */
1139 int can_dl_again
= 0;
1141 tor_assert(!allow_annotations
|| !prepend_annotations
);
1144 end
= s
+ strlen(s
);
1147 /* point 'end' to a point immediately after the final newline. */
1148 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1151 area
= memarea_new();
1152 tokens
= smartlist_new();
1153 if (prepend_annotations
) {
1154 if (tokenize_string(area
,prepend_annotations
,NULL
,tokens
,
1155 routerdesc_token_table
,TS_NOCHECK
)) {
1156 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1161 start_of_annotations
= s
;
1162 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1164 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1165 log_warn(LD_DIR
, "No router keyword found.");
1172 if (start_of_annotations
!= s
) { /* We have annotations */
1173 if (allow_annotations
) {
1174 if (tokenize_string(area
,start_of_annotations
,s
,tokens
,
1175 routerdesc_token_table
,TS_NOCHECK
)) {
1176 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1180 log_warn(LD_DIR
, "Found unexpected annotations on router descriptor not "
1181 "loaded from disk. Dropping it.");
1186 if (router_get_router_hash(s
, end
- s
, digest
) < 0) {
1187 log_warn(LD_DIR
, "Couldn't compute router hash.");
1192 if (allow_annotations
)
1193 flags
|= TS_ANNOTATIONS_OK
;
1194 if (prepend_annotations
)
1195 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1197 if (tokenize_string(area
,s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1198 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1203 if (smartlist_len(tokens
) < 2) {
1204 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1208 tok
= find_by_keyword(tokens
, K_ROUTER
);
1209 const int router_token_pos
= smartlist_pos(tokens
, tok
);
1210 tor_assert(tok
->n_args
>= 5);
1212 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1213 router
->cert_expiration_time
= TIME_MAX
;
1214 router
->cache_info
.routerlist_index
= -1;
1215 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1216 router
->cache_info
.signed_descriptor_len
= end
-s
;
1218 size_t len
= router
->cache_info
.signed_descriptor_len
+
1219 router
->cache_info
.annotations_len
;
1221 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1222 if (prepend_annotations
) {
1223 memcpy(cp
, prepend_annotations
, prepend_len
);
1226 /* This assertion will always succeed.
1227 * len == signed_desc_len + annotations_len
1228 * == end-s + s-start_of_annotations + prepend_len
1229 * == end-start_of_annotations + prepend_len
1230 * We already wrote prepend_len bytes into the buffer; now we're
1231 * writing end-start_of_annotations -NM. */
1232 tor_assert(cp
+(end
-start_of_annotations
) ==
1233 router
->cache_info
.signed_descriptor_body
+len
);
1234 memcpy(cp
, start_of_annotations
, end
-start_of_annotations
);
1235 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1236 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1238 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1240 router
->nickname
= tor_strdup(tok
->args
[0]);
1241 if (!is_legal_nickname(router
->nickname
)) {
1242 log_warn(LD_DIR
,"Router nickname is invalid");
1245 if (!tor_inet_aton(tok
->args
[1], &in
)) {
1246 log_warn(LD_DIR
,"Router address is not an IP address.");
1249 router
->addr
= ntohl(in
.s_addr
);
1252 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,&ok
,NULL
);
1254 log_warn(LD_DIR
,"Invalid OR port %s", escaped(tok
->args
[2]));
1258 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,&ok
,NULL
);
1260 log_warn(LD_DIR
,"Invalid dir port %s", escaped(tok
->args
[4]));
1264 tok
= find_by_keyword(tokens
, K_BANDWIDTH
);
1265 tor_assert(tok
->n_args
>= 3);
1266 router
->bandwidthrate
= (int)
1267 tor_parse_long(tok
->args
[0],10,1,INT_MAX
,&ok
,NULL
);
1270 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1271 escaped(tok
->args
[0]));
1274 router
->bandwidthburst
=
1275 (int) tor_parse_long(tok
->args
[1],10,0,INT_MAX
,&ok
,NULL
);
1277 log_warn(LD_DIR
, "Invalid bandwidthburst %s", escaped(tok
->args
[1]));
1280 router
->bandwidthcapacity
= (int)
1281 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,&ok
,NULL
);
1283 log_warn(LD_DIR
, "Invalid bandwidthcapacity %s", escaped(tok
->args
[1]));
1287 if ((tok
= find_opt_by_keyword(tokens
, A_PURPOSE
))) {
1288 tor_assert(tok
->n_args
);
1289 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1291 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1293 router
->cache_info
.send_unencrypted
=
1294 (router
->purpose
== ROUTER_PURPOSE_GENERAL
) ? 1 : 0;
1296 if ((tok
= find_opt_by_keyword(tokens
, K_UPTIME
))) {
1297 tor_assert(tok
->n_args
>= 1);
1298 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,&ok
,NULL
);
1300 log_warn(LD_DIR
, "Invalid uptime %s", escaped(tok
->args
[0]));
1305 if ((tok
= find_opt_by_keyword(tokens
, K_HIBERNATING
))) {
1306 tor_assert(tok
->n_args
>= 1);
1307 router
->is_hibernating
1308 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1311 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1312 tor_assert(tok
->n_args
== 1);
1313 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1316 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
1317 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
1319 "Relay's onion key had invalid exponent.");
1322 router
->onion_pkey
= tok
->key
;
1323 tok
->key
= NULL
; /* Prevent free */
1325 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
1326 curve25519_public_key_t k
;
1327 tor_assert(tok
->n_args
>= 1);
1328 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
1329 log_warn(LD_DIR
, "Bogus ntor-onion-key in routerinfo");
1332 router
->onion_curve25519_pkey
=
1333 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
1336 tok
= find_by_keyword(tokens
, K_SIGNING_KEY
);
1337 router
->identity_pkey
= tok
->key
;
1338 tok
->key
= NULL
; /* Prevent free */
1339 if (crypto_pk_get_digest(router
->identity_pkey
,
1340 router
->cache_info
.identity_digest
)) {
1341 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1345 directory_token_t
*ed_sig_tok
, *ed_cert_tok
, *cc_tap_tok
, *cc_ntor_tok
,
1347 ed_sig_tok
= find_opt_by_keyword(tokens
, K_ROUTER_SIG_ED25519
);
1348 ed_cert_tok
= find_opt_by_keyword(tokens
, K_IDENTITY_ED25519
);
1349 master_key_tok
= find_opt_by_keyword(tokens
, K_MASTER_KEY_ED25519
);
1350 cc_tap_tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_CROSSCERT
);
1351 cc_ntor_tok
= find_opt_by_keyword(tokens
, K_NTOR_ONION_KEY_CROSSCERT
);
1352 int n_ed_toks
= !!ed_sig_tok
+ !!ed_cert_tok
+
1353 !!cc_tap_tok
+ !!cc_ntor_tok
;
1354 if ((n_ed_toks
!= 0 && n_ed_toks
!= 4) ||
1355 (n_ed_toks
== 4 && !router
->onion_curve25519_pkey
)) {
1356 log_warn(LD_DIR
, "Router descriptor with only partial ed25519/"
1357 "cross-certification support");
1360 if (master_key_tok
&& !ed_sig_tok
) {
1361 log_warn(LD_DIR
, "Router descriptor has ed25519 master key but no "
1366 tor_assert(ed_cert_tok
&& cc_tap_tok
&& cc_ntor_tok
);
1367 const int ed_cert_token_pos
= smartlist_pos(tokens
, ed_cert_tok
);
1368 if (ed_cert_token_pos
== -1 || router_token_pos
== -1 ||
1369 (ed_cert_token_pos
!= router_token_pos
+ 1 &&
1370 ed_cert_token_pos
!= router_token_pos
- 1)) {
1371 log_warn(LD_DIR
, "Ed25519 certificate in wrong position");
1374 if (ed_sig_tok
!= smartlist_get(tokens
, smartlist_len(tokens
)-2)) {
1375 log_warn(LD_DIR
, "Ed25519 signature in wrong position");
1378 if (strcmp(ed_cert_tok
->object_type
, "ED25519 CERT")) {
1379 log_warn(LD_DIR
, "Wrong object type on identity-ed25519 in decriptor");
1382 if (strcmp(cc_ntor_tok
->object_type
, "ED25519 CERT")) {
1383 log_warn(LD_DIR
, "Wrong object type on ntor-onion-key-crosscert "
1387 if (strcmp(cc_tap_tok
->object_type
, "CROSSCERT")) {
1388 log_warn(LD_DIR
, "Wrong object type on onion-key-crosscert "
1392 if (strcmp(cc_ntor_tok
->args
[0], "0") &&
1393 strcmp(cc_ntor_tok
->args
[0], "1")) {
1394 log_warn(LD_DIR
, "Bad sign bit on ntor-onion-key-crosscert");
1397 int ntor_cc_sign_bit
= !strcmp(cc_ntor_tok
->args
[0], "1");
1399 uint8_t d256
[DIGEST256_LEN
];
1400 const char *signed_start
, *signed_end
;
1401 tor_cert_t
*cert
= tor_cert_parse(
1402 (const uint8_t*)ed_cert_tok
->object_body
,
1403 ed_cert_tok
->object_size
);
1405 log_warn(LD_DIR
, "Couldn't parse ed25519 cert");
1408 /* makes sure it gets freed. */
1409 router
->cache_info
.signing_key_cert
= cert
;
1411 if (cert
->cert_type
!= CERT_TYPE_ID_SIGNING
||
1412 ! cert
->signing_key_included
) {
1413 log_warn(LD_DIR
, "Invalid form for ed25519 cert");
1417 if (master_key_tok
) {
1418 /* This token is optional, but if it's present, it must match
1419 * the signature in the signing cert, or supplant it. */
1420 tor_assert(master_key_tok
->n_args
>= 1);
1421 ed25519_public_key_t pkey
;
1422 if (ed25519_public_from_base64(&pkey
, master_key_tok
->args
[0])<0) {
1423 log_warn(LD_DIR
, "Can't parse ed25519 master key");
1427 if (fast_memneq(&cert
->signing_key
.pubkey
,
1428 pkey
.pubkey
, ED25519_PUBKEY_LEN
)) {
1429 log_warn(LD_DIR
, "Ed25519 master key does not match "
1430 "key in certificate");
1434 ntor_cc_cert
= tor_cert_parse((const uint8_t*)cc_ntor_tok
->object_body
,
1435 cc_ntor_tok
->object_size
);
1436 if (!ntor_cc_cert
) {
1437 log_warn(LD_DIR
, "Couldn't parse ntor-onion-key-crosscert cert");
1440 if (ntor_cc_cert
->cert_type
!= CERT_TYPE_ONION_ID
||
1441 ! ed25519_pubkey_eq(&ntor_cc_cert
->signed_key
, &cert
->signing_key
)) {
1442 log_warn(LD_DIR
, "Invalid contents for ntor-onion-key-crosscert cert");
1446 ed25519_public_key_t ntor_cc_pk
;
1447 if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk
,
1448 router
->onion_curve25519_pkey
,
1449 ntor_cc_sign_bit
)<0) {
1450 log_warn(LD_DIR
, "Error converting onion key to ed25519");
1454 if (router_get_hash_impl_helper(s
, end
-s
, "router ",
1455 "\nrouter-sig-ed25519",
1456 ' ', &signed_start
, &signed_end
) < 0) {
1457 log_warn(LD_DIR
, "Can't find ed25519-signed portion of descriptor");
1460 crypto_digest_t
*d
= crypto_digest256_new(DIGEST_SHA256
);
1461 crypto_digest_add_bytes(d
, ED_DESC_SIGNATURE_PREFIX
,
1462 strlen(ED_DESC_SIGNATURE_PREFIX
));
1463 crypto_digest_add_bytes(d
, signed_start
, signed_end
-signed_start
);
1464 crypto_digest_get_digest(d
, (char*)d256
, sizeof(d256
));
1465 crypto_digest_free(d
);
1467 ed25519_checkable_t check
[3];
1469 if (tor_cert_get_checkable_sig(&check
[0], cert
, NULL
) < 0) {
1470 log_err(LD_BUG
, "Couldn't create 'checkable' for cert.");
1473 if (tor_cert_get_checkable_sig(&check
[1],
1474 ntor_cc_cert
, &ntor_cc_pk
) < 0) {
1475 log_err(LD_BUG
, "Couldn't create 'checkable' for ntor_cc_cert.");
1479 if (ed25519_signature_from_base64(&check
[2].signature
,
1480 ed_sig_tok
->args
[0])<0) {
1481 log_warn(LD_DIR
, "Couldn't decode ed25519 signature");
1484 check
[2].pubkey
= &cert
->signed_key
;
1485 check
[2].msg
= d256
;
1486 check
[2].len
= DIGEST256_LEN
;
1488 if (ed25519_checksig_batch(check_ok
, check
, 3) < 0) {
1489 log_warn(LD_DIR
, "Incorrect ed25519 signature(s)");
1493 if (check_tap_onion_key_crosscert(
1494 (const uint8_t*)cc_tap_tok
->object_body
,
1495 (int)cc_tap_tok
->object_size
,
1498 (const uint8_t*)router
->cache_info
.identity_digest
)<0) {
1499 log_warn(LD_DIR
, "Incorrect TAP cross-verification");
1503 /* We check this before adding it to the routerlist. */
1504 if (cert
->valid_until
< ntor_cc_cert
->valid_until
)
1505 router
->cert_expiration_time
= cert
->valid_until
;
1507 router
->cert_expiration_time
= ntor_cc_cert
->valid_until
;
1511 if ((tok
= find_opt_by_keyword(tokens
, K_FINGERPRINT
))) {
1512 /* If there's a fingerprint line, it must match the identity digest. */
1514 tor_assert(tok
->n_args
== 1);
1515 tor_strstrip(tok
->args
[0], " ");
1516 if (base16_decode(d
, DIGEST_LEN
,
1517 tok
->args
[0], strlen(tok
->args
[0])) != DIGEST_LEN
) {
1518 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1519 escaped(tok
->args
[0]));
1522 if (tor_memneq(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)) {
1523 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1529 if ((tok
= find_opt_by_keyword(tokens
, K_PLATFORM
))) {
1530 router
->platform
= tor_strdup(tok
->args
[0]);
1533 if ((tok
= find_opt_by_keyword(tokens
, K_CONTACT
))) {
1534 router
->contact_info
= tor_strdup(tok
->args
[0]);
1537 if (find_opt_by_keyword(tokens
, K_REJECT6
) ||
1538 find_opt_by_keyword(tokens
, K_ACCEPT6
)) {
1539 log_warn(LD_DIR
, "Rejecting router with reject6/accept6 line: they crash "
1544 smartlist_t
*or_addresses
= find_all_by_keyword(tokens
, K_OR_ADDRESS
);
1546 find_single_ipv6_orport(or_addresses
, &router
->ipv6_addr
,
1547 &router
->ipv6_orport
);
1548 smartlist_free(or_addresses
);
1551 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1552 if (!smartlist_len(exit_policy_tokens
)) {
1553 log_warn(LD_DIR
, "No exit policy tokens in descriptor.");
1556 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1557 if (router_add_exit_policy(router
,t
)<0) {
1558 log_warn(LD_DIR
,"Error in exit policy");
1561 policy_expand_private(&router
->exit_policy
);
1563 if ((tok
= find_opt_by_keyword(tokens
, K_IPV6_POLICY
)) && tok
->n_args
) {
1564 router
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
1565 if (! router
->ipv6_exit_policy
) {
1566 log_warn(LD_DIR
, "Error in ipv6-policy %s", escaped(tok
->args
[0]));
1571 if (policy_is_reject_star(router
->exit_policy
, AF_INET
) &&
1572 (!router
->ipv6_exit_policy
||
1573 short_policy_is_reject_star(router
->ipv6_exit_policy
)))
1574 router
->policy_is_reject_star
= 1;
1576 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1578 router
->declared_family
= smartlist_new();
1579 for (i
=0;i
<tok
->n_args
;++i
) {
1580 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1581 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1582 escaped(tok
->args
[i
]));
1585 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
1589 if (find_opt_by_keyword(tokens
, K_CACHES_EXTRA_INFO
))
1590 router
->caches_extra_info
= 1;
1592 if (find_opt_by_keyword(tokens
, K_ALLOW_SINGLE_HOP_EXITS
))
1593 router
->allow_single_hop_exits
= 1;
1595 if ((tok
= find_opt_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1596 tor_assert(tok
->n_args
>= 1);
1597 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1598 if (base16_decode(router
->cache_info
.extra_info_digest
, DIGEST_LEN
,
1599 tok
->args
[0], HEX_DIGEST_LEN
) != DIGEST_LEN
) {
1600 log_warn(LD_DIR
,"Invalid extra info digest");
1603 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1606 if (tok
->n_args
>= 2) {
1607 if (digest256_from_base64(router
->cache_info
.extra_info_digest256
,
1608 tok
->args
[1]) < 0) {
1609 log_warn(LD_DIR
, "Invalid extra info digest256 %s",
1610 escaped(tok
->args
[1]));
1615 if (find_opt_by_keyword(tokens
, K_HIDDEN_SERVICE_DIR
)) {
1616 router
->wants_to_be_hs_dir
= 1;
1619 /* This router accepts tunnelled directory requests via begindir if it has
1620 * an open dirport or it included "tunnelled-dir-server". */
1621 if (find_opt_by_keyword(tokens
, K_DIR_TUNNELLED
) || router
->dir_port
> 0) {
1622 router
->supports_tunnelled_dir_requests
= 1;
1625 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1626 note_crypto_pk_op(VERIFY_RTR
);
1627 #ifdef COUNT_DISTINCT_DIGESTS
1628 if (!verified_digests
)
1629 verified_digests
= digestmap_new();
1630 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
1633 if (!router
->or_port
) {
1634 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
1638 /* We've checked everything that's covered by the hash. */
1640 if (check_signature_token(digest
, DIGEST_LEN
, tok
, router
->identity_pkey
, 0,
1641 "router descriptor") < 0)
1644 if (!router
->platform
) {
1645 router
->platform
= tor_strdup("<unknown>");
1650 dump_desc(s_dup
, "router descriptor");
1651 routerinfo_free(router
);
1654 tor_cert_free(ntor_cc_cert
);
1656 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1657 smartlist_free(tokens
);
1659 smartlist_free(exit_policy_tokens
);
1661 DUMP_AREA(area
, "routerinfo");
1662 memarea_drop_all(area
);
1664 if (can_dl_again_out
)
1665 *can_dl_again_out
= can_dl_again
;
1669 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1670 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1671 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1672 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1673 * as a map from router identity to routerinfo_t when looking up signing keys.
1675 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1676 * if it's okay to try to download an extrainfo with this same digest again,
1677 * and 0 if it isn't. (It might not be okay to download it again if part of
1678 * the part covered by the digest is invalid.)
1681 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
1682 int cache_copy
, struct digest_ri_map_t
*routermap
,
1683 int *can_dl_again_out
)
1685 extrainfo_t
*extrainfo
= NULL
;
1687 smartlist_t
*tokens
= NULL
;
1688 directory_token_t
*tok
;
1689 crypto_pk_t
*key
= NULL
;
1690 routerinfo_t
*router
= NULL
;
1691 memarea_t
*area
= NULL
;
1692 const char *s_dup
= s
;
1693 /* Do not set this to '1' until we have parsed everything that we intend to
1694 * parse that's covered by the hash. */
1695 int can_dl_again
= 0;
1698 end
= s
+ strlen(s
);
1701 /* point 'end' to a point immediately after the final newline. */
1702 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1705 if (router_get_extrainfo_hash(s
, end
-s
, digest
) < 0) {
1706 log_warn(LD_DIR
, "Couldn't compute router hash.");
1709 tokens
= smartlist_new();
1710 area
= memarea_new();
1711 if (tokenize_string(area
,s
,end
,tokens
,extrainfo_token_table
,0)) {
1712 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
1716 if (smartlist_len(tokens
) < 2) {
1717 log_warn(LD_DIR
, "Impossibly short extra-info document.");
1721 /* XXXX Accept this in position 1 too, and ed identity in position 0. */
1722 tok
= smartlist_get(tokens
,0);
1723 if (tok
->tp
!= K_EXTRA_INFO
) {
1724 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
1728 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
1729 extrainfo
->cache_info
.is_extrainfo
= 1;
1731 extrainfo
->cache_info
.signed_descriptor_body
= tor_memdup_nulterm(s
,end
-s
);
1732 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
1733 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1734 crypto_digest256((char*)extrainfo
->digest256
, s
, end
-s
, DIGEST_SHA256
);
1736 tor_assert(tok
->n_args
>= 2);
1737 if (!is_legal_nickname(tok
->args
[0])) {
1738 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
1741 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
1742 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
1743 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
1744 tok
->args
[1], HEX_DIGEST_LEN
) != DIGEST_LEN
) {
1745 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
1746 escaped(tok
->args
[1]));
1750 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1751 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
1752 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
1753 escaped(tok
->args
[0]));
1758 directory_token_t
*ed_sig_tok
, *ed_cert_tok
;
1759 ed_sig_tok
= find_opt_by_keyword(tokens
, K_ROUTER_SIG_ED25519
);
1760 ed_cert_tok
= find_opt_by_keyword(tokens
, K_IDENTITY_ED25519
);
1761 int n_ed_toks
= !!ed_sig_tok
+ !!ed_cert_tok
;
1762 if (n_ed_toks
!= 0 && n_ed_toks
!= 2) {
1763 log_warn(LD_DIR
, "Router descriptor with only partial ed25519/"
1764 "cross-certification support");
1768 tor_assert(ed_cert_tok
);
1769 const int ed_cert_token_pos
= smartlist_pos(tokens
, ed_cert_tok
);
1770 if (ed_cert_token_pos
!= 1) {
1771 /* Accept this in position 0 XXXX */
1772 log_warn(LD_DIR
, "Ed25519 certificate in wrong position");
1775 if (ed_sig_tok
!= smartlist_get(tokens
, smartlist_len(tokens
)-2)) {
1776 log_warn(LD_DIR
, "Ed25519 signature in wrong position");
1779 if (strcmp(ed_cert_tok
->object_type
, "ED25519 CERT")) {
1780 log_warn(LD_DIR
, "Wrong object type on identity-ed25519 in decriptor");
1784 uint8_t d256
[DIGEST256_LEN
];
1785 const char *signed_start
, *signed_end
;
1786 tor_cert_t
*cert
= tor_cert_parse(
1787 (const uint8_t*)ed_cert_tok
->object_body
,
1788 ed_cert_tok
->object_size
);
1790 log_warn(LD_DIR
, "Couldn't parse ed25519 cert");
1793 /* makes sure it gets freed. */
1794 extrainfo
->cache_info
.signing_key_cert
= cert
;
1796 if (cert
->cert_type
!= CERT_TYPE_ID_SIGNING
||
1797 ! cert
->signing_key_included
) {
1798 log_warn(LD_DIR
, "Invalid form for ed25519 cert");
1802 if (router_get_hash_impl_helper(s
, end
-s
, "extra-info ",
1803 "\nrouter-sig-ed25519",
1804 ' ', &signed_start
, &signed_end
) < 0) {
1805 log_warn(LD_DIR
, "Can't find ed25519-signed portion of extrainfo");
1808 crypto_digest_t
*d
= crypto_digest256_new(DIGEST_SHA256
);
1809 crypto_digest_add_bytes(d
, ED_DESC_SIGNATURE_PREFIX
,
1810 strlen(ED_DESC_SIGNATURE_PREFIX
));
1811 crypto_digest_add_bytes(d
, signed_start
, signed_end
-signed_start
);
1812 crypto_digest_get_digest(d
, (char*)d256
, sizeof(d256
));
1813 crypto_digest_free(d
);
1815 ed25519_checkable_t check
[2];
1817 if (tor_cert_get_checkable_sig(&check
[0], cert
, NULL
) < 0) {
1818 log_err(LD_BUG
, "Couldn't create 'checkable' for cert.");
1822 if (ed25519_signature_from_base64(&check
[1].signature
,
1823 ed_sig_tok
->args
[0])<0) {
1824 log_warn(LD_DIR
, "Couldn't decode ed25519 signature");
1827 check
[1].pubkey
= &cert
->signed_key
;
1828 check
[1].msg
= d256
;
1829 check
[1].len
= DIGEST256_LEN
;
1831 if (ed25519_checksig_batch(check_ok
, check
, 2) < 0) {
1832 log_warn(LD_DIR
, "Incorrect ed25519 signature(s)");
1835 /* We don't check the certificate expiration time: checking that it
1836 * matches the cert in the router descriptor is adequate. */
1840 /* We've checked everything that's covered by the hash. */
1844 (router
= digestmap_get((digestmap_t
*)routermap
,
1845 extrainfo
->cache_info
.identity_digest
))) {
1846 key
= router
->identity_pkey
;
1849 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1850 if (strcmp(tok
->object_type
, "SIGNATURE") ||
1851 tok
->object_size
< 128 || tok
->object_size
> 512) {
1852 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
1857 note_crypto_pk_op(VERIFY_RTR
);
1858 if (check_signature_token(digest
, DIGEST_LEN
, tok
, key
, 0,
1863 extrainfo
->cache_info
.send_unencrypted
=
1864 router
->cache_info
.send_unencrypted
;
1866 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
1868 extrainfo
->pending_sig_len
= tok
->object_size
;
1873 dump_desc(s_dup
, "extra-info descriptor");
1874 extrainfo_free(extrainfo
);
1878 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1879 smartlist_free(tokens
);
1882 DUMP_AREA(area
, "extrainfo");
1883 memarea_drop_all(area
);
1885 if (can_dl_again_out
)
1886 *can_dl_again_out
= can_dl_again
;
1890 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1891 * the first character after the certificate. */
1893 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
1895 /** Reject any certificate at least this big; it is probably an overflow, an
1896 * attack, a bug, or some other nonsense. */
1897 #define MAX_CERT_SIZE (128*1024)
1899 authority_cert_t
*cert
= NULL
, *old_cert
;
1900 smartlist_t
*tokens
= NULL
;
1901 char digest
[DIGEST_LEN
];
1902 directory_token_t
*tok
;
1903 char fp_declared
[DIGEST_LEN
];
1907 memarea_t
*area
= NULL
;
1908 const char *s_dup
= s
;
1910 s
= eat_whitespace(s
);
1911 eos
= strstr(s
, "\ndir-key-certification");
1913 log_warn(LD_DIR
, "No signature found on key certificate");
1916 eos
= strstr(eos
, "\n-----END SIGNATURE-----\n");
1918 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
1921 eos
= strchr(eos
+2, '\n');
1926 if (len
> MAX_CERT_SIZE
) {
1927 log_warn(LD_DIR
, "Certificate is far too big (at %lu bytes long); "
1928 "rejecting", (unsigned long)len
);
1932 tokens
= smartlist_new();
1933 area
= memarea_new();
1934 if (tokenize_string(area
,s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
1935 log_warn(LD_DIR
, "Error tokenizing key certificate");
1938 if (router_get_hash_impl(s
, strlen(s
), digest
, "dir-key-certificate-version",
1939 "\ndir-key-certification", '\n', DIGEST_SHA1
) < 0)
1941 tok
= smartlist_get(tokens
, 0);
1942 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
1944 "Key certificate does not begin with a recognized version (3).");
1948 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
1949 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1951 tok
= find_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1952 tor_assert(tok
->key
);
1953 cert
->signing_key
= tok
->key
;
1955 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
1958 tok
= find_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
1959 tor_assert(tok
->key
);
1960 cert
->identity_key
= tok
->key
;
1963 tok
= find_by_keyword(tokens
, K_FINGERPRINT
);
1964 tor_assert(tok
->n_args
);
1965 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
1966 strlen(tok
->args
[0])) != DIGEST_LEN
) {
1967 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
1968 escaped(tok
->args
[0]));
1972 if (crypto_pk_get_digest(cert
->identity_key
,
1973 cert
->cache_info
.identity_digest
))
1976 if (tor_memneq(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
1977 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
1982 tok
= find_opt_by_keyword(tokens
, K_DIR_ADDRESS
);
1985 char *address
= NULL
;
1986 tor_assert(tok
->n_args
);
1987 /* XXX++ use some tor_addr parse function below instead. -RD */
1988 if (tor_addr_port_split(LOG_WARN
, tok
->args
[0], &address
,
1989 &cert
->dir_port
) < 0 ||
1990 tor_inet_aton(address
, &in
) == 0) {
1991 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
1995 cert
->addr
= ntohl(in
.s_addr
);
1999 tok
= find_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
2000 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
2003 tok
= find_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
2004 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
2008 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
2009 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
2010 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
2014 /* If we already have this cert, don't bother checking the signature. */
2015 old_cert
= authority_cert_get_by_digests(
2016 cert
->cache_info
.identity_digest
,
2017 cert
->signing_key_digest
);
2020 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
2022 if (old_cert
->cache_info
.signed_descriptor_len
== len
&&
2023 old_cert
->cache_info
.signed_descriptor_body
&&
2024 tor_memeq(s
, old_cert
->cache_info
.signed_descriptor_body
, len
)) {
2025 log_debug(LD_DIR
, "We already checked the signature on this "
2026 "certificate; no need to do so again.");
2031 if (check_signature_token(digest
, DIGEST_LEN
, tok
, cert
->identity_key
, 0,
2032 "key certificate")) {
2036 tok
= find_by_keyword(tokens
, K_DIR_KEY_CROSSCERT
);
2037 if (check_signature_token(cert
->cache_info
.identity_digest
,
2041 CST_NO_CHECK_OBJTYPE
,
2042 "key cross-certification")) {
2047 cert
->cache_info
.signed_descriptor_len
= len
;
2048 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
2049 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
2050 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
2051 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
2053 if (end_of_string
) {
2054 *end_of_string
= eat_whitespace(eos
);
2056 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2057 smartlist_free(tokens
);
2059 DUMP_AREA(area
, "authority cert");
2060 memarea_drop_all(area
);
2064 dump_desc(s_dup
, "authority cert");
2065 authority_cert_free(cert
);
2066 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2067 smartlist_free(tokens
);
2069 DUMP_AREA(area
, "authority cert");
2070 memarea_drop_all(area
);
2075 /** Helper: given a string <b>s</b>, return the start of the next router-status
2076 * object (starting with "r " at the start of a line). If none is found,
2077 * return the start of the directory footer, or the next directory signature.
2078 * If none is found, return the end of the string. */
2079 static inline const char *
2080 find_start_of_next_routerstatus(const char *s
)
2082 const char *eos
, *footer
, *sig
;
2083 if ((eos
= strstr(s
, "\nr ")))
2086 eos
= s
+ strlen(s
);
2088 footer
= tor_memstr(s
, eos
-s
, "\ndirectory-footer");
2089 sig
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
2092 return MIN(footer
, sig
) + 1;
2101 /** Parse the GuardFraction string from a consensus or vote.
2103 * If <b>vote</b> or <b>vote_rs</b> are set the document getting
2104 * parsed is a vote routerstatus. Otherwise it's a consensus. This is
2105 * the same semantic as in routerstatus_parse_entry_from_string(). */
2107 routerstatus_parse_guardfraction(const char *guardfraction_str
,
2108 networkstatus_t
*vote
,
2109 vote_routerstatus_t
*vote_rs
,
2113 const char *end_of_header
= NULL
;
2114 int is_consensus
= !vote_rs
;
2115 uint32_t guardfraction
;
2117 tor_assert(bool_eq(vote
, vote_rs
));
2119 /* If this info comes from a consensus, but we should't apply
2120 guardfraction, just exit. */
2121 if (is_consensus
&& !should_apply_guardfraction(NULL
)) {
2125 end_of_header
= strchr(guardfraction_str
, '=');
2126 if (!end_of_header
) {
2130 guardfraction
= (uint32_t)tor_parse_ulong(end_of_header
+1,
2131 10, 0, 100, &ok
, NULL
);
2133 log_warn(LD_DIR
, "Invalid GuardFraction %s", escaped(guardfraction_str
));
2137 log_debug(LD_GENERAL
, "[*] Parsed %s guardfraction '%s' for '%s'.",
2138 is_consensus
? "consensus" : "vote",
2139 guardfraction_str
, rs
->nickname
);
2141 if (!is_consensus
) { /* We are parsing a vote */
2142 vote_rs
->status
.guardfraction_percentage
= guardfraction
;
2143 vote_rs
->status
.has_guardfraction
= 1;
2145 /* We are parsing a consensus. Only apply guardfraction to guards. */
2146 if (rs
->is_possible_guard
) {
2147 rs
->guardfraction_percentage
= guardfraction
;
2148 rs
->has_guardfraction
= 1;
2150 log_warn(LD_BUG
, "Got GuardFraction for non-guard %s. "
2151 "This is not supposed to happen. Not applying. ", rs
->nickname
);
2158 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
2159 * empty smartlist at <b>tokens</b>, parse and return the first router status
2160 * object in the string, and advance *<b>s</b> to just after the end of the
2161 * router status. Return NULL and advance *<b>s</b> on error.
2163 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
2164 * routerstatus but use <b>vote_rs</b> instead.
2166 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
2167 * consensus, and we should parse it according to the method used to
2168 * make that consensus.
2170 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
2172 static routerstatus_t
*
2173 routerstatus_parse_entry_from_string(memarea_t
*area
,
2174 const char **s
, smartlist_t
*tokens
,
2175 networkstatus_t
*vote
,
2176 vote_routerstatus_t
*vote_rs
,
2177 int consensus_method
,
2178 consensus_flavor_t flav
)
2180 const char *eos
, *s_dup
= *s
;
2181 routerstatus_t
*rs
= NULL
;
2182 directory_token_t
*tok
;
2183 char timebuf
[ISO_TIME_LEN
+1];
2187 tor_assert(bool_eq(vote
, vote_rs
));
2189 if (!consensus_method
)
2191 tor_assert(flav
== FLAV_NS
|| flav
== FLAV_MICRODESC
);
2193 eos
= find_start_of_next_routerstatus(*s
);
2195 if (tokenize_string(area
,*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
2196 log_warn(LD_DIR
, "Error tokenizing router status");
2199 if (smartlist_len(tokens
) < 1) {
2200 log_warn(LD_DIR
, "Impossibly short router status");
2203 tok
= find_by_keyword(tokens
, K_R
);
2204 tor_assert(tok
->n_args
>= 7); /* guaranteed by GE(7) in K_R setup */
2205 if (flav
== FLAV_NS
) {
2206 if (tok
->n_args
< 8) {
2207 log_warn(LD_DIR
, "Too few arguments to r");
2210 } else if (flav
== FLAV_MICRODESC
) {
2211 offset
= -1; /* There is no identity digest */
2215 rs
= &vote_rs
->status
;
2217 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
2220 if (!is_legal_nickname(tok
->args
[0])) {
2222 "Invalid nickname %s in router status; skipping.",
2223 escaped(tok
->args
[0]));
2226 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
2228 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
2229 log_warn(LD_DIR
, "Error decoding identity digest %s",
2230 escaped(tok
->args
[1]));
2234 if (flav
== FLAV_NS
) {
2235 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
2236 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
2237 escaped(tok
->args
[2]));
2242 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
2243 tok
->args
[3+offset
], tok
->args
[4+offset
]) < 0 ||
2244 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
2245 log_warn(LD_DIR
, "Error parsing time '%s %s' [%d %d]",
2246 tok
->args
[3+offset
], tok
->args
[4+offset
],
2251 if (tor_inet_aton(tok
->args
[5+offset
], &in
) == 0) {
2252 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
2253 escaped(tok
->args
[5+offset
]));
2256 rs
->addr
= ntohl(in
.s_addr
);
2258 rs
->or_port
= (uint16_t) tor_parse_long(tok
->args
[6+offset
],
2259 10,0,65535,NULL
,NULL
);
2260 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7+offset
],
2261 10,0,65535,NULL
,NULL
);
2264 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
2266 find_single_ipv6_orport(a_lines
, &rs
->ipv6_addr
, &rs
->ipv6_orport
);
2267 smartlist_free(a_lines
);
2271 tok
= find_opt_by_keyword(tokens
, K_S
);
2275 for (i
=0; i
< tok
->n_args
; ++i
) {
2276 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
2278 vote_rs
->flags
|= (U64_LITERAL(1)<<p
);
2280 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
2281 escaped(tok
->args
[i
]));
2287 for (i
=0; i
< tok
->n_args
; ++i
) {
2288 if (!strcmp(tok
->args
[i
], "Exit"))
2290 else if (!strcmp(tok
->args
[i
], "Stable"))
2292 else if (!strcmp(tok
->args
[i
], "Fast"))
2294 else if (!strcmp(tok
->args
[i
], "Running"))
2295 rs
->is_flagged_running
= 1;
2296 else if (!strcmp(tok
->args
[i
], "Named"))
2298 else if (!strcmp(tok
->args
[i
], "Valid"))
2300 else if (!strcmp(tok
->args
[i
], "Guard"))
2301 rs
->is_possible_guard
= 1;
2302 else if (!strcmp(tok
->args
[i
], "BadExit"))
2303 rs
->is_bad_exit
= 1;
2304 else if (!strcmp(tok
->args
[i
], "Authority"))
2305 rs
->is_authority
= 1;
2306 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
2307 consensus_method
>= 2) {
2308 /* Unnamed is computed right by consensus method 2 and later. */
2310 } else if (!strcmp(tok
->args
[i
], "HSDir")) {
2312 } else if (!strcmp(tok
->args
[i
], "V2Dir")) {
2317 if ((tok
= find_opt_by_keyword(tokens
, K_V
))) {
2318 tor_assert(tok
->n_args
== 1);
2319 rs
->version_known
= 1;
2320 if (strcmpstart(tok
->args
[0], "Tor ")) {
2322 rs
->version_supports_extend2_cells
=
2323 tor_version_as_new_as(tok
->args
[0], "0.2.4.8-alpha");
2326 vote_rs
->version
= tor_strdup(tok
->args
[0]);
2330 /* handle weighting/bandwidth info */
2331 if ((tok
= find_opt_by_keyword(tokens
, K_W
))) {
2333 for (i
=0; i
< tok
->n_args
; ++i
) {
2334 if (!strcmpstart(tok
->args
[i
], "Bandwidth=")) {
2337 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
2341 log_warn(LD_DIR
, "Invalid Bandwidth %s", escaped(tok
->args
[i
]));
2344 rs
->has_bandwidth
= 1;
2345 } else if (!strcmpstart(tok
->args
[i
], "Measured=") && vote_rs
) {
2347 vote_rs
->measured_bw_kb
=
2348 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
2349 10, 0, UINT32_MAX
, &ok
, NULL
);
2351 log_warn(LD_DIR
, "Invalid Measured Bandwidth %s",
2352 escaped(tok
->args
[i
]));
2355 vote_rs
->has_measured_bw
= 1;
2356 vote
->has_measured_bws
= 1;
2357 } else if (!strcmpstart(tok
->args
[i
], "Unmeasured=1")) {
2358 rs
->bw_is_unmeasured
= 1;
2359 } else if (!strcmpstart(tok
->args
[i
], "GuardFraction=")) {
2360 if (routerstatus_parse_guardfraction(tok
->args
[i
],
2361 vote
, vote_rs
, rs
) < 0) {
2368 /* parse exit policy summaries */
2369 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
2370 tor_assert(tok
->n_args
== 1);
2371 if (strcmpstart(tok
->args
[0], "accept ") &&
2372 strcmpstart(tok
->args
[0], "reject ")) {
2373 log_warn(LD_DIR
, "Unknown exit policy summary type %s.",
2374 escaped(tok
->args
[0]));
2377 /* XXX weasel: parse this into ports and represent them somehow smart,
2378 * maybe not here but somewhere on if we need it for the client.
2379 * we should still parse it here to check it's valid tho.
2381 rs
->exitsummary
= tor_strdup(tok
->args
[0]);
2382 rs
->has_exitsummary
= 1;
2386 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, t
) {
2387 if (t
->tp
== K_M
&& t
->n_args
) {
2388 vote_microdesc_hash_t
*line
=
2389 tor_malloc(sizeof(vote_microdesc_hash_t
));
2390 line
->next
= vote_rs
->microdesc
;
2391 line
->microdesc_hash_line
= tor_strdup(t
->args
[0]);
2392 vote_rs
->microdesc
= line
;
2394 if (t
->tp
== K_ID
) {
2395 tor_assert(t
->n_args
>= 2);
2396 if (!strcmp(t
->args
[0], "ed25519")) {
2397 vote_rs
->has_ed25519_listing
= 1;
2398 if (strcmp(t
->args
[1], "none") &&
2399 digest256_from_base64((char*)vote_rs
->ed25519_id
,
2401 log_warn(LD_DIR
, "Bogus ed25519 key in networkstatus vote");
2406 } SMARTLIST_FOREACH_END(t
);
2407 } else if (flav
== FLAV_MICRODESC
) {
2408 tok
= find_opt_by_keyword(tokens
, K_M
);
2410 tor_assert(tok
->n_args
);
2411 if (digest256_from_base64(rs
->descriptor_digest
, tok
->args
[0])) {
2412 log_warn(LD_DIR
, "Error decoding microdescriptor digest %s",
2413 escaped(tok
->args
[0]));
2417 log_info(LD_BUG
, "Found an entry in networkstatus with no "
2418 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
2419 rs
->nickname
, hex_str(rs
->identity_digest
, DIGEST_LEN
),
2420 fmt_addr32(rs
->addr
), rs
->or_port
);
2424 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
2429 dump_desc(s_dup
, "routerstatus entry");
2431 routerstatus_free(rs
);
2434 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2435 smartlist_clear(tokens
);
2437 DUMP_AREA(area
, "routerstatus entry");
2438 memarea_clear(area
);
2446 compare_vote_routerstatus_entries(const void **_a
, const void **_b
)
2448 const vote_routerstatus_t
*a
= *_a
, *b
= *_b
;
2449 return fast_memcmp(a
->status
.identity_digest
, b
->status
.identity_digest
,
2453 /** Verify the bandwidth weights of a network status document */
2455 networkstatus_verify_bw_weights(networkstatus_t
*ns
, int consensus_method
)
2457 int64_t weight_scale
;
2458 int64_t G
=0, M
=0, E
=0, D
=0, T
=0;
2459 double Wgg
, Wgm
, Wgd
, Wmg
, Wmm
, Wme
, Wmd
, Weg
, Wem
, Wee
, Wed
;
2460 double Gtotal
=0, Mtotal
=0, Etotal
=0;
2461 const char *casename
= NULL
;
2463 (void) consensus_method
;
2465 weight_scale
= networkstatus_get_weight_scale_param(ns
);
2466 Wgg
= networkstatus_get_bw_weight(ns
, "Wgg", -1);
2467 Wgm
= networkstatus_get_bw_weight(ns
, "Wgm", -1);
2468 Wgd
= networkstatus_get_bw_weight(ns
, "Wgd", -1);
2469 Wmg
= networkstatus_get_bw_weight(ns
, "Wmg", -1);
2470 Wmm
= networkstatus_get_bw_weight(ns
, "Wmm", -1);
2471 Wme
= networkstatus_get_bw_weight(ns
, "Wme", -1);
2472 Wmd
= networkstatus_get_bw_weight(ns
, "Wmd", -1);
2473 Weg
= networkstatus_get_bw_weight(ns
, "Weg", -1);
2474 Wem
= networkstatus_get_bw_weight(ns
, "Wem", -1);
2475 Wee
= networkstatus_get_bw_weight(ns
, "Wee", -1);
2476 Wed
= networkstatus_get_bw_weight(ns
, "Wed", -1);
2478 if (Wgg
<0 || Wgm
<0 || Wgd
<0 || Wmg
<0 || Wmm
<0 || Wme
<0 || Wmd
<0 || Weg
<0
2479 || Wem
<0 || Wee
<0 || Wed
<0) {
2480 log_warn(LD_BUG
, "No bandwidth weights produced in consensus!");
2484 // First, sanity check basic summing properties that hold for all cases
2485 // We use > 1 as the check for these because they are computed as integers.
2486 // Sometimes there are rounding errors.
2487 if (fabs(Wmm
- weight_scale
) > 1) {
2488 log_warn(LD_BUG
, "Wmm=%f != "I64_FORMAT
,
2489 Wmm
, I64_PRINTF_ARG(weight_scale
));
2493 if (fabs(Wem
- Wee
) > 1) {
2494 log_warn(LD_BUG
, "Wem=%f != Wee=%f", Wem
, Wee
);
2498 if (fabs(Wgm
- Wgg
) > 1) {
2499 log_warn(LD_BUG
, "Wgm=%f != Wgg=%f", Wgm
, Wgg
);
2503 if (fabs(Weg
- Wed
) > 1) {
2504 log_warn(LD_BUG
, "Wed=%f != Weg=%f", Wed
, Weg
);
2508 if (fabs(Wgg
+ Wmg
- weight_scale
) > 0.001*weight_scale
) {
2509 log_warn(LD_BUG
, "Wgg=%f != "I64_FORMAT
" - Wmg=%f", Wgg
,
2510 I64_PRINTF_ARG(weight_scale
), Wmg
);
2514 if (fabs(Wee
+ Wme
- weight_scale
) > 0.001*weight_scale
) {
2515 log_warn(LD_BUG
, "Wee=%f != "I64_FORMAT
" - Wme=%f", Wee
,
2516 I64_PRINTF_ARG(weight_scale
), Wme
);
2520 if (fabs(Wgd
+ Wmd
+ Wed
- weight_scale
) > 0.001*weight_scale
) {
2521 log_warn(LD_BUG
, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT
,
2522 Wgd
, Wmd
, Wed
, I64_PRINTF_ARG(weight_scale
));
2526 Wgg
/= weight_scale
;
2527 Wgm
/= weight_scale
;
2528 Wgd
/= weight_scale
;
2530 Wmg
/= weight_scale
;
2531 Wmm
/= weight_scale
;
2532 Wme
/= weight_scale
;
2533 Wmd
/= weight_scale
;
2535 Weg
/= weight_scale
;
2536 Wem
/= weight_scale
;
2537 Wee
/= weight_scale
;
2538 Wed
/= weight_scale
;
2540 // Then, gather G, M, E, D, T to determine case
2541 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, routerstatus_t
*, rs
) {
2543 /* Bug #2203: Don't count bad exits as exits for balancing */
2544 is_exit
= rs
->is_exit
&& !rs
->is_bad_exit
;
2545 if (rs
->has_bandwidth
) {
2546 T
+= rs
->bandwidth_kb
;
2547 if (is_exit
&& rs
->is_possible_guard
) {
2548 D
+= rs
->bandwidth_kb
;
2549 Gtotal
+= Wgd
*rs
->bandwidth_kb
;
2550 Mtotal
+= Wmd
*rs
->bandwidth_kb
;
2551 Etotal
+= Wed
*rs
->bandwidth_kb
;
2552 } else if (is_exit
) {
2553 E
+= rs
->bandwidth_kb
;
2554 Mtotal
+= Wme
*rs
->bandwidth_kb
;
2555 Etotal
+= Wee
*rs
->bandwidth_kb
;
2556 } else if (rs
->is_possible_guard
) {
2557 G
+= rs
->bandwidth_kb
;
2558 Gtotal
+= Wgg
*rs
->bandwidth_kb
;
2559 Mtotal
+= Wmg
*rs
->bandwidth_kb
;
2561 M
+= rs
->bandwidth_kb
;
2562 Mtotal
+= Wmm
*rs
->bandwidth_kb
;
2565 log_warn(LD_BUG
, "Missing consensus bandwidth for router %s",
2566 routerstatus_describe(rs
));
2568 } SMARTLIST_FOREACH_END(rs
);
2570 // Finally, check equality conditions depending upon case 1, 2 or 3
2571 // Full equality cases: 1, 3b
2572 // Partial equality cases: 2b (E=G), 3a (M=E)
2573 // Fully unknown: 2a
2574 if (3*E
>= T
&& 3*G
>= T
) {
2575 // Case 1: Neither are scarce
2576 casename
= "Case 1";
2577 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2579 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2580 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2582 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2583 casename
, Etotal
, Mtotal
,
2584 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2585 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2586 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2589 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2591 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2592 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2594 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2595 casename
, Etotal
, Gtotal
,
2596 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2597 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2598 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2601 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2603 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2604 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2606 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2607 casename
, Mtotal
, Gtotal
,
2608 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2609 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2610 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2613 } else if (3*E
< T
&& 3*G
< T
) {
2614 int64_t R
= MIN(E
, G
);
2615 int64_t S
= MAX(E
, G
);
2617 * Case 2: Both Guards and Exits are scarce
2618 * Balance D between E and G, depending upon
2619 * D capacity and scarcity. Devote no extra
2620 * bandwidth to middle nodes.
2622 if (R
+D
< S
) { // Subcase a
2623 double Rtotal
, Stotal
;
2631 casename
= "Case 2a";
2633 if (Rtotal
> Stotal
) {
2635 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
2636 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2638 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2639 casename
, Rtotal
, Stotal
,
2640 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2641 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2642 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2648 "Bw Weight Failure for %s: 3*Rtotal %f > T "
2649 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2650 " D="I64_FORMAT
" T="I64_FORMAT
". "
2651 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2652 casename
, Rtotal
*3, I64_PRINTF_ARG(T
),
2653 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2654 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2655 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2661 "Bw Weight Failure for %s: 3*Stotal %f > T "
2662 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2663 " D="I64_FORMAT
" T="I64_FORMAT
". "
2664 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2665 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
2666 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2667 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2668 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2674 "Bw Weight Failure for %s: 3*Mtotal %f < T "
2676 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2678 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2679 casename
, Mtotal
*3, I64_PRINTF_ARG(T
),
2680 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2681 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2682 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2685 } else { // Subcase b: R+D > S
2686 casename
= "Case 2b";
2688 /* Check the rare-M redirect case. */
2689 if (D
!= 0 && 3*M
< T
) {
2690 casename
= "Case 2b (balanced)";
2691 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2693 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2694 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2696 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2697 casename
, Etotal
, Mtotal
,
2698 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2699 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2700 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2703 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2705 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2706 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2708 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2709 casename
, Etotal
, Gtotal
,
2710 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2711 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2712 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2715 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2717 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2718 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2720 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2721 casename
, Mtotal
, Gtotal
,
2722 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2723 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2724 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2728 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2730 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2731 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2733 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2734 casename
, Etotal
, Gtotal
,
2735 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2736 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2737 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2742 } else { // if (E < T/3 || G < T/3) {
2743 int64_t S
= MIN(E
, G
);
2744 int64_t NS
= MAX(E
, G
);
2745 if (3*(S
+D
) < T
) { // Subcase a:
2749 casename
= "Case 3a (G scarce)";
2752 } else { // if (G >= E) {
2753 casename
= "Case 3a (E scarce)";
2760 "Bw Weight Failure for %s: 3*Stotal %f > T "
2761 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2762 " D="I64_FORMAT
" T="I64_FORMAT
". "
2763 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2764 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
2765 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2766 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2767 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2771 if (fabs(NStotal
-Mtotal
) > 0.01*MAX(NStotal
,Mtotal
)) {
2773 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
2774 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2776 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2777 casename
, NStotal
, Mtotal
,
2778 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2779 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2780 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2784 // if NS < M, NStotal > T/3 because only one of G or E is scarce
2785 if (3*NStotal
< T
) {
2787 "Bw Weight Failure for %s: 3*NStotal %f < T "
2788 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
2789 " E="I64_FORMAT
" D="I64_FORMAT
" T="I64_FORMAT
". "
2790 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2791 casename
, NStotal
*3, I64_PRINTF_ARG(T
),
2792 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2793 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2794 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2798 } else { // Subcase b: S+D >= T/3
2799 casename
= "Case 3b";
2800 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2802 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2803 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2805 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2806 casename
, Etotal
, Mtotal
,
2807 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2808 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2809 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2812 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2814 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2815 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2817 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2818 casename
, Etotal
, Gtotal
,
2819 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2820 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2821 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2824 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2826 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2827 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2829 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2830 casename
, Mtotal
, Gtotal
,
2831 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2832 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2833 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2840 log_notice(LD_DIR
, "Bandwidth-weight %s is verified and valid.",
2846 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2847 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2849 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
2850 networkstatus_type_t ns_type
)
2852 smartlist_t
*tokens
= smartlist_new();
2853 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
2854 networkstatus_voter_info_t
*voter
= NULL
;
2855 networkstatus_t
*ns
= NULL
;
2856 common_digests_t ns_digests
;
2857 const char *cert
, *end_of_header
, *end_of_footer
, *s_dup
= s
;
2858 directory_token_t
*tok
;
2861 int i
, inorder
, n_signatures
= 0;
2862 memarea_t
*area
= NULL
, *rs_area
= NULL
;
2863 consensus_flavor_t flav
= FLAV_NS
;
2864 char *last_kwd
=NULL
;
2871 if (router_get_networkstatus_v3_hashes(s
, &ns_digests
)) {
2872 log_warn(LD_DIR
, "Unable to compute digest of network-status");
2876 area
= memarea_new();
2877 end_of_header
= find_start_of_next_routerstatus(s
);
2878 if (tokenize_string(area
, s
, end_of_header
, tokens
,
2879 (ns_type
== NS_TYPE_CONSENSUS
) ?
2880 networkstatus_consensus_token_table
:
2881 networkstatus_token_table
, 0)) {
2882 log_warn(LD_DIR
, "Error tokenizing network-status header");
2886 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
2887 memcpy(&ns
->digests
, &ns_digests
, sizeof(ns_digests
));
2889 tok
= find_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
2891 if (tok
->n_args
> 1) {
2892 int flavor
= networkstatus_parse_flavor_name(tok
->args
[1]);
2894 log_warn(LD_DIR
, "Can't parse document with unknown flavor %s",
2895 escaped(tok
->args
[1]));
2898 ns
->flavor
= flav
= flavor
;
2900 if (flav
!= FLAV_NS
&& ns_type
!= NS_TYPE_CONSENSUS
) {
2901 log_warn(LD_DIR
, "Flavor found on non-consensus networkstatus.");
2905 if (ns_type
!= NS_TYPE_CONSENSUS
) {
2906 const char *end_of_cert
= NULL
;
2907 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
2910 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
2911 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
2915 tok
= find_by_keyword(tokens
, K_VOTE_STATUS
);
2916 tor_assert(tok
->n_args
);
2917 if (!strcmp(tok
->args
[0], "vote")) {
2918 ns
->type
= NS_TYPE_VOTE
;
2919 } else if (!strcmp(tok
->args
[0], "consensus")) {
2920 ns
->type
= NS_TYPE_CONSENSUS
;
2921 } else if (!strcmp(tok
->args
[0], "opinion")) {
2922 ns
->type
= NS_TYPE_OPINION
;
2924 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
2925 escaped(tok
->args
[0]));
2928 if (ns_type
!= ns
->type
) {
2929 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
2933 if (ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_OPINION
) {
2934 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
2935 if (parse_iso_time(tok
->args
[0], &ns
->published
))
2938 ns
->supported_methods
= smartlist_new();
2939 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHODS
);
2941 for (i
=0; i
< tok
->n_args
; ++i
)
2942 smartlist_add(ns
->supported_methods
, tor_strdup(tok
->args
[i
]));
2944 smartlist_add(ns
->supported_methods
, tor_strdup("1"));
2947 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHOD
);
2949 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
2954 ns
->consensus_method
= 1;
2958 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
2959 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
2962 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
2963 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
2966 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
2967 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
2970 tok
= find_by_keyword(tokens
, K_VOTING_DELAY
);
2971 tor_assert(tok
->n_args
>= 2);
2973 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
2977 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
2980 if (ns
->valid_after
+
2981 (get_options()->TestingTorNetwork
?
2982 MIN_VOTE_INTERVAL_TESTING
: MIN_VOTE_INTERVAL
) > ns
->fresh_until
) {
2983 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
2986 if (ns
->valid_after
+
2987 (get_options()->TestingTorNetwork
?
2988 MIN_VOTE_INTERVAL_TESTING
: MIN_VOTE_INTERVAL
)*2 > ns
->valid_until
) {
2989 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
2992 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
2993 log_warn(LD_DIR
, "Vote seconds is too short");
2996 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
2997 log_warn(LD_DIR
, "Dist seconds is too short");
3001 if ((tok
= find_opt_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
3002 ns
->client_versions
= tor_strdup(tok
->args
[0]);
3004 if ((tok
= find_opt_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
3005 ns
->server_versions
= tor_strdup(tok
->args
[0]);
3009 smartlist_t
*package_lst
= find_all_by_keyword(tokens
, K_PACKAGE
);
3010 ns
->package_lines
= smartlist_new();
3012 SMARTLIST_FOREACH(package_lst
, directory_token_t
*, t
,
3013 smartlist_add(ns
->package_lines
, tor_strdup(t
->args
[0])));
3015 smartlist_free(package_lst
);
3018 tok
= find_by_keyword(tokens
, K_KNOWN_FLAGS
);
3019 ns
->known_flags
= smartlist_new();
3021 for (i
= 0; i
< tok
->n_args
; ++i
) {
3022 smartlist_add(ns
->known_flags
, tor_strdup(tok
->args
[i
]));
3023 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
3024 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
3029 log_warn(LD_DIR
, "known-flags not in order");
3032 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3033 smartlist_len(ns
->known_flags
) > MAX_KNOWN_FLAGS_IN_VOTE
) {
3034 /* If we allowed more than 64 flags in votes, then parsing them would make
3035 * us invoke undefined behavior whenever we used 1<<flagnum to do a
3036 * bit-shift. This is only for votes and opinions: consensus users don't
3037 * care about flags they don't recognize, and so don't build a bitfield
3039 log_warn(LD_DIR
, "Too many known-flags in consensus vote or opinion");
3043 tok
= find_opt_by_keyword(tokens
, K_PARAMS
);
3047 ns
->net_params
= smartlist_new();
3048 for (i
= 0; i
< tok
->n_args
; ++i
) {
3050 char *eq
= strchr(tok
->args
[i
], '=');
3053 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3056 eq_pos
= eq
-tok
->args
[i
];
3057 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
3059 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3062 if (i
> 0 && strcmp(tok
->args
[i
-1], tok
->args
[i
]) >= 0) {
3063 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
3066 if (last_kwd
&& eq_pos
== strlen(last_kwd
) &&
3067 fast_memeq(last_kwd
, tok
->args
[i
], eq_pos
)) {
3068 log_warn(LD_DIR
, "Duplicate value for %s parameter",
3069 escaped(tok
->args
[i
]));
3073 last_kwd
= tor_strndup(tok
->args
[i
], eq_pos
);
3074 smartlist_add(ns
->net_params
, tor_strdup(tok
->args
[i
]));
3077 log_warn(LD_DIR
, "params not in order");
3081 log_warn(LD_DIR
, "Duplicate in parameters");
3086 ns
->voters
= smartlist_new();
3088 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3090 if (tok
->tp
== K_DIR_SOURCE
) {
3091 tor_assert(tok
->n_args
>= 6);
3094 smartlist_add(ns
->voters
, voter
);
3095 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
3096 voter
->sigs
= smartlist_new();
3097 if (ns
->type
!= NS_TYPE_CONSENSUS
)
3098 memcpy(voter
->vote_digest
, ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
);
3100 voter
->nickname
= tor_strdup(tok
->args
[0]);
3101 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
3102 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
3103 tok
->args
[1], HEX_DIGEST_LEN
)
3104 != sizeof(voter
->identity_digest
)) {
3105 log_warn(LD_DIR
, "Error decoding identity digest %s in "
3106 "network-status document.", escaped(tok
->args
[1]));
3109 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3110 tor_memneq(ns
->cert
->cache_info
.identity_digest
,
3111 voter
->identity_digest
, DIGEST_LEN
)) {
3112 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
3115 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3116 if (authority_cert_is_blacklisted(ns
->cert
)) {
3117 log_warn(LD_DIR
, "Rejecting vote signature made with blacklisted "
3119 hex_str(ns
->cert
->signing_key_digest
, DIGEST_LEN
));
3123 voter
->address
= tor_strdup(tok
->args
[2]);
3124 if (!tor_inet_aton(tok
->args
[3], &in
)) {
3125 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
3126 escaped(tok
->args
[3]));
3129 voter
->addr
= ntohl(in
.s_addr
);
3130 voter
->dir_port
= (uint16_t)
3131 tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
3134 voter
->or_port
= (uint16_t)
3135 tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
3138 } else if (tok
->tp
== K_CONTACT
) {
3139 if (!voter
|| voter
->contact
) {
3140 log_warn(LD_DIR
, "contact element is out of place.");
3143 voter
->contact
= tor_strdup(tok
->args
[0]);
3144 } else if (tok
->tp
== K_VOTE_DIGEST
) {
3145 tor_assert(ns
->type
== NS_TYPE_CONSENSUS
);
3146 tor_assert(tok
->n_args
>= 1);
3147 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
3148 log_warn(LD_DIR
, "vote-digest element is out of place.");
3151 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
3152 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
3153 tok
->args
[0], HEX_DIGEST_LEN
)
3154 != sizeof(voter
->vote_digest
)) {
3155 log_warn(LD_DIR
, "Error decoding vote digest %s in "
3156 "network-status consensus.", escaped(tok
->args
[0]));
3160 } SMARTLIST_FOREACH_END(_tok
);
3162 smartlist_add(ns
->voters
, voter
);
3165 if (smartlist_len(ns
->voters
) == 0) {
3166 log_warn(LD_DIR
, "Missing dir-source elements in a networkstatus.");
3168 } else if (ns
->type
!= NS_TYPE_CONSENSUS
&& smartlist_len(ns
->voters
) != 1) {
3169 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
3173 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3174 (tok
= find_opt_by_keyword(tokens
, K_LEGACY_DIR_KEY
))) {
3176 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
3177 networkstatus_voter_info_t
*voter
= smartlist_get(ns
->voters
, 0);
3178 if (base16_decode(voter
->legacy_id_digest
, DIGEST_LEN
,
3179 tok
->args
[0], HEX_DIGEST_LEN
) != DIGEST_LEN
)
3185 log_warn(LD_DIR
, "Invalid legacy key digest %s on vote.",
3186 escaped(tok
->args
[0]));
3190 /* Parse routerstatus lines. */
3191 rs_tokens
= smartlist_new();
3192 rs_area
= memarea_new();
3194 ns
->routerstatus_list
= smartlist_new();
3196 while (!strcmpstart(s
, "r ")) {
3197 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3198 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
3199 if (routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
, ns
,
3201 smartlist_add(ns
->routerstatus_list
, rs
);
3203 tor_free(rs
->version
);
3208 if ((rs
= routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
,
3210 ns
->consensus_method
,
3212 /* Use exponential-backoff scheduling when downloading microdescs */
3213 rs
->dl_status
.backoff
= DL_SCHED_RANDOM_EXPONENTIAL
;
3214 smartlist_add(ns
->routerstatus_list
, rs
);
3218 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
3219 routerstatus_t
*rs1
, *rs2
;
3220 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3221 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
3222 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
3223 rs1
= &a
->status
; rs2
= &b
->status
;
3225 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
3226 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
3228 if (fast_memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
)
3230 log_warn(LD_DIR
, "Networkstatus entries not sorted by identity digest");
3234 if (ns_type
!= NS_TYPE_CONSENSUS
) {
3235 digest256map_t
*ed_id_map
= digest256map_new();
3236 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, vote_routerstatus_t
*,
3238 if (! vrs
->has_ed25519_listing
||
3239 tor_mem_is_zero((const char *)vrs
->ed25519_id
, DIGEST256_LEN
))
3241 if (digest256map_get(ed_id_map
, vrs
->ed25519_id
) != NULL
) {
3242 log_warn(LD_DIR
, "Vote networkstatus ed25519 identities were not "
3244 digest256map_free(ed_id_map
, NULL
);
3247 digest256map_set(ed_id_map
, vrs
->ed25519_id
, (void*)1);
3248 } SMARTLIST_FOREACH_END(vrs
);
3249 digest256map_free(ed_id_map
, NULL
);
3252 /* Parse footer; check signature. */
3253 footer_tokens
= smartlist_new();
3254 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
3257 end_of_footer
= s
+ strlen(s
);
3258 if (tokenize_string(area
,s
, end_of_footer
, footer_tokens
,
3259 networkstatus_vote_footer_token_table
, 0)) {
3260 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
3266 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
3268 if (tok
->tp
== K_DIRECTORY_SIGNATURE
)
3270 else if (found_sig
) {
3271 log_warn(LD_DIR
, "Extraneous token after first directory-signature");
3274 } SMARTLIST_FOREACH_END(_tok
);
3277 if ((tok
= find_opt_by_keyword(footer_tokens
, K_DIRECTORY_FOOTER
))) {
3278 if (tok
!= smartlist_get(footer_tokens
, 0)) {
3279 log_warn(LD_DIR
, "Misplaced directory-footer token");
3284 tok
= find_opt_by_keyword(footer_tokens
, K_BW_WEIGHTS
);
3286 ns
->weight_params
= smartlist_new();
3287 for (i
= 0; i
< tok
->n_args
; ++i
) {
3289 char *eq
= strchr(tok
->args
[i
], '=');
3291 log_warn(LD_DIR
, "Bad element '%s' in weight params",
3292 escaped(tok
->args
[i
]));
3295 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
3297 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3300 smartlist_add(ns
->weight_params
, tor_strdup(tok
->args
[i
]));
3304 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
3305 char declared_identity
[DIGEST_LEN
];
3306 networkstatus_voter_info_t
*v
;
3307 document_signature_t
*sig
;
3308 const char *id_hexdigest
= NULL
;
3309 const char *sk_hexdigest
= NULL
;
3310 digest_algorithm_t alg
= DIGEST_SHA1
;
3312 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
3314 tor_assert(tok
->n_args
>= 2);
3315 if (tok
->n_args
== 2) {
3316 id_hexdigest
= tok
->args
[0];
3317 sk_hexdigest
= tok
->args
[1];
3319 const char *algname
= tok
->args
[0];
3321 id_hexdigest
= tok
->args
[1];
3322 sk_hexdigest
= tok
->args
[2];
3323 a
= crypto_digest_algorithm_parse_name(algname
);
3325 log_warn(LD_DIR
, "Unknown digest algorithm %s; skipping",
3332 if (!tok
->object_type
||
3333 strcmp(tok
->object_type
, "SIGNATURE") ||
3334 tok
->object_size
< 128 || tok
->object_size
> 512) {
3335 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
3339 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
3340 base16_decode(declared_identity
, sizeof(declared_identity
),
3341 id_hexdigest
, HEX_DIGEST_LEN
)
3342 != sizeof(declared_identity
)) {
3343 log_warn(LD_DIR
, "Error decoding declared identity %s in "
3344 "network-status document.", escaped(id_hexdigest
));
3347 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
3348 log_warn(LD_DIR
, "ID on signature on network-status document does "
3349 "not match any declared directory source.");
3352 sig
= tor_malloc_zero(sizeof(document_signature_t
));
3353 memcpy(sig
->identity_digest
, v
->identity_digest
, DIGEST_LEN
);
3355 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
3356 base16_decode(sig
->signing_key_digest
, sizeof(sig
->signing_key_digest
),
3357 sk_hexdigest
, HEX_DIGEST_LEN
)
3358 != sizeof(sig
->signing_key_digest
)) {
3359 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
3360 "network-status document.", escaped(sk_hexdigest
));
3365 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3366 if (tor_memneq(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
3368 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
3369 "network-status vote.");
3375 if (voter_get_sig_by_algorithm(v
, sig
->alg
)) {
3376 /* We already parsed a vote with this algorithm from this voter. Use the
3378 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "We received a networkstatus "
3379 "that contains two signatures from the same voter with the same "
3380 "algorithm. Ignoring the second signature.");
3385 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3386 if (check_signature_token(ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
,
3387 tok
, ns
->cert
->signing_key
, 0,
3388 "network-status document")) {
3392 sig
->good_signature
= 1;
3394 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
3398 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
3399 sig
->signature_len
= (int) tok
->object_size
;
3401 smartlist_add(v
->sigs
, sig
);
3404 } SMARTLIST_FOREACH_END(_tok
);
3406 if (! n_signatures
) {
3407 log_warn(LD_DIR
, "No signatures on networkstatus document.");
3409 } else if (ns
->type
== NS_TYPE_VOTE
&& n_signatures
!= 1) {
3410 log_warn(LD_DIR
, "Received more than one signature on a "
3411 "network-status vote.");
3416 *eos_out
= end_of_footer
;
3420 dump_desc(s_dup
, "v3 networkstatus");
3421 networkstatus_vote_free(ns
);
3425 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
3426 smartlist_free(tokens
);
3430 SMARTLIST_FOREACH(voter
->sigs
, document_signature_t
*, sig
,
3431 document_signature_free(sig
));
3432 smartlist_free(voter
->sigs
);
3434 tor_free(voter
->nickname
);
3435 tor_free(voter
->address
);
3436 tor_free(voter
->contact
);
3440 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_clear(t
));
3441 smartlist_free(rs_tokens
);
3443 if (footer_tokens
) {
3444 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_clear(t
));
3445 smartlist_free(footer_tokens
);
3448 DUMP_AREA(area
, "v3 networkstatus");
3449 memarea_drop_all(area
);
3452 memarea_drop_all(rs_area
);
3458 /** Return the common_digests_t that holds the digests of the
3459 * <b>flavor_name</b>-flavored networkstatus according to the detached
3460 * signatures document <b>sigs</b>, allocating a new common_digests_t as
3462 static common_digests_t
*
3463 detached_get_digests(ns_detached_signatures_t
*sigs
, const char *flavor_name
)
3465 common_digests_t
*d
= strmap_get(sigs
->digests
, flavor_name
);
3467 d
= tor_malloc_zero(sizeof(common_digests_t
));
3468 strmap_set(sigs
->digests
, flavor_name
, d
);
3473 /** Return the list of signatures of the <b>flavor_name</b>-flavored
3474 * networkstatus according to the detached signatures document <b>sigs</b>,
3475 * allocating a new common_digests_t as neeeded. */
3476 static smartlist_t
*
3477 detached_get_signatures(ns_detached_signatures_t
*sigs
,
3478 const char *flavor_name
)
3480 smartlist_t
*sl
= strmap_get(sigs
->signatures
, flavor_name
);
3482 sl
= smartlist_new();
3483 strmap_set(sigs
->signatures
, flavor_name
, sl
);
3488 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
3489 * <b>eos</b> and return the result. Return -1 on failure. */
3490 ns_detached_signatures_t
*
3491 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
3493 /* XXXX there is too much duplicate shared between this function and
3494 * networkstatus_parse_vote_from_string(). */
3495 directory_token_t
*tok
;
3496 memarea_t
*area
= NULL
;
3497 common_digests_t
*digests
;
3499 smartlist_t
*tokens
= smartlist_new();
3500 ns_detached_signatures_t
*sigs
=
3501 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
3502 sigs
->digests
= strmap_new();
3503 sigs
->signatures
= strmap_new();
3506 eos
= s
+ strlen(s
);
3508 area
= memarea_new();
3509 if (tokenize_string(area
,s
, eos
, tokens
,
3510 networkstatus_detached_signature_token_table
, 0)) {
3511 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
3515 /* Grab all the digest-like tokens. */
3516 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3517 const char *algname
;
3518 digest_algorithm_t alg
;
3520 const char *hexdigest
;
3521 size_t expected_length
, digest_length
;
3525 if (tok
->tp
== K_CONSENSUS_DIGEST
) {
3529 hexdigest
= tok
->args
[0];
3530 } else if (tok
->tp
== K_ADDITIONAL_DIGEST
) {
3531 int a
= crypto_digest_algorithm_parse_name(tok
->args
[1]);
3533 log_warn(LD_DIR
, "Unrecognized algorithm name %s", tok
->args
[0]);
3536 alg
= (digest_algorithm_t
) a
;
3537 flavor
= tok
->args
[0];
3538 algname
= tok
->args
[1];
3539 hexdigest
= tok
->args
[2];
3544 digest_length
= crypto_digest_algorithm_get_length(alg
);
3545 expected_length
= digest_length
* 2; /* hex encoding */
3547 if (strlen(hexdigest
) != expected_length
) {
3548 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
3549 "networkstatus signatures");
3552 digests
= detached_get_digests(sigs
, flavor
);
3553 tor_assert(digests
);
3554 if (!tor_mem_is_zero(digests
->d
[alg
], digest_length
)) {
3555 log_warn(LD_DIR
, "Multiple digests for %s with %s on detached "
3556 "signatures document", flavor
, algname
);
3559 if (base16_decode(digests
->d
[alg
], digest_length
,
3560 hexdigest
, strlen(hexdigest
)) != (int) digest_length
) {
3561 log_warn(LD_DIR
, "Bad encoding on consensus-digest in detached "
3562 "networkstatus signatures");
3565 } SMARTLIST_FOREACH_END(_tok
);
3567 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
3568 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
3569 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
3573 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
3574 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
3575 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
3579 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
3580 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
3581 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
3585 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3586 const char *id_hexdigest
;
3587 const char *sk_hexdigest
;
3588 const char *algname
;
3590 digest_algorithm_t alg
;
3592 char id_digest
[DIGEST_LEN
];
3593 char sk_digest
[DIGEST_LEN
];
3594 smartlist_t
*siglist
;
3595 document_signature_t
*sig
;
3599 if (tok
->tp
== K_DIRECTORY_SIGNATURE
) {
3600 tor_assert(tok
->n_args
>= 2);
3603 id_hexdigest
= tok
->args
[0];
3604 sk_hexdigest
= tok
->args
[1];
3605 } else if (tok
->tp
== K_ADDITIONAL_SIGNATURE
) {
3606 tor_assert(tok
->n_args
>= 4);
3607 flavor
= tok
->args
[0];
3608 algname
= tok
->args
[1];
3609 id_hexdigest
= tok
->args
[2];
3610 sk_hexdigest
= tok
->args
[3];
3616 int a
= crypto_digest_algorithm_parse_name(algname
);
3618 log_warn(LD_DIR
, "Unrecognized algorithm name %s", algname
);
3621 alg
= (digest_algorithm_t
) a
;
3624 if (!tok
->object_type
||
3625 strcmp(tok
->object_type
, "SIGNATURE") ||
3626 tok
->object_size
< 128 || tok
->object_size
> 512) {
3627 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
3631 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
3632 base16_decode(id_digest
, sizeof(id_digest
),
3633 id_hexdigest
, HEX_DIGEST_LEN
) != sizeof(id_digest
)) {
3634 log_warn(LD_DIR
, "Error decoding declared identity %s in "
3635 "network-status vote.", escaped(id_hexdigest
));
3638 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
3639 base16_decode(sk_digest
, sizeof(sk_digest
),
3640 sk_hexdigest
, HEX_DIGEST_LEN
) != sizeof(sk_digest
)) {
3641 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
3642 "network-status vote.", escaped(sk_hexdigest
));
3646 siglist
= detached_get_signatures(sigs
, flavor
);
3648 SMARTLIST_FOREACH(siglist
, document_signature_t
*, dsig
, {
3649 if (dsig
->alg
== alg
&&
3650 tor_memeq(id_digest
, dsig
->identity_digest
, DIGEST_LEN
) &&
3651 tor_memeq(sk_digest
, dsig
->signing_key_digest
, DIGEST_LEN
)) {
3656 log_warn(LD_DIR
, "Two signatures with identical keys and algorithm "
3661 sig
= tor_malloc_zero(sizeof(document_signature_t
));
3663 memcpy(sig
->identity_digest
, id_digest
, DIGEST_LEN
);
3664 memcpy(sig
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
3665 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
3669 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
3670 sig
->signature_len
= (int) tok
->object_size
;
3672 smartlist_add(siglist
, sig
);
3673 } SMARTLIST_FOREACH_END(_tok
);
3677 ns_detached_signatures_free(sigs
);
3680 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
3681 smartlist_free(tokens
);
3683 DUMP_AREA(area
, "detached signatures");
3684 memarea_drop_all(area
);
3689 /** Parse the addr policy in the string <b>s</b> and return it. If
3690 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
3691 * ADDR_POLICY_REJECT) for items that specify no action.
3693 * Returns NULL on policy errors.
3695 * Set *<b>malformed_list</b> to true if the entire policy list should be
3696 * discarded. Otherwise, set it to false, and only this item should be ignored
3697 * on error - the rest of the policy list can continue to be processed and
3700 * The addr_policy_t returned by this function can have its address set to
3701 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
3702 * of AF_INET and AF_INET6 items.
3704 MOCK_IMPL(addr_policy_t
*,
3705 router_parse_addr_policy_item_from_string
,(const char *s
, int assume_action
,
3706 int *malformed_list
))
3708 directory_token_t
*tok
= NULL
;
3709 const char *cp
, *eos
;
3710 /* Longest possible policy is
3711 * "accept6 [ffff:ffff:..255]/128:10000-65535",
3712 * which contains a max-length IPv6 address, plus 26 characters.
3713 * But note that there can be an arbitrary amount of space between the
3714 * accept and the address:mask/port element.
3715 * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
3716 * IPv6 address. But making the buffer shorter might cause valid long lines,
3717 * which parsed in previous versions, to fail to parse in new versions.
3718 * (These lines would have to have excessive amounts of whitespace.) */
3719 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
3721 memarea_t
*area
= NULL
;
3723 tor_assert(malformed_list
);
3724 *malformed_list
= 0;
3726 s
= eat_whitespace(s
);
3727 /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
3728 * and ":" (port separator) are ambiguous */
3729 if ((*s
== '*' || *s
== '[' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
3730 if (tor_snprintf(line
, sizeof(line
), "%s %s",
3731 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
3732 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
3737 } else { /* assume an already well-formed address policy line */
3741 eos
= cp
+ strlen(cp
);
3742 area
= memarea_new();
3743 tok
= get_next_token(area
, &cp
, eos
, routerdesc_token_table
);
3744 if (tok
->tp
== ERR_
) {
3745 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
3748 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_ACCEPT6
&&
3749 tok
->tp
!= K_REJECT
&& tok
->tp
!= K_REJECT6
) {
3750 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
3754 /* Use the extended interpretation of accept/reject *,
3755 * expanding it into an IPv4 wildcard and an IPv6 wildcard.
3756 * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
3757 r
= router_parse_addr_policy(tok
, TAPMP_EXTENDED_STAR
);
3762 /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
3763 * AF_UNSPEC addresses are only permitted on the accept/reject field type.
3764 * Unlike descriptors, torrcs exit policy accept/reject can be followed by
3765 * either an IPv4 or IPv6 address. */
3766 if ((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
3767 tor_addr_family(&r
->addr
) != AF_INET6
) {
3768 /* This is a non-fatal error, just ignore this one entry. */
3769 *malformed_list
= 0;
3770 log_warn(LD_DIR
, "IPv4 address '%s' with accept6/reject6 field type in "
3771 "exit policy. Ignoring, but continuing to parse rules. (Use "
3772 "accept/reject with IPv4 addresses.)",
3773 tok
->n_args
== 1 ? tok
->args
[0] : "");
3774 addr_policy_free(r
);
3781 *malformed_list
= 1;
3786 DUMP_AREA(area
, "policy item");
3787 memarea_drop_all(area
);
3792 /** Add an exit policy stored in the token <b>tok</b> to the router info in
3793 * <b>router</b>. Return 0 on success, -1 on failure. */
3795 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
3797 addr_policy_t
*newe
;
3798 /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
3799 newe
= router_parse_addr_policy(tok
, 0);
3802 if (! router
->exit_policy
)
3803 router
->exit_policy
= smartlist_new();
3805 /* Ensure that in descriptors, accept/reject fields are followed by
3806 * IPv4 addresses, and accept6/reject6 fields are followed by
3807 * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
3808 * accept/reject followed by IPv6. */
3809 if (((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
3810 tor_addr_family(&newe
->addr
) == AF_INET
)
3812 ((tok
->tp
== K_ACCEPT
|| tok
->tp
== K_REJECT
) &&
3813 tor_addr_family(&newe
->addr
) == AF_INET6
)) {
3814 /* There's nothing the user can do about other relays' descriptors,
3815 * so we don't provide usage advice here. */
3816 log_warn(LD_DIR
, "Mismatch between field type and address type in exit "
3817 "policy '%s'. Discarding entire router descriptor.",
3818 tok
->n_args
== 1 ? tok
->args
[0] : "");
3819 addr_policy_free(newe
);
3823 smartlist_add(router
->exit_policy
, newe
);
3828 /** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
3829 * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
3830 * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
3831 * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
3833 static addr_policy_t
*
3834 router_parse_addr_policy(directory_token_t
*tok
, unsigned fmt_flags
)
3839 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
||
3840 tok
->tp
== K_ACCEPT
|| tok
->tp
== K_ACCEPT6
);
3842 if (tok
->n_args
!= 1)
3846 if (!strcmpstart(arg
,"private"))
3847 return router_parse_addr_policy_private(tok
);
3849 memset(&newe
, 0, sizeof(newe
));
3851 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
3852 newe
.policy_type
= ADDR_POLICY_REJECT
;
3854 newe
.policy_type
= ADDR_POLICY_ACCEPT
;
3856 /* accept6/reject6 * produces an IPv6 wildcard address only.
3857 * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
3858 if ((fmt_flags
& TAPMP_EXTENDED_STAR
)
3859 && (tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
)) {
3860 fmt_flags
|= TAPMP_STAR_IPV6_ONLY
;
3863 if (tor_addr_parse_mask_ports(arg
, fmt_flags
, &newe
.addr
, &newe
.maskbits
,
3864 &newe
.prt_min
, &newe
.prt_max
) < 0) {
3865 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
3869 return addr_policy_get_canonical_entry(&newe
);
3872 /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
3873 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
3874 * router descriptors until earlier versions are obsolete.
3876 * accept/reject and accept6/reject6 private all produce rules for both
3877 * IPv4 and IPv6 addresses.
3879 static addr_policy_t
*
3880 router_parse_addr_policy_private(directory_token_t
*tok
)
3883 uint16_t port_min
, port_max
;
3884 addr_policy_t result
;
3887 if (strcmpstart(arg
, "private"))
3890 arg
+= strlen("private");
3891 arg
= (char*) eat_whitespace(arg
);
3892 if (!arg
|| *arg
!= ':')
3895 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
3898 memset(&result
, 0, sizeof(result
));
3899 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
3900 result
.policy_type
= ADDR_POLICY_REJECT
;
3902 result
.policy_type
= ADDR_POLICY_ACCEPT
;
3903 result
.is_private
= 1;
3904 result
.prt_min
= port_min
;
3905 result
.prt_max
= port_max
;
3907 if (tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) {
3908 log_warn(LD_GENERAL
,
3909 "'%s' expands into rules which apply to all private IPv4 and "
3910 "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
3911 "IPv6.)", tok
->n_args
== 1 ? tok
->args
[0] : "");
3914 return addr_policy_get_canonical_entry(&result
);
3917 /** Log and exit if <b>t</b> is malformed */
3919 assert_addr_policy_ok(smartlist_t
*lst
)
3922 SMARTLIST_FOREACH(lst
, addr_policy_t
*, t
, {
3923 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
3924 t
->policy_type
== ADDR_POLICY_ACCEPT
);
3925 tor_assert(t
->prt_min
<= t
->prt_max
);
3930 * Low-level tokenizer for router descriptors and directories.
3933 /** Free all resources allocated for <b>tok</b> */
3935 token_clear(directory_token_t
*tok
)
3938 crypto_pk_free(tok
->key
);
3941 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
3942 #define ALLOC(sz) memarea_alloc(area,sz)
3943 #define STRDUP(str) memarea_strdup(area,str)
3944 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
3946 #define RET_ERR(msg) \
3948 if (tok) token_clear(tok); \
3949 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
3951 tok->error = STRDUP(msg); \
3952 goto done_tokenizing; \
3955 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
3956 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
3957 * Return <b>tok</b> on success, or a new ERR_ token if the token didn't
3958 * conform to the syntax we wanted.
3960 static inline directory_token_t
*
3961 token_check_object(memarea_t
*area
, const char *kwd
,
3962 directory_token_t
*tok
, obj_syntax o_syn
)
3967 /* No object is allowed for this token. */
3968 if (tok
->object_body
) {
3969 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected object for %s", kwd
);
3973 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected public key for %s", kwd
);
3978 /* There must be a (non-key) object. */
3979 if (!tok
->object_body
) {
3980 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing object for %s", kwd
);
3984 case NEED_KEY_1024
: /* There must be a 1024-bit public key. */
3985 case NEED_SKEY_1024
: /* There must be a 1024-bit private key. */
3986 if (tok
->key
&& crypto_pk_num_bits(tok
->key
) != PK_BYTES
*8) {
3987 tor_snprintf(ebuf
, sizeof(ebuf
), "Wrong size on key for %s: %d bits",
3988 kwd
, crypto_pk_num_bits(tok
->key
));
3992 case NEED_KEY
: /* There must be some kind of key. */
3994 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing public key for %s", kwd
);
3997 if (o_syn
!= NEED_SKEY_1024
) {
3998 if (crypto_pk_key_is_private(tok
->key
)) {
3999 tor_snprintf(ebuf
, sizeof(ebuf
),
4000 "Private key given for %s, which wants a public key", kwd
);
4003 } else { /* o_syn == NEED_SKEY_1024 */
4004 if (!crypto_pk_key_is_private(tok
->key
)) {
4005 tor_snprintf(ebuf
, sizeof(ebuf
),
4006 "Public key given for %s, which wants a private key", kwd
);
4012 /* Anything goes with this token. */
4020 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
4021 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
4022 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
4023 * all storage in <b>area</b>. Return the number of arguments parsed, or
4024 * return -1 if there was an insanely high number of arguments. */
4026 get_token_arguments(memarea_t
*area
, directory_token_t
*tok
,
4027 const char *s
, const char *eol
)
4029 /** Largest number of arguments we'll accept to any token, ever. */
4030 #define MAX_ARGS 512
4031 char *mem
= memarea_strndup(area
, s
, eol
-s
);
4034 char *args
[MAX_ARGS
];
4039 cp
= (char*)find_whitespace(cp
);
4041 break; /* End of the line. */
4043 cp
= (char*)eat_whitespace(cp
);
4046 tok
->args
= memarea_memdup(area
, args
, j
*sizeof(char*));
4051 /** Helper function: read the next token from *s, advance *s to the end of the
4052 * token, and return the parsed token. Parse *<b>s</b> according to the list
4053 * of tokens in <b>table</b>.
4055 static directory_token_t
*
4056 get_next_token(memarea_t
*area
,
4057 const char **s
, const char *eos
, token_rule_t
*table
)
4059 /** Reject any object at least this big; it is probably an overflow, an
4060 * attack, a bug, or some other nonsense. */
4061 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
4062 /** Reject any line at least this big; it is probably an overflow, an
4063 * attack, a bug, or some other nonsense. */
4064 #define MAX_LINE_LENGTH (128*1024)
4066 const char *next
, *eol
, *obstart
;
4069 directory_token_t
*tok
;
4070 obj_syntax o_syn
= NO_OBJ
;
4072 const char *kwd
= "";
4075 tok
= ALLOC_ZERO(sizeof(directory_token_t
));
4078 /* Set *s to first token, eol to end-of-line, next to after first token */
4079 *s
= eat_whitespace_eos(*s
, eos
); /* eat multi-line whitespace */
4080 tor_assert(eos
>= *s
);
4081 eol
= memchr(*s
, '\n', eos
-*s
);
4084 if (eol
- *s
> MAX_LINE_LENGTH
) {
4085 RET_ERR("Line far too long");
4088 next
= find_whitespace_eos(*s
, eol
);
4090 if (!strcmp_len(*s
, "opt", next
-*s
)) {
4091 /* Skip past an "opt" at the start of the line. */
4092 *s
= eat_whitespace_eos_no_nl(next
, eol
);
4093 next
= find_whitespace_eos(*s
, eol
);
4094 } else if (*s
== eos
) { /* If no "opt", and end-of-line, line is invalid */
4095 RET_ERR("Unexpected EOF");
4098 /* Search the table for the appropriate entry. (I tried a binary search
4099 * instead, but it wasn't any faster.) */
4100 for (i
= 0; table
[i
].t
; ++i
) {
4101 if (!strcmp_len(*s
, table
[i
].t
, next
-*s
)) {
4102 /* We've found the keyword. */
4104 tok
->tp
= table
[i
].v
;
4105 o_syn
= table
[i
].os
;
4106 *s
= eat_whitespace_eos_no_nl(next
, eol
);
4107 /* We go ahead whether there are arguments or not, so that tok->args is
4108 * always set if we want arguments. */
4109 if (table
[i
].concat_args
) {
4110 /* The keyword takes the line as a single argument */
4111 tok
->args
= ALLOC(sizeof(char*));
4112 tok
->args
[0] = STRNDUP(*s
,eol
-*s
); /* Grab everything on line */
4115 /* This keyword takes multiple arguments. */
4116 if (get_token_arguments(area
, tok
, *s
, eol
)<0) {
4117 tor_snprintf(ebuf
, sizeof(ebuf
),"Far too many arguments to %s", kwd
);
4122 if (tok
->n_args
< table
[i
].min_args
) {
4123 tor_snprintf(ebuf
, sizeof(ebuf
), "Too few arguments to %s", kwd
);
4125 } else if (tok
->n_args
> table
[i
].max_args
) {
4126 tor_snprintf(ebuf
, sizeof(ebuf
), "Too many arguments to %s", kwd
);
4133 if (tok
->tp
== ERR_
) {
4134 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
4136 tok
->tp
= A_UNKNOWN_
;
4139 tok
->args
= ALLOC(sizeof(char*));
4140 tok
->args
[0] = STRNDUP(*s
, eol
-*s
);
4145 /* Check whether there's an object present */
4146 *s
= eat_whitespace_eos(eol
, eos
); /* Scan from end of first line */
4147 tor_assert(eos
>= *s
);
4148 eol
= memchr(*s
, '\n', eos
-*s
);
4149 if (!eol
|| eol
-*s
<11 || strcmpstart(*s
, "-----BEGIN ")) /* No object. */
4152 obstart
= *s
; /* Set obstart to start of object spec */
4153 if (*s
+16 >= eol
|| memchr(*s
+11,'\0',eol
-*s
-16) || /* no short lines, */
4154 strcmp_len(eol
-5, "-----", 5) || /* nuls or invalid endings */
4155 (eol
-*s
) > MAX_UNPARSED_OBJECT_SIZE
) { /* name too long */
4156 RET_ERR("Malformed object: bad begin line");
4158 tok
->object_type
= STRNDUP(*s
+11, eol
-*s
-16);
4159 obname_len
= eol
-*s
-16; /* store objname length here to avoid a strlen() */
4160 *s
= eol
+1; /* Set *s to possible start of object data (could be eos) */
4162 /* Go to the end of the object */
4163 next
= tor_memstr(*s
, eos
-*s
, "-----END ");
4165 RET_ERR("Malformed object: missing object end line");
4167 tor_assert(eos
>= next
);
4168 eol
= memchr(next
, '\n', eos
-next
);
4169 if (!eol
) /* end-of-line marker, or eos if there's no '\n' */
4171 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
4172 if ((size_t)(eol
-next
) != 9+obname_len
+5 ||
4173 strcmp_len(next
+9, tok
->object_type
, obname_len
) ||
4174 strcmp_len(eol
-5, "-----", 5)) {
4175 tor_snprintf(ebuf
, sizeof(ebuf
), "Malformed object: mismatched end tag %s",
4177 ebuf
[sizeof(ebuf
)-1] = '\0';
4180 if (next
- *s
> MAX_UNPARSED_OBJECT_SIZE
)
4181 RET_ERR("Couldn't parse object: missing footer or object much too big.");
4183 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) { /* If it's a public key */
4184 tok
->key
= crypto_pk_new();
4185 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, eol
-obstart
))
4186 RET_ERR("Couldn't parse public key.");
4187 } else if (!strcmp(tok
->object_type
, "RSA PRIVATE KEY")) { /* private key */
4188 tok
->key
= crypto_pk_new();
4189 if (crypto_pk_read_private_key_from_string(tok
->key
, obstart
, eol
-obstart
))
4190 RET_ERR("Couldn't parse private key.");
4191 } else { /* If it's something else, try to base64-decode it */
4193 tok
->object_body
= ALLOC(next
-*s
); /* really, this is too much RAM. */
4194 r
= base64_decode(tok
->object_body
, next
-*s
, *s
, next
-*s
);
4196 RET_ERR("Malformed object: bad base64-encoded data");
4197 tok
->object_size
= r
;
4202 tok
= token_check_object(area
, kwd
, tok
, o_syn
);
4214 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
4215 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
4216 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
4220 tokenize_string(memarea_t
*area
,
4221 const char *start
, const char *end
, smartlist_t
*out
,
4222 token_rule_t
*table
, int flags
)
4225 directory_token_t
*tok
= NULL
;
4228 int first_nonannotation
;
4229 int prev_len
= smartlist_len(out
);
4234 end
= start
+strlen(start
);
4236 /* it's only meaningful to check for nuls if we got an end-of-string ptr */
4237 if (memchr(start
, '\0', end
-start
)) {
4238 log_warn(LD_DIR
, "parse error: internal NUL character.");
4242 for (i
= 0; i
< NIL_
; ++i
)
4245 SMARTLIST_FOREACH(out
, const directory_token_t
*, t
, ++counts
[t
->tp
]);
4247 while (*s
< end
&& (!tok
|| tok
->tp
!= EOF_
)) {
4248 tok
= get_next_token(area
, s
, end
, table
);
4249 if (tok
->tp
== ERR_
) {
4250 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
4255 smartlist_add(out
, tok
);
4256 *s
= eat_whitespace_eos(*s
, end
);
4259 if (flags
& TS_NOCHECK
)
4262 if ((flags
& TS_ANNOTATIONS_OK
)) {
4263 first_nonannotation
= -1;
4264 for (i
= 0; i
< smartlist_len(out
); ++i
) {
4265 tok
= smartlist_get(out
, i
);
4266 if (tok
->tp
< MIN_ANNOTATION
|| tok
->tp
> MAX_ANNOTATION
) {
4267 first_nonannotation
= i
;
4271 if (first_nonannotation
< 0) {
4272 log_warn(LD_DIR
, "parse error: item contains only annotations");
4275 for (i
=first_nonannotation
; i
< smartlist_len(out
); ++i
) {
4276 tok
= smartlist_get(out
, i
);
4277 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
4278 log_warn(LD_DIR
, "parse error: Annotations mixed with keywords");
4282 if ((flags
& TS_NO_NEW_ANNOTATIONS
)) {
4283 if (first_nonannotation
!= prev_len
) {
4284 log_warn(LD_DIR
, "parse error: Unexpected annotations.");
4289 for (i
=0; i
< smartlist_len(out
); ++i
) {
4290 tok
= smartlist_get(out
, i
);
4291 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
4292 log_warn(LD_DIR
, "parse error: no annotations allowed.");
4296 first_nonannotation
= 0;
4298 for (i
= 0; table
[i
].t
; ++i
) {
4299 if (counts
[table
[i
].v
] < table
[i
].min_cnt
) {
4300 log_warn(LD_DIR
, "Parse error: missing %s element.", table
[i
].t
);
4303 if (counts
[table
[i
].v
] > table
[i
].max_cnt
) {
4304 log_warn(LD_DIR
, "Parse error: too many %s elements.", table
[i
].t
);
4307 if (table
[i
].pos
& AT_START
) {
4308 if (smartlist_len(out
) < 1 ||
4309 (tok
= smartlist_get(out
, first_nonannotation
))->tp
!= table
[i
].v
) {
4310 log_warn(LD_DIR
, "Parse error: first item is not %s.", table
[i
].t
);
4314 if (table
[i
].pos
& AT_END
) {
4315 if (smartlist_len(out
) < 1 ||
4316 (tok
= smartlist_get(out
, smartlist_len(out
)-1))->tp
!= table
[i
].v
) {
4317 log_warn(LD_DIR
, "Parse error: last item is not %s.", table
[i
].t
);
4325 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
4326 * NULL if no such keyword is found.
4328 static directory_token_t
*
4329 find_opt_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
4331 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
4335 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
4336 * with an assert if no such keyword is found.
4338 static directory_token_t
*
4339 find_by_keyword_(smartlist_t
*s
, directory_keyword keyword
,
4340 const char *keyword_as_string
)
4342 directory_token_t
*tok
= find_opt_by_keyword(s
, keyword
);
4343 if (PREDICT_UNLIKELY(!tok
)) {
4344 log_err(LD_BUG
, "Missing %s [%d] in directory object that should have "
4345 "been validated. Internal error.", keyword_as_string
, (int)keyword
);
4351 /** If there are any directory_token_t entries in <b>s</b> whose keyword is
4352 * <b>k</b>, return a newly allocated smartlist_t containing all such entries,
4353 * in the same order in which they occur in <b>s</b>. Otherwise return
4355 static smartlist_t
*
4356 find_all_by_keyword(smartlist_t
*s
, directory_keyword k
)
4358 smartlist_t
*out
= NULL
;
4359 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
4362 out
= smartlist_new();
4363 smartlist_add(out
, t
);
4368 /** Return a newly allocated smartlist of all accept or reject tokens in
4371 static smartlist_t
*
4372 find_all_exitpolicy(smartlist_t
*s
)
4374 smartlist_t
*out
= smartlist_new();
4375 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
4376 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_ACCEPT6
||
4377 t
->tp
== K_REJECT
|| t
->tp
== K_REJECT6
)
4378 smartlist_add(out
,t
));
4382 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
4383 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
4384 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
4385 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
4387 * Return 0 on success and -1 on failure.
4390 router_get_hash_impl_helper(const char *s
, size_t s_len
,
4391 const char *start_str
,
4392 const char *end_str
, char end_c
,
4393 const char **start_out
, const char **end_out
)
4395 const char *start
, *end
;
4396 start
= tor_memstr(s
, s_len
, start_str
);
4398 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
4401 if (start
!= s
&& *(start
-1) != '\n') {
4403 "first occurrence of \"%s\" is not at the start of a line",
4407 end
= tor_memstr(start
+strlen(start_str
),
4408 s_len
- (start
-s
) - strlen(start_str
), end_str
);
4410 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
4413 end
= memchr(end
+strlen(end_str
), end_c
, s_len
- (end
-s
) - strlen(end_str
));
4415 log_warn(LD_DIR
,"couldn't find EOL");
4425 /** Compute the digest of the substring of <b>s</b> taken from the first
4426 * occurrence of <b>start_str</b> through the first instance of c after the
4427 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
4428 * result in <b>digest</b>; return 0 on success.
4430 * If no such substring exists, return -1.
4433 router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
4434 const char *start_str
,
4435 const char *end_str
, char end_c
,
4436 digest_algorithm_t alg
)
4438 const char *start
=NULL
, *end
=NULL
;
4439 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,
4443 if (alg
== DIGEST_SHA1
) {
4444 if (crypto_digest(digest
, start
, end
-start
)) {
4445 log_warn(LD_BUG
,"couldn't compute digest");
4449 if (crypto_digest256(digest
, start
, end
-start
, alg
)) {
4450 log_warn(LD_BUG
,"couldn't compute digest");
4458 /** As router_get_hash_impl, but compute all hashes. */
4460 router_get_hashes_impl(const char *s
, size_t s_len
, common_digests_t
*digests
,
4461 const char *start_str
,
4462 const char *end_str
, char end_c
)
4464 const char *start
=NULL
, *end
=NULL
;
4465 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,
4469 if (crypto_common_digests(digests
, start
, end
-start
)) {
4470 log_warn(LD_BUG
,"couldn't compute digests");
4477 /** Assuming that s starts with a microdesc, return the start of the
4478 * *NEXT* one. Return NULL on "not found." */
4480 find_start_of_next_microdesc(const char *s
, const char *eos
)
4482 int started_with_annotations
;
4483 s
= eat_whitespace_eos(s
, eos
);
4487 #define CHECK_LENGTH() STMT_BEGIN \
4492 #define NEXT_LINE() STMT_BEGIN \
4493 s = memchr(s, '\n', eos-s); \
4494 if (!s || s+1 >= eos) \
4501 started_with_annotations
= (*s
== '@');
4503 if (started_with_annotations
) {
4504 /* Start by advancing to the first non-annotation line. */
4510 /* Now we should be pointed at an onion-key line. If we are, then skip
4512 if (!strcmpstart(s
, "onion-key"))
4515 /* Okay, now we're pointed at the first line of the microdescriptor which is
4516 not an annotation or onion-key. The next line that _is_ an annotation or
4517 onion-key is the start of the next microdescriptor. */
4518 while (s
+32 < eos
) {
4519 if (*s
== '@' || !strcmpstart(s
, "onion-key"))
4529 /** Parse as many microdescriptors as are found from the string starting at
4530 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4531 * annotations we recognize and ignore ones we don't.
4533 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
4534 * descriptor in the body field of each microdesc_t.
4536 * Return all newly parsed microdescriptors in a newly allocated
4537 * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
4538 * microdesc digest to it for every microdesc that we found to be badly
4539 * formed. (This may cause duplicates) */
4541 microdescs_parse_from_string(const char *s
, const char *eos
,
4542 int allow_annotations
,
4543 saved_location_t where
,
4544 smartlist_t
*invalid_digests_out
)
4546 smartlist_t
*tokens
;
4547 smartlist_t
*result
;
4548 microdesc_t
*md
= NULL
;
4550 const char *start
= s
;
4551 const char *start_of_next_microdesc
;
4552 int flags
= allow_annotations
? TS_ANNOTATIONS_OK
: 0;
4553 const int copy_body
= (where
!= SAVED_IN_CACHE
);
4555 directory_token_t
*tok
;
4558 eos
= s
+ strlen(s
);
4560 s
= eat_whitespace_eos(s
, eos
);
4561 area
= memarea_new();
4562 result
= smartlist_new();
4563 tokens
= smartlist_new();
4568 start_of_next_microdesc
= find_start_of_next_microdesc(s
, eos
);
4569 if (!start_of_next_microdesc
)
4570 start_of_next_microdesc
= eos
;
4572 md
= tor_malloc_zero(sizeof(microdesc_t
));
4574 const char *cp
= tor_memstr(s
, start_of_next_microdesc
-s
,
4576 const int no_onion_key
= (cp
== NULL
);
4578 cp
= s
; /* So that we have *some* junk to put in the body */
4581 md
->bodylen
= start_of_next_microdesc
- cp
;
4582 md
->saved_location
= where
;
4584 md
->body
= tor_memdup_nulterm(cp
, md
->bodylen
);
4586 md
->body
= (char*)cp
;
4587 md
->off
= cp
- start
;
4588 crypto_digest256(md
->digest
, md
->body
, md
->bodylen
, DIGEST_SHA256
);
4590 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "Malformed or truncated descriptor");
4595 if (tokenize_string(area
, s
, start_of_next_microdesc
, tokens
,
4596 microdesc_token_table
, flags
)) {
4597 log_warn(LD_DIR
, "Unparseable microdescriptor");
4601 if ((tok
= find_opt_by_keyword(tokens
, A_LAST_LISTED
))) {
4602 if (parse_iso_time(tok
->args
[0], &md
->last_listed
)) {
4603 log_warn(LD_DIR
, "Bad last-listed time in microdescriptor");
4608 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
4609 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
4611 "Relay's onion key had invalid exponent.");
4614 md
->onion_pkey
= tok
->key
;
4617 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
4618 curve25519_public_key_t k
;
4619 tor_assert(tok
->n_args
>= 1);
4620 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
4621 log_warn(LD_DIR
, "Bogus ntor-onion-key in microdesc");
4624 md
->onion_curve25519_pkey
=
4625 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
4628 smartlist_t
*id_lines
= find_all_by_keyword(tokens
, K_ID
);
4630 SMARTLIST_FOREACH_BEGIN(id_lines
, directory_token_t
*, t
) {
4631 tor_assert(t
->n_args
>= 2);
4632 if (!strcmp(t
->args
[0], "ed25519")) {
4633 if (md
->ed25519_identity_pkey
) {
4634 log_warn(LD_DIR
, "Extra ed25519 key in microdesc");
4637 ed25519_public_key_t k
;
4638 if (ed25519_public_from_base64(&k
, t
->args
[1])<0) {
4639 log_warn(LD_DIR
, "Bogus ed25519 key in microdesc");
4642 md
->ed25519_identity_pkey
= tor_memdup(&k
, sizeof(k
));
4644 } SMARTLIST_FOREACH_END(t
);
4645 smartlist_free(id_lines
);
4649 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
4651 find_single_ipv6_orport(a_lines
, &md
->ipv6_addr
, &md
->ipv6_orport
);
4652 smartlist_free(a_lines
);
4656 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
))) {
4658 md
->family
= smartlist_new();
4659 for (i
=0;i
<tok
->n_args
;++i
) {
4660 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
4661 log_warn(LD_DIR
, "Illegal nickname %s in family line",
4662 escaped(tok
->args
[i
]));
4665 smartlist_add(md
->family
, tor_strdup(tok
->args
[i
]));
4669 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
4670 md
->exit_policy
= parse_short_policy(tok
->args
[0]);
4672 if ((tok
= find_opt_by_keyword(tokens
, K_P6
))) {
4673 md
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
4676 smartlist_add(result
, md
);
4681 if (! okay
&& invalid_digests_out
) {
4682 smartlist_add(invalid_digests_out
,
4683 tor_memdup(md
->digest
, DIGEST256_LEN
));
4688 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4689 memarea_clear(area
);
4690 smartlist_clear(tokens
);
4691 s
= start_of_next_microdesc
;
4694 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4695 memarea_drop_all(area
);
4696 smartlist_free(tokens
);
4701 /** Parse the Tor version of the platform string <b>platform</b>,
4702 * and compare it to the version in <b>cutoff</b>. Return 1 if
4703 * the router is at least as new as the cutoff, else return 0.
4706 tor_version_as_new_as(const char *platform
, const char *cutoff
)
4708 tor_version_t cutoff_version
, router_version
;
4709 char *s
, *s2
, *start
;
4712 tor_assert(platform
);
4714 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
4715 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
4718 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
4721 start
= (char *)eat_whitespace(platform
+3);
4722 if (!*start
) return 0;
4723 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
4724 s2
= (char*)eat_whitespace(s
);
4725 if (!strcmpstart(s2
, "(r") || !strcmpstart(s2
, "(git-"))
4726 s
= (char*)find_whitespace(s2
);
4728 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
4730 strlcpy(tmp
, start
, s
-start
+1);
4732 if (tor_version_parse(tmp
, &router_version
)<0) {
4733 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
4734 return 1; /* be safe and say yes */
4737 /* Here's why we don't need to do any special handling for svn revisions:
4738 * - If neither has an svn revision, we're fine.
4739 * - If the router doesn't have an svn revision, we can't assume that it
4740 * is "at least" any svn revision, so we need to return 0.
4741 * - If the target version doesn't have an svn revision, any svn revision
4742 * (or none at all) is good enough, so return 1.
4743 * - If both target and router have an svn revision, we compare them.
4746 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
4749 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4750 * Return 0 on success, -1 on failure. */
4752 tor_version_parse(const char *s
, tor_version_t
*out
)
4755 const char *cp
=NULL
;
4757 * "Tor " ? NUM dot NUM [ dot NUM [ ( pre | rc | dot ) NUM ] ] [ - tag ]
4762 memset(out
, 0, sizeof(tor_version_t
));
4763 out
->status
= VER_RELEASE
;
4764 if (!strcasecmpstart(s
, "Tor "))
4771 out->m = (int)strtol(cp, &eos, 10); \
4772 if (!eos || eos == cp) \
4789 else if (*cp
== '-')
4797 } else if (*cp
== '.') {
4799 } else if (*cp
== '-') {
4801 } else if (0==strncmp(cp
, "pre", 3)) {
4802 out
->status
= VER_PRE
;
4804 } else if (0==strncmp(cp
, "rc", 2)) {
4805 out
->status
= VER_RC
;
4814 /* Get status tag. */
4815 if (*cp
== '-' || *cp
== '.')
4817 eos
= (char*) find_whitespace(cp
);
4818 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
4819 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
4821 memcpy(out
->status_tag
, cp
, eos
-cp
);
4822 out
->status_tag
[eos
-cp
] = 0;
4824 cp
= eat_whitespace(eos
);
4826 if (!strcmpstart(cp
, "(r")) {
4828 out
->svn_revision
= (int) strtol(cp
,&eos
,10);
4829 } else if (!strcmpstart(cp
, "(git-")) {
4830 char *close_paren
= strchr(cp
, ')');
4832 char digest
[DIGEST_LEN
];
4836 if (close_paren
-cp
> HEX_DIGEST_LEN
)
4838 hexlen
= (int)(close_paren
-cp
);
4839 memwipe(digest
, 0, sizeof(digest
));
4840 if ( hexlen
== 0 || (hexlen
% 2) == 1)
4842 if (base16_decode(digest
, hexlen
/2, cp
, hexlen
) != hexlen
/2)
4844 memcpy(out
->git_tag
, digest
, hexlen
/2);
4845 out
->git_tag_len
= hexlen
/2;
4853 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
4856 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
4861 if ((i
= a
->major
- b
->major
))
4863 else if ((i
= a
->minor
- b
->minor
))
4865 else if ((i
= a
->micro
- b
->micro
))
4867 else if ((i
= a
->status
- b
->status
))
4869 else if ((i
= a
->patchlevel
- b
->patchlevel
))
4871 else if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
4873 else if ((i
= a
->svn_revision
- b
->svn_revision
))
4875 else if ((i
= a
->git_tag_len
- b
->git_tag_len
))
4877 else if (a
->git_tag_len
)
4878 return fast_memcmp(a
->git_tag
, b
->git_tag
, a
->git_tag_len
);
4883 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
4886 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
4890 return ((a
->major
== b
->major
) &&
4891 (a
->minor
== b
->minor
) &&
4892 (a
->micro
== b
->micro
));
4895 /** Helper: Given pointers to two strings describing tor versions, return -1
4896 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
4897 * Used to sort a list of versions. */
4899 compare_tor_version_str_ptr_(const void **_a
, const void **_b
)
4901 const char *a
= *_a
, *b
= *_b
;
4903 tor_version_t va
, vb
;
4904 ca
= tor_version_parse(a
, &va
);
4905 cb
= tor_version_parse(b
, &vb
);
4906 /* If they both parse, compare them. */
4908 return tor_version_compare(&va
,&vb
);
4909 /* If one parses, it comes first. */
4914 /* If neither parses, compare strings. Also, the directory server admin
4915 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
4919 /** Sort a list of string-representations of versions in ascending order. */
4921 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
4923 smartlist_sort(versions
, compare_tor_version_str_ptr_
);
4925 if (remove_duplicates
)
4926 smartlist_uniq(versions
, compare_tor_version_str_ptr_
, tor_free_
);
4929 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
4930 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
4931 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
4932 * encrypted introduction points to the newly allocated
4933 * *<b>intro_points_encrypted_out</b>, their encrypted size to
4934 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
4935 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
4936 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
4937 * and -1 for failure.
4939 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
4940 * be strict about time formats.
4943 rend_parse_v2_service_descriptor(rend_service_descriptor_t
**parsed_out
,
4945 char **intro_points_encrypted_out
,
4946 size_t *intro_points_encrypted_size_out
,
4947 size_t *encoded_size_out
,
4948 const char **next_out
, const char *desc
,
4951 rend_service_descriptor_t
*result
=
4952 tor_malloc_zero(sizeof(rend_service_descriptor_t
));
4953 char desc_hash
[DIGEST_LEN
];
4955 smartlist_t
*tokens
= smartlist_new();
4956 directory_token_t
*tok
;
4957 char secret_id_part
[DIGEST_LEN
];
4958 int i
, version
, num_ok
=1;
4959 smartlist_t
*versions
;
4960 char public_key_hash
[DIGEST_LEN
];
4961 char test_desc_id
[DIGEST_LEN
];
4962 memarea_t
*area
= NULL
;
4963 const int strict_time_fmt
= as_hsdir
;
4966 /* Check if desc starts correctly. */
4967 if (strncmp(desc
, "rendezvous-service-descriptor ",
4968 strlen("rendezvous-service-descriptor "))) {
4969 log_info(LD_REND
, "Descriptor does not start correctly.");
4972 /* Compute descriptor hash for later validation. */
4973 if (router_get_hash_impl(desc
, strlen(desc
), desc_hash
,
4974 "rendezvous-service-descriptor ",
4975 "\nsignature", '\n', DIGEST_SHA1
) < 0) {
4976 log_warn(LD_REND
, "Couldn't compute descriptor hash.");
4979 /* Determine end of string. */
4980 eos
= strstr(desc
, "\nrendezvous-service-descriptor ");
4982 eos
= desc
+ strlen(desc
);
4986 if (eos
-desc
> REND_DESC_MAX_SIZE
) {
4987 /* XXXX+ If we are parsing this descriptor as a server, this
4988 * should be a protocol warning. */
4989 log_warn(LD_REND
, "Descriptor length is %d which exceeds "
4990 "maximum rendezvous descriptor size of %d bytes.",
4991 (int)(eos
-desc
), REND_DESC_MAX_SIZE
);
4994 /* Tokenize descriptor. */
4995 area
= memarea_new();
4996 if (tokenize_string(area
, desc
, eos
, tokens
, desc_token_table
, 0)) {
4997 log_warn(LD_REND
, "Error tokenizing descriptor.");
5000 /* Set next to next descriptor, if available. */
5002 /* Set length of encoded descriptor. */
5003 *encoded_size_out
= eos
- desc
;
5004 /* Check min allowed length of token list. */
5005 if (smartlist_len(tokens
) < 7) {
5006 log_warn(LD_REND
, "Impossibly short descriptor.");
5009 /* Parse base32-encoded descriptor ID. */
5010 tok
= find_by_keyword(tokens
, R_RENDEZVOUS_SERVICE_DESCRIPTOR
);
5011 tor_assert(tok
== smartlist_get(tokens
, 0));
5012 tor_assert(tok
->n_args
== 1);
5013 if (!rend_valid_descriptor_id(tok
->args
[0])) {
5014 log_warn(LD_REND
, "Invalid descriptor ID: '%s'", tok
->args
[0]);
5017 if (base32_decode(desc_id_out
, DIGEST_LEN
,
5018 tok
->args
[0], REND_DESC_ID_V2_LEN_BASE32
) < 0) {
5019 log_warn(LD_REND
, "Descriptor ID contains illegal characters: %s",
5023 /* Parse descriptor version. */
5024 tok
= find_by_keyword(tokens
, R_VERSION
);
5025 tor_assert(tok
->n_args
== 1);
5027 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &num_ok
, NULL
);
5028 if (result
->version
!= 2 || !num_ok
) {
5029 /* If it's <2, it shouldn't be under this format. If the number
5030 * is greater than 2, we bumped it because we broke backward
5031 * compatibility. See how version numbers in our other formats
5033 log_warn(LD_REND
, "Unrecognized descriptor version: %s",
5034 escaped(tok
->args
[0]));
5037 /* Parse public key. */
5038 tok
= find_by_keyword(tokens
, R_PERMANENT_KEY
);
5039 result
->pk
= tok
->key
;
5040 tok
->key
= NULL
; /* Prevent free */
5041 /* Parse secret ID part. */
5042 tok
= find_by_keyword(tokens
, R_SECRET_ID_PART
);
5043 tor_assert(tok
->n_args
== 1);
5044 if (strlen(tok
->args
[0]) != REND_SECRET_ID_PART_LEN_BASE32
||
5045 strspn(tok
->args
[0], BASE32_CHARS
) != REND_SECRET_ID_PART_LEN_BASE32
) {
5046 log_warn(LD_REND
, "Invalid secret ID part: '%s'", tok
->args
[0]);
5049 if (base32_decode(secret_id_part
, DIGEST_LEN
, tok
->args
[0], 32) < 0) {
5050 log_warn(LD_REND
, "Secret ID part contains illegal characters: %s",
5054 /* Parse publication time -- up-to-date check is done when storing the
5056 tok
= find_by_keyword(tokens
, R_PUBLICATION_TIME
);
5057 tor_assert(tok
->n_args
== 1);
5058 if (parse_iso_time_(tok
->args
[0], &result
->timestamp
, strict_time_fmt
) < 0) {
5059 log_warn(LD_REND
, "Invalid publication time: '%s'", tok
->args
[0]);
5062 /* Parse protocol versions. */
5063 tok
= find_by_keyword(tokens
, R_PROTOCOL_VERSIONS
);
5064 tor_assert(tok
->n_args
== 1);
5065 versions
= smartlist_new();
5066 smartlist_split_string(versions
, tok
->args
[0], ",",
5067 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
5068 for (i
= 0; i
< smartlist_len(versions
); i
++) {
5069 version
= (int) tor_parse_long(smartlist_get(versions
, i
),
5070 10, 0, INT_MAX
, &num_ok
, NULL
);
5071 if (!num_ok
) /* It's a string; let's ignore it. */
5073 if (version
>= REND_PROTOCOL_VERSION_BITMASK_WIDTH
)
5074 /* Avoid undefined left-shift behaviour. */
5076 result
->protocols
|= 1 << version
;
5078 SMARTLIST_FOREACH(versions
, char *, cp
, tor_free(cp
));
5079 smartlist_free(versions
);
5080 /* Parse encrypted introduction points. Don't verify. */
5081 tok
= find_opt_by_keyword(tokens
, R_INTRODUCTION_POINTS
);
5083 if (strcmp(tok
->object_type
, "MESSAGE")) {
5084 log_warn(LD_DIR
, "Bad object type: introduction points should be of "
5088 *intro_points_encrypted_out
= tor_memdup(tok
->object_body
,
5090 *intro_points_encrypted_size_out
= tok
->object_size
;
5092 *intro_points_encrypted_out
= NULL
;
5093 *intro_points_encrypted_size_out
= 0;
5095 /* Parse and verify signature. */
5096 tok
= find_by_keyword(tokens
, R_SIGNATURE
);
5097 note_crypto_pk_op(VERIFY_RTR
);
5098 if (check_signature_token(desc_hash
, DIGEST_LEN
, tok
, result
->pk
, 0,
5099 "v2 rendezvous service descriptor") < 0)
5101 /* Verify that descriptor ID belongs to public key and secret ID part. */
5102 crypto_pk_get_digest(result
->pk
, public_key_hash
);
5103 rend_get_descriptor_id_bytes(test_desc_id
, public_key_hash
,
5105 if (tor_memneq(desc_id_out
, test_desc_id
, DIGEST_LEN
)) {
5106 log_warn(LD_REND
, "Parsed descriptor ID does not match "
5107 "computed descriptor ID.");
5112 rend_service_descriptor_free(result
);
5116 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5117 smartlist_free(tokens
);
5120 memarea_drop_all(area
);
5121 *parsed_out
= result
;
5127 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
5128 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
5129 * write the result to a newly allocated string that is pointed to by
5130 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
5131 * Return 0 if decryption was successful and -1 otherwise. */
5133 rend_decrypt_introduction_points(char **ipos_decrypted
,
5134 size_t *ipos_decrypted_size
,
5135 const char *descriptor_cookie
,
5136 const char *ipos_encrypted
,
5137 size_t ipos_encrypted_size
)
5139 tor_assert(ipos_encrypted
);
5140 tor_assert(descriptor_cookie
);
5141 if (ipos_encrypted_size
< 2) {
5142 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5146 if (ipos_encrypted
[0] == (int)REND_BASIC_AUTH
) {
5147 char iv
[CIPHER_IV_LEN
], client_id
[REND_BASIC_AUTH_CLIENT_ID_LEN
],
5148 session_key
[CIPHER_KEY_LEN
], *dec
;
5149 int declen
, client_blocks
;
5150 size_t pos
= 0, len
, client_entries_len
;
5151 crypto_digest_t
*digest
;
5152 crypto_cipher_t
*cipher
;
5153 client_blocks
= (int) ipos_encrypted
[1];
5154 client_entries_len
= client_blocks
* REND_BASIC_AUTH_CLIENT_MULTIPLE
*
5155 REND_BASIC_AUTH_CLIENT_ENTRY_LEN
;
5156 if (ipos_encrypted_size
< 2 + client_entries_len
+ CIPHER_IV_LEN
+ 1) {
5157 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5161 memcpy(iv
, ipos_encrypted
+ 2 + client_entries_len
, CIPHER_IV_LEN
);
5162 digest
= crypto_digest_new();
5163 crypto_digest_add_bytes(digest
, descriptor_cookie
, REND_DESC_COOKIE_LEN
);
5164 crypto_digest_add_bytes(digest
, iv
, CIPHER_IV_LEN
);
5165 crypto_digest_get_digest(digest
, client_id
,
5166 REND_BASIC_AUTH_CLIENT_ID_LEN
);
5167 crypto_digest_free(digest
);
5168 for (pos
= 2; pos
< 2 + client_entries_len
;
5169 pos
+= REND_BASIC_AUTH_CLIENT_ENTRY_LEN
) {
5170 if (tor_memeq(ipos_encrypted
+ pos
, client_id
,
5171 REND_BASIC_AUTH_CLIENT_ID_LEN
)) {
5172 /* Attempt to decrypt introduction points. */
5173 cipher
= crypto_cipher_new(descriptor_cookie
);
5174 if (crypto_cipher_decrypt(cipher
, session_key
, ipos_encrypted
5175 + pos
+ REND_BASIC_AUTH_CLIENT_ID_LEN
,
5176 CIPHER_KEY_LEN
) < 0) {
5177 log_warn(LD_REND
, "Could not decrypt session key for client.");
5178 crypto_cipher_free(cipher
);
5181 crypto_cipher_free(cipher
);
5183 len
= ipos_encrypted_size
- 2 - client_entries_len
- CIPHER_IV_LEN
;
5184 dec
= tor_malloc(len
);
5185 declen
= crypto_cipher_decrypt_with_iv(session_key
, dec
, len
,
5186 ipos_encrypted
+ 2 + client_entries_len
,
5187 ipos_encrypted_size
- 2 - client_entries_len
);
5190 log_warn(LD_REND
, "Could not decrypt introduction point string.");
5194 if (fast_memcmpstart(dec
, declen
, "introduction-point ")) {
5195 log_warn(LD_REND
, "Decrypted introduction points don't "
5196 "look like we could parse them.");
5200 *ipos_decrypted
= dec
;
5201 *ipos_decrypted_size
= declen
;
5205 log_warn(LD_REND
, "Could not decrypt introduction points. Please "
5206 "check your authorization for this service!");
5208 } else if (ipos_encrypted
[0] == (int)REND_STEALTH_AUTH
) {
5211 if (ipos_encrypted_size
< CIPHER_IV_LEN
+ 2) {
5212 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5216 dec
= tor_malloc_zero(ipos_encrypted_size
- CIPHER_IV_LEN
- 1);
5218 declen
= crypto_cipher_decrypt_with_iv(descriptor_cookie
, dec
,
5219 ipos_encrypted_size
-
5222 ipos_encrypted_size
- 1);
5225 log_warn(LD_REND
, "Decrypting introduction points failed!");
5229 *ipos_decrypted
= dec
;
5230 *ipos_decrypted_size
= declen
;
5233 log_warn(LD_REND
, "Unknown authorization type number: %d",
5239 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
5240 * length <b>intro_points_encoded_size</b> and write the result to the
5241 * descriptor in <b>parsed</b>; return the number of successfully parsed
5242 * introduction points or -1 in case of a failure. */
5244 rend_parse_introduction_points(rend_service_descriptor_t
*parsed
,
5245 const char *intro_points_encoded
,
5246 size_t intro_points_encoded_size
)
5248 const char *current_ipo
, *end_of_intro_points
;
5249 smartlist_t
*tokens
= NULL
;
5250 directory_token_t
*tok
;
5251 rend_intro_point_t
*intro
;
5252 extend_info_t
*info
;
5253 int result
, num_ok
=1;
5254 memarea_t
*area
= NULL
;
5256 /** Function may only be invoked once. */
5257 tor_assert(!parsed
->intro_nodes
);
5258 if (!intro_points_encoded
|| intro_points_encoded_size
== 0) {
5259 log_warn(LD_REND
, "Empty or zero size introduction point list");
5262 /* Consider one intro point after the other. */
5263 current_ipo
= intro_points_encoded
;
5264 end_of_intro_points
= intro_points_encoded
+ intro_points_encoded_size
;
5265 tokens
= smartlist_new();
5266 parsed
->intro_nodes
= smartlist_new();
5267 area
= memarea_new();
5269 while (!fast_memcmpstart(current_ipo
, end_of_intro_points
-current_ipo
,
5270 "introduction-point ")) {
5271 /* Determine end of string. */
5272 const char *eos
= tor_memstr(current_ipo
, end_of_intro_points
-current_ipo
,
5273 "\nintroduction-point ");
5275 eos
= end_of_intro_points
;
5278 tor_assert(eos
<= intro_points_encoded
+intro_points_encoded_size
);
5279 /* Free tokens and clear token list. */
5280 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5281 smartlist_clear(tokens
);
5282 memarea_clear(area
);
5283 /* Tokenize string. */
5284 if (tokenize_string(area
, current_ipo
, eos
, tokens
, ipo_token_table
, 0)) {
5285 log_warn(LD_REND
, "Error tokenizing introduction point");
5288 /* Advance to next introduction point, if available. */
5290 /* Check minimum allowed length of introduction point. */
5291 if (smartlist_len(tokens
) < 5) {
5292 log_warn(LD_REND
, "Impossibly short introduction point.");
5295 /* Allocate new intro point and extend info. */
5296 intro
= tor_malloc_zero(sizeof(rend_intro_point_t
));
5297 info
= intro
->extend_info
= tor_malloc_zero(sizeof(extend_info_t
));
5298 /* Parse identifier. */
5299 tok
= find_by_keyword(tokens
, R_IPO_IDENTIFIER
);
5300 if (base32_decode(info
->identity_digest
, DIGEST_LEN
,
5301 tok
->args
[0], REND_INTRO_POINT_ID_LEN_BASE32
) < 0) {
5302 log_warn(LD_REND
, "Identity digest contains illegal characters: %s",
5304 rend_intro_point_free(intro
);
5307 /* Write identifier to nickname. */
5308 info
->nickname
[0] = '$';
5309 base16_encode(info
->nickname
+ 1, sizeof(info
->nickname
) - 1,
5310 info
->identity_digest
, DIGEST_LEN
);
5311 /* Parse IP address. */
5312 tok
= find_by_keyword(tokens
, R_IPO_IP_ADDRESS
);
5313 if (tor_addr_parse(&info
->addr
, tok
->args
[0])<0) {
5314 log_warn(LD_REND
, "Could not parse introduction point address.");
5315 rend_intro_point_free(intro
);
5318 if (tor_addr_family(&info
->addr
) != AF_INET
) {
5319 log_warn(LD_REND
, "Introduction point address was not ipv4.");
5320 rend_intro_point_free(intro
);
5324 /* Parse onion port. */
5325 tok
= find_by_keyword(tokens
, R_IPO_ONION_PORT
);
5326 info
->port
= (uint16_t) tor_parse_long(tok
->args
[0],10,1,65535,
5328 if (!info
->port
|| !num_ok
) {
5329 log_warn(LD_REND
, "Introduction point onion port %s is invalid",
5330 escaped(tok
->args
[0]));
5331 rend_intro_point_free(intro
);
5334 /* Parse onion key. */
5335 tok
= find_by_keyword(tokens
, R_IPO_ONION_KEY
);
5336 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
5338 "Introduction point's onion key had invalid exponent.");
5339 rend_intro_point_free(intro
);
5342 info
->onion_key
= tok
->key
;
5343 tok
->key
= NULL
; /* Prevent free */
5344 /* Parse service key. */
5345 tok
= find_by_keyword(tokens
, R_IPO_SERVICE_KEY
);
5346 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
5348 "Introduction point key had invalid exponent.");
5349 rend_intro_point_free(intro
);
5352 intro
->intro_key
= tok
->key
;
5353 tok
->key
= NULL
; /* Prevent free */
5354 /* Add extend info to list of introduction points. */
5355 smartlist_add(parsed
->intro_nodes
, intro
);
5357 result
= smartlist_len(parsed
->intro_nodes
);
5364 /* Free tokens and clear token list. */
5366 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5367 smartlist_free(tokens
);
5370 memarea_drop_all(area
);
5375 /** Parse the content of a client_key file in <b>ckstr</b> and add
5376 * rend_authorized_client_t's for each parsed client to
5377 * <b>parsed_clients</b>. Return the number of parsed clients as result
5378 * or -1 for failure. */
5380 rend_parse_client_keys(strmap_t
*parsed_clients
, const char *ckstr
)
5383 smartlist_t
*tokens
;
5384 directory_token_t
*tok
;
5385 const char *current_entry
= NULL
;
5386 memarea_t
*area
= NULL
;
5387 char *err_msg
= NULL
;
5388 if (!ckstr
|| strlen(ckstr
) == 0)
5390 tokens
= smartlist_new();
5391 /* Begin parsing with first entry, skipping comments or whitespace at the
5393 area
= memarea_new();
5394 current_entry
= eat_whitespace(ckstr
);
5395 while (!strcmpstart(current_entry
, "client-name ")) {
5396 rend_authorized_client_t
*parsed_entry
;
5397 /* Determine end of string. */
5398 const char *eos
= strstr(current_entry
, "\nclient-name ");
5400 eos
= current_entry
+ strlen(current_entry
);
5403 /* Free tokens and clear token list. */
5404 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5405 smartlist_clear(tokens
);
5406 memarea_clear(area
);
5407 /* Tokenize string. */
5408 if (tokenize_string(area
, current_entry
, eos
, tokens
,
5409 client_keys_token_table
, 0)) {
5410 log_warn(LD_REND
, "Error tokenizing client keys file.");
5413 /* Advance to next entry, if available. */
5414 current_entry
= eos
;
5415 /* Check minimum allowed length of token list. */
5416 if (smartlist_len(tokens
) < 2) {
5417 log_warn(LD_REND
, "Impossibly short client key entry.");
5420 /* Parse client name. */
5421 tok
= find_by_keyword(tokens
, C_CLIENT_NAME
);
5422 tor_assert(tok
== smartlist_get(tokens
, 0));
5423 tor_assert(tok
->n_args
== 1);
5425 if (!rend_valid_client_name(tok
->args
[0])) {
5426 log_warn(LD_CONFIG
, "Illegal client name: %s. (Length must be "
5427 "between 1 and %d, and valid characters are "
5428 "[A-Za-z0-9+-_].)", tok
->args
[0], REND_CLIENTNAME_MAX_LEN
);
5431 /* Check if client name is duplicate. */
5432 if (strmap_get(parsed_clients
, tok
->args
[0])) {
5433 log_warn(LD_CONFIG
, "HiddenServiceAuthorizeClient contains a "
5434 "duplicate client name: '%s'. Ignoring.", tok
->args
[0]);
5437 parsed_entry
= tor_malloc_zero(sizeof(rend_authorized_client_t
));
5438 parsed_entry
->client_name
= tor_strdup(tok
->args
[0]);
5439 strmap_set(parsed_clients
, parsed_entry
->client_name
, parsed_entry
);
5440 /* Parse client key. */
5441 tok
= find_opt_by_keyword(tokens
, C_CLIENT_KEY
);
5443 parsed_entry
->client_key
= tok
->key
;
5444 tok
->key
= NULL
; /* Prevent free */
5447 /* Parse descriptor cookie. */
5448 tok
= find_by_keyword(tokens
, C_DESCRIPTOR_COOKIE
);
5449 tor_assert(tok
->n_args
== 1);
5450 if (rend_auth_decode_cookie(tok
->args
[0], parsed_entry
->descriptor_cookie
,
5451 NULL
, &err_msg
) < 0) {
5452 tor_assert(err_msg
);
5453 log_warn(LD_REND
, "%s", err_msg
);
5458 result
= strmap_size(parsed_clients
);
5463 /* Free tokens and clear token list. */
5464 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5465 smartlist_free(tokens
);
5467 memarea_drop_all(area
);