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-2013, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to parse and validate router descriptors and directories.
14 #include "circuitstats.h"
18 #include "rendcommon.h"
20 #include "routerlist.h"
22 #include "microdesc.h"
23 #include "networkstatus.h"
25 #include "routerparse.h"
29 /****************************************************************************/
31 /** Enumeration of possible token types. The ones starting with K_ correspond
32 * to directory 'keywords'. ERR_ is an error in the tokenizing process, EOF_
33 * is an end-of-file marker, and NIL_ is used to encode not-a-token.
38 K_DIRECTORY_SIGNATURE
,
39 K_RECOMMENDED_SOFTWARE
,
63 K_NETWORK_STATUS_VERSION
,
81 K_ALLOW_SINGLE_HOP_EXITS
,
109 K_DIR_KEY_CERTIFICATE_VERSION
,
113 K_DIR_KEY_CERTIFICATION
,
129 K_ADDITIONAL_SIGNATURE
,
139 R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
145 R_INTRODUCTION_POINTS
,
163 #define MIN_ANNOTATION A_PURPOSE
164 #define MAX_ANNOTATION A_UNKNOWN_
166 /** Structure to hold a single directory token.
168 * We parse a directory by breaking it into "tokens", each consisting
169 * of a keyword, a line full of arguments, and a binary object. The
170 * arguments and object are both optional, depending on the keyword
173 * This structure is only allocated in memareas; do not allocate it on
174 * the heap, or token_clear() won't work.
176 typedef struct directory_token_t
{
177 directory_keyword tp
; /**< Type of the token. */
178 int n_args
:30; /**< Number of elements in args */
179 char **args
; /**< Array of arguments from keyword line. */
181 char *object_type
; /**< -----BEGIN [object_type]-----*/
182 size_t object_size
; /**< Bytes in object_body */
183 char *object_body
; /**< Contents of object, base64-decoded. */
185 crypto_pk_t
*key
; /**< For public keys only. Heap-allocated. */
187 char *error
; /**< For ERR_ tokens only. */
190 /* ********************************************************************** */
192 /** We use a table of rules to decide how to parse each token type. */
194 /** Rules for whether the keyword needs an object. */
196 NO_OBJ
, /**< No object, ever. */
197 NEED_OBJ
, /**< Object is required. */
198 NEED_SKEY_1024
,/**< Object is required, and must be a 1024 bit private key */
199 NEED_KEY_1024
, /**< Object is required, and must be a 1024 bit public key */
200 NEED_KEY
, /**< Object is required, and must be a public key. */
201 OBJ_OK
, /**< Object is optional. */
207 /** Determines the parsing rules for a single token type. */
208 typedef struct token_rule_t
{
209 /** The string value of the keyword identifying the type of item. */
211 /** The corresponding directory_keyword enum. */
213 /** Minimum number of arguments for this item */
215 /** Maximum number of arguments for this item */
217 /** If true, we concatenate all arguments for this item into a single
220 /** Requirements on object syntax for this item. */
222 /** Lowest number of times this item may appear in a document. */
224 /** Highest number of times this item may appear in a document. */
226 /** One or more of AT_START/AT_END to limit where the item may appear in a
229 /** True iff this token is an annotation. */
234 * Helper macros to define token tables. 's' is a string, 't' is a
235 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
240 /** Appears to indicate the end of a table. */
241 #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
242 /** An item with no restrictions: used for obsolete document types */
243 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
244 /** An item with no restrictions on multiplicity or location. */
245 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
246 /** An item that must appear exactly once */
247 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
248 /** An item that must appear exactly once, at the start of the document */
249 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
250 /** An item that must appear exactly once, at the end of the document */
251 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
252 /** An item that must appear one or more times */
253 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
254 /** An item that must appear no more than once */
255 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
256 /** An annotation that must appear no more than once */
257 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
259 /* Argument multiplicity: any number of arguments. */
260 #define ARGS 0,INT_MAX,0
261 /* Argument multiplicity: no arguments. */
262 #define NO_ARGS 0,0,0
263 /* Argument multiplicity: concatenate all arguments. */
264 #define CONCAT_ARGS 1,1,1
265 /* Argument multiplicity: at least <b>n</b> arguments. */
266 #define GE(n) n,INT_MAX,0
267 /* Argument multiplicity: exactly <b>n</b> arguments. */
270 /** List of tokens recognized in router descriptors */
271 static token_rule_t routerdesc_token_table
[] = {
272 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
273 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
274 T0N("reject6", K_REJECT6
, ARGS
, NO_OBJ
),
275 T0N("accept6", K_ACCEPT6
, ARGS
, NO_OBJ
),
276 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
277 T01("ipv6-policy", K_IPV6_POLICY
, CONCAT_ARGS
, NO_OBJ
),
278 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
279 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
280 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
281 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
282 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
283 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
284 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
285 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
286 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
287 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
288 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
289 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
290 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
291 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR
, NO_ARGS
, NO_OBJ
),
292 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS
, NO_ARGS
, NO_OBJ
),
294 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
295 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
296 T0N("or-address", K_OR_ADDRESS
, GE(1), NO_OBJ
),
298 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
299 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
300 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
305 /** List of tokens recognized in extra-info documents. */
306 static token_rule_t extrainfo_token_table
[] = {
307 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
308 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
309 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
310 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
311 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
312 T01("dirreq-stats-end", K_DIRREQ_END
, ARGS
, NO_OBJ
),
313 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS
, ARGS
, NO_OBJ
),
314 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS
, ARGS
, NO_OBJ
),
315 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS
, ARGS
, NO_OBJ
),
316 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS
, ARGS
, NO_OBJ
),
317 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE
, ARGS
, NO_OBJ
),
318 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE
, ARGS
, NO_OBJ
),
319 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP
, ARGS
, NO_OBJ
),
320 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP
, ARGS
, NO_OBJ
),
321 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR
, ARGS
, NO_OBJ
),
322 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR
, ARGS
, NO_OBJ
),
323 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN
, ARGS
, NO_OBJ
),
324 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN
, ARGS
, NO_OBJ
),
325 T01("entry-stats-end", K_ENTRY_END
, ARGS
, NO_OBJ
),
326 T01("entry-ips", K_ENTRY_IPS
, ARGS
, NO_OBJ
),
327 T01("cell-stats-end", K_CELL_END
, ARGS
, NO_OBJ
),
328 T01("cell-processed-cells", K_CELL_PROCESSED
, ARGS
, NO_OBJ
),
329 T01("cell-queued-cells", K_CELL_QUEUED
, ARGS
, NO_OBJ
),
330 T01("cell-time-in-queue", K_CELL_TIME
, ARGS
, NO_OBJ
),
331 T01("cell-circuits-per-decile", K_CELL_CIRCS
, ARGS
, NO_OBJ
),
332 T01("exit-stats-end", K_EXIT_END
, ARGS
, NO_OBJ
),
333 T01("exit-kibibytes-written", K_EXIT_WRITTEN
, ARGS
, NO_OBJ
),
334 T01("exit-kibibytes-read", K_EXIT_READ
, ARGS
, NO_OBJ
),
335 T01("exit-streams-opened", K_EXIT_OPENED
, ARGS
, NO_OBJ
),
337 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
342 /** List of tokens recognized in the body part of v3 networkstatus
344 static token_rule_t rtrstatus_token_table
[] = {
345 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
346 T1( "r", K_R
, GE(7), NO_OBJ
),
347 T0N("a", K_A
, GE(1), NO_OBJ
),
348 T1( "s", K_S
, ARGS
, NO_OBJ
),
349 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
350 T01("w", K_W
, ARGS
, NO_OBJ
),
351 T0N("m", K_M
, CONCAT_ARGS
, NO_OBJ
),
352 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
356 /** List of tokens common to V3 authority certificates and V3 consensuses. */
357 #define CERTIFICATE_MEMBERS \
358 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
360 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
361 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
362 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
363 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
364 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
365 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
366 NO_ARGS, NEED_OBJ), \
367 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
369 /** List of tokens recognized in V3 authority certificates. */
370 static token_rule_t dir_key_certificate_table
[] = {
372 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
376 /** List of tokens recognized in rendezvous service descriptors */
377 static token_rule_t desc_token_table
[] = {
378 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
380 T1("version", R_VERSION
, EQ(1), NO_OBJ
),
381 T1("permanent-key", R_PERMANENT_KEY
, NO_ARGS
, NEED_KEY_1024
),
382 T1("secret-id-part", R_SECRET_ID_PART
, EQ(1), NO_OBJ
),
383 T1("publication-time", R_PUBLICATION_TIME
, CONCAT_ARGS
, NO_OBJ
),
384 T1("protocol-versions", R_PROTOCOL_VERSIONS
, EQ(1), NO_OBJ
),
385 T01("introduction-points", R_INTRODUCTION_POINTS
, NO_ARGS
, NEED_OBJ
),
386 T1_END("signature", R_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
390 /** List of tokens recognized in the (encrypted) list of introduction points of
391 * rendezvous service descriptors */
392 static token_rule_t ipo_token_table
[] = {
393 T1_START("introduction-point", R_IPO_IDENTIFIER
, EQ(1), NO_OBJ
),
394 T1("ip-address", R_IPO_IP_ADDRESS
, EQ(1), NO_OBJ
),
395 T1("onion-port", R_IPO_ONION_PORT
, EQ(1), NO_OBJ
),
396 T1("onion-key", R_IPO_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
397 T1("service-key", R_IPO_SERVICE_KEY
, NO_ARGS
, NEED_KEY_1024
),
401 /** List of tokens recognized in the (possibly encrypted) list of introduction
402 * points of rendezvous service descriptors */
403 static token_rule_t client_keys_token_table
[] = {
404 T1_START("client-name", C_CLIENT_NAME
, CONCAT_ARGS
, NO_OBJ
),
405 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE
, EQ(1), NO_OBJ
),
406 T01("client-key", C_CLIENT_KEY
, NO_ARGS
, NEED_SKEY_1024
),
410 /** List of tokens recognized in V3 networkstatus votes. */
411 static token_rule_t networkstatus_token_table
[] = {
412 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
414 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
415 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
416 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
417 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
418 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
419 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
420 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
421 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
422 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
426 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
427 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
428 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
429 T01("legacy-dir-key", K_LEGACY_DIR_KEY
, GE(1), NO_OBJ
),
430 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
431 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
432 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
433 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
438 /** List of tokens recognized in V3 networkstatus consensuses. */
439 static token_rule_t networkstatus_consensus_token_table
[] = {
440 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
442 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
443 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
444 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
445 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
446 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
448 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
450 T1N("dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
451 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
452 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
454 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
456 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
457 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
458 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
459 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
464 /** List of tokens recognized in the footer of v1 directory footers. */
465 static token_rule_t networkstatus_vote_footer_token_table
[] = {
466 T01("directory-footer", K_DIRECTORY_FOOTER
, NO_ARGS
, NO_OBJ
),
467 T01("bandwidth-weights", K_BW_WEIGHTS
, ARGS
, NO_OBJ
),
468 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
472 /** List of tokens recognized in detached networkstatus signature documents. */
473 static token_rule_t networkstatus_detached_signature_token_table
[] = {
474 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
475 T("additional-digest", K_ADDITIONAL_DIGEST
,GE(3), NO_OBJ
),
476 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
477 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
478 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
479 T("additional-signature", K_ADDITIONAL_SIGNATURE
, GE(4), NEED_OBJ
),
480 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
484 /** List of tokens recognized in microdescriptors */
485 static token_rule_t microdesc_token_table
[] = {
486 T1_START("onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
487 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
488 T0N("a", K_A
, GE(1), NO_OBJ
),
489 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
490 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
491 T01("p6", K_P6
, CONCAT_ARGS
, NO_OBJ
),
492 A01("@last-listed", A_LAST_LISTED
, CONCAT_ARGS
, NO_OBJ
),
498 /* static function prototypes */
499 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
500 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
,
502 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
504 static int router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
505 const char *start_str
, const char *end_str
,
507 digest_algorithm_t alg
);
508 static int router_get_hashes_impl(const char *s
, size_t s_len
,
510 const char *start_str
, const char *end_str
,
512 static void token_clear(directory_token_t
*tok
);
513 static smartlist_t
*find_all_by_keyword(smartlist_t
*s
, directory_keyword k
);
514 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
515 static directory_token_t
*find_by_keyword_(smartlist_t
*s
,
516 directory_keyword keyword
,
517 const char *keyword_str
);
518 #define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword)
519 static directory_token_t
*find_opt_by_keyword(smartlist_t
*s
,
520 directory_keyword keyword
);
522 #define TS_ANNOTATIONS_OK 1
524 #define TS_NO_NEW_ANNOTATIONS 4
525 static int tokenize_string(memarea_t
*area
,
526 const char *start
, const char *end
,
530 static directory_token_t
*get_next_token(memarea_t
*area
,
533 token_rule_t
*table
);
534 #define CST_CHECK_AUTHORITY (1<<0)
535 #define CST_NO_CHECK_OBJTYPE (1<<1)
536 static int check_signature_token(const char *digest
,
538 directory_token_t
*tok
,
541 const char *doctype
);
543 #undef DEBUG_AREA_ALLOC
545 #ifdef DEBUG_AREA_ALLOC
546 #define DUMP_AREA(a,name) STMT_BEGIN \
547 size_t alloc=0, used=0; \
548 memarea_get_stats((a),&alloc,&used); \
549 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
550 name, (unsigned long)alloc, (unsigned long)used); \
553 #define DUMP_AREA(a,name) STMT_NIL
556 /** Last time we dumped a descriptor to disk. */
557 static time_t last_desc_dumped
= 0;
559 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
560 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
561 * than one descriptor to disk per minute. If there is already such a
562 * file in the data directory, overwrite it. */
564 dump_desc(const char *desc
, const char *type
)
566 time_t now
= time(NULL
);
569 if (!last_desc_dumped
|| last_desc_dumped
+ 60 < now
) {
570 char *debugfile
= get_datadir_fname("unparseable-desc");
571 size_t filelen
= 50 + strlen(type
) + strlen(desc
);
572 char *content
= tor_malloc_zero(filelen
);
573 tor_snprintf(content
, filelen
, "Unable to parse descriptor of type "
574 "%s:\n%s", type
, desc
);
575 write_str_to_file(debugfile
, content
, 1);
576 log_info(LD_DIR
, "Unable to parse descriptor of type %s. See file "
577 "unparseable-desc in data directory for details.", type
);
580 last_desc_dumped
= now
;
584 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
585 * <b>s</b>. Return 0 on success, -1 on failure.
588 router_get_dir_hash(const char *s
, char *digest
)
590 return router_get_hash_impl(s
, strlen(s
), digest
,
591 "signed-directory","\ndirectory-signature",'\n',
595 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
596 * <b>s</b>. Return 0 on success, -1 on failure.
599 router_get_router_hash(const char *s
, size_t s_len
, char *digest
)
601 return router_get_hash_impl(s
, s_len
, digest
,
602 "router ","\nrouter-signature", '\n',
606 /** Set <b>digests</b> to all the digests of the consensus document in
609 router_get_networkstatus_v3_hashes(const char *s
, digests_t
*digests
)
611 return router_get_hashes_impl(s
,strlen(s
),digests
,
612 "network-status-version",
613 "\ndirectory-signature",
617 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
618 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
620 router_get_extrainfo_hash(const char *s
, size_t s_len
, char *digest
)
622 return router_get_hash_impl(s
, s_len
, digest
, "extra-info",
623 "\nrouter-signature",'\n', DIGEST_SHA1
);
626 /** Helper: used to generate signatures for routers, directories and
627 * network-status objects. Given a <b>digest_len</b>-byte digest in
628 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
629 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
630 * and return the new signature on success or NULL on failure.
633 router_get_dirobj_signature(const char *digest
,
635 crypto_pk_t
*private_key
)
642 /* overestimate of BEGIN/END lines total len. */
643 #define BEGIN_END_OVERHEAD_LEN 64
645 keysize
= crypto_pk_keysize(private_key
);
646 signature
= tor_malloc(keysize
);
647 siglen
= crypto_pk_private_sign(private_key
, signature
, keysize
,
650 log_warn(LD_BUG
,"Couldn't sign digest.");
654 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
655 buf_len
= (siglen
* 2) + BEGIN_END_OVERHEAD_LEN
;
656 buf
= tor_malloc(buf_len
);
658 if (strlcpy(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
662 if (base64_encode(buf
+i
, buf_len
-i
, signature
, siglen
) < 0) {
663 log_warn(LD_BUG
,"couldn't base64-encode signature");
667 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
674 log_warn(LD_BUG
,"tried to exceed string length.");
681 /** Helper: used to generate signatures for routers, directories and
682 * network-status objects. Given a digest in <b>digest</b> and a secret
683 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
684 * surround it with -----BEGIN/END----- pairs, and write it to the
685 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
689 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
690 size_t digest_len
, crypto_pk_t
*private_key
)
692 size_t sig_len
, s_len
;
693 char *sig
= router_get_dirobj_signature(digest
, digest_len
, private_key
);
695 log_warn(LD_BUG
, "No signature generated");
698 sig_len
= strlen(sig
);
700 if (sig_len
+ s_len
+ 1 > buf_len
) {
701 log_warn(LD_BUG
, "Not enough room for signature");
705 memcpy(buf
+s_len
, sig
, sig_len
+1);
710 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
711 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
712 * entries. Else, return VS_OLD if every member of
713 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
714 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
715 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
716 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
717 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
720 * (versionlist is a comma-separated list of version strings,
721 * optionally prefixed with "Tor". Versions that can't be parsed are
725 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
727 tor_version_t mine
, other
;
728 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
729 found_any_in_series
= 0, r
, same
;
730 version_status_t ret
= VS_UNRECOMMENDED
;
731 smartlist_t
*version_sl
;
733 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
734 myversion
, versionlist
);
736 if (tor_version_parse(myversion
, &mine
)) {
737 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
740 version_sl
= smartlist_new();
741 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
743 if (!strlen(versionlist
)) { /* no authorities cared or agreed */
748 SMARTLIST_FOREACH_BEGIN(version_sl
, const char *, cp
) {
749 if (!strcmpstart(cp
, "Tor "))
752 if (tor_version_parse(cp
, &other
)) {
753 /* Couldn't parse other; it can't be a match. */
755 same
= tor_version_same_series(&mine
, &other
);
757 found_any_in_series
= 1;
758 r
= tor_version_compare(&mine
, &other
);
760 ret
= VS_RECOMMENDED
;
765 found_newer_in_series
= 1;
770 } SMARTLIST_FOREACH_END(cp
);
772 /* We didn't find the listed version. Is it new or old? */
773 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
774 ret
= VS_NEW_IN_SERIES
;
775 } else if (found_newer
&& !found_older
) {
777 } else if (found_older
&& !found_newer
) {
780 ret
= VS_UNRECOMMENDED
;
784 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
785 smartlist_free(version_sl
);
789 /** Return true iff <b>key</b> is allowed to sign directories.
792 dir_signing_key_is_trusted(crypto_pk_t
*key
)
794 char digest
[DIGEST_LEN
];
796 if (crypto_pk_get_digest(key
, digest
) < 0) {
797 log_warn(LD_DIR
, "Error computing dir-signing-key digest");
800 if (!router_digest_is_trusted_dir(digest
)) {
801 log_warn(LD_DIR
, "Listed dir-signing-key is not trusted");
807 /** Check whether the object body of the token in <b>tok</b> has a good
808 * signature for <b>digest</b> using key <b>pkey</b>. If
809 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
810 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
811 * the object type of the signature object. Use <b>doctype</b> as the type of
812 * the document when generating log messages. Return 0 on success, negative
816 check_signature_token(const char *digest
,
818 directory_token_t
*tok
,
825 const int check_authority
= (flags
& CST_CHECK_AUTHORITY
);
826 const int check_objtype
= ! (flags
& CST_NO_CHECK_OBJTYPE
);
833 if (check_authority
&& !dir_signing_key_is_trusted(pkey
)) {
834 log_warn(LD_DIR
, "Key on %s did not come from an authority; rejecting",
840 if (strcmp(tok
->object_type
, "SIGNATURE")) {
841 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
846 keysize
= crypto_pk_keysize(pkey
);
847 signed_digest
= tor_malloc(keysize
);
848 if (crypto_pk_public_checksig(pkey
, signed_digest
, keysize
,
849 tok
->object_body
, tok
->object_size
)
851 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
852 tor_free(signed_digest
);
855 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
856 // hex_str(signed_digest,4));
857 if (tor_memneq(digest
, signed_digest
, digest_len
)) {
858 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
859 tor_free(signed_digest
);
862 tor_free(signed_digest
);
866 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
867 * or to the first of the annotations proceeding the next router or
868 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
869 * we found an extrainfo, or false if found a router. Do not scan beyond
870 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
872 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
874 int *is_extrainfo_out
)
876 const char *annotations
= NULL
;
877 const char *s
= *s_ptr
;
879 s
= eat_whitespace_eos(s
, eos
);
881 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
882 /* We're at the start of a line. */
883 tor_assert(*s
!= '\n');
885 if (*s
== '@' && !annotations
) {
887 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
888 *s_ptr
= annotations
? annotations
: s
;
889 *is_extrainfo_out
= 0;
891 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
892 *s_ptr
= annotations
? annotations
: s
;
893 *is_extrainfo_out
= 1;
897 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
899 s
= eat_whitespace_eos(s
, eos
);
904 /** Given a string *<b>s</b> containing a concatenated sequence of router
905 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
906 * them and stores the result in <b>dest</b>. All routers are marked running
907 * and valid. Advances *s to a point immediately following the last router
908 * entry. Ignore any trailing router entries that are not complete.
910 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
911 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
912 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
914 * Returns 0 on success and -1 on failure.
917 router_parse_list_from_string(const char **s
, const char *eos
,
919 saved_location_t saved_location
,
921 int allow_annotations
,
922 const char *prepend_annotations
)
924 routerinfo_t
*router
;
925 extrainfo_t
*extrainfo
;
926 signed_descriptor_t
*signed_desc
= NULL
;
928 const char *end
, *start
;
937 eos
= *s
+ strlen(*s
);
939 tor_assert(eos
>= *s
);
942 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
945 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
947 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
949 end
+= strlen("\n-----END SIGNATURE-----\n");
956 if (have_extrainfo
&& want_extrainfo
) {
957 routerlist_t
*rl
= router_get_routerlist();
958 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
959 saved_location
!= SAVED_IN_CACHE
,
962 signed_desc
= &extrainfo
->cache_info
;
965 } else if (!have_extrainfo
&& !want_extrainfo
) {
966 router
= router_parse_entry_from_string(*s
, end
,
967 saved_location
!= SAVED_IN_CACHE
,
969 prepend_annotations
);
971 log_debug(LD_DIR
, "Read router '%s', purpose '%s'",
972 router_describe(router
),
973 router_purpose_to_string(router
->purpose
));
974 signed_desc
= &router
->cache_info
;
982 if (saved_location
!= SAVED_NOWHERE
) {
983 tor_assert(signed_desc
);
984 signed_desc
->saved_location
= saved_location
;
985 signed_desc
->saved_offset
= *s
- start
;
988 smartlist_add(dest
, elt
);
994 /* For debugging: define to count every descriptor digest we've seen so we
995 * know if we need to try harder to avoid duplicate verifies. */
996 #undef COUNT_DISTINCT_DIGESTS
998 #ifdef COUNT_DISTINCT_DIGESTS
999 static digestmap_t
*verified_digests
= NULL
;
1002 /** Log the total count of the number of distinct router digests we've ever
1003 * verified. When compared to the number of times we've verified routerdesc
1004 * signatures <i>in toto</i>, this will tell us if we're doing too much
1005 * multiple-verification. */
1007 dump_distinct_digest_count(int severity
)
1009 #ifdef COUNT_DISTINCT_DIGESTS
1010 if (!verified_digests
)
1011 verified_digests
= digestmap_new();
1012 tor_log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
1013 digestmap_size(verified_digests
));
1015 (void)severity
; /* suppress "unused parameter" warning */
1019 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1020 * with at least one argument (use GE(1) in setup). If found, store
1021 * address and port number to <b>addr_out</b> and
1022 * <b>port_out</b>. Return number of OR ports found. */
1024 find_single_ipv6_orport(const smartlist_t
*list
,
1025 tor_addr_t
*addr_out
,
1029 tor_assert(list
!= NULL
);
1030 tor_assert(addr_out
!= NULL
);
1031 tor_assert(port_out
!= NULL
);
1033 SMARTLIST_FOREACH_BEGIN(list
, directory_token_t
*, t
) {
1036 uint16_t port_min
, port_max
;
1037 tor_assert(t
->n_args
>= 1);
1038 /* XXXX Prop186 the full spec allows much more than this. */
1039 if (tor_addr_parse_mask_ports(t
->args
[0], 0,
1040 &a
, &bits
, &port_min
,
1041 &port_max
) == AF_INET6
&&
1043 port_min
== port_max
) {
1044 /* Okay, this is one we can understand. Use it and ignore
1045 any potential more addresses in list. */
1046 tor_addr_copy(addr_out
, &a
);
1047 *port_out
= port_min
;
1051 } SMARTLIST_FOREACH_END(t
);
1056 /** Helper function: reads a single router entry from *<b>s</b> ...
1057 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1058 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1059 * s through end into the signed_descriptor_body of the resulting
1062 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1064 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1065 * before the router; if it's false, reject the router if it's annotated. If
1066 * <b>prepend_annotations</b> is set, it should contain some annotations:
1067 * append them to the front of the router before parsing it, and keep them
1068 * around when caching the router.
1070 * Only one of allow_annotations and prepend_annotations may be set.
1073 router_parse_entry_from_string(const char *s
, const char *end
,
1074 int cache_copy
, int allow_annotations
,
1075 const char *prepend_annotations
)
1077 routerinfo_t
*router
= NULL
;
1079 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1080 directory_token_t
*tok
;
1082 const char *start_of_annotations
, *cp
, *s_dup
= s
;
1083 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1085 memarea_t
*area
= NULL
;
1087 tor_assert(!allow_annotations
|| !prepend_annotations
);
1090 end
= s
+ strlen(s
);
1093 /* point 'end' to a point immediately after the final newline. */
1094 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1097 area
= memarea_new();
1098 tokens
= smartlist_new();
1099 if (prepend_annotations
) {
1100 if (tokenize_string(area
,prepend_annotations
,NULL
,tokens
,
1101 routerdesc_token_table
,TS_NOCHECK
)) {
1102 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1107 start_of_annotations
= s
;
1108 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1110 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1111 log_warn(LD_DIR
, "No router keyword found.");
1118 if (start_of_annotations
!= s
) { /* We have annotations */
1119 if (allow_annotations
) {
1120 if (tokenize_string(area
,start_of_annotations
,s
,tokens
,
1121 routerdesc_token_table
,TS_NOCHECK
)) {
1122 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1126 log_warn(LD_DIR
, "Found unexpected annotations on router descriptor not "
1127 "loaded from disk. Dropping it.");
1132 if (router_get_router_hash(s
, end
- s
, digest
) < 0) {
1133 log_warn(LD_DIR
, "Couldn't compute router hash.");
1138 if (allow_annotations
)
1139 flags
|= TS_ANNOTATIONS_OK
;
1140 if (prepend_annotations
)
1141 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1143 if (tokenize_string(area
,s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1144 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1149 if (smartlist_len(tokens
) < 2) {
1150 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1154 tok
= find_by_keyword(tokens
, K_ROUTER
);
1155 tor_assert(tok
->n_args
>= 5);
1157 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1158 router
->cache_info
.routerlist_index
= -1;
1159 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1160 router
->cache_info
.signed_descriptor_len
= end
-s
;
1162 size_t len
= router
->cache_info
.signed_descriptor_len
+
1163 router
->cache_info
.annotations_len
;
1165 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1166 if (prepend_annotations
) {
1167 memcpy(cp
, prepend_annotations
, prepend_len
);
1170 /* This assertion will always succeed.
1171 * len == signed_desc_len + annotations_len
1172 * == end-s + s-start_of_annotations + prepend_len
1173 * == end-start_of_annotations + prepend_len
1174 * We already wrote prepend_len bytes into the buffer; now we're
1175 * writing end-start_of_annotations -NM. */
1176 tor_assert(cp
+(end
-start_of_annotations
) ==
1177 router
->cache_info
.signed_descriptor_body
+len
);
1178 memcpy(cp
, start_of_annotations
, end
-start_of_annotations
);
1179 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1180 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1182 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1184 router
->nickname
= tor_strdup(tok
->args
[0]);
1185 if (!is_legal_nickname(router
->nickname
)) {
1186 log_warn(LD_DIR
,"Router nickname is invalid");
1189 if (!tor_inet_aton(tok
->args
[1], &in
)) {
1190 log_warn(LD_DIR
,"Router address is not an IP address.");
1193 router
->addr
= ntohl(in
.s_addr
);
1196 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,&ok
,NULL
);
1198 log_warn(LD_DIR
,"Invalid OR port %s", escaped(tok
->args
[2]));
1202 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,&ok
,NULL
);
1204 log_warn(LD_DIR
,"Invalid dir port %s", escaped(tok
->args
[4]));
1208 tok
= find_by_keyword(tokens
, K_BANDWIDTH
);
1209 tor_assert(tok
->n_args
>= 3);
1210 router
->bandwidthrate
= (int)
1211 tor_parse_long(tok
->args
[0],10,1,INT_MAX
,&ok
,NULL
);
1214 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1215 escaped(tok
->args
[0]));
1218 router
->bandwidthburst
=
1219 (int) tor_parse_long(tok
->args
[1],10,0,INT_MAX
,&ok
,NULL
);
1221 log_warn(LD_DIR
, "Invalid bandwidthburst %s", escaped(tok
->args
[1]));
1224 router
->bandwidthcapacity
= (int)
1225 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,&ok
,NULL
);
1227 log_warn(LD_DIR
, "Invalid bandwidthcapacity %s", escaped(tok
->args
[1]));
1231 if ((tok
= find_opt_by_keyword(tokens
, A_PURPOSE
))) {
1232 tor_assert(tok
->n_args
);
1233 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1235 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1237 router
->cache_info
.send_unencrypted
=
1238 (router
->purpose
== ROUTER_PURPOSE_GENERAL
) ? 1 : 0;
1240 if ((tok
= find_opt_by_keyword(tokens
, K_UPTIME
))) {
1241 tor_assert(tok
->n_args
>= 1);
1242 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,&ok
,NULL
);
1244 log_warn(LD_DIR
, "Invalid uptime %s", escaped(tok
->args
[0]));
1249 if ((tok
= find_opt_by_keyword(tokens
, K_HIBERNATING
))) {
1250 tor_assert(tok
->n_args
>= 1);
1251 router
->is_hibernating
1252 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1255 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1256 tor_assert(tok
->n_args
== 1);
1257 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1260 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
1261 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
1263 "Relay's onion key had invalid exponent.");
1266 router
->onion_pkey
= tok
->key
;
1267 tok
->key
= NULL
; /* Prevent free */
1269 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
1270 curve25519_public_key_t k
;
1271 tor_assert(tok
->n_args
>= 1);
1272 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
1273 log_warn(LD_DIR
, "Bogus ntor-onion-key in routerinfo");
1276 router
->onion_curve25519_pkey
=
1277 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
1280 tok
= find_by_keyword(tokens
, K_SIGNING_KEY
);
1281 router
->identity_pkey
= tok
->key
;
1282 tok
->key
= NULL
; /* Prevent free */
1283 if (crypto_pk_get_digest(router
->identity_pkey
,
1284 router
->cache_info
.identity_digest
)) {
1285 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1288 if ((tok
= find_opt_by_keyword(tokens
, K_FINGERPRINT
))) {
1289 /* If there's a fingerprint line, it must match the identity digest. */
1291 tor_assert(tok
->n_args
== 1);
1292 tor_strstrip(tok
->args
[0], " ");
1293 if (base16_decode(d
, DIGEST_LEN
, tok
->args
[0], strlen(tok
->args
[0]))) {
1294 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1295 escaped(tok
->args
[0]));
1298 if (tor_memneq(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)) {
1299 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1305 if ((tok
= find_opt_by_keyword(tokens
, K_PLATFORM
))) {
1306 router
->platform
= tor_strdup(tok
->args
[0]);
1309 if ((tok
= find_opt_by_keyword(tokens
, K_CONTACT
))) {
1310 router
->contact_info
= tor_strdup(tok
->args
[0]);
1313 if (find_opt_by_keyword(tokens
, K_REJECT6
) ||
1314 find_opt_by_keyword(tokens
, K_ACCEPT6
)) {
1315 log_warn(LD_DIR
, "Rejecting router with reject6/accept6 line: they crash "
1320 smartlist_t
*or_addresses
= find_all_by_keyword(tokens
, K_OR_ADDRESS
);
1322 find_single_ipv6_orport(or_addresses
, &router
->ipv6_addr
,
1323 &router
->ipv6_orport
);
1324 smartlist_free(or_addresses
);
1327 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1328 if (!smartlist_len(exit_policy_tokens
)) {
1329 log_warn(LD_DIR
, "No exit policy tokens in descriptor.");
1332 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1333 if (router_add_exit_policy(router
,t
)<0) {
1334 log_warn(LD_DIR
,"Error in exit policy");
1337 policy_expand_private(&router
->exit_policy
);
1339 if ((tok
= find_opt_by_keyword(tokens
, K_IPV6_POLICY
)) && tok
->n_args
) {
1340 router
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
1341 if (! router
->ipv6_exit_policy
) {
1342 log_warn(LD_DIR
, "Error in ipv6-policy %s", escaped(tok
->args
[0]));
1347 if (policy_is_reject_star(router
->exit_policy
, AF_INET
) &&
1348 (!router
->ipv6_exit_policy
||
1349 short_policy_is_reject_star(router
->ipv6_exit_policy
)))
1350 router
->policy_is_reject_star
= 1;
1352 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1354 router
->declared_family
= smartlist_new();
1355 for (i
=0;i
<tok
->n_args
;++i
) {
1356 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1357 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1358 escaped(tok
->args
[i
]));
1361 smartlist_add(router
->declared_family
, tor_strdup(tok
->args
[i
]));
1365 if (find_opt_by_keyword(tokens
, K_CACHES_EXTRA_INFO
))
1366 router
->caches_extra_info
= 1;
1368 if (find_opt_by_keyword(tokens
, K_ALLOW_SINGLE_HOP_EXITS
))
1369 router
->allow_single_hop_exits
= 1;
1371 if ((tok
= find_opt_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1372 tor_assert(tok
->n_args
>= 1);
1373 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1374 base16_decode(router
->cache_info
.extra_info_digest
,
1375 DIGEST_LEN
, tok
->args
[0], HEX_DIGEST_LEN
);
1377 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1381 if (find_opt_by_keyword(tokens
, K_HIDDEN_SERVICE_DIR
)) {
1382 router
->wants_to_be_hs_dir
= 1;
1385 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1386 note_crypto_pk_op(VERIFY_RTR
);
1387 #ifdef COUNT_DISTINCT_DIGESTS
1388 if (!verified_digests
)
1389 verified_digests
= digestmap_new();
1390 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
1392 if (check_signature_token(digest
, DIGEST_LEN
, tok
, router
->identity_pkey
, 0,
1393 "router descriptor") < 0)
1396 if (!router
->or_port
) {
1397 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
1401 if (!router
->platform
) {
1402 router
->platform
= tor_strdup("<unknown>");
1408 dump_desc(s_dup
, "router descriptor");
1409 routerinfo_free(router
);
1413 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1414 smartlist_free(tokens
);
1416 smartlist_free(exit_policy_tokens
);
1418 DUMP_AREA(area
, "routerinfo");
1419 memarea_drop_all(area
);
1424 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1425 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1426 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1427 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1428 * as a map from router identity to routerinfo_t when looking up signing keys.
1431 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
1432 int cache_copy
, struct digest_ri_map_t
*routermap
)
1434 extrainfo_t
*extrainfo
= NULL
;
1436 smartlist_t
*tokens
= NULL
;
1437 directory_token_t
*tok
;
1438 crypto_pk_t
*key
= NULL
;
1439 routerinfo_t
*router
= NULL
;
1440 memarea_t
*area
= NULL
;
1441 const char *s_dup
= s
;
1444 end
= s
+ strlen(s
);
1447 /* point 'end' to a point immediately after the final newline. */
1448 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1451 if (router_get_extrainfo_hash(s
, end
-s
, digest
) < 0) {
1452 log_warn(LD_DIR
, "Couldn't compute router hash.");
1455 tokens
= smartlist_new();
1456 area
= memarea_new();
1457 if (tokenize_string(area
,s
,end
,tokens
,extrainfo_token_table
,0)) {
1458 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
1462 if (smartlist_len(tokens
) < 2) {
1463 log_warn(LD_DIR
, "Impossibly short extra-info document.");
1467 tok
= smartlist_get(tokens
,0);
1468 if (tok
->tp
!= K_EXTRA_INFO
) {
1469 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
1473 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
1474 extrainfo
->cache_info
.is_extrainfo
= 1;
1476 extrainfo
->cache_info
.signed_descriptor_body
= tor_memdup_nulterm(s
,end
-s
);
1477 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
1478 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1480 tor_assert(tok
->n_args
>= 2);
1481 if (!is_legal_nickname(tok
->args
[0])) {
1482 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
1485 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
1486 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
1487 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
1488 tok
->args
[1], HEX_DIGEST_LEN
)) {
1489 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
1490 escaped(tok
->args
[1]));
1494 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1495 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
1496 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
1497 escaped(tok
->args
[0]));
1502 (router
= digestmap_get((digestmap_t
*)routermap
,
1503 extrainfo
->cache_info
.identity_digest
))) {
1504 key
= router
->identity_pkey
;
1507 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
1508 if (strcmp(tok
->object_type
, "SIGNATURE") ||
1509 tok
->object_size
< 128 || tok
->object_size
> 512) {
1510 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
1515 note_crypto_pk_op(VERIFY_RTR
);
1516 if (check_signature_token(digest
, DIGEST_LEN
, tok
, key
, 0,
1521 extrainfo
->cache_info
.send_unencrypted
=
1522 router
->cache_info
.send_unencrypted
;
1524 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
1526 extrainfo
->pending_sig_len
= tok
->object_size
;
1531 dump_desc(s_dup
, "extra-info descriptor");
1532 extrainfo_free(extrainfo
);
1536 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1537 smartlist_free(tokens
);
1540 DUMP_AREA(area
, "extrainfo");
1541 memarea_drop_all(area
);
1546 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1547 * the first character after the certificate. */
1549 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
1551 /** Reject any certificate at least this big; it is probably an overflow, an
1552 * attack, a bug, or some other nonsense. */
1553 #define MAX_CERT_SIZE (128*1024)
1555 authority_cert_t
*cert
= NULL
, *old_cert
;
1556 smartlist_t
*tokens
= NULL
;
1557 char digest
[DIGEST_LEN
];
1558 directory_token_t
*tok
;
1559 char fp_declared
[DIGEST_LEN
];
1563 memarea_t
*area
= NULL
;
1564 const char *s_dup
= s
;
1566 s
= eat_whitespace(s
);
1567 eos
= strstr(s
, "\ndir-key-certification");
1569 log_warn(LD_DIR
, "No signature found on key certificate");
1572 eos
= strstr(eos
, "\n-----END SIGNATURE-----\n");
1574 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
1577 eos
= strchr(eos
+2, '\n');
1582 if (len
> MAX_CERT_SIZE
) {
1583 log_warn(LD_DIR
, "Certificate is far too big (at %lu bytes long); "
1584 "rejecting", (unsigned long)len
);
1588 tokens
= smartlist_new();
1589 area
= memarea_new();
1590 if (tokenize_string(area
,s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
1591 log_warn(LD_DIR
, "Error tokenizing key certificate");
1594 if (router_get_hash_impl(s
, strlen(s
), digest
, "dir-key-certificate-version",
1595 "\ndir-key-certification", '\n', DIGEST_SHA1
) < 0)
1597 tok
= smartlist_get(tokens
, 0);
1598 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
1600 "Key certificate does not begin with a recognized version (3).");
1604 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
1605 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1607 tok
= find_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
1608 tor_assert(tok
->key
);
1609 cert
->signing_key
= tok
->key
;
1611 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
1614 tok
= find_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
1615 tor_assert(tok
->key
);
1616 cert
->identity_key
= tok
->key
;
1619 tok
= find_by_keyword(tokens
, K_FINGERPRINT
);
1620 tor_assert(tok
->n_args
);
1621 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
1622 strlen(tok
->args
[0]))) {
1623 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
1624 escaped(tok
->args
[0]));
1628 if (crypto_pk_get_digest(cert
->identity_key
,
1629 cert
->cache_info
.identity_digest
))
1632 if (tor_memneq(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
1633 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
1638 tok
= find_opt_by_keyword(tokens
, K_DIR_ADDRESS
);
1641 char *address
= NULL
;
1642 tor_assert(tok
->n_args
);
1643 /* XXX024 use some tor_addr parse function below instead. -RD */
1644 if (tor_addr_port_split(LOG_WARN
, tok
->args
[0], &address
,
1645 &cert
->dir_port
) < 0 ||
1646 tor_inet_aton(address
, &in
) == 0) {
1647 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
1651 cert
->addr
= ntohl(in
.s_addr
);
1655 tok
= find_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
1656 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
1659 tok
= find_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
1660 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
1664 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
1665 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
1666 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
1670 /* If we already have this cert, don't bother checking the signature. */
1671 old_cert
= authority_cert_get_by_digests(
1672 cert
->cache_info
.identity_digest
,
1673 cert
->signing_key_digest
);
1676 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1678 if (old_cert
->cache_info
.signed_descriptor_len
== len
&&
1679 old_cert
->cache_info
.signed_descriptor_body
&&
1680 tor_memeq(s
, old_cert
->cache_info
.signed_descriptor_body
, len
)) {
1681 log_debug(LD_DIR
, "We already checked the signature on this "
1682 "certificate; no need to do so again.");
1687 if (check_signature_token(digest
, DIGEST_LEN
, tok
, cert
->identity_key
, 0,
1688 "key certificate")) {
1692 tok
= find_by_keyword(tokens
, K_DIR_KEY_CROSSCERT
);
1693 if (check_signature_token(cert
->cache_info
.identity_digest
,
1697 CST_NO_CHECK_OBJTYPE
,
1698 "key cross-certification")) {
1703 cert
->cache_info
.signed_descriptor_len
= len
;
1704 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1705 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
1706 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
1707 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
1709 if (end_of_string
) {
1710 *end_of_string
= eat_whitespace(eos
);
1712 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1713 smartlist_free(tokens
);
1715 DUMP_AREA(area
, "authority cert");
1716 memarea_drop_all(area
);
1720 dump_desc(s_dup
, "authority cert");
1721 authority_cert_free(cert
);
1722 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
1723 smartlist_free(tokens
);
1725 DUMP_AREA(area
, "authority cert");
1726 memarea_drop_all(area
);
1731 /** Helper: given a string <b>s</b>, return the start of the next router-status
1732 * object (starting with "r " at the start of a line). If none is found,
1733 * return the start of the directory footer, or the next directory signature.
1734 * If none is found, return the end of the string. */
1735 static INLINE
const char *
1736 find_start_of_next_routerstatus(const char *s
)
1738 const char *eos
, *footer
, *sig
;
1739 if ((eos
= strstr(s
, "\nr ")))
1742 eos
= s
+ strlen(s
);
1744 footer
= tor_memstr(s
, eos
-s
, "\ndirectory-footer");
1745 sig
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
1748 return MIN(footer
, sig
) + 1;
1757 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1758 * empty smartlist at <b>tokens</b>, parse and return the first router status
1759 * object in the string, and advance *<b>s</b> to just after the end of the
1760 * router status. Return NULL and advance *<b>s</b> on error.
1762 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1763 * routerstatus but use <b>vote_rs</b> instead.
1765 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1766 * consensus, and we should parse it according to the method used to
1767 * make that consensus.
1769 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
1771 static routerstatus_t
*
1772 routerstatus_parse_entry_from_string(memarea_t
*area
,
1773 const char **s
, smartlist_t
*tokens
,
1774 networkstatus_t
*vote
,
1775 vote_routerstatus_t
*vote_rs
,
1776 int consensus_method
,
1777 consensus_flavor_t flav
)
1779 const char *eos
, *s_dup
= *s
;
1780 routerstatus_t
*rs
= NULL
;
1781 directory_token_t
*tok
;
1782 char timebuf
[ISO_TIME_LEN
+1];
1786 tor_assert(bool_eq(vote
, vote_rs
));
1788 if (!consensus_method
)
1790 tor_assert(flav
== FLAV_NS
|| flav
== FLAV_MICRODESC
);
1792 eos
= find_start_of_next_routerstatus(*s
);
1794 if (tokenize_string(area
,*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
1795 log_warn(LD_DIR
, "Error tokenizing router status");
1798 if (smartlist_len(tokens
) < 1) {
1799 log_warn(LD_DIR
, "Impossibly short router status");
1802 tok
= find_by_keyword(tokens
, K_R
);
1803 tor_assert(tok
->n_args
>= 7); /* guaranteed by GE(7) in K_R setup */
1804 if (flav
== FLAV_NS
) {
1805 if (tok
->n_args
< 8) {
1806 log_warn(LD_DIR
, "Too few arguments to r");
1809 } else if (flav
== FLAV_MICRODESC
) {
1810 offset
= -1; /* There is no identity digest */
1814 rs
= &vote_rs
->status
;
1816 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
1819 if (!is_legal_nickname(tok
->args
[0])) {
1821 "Invalid nickname %s in router status; skipping.",
1822 escaped(tok
->args
[0]));
1825 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
1827 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
1828 log_warn(LD_DIR
, "Error decoding identity digest %s",
1829 escaped(tok
->args
[1]));
1833 if (flav
== FLAV_NS
) {
1834 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
1835 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
1836 escaped(tok
->args
[2]));
1841 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
1842 tok
->args
[3+offset
], tok
->args
[4+offset
]) < 0 ||
1843 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
1844 log_warn(LD_DIR
, "Error parsing time '%s %s' [%d %d]",
1845 tok
->args
[3+offset
], tok
->args
[4+offset
],
1850 if (tor_inet_aton(tok
->args
[5+offset
], &in
) == 0) {
1851 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
1852 escaped(tok
->args
[5+offset
]));
1855 rs
->addr
= ntohl(in
.s_addr
);
1857 rs
->or_port
= (uint16_t) tor_parse_long(tok
->args
[6+offset
],
1858 10,0,65535,NULL
,NULL
);
1859 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7+offset
],
1860 10,0,65535,NULL
,NULL
);
1863 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
1865 find_single_ipv6_orport(a_lines
, &rs
->ipv6_addr
, &rs
->ipv6_orport
);
1866 smartlist_free(a_lines
);
1870 tok
= find_opt_by_keyword(tokens
, K_S
);
1874 for (i
=0; i
< tok
->n_args
; ++i
) {
1875 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
1877 vote_rs
->flags
|= (U64_LITERAL(1)<<p
);
1879 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
1880 escaped(tok
->args
[i
]));
1886 for (i
=0; i
< tok
->n_args
; ++i
) {
1887 if (!strcmp(tok
->args
[i
], "Exit"))
1889 else if (!strcmp(tok
->args
[i
], "Stable"))
1891 else if (!strcmp(tok
->args
[i
], "Fast"))
1893 else if (!strcmp(tok
->args
[i
], "Running"))
1894 rs
->is_flagged_running
= 1;
1895 else if (!strcmp(tok
->args
[i
], "Named"))
1897 else if (!strcmp(tok
->args
[i
], "Valid"))
1899 else if (!strcmp(tok
->args
[i
], "Guard"))
1900 rs
->is_possible_guard
= 1;
1901 else if (!strcmp(tok
->args
[i
], "BadExit"))
1902 rs
->is_bad_exit
= 1;
1903 else if (!strcmp(tok
->args
[i
], "BadDirectory"))
1904 rs
->is_bad_directory
= 1;
1905 else if (!strcmp(tok
->args
[i
], "Authority"))
1906 rs
->is_authority
= 1;
1907 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
1908 consensus_method
>= 2) {
1909 /* Unnamed is computed right by consensus method 2 and later. */
1911 } else if (!strcmp(tok
->args
[i
], "HSDir")) {
1916 if ((tok
= find_opt_by_keyword(tokens
, K_V
))) {
1917 tor_assert(tok
->n_args
== 1);
1918 rs
->version_known
= 1;
1919 if (strcmpstart(tok
->args
[0], "Tor ")) {
1920 rs
->version_supports_microdesc_cache
= 1;
1921 rs
->version_supports_optimistic_data
= 1;
1923 rs
->version_supports_microdesc_cache
=
1924 tor_version_supports_microdescriptors(tok
->args
[0]);
1925 rs
->version_supports_optimistic_data
=
1926 tor_version_as_new_as(tok
->args
[0], "0.2.3.1-alpha");
1927 rs
->version_supports_extend2_cells
=
1928 tor_version_as_new_as(tok
->args
[0], "0.2.4.8-alpha");
1931 vote_rs
->version
= tor_strdup(tok
->args
[0]);
1935 /* handle weighting/bandwidth info */
1936 if ((tok
= find_opt_by_keyword(tokens
, K_W
))) {
1938 for (i
=0; i
< tok
->n_args
; ++i
) {
1939 if (!strcmpstart(tok
->args
[i
], "Bandwidth=")) {
1942 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
1946 log_warn(LD_DIR
, "Invalid Bandwidth %s", escaped(tok
->args
[i
]));
1949 rs
->has_bandwidth
= 1;
1950 } else if (!strcmpstart(tok
->args
[i
], "Measured=") && vote_rs
) {
1952 vote_rs
->measured_bw_kb
=
1953 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
1954 10, 0, UINT32_MAX
, &ok
, NULL
);
1956 log_warn(LD_DIR
, "Invalid Measured Bandwidth %s",
1957 escaped(tok
->args
[i
]));
1960 vote_rs
->has_measured_bw
= 1;
1961 vote
->has_measured_bws
= 1;
1962 } else if (!strcmpstart(tok
->args
[i
], "Unmeasured=1")) {
1963 rs
->bw_is_unmeasured
= 1;
1968 /* parse exit policy summaries */
1969 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
1970 tor_assert(tok
->n_args
== 1);
1971 if (strcmpstart(tok
->args
[0], "accept ") &&
1972 strcmpstart(tok
->args
[0], "reject ")) {
1973 log_warn(LD_DIR
, "Unknown exit policy summary type %s.",
1974 escaped(tok
->args
[0]));
1977 /* XXX weasel: parse this into ports and represent them somehow smart,
1978 * maybe not here but somewhere on if we need it for the client.
1979 * we should still parse it here to check it's valid tho.
1981 rs
->exitsummary
= tor_strdup(tok
->args
[0]);
1982 rs
->has_exitsummary
= 1;
1986 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, t
) {
1987 if (t
->tp
== K_M
&& t
->n_args
) {
1988 vote_microdesc_hash_t
*line
=
1989 tor_malloc(sizeof(vote_microdesc_hash_t
));
1990 line
->next
= vote_rs
->microdesc
;
1991 line
->microdesc_hash_line
= tor_strdup(t
->args
[0]);
1992 vote_rs
->microdesc
= line
;
1994 } SMARTLIST_FOREACH_END(t
);
1995 } else if (flav
== FLAV_MICRODESC
) {
1996 tok
= find_opt_by_keyword(tokens
, K_M
);
1998 tor_assert(tok
->n_args
);
1999 if (digest256_from_base64(rs
->descriptor_digest
, tok
->args
[0])) {
2000 log_warn(LD_DIR
, "Error decoding microdescriptor digest %s",
2001 escaped(tok
->args
[0]));
2005 log_info(LD_BUG
, "Found an entry in networkstatus with no "
2006 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
2007 rs
->nickname
, hex_str(rs
->identity_digest
, DIGEST_LEN
),
2008 fmt_addr32(rs
->addr
), rs
->or_port
);
2012 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
2017 dump_desc(s_dup
, "routerstatus entry");
2019 routerstatus_free(rs
);
2022 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2023 smartlist_clear(tokens
);
2025 DUMP_AREA(area
, "routerstatus entry");
2026 memarea_clear(area
);
2034 compare_vote_routerstatus_entries(const void **_a
, const void **_b
)
2036 const vote_routerstatus_t
*a
= *_a
, *b
= *_b
;
2037 return fast_memcmp(a
->status
.identity_digest
, b
->status
.identity_digest
,
2041 /** Verify the bandwidth weights of a network status document */
2043 networkstatus_verify_bw_weights(networkstatus_t
*ns
, int consensus_method
)
2045 int64_t weight_scale
;
2046 int64_t G
=0, M
=0, E
=0, D
=0, T
=0;
2047 double Wgg
, Wgm
, Wgd
, Wmg
, Wmm
, Wme
, Wmd
, Weg
, Wem
, Wee
, Wed
;
2048 double Gtotal
=0, Mtotal
=0, Etotal
=0;
2049 const char *casename
= NULL
;
2052 weight_scale
= networkstatus_get_weight_scale_param(ns
);
2053 Wgg
= networkstatus_get_bw_weight(ns
, "Wgg", -1);
2054 Wgm
= networkstatus_get_bw_weight(ns
, "Wgm", -1);
2055 Wgd
= networkstatus_get_bw_weight(ns
, "Wgd", -1);
2056 Wmg
= networkstatus_get_bw_weight(ns
, "Wmg", -1);
2057 Wmm
= networkstatus_get_bw_weight(ns
, "Wmm", -1);
2058 Wme
= networkstatus_get_bw_weight(ns
, "Wme", -1);
2059 Wmd
= networkstatus_get_bw_weight(ns
, "Wmd", -1);
2060 Weg
= networkstatus_get_bw_weight(ns
, "Weg", -1);
2061 Wem
= networkstatus_get_bw_weight(ns
, "Wem", -1);
2062 Wee
= networkstatus_get_bw_weight(ns
, "Wee", -1);
2063 Wed
= networkstatus_get_bw_weight(ns
, "Wed", -1);
2065 if (Wgg
<0 || Wgm
<0 || Wgd
<0 || Wmg
<0 || Wmm
<0 || Wme
<0 || Wmd
<0 || Weg
<0
2066 || Wem
<0 || Wee
<0 || Wed
<0) {
2067 log_warn(LD_BUG
, "No bandwidth weights produced in consensus!");
2071 // First, sanity check basic summing properties that hold for all cases
2072 // We use > 1 as the check for these because they are computed as integers.
2073 // Sometimes there are rounding errors.
2074 if (fabs(Wmm
- weight_scale
) > 1) {
2075 log_warn(LD_BUG
, "Wmm=%f != "I64_FORMAT
,
2076 Wmm
, I64_PRINTF_ARG(weight_scale
));
2080 if (fabs(Wem
- Wee
) > 1) {
2081 log_warn(LD_BUG
, "Wem=%f != Wee=%f", Wem
, Wee
);
2085 if (fabs(Wgm
- Wgg
) > 1) {
2086 log_warn(LD_BUG
, "Wgm=%f != Wgg=%f", Wgm
, Wgg
);
2090 if (fabs(Weg
- Wed
) > 1) {
2091 log_warn(LD_BUG
, "Wed=%f != Weg=%f", Wed
, Weg
);
2095 if (fabs(Wgg
+ Wmg
- weight_scale
) > 0.001*weight_scale
) {
2096 log_warn(LD_BUG
, "Wgg=%f != "I64_FORMAT
" - Wmg=%f", Wgg
,
2097 I64_PRINTF_ARG(weight_scale
), Wmg
);
2101 if (fabs(Wee
+ Wme
- weight_scale
) > 0.001*weight_scale
) {
2102 log_warn(LD_BUG
, "Wee=%f != "I64_FORMAT
" - Wme=%f", Wee
,
2103 I64_PRINTF_ARG(weight_scale
), Wme
);
2107 if (fabs(Wgd
+ Wmd
+ Wed
- weight_scale
) > 0.001*weight_scale
) {
2108 log_warn(LD_BUG
, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT
,
2109 Wgd
, Wmd
, Wed
, I64_PRINTF_ARG(weight_scale
));
2113 Wgg
/= weight_scale
;
2114 Wgm
/= weight_scale
;
2115 Wgd
/= weight_scale
;
2117 Wmg
/= weight_scale
;
2118 Wmm
/= weight_scale
;
2119 Wme
/= weight_scale
;
2120 Wmd
/= weight_scale
;
2122 Weg
/= weight_scale
;
2123 Wem
/= weight_scale
;
2124 Wee
/= weight_scale
;
2125 Wed
/= weight_scale
;
2127 // Then, gather G, M, E, D, T to determine case
2128 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, routerstatus_t
*, rs
) {
2130 if (consensus_method
>= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT
) {
2131 /* Bug #2203: Don't count bad exits as exits for balancing */
2132 is_exit
= rs
->is_exit
&& !rs
->is_bad_exit
;
2134 is_exit
= rs
->is_exit
;
2136 if (rs
->has_bandwidth
) {
2137 T
+= rs
->bandwidth_kb
;
2138 if (is_exit
&& rs
->is_possible_guard
) {
2139 D
+= rs
->bandwidth_kb
;
2140 Gtotal
+= Wgd
*rs
->bandwidth_kb
;
2141 Mtotal
+= Wmd
*rs
->bandwidth_kb
;
2142 Etotal
+= Wed
*rs
->bandwidth_kb
;
2143 } else if (is_exit
) {
2144 E
+= rs
->bandwidth_kb
;
2145 Mtotal
+= Wme
*rs
->bandwidth_kb
;
2146 Etotal
+= Wee
*rs
->bandwidth_kb
;
2147 } else if (rs
->is_possible_guard
) {
2148 G
+= rs
->bandwidth_kb
;
2149 Gtotal
+= Wgg
*rs
->bandwidth_kb
;
2150 Mtotal
+= Wmg
*rs
->bandwidth_kb
;
2152 M
+= rs
->bandwidth_kb
;
2153 Mtotal
+= Wmm
*rs
->bandwidth_kb
;
2156 log_warn(LD_BUG
, "Missing consensus bandwidth for router %s",
2157 routerstatus_describe(rs
));
2159 } SMARTLIST_FOREACH_END(rs
);
2161 // Finally, check equality conditions depending upon case 1, 2 or 3
2162 // Full equality cases: 1, 3b
2163 // Partial equality cases: 2b (E=G), 3a (M=E)
2164 // Fully unknown: 2a
2165 if (3*E
>= T
&& 3*G
>= T
) {
2166 // Case 1: Neither are scarce
2167 casename
= "Case 1";
2168 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2170 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2171 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2173 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2174 casename
, Etotal
, Mtotal
,
2175 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2176 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2177 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2180 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2182 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2183 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2185 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2186 casename
, Etotal
, Gtotal
,
2187 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2188 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2189 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2192 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2194 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2195 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2197 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2198 casename
, Mtotal
, Gtotal
,
2199 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2200 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2201 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2204 } else if (3*E
< T
&& 3*G
< T
) {
2205 int64_t R
= MIN(E
, G
);
2206 int64_t S
= MAX(E
, G
);
2208 * Case 2: Both Guards and Exits are scarce
2209 * Balance D between E and G, depending upon
2210 * D capacity and scarcity. Devote no extra
2211 * bandwidth to middle nodes.
2213 if (R
+D
< S
) { // Subcase a
2214 double Rtotal
, Stotal
;
2222 casename
= "Case 2a";
2224 if (Rtotal
> Stotal
) {
2226 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
2227 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2229 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2230 casename
, Rtotal
, Stotal
,
2231 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2232 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2233 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2239 "Bw Weight Failure for %s: 3*Rtotal %f > T "
2240 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2241 " D="I64_FORMAT
" T="I64_FORMAT
". "
2242 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2243 casename
, Rtotal
*3, I64_PRINTF_ARG(T
),
2244 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2245 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2246 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2252 "Bw Weight Failure for %s: 3*Stotal %f > T "
2253 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2254 " D="I64_FORMAT
" T="I64_FORMAT
". "
2255 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2256 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
2257 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2258 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2259 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2265 "Bw Weight Failure for %s: 3*Mtotal %f < T "
2267 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2269 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2270 casename
, Mtotal
*3, I64_PRINTF_ARG(T
),
2271 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2272 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2273 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2276 } else { // Subcase b: R+D > S
2277 casename
= "Case 2b";
2279 /* Check the rare-M redirect case. */
2280 if (D
!= 0 && 3*M
< T
) {
2281 casename
= "Case 2b (balanced)";
2282 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2284 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2285 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2287 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2288 casename
, Etotal
, Mtotal
,
2289 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2290 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2291 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2294 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2296 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2297 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2299 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2300 casename
, Etotal
, Gtotal
,
2301 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2302 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2303 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2306 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2308 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2309 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2311 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2312 casename
, Mtotal
, Gtotal
,
2313 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2314 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2315 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2319 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2321 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2322 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2324 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2325 casename
, Etotal
, Gtotal
,
2326 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2327 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2328 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2333 } else { // if (E < T/3 || G < T/3) {
2334 int64_t S
= MIN(E
, G
);
2335 int64_t NS
= MAX(E
, G
);
2336 if (3*(S
+D
) < T
) { // Subcase a:
2340 casename
= "Case 3a (G scarce)";
2343 } else { // if (G >= E) {
2344 casename
= "Case 3a (E scarce)";
2351 "Bw Weight Failure for %s: 3*Stotal %f > T "
2352 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
2353 " D="I64_FORMAT
" T="I64_FORMAT
". "
2354 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2355 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
2356 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2357 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2358 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2362 if (fabs(NStotal
-Mtotal
) > 0.01*MAX(NStotal
,Mtotal
)) {
2364 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
2365 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2367 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2368 casename
, NStotal
, Mtotal
,
2369 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2370 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2371 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2375 // if NS < M, NStotal > T/3 because only one of G or E is scarce
2376 if (3*NStotal
< T
) {
2378 "Bw Weight Failure for %s: 3*NStotal %f < T "
2379 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
2380 " E="I64_FORMAT
" D="I64_FORMAT
" T="I64_FORMAT
". "
2381 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2382 casename
, NStotal
*3, I64_PRINTF_ARG(T
),
2383 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2384 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2385 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2389 } else { // Subcase b: S+D >= T/3
2390 casename
= "Case 3b";
2391 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
2393 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2394 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2396 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2397 casename
, Etotal
, Mtotal
,
2398 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2399 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2400 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2403 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
2405 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2406 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2408 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2409 casename
, Etotal
, Gtotal
,
2410 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2411 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2412 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2415 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
2417 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2418 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
2420 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2421 casename
, Mtotal
, Gtotal
,
2422 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
2423 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
2424 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
2431 log_notice(LD_DIR
, "Bandwidth-weight %s is verified and valid.",
2437 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2438 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2440 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
2441 networkstatus_type_t ns_type
)
2443 smartlist_t
*tokens
= smartlist_new();
2444 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
2445 networkstatus_voter_info_t
*voter
= NULL
;
2446 networkstatus_t
*ns
= NULL
;
2447 digests_t ns_digests
;
2448 const char *cert
, *end_of_header
, *end_of_footer
, *s_dup
= s
;
2449 directory_token_t
*tok
;
2452 int i
, inorder
, n_signatures
= 0;
2453 memarea_t
*area
= NULL
, *rs_area
= NULL
;
2454 consensus_flavor_t flav
= FLAV_NS
;
2455 char *last_kwd
=NULL
;
2462 if (router_get_networkstatus_v3_hashes(s
, &ns_digests
)) {
2463 log_warn(LD_DIR
, "Unable to compute digest of network-status");
2467 area
= memarea_new();
2468 end_of_header
= find_start_of_next_routerstatus(s
);
2469 if (tokenize_string(area
, s
, end_of_header
, tokens
,
2470 (ns_type
== NS_TYPE_CONSENSUS
) ?
2471 networkstatus_consensus_token_table
:
2472 networkstatus_token_table
, 0)) {
2473 log_warn(LD_DIR
, "Error tokenizing network-status vote header");
2477 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
2478 memcpy(&ns
->digests
, &ns_digests
, sizeof(ns_digests
));
2480 tok
= find_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
2482 if (tok
->n_args
> 1) {
2483 int flavor
= networkstatus_parse_flavor_name(tok
->args
[1]);
2485 log_warn(LD_DIR
, "Can't parse document with unknown flavor %s",
2486 escaped(tok
->args
[1]));
2489 ns
->flavor
= flav
= flavor
;
2491 if (flav
!= FLAV_NS
&& ns_type
!= NS_TYPE_CONSENSUS
) {
2492 log_warn(LD_DIR
, "Flavor found on non-consensus networkstatus.");
2496 if (ns_type
!= NS_TYPE_CONSENSUS
) {
2497 const char *end_of_cert
= NULL
;
2498 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
2501 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
2502 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
2506 tok
= find_by_keyword(tokens
, K_VOTE_STATUS
);
2507 tor_assert(tok
->n_args
);
2508 if (!strcmp(tok
->args
[0], "vote")) {
2509 ns
->type
= NS_TYPE_VOTE
;
2510 } else if (!strcmp(tok
->args
[0], "consensus")) {
2511 ns
->type
= NS_TYPE_CONSENSUS
;
2512 } else if (!strcmp(tok
->args
[0], "opinion")) {
2513 ns
->type
= NS_TYPE_OPINION
;
2515 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
2516 escaped(tok
->args
[0]));
2519 if (ns_type
!= ns
->type
) {
2520 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
2524 if (ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_OPINION
) {
2525 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
2526 if (parse_iso_time(tok
->args
[0], &ns
->published
))
2529 ns
->supported_methods
= smartlist_new();
2530 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHODS
);
2532 for (i
=0; i
< tok
->n_args
; ++i
)
2533 smartlist_add(ns
->supported_methods
, tor_strdup(tok
->args
[i
]));
2535 smartlist_add(ns
->supported_methods
, tor_strdup("1"));
2538 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHOD
);
2540 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
2545 ns
->consensus_method
= 1;
2549 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
2550 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
2553 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
2554 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
2557 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
2558 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
2561 tok
= find_by_keyword(tokens
, K_VOTING_DELAY
);
2562 tor_assert(tok
->n_args
>= 2);
2564 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
2568 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
2571 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
> ns
->fresh_until
) {
2572 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
2575 if (ns
->valid_after
+ MIN_VOTE_INTERVAL
*2 > ns
->valid_until
) {
2576 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
2579 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
2580 log_warn(LD_DIR
, "Vote seconds is too short");
2583 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
2584 log_warn(LD_DIR
, "Dist seconds is too short");
2588 if ((tok
= find_opt_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
2589 ns
->client_versions
= tor_strdup(tok
->args
[0]);
2591 if ((tok
= find_opt_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
2592 ns
->server_versions
= tor_strdup(tok
->args
[0]);
2595 tok
= find_by_keyword(tokens
, K_KNOWN_FLAGS
);
2596 ns
->known_flags
= smartlist_new();
2598 for (i
= 0; i
< tok
->n_args
; ++i
) {
2599 smartlist_add(ns
->known_flags
, tor_strdup(tok
->args
[i
]));
2600 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
2601 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2606 log_warn(LD_DIR
, "known-flags not in order");
2609 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
2610 smartlist_len(ns
->known_flags
) > MAX_KNOWN_FLAGS_IN_VOTE
) {
2611 /* If we allowed more than 64 flags in votes, then parsing them would make
2612 * us invoke undefined behavior whenever we used 1<<flagnum to do a
2613 * bit-shift. This is only for votes and opinions: consensus users don't
2614 * care about flags they don't recognize, and so don't build a bitfield
2616 log_warn(LD_DIR
, "Too many known-flags in consensus vote or opinion");
2620 tok
= find_opt_by_keyword(tokens
, K_PARAMS
);
2624 ns
->net_params
= smartlist_new();
2625 for (i
= 0; i
< tok
->n_args
; ++i
) {
2627 char *eq
= strchr(tok
->args
[i
], '=');
2630 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
2633 eq_pos
= eq
-tok
->args
[i
];
2634 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
2636 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
2639 if (i
> 0 && strcmp(tok
->args
[i
-1], tok
->args
[i
]) >= 0) {
2640 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
2643 if (last_kwd
&& eq_pos
== strlen(last_kwd
) &&
2644 fast_memeq(last_kwd
, tok
->args
[i
], eq_pos
)) {
2645 log_warn(LD_DIR
, "Duplicate value for %s parameter",
2646 escaped(tok
->args
[i
]));
2650 last_kwd
= tor_strndup(tok
->args
[i
], eq_pos
);
2651 smartlist_add(ns
->net_params
, tor_strdup(tok
->args
[i
]));
2654 log_warn(LD_DIR
, "params not in order");
2658 log_warn(LD_DIR
, "Duplicate in parameters");
2663 ns
->voters
= smartlist_new();
2665 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
2667 if (tok
->tp
== K_DIR_SOURCE
) {
2668 tor_assert(tok
->n_args
>= 6);
2671 smartlist_add(ns
->voters
, voter
);
2672 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
2673 voter
->sigs
= smartlist_new();
2674 if (ns
->type
!= NS_TYPE_CONSENSUS
)
2675 memcpy(voter
->vote_digest
, ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
);
2677 voter
->nickname
= tor_strdup(tok
->args
[0]);
2678 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2679 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
2680 tok
->args
[1], HEX_DIGEST_LEN
) < 0) {
2681 log_warn(LD_DIR
, "Error decoding identity digest %s in "
2682 "network-status vote.", escaped(tok
->args
[1]));
2685 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
2686 tor_memneq(ns
->cert
->cache_info
.identity_digest
,
2687 voter
->identity_digest
, DIGEST_LEN
)) {
2688 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
2691 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2692 if (authority_cert_is_blacklisted(ns
->cert
)) {
2693 log_warn(LD_DIR
, "Rejecting vote signature made with blacklisted "
2695 hex_str(ns
->cert
->signing_key_digest
, DIGEST_LEN
));
2699 voter
->address
= tor_strdup(tok
->args
[2]);
2700 if (!tor_inet_aton(tok
->args
[3], &in
)) {
2701 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
2702 escaped(tok
->args
[3]));
2705 voter
->addr
= ntohl(in
.s_addr
);
2706 voter
->dir_port
= (uint16_t)
2707 tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
2710 voter
->or_port
= (uint16_t)
2711 tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
2714 } else if (tok
->tp
== K_CONTACT
) {
2715 if (!voter
|| voter
->contact
) {
2716 log_warn(LD_DIR
, "contact element is out of place.");
2719 voter
->contact
= tor_strdup(tok
->args
[0]);
2720 } else if (tok
->tp
== K_VOTE_DIGEST
) {
2721 tor_assert(ns
->type
== NS_TYPE_CONSENSUS
);
2722 tor_assert(tok
->n_args
>= 1);
2723 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
2724 log_warn(LD_DIR
, "vote-digest element is out of place.");
2727 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
2728 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
2729 tok
->args
[0], HEX_DIGEST_LEN
) < 0) {
2730 log_warn(LD_DIR
, "Error decoding vote digest %s in "
2731 "network-status consensus.", escaped(tok
->args
[0]));
2735 } SMARTLIST_FOREACH_END(_tok
);
2737 smartlist_add(ns
->voters
, voter
);
2740 if (smartlist_len(ns
->voters
) == 0) {
2741 log_warn(LD_DIR
, "Missing dir-source elements in a vote networkstatus.");
2743 } else if (ns
->type
!= NS_TYPE_CONSENSUS
&& smartlist_len(ns
->voters
) != 1) {
2744 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
2748 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
2749 (tok
= find_opt_by_keyword(tokens
, K_LEGACY_DIR_KEY
))) {
2751 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
2752 networkstatus_voter_info_t
*voter
= smartlist_get(ns
->voters
, 0);
2753 if (base16_decode(voter
->legacy_id_digest
, DIGEST_LEN
,
2754 tok
->args
[0], HEX_DIGEST_LEN
)<0)
2760 log_warn(LD_DIR
, "Invalid legacy key digest %s on vote.",
2761 escaped(tok
->args
[0]));
2765 /* Parse routerstatus lines. */
2766 rs_tokens
= smartlist_new();
2767 rs_area
= memarea_new();
2769 ns
->routerstatus_list
= smartlist_new();
2771 while (!strcmpstart(s
, "r ")) {
2772 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2773 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
2774 if (routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
, ns
,
2776 smartlist_add(ns
->routerstatus_list
, rs
);
2778 tor_free(rs
->version
);
2783 if ((rs
= routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
,
2785 ns
->consensus_method
,
2787 smartlist_add(ns
->routerstatus_list
, rs
);
2790 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
2791 routerstatus_t
*rs1
, *rs2
;
2792 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2793 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
2794 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
2795 rs1
= &a
->status
; rs2
= &b
->status
;
2797 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
2798 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
2800 if (fast_memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
)
2802 log_warn(LD_DIR
, "Vote networkstatus entries not sorted by identity "
2808 /* Parse footer; check signature. */
2809 footer_tokens
= smartlist_new();
2810 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
2813 end_of_footer
= s
+ strlen(s
);
2814 if (tokenize_string(area
,s
, end_of_footer
, footer_tokens
,
2815 networkstatus_vote_footer_token_table
, 0)) {
2816 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
2822 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
2824 if (tok
->tp
== K_DIRECTORY_SIGNATURE
)
2826 else if (found_sig
) {
2827 log_warn(LD_DIR
, "Extraneous token after first directory-signature");
2830 } SMARTLIST_FOREACH_END(_tok
);
2833 if ((tok
= find_opt_by_keyword(footer_tokens
, K_DIRECTORY_FOOTER
))) {
2834 if (tok
!= smartlist_get(footer_tokens
, 0)) {
2835 log_warn(LD_DIR
, "Misplaced directory-footer token");
2840 tok
= find_opt_by_keyword(footer_tokens
, K_BW_WEIGHTS
);
2842 ns
->weight_params
= smartlist_new();
2843 for (i
= 0; i
< tok
->n_args
; ++i
) {
2845 char *eq
= strchr(tok
->args
[i
], '=');
2847 log_warn(LD_DIR
, "Bad element '%s' in weight params",
2848 escaped(tok
->args
[i
]));
2851 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
2853 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
2856 smartlist_add(ns
->weight_params
, tor_strdup(tok
->args
[i
]));
2860 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
2861 char declared_identity
[DIGEST_LEN
];
2862 networkstatus_voter_info_t
*v
;
2863 document_signature_t
*sig
;
2864 const char *id_hexdigest
= NULL
;
2865 const char *sk_hexdigest
= NULL
;
2866 digest_algorithm_t alg
= DIGEST_SHA1
;
2868 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
2870 tor_assert(tok
->n_args
>= 2);
2871 if (tok
->n_args
== 2) {
2872 id_hexdigest
= tok
->args
[0];
2873 sk_hexdigest
= tok
->args
[1];
2875 const char *algname
= tok
->args
[0];
2877 id_hexdigest
= tok
->args
[1];
2878 sk_hexdigest
= tok
->args
[2];
2879 a
= crypto_digest_algorithm_parse_name(algname
);
2881 log_warn(LD_DIR
, "Unknown digest algorithm %s; skipping",
2888 if (!tok
->object_type
||
2889 strcmp(tok
->object_type
, "SIGNATURE") ||
2890 tok
->object_size
< 128 || tok
->object_size
> 512) {
2891 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
2895 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
2896 base16_decode(declared_identity
, sizeof(declared_identity
),
2897 id_hexdigest
, HEX_DIGEST_LEN
) < 0) {
2898 log_warn(LD_DIR
, "Error decoding declared identity %s in "
2899 "network-status vote.", escaped(id_hexdigest
));
2902 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
2903 log_warn(LD_DIR
, "ID on signature on network-status vote does not match "
2904 "any declared directory source.");
2907 sig
= tor_malloc_zero(sizeof(document_signature_t
));
2908 memcpy(sig
->identity_digest
, v
->identity_digest
, DIGEST_LEN
);
2910 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
2911 base16_decode(sig
->signing_key_digest
, sizeof(sig
->signing_key_digest
),
2912 sk_hexdigest
, HEX_DIGEST_LEN
) < 0) {
2913 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
2914 "network-status vote.", escaped(sk_hexdigest
));
2919 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2920 if (tor_memneq(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
2922 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
2923 "network-status vote.");
2929 if (voter_get_sig_by_algorithm(v
, sig
->alg
)) {
2930 /* We already parsed a vote with this algorithm from this voter. Use the
2932 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "We received a networkstatus "
2933 "that contains two votes from the same voter with the same "
2934 "algorithm. Ignoring the second vote.");
2939 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
2940 if (check_signature_token(ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
,
2941 tok
, ns
->cert
->signing_key
, 0,
2942 "network-status vote")) {
2946 sig
->good_signature
= 1;
2948 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
2952 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
2953 sig
->signature_len
= (int) tok
->object_size
;
2955 smartlist_add(v
->sigs
, sig
);
2958 } SMARTLIST_FOREACH_END(_tok
);
2960 if (! n_signatures
) {
2961 log_warn(LD_DIR
, "No signatures on networkstatus vote.");
2963 } else if (ns
->type
== NS_TYPE_VOTE
&& n_signatures
!= 1) {
2964 log_warn(LD_DIR
, "Received more than one signature on a "
2965 "network-status vote.");
2970 *eos_out
= end_of_footer
;
2974 dump_desc(s_dup
, "v3 networkstatus");
2975 networkstatus_vote_free(ns
);
2979 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2980 smartlist_free(tokens
);
2984 SMARTLIST_FOREACH(voter
->sigs
, document_signature_t
*, sig
,
2985 document_signature_free(sig
));
2986 smartlist_free(voter
->sigs
);
2988 tor_free(voter
->nickname
);
2989 tor_free(voter
->address
);
2990 tor_free(voter
->contact
);
2994 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_clear(t
));
2995 smartlist_free(rs_tokens
);
2997 if (footer_tokens
) {
2998 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_clear(t
));
2999 smartlist_free(footer_tokens
);
3002 DUMP_AREA(area
, "v3 networkstatus");
3003 memarea_drop_all(area
);
3006 memarea_drop_all(rs_area
);
3012 /** Return the digests_t that holds the digests of the
3013 * <b>flavor_name</b>-flavored networkstatus according to the detached
3014 * signatures document <b>sigs</b>, allocating a new digests_t as neeeded. */
3016 detached_get_digests(ns_detached_signatures_t
*sigs
, const char *flavor_name
)
3018 digests_t
*d
= strmap_get(sigs
->digests
, flavor_name
);
3020 d
= tor_malloc_zero(sizeof(digests_t
));
3021 strmap_set(sigs
->digests
, flavor_name
, d
);
3026 /** Return the list of signatures of the <b>flavor_name</b>-flavored
3027 * networkstatus according to the detached signatures document <b>sigs</b>,
3028 * allocating a new digests_t as neeeded. */
3029 static smartlist_t
*
3030 detached_get_signatures(ns_detached_signatures_t
*sigs
,
3031 const char *flavor_name
)
3033 smartlist_t
*sl
= strmap_get(sigs
->signatures
, flavor_name
);
3035 sl
= smartlist_new();
3036 strmap_set(sigs
->signatures
, flavor_name
, sl
);
3041 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
3042 * <b>eos</b> and return the result. Return -1 on failure. */
3043 ns_detached_signatures_t
*
3044 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
3046 /* XXXX there is too much duplicate shared between this function and
3047 * networkstatus_parse_vote_from_string(). */
3048 directory_token_t
*tok
;
3049 memarea_t
*area
= NULL
;
3052 smartlist_t
*tokens
= smartlist_new();
3053 ns_detached_signatures_t
*sigs
=
3054 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
3055 sigs
->digests
= strmap_new();
3056 sigs
->signatures
= strmap_new();
3059 eos
= s
+ strlen(s
);
3061 area
= memarea_new();
3062 if (tokenize_string(area
,s
, eos
, tokens
,
3063 networkstatus_detached_signature_token_table
, 0)) {
3064 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
3068 /* Grab all the digest-like tokens. */
3069 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3070 const char *algname
;
3071 digest_algorithm_t alg
;
3073 const char *hexdigest
;
3074 size_t expected_length
;
3078 if (tok
->tp
== K_CONSENSUS_DIGEST
) {
3082 hexdigest
= tok
->args
[0];
3083 } else if (tok
->tp
== K_ADDITIONAL_DIGEST
) {
3084 int a
= crypto_digest_algorithm_parse_name(tok
->args
[1]);
3086 log_warn(LD_DIR
, "Unrecognized algorithm name %s", tok
->args
[0]);
3089 alg
= (digest_algorithm_t
) a
;
3090 flavor
= tok
->args
[0];
3091 algname
= tok
->args
[1];
3092 hexdigest
= tok
->args
[2];
3098 (alg
== DIGEST_SHA1
) ? HEX_DIGEST_LEN
: HEX_DIGEST256_LEN
;
3100 if (strlen(hexdigest
) != expected_length
) {
3101 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
3102 "networkstatus signatures");
3105 digests
= detached_get_digests(sigs
, flavor
);
3106 tor_assert(digests
);
3107 if (!tor_mem_is_zero(digests
->d
[alg
], DIGEST256_LEN
)) {
3108 log_warn(LD_DIR
, "Multiple digests for %s with %s on detached "
3109 "signatures document", flavor
, algname
);
3112 if (base16_decode(digests
->d
[alg
], DIGEST256_LEN
,
3113 hexdigest
, strlen(hexdigest
)) < 0) {
3114 log_warn(LD_DIR
, "Bad encoding on consensus-digest in detached "
3115 "networkstatus signatures");
3118 } SMARTLIST_FOREACH_END(_tok
);
3120 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
3121 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
3122 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
3126 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
3127 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
3128 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
3132 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
3133 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
3134 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
3138 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3139 const char *id_hexdigest
;
3140 const char *sk_hexdigest
;
3141 const char *algname
;
3143 digest_algorithm_t alg
;
3145 char id_digest
[DIGEST_LEN
];
3146 char sk_digest
[DIGEST_LEN
];
3147 smartlist_t
*siglist
;
3148 document_signature_t
*sig
;
3152 if (tok
->tp
== K_DIRECTORY_SIGNATURE
) {
3153 tor_assert(tok
->n_args
>= 2);
3156 id_hexdigest
= tok
->args
[0];
3157 sk_hexdigest
= tok
->args
[1];
3158 } else if (tok
->tp
== K_ADDITIONAL_SIGNATURE
) {
3159 tor_assert(tok
->n_args
>= 4);
3160 flavor
= tok
->args
[0];
3161 algname
= tok
->args
[1];
3162 id_hexdigest
= tok
->args
[2];
3163 sk_hexdigest
= tok
->args
[3];
3169 int a
= crypto_digest_algorithm_parse_name(algname
);
3171 log_warn(LD_DIR
, "Unrecognized algorithm name %s", algname
);
3174 alg
= (digest_algorithm_t
) a
;
3177 if (!tok
->object_type
||
3178 strcmp(tok
->object_type
, "SIGNATURE") ||
3179 tok
->object_size
< 128 || tok
->object_size
> 512) {
3180 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
3184 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
3185 base16_decode(id_digest
, sizeof(id_digest
),
3186 id_hexdigest
, HEX_DIGEST_LEN
) < 0) {
3187 log_warn(LD_DIR
, "Error decoding declared identity %s in "
3188 "network-status vote.", escaped(id_hexdigest
));
3191 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
3192 base16_decode(sk_digest
, sizeof(sk_digest
),
3193 sk_hexdigest
, HEX_DIGEST_LEN
) < 0) {
3194 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
3195 "network-status vote.", escaped(sk_hexdigest
));
3199 siglist
= detached_get_signatures(sigs
, flavor
);
3201 SMARTLIST_FOREACH(siglist
, document_signature_t
*, dsig
, {
3202 if (dsig
->alg
== alg
&&
3203 tor_memeq(id_digest
, dsig
->identity_digest
, DIGEST_LEN
) &&
3204 tor_memeq(sk_digest
, dsig
->signing_key_digest
, DIGEST_LEN
)) {
3209 log_warn(LD_DIR
, "Two signatures with identical keys and algorithm "
3214 sig
= tor_malloc_zero(sizeof(document_signature_t
));
3216 memcpy(sig
->identity_digest
, id_digest
, DIGEST_LEN
);
3217 memcpy(sig
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
3218 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
3222 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
3223 sig
->signature_len
= (int) tok
->object_size
;
3225 smartlist_add(siglist
, sig
);
3226 } SMARTLIST_FOREACH_END(_tok
);
3230 ns_detached_signatures_free(sigs
);
3233 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
3234 smartlist_free(tokens
);
3236 DUMP_AREA(area
, "detached signatures");
3237 memarea_drop_all(area
);
3242 /** Parse the addr policy in the string <b>s</b> and return it. If
3243 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
3244 * ADDR_POLICY_REJECT) for items that specify no action.
3246 * The addr_policy_t returned by this function can have its address set to
3247 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
3248 * of AF_INET and AF_INET6 items.
3251 router_parse_addr_policy_item_from_string(const char *s
, int assume_action
)
3253 directory_token_t
*tok
= NULL
;
3254 const char *cp
, *eos
;
3255 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
3256 * But note that there can be an arbitrary amount of space between the
3257 * accept and the address:mask/port element. */
3258 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
3260 memarea_t
*area
= NULL
;
3262 s
= eat_whitespace(s
);
3263 if ((*s
== '*' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
3264 if (tor_snprintf(line
, sizeof(line
), "%s %s",
3265 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
3266 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
3271 } else { /* assume an already well-formed address policy line */
3275 eos
= cp
+ strlen(cp
);
3276 area
= memarea_new();
3277 tok
= get_next_token(area
, &cp
, eos
, routerdesc_token_table
);
3278 if (tok
->tp
== ERR_
) {
3279 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
3282 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_ACCEPT6
&&
3283 tok
->tp
!= K_REJECT
&& tok
->tp
!= K_REJECT6
) {
3284 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
3288 r
= router_parse_addr_policy(tok
, TAPMP_EXTENDED_STAR
);
3295 DUMP_AREA(area
, "policy item");
3296 memarea_drop_all(area
);
3301 /** Add an exit policy stored in the token <b>tok</b> to the router info in
3302 * <b>router</b>. Return 0 on success, -1 on failure. */
3304 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
3306 addr_policy_t
*newe
;
3307 newe
= router_parse_addr_policy(tok
, 0);
3310 if (! router
->exit_policy
)
3311 router
->exit_policy
= smartlist_new();
3313 if (((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
3314 tor_addr_family(&newe
->addr
) == AF_INET
)
3316 ((tok
->tp
== K_ACCEPT
|| tok
->tp
== K_REJECT
) &&
3317 tor_addr_family(&newe
->addr
) == AF_INET6
)) {
3318 log_warn(LD_DIR
, "Mismatch between field type and address type in exit "
3320 addr_policy_free(newe
);
3324 smartlist_add(router
->exit_policy
, newe
);
3329 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
3330 * a new exit_policy_t corresponding to the token. */
3331 static addr_policy_t
*
3332 router_parse_addr_policy(directory_token_t
*tok
, unsigned fmt_flags
)
3337 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
||
3338 tok
->tp
== K_ACCEPT
|| tok
->tp
== K_ACCEPT6
);
3340 if (tok
->n_args
!= 1)
3344 if (!strcmpstart(arg
,"private"))
3345 return router_parse_addr_policy_private(tok
);
3347 memset(&newe
, 0, sizeof(newe
));
3349 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
3350 newe
.policy_type
= ADDR_POLICY_REJECT
;
3352 newe
.policy_type
= ADDR_POLICY_ACCEPT
;
3354 if (tor_addr_parse_mask_ports(arg
, fmt_flags
, &newe
.addr
, &newe
.maskbits
,
3355 &newe
.prt_min
, &newe
.prt_max
) < 0) {
3356 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
3360 return addr_policy_get_canonical_entry(&newe
);
3363 /** Parse an exit policy line of the format "accept/reject private:...".
3364 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
3365 * router descriptors until earlier versions are obsolete.
3367 static addr_policy_t
*
3368 router_parse_addr_policy_private(directory_token_t
*tok
)
3371 uint16_t port_min
, port_max
;
3372 addr_policy_t result
;
3375 if (strcmpstart(arg
, "private"))
3378 arg
+= strlen("private");
3379 arg
= (char*) eat_whitespace(arg
);
3380 if (!arg
|| *arg
!= ':')
3383 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
3386 memset(&result
, 0, sizeof(result
));
3387 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
3388 result
.policy_type
= ADDR_POLICY_REJECT
;
3390 result
.policy_type
= ADDR_POLICY_ACCEPT
;
3391 result
.is_private
= 1;
3392 result
.prt_min
= port_min
;
3393 result
.prt_max
= port_max
;
3395 return addr_policy_get_canonical_entry(&result
);
3398 /** Log and exit if <b>t</b> is malformed */
3400 assert_addr_policy_ok(smartlist_t
*lst
)
3403 SMARTLIST_FOREACH(lst
, addr_policy_t
*, t
, {
3404 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
3405 t
->policy_type
== ADDR_POLICY_ACCEPT
);
3406 tor_assert(t
->prt_min
<= t
->prt_max
);
3411 * Low-level tokenizer for router descriptors and directories.
3414 /** Free all resources allocated for <b>tok</b> */
3416 token_clear(directory_token_t
*tok
)
3419 crypto_pk_free(tok
->key
);
3422 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
3423 #define ALLOC(sz) memarea_alloc(area,sz)
3424 #define STRDUP(str) memarea_strdup(area,str)
3425 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
3427 #define RET_ERR(msg) \
3429 if (tok) token_clear(tok); \
3430 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
3432 tok->error = STRDUP(msg); \
3433 goto done_tokenizing; \
3436 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
3437 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
3438 * Return <b>tok</b> on success, or a new ERR_ token if the token didn't
3439 * conform to the syntax we wanted.
3441 static INLINE directory_token_t
*
3442 token_check_object(memarea_t
*area
, const char *kwd
,
3443 directory_token_t
*tok
, obj_syntax o_syn
)
3448 /* No object is allowed for this token. */
3449 if (tok
->object_body
) {
3450 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected object for %s", kwd
);
3454 tor_snprintf(ebuf
, sizeof(ebuf
), "Unexpected public key for %s", kwd
);
3459 /* There must be a (non-key) object. */
3460 if (!tok
->object_body
) {
3461 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing object for %s", kwd
);
3465 case NEED_KEY_1024
: /* There must be a 1024-bit public key. */
3466 case NEED_SKEY_1024
: /* There must be a 1024-bit private key. */
3467 if (tok
->key
&& crypto_pk_num_bits(tok
->key
) != PK_BYTES
*8) {
3468 tor_snprintf(ebuf
, sizeof(ebuf
), "Wrong size on key for %s: %d bits",
3469 kwd
, crypto_pk_num_bits(tok
->key
));
3473 case NEED_KEY
: /* There must be some kind of key. */
3475 tor_snprintf(ebuf
, sizeof(ebuf
), "Missing public key for %s", kwd
);
3478 if (o_syn
!= NEED_SKEY_1024
) {
3479 if (crypto_pk_key_is_private(tok
->key
)) {
3480 tor_snprintf(ebuf
, sizeof(ebuf
),
3481 "Private key given for %s, which wants a public key", kwd
);
3484 } else { /* o_syn == NEED_SKEY_1024 */
3485 if (!crypto_pk_key_is_private(tok
->key
)) {
3486 tor_snprintf(ebuf
, sizeof(ebuf
),
3487 "Public key given for %s, which wants a private key", kwd
);
3493 /* Anything goes with this token. */
3501 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3502 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3503 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3504 * all storage in <b>area</b>. Return the number of arguments parsed, or
3505 * return -1 if there was an insanely high number of arguments. */
3507 get_token_arguments(memarea_t
*area
, directory_token_t
*tok
,
3508 const char *s
, const char *eol
)
3510 /** Largest number of arguments we'll accept to any token, ever. */
3511 #define MAX_ARGS 512
3512 char *mem
= memarea_strndup(area
, s
, eol
-s
);
3515 char *args
[MAX_ARGS
];
3520 cp
= (char*)find_whitespace(cp
);
3522 break; /* End of the line. */
3524 cp
= (char*)eat_whitespace(cp
);
3527 tok
->args
= memarea_memdup(area
, args
, j
*sizeof(char*));
3532 /** Helper function: read the next token from *s, advance *s to the end of the
3533 * token, and return the parsed token. Parse *<b>s</b> according to the list
3534 * of tokens in <b>table</b>.
3536 static directory_token_t
*
3537 get_next_token(memarea_t
*area
,
3538 const char **s
, const char *eos
, token_rule_t
*table
)
3540 /** Reject any object at least this big; it is probably an overflow, an
3541 * attack, a bug, or some other nonsense. */
3542 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
3543 /** Reject any line at least this big; it is probably an overflow, an
3544 * attack, a bug, or some other nonsense. */
3545 #define MAX_LINE_LENGTH (128*1024)
3547 const char *next
, *eol
, *obstart
;
3550 directory_token_t
*tok
;
3551 obj_syntax o_syn
= NO_OBJ
;
3553 const char *kwd
= "";
3556 tok
= ALLOC_ZERO(sizeof(directory_token_t
));
3559 /* Set *s to first token, eol to end-of-line, next to after first token */
3560 *s
= eat_whitespace_eos(*s
, eos
); /* eat multi-line whitespace */
3561 tor_assert(eos
>= *s
);
3562 eol
= memchr(*s
, '\n', eos
-*s
);
3565 if (eol
- *s
> MAX_LINE_LENGTH
) {
3566 RET_ERR("Line far too long");
3569 next
= find_whitespace_eos(*s
, eol
);
3571 if (!strcmp_len(*s
, "opt", next
-*s
)) {
3572 /* Skip past an "opt" at the start of the line. */
3573 *s
= eat_whitespace_eos_no_nl(next
, eol
);
3574 next
= find_whitespace_eos(*s
, eol
);
3575 } else if (*s
== eos
) { /* If no "opt", and end-of-line, line is invalid */
3576 RET_ERR("Unexpected EOF");
3579 /* Search the table for the appropriate entry. (I tried a binary search
3580 * instead, but it wasn't any faster.) */
3581 for (i
= 0; table
[i
].t
; ++i
) {
3582 if (!strcmp_len(*s
, table
[i
].t
, next
-*s
)) {
3583 /* We've found the keyword. */
3585 tok
->tp
= table
[i
].v
;
3586 o_syn
= table
[i
].os
;
3587 *s
= eat_whitespace_eos_no_nl(next
, eol
);
3588 /* We go ahead whether there are arguments or not, so that tok->args is
3589 * always set if we want arguments. */
3590 if (table
[i
].concat_args
) {
3591 /* The keyword takes the line as a single argument */
3592 tok
->args
= ALLOC(sizeof(char*));
3593 tok
->args
[0] = STRNDUP(*s
,eol
-*s
); /* Grab everything on line */
3596 /* This keyword takes multiple arguments. */
3597 if (get_token_arguments(area
, tok
, *s
, eol
)<0) {
3598 tor_snprintf(ebuf
, sizeof(ebuf
),"Far too many arguments to %s", kwd
);
3603 if (tok
->n_args
< table
[i
].min_args
) {
3604 tor_snprintf(ebuf
, sizeof(ebuf
), "Too few arguments to %s", kwd
);
3606 } else if (tok
->n_args
> table
[i
].max_args
) {
3607 tor_snprintf(ebuf
, sizeof(ebuf
), "Too many arguments to %s", kwd
);
3614 if (tok
->tp
== ERR_
) {
3615 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3617 tok
->tp
= A_UNKNOWN_
;
3620 tok
->args
= ALLOC(sizeof(char*));
3621 tok
->args
[0] = STRNDUP(*s
, eol
-*s
);
3626 /* Check whether there's an object present */
3627 *s
= eat_whitespace_eos(eol
, eos
); /* Scan from end of first line */
3628 tor_assert(eos
>= *s
);
3629 eol
= memchr(*s
, '\n', eos
-*s
);
3630 if (!eol
|| eol
-*s
<11 || strcmpstart(*s
, "-----BEGIN ")) /* No object. */
3633 obstart
= *s
; /* Set obstart to start of object spec */
3634 if (*s
+16 >= eol
|| memchr(*s
+11,'\0',eol
-*s
-16) || /* no short lines, */
3635 strcmp_len(eol
-5, "-----", 5) || /* nuls or invalid endings */
3636 (eol
-*s
) > MAX_UNPARSED_OBJECT_SIZE
) { /* name too long */
3637 RET_ERR("Malformed object: bad begin line");
3639 tok
->object_type
= STRNDUP(*s
+11, eol
-*s
-16);
3640 obname_len
= eol
-*s
-16; /* store objname length here to avoid a strlen() */
3641 *s
= eol
+1; /* Set *s to possible start of object data (could be eos) */
3643 /* Go to the end of the object */
3644 next
= tor_memstr(*s
, eos
-*s
, "-----END ");
3646 RET_ERR("Malformed object: missing object end line");
3648 tor_assert(eos
>= next
);
3649 eol
= memchr(next
, '\n', eos
-next
);
3650 if (!eol
) /* end-of-line marker, or eos if there's no '\n' */
3652 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3653 if ((size_t)(eol
-next
) != 9+obname_len
+5 ||
3654 strcmp_len(next
+9, tok
->object_type
, obname_len
) ||
3655 strcmp_len(eol
-5, "-----", 5)) {
3656 tor_snprintf(ebuf
, sizeof(ebuf
), "Malformed object: mismatched end tag %s",
3658 ebuf
[sizeof(ebuf
)-1] = '\0';
3661 if (next
- *s
> MAX_UNPARSED_OBJECT_SIZE
)
3662 RET_ERR("Couldn't parse object: missing footer or object much too big.");
3664 if (!strcmp(tok
->object_type
, "RSA PUBLIC KEY")) { /* If it's a public key */
3665 tok
->key
= crypto_pk_new();
3666 if (crypto_pk_read_public_key_from_string(tok
->key
, obstart
, eol
-obstart
))
3667 RET_ERR("Couldn't parse public key.");
3668 } else if (!strcmp(tok
->object_type
, "RSA PRIVATE KEY")) { /* private key */
3669 tok
->key
= crypto_pk_new();
3670 if (crypto_pk_read_private_key_from_string(tok
->key
, obstart
, eol
-obstart
))
3671 RET_ERR("Couldn't parse private key.");
3672 } else { /* If it's something else, try to base64-decode it */
3674 tok
->object_body
= ALLOC(next
-*s
); /* really, this is too much RAM. */
3675 r
= base64_decode(tok
->object_body
, next
-*s
, *s
, next
-*s
);
3677 RET_ERR("Malformed object: bad base64-encoded data");
3678 tok
->object_size
= r
;
3683 tok
= token_check_object(area
, kwd
, tok
, o_syn
);
3695 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3696 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3697 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3701 tokenize_string(memarea_t
*area
,
3702 const char *start
, const char *end
, smartlist_t
*out
,
3703 token_rule_t
*table
, int flags
)
3706 directory_token_t
*tok
= NULL
;
3709 int first_nonannotation
;
3710 int prev_len
= smartlist_len(out
);
3715 end
= start
+strlen(start
);
3717 /* it's only meaningful to check for nuls if we got an end-of-string ptr */
3718 if (memchr(start
, '\0', end
-start
)) {
3719 log_warn(LD_DIR
, "parse error: internal NUL character.");
3723 for (i
= 0; i
< NIL_
; ++i
)
3726 SMARTLIST_FOREACH(out
, const directory_token_t
*, t
, ++counts
[t
->tp
]);
3728 while (*s
< end
&& (!tok
|| tok
->tp
!= EOF_
)) {
3729 tok
= get_next_token(area
, s
, end
, table
);
3730 if (tok
->tp
== ERR_
) {
3731 log_warn(LD_DIR
, "parse error: %s", tok
->error
);
3736 smartlist_add(out
, tok
);
3737 *s
= eat_whitespace_eos(*s
, end
);
3740 if (flags
& TS_NOCHECK
)
3743 if ((flags
& TS_ANNOTATIONS_OK
)) {
3744 first_nonannotation
= -1;
3745 for (i
= 0; i
< smartlist_len(out
); ++i
) {
3746 tok
= smartlist_get(out
, i
);
3747 if (tok
->tp
< MIN_ANNOTATION
|| tok
->tp
> MAX_ANNOTATION
) {
3748 first_nonannotation
= i
;
3752 if (first_nonannotation
< 0) {
3753 log_warn(LD_DIR
, "parse error: item contains only annotations");
3756 for (i
=first_nonannotation
; i
< smartlist_len(out
); ++i
) {
3757 tok
= smartlist_get(out
, i
);
3758 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
3759 log_warn(LD_DIR
, "parse error: Annotations mixed with keywords");
3763 if ((flags
& TS_NO_NEW_ANNOTATIONS
)) {
3764 if (first_nonannotation
!= prev_len
) {
3765 log_warn(LD_DIR
, "parse error: Unexpected annotations.");
3770 for (i
=0; i
< smartlist_len(out
); ++i
) {
3771 tok
= smartlist_get(out
, i
);
3772 if (tok
->tp
>= MIN_ANNOTATION
&& tok
->tp
<= MAX_ANNOTATION
) {
3773 log_warn(LD_DIR
, "parse error: no annotations allowed.");
3777 first_nonannotation
= 0;
3779 for (i
= 0; table
[i
].t
; ++i
) {
3780 if (counts
[table
[i
].v
] < table
[i
].min_cnt
) {
3781 log_warn(LD_DIR
, "Parse error: missing %s element.", table
[i
].t
);
3784 if (counts
[table
[i
].v
] > table
[i
].max_cnt
) {
3785 log_warn(LD_DIR
, "Parse error: too many %s elements.", table
[i
].t
);
3788 if (table
[i
].pos
& AT_START
) {
3789 if (smartlist_len(out
) < 1 ||
3790 (tok
= smartlist_get(out
, first_nonannotation
))->tp
!= table
[i
].v
) {
3791 log_warn(LD_DIR
, "Parse error: first item is not %s.", table
[i
].t
);
3795 if (table
[i
].pos
& AT_END
) {
3796 if (smartlist_len(out
) < 1 ||
3797 (tok
= smartlist_get(out
, smartlist_len(out
)-1))->tp
!= table
[i
].v
) {
3798 log_warn(LD_DIR
, "Parse error: last item is not %s.", table
[i
].t
);
3806 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3807 * NULL if no such keyword is found.
3809 static directory_token_t
*
3810 find_opt_by_keyword(smartlist_t
*s
, directory_keyword keyword
)
3812 SMARTLIST_FOREACH(s
, directory_token_t
*, t
, if (t
->tp
== keyword
) return t
);
3816 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3817 * with an assert if no such keyword is found.
3819 static directory_token_t
*
3820 find_by_keyword_(smartlist_t
*s
, directory_keyword keyword
,
3821 const char *keyword_as_string
)
3823 directory_token_t
*tok
= find_opt_by_keyword(s
, keyword
);
3824 if (PREDICT_UNLIKELY(!tok
)) {
3825 log_err(LD_BUG
, "Missing %s [%d] in directory object that should have "
3826 "been validated. Internal error.", keyword_as_string
, (int)keyword
);
3832 /** If there are any directory_token_t entries in <b>s</b> whose keyword is
3833 * <b>k</b>, return a newly allocated smartlist_t containing all such entries,
3834 * in the same order in which they occur in <b>s</b>. Otherwise return
3836 static smartlist_t
*
3837 find_all_by_keyword(smartlist_t
*s
, directory_keyword k
)
3839 smartlist_t
*out
= NULL
;
3840 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
3843 out
= smartlist_new();
3844 smartlist_add(out
, t
);
3849 /** Return a newly allocated smartlist of all accept or reject tokens in
3852 static smartlist_t
*
3853 find_all_exitpolicy(smartlist_t
*s
)
3855 smartlist_t
*out
= smartlist_new();
3856 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
3857 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_ACCEPT6
||
3858 t
->tp
== K_REJECT
|| t
->tp
== K_REJECT6
)
3859 smartlist_add(out
,t
));
3863 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
3864 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
3865 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
3866 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
3868 * Return 0 on success and -1 on failure.
3871 router_get_hash_impl_helper(const char *s
, size_t s_len
,
3872 const char *start_str
,
3873 const char *end_str
, char end_c
,
3874 const char **start_out
, const char **end_out
)
3876 const char *start
, *end
;
3877 start
= tor_memstr(s
, s_len
, start_str
);
3879 log_warn(LD_DIR
,"couldn't find start of hashed material \"%s\"",start_str
);
3882 if (start
!= s
&& *(start
-1) != '\n') {
3884 "first occurrence of \"%s\" is not at the start of a line",
3888 end
= tor_memstr(start
+strlen(start_str
),
3889 s_len
- (start
-s
) - strlen(start_str
), end_str
);
3891 log_warn(LD_DIR
,"couldn't find end of hashed material \"%s\"",end_str
);
3894 end
= memchr(end
+strlen(end_str
), end_c
, s_len
- (end
-s
) - strlen(end_str
));
3896 log_warn(LD_DIR
,"couldn't find EOL");
3906 /** Compute the digest of the substring of <b>s</b> taken from the first
3907 * occurrence of <b>start_str</b> through the first instance of c after the
3908 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
3909 * result in <b>digest</b>; return 0 on success.
3911 * If no such substring exists, return -1.
3914 router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
3915 const char *start_str
,
3916 const char *end_str
, char end_c
,
3917 digest_algorithm_t alg
)
3919 const char *start
=NULL
, *end
=NULL
;
3920 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,
3924 if (alg
== DIGEST_SHA1
) {
3925 if (crypto_digest(digest
, start
, end
-start
)) {
3926 log_warn(LD_BUG
,"couldn't compute digest");
3930 if (crypto_digest256(digest
, start
, end
-start
, alg
)) {
3931 log_warn(LD_BUG
,"couldn't compute digest");
3939 /** As router_get_hash_impl, but compute all hashes. */
3941 router_get_hashes_impl(const char *s
, size_t s_len
, digests_t
*digests
,
3942 const char *start_str
,
3943 const char *end_str
, char end_c
)
3945 const char *start
=NULL
, *end
=NULL
;
3946 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,
3950 if (crypto_digest_all(digests
, start
, end
-start
)) {
3951 log_warn(LD_BUG
,"couldn't compute digests");
3958 /** Assuming that s starts with a microdesc, return the start of the
3959 * *NEXT* one. Return NULL on "not found." */
3961 find_start_of_next_microdesc(const char *s
, const char *eos
)
3963 int started_with_annotations
;
3964 s
= eat_whitespace_eos(s
, eos
);
3968 #define CHECK_LENGTH() STMT_BEGIN \
3973 #define NEXT_LINE() STMT_BEGIN \
3974 s = memchr(s, '\n', eos-s); \
3975 if (!s || s+1 >= eos) \
3982 started_with_annotations
= (*s
== '@');
3984 if (started_with_annotations
) {
3985 /* Start by advancing to the first non-annotation line. */
3991 /* Now we should be pointed at an onion-key line. If we are, then skip
3993 if (!strcmpstart(s
, "onion-key"))
3996 /* Okay, now we're pointed at the first line of the microdescriptor which is
3997 not an annotation or onion-key. The next line that _is_ an annotation or
3998 onion-key is the start of the next microdescriptor. */
3999 while (s
+32 < eos
) {
4000 if (*s
== '@' || !strcmpstart(s
, "onion-key"))
4010 /** Parse as many microdescriptors as are found from the string starting at
4011 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4012 * annotations we recognize and ignore ones we don't.
4014 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
4015 * descriptor in the body field of each microdesc_t.
4018 * parsed microdescriptors in a newly allocated smartlist_t. */
4020 microdescs_parse_from_string(const char *s
, const char *eos
,
4021 int allow_annotations
,
4022 saved_location_t where
)
4024 smartlist_t
*tokens
;
4025 smartlist_t
*result
;
4026 microdesc_t
*md
= NULL
;
4028 const char *start
= s
;
4029 const char *start_of_next_microdesc
;
4030 int flags
= allow_annotations
? TS_ANNOTATIONS_OK
: 0;
4031 const int copy_body
= (where
!= SAVED_IN_CACHE
);
4033 directory_token_t
*tok
;
4036 eos
= s
+ strlen(s
);
4038 s
= eat_whitespace_eos(s
, eos
);
4039 area
= memarea_new();
4040 result
= smartlist_new();
4041 tokens
= smartlist_new();
4044 start_of_next_microdesc
= find_start_of_next_microdesc(s
, eos
);
4045 if (!start_of_next_microdesc
)
4046 start_of_next_microdesc
= eos
;
4048 if (tokenize_string(area
, s
, start_of_next_microdesc
, tokens
,
4049 microdesc_token_table
, flags
)) {
4050 log_warn(LD_DIR
, "Unparseable microdescriptor");
4054 md
= tor_malloc_zero(sizeof(microdesc_t
));
4056 const char *cp
= tor_memstr(s
, start_of_next_microdesc
-s
,
4060 md
->bodylen
= start_of_next_microdesc
- cp
;
4061 md
->saved_location
= where
;
4063 md
->body
= tor_memdup_nulterm(cp
, md
->bodylen
);
4065 md
->body
= (char*)cp
;
4066 md
->off
= cp
- start
;
4069 if ((tok
= find_opt_by_keyword(tokens
, A_LAST_LISTED
))) {
4070 if (parse_iso_time(tok
->args
[0], &md
->last_listed
)) {
4071 log_warn(LD_DIR
, "Bad last-listed time in microdescriptor");
4076 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
4077 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
4079 "Relay's onion key had invalid exponent.");
4082 md
->onion_pkey
= tok
->key
;
4085 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
4086 curve25519_public_key_t k
;
4087 tor_assert(tok
->n_args
>= 1);
4088 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
4089 log_warn(LD_DIR
, "Bogus ntor-onion-key in microdesc");
4092 md
->onion_curve25519_pkey
=
4093 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
4097 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
4099 find_single_ipv6_orport(a_lines
, &md
->ipv6_addr
, &md
->ipv6_orport
);
4100 smartlist_free(a_lines
);
4104 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
))) {
4106 md
->family
= smartlist_new();
4107 for (i
=0;i
<tok
->n_args
;++i
) {
4108 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
4109 log_warn(LD_DIR
, "Illegal nickname %s in family line",
4110 escaped(tok
->args
[i
]));
4113 smartlist_add(md
->family
, tor_strdup(tok
->args
[i
]));
4117 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
4118 md
->exit_policy
= parse_short_policy(tok
->args
[0]);
4120 if ((tok
= find_opt_by_keyword(tokens
, K_P6
))) {
4121 md
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
4124 crypto_digest256(md
->digest
, md
->body
, md
->bodylen
, DIGEST_SHA256
);
4126 smartlist_add(result
, md
);
4133 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4134 memarea_clear(area
);
4135 smartlist_clear(tokens
);
4136 s
= start_of_next_microdesc
;
4139 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4140 memarea_drop_all(area
);
4141 smartlist_free(tokens
);
4146 /** Return true iff this Tor version can answer directory questions
4147 * about microdescriptors. */
4149 tor_version_supports_microdescriptors(const char *platform
)
4151 return tor_version_as_new_as(platform
, "0.2.3.1-alpha");
4154 /** Parse the Tor version of the platform string <b>platform</b>,
4155 * and compare it to the version in <b>cutoff</b>. Return 1 if
4156 * the router is at least as new as the cutoff, else return 0.
4159 tor_version_as_new_as(const char *platform
, const char *cutoff
)
4161 tor_version_t cutoff_version
, router_version
;
4162 char *s
, *s2
, *start
;
4165 tor_assert(platform
);
4167 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
4168 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
4171 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; be safe and say yes */
4174 start
= (char *)eat_whitespace(platform
+3);
4175 if (!*start
) return 0;
4176 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
4177 s2
= (char*)eat_whitespace(s
);
4178 if (!strcmpstart(s2
, "(r") || !strcmpstart(s2
, "(git-"))
4179 s
= (char*)find_whitespace(s2
);
4181 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
4183 strlcpy(tmp
, start
, s
-start
+1);
4185 if (tor_version_parse(tmp
, &router_version
)<0) {
4186 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
4187 return 1; /* be safe and say yes */
4190 /* Here's why we don't need to do any special handling for svn revisions:
4191 * - If neither has an svn revision, we're fine.
4192 * - If the router doesn't have an svn revision, we can't assume that it
4193 * is "at least" any svn revision, so we need to return 0.
4194 * - If the target version doesn't have an svn revision, any svn revision
4195 * (or none at all) is good enough, so return 1.
4196 * - If both target and router have an svn revision, we compare them.
4199 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
4202 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4203 * Return 0 on success, -1 on failure. */
4205 tor_version_parse(const char *s
, tor_version_t
*out
)
4208 const char *cp
=NULL
;
4210 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
4215 memset(out
, 0, sizeof(tor_version_t
));
4217 if (!strcasecmpstart(s
, "Tor "))
4221 out
->major
= (int)strtol(s
,&eos
,10);
4222 if (!eos
|| eos
==s
|| *eos
!= '.') return -1;
4226 out
->minor
= (int) strtol(cp
,&eos
,10);
4227 if (!eos
|| eos
==cp
|| *eos
!= '.') return -1;
4231 out
->micro
= (int) strtol(cp
,&eos
,10);
4232 if (!eos
|| eos
==cp
) return -1;
4234 out
->status
= VER_RELEASE
;
4235 out
->patchlevel
= 0;
4242 out
->status
= VER_RELEASE
;
4244 } else if (0==strncmp(cp
, "pre", 3)) {
4245 out
->status
= VER_PRE
;
4247 } else if (0==strncmp(cp
, "rc", 2)) {
4248 out
->status
= VER_RC
;
4254 /* Get patchlevel */
4255 out
->patchlevel
= (int) strtol(cp
,&eos
,10);
4256 if (!eos
|| eos
==cp
) return -1;
4259 /* Get status tag. */
4260 if (*cp
== '-' || *cp
== '.')
4262 eos
= (char*) find_whitespace(cp
);
4263 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
4264 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
4266 memcpy(out
->status_tag
, cp
, eos
-cp
);
4267 out
->status_tag
[eos
-cp
] = 0;
4269 cp
= eat_whitespace(eos
);
4271 if (!strcmpstart(cp
, "(r")) {
4273 out
->svn_revision
= (int) strtol(cp
,&eos
,10);
4274 } else if (!strcmpstart(cp
, "(git-")) {
4275 char *close_paren
= strchr(cp
, ')');
4277 char digest
[DIGEST_LEN
];
4281 if (close_paren
-cp
> HEX_DIGEST_LEN
)
4283 hexlen
= (int)(close_paren
-cp
);
4284 memwipe(digest
, 0, sizeof(digest
));
4285 if ( hexlen
== 0 || (hexlen
% 2) == 1)
4287 if (base16_decode(digest
, hexlen
/2, cp
, hexlen
))
4289 memcpy(out
->git_tag
, digest
, hexlen
/2);
4290 out
->git_tag_len
= hexlen
/2;
4296 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
4299 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
4304 if ((i
= a
->major
- b
->major
))
4306 else if ((i
= a
->minor
- b
->minor
))
4308 else if ((i
= a
->micro
- b
->micro
))
4310 else if ((i
= a
->status
- b
->status
))
4312 else if ((i
= a
->patchlevel
- b
->patchlevel
))
4314 else if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
4316 else if ((i
= a
->svn_revision
- b
->svn_revision
))
4318 else if ((i
= a
->git_tag_len
- b
->git_tag_len
))
4320 else if (a
->git_tag_len
)
4321 return fast_memcmp(a
->git_tag
, b
->git_tag
, a
->git_tag_len
);
4326 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
4329 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
4333 return ((a
->major
== b
->major
) &&
4334 (a
->minor
== b
->minor
) &&
4335 (a
->micro
== b
->micro
));
4338 /** Helper: Given pointers to two strings describing tor versions, return -1
4339 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
4340 * Used to sort a list of versions. */
4342 compare_tor_version_str_ptr_(const void **_a
, const void **_b
)
4344 const char *a
= *_a
, *b
= *_b
;
4346 tor_version_t va
, vb
;
4347 ca
= tor_version_parse(a
, &va
);
4348 cb
= tor_version_parse(b
, &vb
);
4349 /* If they both parse, compare them. */
4351 return tor_version_compare(&va
,&vb
);
4352 /* If one parses, it comes first. */
4357 /* If neither parses, compare strings. Also, the directory server admin
4358 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
4362 /** Sort a list of string-representations of versions in ascending order. */
4364 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
4366 smartlist_sort(versions
, compare_tor_version_str_ptr_
);
4368 if (remove_duplicates
)
4369 smartlist_uniq(versions
, compare_tor_version_str_ptr_
, tor_free_
);
4372 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
4373 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
4374 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
4375 * encrypted introduction points to the newly allocated
4376 * *<b>intro_points_encrypted_out</b>, their encrypted size to
4377 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
4378 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
4379 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
4380 * and -1 for failure.
4383 rend_parse_v2_service_descriptor(rend_service_descriptor_t
**parsed_out
,
4385 char **intro_points_encrypted_out
,
4386 size_t *intro_points_encrypted_size_out
,
4387 size_t *encoded_size_out
,
4388 const char **next_out
, const char *desc
)
4390 rend_service_descriptor_t
*result
=
4391 tor_malloc_zero(sizeof(rend_service_descriptor_t
));
4392 char desc_hash
[DIGEST_LEN
];
4394 smartlist_t
*tokens
= smartlist_new();
4395 directory_token_t
*tok
;
4396 char secret_id_part
[DIGEST_LEN
];
4397 int i
, version
, num_ok
=1;
4398 smartlist_t
*versions
;
4399 char public_key_hash
[DIGEST_LEN
];
4400 char test_desc_id
[DIGEST_LEN
];
4401 memarea_t
*area
= NULL
;
4403 /* Check if desc starts correctly. */
4404 if (strncmp(desc
, "rendezvous-service-descriptor ",
4405 strlen("rendezvous-service-descriptor "))) {
4406 log_info(LD_REND
, "Descriptor does not start correctly.");
4409 /* Compute descriptor hash for later validation. */
4410 if (router_get_hash_impl(desc
, strlen(desc
), desc_hash
,
4411 "rendezvous-service-descriptor ",
4412 "\nsignature", '\n', DIGEST_SHA1
) < 0) {
4413 log_warn(LD_REND
, "Couldn't compute descriptor hash.");
4416 /* Determine end of string. */
4417 eos
= strstr(desc
, "\nrendezvous-service-descriptor ");
4419 eos
= desc
+ strlen(desc
);
4423 if (eos
-desc
> REND_DESC_MAX_SIZE
) {
4424 /* XXX023 If we are parsing this descriptor as a server, this
4425 * should be a protocol warning. */
4426 log_warn(LD_REND
, "Descriptor length is %d which exceeds "
4427 "maximum rendezvous descriptor size of %d bytes.",
4428 (int)(eos
-desc
), REND_DESC_MAX_SIZE
);
4431 /* Tokenize descriptor. */
4432 area
= memarea_new();
4433 if (tokenize_string(area
, desc
, eos
, tokens
, desc_token_table
, 0)) {
4434 log_warn(LD_REND
, "Error tokenizing descriptor.");
4437 /* Set next to next descriptor, if available. */
4439 /* Set length of encoded descriptor. */
4440 *encoded_size_out
= eos
- desc
;
4441 /* Check min allowed length of token list. */
4442 if (smartlist_len(tokens
) < 7) {
4443 log_warn(LD_REND
, "Impossibly short descriptor.");
4446 /* Parse base32-encoded descriptor ID. */
4447 tok
= find_by_keyword(tokens
, R_RENDEZVOUS_SERVICE_DESCRIPTOR
);
4448 tor_assert(tok
== smartlist_get(tokens
, 0));
4449 tor_assert(tok
->n_args
== 1);
4450 if (strlen(tok
->args
[0]) != REND_DESC_ID_V2_LEN_BASE32
||
4451 strspn(tok
->args
[0], BASE32_CHARS
) != REND_DESC_ID_V2_LEN_BASE32
) {
4452 log_warn(LD_REND
, "Invalid descriptor ID: '%s'", tok
->args
[0]);
4455 if (base32_decode(desc_id_out
, DIGEST_LEN
,
4456 tok
->args
[0], REND_DESC_ID_V2_LEN_BASE32
) < 0) {
4457 log_warn(LD_REND
, "Descriptor ID contains illegal characters: %s",
4461 /* Parse descriptor version. */
4462 tok
= find_by_keyword(tokens
, R_VERSION
);
4463 tor_assert(tok
->n_args
== 1);
4465 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &num_ok
, NULL
);
4466 if (result
->version
!= 2 || !num_ok
) {
4467 /* If it's <2, it shouldn't be under this format. If the number
4468 * is greater than 2, we bumped it because we broke backward
4469 * compatibility. See how version numbers in our other formats
4471 log_warn(LD_REND
, "Unrecognized descriptor version: %s",
4472 escaped(tok
->args
[0]));
4475 /* Parse public key. */
4476 tok
= find_by_keyword(tokens
, R_PERMANENT_KEY
);
4477 result
->pk
= tok
->key
;
4478 tok
->key
= NULL
; /* Prevent free */
4479 /* Parse secret ID part. */
4480 tok
= find_by_keyword(tokens
, R_SECRET_ID_PART
);
4481 tor_assert(tok
->n_args
== 1);
4482 if (strlen(tok
->args
[0]) != REND_SECRET_ID_PART_LEN_BASE32
||
4483 strspn(tok
->args
[0], BASE32_CHARS
) != REND_SECRET_ID_PART_LEN_BASE32
) {
4484 log_warn(LD_REND
, "Invalid secret ID part: '%s'", tok
->args
[0]);
4487 if (base32_decode(secret_id_part
, DIGEST_LEN
, tok
->args
[0], 32) < 0) {
4488 log_warn(LD_REND
, "Secret ID part contains illegal characters: %s",
4492 /* Parse publication time -- up-to-date check is done when storing the
4494 tok
= find_by_keyword(tokens
, R_PUBLICATION_TIME
);
4495 tor_assert(tok
->n_args
== 1);
4496 if (parse_iso_time(tok
->args
[0], &result
->timestamp
) < 0) {
4497 log_warn(LD_REND
, "Invalid publication time: '%s'", tok
->args
[0]);
4500 /* Parse protocol versions. */
4501 tok
= find_by_keyword(tokens
, R_PROTOCOL_VERSIONS
);
4502 tor_assert(tok
->n_args
== 1);
4503 versions
= smartlist_new();
4504 smartlist_split_string(versions
, tok
->args
[0], ",",
4505 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
4506 for (i
= 0; i
< smartlist_len(versions
); i
++) {
4507 version
= (int) tor_parse_long(smartlist_get(versions
, i
),
4508 10, 0, INT_MAX
, &num_ok
, NULL
);
4509 if (!num_ok
) /* It's a string; let's ignore it. */
4511 if (version
>= REND_PROTOCOL_VERSION_BITMASK_WIDTH
)
4512 /* Avoid undefined left-shift behaviour. */
4514 result
->protocols
|= 1 << version
;
4516 SMARTLIST_FOREACH(versions
, char *, cp
, tor_free(cp
));
4517 smartlist_free(versions
);
4518 /* Parse encrypted introduction points. Don't verify. */
4519 tok
= find_opt_by_keyword(tokens
, R_INTRODUCTION_POINTS
);
4521 if (strcmp(tok
->object_type
, "MESSAGE")) {
4522 log_warn(LD_DIR
, "Bad object type: introduction points should be of "
4526 *intro_points_encrypted_out
= tor_memdup(tok
->object_body
,
4528 *intro_points_encrypted_size_out
= tok
->object_size
;
4530 *intro_points_encrypted_out
= NULL
;
4531 *intro_points_encrypted_size_out
= 0;
4533 /* Parse and verify signature. */
4534 tok
= find_by_keyword(tokens
, R_SIGNATURE
);
4535 note_crypto_pk_op(VERIFY_RTR
);
4536 if (check_signature_token(desc_hash
, DIGEST_LEN
, tok
, result
->pk
, 0,
4537 "v2 rendezvous service descriptor") < 0)
4539 /* Verify that descriptor ID belongs to public key and secret ID part. */
4540 crypto_pk_get_digest(result
->pk
, public_key_hash
);
4541 rend_get_descriptor_id_bytes(test_desc_id
, public_key_hash
,
4543 if (tor_memneq(desc_id_out
, test_desc_id
, DIGEST_LEN
)) {
4544 log_warn(LD_REND
, "Parsed descriptor ID does not match "
4545 "computed descriptor ID.");
4550 rend_service_descriptor_free(result
);
4554 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4555 smartlist_free(tokens
);
4558 memarea_drop_all(area
);
4559 *parsed_out
= result
;
4565 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
4566 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
4567 * write the result to a newly allocated string that is pointed to by
4568 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
4569 * Return 0 if decryption was successful and -1 otherwise. */
4571 rend_decrypt_introduction_points(char **ipos_decrypted
,
4572 size_t *ipos_decrypted_size
,
4573 const char *descriptor_cookie
,
4574 const char *ipos_encrypted
,
4575 size_t ipos_encrypted_size
)
4577 tor_assert(ipos_encrypted
);
4578 tor_assert(descriptor_cookie
);
4579 if (ipos_encrypted_size
< 2) {
4580 log_warn(LD_REND
, "Size of encrypted introduction points is too "
4584 if (ipos_encrypted
[0] == (int)REND_BASIC_AUTH
) {
4585 char iv
[CIPHER_IV_LEN
], client_id
[REND_BASIC_AUTH_CLIENT_ID_LEN
],
4586 session_key
[CIPHER_KEY_LEN
], *dec
;
4587 int declen
, client_blocks
;
4588 size_t pos
= 0, len
, client_entries_len
;
4589 crypto_digest_t
*digest
;
4590 crypto_cipher_t
*cipher
;
4591 client_blocks
= (int) ipos_encrypted
[1];
4592 client_entries_len
= client_blocks
* REND_BASIC_AUTH_CLIENT_MULTIPLE
*
4593 REND_BASIC_AUTH_CLIENT_ENTRY_LEN
;
4594 if (ipos_encrypted_size
< 2 + client_entries_len
+ CIPHER_IV_LEN
+ 1) {
4595 log_warn(LD_REND
, "Size of encrypted introduction points is too "
4599 memcpy(iv
, ipos_encrypted
+ 2 + client_entries_len
, CIPHER_IV_LEN
);
4600 digest
= crypto_digest_new();
4601 crypto_digest_add_bytes(digest
, descriptor_cookie
, REND_DESC_COOKIE_LEN
);
4602 crypto_digest_add_bytes(digest
, iv
, CIPHER_IV_LEN
);
4603 crypto_digest_get_digest(digest
, client_id
,
4604 REND_BASIC_AUTH_CLIENT_ID_LEN
);
4605 crypto_digest_free(digest
);
4606 for (pos
= 2; pos
< 2 + client_entries_len
;
4607 pos
+= REND_BASIC_AUTH_CLIENT_ENTRY_LEN
) {
4608 if (tor_memeq(ipos_encrypted
+ pos
, client_id
,
4609 REND_BASIC_AUTH_CLIENT_ID_LEN
)) {
4610 /* Attempt to decrypt introduction points. */
4611 cipher
= crypto_cipher_new(descriptor_cookie
);
4612 if (crypto_cipher_decrypt(cipher
, session_key
, ipos_encrypted
4613 + pos
+ REND_BASIC_AUTH_CLIENT_ID_LEN
,
4614 CIPHER_KEY_LEN
) < 0) {
4615 log_warn(LD_REND
, "Could not decrypt session key for client.");
4616 crypto_cipher_free(cipher
);
4619 crypto_cipher_free(cipher
);
4621 len
= ipos_encrypted_size
- 2 - client_entries_len
- CIPHER_IV_LEN
;
4622 dec
= tor_malloc(len
);
4623 declen
= crypto_cipher_decrypt_with_iv(session_key
, dec
, len
,
4624 ipos_encrypted
+ 2 + client_entries_len
,
4625 ipos_encrypted_size
- 2 - client_entries_len
);
4628 log_warn(LD_REND
, "Could not decrypt introduction point string.");
4632 if (fast_memcmpstart(dec
, declen
, "introduction-point ")) {
4633 log_warn(LD_REND
, "Decrypted introduction points don't "
4634 "look like we could parse them.");
4638 *ipos_decrypted
= dec
;
4639 *ipos_decrypted_size
= declen
;
4643 log_warn(LD_REND
, "Could not decrypt introduction points. Please "
4644 "check your authorization for this service!");
4646 } else if (ipos_encrypted
[0] == (int)REND_STEALTH_AUTH
) {
4649 if (ipos_encrypted_size
< CIPHER_IV_LEN
+ 2) {
4650 log_warn(LD_REND
, "Size of encrypted introduction points is too "
4654 dec
= tor_malloc_zero(ipos_encrypted_size
- CIPHER_IV_LEN
- 1);
4656 declen
= crypto_cipher_decrypt_with_iv(descriptor_cookie
, dec
,
4657 ipos_encrypted_size
-
4660 ipos_encrypted_size
- 1);
4663 log_warn(LD_REND
, "Decrypting introduction points failed!");
4667 *ipos_decrypted
= dec
;
4668 *ipos_decrypted_size
= declen
;
4671 log_warn(LD_REND
, "Unknown authorization type number: %d",
4677 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
4678 * length <b>intro_points_encoded_size</b> and write the result to the
4679 * descriptor in <b>parsed</b>; return the number of successfully parsed
4680 * introduction points or -1 in case of a failure. */
4682 rend_parse_introduction_points(rend_service_descriptor_t
*parsed
,
4683 const char *intro_points_encoded
,
4684 size_t intro_points_encoded_size
)
4686 const char *current_ipo
, *end_of_intro_points
;
4687 smartlist_t
*tokens
;
4688 directory_token_t
*tok
;
4689 rend_intro_point_t
*intro
;
4690 extend_info_t
*info
;
4691 int result
, num_ok
=1;
4692 memarea_t
*area
= NULL
;
4694 /** Function may only be invoked once. */
4695 tor_assert(!parsed
->intro_nodes
);
4696 tor_assert(intro_points_encoded
);
4697 tor_assert(intro_points_encoded_size
> 0);
4698 /* Consider one intro point after the other. */
4699 current_ipo
= intro_points_encoded
;
4700 end_of_intro_points
= intro_points_encoded
+ intro_points_encoded_size
;
4701 tokens
= smartlist_new();
4702 parsed
->intro_nodes
= smartlist_new();
4703 area
= memarea_new();
4705 while (!fast_memcmpstart(current_ipo
, end_of_intro_points
-current_ipo
,
4706 "introduction-point ")) {
4707 /* Determine end of string. */
4708 const char *eos
= tor_memstr(current_ipo
, end_of_intro_points
-current_ipo
,
4709 "\nintroduction-point ");
4711 eos
= end_of_intro_points
;
4714 tor_assert(eos
<= intro_points_encoded
+intro_points_encoded_size
);
4715 /* Free tokens and clear token list. */
4716 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4717 smartlist_clear(tokens
);
4718 memarea_clear(area
);
4719 /* Tokenize string. */
4720 if (tokenize_string(area
, current_ipo
, eos
, tokens
, ipo_token_table
, 0)) {
4721 log_warn(LD_REND
, "Error tokenizing introduction point");
4724 /* Advance to next introduction point, if available. */
4726 /* Check minimum allowed length of introduction point. */
4727 if (smartlist_len(tokens
) < 5) {
4728 log_warn(LD_REND
, "Impossibly short introduction point.");
4731 /* Allocate new intro point and extend info. */
4732 intro
= tor_malloc_zero(sizeof(rend_intro_point_t
));
4733 info
= intro
->extend_info
= tor_malloc_zero(sizeof(extend_info_t
));
4734 /* Parse identifier. */
4735 tok
= find_by_keyword(tokens
, R_IPO_IDENTIFIER
);
4736 if (base32_decode(info
->identity_digest
, DIGEST_LEN
,
4737 tok
->args
[0], REND_INTRO_POINT_ID_LEN_BASE32
) < 0) {
4738 log_warn(LD_REND
, "Identity digest contains illegal characters: %s",
4740 rend_intro_point_free(intro
);
4743 /* Write identifier to nickname. */
4744 info
->nickname
[0] = '$';
4745 base16_encode(info
->nickname
+ 1, sizeof(info
->nickname
) - 1,
4746 info
->identity_digest
, DIGEST_LEN
);
4747 /* Parse IP address. */
4748 tok
= find_by_keyword(tokens
, R_IPO_IP_ADDRESS
);
4749 if (tor_addr_parse(&info
->addr
, tok
->args
[0])<0) {
4750 log_warn(LD_REND
, "Could not parse introduction point address.");
4751 rend_intro_point_free(intro
);
4754 if (tor_addr_family(&info
->addr
) != AF_INET
) {
4755 log_warn(LD_REND
, "Introduction point address was not ipv4.");
4756 rend_intro_point_free(intro
);
4760 /* Parse onion port. */
4761 tok
= find_by_keyword(tokens
, R_IPO_ONION_PORT
);
4762 info
->port
= (uint16_t) tor_parse_long(tok
->args
[0],10,1,65535,
4764 if (!info
->port
|| !num_ok
) {
4765 log_warn(LD_REND
, "Introduction point onion port %s is invalid",
4766 escaped(tok
->args
[0]));
4767 rend_intro_point_free(intro
);
4770 /* Parse onion key. */
4771 tok
= find_by_keyword(tokens
, R_IPO_ONION_KEY
);
4772 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
4774 "Introduction point's onion key had invalid exponent.");
4775 rend_intro_point_free(intro
);
4778 info
->onion_key
= tok
->key
;
4779 tok
->key
= NULL
; /* Prevent free */
4780 /* Parse service key. */
4781 tok
= find_by_keyword(tokens
, R_IPO_SERVICE_KEY
);
4782 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
4784 "Introduction point key had invalid exponent.");
4785 rend_intro_point_free(intro
);
4788 intro
->intro_key
= tok
->key
;
4789 tok
->key
= NULL
; /* Prevent free */
4790 /* Add extend info to list of introduction points. */
4791 smartlist_add(parsed
->intro_nodes
, intro
);
4793 result
= smartlist_len(parsed
->intro_nodes
);
4800 /* Free tokens and clear token list. */
4801 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4802 smartlist_free(tokens
);
4804 memarea_drop_all(area
);
4809 /** Parse the content of a client_key file in <b>ckstr</b> and add
4810 * rend_authorized_client_t's for each parsed client to
4811 * <b>parsed_clients</b>. Return the number of parsed clients as result
4812 * or -1 for failure. */
4814 rend_parse_client_keys(strmap_t
*parsed_clients
, const char *ckstr
)
4817 smartlist_t
*tokens
;
4818 directory_token_t
*tok
;
4819 const char *current_entry
= NULL
;
4820 memarea_t
*area
= NULL
;
4821 if (!ckstr
|| strlen(ckstr
) == 0)
4823 tokens
= smartlist_new();
4824 /* Begin parsing with first entry, skipping comments or whitespace at the
4826 area
= memarea_new();
4827 current_entry
= eat_whitespace(ckstr
);
4828 while (!strcmpstart(current_entry
, "client-name ")) {
4829 rend_authorized_client_t
*parsed_entry
;
4831 char descriptor_cookie_tmp
[REND_DESC_COOKIE_LEN
+2];
4832 /* Determine end of string. */
4833 const char *eos
= strstr(current_entry
, "\nclient-name ");
4835 eos
= current_entry
+ strlen(current_entry
);
4838 /* Free tokens and clear token list. */
4839 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4840 smartlist_clear(tokens
);
4841 memarea_clear(area
);
4842 /* Tokenize string. */
4843 if (tokenize_string(area
, current_entry
, eos
, tokens
,
4844 client_keys_token_table
, 0)) {
4845 log_warn(LD_REND
, "Error tokenizing client keys file.");
4848 /* Advance to next entry, if available. */
4849 current_entry
= eos
;
4850 /* Check minimum allowed length of token list. */
4851 if (smartlist_len(tokens
) < 2) {
4852 log_warn(LD_REND
, "Impossibly short client key entry.");
4855 /* Parse client name. */
4856 tok
= find_by_keyword(tokens
, C_CLIENT_NAME
);
4857 tor_assert(tok
== smartlist_get(tokens
, 0));
4858 tor_assert(tok
->n_args
== 1);
4860 len
= strlen(tok
->args
[0]);
4861 if (len
< 1 || len
> 19 ||
4862 strspn(tok
->args
[0], REND_LEGAL_CLIENTNAME_CHARACTERS
) != len
) {
4863 log_warn(LD_CONFIG
, "Illegal client name: %s. (Length must be "
4864 "between 1 and 19, and valid characters are "
4865 "[A-Za-z0-9+-_].)", tok
->args
[0]);
4868 /* Check if client name is duplicate. */
4869 if (strmap_get(parsed_clients
, tok
->args
[0])) {
4870 log_warn(LD_CONFIG
, "HiddenServiceAuthorizeClient contains a "
4871 "duplicate client name: '%s'. Ignoring.", tok
->args
[0]);
4874 parsed_entry
= tor_malloc_zero(sizeof(rend_authorized_client_t
));
4875 parsed_entry
->client_name
= tor_strdup(tok
->args
[0]);
4876 strmap_set(parsed_clients
, parsed_entry
->client_name
, parsed_entry
);
4877 /* Parse client key. */
4878 tok
= find_opt_by_keyword(tokens
, C_CLIENT_KEY
);
4880 parsed_entry
->client_key
= tok
->key
;
4881 tok
->key
= NULL
; /* Prevent free */
4884 /* Parse descriptor cookie. */
4885 tok
= find_by_keyword(tokens
, C_DESCRIPTOR_COOKIE
);
4886 tor_assert(tok
->n_args
== 1);
4887 if (strlen(tok
->args
[0]) != REND_DESC_COOKIE_LEN_BASE64
+ 2) {
4888 log_warn(LD_REND
, "Descriptor cookie has illegal length: %s",
4889 escaped(tok
->args
[0]));
4892 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
4893 * because a base64 encoding of length 24 does not fit into 16 bytes in all
4895 if (base64_decode(descriptor_cookie_tmp
, sizeof(descriptor_cookie_tmp
),
4896 tok
->args
[0], strlen(tok
->args
[0]))
4897 != REND_DESC_COOKIE_LEN
) {
4898 log_warn(LD_REND
, "Descriptor cookie contains illegal characters: "
4899 "%s", escaped(tok
->args
[0]));
4902 memcpy(parsed_entry
->descriptor_cookie
, descriptor_cookie_tmp
,
4903 REND_DESC_COOKIE_LEN
);
4905 result
= strmap_size(parsed_clients
);
4910 /* Free tokens and clear token list. */
4911 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4912 smartlist_free(tokens
);
4914 memarea_drop_all(area
);