Merge remote-tracking branch 'public/bug23985_029' into maint-0.2.9
[tor.git] / src / or / routerparse.c
blob521e237be2966778114859a7a7b4e5a92f6b1dd4
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2016, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file routerparse.c
9 * \brief Code to parse and validate router descriptors, consenus directories,
10 * and similar objects.
12 * The objects parsed by this module use a common text-based metaformat,
13 * documented in dir-spec.txt in torspec.git. This module is itself divided
14 * into two major kinds of function: code to handle the metaformat, and code
15 * to convert from particular instances of the metaformat into the
16 * objects that Tor uses.
18 * The generic parsing code works by calling a table-based tokenizer on the
19 * input string. Each token corresponds to a single line with a token, plus
20 * optional arguments on that line, plus an optional base-64 encoded object
21 * after that line. Each token has a definition in a table of token_rule_t
22 * entries that describes how many arguments it can take, whether it takes an
23 * object, how many times it may appear, whether it must appear first, and so
24 * on.
26 * The tokenizer function tokenize_string() converts its string input into a
27 * smartlist full of instances of directory_token_t, according to a provided
28 * table of token_rule_t.
30 * The generic parts of this module additionally include functions for
31 * finding the start and end of signed information inside a signed object, and
32 * computing the digest that will be signed.
34 * There are also functions for saving objects to disk that have caused
35 * parsing to fail.
37 * The specific parts of this module describe conversions between
38 * particular lists of directory_token_t and particular objects. The
39 * kinds of objects that can be parsed here are:
40 * <ul>
41 * <li>router descriptors (managed from routerlist.c)
42 * <li>extra-info documents (managed from routerlist.c)
43 * <li>microdescriptors (managed from microdesc.c)
44 * <li>vote and consensus networkstatus documents, and the routerstatus_t
45 * objects that they comprise (managed from networkstatus.c)
46 * <li>detached-signature objects used by authorities for gathering
47 * signatures on the networkstatus consensus (managed from dirvote.c)
48 * <li>authority key certificates (managed from routerlist.c)
49 * <li>hidden service descriptors (managed from rendcommon.c and rendcache.c)
50 * </ul>
52 * For no terribly good reason, the functions to <i>generate</i> signatures on
53 * the above directory objects are also in this module.
54 **/
56 #define ROUTERPARSE_PRIVATE
58 #include "or.h"
59 #include "config.h"
60 #include "circuitstats.h"
61 #include "dirserv.h"
62 #include "dirvote.h"
63 #include "policies.h"
64 #include "protover.h"
65 #include "rendcommon.h"
66 #include "router.h"
67 #include "routerlist.h"
68 #include "memarea.h"
69 #include "microdesc.h"
70 #include "networkstatus.h"
71 #include "rephist.h"
72 #include "routerkeys.h"
73 #include "routerparse.h"
74 #include "entrynodes.h"
75 #include "torcert.h"
76 #include "sandbox.h"
77 #include "shared_random.h"
79 #undef log
80 #include <math.h>
82 /****************************************************************************/
84 /** Enumeration of possible token types. The ones starting with K_ correspond
85 * to directory 'keywords'. A_ is for an annotation, R or C is related to
86 * hidden services, ERR_ is an error in the tokenizing process, EOF_ is an
87 * end-of-file marker, and NIL_ is used to encode not-a-token.
89 typedef enum {
90 K_ACCEPT = 0,
91 K_ACCEPT6,
92 K_DIRECTORY_SIGNATURE,
93 K_RECOMMENDED_SOFTWARE,
94 K_REJECT,
95 K_REJECT6,
96 K_ROUTER,
97 K_SIGNED_DIRECTORY,
98 K_SIGNING_KEY,
99 K_ONION_KEY,
100 K_ONION_KEY_NTOR,
101 K_ROUTER_SIGNATURE,
102 K_PUBLISHED,
103 K_RUNNING_ROUTERS,
104 K_ROUTER_STATUS,
105 K_PLATFORM,
106 K_PROTO,
107 K_OPT,
108 K_BANDWIDTH,
109 K_CONTACT,
110 K_NETWORK_STATUS,
111 K_UPTIME,
112 K_DIR_SIGNING_KEY,
113 K_FAMILY,
114 K_FINGERPRINT,
115 K_HIBERNATING,
116 K_READ_HISTORY,
117 K_WRITE_HISTORY,
118 K_NETWORK_STATUS_VERSION,
119 K_DIR_SOURCE,
120 K_DIR_OPTIONS,
121 K_CLIENT_VERSIONS,
122 K_SERVER_VERSIONS,
123 K_RECOMMENDED_CLIENT_PROTOCOLS,
124 K_RECOMMENDED_RELAY_PROTOCOLS,
125 K_REQUIRED_CLIENT_PROTOCOLS,
126 K_REQUIRED_RELAY_PROTOCOLS,
127 K_OR_ADDRESS,
128 K_ID,
129 K_P,
130 K_P6,
131 K_R,
132 K_A,
133 K_S,
134 K_V,
135 K_W,
136 K_M,
137 K_EXTRA_INFO,
138 K_EXTRA_INFO_DIGEST,
139 K_CACHES_EXTRA_INFO,
140 K_HIDDEN_SERVICE_DIR,
141 K_ALLOW_SINGLE_HOP_EXITS,
142 K_IPV6_POLICY,
143 K_ROUTER_SIG_ED25519,
144 K_IDENTITY_ED25519,
145 K_MASTER_KEY_ED25519,
146 K_ONION_KEY_CROSSCERT,
147 K_NTOR_ONION_KEY_CROSSCERT,
149 K_DIRREQ_END,
150 K_DIRREQ_V2_IPS,
151 K_DIRREQ_V3_IPS,
152 K_DIRREQ_V2_REQS,
153 K_DIRREQ_V3_REQS,
154 K_DIRREQ_V2_SHARE,
155 K_DIRREQ_V3_SHARE,
156 K_DIRREQ_V2_RESP,
157 K_DIRREQ_V3_RESP,
158 K_DIRREQ_V2_DIR,
159 K_DIRREQ_V3_DIR,
160 K_DIRREQ_V2_TUN,
161 K_DIRREQ_V3_TUN,
162 K_ENTRY_END,
163 K_ENTRY_IPS,
164 K_CELL_END,
165 K_CELL_PROCESSED,
166 K_CELL_QUEUED,
167 K_CELL_TIME,
168 K_CELL_CIRCS,
169 K_EXIT_END,
170 K_EXIT_WRITTEN,
171 K_EXIT_READ,
172 K_EXIT_OPENED,
174 K_DIR_KEY_CERTIFICATE_VERSION,
175 K_DIR_IDENTITY_KEY,
176 K_DIR_KEY_PUBLISHED,
177 K_DIR_KEY_EXPIRES,
178 K_DIR_KEY_CERTIFICATION,
179 K_DIR_KEY_CROSSCERT,
180 K_DIR_ADDRESS,
181 K_DIR_TUNNELLED,
183 K_VOTE_STATUS,
184 K_VALID_AFTER,
185 K_FRESH_UNTIL,
186 K_VALID_UNTIL,
187 K_VOTING_DELAY,
189 K_KNOWN_FLAGS,
190 K_PARAMS,
191 K_BW_WEIGHTS,
192 K_VOTE_DIGEST,
193 K_CONSENSUS_DIGEST,
194 K_ADDITIONAL_DIGEST,
195 K_ADDITIONAL_SIGNATURE,
196 K_CONSENSUS_METHODS,
197 K_CONSENSUS_METHOD,
198 K_LEGACY_DIR_KEY,
199 K_DIRECTORY_FOOTER,
200 K_SIGNING_CERT_ED,
201 K_SR_FLAG,
202 K_COMMIT,
203 K_PREVIOUS_SRV,
204 K_CURRENT_SRV,
205 K_PACKAGE,
207 A_PURPOSE,
208 A_LAST_LISTED,
209 A_UNKNOWN_,
211 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
212 R_VERSION,
213 R_PERMANENT_KEY,
214 R_SECRET_ID_PART,
215 R_PUBLICATION_TIME,
216 R_PROTOCOL_VERSIONS,
217 R_INTRODUCTION_POINTS,
218 R_SIGNATURE,
220 R_IPO_IDENTIFIER,
221 R_IPO_IP_ADDRESS,
222 R_IPO_ONION_PORT,
223 R_IPO_ONION_KEY,
224 R_IPO_SERVICE_KEY,
226 C_CLIENT_NAME,
227 C_DESCRIPTOR_COOKIE,
228 C_CLIENT_KEY,
230 ERR_,
231 EOF_,
232 NIL_
233 } directory_keyword;
235 #define MIN_ANNOTATION A_PURPOSE
236 #define MAX_ANNOTATION A_UNKNOWN_
238 /** Structure to hold a single directory token.
240 * We parse a directory by breaking it into "tokens", each consisting
241 * of a keyword, a line full of arguments, and a binary object. The
242 * arguments and object are both optional, depending on the keyword
243 * type.
245 * This structure is only allocated in memareas; do not allocate it on
246 * the heap, or token_clear() won't work.
248 typedef struct directory_token_t {
249 directory_keyword tp; /**< Type of the token. */
250 int n_args:30; /**< Number of elements in args */
251 char **args; /**< Array of arguments from keyword line. */
253 char *object_type; /**< -----BEGIN [object_type]-----*/
254 size_t object_size; /**< Bytes in object_body */
255 char *object_body; /**< Contents of object, base64-decoded. */
257 crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
259 char *error; /**< For ERR_ tokens only. */
260 } directory_token_t;
262 /* ********************************************************************** */
264 /** We use a table of rules to decide how to parse each token type. */
266 /** Rules for whether the keyword needs an object. */
267 typedef enum {
268 NO_OBJ, /**< No object, ever. */
269 NEED_OBJ, /**< Object is required. */
270 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
271 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
272 NEED_KEY, /**< Object is required, and must be a public key. */
273 OBJ_OK, /**< Object is optional. */
274 } obj_syntax;
276 #define AT_START 1
277 #define AT_END 2
279 /** Determines the parsing rules for a single token type. */
280 typedef struct token_rule_t {
281 /** The string value of the keyword identifying the type of item. */
282 const char *t;
283 /** The corresponding directory_keyword enum. */
284 directory_keyword v;
285 /** Minimum number of arguments for this item */
286 int min_args;
287 /** Maximum number of arguments for this item */
288 int max_args;
289 /** If true, we concatenate all arguments for this item into a single
290 * string. */
291 int concat_args;
292 /** Requirements on object syntax for this item. */
293 obj_syntax os;
294 /** Lowest number of times this item may appear in a document. */
295 int min_cnt;
296 /** Highest number of times this item may appear in a document. */
297 int max_cnt;
298 /** One or more of AT_START/AT_END to limit where the item may appear in a
299 * document. */
300 int pos;
301 /** True iff this token is an annotation. */
302 int is_annotation;
303 } token_rule_t;
306 * @name macros for defining token rules
308 * Helper macros to define token tables. 's' is a string, 't' is a
309 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
310 * object syntax.
312 /**@{*/
314 /** Appears to indicate the end of a table. */
315 #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
316 /** An item with no restrictions: used for obsolete document types */
317 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
318 /** An item with no restrictions on multiplicity or location. */
319 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
320 /** An item that must appear exactly once */
321 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
322 /** An item that must appear exactly once, at the start of the document */
323 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
324 /** An item that must appear exactly once, at the end of the document */
325 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
326 /** An item that must appear one or more times */
327 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
328 /** An item that must appear no more than once */
329 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
330 /** An annotation that must appear no more than once */
331 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
333 /** Argument multiplicity: any number of arguments. */
334 #define ARGS 0,INT_MAX,0
335 /** Argument multiplicity: no arguments. */
336 #define NO_ARGS 0,0,0
337 /** Argument multiplicity: concatenate all arguments. */
338 #define CONCAT_ARGS 1,1,1
339 /** Argument multiplicity: at least <b>n</b> arguments. */
340 #define GE(n) n,INT_MAX,0
341 /** Argument multiplicity: exactly <b>n</b> arguments. */
342 #define EQ(n) n,n,0
343 /**@}*/
345 /** List of tokens recognized in router descriptors */
346 static token_rule_t routerdesc_token_table[] = {
347 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
348 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
349 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
350 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
351 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
352 T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
353 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
354 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
355 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
356 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
357 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
358 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
359 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
360 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
361 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
362 T01("proto", K_PROTO, CONCAT_ARGS, NO_OBJ ),
363 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
364 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
365 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
366 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
367 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
368 T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
369 T01("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
370 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
371 T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
372 T01("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
373 EQ(1), NEED_OBJ ),
375 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
377 T01("family", K_FAMILY, ARGS, NO_OBJ ),
378 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
379 T0N("or-address", K_OR_ADDRESS, GE(1), NO_OBJ ),
381 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
382 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
383 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
384 T01("tunnelled-dir-server",K_DIR_TUNNELLED, NO_ARGS, NO_OBJ ),
386 END_OF_TABLE
389 /** List of tokens recognized in extra-info documents. */
390 static token_rule_t extrainfo_token_table[] = {
391 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
392 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
393 T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
394 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
395 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
396 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
397 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
398 T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ),
399 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ),
400 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ),
401 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ),
402 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ),
403 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ),
404 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ),
405 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ),
406 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ),
407 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ),
408 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ),
409 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ),
410 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ),
411 T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ),
412 T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ),
413 T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ),
414 T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ),
415 T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ),
416 T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ),
417 T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ),
418 T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ),
419 T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ),
420 T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ),
421 T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ),
423 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
425 END_OF_TABLE
428 /** List of tokens recognized in the body part of v3 networkstatus
429 * documents. */
430 static token_rule_t rtrstatus_token_table[] = {
431 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
432 T1( "r", K_R, GE(7), NO_OBJ ),
433 T0N("a", K_A, GE(1), NO_OBJ ),
434 T1( "s", K_S, ARGS, NO_OBJ ),
435 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
436 T01("w", K_W, ARGS, NO_OBJ ),
437 T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
438 T0N("id", K_ID, GE(2), NO_OBJ ),
439 T01("pr", K_PROTO, CONCAT_ARGS, NO_OBJ ),
440 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
441 END_OF_TABLE
444 /** List of tokens common to V3 authority certificates and V3 consensuses. */
445 #define CERTIFICATE_MEMBERS \
446 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
447 GE(1), NO_OBJ ), \
448 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
449 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
450 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
451 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
452 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
453 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
454 NO_ARGS, NEED_OBJ), \
455 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
457 /** List of tokens recognized in V3 authority certificates. */
458 static token_rule_t dir_key_certificate_table[] = {
459 CERTIFICATE_MEMBERS
460 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
461 END_OF_TABLE
464 /** List of tokens recognized in rendezvous service descriptors */
465 static token_rule_t desc_token_table[] = {
466 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
467 EQ(1), NO_OBJ),
468 T1("version", R_VERSION, EQ(1), NO_OBJ),
469 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
470 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
471 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
472 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
473 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
474 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
475 END_OF_TABLE
478 /** List of tokens recognized in the (encrypted) list of introduction points of
479 * rendezvous service descriptors */
480 static token_rule_t ipo_token_table[] = {
481 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
482 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
483 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
484 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
485 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
486 END_OF_TABLE
489 /** List of tokens recognized in the (possibly encrypted) list of introduction
490 * points of rendezvous service descriptors */
491 static token_rule_t client_keys_token_table[] = {
492 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
493 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
494 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
495 END_OF_TABLE
498 /** List of tokens recognized in V3 networkstatus votes. */
499 static token_rule_t networkstatus_token_table[] = {
500 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
501 GE(1), NO_OBJ ),
502 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
503 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
504 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
505 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
506 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
507 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
508 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
509 T01("params", K_PARAMS, ARGS, NO_OBJ ),
510 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
511 T01("signing-ed25519", K_SIGNING_CERT_ED, NO_ARGS , NEED_OBJ ),
512 T01("shared-rand-participate",K_SR_FLAG, NO_ARGS, NO_OBJ ),
513 T0N("shared-rand-commit", K_COMMIT, GE(3), NO_OBJ ),
514 T01("shared-rand-previous-value", K_PREVIOUS_SRV,EQ(2), NO_OBJ ),
515 T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
516 T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ),
517 T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
518 CONCAT_ARGS, NO_OBJ ),
519 T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
520 CONCAT_ARGS, NO_OBJ ),
521 T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
522 CONCAT_ARGS, NO_OBJ ),
523 T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
524 CONCAT_ARGS, NO_OBJ ),
526 CERTIFICATE_MEMBERS
528 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
529 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
530 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
531 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
532 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
533 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
534 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
535 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
537 END_OF_TABLE
540 /** List of tokens recognized in V3 networkstatus consensuses. */
541 static token_rule_t networkstatus_consensus_token_table[] = {
542 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
543 GE(1), NO_OBJ ),
544 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
545 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
546 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
547 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
548 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
550 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
552 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
553 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
554 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
556 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
558 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
559 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
560 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
561 T01("params", K_PARAMS, ARGS, NO_OBJ ),
563 T01("shared-rand-previous-value", K_PREVIOUS_SRV, EQ(2), NO_OBJ ),
564 T01("shared-rand-current-value", K_CURRENT_SRV, EQ(2), NO_OBJ ),
566 T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS,
567 CONCAT_ARGS, NO_OBJ ),
568 T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS,
569 CONCAT_ARGS, NO_OBJ ),
570 T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS,
571 CONCAT_ARGS, NO_OBJ ),
572 T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS,
573 CONCAT_ARGS, NO_OBJ ),
575 END_OF_TABLE
578 /** List of tokens recognized in the footer of v1 directory footers. */
579 static token_rule_t networkstatus_vote_footer_token_table[] = {
580 T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
581 T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
582 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
583 END_OF_TABLE
586 /** List of tokens recognized in detached networkstatus signature documents. */
587 static token_rule_t networkstatus_detached_signature_token_table[] = {
588 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
589 T("additional-digest", K_ADDITIONAL_DIGEST,GE(3), NO_OBJ ),
590 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
591 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
592 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
593 T("additional-signature", K_ADDITIONAL_SIGNATURE, GE(4), NEED_OBJ ),
594 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
595 END_OF_TABLE
598 /** List of tokens recognized in microdescriptors */
599 static token_rule_t microdesc_token_table[] = {
600 T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
601 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
602 T0N("id", K_ID, GE(2), NO_OBJ ),
603 T0N("a", K_A, GE(1), NO_OBJ ),
604 T01("family", K_FAMILY, ARGS, NO_OBJ ),
605 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
606 T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ),
607 A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
608 END_OF_TABLE
611 #undef T
613 /* static function prototypes */
614 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
615 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok,
616 unsigned fmt_flags);
617 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
619 static int router_get_hash_impl_helper(const char *s, size_t s_len,
620 const char *start_str,
621 const char *end_str, char end_c,
622 const char **start_out, const char **end_out);
623 static int router_get_hash_impl(const char *s, size_t s_len, char *digest,
624 const char *start_str, const char *end_str,
625 char end_char,
626 digest_algorithm_t alg);
627 static int router_get_hashes_impl(const char *s, size_t s_len,
628 common_digests_t *digests,
629 const char *start_str, const char *end_str,
630 char end_char);
631 static void token_clear(directory_token_t *tok);
632 static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k);
633 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
634 static directory_token_t *find_by_keyword_(smartlist_t *s,
635 directory_keyword keyword,
636 const char *keyword_str);
637 #define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword)
638 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
639 directory_keyword keyword);
641 #define TS_ANNOTATIONS_OK 1
642 #define TS_NOCHECK 2
643 #define TS_NO_NEW_ANNOTATIONS 4
644 static int tokenize_string(memarea_t *area,
645 const char *start, const char *end,
646 smartlist_t *out,
647 token_rule_t *table,
648 int flags);
649 static directory_token_t *get_next_token(memarea_t *area,
650 const char **s,
651 const char *eos,
652 token_rule_t *table);
653 #define CST_CHECK_AUTHORITY (1<<0)
654 #define CST_NO_CHECK_OBJTYPE (1<<1)
655 static int check_signature_token(const char *digest,
656 ssize_t digest_len,
657 directory_token_t *tok,
658 crypto_pk_t *pkey,
659 int flags,
660 const char *doctype);
662 #undef DEBUG_AREA_ALLOC
664 #ifdef DEBUG_AREA_ALLOC
665 #define DUMP_AREA(a,name) STMT_BEGIN \
666 size_t alloc=0, used=0; \
667 memarea_get_stats((a),&alloc,&used); \
668 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
669 name, (unsigned long)alloc, (unsigned long)used); \
670 STMT_END
671 #else
672 #define DUMP_AREA(a,name) STMT_NIL
673 #endif
675 /* Dump mechanism for unparseable descriptors */
677 /** List of dumped descriptors for FIFO cleanup purposes */
678 STATIC smartlist_t *descs_dumped = NULL;
679 /** Total size of dumped descriptors for FIFO cleanup */
680 STATIC uint64_t len_descs_dumped = 0;
681 /** Directory to stash dumps in */
682 static int have_dump_desc_dir = 0;
683 static int problem_with_dump_desc_dir = 0;
685 #define DESC_DUMP_DATADIR_SUBDIR "unparseable-descs"
686 #define DESC_DUMP_BASE_FILENAME "unparseable-desc"
688 /** Find the dump directory and check if we'll be able to create it */
689 static void
690 dump_desc_init(void)
692 char *dump_desc_dir;
694 dump_desc_dir = get_datadir_fname(DESC_DUMP_DATADIR_SUBDIR);
697 * We just check for it, don't create it at this point; we'll
698 * create it when we need it if it isn't already there.
700 if (check_private_dir(dump_desc_dir, CPD_CHECK, get_options()->User) < 0) {
701 /* Error, log and flag it as having a problem */
702 log_notice(LD_DIR,
703 "Doesn't look like we'll be able to create descriptor dump "
704 "directory %s; dumps will be disabled.",
705 dump_desc_dir);
706 problem_with_dump_desc_dir = 1;
707 tor_free(dump_desc_dir);
708 return;
711 /* Check if it exists */
712 switch (file_status(dump_desc_dir)) {
713 case FN_DIR:
714 /* We already have a directory */
715 have_dump_desc_dir = 1;
716 break;
717 case FN_NOENT:
718 /* Nothing, we'll need to create it later */
719 have_dump_desc_dir = 0;
720 break;
721 case FN_ERROR:
722 /* Log and flag having a problem */
723 log_notice(LD_DIR,
724 "Couldn't check whether descriptor dump directory %s already"
725 " exists: %s",
726 dump_desc_dir, strerror(errno));
727 problem_with_dump_desc_dir = 1;
728 break;
729 case FN_FILE:
730 case FN_EMPTY:
731 default:
732 /* Something else was here! */
733 log_notice(LD_DIR,
734 "Descriptor dump directory %s already exists and isn't a "
735 "directory",
736 dump_desc_dir);
737 problem_with_dump_desc_dir = 1;
740 if (have_dump_desc_dir && !problem_with_dump_desc_dir) {
741 dump_desc_populate_fifo_from_directory(dump_desc_dir);
744 tor_free(dump_desc_dir);
747 /** Create the dump directory if needed and possible */
748 static void
749 dump_desc_create_dir(void)
751 char *dump_desc_dir;
753 /* If the problem flag is set, skip it */
754 if (problem_with_dump_desc_dir) return;
756 /* Do we need it? */
757 if (!have_dump_desc_dir) {
758 dump_desc_dir = get_datadir_fname(DESC_DUMP_DATADIR_SUBDIR);
760 if (check_private_dir(dump_desc_dir, CPD_CREATE,
761 get_options()->User) < 0) {
762 log_notice(LD_DIR,
763 "Failed to create descriptor dump directory %s",
764 dump_desc_dir);
765 problem_with_dump_desc_dir = 1;
768 /* Okay, we created it */
769 have_dump_desc_dir = 1;
771 tor_free(dump_desc_dir);
775 /** Dump desc FIFO/cleanup; take ownership of the given filename, add it to
776 * the FIFO, and clean up the oldest entries to the extent they exceed the
777 * configured cap. If any old entries with a matching hash existed, they
778 * just got overwritten right before this was called and we should adjust
779 * the total size counter without deleting them.
781 static void
782 dump_desc_fifo_add_and_clean(char *filename, const uint8_t *digest_sha256,
783 size_t len)
785 dumped_desc_t *ent = NULL, *tmp;
786 uint64_t max_len;
788 tor_assert(filename != NULL);
789 tor_assert(digest_sha256 != NULL);
791 if (descs_dumped == NULL) {
792 /* We better have no length, then */
793 tor_assert(len_descs_dumped == 0);
794 /* Make a smartlist */
795 descs_dumped = smartlist_new();
798 /* Make a new entry to put this one in */
799 ent = tor_malloc_zero(sizeof(*ent));
800 ent->filename = filename;
801 ent->len = len;
802 ent->when = time(NULL);
803 memcpy(ent->digest_sha256, digest_sha256, DIGEST256_LEN);
805 /* Do we need to do some cleanup? */
806 max_len = get_options()->MaxUnparseableDescSizeToLog;
807 /* Iterate over the list until we've freed enough space */
808 while (len > max_len - len_descs_dumped &&
809 smartlist_len(descs_dumped) > 0) {
810 /* Get the oldest thing on the list */
811 tmp = (dumped_desc_t *)(smartlist_get(descs_dumped, 0));
814 * Check if it matches the filename we just added, so we don't delete
815 * something we just emitted if we get repeated identical descriptors.
817 if (strcmp(tmp->filename, filename) != 0) {
818 /* Delete it and adjust the length counter */
819 tor_unlink(tmp->filename);
820 tor_assert(len_descs_dumped >= tmp->len);
821 len_descs_dumped -= tmp->len;
822 log_info(LD_DIR,
823 "Deleting old unparseable descriptor dump %s due to "
824 "space limits",
825 tmp->filename);
826 } else {
828 * Don't delete, but do adjust the counter since we will bump it
829 * later
831 tor_assert(len_descs_dumped >= tmp->len);
832 len_descs_dumped -= tmp->len;
833 log_info(LD_DIR,
834 "Replacing old descriptor dump %s with new identical one",
835 tmp->filename);
838 /* Free it and remove it from the list */
839 smartlist_del_keeporder(descs_dumped, 0);
840 tor_free(tmp->filename);
841 tor_free(tmp);
844 /* Append our entry to the end of the list and bump the counter */
845 smartlist_add(descs_dumped, ent);
846 len_descs_dumped += len;
849 /** Check if we already have a descriptor for this hash and move it to the
850 * head of the queue if so. Return 1 if one existed and 0 otherwise.
852 static int
853 dump_desc_fifo_bump_hash(const uint8_t *digest_sha256)
855 dumped_desc_t *match = NULL;
857 tor_assert(digest_sha256);
859 if (descs_dumped) {
860 /* Find a match if one exists */
861 SMARTLIST_FOREACH_BEGIN(descs_dumped, dumped_desc_t *, ent) {
862 if (ent &&
863 tor_memeq(ent->digest_sha256, digest_sha256, DIGEST256_LEN)) {
865 * Save a pointer to the match and remove it from its current
866 * position.
868 match = ent;
869 SMARTLIST_DEL_CURRENT_KEEPORDER(descs_dumped, ent);
870 break;
872 } SMARTLIST_FOREACH_END(ent);
874 if (match) {
875 /* Update the timestamp */
876 match->when = time(NULL);
877 /* Add it back at the end of the list */
878 smartlist_add(descs_dumped, match);
880 /* Indicate we found one */
881 return 1;
885 return 0;
888 /** Clean up on exit; just memory, leave the dumps behind
890 STATIC void
891 dump_desc_fifo_cleanup(void)
893 if (descs_dumped) {
894 /* Free each descriptor */
895 SMARTLIST_FOREACH_BEGIN(descs_dumped, dumped_desc_t *, ent) {
896 tor_assert(ent);
897 tor_free(ent->filename);
898 tor_free(ent);
899 } SMARTLIST_FOREACH_END(ent);
900 /* Free the list */
901 smartlist_free(descs_dumped);
902 descs_dumped = NULL;
903 len_descs_dumped = 0;
907 /** Handle one file for dump_desc_populate_fifo_from_directory(); make sure
908 * the filename is sensibly formed and matches the file content, and either
909 * return a dumped_desc_t for it or remove the file and return NULL.
911 MOCK_IMPL(STATIC dumped_desc_t *,
912 dump_desc_populate_one_file, (const char *dirname, const char *f))
914 dumped_desc_t *ent = NULL;
915 char *path = NULL, *desc = NULL;
916 const char *digest_str;
917 char digest[DIGEST256_LEN], content_digest[DIGEST256_LEN];
918 /* Expected prefix before digest in filenames */
919 const char *f_pfx = DESC_DUMP_BASE_FILENAME ".";
921 * Stat while reading; this is important in case the file
922 * contains a NUL character.
924 struct stat st;
926 /* Sanity-check args */
927 tor_assert(dirname != NULL);
928 tor_assert(f != NULL);
930 /* Form the full path */
931 tor_asprintf(&path, "%s" PATH_SEPARATOR "%s", dirname, f);
933 /* Check that f has the form DESC_DUMP_BASE_FILENAME.<digest256> */
935 if (!strcmpstart(f, f_pfx)) {
936 /* It matches the form, but is the digest parseable as such? */
937 digest_str = f + strlen(f_pfx);
938 if (base16_decode(digest, DIGEST256_LEN,
939 digest_str, strlen(digest_str)) != DIGEST256_LEN) {
940 /* We failed to decode it */
941 digest_str = NULL;
943 } else {
944 /* No match */
945 digest_str = NULL;
948 if (!digest_str) {
949 /* We couldn't get a sensible digest */
950 log_notice(LD_DIR,
951 "Removing unrecognized filename %s from unparseable "
952 "descriptors directory", f);
953 tor_unlink(path);
954 /* We're done */
955 goto done;
959 * The filename has the form DESC_DUMP_BASE_FILENAME "." <digest256> and
960 * we've decoded the digest. Next, check that we can read it and the
961 * content matches this digest. We are relying on the fact that if the
962 * file contains a '\0', read_file_to_str() will allocate space for and
963 * read the entire file and return the correct size in st.
965 desc = read_file_to_str(path, RFTS_IGNORE_MISSING|RFTS_BIN, &st);
966 if (!desc) {
967 /* We couldn't read it */
968 log_notice(LD_DIR,
969 "Failed to read %s from unparseable descriptors directory; "
970 "attempting to remove it.", f);
971 tor_unlink(path);
972 /* We're done */
973 goto done;
976 #if SIZE_MAX > UINT64_MAX
977 if (BUG((uint64_t)st.st_size > (uint64_t)SIZE_MAX)) {
978 /* LCOV_EXCL_START
979 * Should be impossible since RFTS above should have failed to read the
980 * huge file into RAM. */
981 goto done;
982 /* LCOV_EXCL_STOP */
984 #endif
985 if (BUG(st.st_size < 0)) {
986 /* LCOV_EXCL_START
987 * Should be impossible, since the OS isn't supposed to be b0rken. */
988 goto done;
989 /* LCOV_EXCL_STOP */
991 /* (Now we can be sure that st.st_size is safe to cast to a size_t.) */
994 * We got one; now compute its digest and check that it matches the
995 * filename.
997 if (crypto_digest256((char *)content_digest, desc, (size_t) st.st_size,
998 DIGEST_SHA256) != 0) {
999 /* Weird, but okay */
1000 log_info(LD_DIR,
1001 "Unable to hash content of %s from unparseable descriptors "
1002 "directory", f);
1003 tor_unlink(path);
1004 /* We're done */
1005 goto done;
1008 /* Compare the digests */
1009 if (tor_memneq(digest, content_digest, DIGEST256_LEN)) {
1010 /* No match */
1011 log_info(LD_DIR,
1012 "Hash of %s from unparseable descriptors directory didn't "
1013 "match its filename; removing it", f);
1014 tor_unlink(path);
1015 /* We're done */
1016 goto done;
1019 /* Okay, it's a match, we should prepare ent */
1020 ent = tor_malloc_zero(sizeof(dumped_desc_t));
1021 ent->filename = path;
1022 memcpy(ent->digest_sha256, digest, DIGEST256_LEN);
1023 ent->len = (size_t) st.st_size;
1024 ent->when = st.st_mtime;
1025 /* Null out path so we don't free it out from under ent */
1026 path = NULL;
1028 done:
1029 /* Free allocations if we had them */
1030 tor_free(desc);
1031 tor_free(path);
1033 return ent;
1036 /** Sort helper for dump_desc_populate_fifo_from_directory(); compares
1037 * the when field of dumped_desc_ts in a smartlist to put the FIFO in
1038 * the correct order after reconstructing it from the directory.
1040 static int
1041 dump_desc_compare_fifo_entries(const void **a_v, const void **b_v)
1043 const dumped_desc_t **a = (const dumped_desc_t **)a_v;
1044 const dumped_desc_t **b = (const dumped_desc_t **)b_v;
1046 if ((a != NULL) && (*a != NULL)) {
1047 if ((b != NULL) && (*b != NULL)) {
1048 /* We have sensible dumped_desc_ts to compare */
1049 if ((*a)->when < (*b)->when) {
1050 return -1;
1051 } else if ((*a)->when == (*b)->when) {
1052 return 0;
1053 } else {
1054 return 1;
1056 } else {
1058 * We shouldn't see this, but what the hell, NULLs precede everythin
1059 * else
1061 return 1;
1063 } else {
1064 return -1;
1068 /** Scan the contents of the directory, and update FIFO/counters; this will
1069 * consistency-check descriptor dump filenames against hashes of descriptor
1070 * dump file content, and remove any inconsistent/unreadable dumps, and then
1071 * reconstruct the dump FIFO as closely as possible for the last time the
1072 * tor process shut down. If a previous dump was repeated more than once and
1073 * moved ahead in the FIFO, the mtime will not have been updated and the
1074 * reconstructed order will be wrong, but will always be a permutation of
1075 * the original.
1077 STATIC void
1078 dump_desc_populate_fifo_from_directory(const char *dirname)
1080 smartlist_t *files = NULL;
1081 dumped_desc_t *ent = NULL;
1083 tor_assert(dirname != NULL);
1085 /* Get a list of files */
1086 files = tor_listdir(dirname);
1087 if (!files) {
1088 log_notice(LD_DIR,
1089 "Unable to get contents of unparseable descriptor dump "
1090 "directory %s",
1091 dirname);
1092 return;
1096 * Iterate through the list and decide which files should go in the
1097 * FIFO and which should be purged.
1100 SMARTLIST_FOREACH_BEGIN(files, char *, f) {
1101 /* Try to get a FIFO entry */
1102 ent = dump_desc_populate_one_file(dirname, f);
1103 if (ent) {
1105 * We got one; add it to the FIFO. No need for duplicate checking
1106 * here since we just verified the name and digest match.
1109 /* Make sure we have a list to add it to */
1110 if (!descs_dumped) {
1111 descs_dumped = smartlist_new();
1112 len_descs_dumped = 0;
1115 /* Add it and adjust the counter */
1116 smartlist_add(descs_dumped, ent);
1117 len_descs_dumped += ent->len;
1120 * If we didn't, we will have unlinked the file if necessary and
1121 * possible, and emitted a log message about it, so just go on to
1122 * the next.
1124 } SMARTLIST_FOREACH_END(f);
1126 /* Did we get anything? */
1127 if (descs_dumped != NULL) {
1128 /* Sort the FIFO in order of increasing timestamp */
1129 smartlist_sort(descs_dumped, dump_desc_compare_fifo_entries);
1131 /* Log some stats */
1132 log_info(LD_DIR,
1133 "Reloaded unparseable descriptor dump FIFO with %d dump(s) "
1134 "totaling " U64_FORMAT " bytes",
1135 smartlist_len(descs_dumped), U64_PRINTF_ARG(len_descs_dumped));
1138 /* Free the original list */
1139 SMARTLIST_FOREACH(files, char *, f, tor_free(f));
1140 smartlist_free(files);
1143 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
1144 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
1145 * than one descriptor to disk per minute. If there is already such a
1146 * file in the data directory, overwrite it. */
1147 STATIC void
1148 dump_desc(const char *desc, const char *type)
1150 tor_assert(desc);
1151 tor_assert(type);
1152 size_t len;
1153 /* The SHA256 of the string */
1154 uint8_t digest_sha256[DIGEST256_LEN];
1155 char digest_sha256_hex[HEX_DIGEST256_LEN+1];
1156 /* Filename to log it to */
1157 char *debugfile, *debugfile_base;
1159 /* Get the hash for logging purposes anyway */
1160 len = strlen(desc);
1161 if (crypto_digest256((char *)digest_sha256, desc, len,
1162 DIGEST_SHA256) != 0) {
1163 log_info(LD_DIR,
1164 "Unable to parse descriptor of type %s, and unable to even hash"
1165 " it!", type);
1166 goto err;
1169 base16_encode(digest_sha256_hex, sizeof(digest_sha256_hex),
1170 (const char *)digest_sha256, sizeof(digest_sha256));
1173 * We mention type and hash in the main log; don't clutter up the files
1174 * with anything but the exact dump.
1176 tor_asprintf(&debugfile_base,
1177 DESC_DUMP_BASE_FILENAME ".%s", digest_sha256_hex);
1178 debugfile = get_datadir_fname2(DESC_DUMP_DATADIR_SUBDIR, debugfile_base);
1181 * Check if the sandbox is active or will become active; see comment
1182 * below at the log message for why.
1184 if (!(sandbox_is_active() || get_options()->Sandbox)) {
1185 if (len <= get_options()->MaxUnparseableDescSizeToLog) {
1186 if (!dump_desc_fifo_bump_hash(digest_sha256)) {
1187 /* Create the directory if needed */
1188 dump_desc_create_dir();
1189 /* Make sure we've got it */
1190 if (have_dump_desc_dir && !problem_with_dump_desc_dir) {
1191 /* Write it, and tell the main log about it */
1192 write_str_to_file(debugfile, desc, 1);
1193 log_info(LD_DIR,
1194 "Unable to parse descriptor of type %s with hash %s and "
1195 "length %lu. See file %s in data directory for details.",
1196 type, digest_sha256_hex, (unsigned long)len,
1197 debugfile_base);
1198 dump_desc_fifo_add_and_clean(debugfile, digest_sha256, len);
1199 /* Since we handed ownership over, don't free debugfile later */
1200 debugfile = NULL;
1201 } else {
1202 /* Problem with the subdirectory */
1203 log_info(LD_DIR,
1204 "Unable to parse descriptor of type %s with hash %s and "
1205 "length %lu. Descriptor not dumped because we had a "
1206 "problem creating the " DESC_DUMP_DATADIR_SUBDIR
1207 " subdirectory",
1208 type, digest_sha256_hex, (unsigned long)len);
1209 /* We do have to free debugfile in this case */
1211 } else {
1212 /* We already had one with this hash dumped */
1213 log_info(LD_DIR,
1214 "Unable to parse descriptor of type %s with hash %s and "
1215 "length %lu. Descriptor not dumped because one with that "
1216 "hash has already been dumped.",
1217 type, digest_sha256_hex, (unsigned long)len);
1218 /* We do have to free debugfile in this case */
1220 } else {
1221 /* Just log that it happened without dumping */
1222 log_info(LD_DIR,
1223 "Unable to parse descriptor of type %s with hash %s and "
1224 "length %lu. Descriptor not dumped because it exceeds maximum"
1225 " log size all by itself.",
1226 type, digest_sha256_hex, (unsigned long)len);
1227 /* We do have to free debugfile in this case */
1229 } else {
1231 * Not logging because the sandbox is active and seccomp2 apparently
1232 * doesn't have a sensible way to allow filenames according to a pattern
1233 * match. (If we ever figure out how to say "allow writes to /regex/",
1234 * remove this checK).
1236 log_info(LD_DIR,
1237 "Unable to parse descriptor of type %s with hash %s and "
1238 "length %lu. Descriptor not dumped because the sandbox is "
1239 "configured",
1240 type, digest_sha256_hex, (unsigned long)len);
1243 tor_free(debugfile_base);
1244 tor_free(debugfile);
1246 err:
1247 return;
1250 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
1251 * <b>s</b>. Return 0 on success, -1 on failure.
1254 router_get_dir_hash(const char *s, char *digest)
1256 return router_get_hash_impl(s, strlen(s), digest,
1257 "signed-directory","\ndirectory-signature",'\n',
1258 DIGEST_SHA1);
1261 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
1262 * <b>s</b>. Return 0 on success, -1 on failure.
1265 router_get_router_hash(const char *s, size_t s_len, char *digest)
1267 return router_get_hash_impl(s, s_len, digest,
1268 "router ","\nrouter-signature", '\n',
1269 DIGEST_SHA1);
1272 /** Set <b>digests</b> to all the digests of the consensus document in
1273 * <b>s</b> */
1275 router_get_networkstatus_v3_hashes(const char *s, common_digests_t *digests)
1277 return router_get_hashes_impl(s,strlen(s),digests,
1278 "network-status-version",
1279 "\ndirectory-signature",
1280 ' ');
1283 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
1284 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
1286 router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
1288 return router_get_hash_impl(s, s_len, digest, "extra-info",
1289 "\nrouter-signature",'\n', DIGEST_SHA1);
1292 /** Helper: used to generate signatures for routers, directories and
1293 * network-status objects. Given a <b>digest_len</b>-byte digest in
1294 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
1295 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
1296 * and return the new signature on success or NULL on failure.
1298 char *
1299 router_get_dirobj_signature(const char *digest,
1300 size_t digest_len,
1301 const crypto_pk_t *private_key)
1303 char *signature;
1304 size_t i, keysize;
1305 int siglen;
1306 char *buf = NULL;
1307 size_t buf_len;
1308 /* overestimate of BEGIN/END lines total len. */
1309 #define BEGIN_END_OVERHEAD_LEN 64
1311 keysize = crypto_pk_keysize(private_key);
1312 signature = tor_malloc(keysize);
1313 siglen = crypto_pk_private_sign(private_key, signature, keysize,
1314 digest, digest_len);
1315 if (siglen < 0) {
1316 log_warn(LD_BUG,"Couldn't sign digest.");
1317 goto err;
1320 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
1321 buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN;
1322 buf = tor_malloc(buf_len);
1324 if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
1325 goto truncated;
1327 i = strlen(buf);
1328 if (base64_encode(buf+i, buf_len-i, signature, siglen,
1329 BASE64_ENCODE_MULTILINE) < 0) {
1330 log_warn(LD_BUG,"couldn't base64-encode signature");
1331 goto err;
1334 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
1335 goto truncated;
1337 tor_free(signature);
1338 return buf;
1340 truncated:
1341 log_warn(LD_BUG,"tried to exceed string length.");
1342 err:
1343 tor_free(signature);
1344 tor_free(buf);
1345 return NULL;
1348 /** Helper: used to generate signatures for routers, directories and
1349 * network-status objects. Given a digest in <b>digest</b> and a secret
1350 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
1351 * surround it with -----BEGIN/END----- pairs, and write it to the
1352 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
1353 * failure.
1356 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
1357 size_t digest_len, crypto_pk_t *private_key)
1359 size_t sig_len, s_len;
1360 char *sig = router_get_dirobj_signature(digest, digest_len, private_key);
1361 if (!sig) {
1362 log_warn(LD_BUG, "No signature generated");
1363 return -1;
1365 sig_len = strlen(sig);
1366 s_len = strlen(buf);
1367 if (sig_len + s_len + 1 > buf_len) {
1368 log_warn(LD_BUG, "Not enough room for signature");
1369 tor_free(sig);
1370 return -1;
1372 memcpy(buf+s_len, sig, sig_len+1);
1373 tor_free(sig);
1374 return 0;
1377 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
1378 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
1379 * entries. Else, return VS_OLD if every member of
1380 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
1381 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
1382 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
1383 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
1384 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
1385 * VS_UNRECOMMENDED.
1387 * (versionlist is a comma-separated list of version strings,
1388 * optionally prefixed with "Tor". Versions that can't be parsed are
1389 * ignored.)
1391 version_status_t
1392 tor_version_is_obsolete(const char *myversion, const char *versionlist)
1394 tor_version_t mine, other;
1395 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
1396 found_any_in_series = 0, r, same;
1397 version_status_t ret = VS_UNRECOMMENDED;
1398 smartlist_t *version_sl;
1400 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
1401 myversion, versionlist);
1403 if (tor_version_parse(myversion, &mine)) {
1404 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
1405 tor_assert(0);
1407 version_sl = smartlist_new();
1408 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
1410 if (!strlen(versionlist)) { /* no authorities cared or agreed */
1411 ret = VS_EMPTY;
1412 goto done;
1415 SMARTLIST_FOREACH_BEGIN(version_sl, const char *, cp) {
1416 if (!strcmpstart(cp, "Tor "))
1417 cp += 4;
1419 if (tor_version_parse(cp, &other)) {
1420 /* Couldn't parse other; it can't be a match. */
1421 } else {
1422 same = tor_version_same_series(&mine, &other);
1423 if (same)
1424 found_any_in_series = 1;
1425 r = tor_version_compare(&mine, &other);
1426 if (r==0) {
1427 ret = VS_RECOMMENDED;
1428 goto done;
1429 } else if (r<0) {
1430 found_newer = 1;
1431 if (same)
1432 found_newer_in_series = 1;
1433 } else if (r>0) {
1434 found_older = 1;
1437 } SMARTLIST_FOREACH_END(cp);
1439 /* We didn't find the listed version. Is it new or old? */
1440 if (found_any_in_series && !found_newer_in_series && found_newer) {
1441 ret = VS_NEW_IN_SERIES;
1442 } else if (found_newer && !found_older) {
1443 ret = VS_OLD;
1444 } else if (found_older && !found_newer) {
1445 ret = VS_NEW;
1446 } else {
1447 ret = VS_UNRECOMMENDED;
1450 done:
1451 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
1452 smartlist_free(version_sl);
1453 return ret;
1456 /** Return true iff <b>key</b> is allowed to sign directories.
1458 static int
1459 dir_signing_key_is_trusted(crypto_pk_t *key)
1461 char digest[DIGEST_LEN];
1462 if (!key) return 0;
1463 if (crypto_pk_get_digest(key, digest) < 0) {
1464 log_warn(LD_DIR, "Error computing dir-signing-key digest");
1465 return 0;
1467 if (!router_digest_is_trusted_dir(digest)) {
1468 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
1469 return 0;
1471 return 1;
1474 /** Check whether the object body of the token in <b>tok</b> has a good
1475 * signature for <b>digest</b> using key <b>pkey</b>. If
1476 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
1477 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
1478 * the object type of the signature object. Use <b>doctype</b> as the type of
1479 * the document when generating log messages. Return 0 on success, negative
1480 * on failure.
1482 static int
1483 check_signature_token(const char *digest,
1484 ssize_t digest_len,
1485 directory_token_t *tok,
1486 crypto_pk_t *pkey,
1487 int flags,
1488 const char *doctype)
1490 char *signed_digest;
1491 size_t keysize;
1492 const int check_authority = (flags & CST_CHECK_AUTHORITY);
1493 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
1495 tor_assert(pkey);
1496 tor_assert(tok);
1497 tor_assert(digest);
1498 tor_assert(doctype);
1500 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
1501 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
1502 doctype);
1503 return -1;
1506 if (check_objtype) {
1507 if (strcmp(tok->object_type, "SIGNATURE")) {
1508 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
1509 return -1;
1513 keysize = crypto_pk_keysize(pkey);
1514 signed_digest = tor_malloc(keysize);
1515 if (crypto_pk_public_checksig(pkey, signed_digest, keysize,
1516 tok->object_body, tok->object_size)
1517 < digest_len) {
1518 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
1519 tor_free(signed_digest);
1520 return -1;
1522 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
1523 // hex_str(signed_digest,4));
1524 if (tor_memneq(digest, signed_digest, digest_len)) {
1525 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
1526 tor_free(signed_digest);
1527 return -1;
1529 tor_free(signed_digest);
1530 return 0;
1533 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
1534 * or to the first of the annotations proceeding the next router or
1535 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
1536 * we found an extrainfo, or false if found a router. Do not scan beyond
1537 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
1538 static int
1539 find_start_of_next_router_or_extrainfo(const char **s_ptr,
1540 const char *eos,
1541 int *is_extrainfo_out)
1543 const char *annotations = NULL;
1544 const char *s = *s_ptr;
1546 s = eat_whitespace_eos(s, eos);
1548 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
1549 /* We're at the start of a line. */
1550 tor_assert(*s != '\n');
1552 if (*s == '@' && !annotations) {
1553 annotations = s;
1554 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
1555 *s_ptr = annotations ? annotations : s;
1556 *is_extrainfo_out = 0;
1557 return 0;
1558 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
1559 *s_ptr = annotations ? annotations : s;
1560 *is_extrainfo_out = 1;
1561 return 0;
1564 if (!(s = memchr(s+1, '\n', eos-(s+1))))
1565 break;
1566 s = eat_whitespace_eos(s, eos);
1568 return -1;
1571 /** Given a string *<b>s</b> containing a concatenated sequence of router
1572 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1573 * them and stores the result in <b>dest</b>. All routers are marked running
1574 * and valid. Advances *s to a point immediately following the last router
1575 * entry. Ignore any trailing router entries that are not complete.
1577 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1578 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1579 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1581 * Returns 0 on success and -1 on failure. Adds a digest to
1582 * <b>invalid_digests_out</b> for every entry that was unparseable or
1583 * invalid. (This may cause duplicate entries.)
1586 router_parse_list_from_string(const char **s, const char *eos,
1587 smartlist_t *dest,
1588 saved_location_t saved_location,
1589 int want_extrainfo,
1590 int allow_annotations,
1591 const char *prepend_annotations,
1592 smartlist_t *invalid_digests_out)
1594 routerinfo_t *router;
1595 extrainfo_t *extrainfo;
1596 signed_descriptor_t *signed_desc = NULL;
1597 void *elt;
1598 const char *end, *start;
1599 int have_extrainfo;
1601 tor_assert(s);
1602 tor_assert(*s);
1603 tor_assert(dest);
1605 start = *s;
1606 if (!eos)
1607 eos = *s + strlen(*s);
1609 tor_assert(eos >= *s);
1611 while (1) {
1612 char raw_digest[DIGEST_LEN];
1613 int have_raw_digest = 0;
1614 int dl_again = 0;
1615 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1616 break;
1618 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1619 if (end)
1620 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1621 if (end)
1622 end += strlen("\n-----END SIGNATURE-----\n");
1624 if (!end)
1625 break;
1627 elt = NULL;
1629 if (have_extrainfo && want_extrainfo) {
1630 routerlist_t *rl = router_get_routerlist();
1631 have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
1632 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1633 saved_location != SAVED_IN_CACHE,
1634 rl->identity_map, &dl_again);
1635 if (extrainfo) {
1636 signed_desc = &extrainfo->cache_info;
1637 elt = extrainfo;
1639 } else if (!have_extrainfo && !want_extrainfo) {
1640 have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
1641 router = router_parse_entry_from_string(*s, end,
1642 saved_location != SAVED_IN_CACHE,
1643 allow_annotations,
1644 prepend_annotations, &dl_again);
1645 if (router) {
1646 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1647 router_describe(router),
1648 router_purpose_to_string(router->purpose));
1649 signed_desc = &router->cache_info;
1650 elt = router;
1653 if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
1654 smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
1656 if (!elt) {
1657 *s = end;
1658 continue;
1660 if (saved_location != SAVED_NOWHERE) {
1661 tor_assert(signed_desc);
1662 signed_desc->saved_location = saved_location;
1663 signed_desc->saved_offset = *s - start;
1665 *s = end;
1666 smartlist_add(dest, elt);
1669 return 0;
1672 /* For debugging: define to count every descriptor digest we've seen so we
1673 * know if we need to try harder to avoid duplicate verifies. */
1674 #undef COUNT_DISTINCT_DIGESTS
1676 #ifdef COUNT_DISTINCT_DIGESTS
1677 static digestmap_t *verified_digests = NULL;
1678 #endif
1680 /** Log the total count of the number of distinct router digests we've ever
1681 * verified. When compared to the number of times we've verified routerdesc
1682 * signatures <i>in toto</i>, this will tell us if we're doing too much
1683 * multiple-verification. */
1684 void
1685 dump_distinct_digest_count(int severity)
1687 #ifdef COUNT_DISTINCT_DIGESTS
1688 if (!verified_digests)
1689 verified_digests = digestmap_new();
1690 tor_log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1691 digestmap_size(verified_digests));
1692 #else
1693 (void)severity; /* suppress "unused parameter" warning */
1694 #endif
1697 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1698 * with at least one argument (use GE(1) in setup). If found, store
1699 * address and port number to <b>addr_out</b> and
1700 * <b>port_out</b>. Return number of OR ports found. */
1701 static int
1702 find_single_ipv6_orport(const smartlist_t *list,
1703 tor_addr_t *addr_out,
1704 uint16_t *port_out)
1706 int ret = 0;
1707 tor_assert(list != NULL);
1708 tor_assert(addr_out != NULL);
1709 tor_assert(port_out != NULL);
1711 SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) {
1712 tor_addr_t a;
1713 maskbits_t bits;
1714 uint16_t port_min, port_max;
1715 tor_assert(t->n_args >= 1);
1716 /* XXXX Prop186 the full spec allows much more than this. */
1717 if (tor_addr_parse_mask_ports(t->args[0], 0,
1718 &a, &bits, &port_min,
1719 &port_max) == AF_INET6 &&
1720 bits == 128 &&
1721 port_min == port_max) {
1722 /* Okay, this is one we can understand. Use it and ignore
1723 any potential more addresses in list. */
1724 tor_addr_copy(addr_out, &a);
1725 *port_out = port_min;
1726 ret = 1;
1727 break;
1729 } SMARTLIST_FOREACH_END(t);
1731 return ret;
1734 /** Helper function: reads a single router entry from *<b>s</b> ...
1735 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1736 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1737 * s through end into the signed_descriptor_body of the resulting
1738 * routerinfo_t.
1740 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1742 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1743 * before the router; if it's false, reject the router if it's annotated. If
1744 * <b>prepend_annotations</b> is set, it should contain some annotations:
1745 * append them to the front of the router before parsing it, and keep them
1746 * around when caching the router.
1748 * Only one of allow_annotations and prepend_annotations may be set.
1750 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1751 * if it's okay to try to download a descriptor with this same digest again,
1752 * and 0 if it isn't. (It might not be okay to download it again if part of
1753 * the part covered by the digest is invalid.)
1755 routerinfo_t *
1756 router_parse_entry_from_string(const char *s, const char *end,
1757 int cache_copy, int allow_annotations,
1758 const char *prepend_annotations,
1759 int *can_dl_again_out)
1761 routerinfo_t *router = NULL;
1762 char digest[128];
1763 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1764 directory_token_t *tok;
1765 struct in_addr in;
1766 const char *start_of_annotations, *cp, *s_dup = s;
1767 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1768 int ok = 1;
1769 memarea_t *area = NULL;
1770 tor_cert_t *ntor_cc_cert = NULL;
1771 /* Do not set this to '1' until we have parsed everything that we intend to
1772 * parse that's covered by the hash. */
1773 int can_dl_again = 0;
1775 tor_assert(!allow_annotations || !prepend_annotations);
1777 if (!end) {
1778 end = s + strlen(s);
1781 /* point 'end' to a point immediately after the final newline. */
1782 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1783 --end;
1785 area = memarea_new();
1786 tokens = smartlist_new();
1787 if (prepend_annotations) {
1788 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1789 routerdesc_token_table,TS_NOCHECK)) {
1790 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1791 goto err;
1795 start_of_annotations = s;
1796 cp = tor_memstr(s, end-s, "\nrouter ");
1797 if (!cp) {
1798 if (end-s < 7 || strcmpstart(s, "router ")) {
1799 log_warn(LD_DIR, "No router keyword found.");
1800 goto err;
1802 } else {
1803 s = cp+1;
1806 if (start_of_annotations != s) { /* We have annotations */
1807 if (allow_annotations) {
1808 if (tokenize_string(area,start_of_annotations,s,tokens,
1809 routerdesc_token_table,TS_NOCHECK)) {
1810 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1811 goto err;
1813 } else {
1814 log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
1815 "loaded from disk. Dropping it.");
1816 goto err;
1820 if (router_get_router_hash(s, end - s, digest) < 0) {
1821 log_warn(LD_DIR, "Couldn't compute router hash.");
1822 goto err;
1825 int flags = 0;
1826 if (allow_annotations)
1827 flags |= TS_ANNOTATIONS_OK;
1828 if (prepend_annotations)
1829 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1831 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1832 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1833 goto err;
1837 if (smartlist_len(tokens) < 2) {
1838 log_warn(LD_DIR, "Impossibly short router descriptor.");
1839 goto err;
1842 tok = find_by_keyword(tokens, K_ROUTER);
1843 const int router_token_pos = smartlist_pos(tokens, tok);
1844 tor_assert(tok->n_args >= 5);
1846 router = tor_malloc_zero(sizeof(routerinfo_t));
1847 router->cert_expiration_time = TIME_MAX;
1848 router->cache_info.routerlist_index = -1;
1849 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1850 router->cache_info.signed_descriptor_len = end-s;
1851 if (cache_copy) {
1852 size_t len = router->cache_info.signed_descriptor_len +
1853 router->cache_info.annotations_len;
1854 char *signed_body =
1855 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1856 if (prepend_annotations) {
1857 memcpy(signed_body, prepend_annotations, prepend_len);
1858 signed_body += prepend_len;
1860 /* This assertion will always succeed.
1861 * len == signed_desc_len + annotations_len
1862 * == end-s + s-start_of_annotations + prepend_len
1863 * == end-start_of_annotations + prepend_len
1864 * We already wrote prepend_len bytes into the buffer; now we're
1865 * writing end-start_of_annotations -NM. */
1866 tor_assert(signed_body+(end-start_of_annotations) ==
1867 router->cache_info.signed_descriptor_body+len);
1868 memcpy(signed_body, start_of_annotations, end-start_of_annotations);
1869 router->cache_info.signed_descriptor_body[len] = '\0';
1870 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1872 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1874 router->nickname = tor_strdup(tok->args[0]);
1875 if (!is_legal_nickname(router->nickname)) {
1876 log_warn(LD_DIR,"Router nickname is invalid");
1877 goto err;
1879 if (!tor_inet_aton(tok->args[1], &in)) {
1880 log_warn(LD_DIR,"Router address is not an IP address.");
1881 goto err;
1883 router->addr = ntohl(in.s_addr);
1885 router->or_port =
1886 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1887 if (!ok) {
1888 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1889 goto err;
1891 router->dir_port =
1892 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1893 if (!ok) {
1894 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1895 goto err;
1898 tok = find_by_keyword(tokens, K_BANDWIDTH);
1899 tor_assert(tok->n_args >= 3);
1900 router->bandwidthrate = (int)
1901 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1903 if (!ok) {
1904 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1905 escaped(tok->args[0]));
1906 goto err;
1908 router->bandwidthburst =
1909 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1910 if (!ok) {
1911 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1912 goto err;
1914 router->bandwidthcapacity = (int)
1915 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1916 if (!ok) {
1917 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1918 goto err;
1921 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1922 tor_assert(tok->n_args);
1923 router->purpose = router_purpose_from_string(tok->args[0]);
1924 } else {
1925 router->purpose = ROUTER_PURPOSE_GENERAL;
1927 router->cache_info.send_unencrypted =
1928 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1930 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1931 tor_assert(tok->n_args >= 1);
1932 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1933 if (!ok) {
1934 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1935 goto err;
1939 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1940 tor_assert(tok->n_args >= 1);
1941 router->is_hibernating
1942 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1945 tok = find_by_keyword(tokens, K_PUBLISHED);
1946 tor_assert(tok->n_args == 1);
1947 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1948 goto err;
1950 tok = find_by_keyword(tokens, K_ONION_KEY);
1951 if (!crypto_pk_public_exponent_ok(tok->key)) {
1952 log_warn(LD_DIR,
1953 "Relay's onion key had invalid exponent.");
1954 goto err;
1956 router->onion_pkey = tok->key;
1957 tok->key = NULL; /* Prevent free */
1959 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
1960 curve25519_public_key_t k;
1961 tor_assert(tok->n_args >= 1);
1962 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
1963 log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
1964 goto err;
1966 router->onion_curve25519_pkey =
1967 tor_memdup(&k, sizeof(curve25519_public_key_t));
1970 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1971 router->identity_pkey = tok->key;
1972 tok->key = NULL; /* Prevent free */
1973 if (crypto_pk_get_digest(router->identity_pkey,
1974 router->cache_info.identity_digest)) {
1975 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1979 directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
1980 *master_key_tok;
1981 ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
1982 ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
1983 master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
1984 cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
1985 cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
1986 int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
1987 !!cc_tap_tok + !!cc_ntor_tok;
1988 if ((n_ed_toks != 0 && n_ed_toks != 4) ||
1989 (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
1990 log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
1991 "cross-certification support");
1992 goto err;
1994 if (master_key_tok && !ed_sig_tok) {
1995 log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
1996 "certificate");
1997 goto err;
1999 if (ed_sig_tok) {
2000 tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
2001 const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
2002 if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
2003 (ed_cert_token_pos != router_token_pos + 1 &&
2004 ed_cert_token_pos != router_token_pos - 1)) {
2005 log_warn(LD_DIR, "Ed25519 certificate in wrong position");
2006 goto err;
2008 if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
2009 log_warn(LD_DIR, "Ed25519 signature in wrong position");
2010 goto err;
2012 if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
2013 log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
2014 goto err;
2016 if (strcmp(cc_ntor_tok->object_type, "ED25519 CERT")) {
2017 log_warn(LD_DIR, "Wrong object type on ntor-onion-key-crosscert "
2018 "in decriptor");
2019 goto err;
2021 if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
2022 log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
2023 "in decriptor");
2024 goto err;
2026 if (strcmp(cc_ntor_tok->args[0], "0") &&
2027 strcmp(cc_ntor_tok->args[0], "1")) {
2028 log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
2029 goto err;
2031 int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
2033 uint8_t d256[DIGEST256_LEN];
2034 const char *signed_start, *signed_end;
2035 tor_cert_t *cert = tor_cert_parse(
2036 (const uint8_t*)ed_cert_tok->object_body,
2037 ed_cert_tok->object_size);
2038 if (! cert) {
2039 log_warn(LD_DIR, "Couldn't parse ed25519 cert");
2040 goto err;
2042 /* makes sure it gets freed. */
2043 router->cache_info.signing_key_cert = cert;
2045 if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
2046 ! cert->signing_key_included) {
2047 log_warn(LD_DIR, "Invalid form for ed25519 cert");
2048 goto err;
2051 if (master_key_tok) {
2052 /* This token is optional, but if it's present, it must match
2053 * the signature in the signing cert, or supplant it. */
2054 tor_assert(master_key_tok->n_args >= 1);
2055 ed25519_public_key_t pkey;
2056 if (ed25519_public_from_base64(&pkey, master_key_tok->args[0])<0) {
2057 log_warn(LD_DIR, "Can't parse ed25519 master key");
2058 goto err;
2061 if (fast_memneq(&cert->signing_key.pubkey,
2062 pkey.pubkey, ED25519_PUBKEY_LEN)) {
2063 log_warn(LD_DIR, "Ed25519 master key does not match "
2064 "key in certificate");
2065 goto err;
2068 ntor_cc_cert = tor_cert_parse((const uint8_t*)cc_ntor_tok->object_body,
2069 cc_ntor_tok->object_size);
2070 if (!ntor_cc_cert) {
2071 log_warn(LD_DIR, "Couldn't parse ntor-onion-key-crosscert cert");
2072 goto err;
2074 if (ntor_cc_cert->cert_type != CERT_TYPE_ONION_ID ||
2075 ! ed25519_pubkey_eq(&ntor_cc_cert->signed_key, &cert->signing_key)) {
2076 log_warn(LD_DIR, "Invalid contents for ntor-onion-key-crosscert cert");
2077 goto err;
2080 ed25519_public_key_t ntor_cc_pk;
2081 if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk,
2082 router->onion_curve25519_pkey,
2083 ntor_cc_sign_bit)<0) {
2084 log_warn(LD_DIR, "Error converting onion key to ed25519");
2085 goto err;
2088 if (router_get_hash_impl_helper(s, end-s, "router ",
2089 "\nrouter-sig-ed25519",
2090 ' ', &signed_start, &signed_end) < 0) {
2091 log_warn(LD_DIR, "Can't find ed25519-signed portion of descriptor");
2092 goto err;
2094 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
2095 crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
2096 strlen(ED_DESC_SIGNATURE_PREFIX));
2097 crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
2098 crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
2099 crypto_digest_free(d);
2101 ed25519_checkable_t check[3];
2102 int check_ok[3];
2103 if (tor_cert_get_checkable_sig(&check[0], cert, NULL) < 0) {
2104 log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
2105 goto err;
2107 if (tor_cert_get_checkable_sig(&check[1],
2108 ntor_cc_cert, &ntor_cc_pk) < 0) {
2109 log_err(LD_BUG, "Couldn't create 'checkable' for ntor_cc_cert.");
2110 goto err;
2113 if (ed25519_signature_from_base64(&check[2].signature,
2114 ed_sig_tok->args[0])<0) {
2115 log_warn(LD_DIR, "Couldn't decode ed25519 signature");
2116 goto err;
2118 check[2].pubkey = &cert->signed_key;
2119 check[2].msg = d256;
2120 check[2].len = DIGEST256_LEN;
2122 if (ed25519_checksig_batch(check_ok, check, 3) < 0) {
2123 log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
2124 goto err;
2127 if (check_tap_onion_key_crosscert(
2128 (const uint8_t*)cc_tap_tok->object_body,
2129 (int)cc_tap_tok->object_size,
2130 router->onion_pkey,
2131 &cert->signing_key,
2132 (const uint8_t*)router->cache_info.identity_digest)<0) {
2133 log_warn(LD_DIR, "Incorrect TAP cross-verification");
2134 goto err;
2137 /* We check this before adding it to the routerlist. */
2138 if (cert->valid_until < ntor_cc_cert->valid_until)
2139 router->cert_expiration_time = cert->valid_until;
2140 else
2141 router->cert_expiration_time = ntor_cc_cert->valid_until;
2145 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
2146 /* If there's a fingerprint line, it must match the identity digest. */
2147 char d[DIGEST_LEN];
2148 tor_assert(tok->n_args == 1);
2149 tor_strstrip(tok->args[0], " ");
2150 if (base16_decode(d, DIGEST_LEN,
2151 tok->args[0], strlen(tok->args[0])) != DIGEST_LEN) {
2152 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
2153 escaped(tok->args[0]));
2154 goto err;
2156 if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
2157 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
2158 tok->args[0]);
2159 goto err;
2163 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
2164 router->platform = tor_strdup(tok->args[0]);
2167 if ((tok = find_opt_by_keyword(tokens, K_PROTO))) {
2168 router->protocol_list = tor_strdup(tok->args[0]);
2171 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2172 router->contact_info = tor_strdup(tok->args[0]);
2175 if (find_opt_by_keyword(tokens, K_REJECT6) ||
2176 find_opt_by_keyword(tokens, K_ACCEPT6)) {
2177 log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
2178 "older Tors.");
2179 goto err;
2182 smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
2183 if (or_addresses) {
2184 find_single_ipv6_orport(or_addresses, &router->ipv6_addr,
2185 &router->ipv6_orport);
2186 smartlist_free(or_addresses);
2189 exit_policy_tokens = find_all_exitpolicy(tokens);
2190 if (!smartlist_len(exit_policy_tokens)) {
2191 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
2192 goto err;
2194 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
2195 if (router_add_exit_policy(router,t)<0) {
2196 log_warn(LD_DIR,"Error in exit policy");
2197 goto err;
2199 policy_expand_private(&router->exit_policy);
2201 if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) {
2202 router->ipv6_exit_policy = parse_short_policy(tok->args[0]);
2203 if (! router->ipv6_exit_policy) {
2204 log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0]));
2205 goto err;
2209 if (policy_is_reject_star(router->exit_policy, AF_INET, 1) &&
2210 (!router->ipv6_exit_policy ||
2211 short_policy_is_reject_star(router->ipv6_exit_policy)))
2212 router->policy_is_reject_star = 1;
2214 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
2215 int i;
2216 router->declared_family = smartlist_new();
2217 for (i=0;i<tok->n_args;++i) {
2218 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
2219 log_warn(LD_DIR, "Illegal nickname %s in family line",
2220 escaped(tok->args[i]));
2221 goto err;
2223 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
2227 if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
2228 router->caches_extra_info = 1;
2230 if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
2231 router->allow_single_hop_exits = 1;
2233 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
2234 tor_assert(tok->n_args >= 1);
2235 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2236 if (base16_decode(router->cache_info.extra_info_digest, DIGEST_LEN,
2237 tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) {
2238 log_warn(LD_DIR,"Invalid extra info digest");
2240 } else {
2241 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
2244 if (tok->n_args >= 2) {
2245 if (digest256_from_base64(router->cache_info.extra_info_digest256,
2246 tok->args[1]) < 0) {
2247 log_warn(LD_DIR, "Invalid extra info digest256 %s",
2248 escaped(tok->args[1]));
2253 if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
2254 router->wants_to_be_hs_dir = 1;
2257 /* This router accepts tunnelled directory requests via begindir if it has
2258 * an open dirport or it included "tunnelled-dir-server". */
2259 if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) || router->dir_port > 0) {
2260 router->supports_tunnelled_dir_requests = 1;
2263 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
2264 note_crypto_pk_op(VERIFY_RTR);
2265 #ifdef COUNT_DISTINCT_DIGESTS
2266 if (!verified_digests)
2267 verified_digests = digestmap_new();
2268 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
2269 #endif
2271 if (!router->or_port) {
2272 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
2273 goto err;
2276 /* We've checked everything that's covered by the hash. */
2277 can_dl_again = 1;
2278 if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
2279 "router descriptor") < 0)
2280 goto err;
2282 if (!router->platform) {
2283 router->platform = tor_strdup("<unknown>");
2285 goto done;
2287 err:
2288 dump_desc(s_dup, "router descriptor");
2289 routerinfo_free(router);
2290 router = NULL;
2291 done:
2292 tor_cert_free(ntor_cc_cert);
2293 if (tokens) {
2294 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2295 smartlist_free(tokens);
2297 smartlist_free(exit_policy_tokens);
2298 if (area) {
2299 DUMP_AREA(area, "routerinfo");
2300 memarea_drop_all(area);
2302 if (can_dl_again_out)
2303 *can_dl_again_out = can_dl_again;
2304 return router;
2307 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
2308 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
2309 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
2310 * cache_info fields of the result. If <b>routermap</b> is provided, use it
2311 * as a map from router identity to routerinfo_t when looking up signing keys.
2313 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
2314 * if it's okay to try to download an extrainfo with this same digest again,
2315 * and 0 if it isn't. (It might not be okay to download it again if part of
2316 * the part covered by the digest is invalid.)
2318 extrainfo_t *
2319 extrainfo_parse_entry_from_string(const char *s, const char *end,
2320 int cache_copy, struct digest_ri_map_t *routermap,
2321 int *can_dl_again_out)
2323 extrainfo_t *extrainfo = NULL;
2324 char digest[128];
2325 smartlist_t *tokens = NULL;
2326 directory_token_t *tok;
2327 crypto_pk_t *key = NULL;
2328 routerinfo_t *router = NULL;
2329 memarea_t *area = NULL;
2330 const char *s_dup = s;
2331 /* Do not set this to '1' until we have parsed everything that we intend to
2332 * parse that's covered by the hash. */
2333 int can_dl_again = 0;
2335 if (!end) {
2336 end = s + strlen(s);
2339 /* point 'end' to a point immediately after the final newline. */
2340 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
2341 --end;
2343 if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
2344 log_warn(LD_DIR, "Couldn't compute router hash.");
2345 goto err;
2347 tokens = smartlist_new();
2348 area = memarea_new();
2349 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
2350 log_warn(LD_DIR, "Error tokenizing extra-info document.");
2351 goto err;
2354 if (smartlist_len(tokens) < 2) {
2355 log_warn(LD_DIR, "Impossibly short extra-info document.");
2356 goto err;
2359 /* XXXX Accept this in position 1 too, and ed identity in position 0. */
2360 tok = smartlist_get(tokens,0);
2361 if (tok->tp != K_EXTRA_INFO) {
2362 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
2363 goto err;
2366 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
2367 extrainfo->cache_info.is_extrainfo = 1;
2368 if (cache_copy)
2369 extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s);
2370 extrainfo->cache_info.signed_descriptor_len = end-s;
2371 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
2372 crypto_digest256((char*)extrainfo->digest256, s, end-s, DIGEST_SHA256);
2374 tor_assert(tok->n_args >= 2);
2375 if (!is_legal_nickname(tok->args[0])) {
2376 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
2377 goto err;
2379 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
2380 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2381 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
2382 tok->args[1], HEX_DIGEST_LEN) != DIGEST_LEN) {
2383 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
2384 escaped(tok->args[1]));
2385 goto err;
2388 tok = find_by_keyword(tokens, K_PUBLISHED);
2389 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
2390 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
2391 escaped(tok->args[0]));
2392 goto err;
2396 directory_token_t *ed_sig_tok, *ed_cert_tok;
2397 ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
2398 ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
2399 int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok;
2400 if (n_ed_toks != 0 && n_ed_toks != 2) {
2401 log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
2402 "cross-certification support");
2403 goto err;
2405 if (ed_sig_tok) {
2406 tor_assert(ed_cert_tok);
2407 const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
2408 if (ed_cert_token_pos != 1) {
2409 /* Accept this in position 0 XXXX */
2410 log_warn(LD_DIR, "Ed25519 certificate in wrong position");
2411 goto err;
2413 if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
2414 log_warn(LD_DIR, "Ed25519 signature in wrong position");
2415 goto err;
2417 if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
2418 log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
2419 goto err;
2422 uint8_t d256[DIGEST256_LEN];
2423 const char *signed_start, *signed_end;
2424 tor_cert_t *cert = tor_cert_parse(
2425 (const uint8_t*)ed_cert_tok->object_body,
2426 ed_cert_tok->object_size);
2427 if (! cert) {
2428 log_warn(LD_DIR, "Couldn't parse ed25519 cert");
2429 goto err;
2431 /* makes sure it gets freed. */
2432 extrainfo->cache_info.signing_key_cert = cert;
2434 if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
2435 ! cert->signing_key_included) {
2436 log_warn(LD_DIR, "Invalid form for ed25519 cert");
2437 goto err;
2440 if (router_get_hash_impl_helper(s, end-s, "extra-info ",
2441 "\nrouter-sig-ed25519",
2442 ' ', &signed_start, &signed_end) < 0) {
2443 log_warn(LD_DIR, "Can't find ed25519-signed portion of extrainfo");
2444 goto err;
2446 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
2447 crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
2448 strlen(ED_DESC_SIGNATURE_PREFIX));
2449 crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
2450 crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
2451 crypto_digest_free(d);
2453 ed25519_checkable_t check[2];
2454 int check_ok[2];
2455 if (tor_cert_get_checkable_sig(&check[0], cert, NULL) < 0) {
2456 log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
2457 goto err;
2460 if (ed25519_signature_from_base64(&check[1].signature,
2461 ed_sig_tok->args[0])<0) {
2462 log_warn(LD_DIR, "Couldn't decode ed25519 signature");
2463 goto err;
2465 check[1].pubkey = &cert->signed_key;
2466 check[1].msg = d256;
2467 check[1].len = DIGEST256_LEN;
2469 if (ed25519_checksig_batch(check_ok, check, 2) < 0) {
2470 log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
2471 goto err;
2473 /* We don't check the certificate expiration time: checking that it
2474 * matches the cert in the router descriptor is adequate. */
2478 /* We've checked everything that's covered by the hash. */
2479 can_dl_again = 1;
2481 if (routermap &&
2482 (router = digestmap_get((digestmap_t*)routermap,
2483 extrainfo->cache_info.identity_digest))) {
2484 key = router->identity_pkey;
2487 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
2488 if (strcmp(tok->object_type, "SIGNATURE") ||
2489 tok->object_size < 128 || tok->object_size > 512) {
2490 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
2491 goto err;
2494 if (key) {
2495 note_crypto_pk_op(VERIFY_RTR);
2496 if (check_signature_token(digest, DIGEST_LEN, tok, key, 0,
2497 "extra-info") < 0)
2498 goto err;
2500 if (router)
2501 extrainfo->cache_info.send_unencrypted =
2502 router->cache_info.send_unencrypted;
2503 } else {
2504 extrainfo->pending_sig = tor_memdup(tok->object_body,
2505 tok->object_size);
2506 extrainfo->pending_sig_len = tok->object_size;
2509 goto done;
2510 err:
2511 dump_desc(s_dup, "extra-info descriptor");
2512 extrainfo_free(extrainfo);
2513 extrainfo = NULL;
2514 done:
2515 if (tokens) {
2516 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2517 smartlist_free(tokens);
2519 if (area) {
2520 DUMP_AREA(area, "extrainfo");
2521 memarea_drop_all(area);
2523 if (can_dl_again_out)
2524 *can_dl_again_out = can_dl_again;
2525 return extrainfo;
2528 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
2529 * the first character after the certificate. */
2530 authority_cert_t *
2531 authority_cert_parse_from_string(const char *s, const char **end_of_string)
2533 /** Reject any certificate at least this big; it is probably an overflow, an
2534 * attack, a bug, or some other nonsense. */
2535 #define MAX_CERT_SIZE (128*1024)
2537 authority_cert_t *cert = NULL, *old_cert;
2538 smartlist_t *tokens = NULL;
2539 char digest[DIGEST_LEN];
2540 directory_token_t *tok;
2541 char fp_declared[DIGEST_LEN];
2542 char *eos;
2543 size_t len;
2544 int found;
2545 memarea_t *area = NULL;
2546 const char *s_dup = s;
2548 s = eat_whitespace(s);
2549 eos = strstr(s, "\ndir-key-certification");
2550 if (! eos) {
2551 log_warn(LD_DIR, "No signature found on key certificate");
2552 return NULL;
2554 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
2555 if (! eos) {
2556 log_warn(LD_DIR, "No end-of-signature found on key certificate");
2557 return NULL;
2559 eos = strchr(eos+2, '\n');
2560 tor_assert(eos);
2561 ++eos;
2562 len = eos - s;
2564 if (len > MAX_CERT_SIZE) {
2565 log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
2566 "rejecting", (unsigned long)len);
2567 return NULL;
2570 tokens = smartlist_new();
2571 area = memarea_new();
2572 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
2573 log_warn(LD_DIR, "Error tokenizing key certificate");
2574 goto err;
2576 if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
2577 "\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
2578 goto err;
2579 tok = smartlist_get(tokens, 0);
2580 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
2581 log_warn(LD_DIR,
2582 "Key certificate does not begin with a recognized version (3).");
2583 goto err;
2586 cert = tor_malloc_zero(sizeof(authority_cert_t));
2587 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
2589 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2590 tor_assert(tok->key);
2591 cert->signing_key = tok->key;
2592 tok->key = NULL;
2593 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
2594 goto err;
2596 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
2597 tor_assert(tok->key);
2598 cert->identity_key = tok->key;
2599 tok->key = NULL;
2601 tok = find_by_keyword(tokens, K_FINGERPRINT);
2602 tor_assert(tok->n_args);
2603 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
2604 strlen(tok->args[0])) != DIGEST_LEN) {
2605 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
2606 escaped(tok->args[0]));
2607 goto err;
2610 if (crypto_pk_get_digest(cert->identity_key,
2611 cert->cache_info.identity_digest))
2612 goto err;
2614 if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
2615 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
2616 "fingerprint");
2617 goto err;
2620 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
2621 if (tok) {
2622 struct in_addr in;
2623 char *address = NULL;
2624 tor_assert(tok->n_args);
2625 /* XXX++ use some tor_addr parse function below instead. -RD */
2626 if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
2627 &cert->dir_port) < 0 ||
2628 tor_inet_aton(address, &in) == 0) {
2629 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
2630 tor_free(address);
2631 goto err;
2633 cert->addr = ntohl(in.s_addr);
2634 tor_free(address);
2637 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
2638 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
2639 goto err;
2641 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
2642 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
2643 goto err;
2646 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
2647 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
2648 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
2649 goto err;
2652 /* If we already have this cert, don't bother checking the signature. */
2653 old_cert = authority_cert_get_by_digests(
2654 cert->cache_info.identity_digest,
2655 cert->signing_key_digest);
2656 found = 0;
2657 if (old_cert) {
2658 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
2659 * buy us much. */
2660 if (old_cert->cache_info.signed_descriptor_len == len &&
2661 old_cert->cache_info.signed_descriptor_body &&
2662 tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) {
2663 log_debug(LD_DIR, "We already checked the signature on this "
2664 "certificate; no need to do so again.");
2665 found = 1;
2668 if (!found) {
2669 if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0,
2670 "key certificate")) {
2671 goto err;
2674 tok = find_by_keyword(tokens, K_DIR_KEY_CROSSCERT);
2675 if (check_signature_token(cert->cache_info.identity_digest,
2676 DIGEST_LEN,
2677 tok,
2678 cert->signing_key,
2679 CST_NO_CHECK_OBJTYPE,
2680 "key cross-certification")) {
2681 goto err;
2685 cert->cache_info.signed_descriptor_len = len;
2686 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
2687 memcpy(cert->cache_info.signed_descriptor_body, s, len);
2688 cert->cache_info.signed_descriptor_body[len] = 0;
2689 cert->cache_info.saved_location = SAVED_NOWHERE;
2691 if (end_of_string) {
2692 *end_of_string = eat_whitespace(eos);
2694 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2695 smartlist_free(tokens);
2696 if (area) {
2697 DUMP_AREA(area, "authority cert");
2698 memarea_drop_all(area);
2700 return cert;
2701 err:
2702 dump_desc(s_dup, "authority cert");
2703 authority_cert_free(cert);
2704 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2705 smartlist_free(tokens);
2706 if (area) {
2707 DUMP_AREA(area, "authority cert");
2708 memarea_drop_all(area);
2710 return NULL;
2713 /** Helper: given a string <b>s</b>, return the start of the next router-status
2714 * object (starting with "r " at the start of a line). If none is found,
2715 * return the start of the directory footer, or the next directory signature.
2716 * If none is found, return the end of the string. */
2717 static inline const char *
2718 find_start_of_next_routerstatus(const char *s)
2720 const char *eos, *footer, *sig;
2721 if ((eos = strstr(s, "\nr ")))
2722 ++eos;
2723 else
2724 eos = s + strlen(s);
2726 footer = tor_memstr(s, eos-s, "\ndirectory-footer");
2727 sig = tor_memstr(s, eos-s, "\ndirectory-signature");
2729 if (footer && sig)
2730 return MIN(footer, sig) + 1;
2731 else if (footer)
2732 return footer+1;
2733 else if (sig)
2734 return sig+1;
2735 else
2736 return eos;
2739 /** Parse the GuardFraction string from a consensus or vote.
2741 * If <b>vote</b> or <b>vote_rs</b> are set the document getting
2742 * parsed is a vote routerstatus. Otherwise it's a consensus. This is
2743 * the same semantic as in routerstatus_parse_entry_from_string(). */
2744 STATIC int
2745 routerstatus_parse_guardfraction(const char *guardfraction_str,
2746 networkstatus_t *vote,
2747 vote_routerstatus_t *vote_rs,
2748 routerstatus_t *rs)
2750 int ok;
2751 const char *end_of_header = NULL;
2752 int is_consensus = !vote_rs;
2753 uint32_t guardfraction;
2755 tor_assert(bool_eq(vote, vote_rs));
2757 /* If this info comes from a consensus, but we should't apply
2758 guardfraction, just exit. */
2759 if (is_consensus && !should_apply_guardfraction(NULL)) {
2760 return 0;
2763 end_of_header = strchr(guardfraction_str, '=');
2764 if (!end_of_header) {
2765 return -1;
2768 guardfraction = (uint32_t)tor_parse_ulong(end_of_header+1,
2769 10, 0, 100, &ok, NULL);
2770 if (!ok) {
2771 log_warn(LD_DIR, "Invalid GuardFraction %s", escaped(guardfraction_str));
2772 return -1;
2775 log_debug(LD_GENERAL, "[*] Parsed %s guardfraction '%s' for '%s'.",
2776 is_consensus ? "consensus" : "vote",
2777 guardfraction_str, rs->nickname);
2779 if (!is_consensus) { /* We are parsing a vote */
2780 vote_rs->status.guardfraction_percentage = guardfraction;
2781 vote_rs->status.has_guardfraction = 1;
2782 } else {
2783 /* We are parsing a consensus. Only apply guardfraction to guards. */
2784 if (rs->is_possible_guard) {
2785 rs->guardfraction_percentage = guardfraction;
2786 rs->has_guardfraction = 1;
2787 } else {
2788 log_warn(LD_BUG, "Got GuardFraction for non-guard %s. "
2789 "This is not supposed to happen. Not applying. ", rs->nickname);
2793 return 0;
2796 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
2797 * empty smartlist at <b>tokens</b>, parse and return the first router status
2798 * object in the string, and advance *<b>s</b> to just after the end of the
2799 * router status. Return NULL and advance *<b>s</b> on error.
2801 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
2802 * routerstatus but use <b>vote_rs</b> instead.
2804 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
2805 * consensus, and we should parse it according to the method used to
2806 * make that consensus.
2808 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
2810 STATIC routerstatus_t *
2811 routerstatus_parse_entry_from_string(memarea_t *area,
2812 const char **s, smartlist_t *tokens,
2813 networkstatus_t *vote,
2814 vote_routerstatus_t *vote_rs,
2815 int consensus_method,
2816 consensus_flavor_t flav)
2818 const char *eos, *s_dup = *s;
2819 routerstatus_t *rs = NULL;
2820 directory_token_t *tok;
2821 char timebuf[ISO_TIME_LEN+1];
2822 struct in_addr in;
2823 int offset = 0;
2824 tor_assert(tokens);
2825 tor_assert(bool_eq(vote, vote_rs));
2827 if (!consensus_method)
2828 flav = FLAV_NS;
2829 tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
2831 eos = find_start_of_next_routerstatus(*s);
2833 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
2834 log_warn(LD_DIR, "Error tokenizing router status");
2835 goto err;
2837 if (smartlist_len(tokens) < 1) {
2838 log_warn(LD_DIR, "Impossibly short router status");
2839 goto err;
2841 tok = find_by_keyword(tokens, K_R);
2842 tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
2843 if (flav == FLAV_NS) {
2844 if (tok->n_args < 8) {
2845 log_warn(LD_DIR, "Too few arguments to r");
2846 goto err;
2848 } else if (flav == FLAV_MICRODESC) {
2849 offset = -1; /* There is no identity digest */
2852 if (vote_rs) {
2853 rs = &vote_rs->status;
2854 } else {
2855 rs = tor_malloc_zero(sizeof(routerstatus_t));
2858 if (!is_legal_nickname(tok->args[0])) {
2859 log_warn(LD_DIR,
2860 "Invalid nickname %s in router status; skipping.",
2861 escaped(tok->args[0]));
2862 goto err;
2864 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
2866 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
2867 log_warn(LD_DIR, "Error decoding identity digest %s",
2868 escaped(tok->args[1]));
2869 goto err;
2872 if (flav == FLAV_NS) {
2873 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
2874 log_warn(LD_DIR, "Error decoding descriptor digest %s",
2875 escaped(tok->args[2]));
2876 goto err;
2880 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
2881 tok->args[3+offset], tok->args[4+offset]) < 0 ||
2882 parse_iso_time(timebuf, &rs->published_on)<0) {
2883 log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]",
2884 tok->args[3+offset], tok->args[4+offset],
2885 offset, (int)flav);
2886 goto err;
2889 if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
2890 log_warn(LD_DIR, "Error parsing router address in network-status %s",
2891 escaped(tok->args[5+offset]));
2892 goto err;
2894 rs->addr = ntohl(in.s_addr);
2896 rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
2897 10,0,65535,NULL,NULL);
2898 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
2899 10,0,65535,NULL,NULL);
2902 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
2903 if (a_lines) {
2904 find_single_ipv6_orport(a_lines, &rs->ipv6_addr, &rs->ipv6_orport);
2905 smartlist_free(a_lines);
2909 tok = find_opt_by_keyword(tokens, K_S);
2910 if (tok && vote) {
2911 int i;
2912 vote_rs->flags = 0;
2913 for (i=0; i < tok->n_args; ++i) {
2914 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
2915 if (p >= 0) {
2916 vote_rs->flags |= (U64_LITERAL(1)<<p);
2917 } else {
2918 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
2919 escaped(tok->args[i]));
2920 goto err;
2923 } else if (tok) {
2924 /* This is a consensus, not a vote. */
2925 int i;
2926 for (i=0; i < tok->n_args; ++i) {
2927 if (!strcmp(tok->args[i], "Exit"))
2928 rs->is_exit = 1;
2929 else if (!strcmp(tok->args[i], "Stable"))
2930 rs->is_stable = 1;
2931 else if (!strcmp(tok->args[i], "Fast"))
2932 rs->is_fast = 1;
2933 else if (!strcmp(tok->args[i], "Running"))
2934 rs->is_flagged_running = 1;
2935 else if (!strcmp(tok->args[i], "Named"))
2936 rs->is_named = 1;
2937 else if (!strcmp(tok->args[i], "Valid"))
2938 rs->is_valid = 1;
2939 else if (!strcmp(tok->args[i], "Guard"))
2940 rs->is_possible_guard = 1;
2941 else if (!strcmp(tok->args[i], "BadExit"))
2942 rs->is_bad_exit = 1;
2943 else if (!strcmp(tok->args[i], "Authority"))
2944 rs->is_authority = 1;
2945 else if (!strcmp(tok->args[i], "Unnamed") &&
2946 consensus_method >= 2) {
2947 /* Unnamed is computed right by consensus method 2 and later. */
2948 rs->is_unnamed = 1;
2949 } else if (!strcmp(tok->args[i], "HSDir")) {
2950 rs->is_hs_dir = 1;
2951 } else if (!strcmp(tok->args[i], "V2Dir")) {
2952 rs->is_v2_dir = 1;
2955 /* These are implied true by having been included in a consensus made
2956 * with a given method */
2957 rs->is_flagged_running = 1; /* Starting with consensus method 4. */
2958 if (consensus_method >= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES)
2959 rs->is_valid = 1;
2961 int found_protocol_list = 0;
2962 if ((tok = find_opt_by_keyword(tokens, K_PROTO))) {
2963 found_protocol_list = 1;
2964 rs->protocols_known = 1;
2965 rs->supports_extend2_cells =
2966 protocol_list_supports_protocol(tok->args[0], PRT_RELAY, 2);
2968 if ((tok = find_opt_by_keyword(tokens, K_V))) {
2969 tor_assert(tok->n_args == 1);
2970 if (!strcmpstart(tok->args[0], "Tor ") && !found_protocol_list) {
2971 /* We only do version checks like this in the case where
2972 * the version is a "Tor" version, and where there is no
2973 * list of protocol versions that we should be looking at instead. */
2974 rs->supports_extend2_cells =
2975 tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
2976 rs->protocols_known = 1;
2978 if (vote_rs) {
2979 vote_rs->version = tor_strdup(tok->args[0]);
2983 /* handle weighting/bandwidth info */
2984 if ((tok = find_opt_by_keyword(tokens, K_W))) {
2985 int i;
2986 for (i=0; i < tok->n_args; ++i) {
2987 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
2988 int ok;
2989 rs->bandwidth_kb =
2990 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
2991 10, 0, UINT32_MAX,
2992 &ok, NULL);
2993 if (!ok) {
2994 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
2995 goto err;
2997 rs->has_bandwidth = 1;
2998 } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) {
2999 int ok;
3000 vote_rs->measured_bw_kb =
3001 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
3002 10, 0, UINT32_MAX, &ok, NULL);
3003 if (!ok) {
3004 log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
3005 escaped(tok->args[i]));
3006 goto err;
3008 vote_rs->has_measured_bw = 1;
3009 vote->has_measured_bws = 1;
3010 } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
3011 rs->bw_is_unmeasured = 1;
3012 } else if (!strcmpstart(tok->args[i], "GuardFraction=")) {
3013 if (routerstatus_parse_guardfraction(tok->args[i],
3014 vote, vote_rs, rs) < 0) {
3015 goto err;
3021 /* parse exit policy summaries */
3022 if ((tok = find_opt_by_keyword(tokens, K_P))) {
3023 tor_assert(tok->n_args == 1);
3024 if (strcmpstart(tok->args[0], "accept ") &&
3025 strcmpstart(tok->args[0], "reject ")) {
3026 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
3027 escaped(tok->args[0]));
3028 goto err;
3030 /* XXX weasel: parse this into ports and represent them somehow smart,
3031 * maybe not here but somewhere on if we need it for the client.
3032 * we should still parse it here to check it's valid tho.
3034 rs->exitsummary = tor_strdup(tok->args[0]);
3035 rs->has_exitsummary = 1;
3038 if (vote_rs) {
3039 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) {
3040 if (t->tp == K_M && t->n_args) {
3041 vote_microdesc_hash_t *line =
3042 tor_malloc(sizeof(vote_microdesc_hash_t));
3043 line->next = vote_rs->microdesc;
3044 line->microdesc_hash_line = tor_strdup(t->args[0]);
3045 vote_rs->microdesc = line;
3047 if (t->tp == K_ID) {
3048 tor_assert(t->n_args >= 2);
3049 if (!strcmp(t->args[0], "ed25519")) {
3050 vote_rs->has_ed25519_listing = 1;
3051 if (strcmp(t->args[1], "none") &&
3052 digest256_from_base64((char*)vote_rs->ed25519_id,
3053 t->args[1])<0) {
3054 log_warn(LD_DIR, "Bogus ed25519 key in networkstatus vote");
3055 goto err;
3059 if (t->tp == K_PROTO) {
3060 tor_assert(t->n_args == 1);
3061 vote_rs->protocols = tor_strdup(t->args[0]);
3063 } SMARTLIST_FOREACH_END(t);
3064 } else if (flav == FLAV_MICRODESC) {
3065 tok = find_opt_by_keyword(tokens, K_M);
3066 if (tok) {
3067 tor_assert(tok->n_args);
3068 if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
3069 log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
3070 escaped(tok->args[0]));
3071 goto err;
3073 } else {
3074 log_info(LD_BUG, "Found an entry in networkstatus with no "
3075 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
3076 rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
3077 fmt_addr32(rs->addr), rs->or_port);
3081 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
3082 rs->is_named = 0;
3084 goto done;
3085 err:
3086 dump_desc(s_dup, "routerstatus entry");
3087 if (rs && !vote_rs)
3088 routerstatus_free(rs);
3089 rs = NULL;
3090 done:
3091 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3092 smartlist_clear(tokens);
3093 if (area) {
3094 DUMP_AREA(area, "routerstatus entry");
3095 memarea_clear(area);
3097 *s = eos;
3099 return rs;
3103 compare_vote_routerstatus_entries(const void **_a, const void **_b)
3105 const vote_routerstatus_t *a = *_a, *b = *_b;
3106 return fast_memcmp(a->status.identity_digest, b->status.identity_digest,
3107 DIGEST_LEN);
3110 /** Verify the bandwidth weights of a network status document */
3112 networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
3114 int64_t weight_scale;
3115 int64_t G=0, M=0, E=0, D=0, T=0;
3116 double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
3117 double Gtotal=0, Mtotal=0, Etotal=0;
3118 const char *casename = NULL;
3119 int valid = 1;
3120 (void) consensus_method;
3122 weight_scale = networkstatus_get_weight_scale_param(ns);
3123 Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1);
3124 Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1);
3125 Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1);
3126 Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1);
3127 Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1);
3128 Wme = networkstatus_get_bw_weight(ns, "Wme", -1);
3129 Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1);
3130 Weg = networkstatus_get_bw_weight(ns, "Weg", -1);
3131 Wem = networkstatus_get_bw_weight(ns, "Wem", -1);
3132 Wee = networkstatus_get_bw_weight(ns, "Wee", -1);
3133 Wed = networkstatus_get_bw_weight(ns, "Wed", -1);
3135 if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
3136 || Wem<0 || Wee<0 || Wed<0) {
3137 log_warn(LD_BUG, "No bandwidth weights produced in consensus!");
3138 return 0;
3141 // First, sanity check basic summing properties that hold for all cases
3142 // We use > 1 as the check for these because they are computed as integers.
3143 // Sometimes there are rounding errors.
3144 if (fabs(Wmm - weight_scale) > 1) {
3145 log_warn(LD_BUG, "Wmm=%f != "I64_FORMAT,
3146 Wmm, I64_PRINTF_ARG(weight_scale));
3147 valid = 0;
3150 if (fabs(Wem - Wee) > 1) {
3151 log_warn(LD_BUG, "Wem=%f != Wee=%f", Wem, Wee);
3152 valid = 0;
3155 if (fabs(Wgm - Wgg) > 1) {
3156 log_warn(LD_BUG, "Wgm=%f != Wgg=%f", Wgm, Wgg);
3157 valid = 0;
3160 if (fabs(Weg - Wed) > 1) {
3161 log_warn(LD_BUG, "Wed=%f != Weg=%f", Wed, Weg);
3162 valid = 0;
3165 if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
3166 log_warn(LD_BUG, "Wgg=%f != "I64_FORMAT" - Wmg=%f", Wgg,
3167 I64_PRINTF_ARG(weight_scale), Wmg);
3168 valid = 0;
3171 if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
3172 log_warn(LD_BUG, "Wee=%f != "I64_FORMAT" - Wme=%f", Wee,
3173 I64_PRINTF_ARG(weight_scale), Wme);
3174 valid = 0;
3177 if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
3178 log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT,
3179 Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
3180 valid = 0;
3183 Wgg /= weight_scale;
3184 Wgm /= weight_scale;
3185 Wgd /= weight_scale;
3187 Wmg /= weight_scale;
3188 Wmm /= weight_scale;
3189 Wme /= weight_scale;
3190 Wmd /= weight_scale;
3192 Weg /= weight_scale;
3193 Wem /= weight_scale;
3194 Wee /= weight_scale;
3195 Wed /= weight_scale;
3197 // Then, gather G, M, E, D, T to determine case
3198 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
3199 int is_exit = 0;
3200 /* Bug #2203: Don't count bad exits as exits for balancing */
3201 is_exit = rs->is_exit && !rs->is_bad_exit;
3202 if (rs->has_bandwidth) {
3203 T += rs->bandwidth_kb;
3204 if (is_exit && rs->is_possible_guard) {
3205 D += rs->bandwidth_kb;
3206 Gtotal += Wgd*rs->bandwidth_kb;
3207 Mtotal += Wmd*rs->bandwidth_kb;
3208 Etotal += Wed*rs->bandwidth_kb;
3209 } else if (is_exit) {
3210 E += rs->bandwidth_kb;
3211 Mtotal += Wme*rs->bandwidth_kb;
3212 Etotal += Wee*rs->bandwidth_kb;
3213 } else if (rs->is_possible_guard) {
3214 G += rs->bandwidth_kb;
3215 Gtotal += Wgg*rs->bandwidth_kb;
3216 Mtotal += Wmg*rs->bandwidth_kb;
3217 } else {
3218 M += rs->bandwidth_kb;
3219 Mtotal += Wmm*rs->bandwidth_kb;
3221 } else {
3222 log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
3223 routerstatus_describe(rs));
3225 } SMARTLIST_FOREACH_END(rs);
3227 // Finally, check equality conditions depending upon case 1, 2 or 3
3228 // Full equality cases: 1, 3b
3229 // Partial equality cases: 2b (E=G), 3a (M=E)
3230 // Fully unknown: 2a
3231 if (3*E >= T && 3*G >= T) {
3232 // Case 1: Neither are scarce
3233 casename = "Case 1";
3234 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
3235 log_warn(LD_DIR,
3236 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3237 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3238 " T="I64_FORMAT". "
3239 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3240 casename, Etotal, Mtotal,
3241 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3242 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3243 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3244 valid = 0;
3246 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
3247 log_warn(LD_DIR,
3248 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3249 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3250 " T="I64_FORMAT". "
3251 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3252 casename, Etotal, Gtotal,
3253 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3254 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3255 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3256 valid = 0;
3258 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
3259 log_warn(LD_DIR,
3260 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3261 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3262 " T="I64_FORMAT". "
3263 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3264 casename, Mtotal, Gtotal,
3265 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3266 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3267 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3268 valid = 0;
3270 } else if (3*E < T && 3*G < T) {
3271 int64_t R = MIN(E, G);
3272 int64_t S = MAX(E, G);
3274 * Case 2: Both Guards and Exits are scarce
3275 * Balance D between E and G, depending upon
3276 * D capacity and scarcity. Devote no extra
3277 * bandwidth to middle nodes.
3279 if (R+D < S) { // Subcase a
3280 double Rtotal, Stotal;
3281 if (E < G) {
3282 Rtotal = Etotal;
3283 Stotal = Gtotal;
3284 } else {
3285 Rtotal = Gtotal;
3286 Stotal = Etotal;
3288 casename = "Case 2a";
3289 // Rtotal < Stotal
3290 if (Rtotal > Stotal) {
3291 log_warn(LD_DIR,
3292 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
3293 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3294 " T="I64_FORMAT". "
3295 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3296 casename, Rtotal, Stotal,
3297 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3298 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3299 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3300 valid = 0;
3302 // Rtotal < T/3
3303 if (3*Rtotal > T) {
3304 log_warn(LD_DIR,
3305 "Bw Weight Failure for %s: 3*Rtotal %f > T "
3306 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
3307 " D="I64_FORMAT" T="I64_FORMAT". "
3308 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3309 casename, Rtotal*3, I64_PRINTF_ARG(T),
3310 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3311 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3312 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3313 valid = 0;
3315 // Stotal < T/3
3316 if (3*Stotal > T) {
3317 log_warn(LD_DIR,
3318 "Bw Weight Failure for %s: 3*Stotal %f > T "
3319 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
3320 " D="I64_FORMAT" T="I64_FORMAT". "
3321 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3322 casename, Stotal*3, I64_PRINTF_ARG(T),
3323 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3324 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3325 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3326 valid = 0;
3328 // Mtotal > T/3
3329 if (3*Mtotal < T) {
3330 log_warn(LD_DIR,
3331 "Bw Weight Failure for %s: 3*Mtotal %f < T "
3332 I64_FORMAT". "
3333 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3334 " T="I64_FORMAT". "
3335 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3336 casename, Mtotal*3, I64_PRINTF_ARG(T),
3337 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3338 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3339 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3340 valid = 0;
3342 } else { // Subcase b: R+D > S
3343 casename = "Case 2b";
3345 /* Check the rare-M redirect case. */
3346 if (D != 0 && 3*M < T) {
3347 casename = "Case 2b (balanced)";
3348 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
3349 log_warn(LD_DIR,
3350 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3351 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3352 " T="I64_FORMAT". "
3353 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3354 casename, Etotal, Mtotal,
3355 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3356 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3357 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3358 valid = 0;
3360 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
3361 log_warn(LD_DIR,
3362 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3363 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3364 " T="I64_FORMAT". "
3365 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3366 casename, Etotal, Gtotal,
3367 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3368 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3369 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3370 valid = 0;
3372 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
3373 log_warn(LD_DIR,
3374 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3375 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3376 " T="I64_FORMAT". "
3377 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3378 casename, Mtotal, Gtotal,
3379 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3380 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3381 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3382 valid = 0;
3384 } else {
3385 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
3386 log_warn(LD_DIR,
3387 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3388 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3389 " T="I64_FORMAT". "
3390 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3391 casename, Etotal, Gtotal,
3392 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3393 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3394 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3395 valid = 0;
3399 } else { // if (E < T/3 || G < T/3) {
3400 int64_t S = MIN(E, G);
3401 int64_t NS = MAX(E, G);
3402 if (3*(S+D) < T) { // Subcase a:
3403 double Stotal;
3404 double NStotal;
3405 if (G < E) {
3406 casename = "Case 3a (G scarce)";
3407 Stotal = Gtotal;
3408 NStotal = Etotal;
3409 } else { // if (G >= E) {
3410 casename = "Case 3a (E scarce)";
3411 NStotal = Gtotal;
3412 Stotal = Etotal;
3414 // Stotal < T/3
3415 if (3*Stotal > T) {
3416 log_warn(LD_DIR,
3417 "Bw Weight Failure for %s: 3*Stotal %f > T "
3418 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
3419 " D="I64_FORMAT" T="I64_FORMAT". "
3420 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3421 casename, Stotal*3, I64_PRINTF_ARG(T),
3422 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3423 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3424 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3425 valid = 0;
3427 if (NS >= M) {
3428 if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
3429 log_warn(LD_DIR,
3430 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
3431 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3432 " T="I64_FORMAT". "
3433 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3434 casename, NStotal, Mtotal,
3435 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3436 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3437 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3438 valid = 0;
3440 } else {
3441 // if NS < M, NStotal > T/3 because only one of G or E is scarce
3442 if (3*NStotal < T) {
3443 log_warn(LD_DIR,
3444 "Bw Weight Failure for %s: 3*NStotal %f < T "
3445 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
3446 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
3447 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3448 casename, NStotal*3, I64_PRINTF_ARG(T),
3449 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3450 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3451 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3452 valid = 0;
3455 } else { // Subcase b: S+D >= T/3
3456 casename = "Case 3b";
3457 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
3458 log_warn(LD_DIR,
3459 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3460 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3461 " T="I64_FORMAT". "
3462 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3463 casename, Etotal, Mtotal,
3464 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3465 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3466 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3467 valid = 0;
3469 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
3470 log_warn(LD_DIR,
3471 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3472 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3473 " T="I64_FORMAT". "
3474 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3475 casename, Etotal, Gtotal,
3476 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3477 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3478 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3479 valid = 0;
3481 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
3482 log_warn(LD_DIR,
3483 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3484 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
3485 " T="I64_FORMAT". "
3486 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3487 casename, Mtotal, Gtotal,
3488 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
3489 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
3490 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
3491 valid = 0;
3496 if (valid)
3497 log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.",
3498 casename);
3500 return valid;
3503 /** Parse and extract all SR commits from <b>tokens</b> and place them in
3504 * <b>ns</b>. */
3505 static void
3506 extract_shared_random_commits(networkstatus_t *ns, smartlist_t *tokens)
3508 smartlist_t *chunks = NULL;
3510 tor_assert(ns);
3511 tor_assert(tokens);
3512 /* Commits are only present in a vote. */
3513 tor_assert(ns->type == NS_TYPE_VOTE);
3515 ns->sr_info.commits = smartlist_new();
3517 smartlist_t *commits = find_all_by_keyword(tokens, K_COMMIT);
3518 /* It's normal that a vote might contain no commits even if it participates
3519 * in the SR protocol. Don't treat it as an error. */
3520 if (commits == NULL) {
3521 goto end;
3524 /* Parse the commit. We do NO validation of number of arguments or ordering
3525 * for forward compatibility, it's the parse commit job to inform us if it's
3526 * supported or not. */
3527 chunks = smartlist_new();
3528 SMARTLIST_FOREACH_BEGIN(commits, directory_token_t *, tok) {
3529 /* Extract all arguments and put them in the chunks list. */
3530 for (int i = 0; i < tok->n_args; i++) {
3531 smartlist_add(chunks, tok->args[i]);
3533 sr_commit_t *commit = sr_parse_commit(chunks);
3534 smartlist_clear(chunks);
3535 if (commit == NULL) {
3536 /* Get voter identity so we can warn that this dirauth vote contains
3537 * commit we can't parse. */
3538 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
3539 tor_assert(voter);
3540 log_warn(LD_DIR, "SR: Unable to parse commit %s from vote of voter %s.",
3541 escaped(tok->object_body),
3542 hex_str(voter->identity_digest,
3543 sizeof(voter->identity_digest)));
3544 /* Commitment couldn't be parsed. Continue onto the next commit because
3545 * this one could be unsupported for instance. */
3546 continue;
3548 /* Add newly created commit object to the vote. */
3549 smartlist_add(ns->sr_info.commits, commit);
3550 } SMARTLIST_FOREACH_END(tok);
3552 end:
3553 smartlist_free(chunks);
3554 smartlist_free(commits);
3557 /** Check if a shared random value of type <b>srv_type</b> is in
3558 * <b>tokens</b>. If there is, parse it and set it to <b>srv_out</b>. Return
3559 * -1 on failure, 0 on success. The resulting srv is allocated on the heap and
3560 * it's the responsibility of the caller to free it. */
3561 static int
3562 extract_one_srv(smartlist_t *tokens, directory_keyword srv_type,
3563 sr_srv_t **srv_out)
3565 int ret = -1;
3566 directory_token_t *tok;
3567 sr_srv_t *srv = NULL;
3568 smartlist_t *chunks;
3570 tor_assert(tokens);
3572 chunks = smartlist_new();
3573 tok = find_opt_by_keyword(tokens, srv_type);
3574 if (!tok) {
3575 /* That's fine, no SRV is allowed. */
3576 ret = 0;
3577 goto end;
3579 for (int i = 0; i < tok->n_args; i++) {
3580 smartlist_add(chunks, tok->args[i]);
3582 srv = sr_parse_srv(chunks);
3583 if (srv == NULL) {
3584 log_warn(LD_DIR, "SR: Unparseable SRV %s", escaped(tok->object_body));
3585 goto end;
3587 /* All is good. */
3588 *srv_out = srv;
3589 ret = 0;
3590 end:
3591 smartlist_free(chunks);
3592 return ret;
3595 /** Extract any shared random values found in <b>tokens</b> and place them in
3596 * the networkstatus <b>ns</b>. */
3597 static void
3598 extract_shared_random_srvs(networkstatus_t *ns, smartlist_t *tokens)
3600 const char *voter_identity;
3601 networkstatus_voter_info_t *voter;
3603 tor_assert(ns);
3604 tor_assert(tokens);
3605 /* Can be only one of them else code flow. */
3606 tor_assert(ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_CONSENSUS);
3608 if (ns->type == NS_TYPE_VOTE) {
3609 voter = smartlist_get(ns->voters, 0);
3610 tor_assert(voter);
3611 voter_identity = hex_str(voter->identity_digest,
3612 sizeof(voter->identity_digest));
3613 } else {
3614 /* Consensus has multiple voters so no specific voter. */
3615 voter_identity = "consensus";
3618 /* We extract both and on error, everything is stopped because it means
3619 * the votes is malformed for the shared random value(s). */
3620 if (extract_one_srv(tokens, K_PREVIOUS_SRV, &ns->sr_info.previous_srv) < 0) {
3621 log_warn(LD_DIR, "SR: Unable to parse previous SRV from %s",
3622 voter_identity);
3623 /* Maybe we have a chance with the current SRV so let's try it anyway. */
3625 if (extract_one_srv(tokens, K_CURRENT_SRV, &ns->sr_info.current_srv) < 0) {
3626 log_warn(LD_DIR, "SR: Unable to parse current SRV from %s",
3627 voter_identity);
3631 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
3632 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
3633 networkstatus_t *
3634 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
3635 networkstatus_type_t ns_type)
3637 smartlist_t *tokens = smartlist_new();
3638 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
3639 networkstatus_voter_info_t *voter = NULL;
3640 networkstatus_t *ns = NULL;
3641 common_digests_t ns_digests;
3642 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
3643 directory_token_t *tok;
3644 struct in_addr in;
3645 int i, inorder, n_signatures = 0;
3646 memarea_t *area = NULL, *rs_area = NULL;
3647 consensus_flavor_t flav = FLAV_NS;
3648 char *last_kwd=NULL;
3650 tor_assert(s);
3652 if (eos_out)
3653 *eos_out = NULL;
3655 if (router_get_networkstatus_v3_hashes(s, &ns_digests)) {
3656 log_warn(LD_DIR, "Unable to compute digest of network-status");
3657 goto err;
3660 area = memarea_new();
3661 end_of_header = find_start_of_next_routerstatus(s);
3662 if (tokenize_string(area, s, end_of_header, tokens,
3663 (ns_type == NS_TYPE_CONSENSUS) ?
3664 networkstatus_consensus_token_table :
3665 networkstatus_token_table, 0)) {
3666 log_warn(LD_DIR, "Error tokenizing network-status header");
3667 goto err;
3670 ns = tor_malloc_zero(sizeof(networkstatus_t));
3671 memcpy(&ns->digests, &ns_digests, sizeof(ns_digests));
3673 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
3674 tor_assert(tok);
3675 if (tok->n_args > 1) {
3676 int flavor = networkstatus_parse_flavor_name(tok->args[1]);
3677 if (flavor < 0) {
3678 log_warn(LD_DIR, "Can't parse document with unknown flavor %s",
3679 escaped(tok->args[1]));
3680 goto err;
3682 ns->flavor = flav = flavor;
3684 if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
3685 log_warn(LD_DIR, "Flavor found on non-consensus networkstatus.");
3686 goto err;
3689 if (ns_type != NS_TYPE_CONSENSUS) {
3690 const char *end_of_cert = NULL;
3691 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
3692 goto err;
3693 ++cert;
3694 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
3695 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
3696 goto err;
3699 tok = find_by_keyword(tokens, K_VOTE_STATUS);
3700 tor_assert(tok->n_args);
3701 if (!strcmp(tok->args[0], "vote")) {
3702 ns->type = NS_TYPE_VOTE;
3703 } else if (!strcmp(tok->args[0], "consensus")) {
3704 ns->type = NS_TYPE_CONSENSUS;
3705 } else if (!strcmp(tok->args[0], "opinion")) {
3706 ns->type = NS_TYPE_OPINION;
3707 } else {
3708 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
3709 escaped(tok->args[0]));
3710 goto err;
3712 if (ns_type != ns->type) {
3713 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
3714 goto err;
3717 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
3718 tok = find_by_keyword(tokens, K_PUBLISHED);
3719 if (parse_iso_time(tok->args[0], &ns->published))
3720 goto err;
3722 ns->supported_methods = smartlist_new();
3723 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
3724 if (tok) {
3725 for (i=0; i < tok->n_args; ++i)
3726 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
3727 } else {
3728 smartlist_add(ns->supported_methods, tor_strdup("1"));
3730 } else {
3731 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
3732 if (tok) {
3733 int num_ok;
3734 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
3735 &num_ok, NULL);
3736 if (!num_ok)
3737 goto err;
3738 } else {
3739 ns->consensus_method = 1;
3743 if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_CLIENT_PROTOCOLS)))
3744 ns->recommended_client_protocols = tor_strdup(tok->args[0]);
3745 if ((tok = find_opt_by_keyword(tokens, K_RECOMMENDED_RELAY_PROTOCOLS)))
3746 ns->recommended_relay_protocols = tor_strdup(tok->args[0]);
3747 if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_CLIENT_PROTOCOLS)))
3748 ns->required_client_protocols = tor_strdup(tok->args[0]);
3749 if ((tok = find_opt_by_keyword(tokens, K_REQUIRED_RELAY_PROTOCOLS)))
3750 ns->required_relay_protocols = tor_strdup(tok->args[0]);
3752 tok = find_by_keyword(tokens, K_VALID_AFTER);
3753 if (parse_iso_time(tok->args[0], &ns->valid_after))
3754 goto err;
3756 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
3757 if (parse_iso_time(tok->args[0], &ns->fresh_until))
3758 goto err;
3760 tok = find_by_keyword(tokens, K_VALID_UNTIL);
3761 if (parse_iso_time(tok->args[0], &ns->valid_until))
3762 goto err;
3764 tok = find_by_keyword(tokens, K_VOTING_DELAY);
3765 tor_assert(tok->n_args >= 2);
3767 int ok;
3768 ns->vote_seconds =
3769 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
3770 if (!ok)
3771 goto err;
3772 ns->dist_seconds =
3773 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
3774 if (!ok)
3775 goto err;
3777 if (ns->valid_after +
3778 (get_options()->TestingTorNetwork ?
3779 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) > ns->fresh_until) {
3780 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
3781 goto err;
3783 if (ns->valid_after +
3784 (get_options()->TestingTorNetwork ?
3785 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL)*2 > ns->valid_until) {
3786 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
3787 goto err;
3789 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
3790 log_warn(LD_DIR, "Vote seconds is too short");
3791 goto err;
3793 if (ns->dist_seconds < MIN_DIST_SECONDS) {
3794 log_warn(LD_DIR, "Dist seconds is too short");
3795 goto err;
3798 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
3799 ns->client_versions = tor_strdup(tok->args[0]);
3801 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
3802 ns->server_versions = tor_strdup(tok->args[0]);
3806 smartlist_t *package_lst = find_all_by_keyword(tokens, K_PACKAGE);
3807 ns->package_lines = smartlist_new();
3808 if (package_lst) {
3809 SMARTLIST_FOREACH(package_lst, directory_token_t *, t,
3810 smartlist_add(ns->package_lines, tor_strdup(t->args[0])));
3812 smartlist_free(package_lst);
3815 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
3816 ns->known_flags = smartlist_new();
3817 inorder = 1;
3818 for (i = 0; i < tok->n_args; ++i) {
3819 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
3820 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
3821 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
3822 inorder = 0;
3825 if (!inorder) {
3826 log_warn(LD_DIR, "known-flags not in order");
3827 goto err;
3829 if (ns->type != NS_TYPE_CONSENSUS &&
3830 smartlist_len(ns->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
3831 /* If we allowed more than 64 flags in votes, then parsing them would make
3832 * us invoke undefined behavior whenever we used 1<<flagnum to do a
3833 * bit-shift. This is only for votes and opinions: consensus users don't
3834 * care about flags they don't recognize, and so don't build a bitfield
3835 * for them. */
3836 log_warn(LD_DIR, "Too many known-flags in consensus vote or opinion");
3837 goto err;
3840 tok = find_opt_by_keyword(tokens, K_PARAMS);
3841 if (tok) {
3842 int any_dups = 0;
3843 inorder = 1;
3844 ns->net_params = smartlist_new();
3845 for (i = 0; i < tok->n_args; ++i) {
3846 int ok=0;
3847 char *eq = strchr(tok->args[i], '=');
3848 size_t eq_pos;
3849 if (!eq) {
3850 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3851 goto err;
3853 eq_pos = eq-tok->args[i];
3854 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
3855 if (!ok) {
3856 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3857 goto err;
3859 if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
3860 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
3861 inorder = 0;
3863 if (last_kwd && eq_pos == strlen(last_kwd) &&
3864 fast_memeq(last_kwd, tok->args[i], eq_pos)) {
3865 log_warn(LD_DIR, "Duplicate value for %s parameter",
3866 escaped(tok->args[i]));
3867 any_dups = 1;
3869 tor_free(last_kwd);
3870 last_kwd = tor_strndup(tok->args[i], eq_pos);
3871 smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
3873 if (!inorder) {
3874 log_warn(LD_DIR, "params not in order");
3875 goto err;
3877 if (any_dups) {
3878 log_warn(LD_DIR, "Duplicate in parameters");
3879 goto err;
3883 ns->voters = smartlist_new();
3885 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3886 tok = _tok;
3887 if (tok->tp == K_DIR_SOURCE) {
3888 tor_assert(tok->n_args >= 6);
3890 if (voter)
3891 smartlist_add(ns->voters, voter);
3892 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
3893 voter->sigs = smartlist_new();
3894 if (ns->type != NS_TYPE_CONSENSUS)
3895 memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN);
3897 voter->nickname = tor_strdup(tok->args[0]);
3898 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
3899 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
3900 tok->args[1], HEX_DIGEST_LEN)
3901 != sizeof(voter->identity_digest)) {
3902 log_warn(LD_DIR, "Error decoding identity digest %s in "
3903 "network-status document.", escaped(tok->args[1]));
3904 goto err;
3906 if (ns->type != NS_TYPE_CONSENSUS &&
3907 tor_memneq(ns->cert->cache_info.identity_digest,
3908 voter->identity_digest, DIGEST_LEN)) {
3909 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
3910 goto err;
3912 if (ns->type != NS_TYPE_CONSENSUS) {
3913 if (authority_cert_is_blacklisted(ns->cert)) {
3914 log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
3915 "signing key %s",
3916 hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
3917 goto err;
3920 voter->address = tor_strdup(tok->args[2]);
3921 if (!tor_inet_aton(tok->args[3], &in)) {
3922 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
3923 escaped(tok->args[3]));
3924 goto err;
3926 voter->addr = ntohl(in.s_addr);
3927 int ok;
3928 voter->dir_port = (uint16_t)
3929 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
3930 if (!ok)
3931 goto err;
3932 voter->or_port = (uint16_t)
3933 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
3934 if (!ok)
3935 goto err;
3936 } else if (tok->tp == K_CONTACT) {
3937 if (!voter || voter->contact) {
3938 log_warn(LD_DIR, "contact element is out of place.");
3939 goto err;
3941 voter->contact = tor_strdup(tok->args[0]);
3942 } else if (tok->tp == K_VOTE_DIGEST) {
3943 tor_assert(ns->type == NS_TYPE_CONSENSUS);
3944 tor_assert(tok->n_args >= 1);
3945 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
3946 log_warn(LD_DIR, "vote-digest element is out of place.");
3947 goto err;
3949 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
3950 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
3951 tok->args[0], HEX_DIGEST_LEN)
3952 != sizeof(voter->vote_digest)) {
3953 log_warn(LD_DIR, "Error decoding vote digest %s in "
3954 "network-status consensus.", escaped(tok->args[0]));
3955 goto err;
3958 } SMARTLIST_FOREACH_END(_tok);
3959 if (voter) {
3960 smartlist_add(ns->voters, voter);
3961 voter = NULL;
3963 if (smartlist_len(ns->voters) == 0) {
3964 log_warn(LD_DIR, "Missing dir-source elements in a networkstatus.");
3965 goto err;
3966 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
3967 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
3968 goto err;
3971 if (ns->type != NS_TYPE_CONSENSUS &&
3972 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
3973 int bad = 1;
3974 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
3975 networkstatus_voter_info_t *voter_0 = smartlist_get(ns->voters, 0);
3976 if (base16_decode(voter_0->legacy_id_digest, DIGEST_LEN,
3977 tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN)
3978 bad = 1;
3979 else
3980 bad = 0;
3982 if (bad) {
3983 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
3984 escaped(tok->args[0]));
3988 /* If this is a vote document, check if information about the shared
3989 randomness protocol is included, and extract it. */
3990 if (ns->type == NS_TYPE_VOTE) {
3991 /* Does this authority participates in the SR protocol? */
3992 tok = find_opt_by_keyword(tokens, K_SR_FLAG);
3993 if (tok) {
3994 ns->sr_info.participate = 1;
3995 /* Get the SR commitments and reveals from the vote. */
3996 extract_shared_random_commits(ns, tokens);
3999 /* For both a vote and consensus, extract the shared random values. */
4000 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_CONSENSUS) {
4001 extract_shared_random_srvs(ns, tokens);
4004 /* Parse routerstatus lines. */
4005 rs_tokens = smartlist_new();
4006 rs_area = memarea_new();
4007 s = end_of_header;
4008 ns->routerstatus_list = smartlist_new();
4010 while (!strcmpstart(s, "r ")) {
4011 if (ns->type != NS_TYPE_CONSENSUS) {
4012 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
4013 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
4014 rs, 0, 0))
4015 smartlist_add(ns->routerstatus_list, rs);
4016 else {
4017 tor_free(rs->version);
4018 tor_free(rs);
4020 } else {
4021 routerstatus_t *rs;
4022 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
4023 NULL, NULL,
4024 ns->consensus_method,
4025 flav))) {
4026 /* Use exponential-backoff scheduling when downloading microdescs */
4027 rs->dl_status.backoff = DL_SCHED_RANDOM_EXPONENTIAL;
4028 smartlist_add(ns->routerstatus_list, rs);
4032 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
4033 routerstatus_t *rs1, *rs2;
4034 if (ns->type != NS_TYPE_CONSENSUS) {
4035 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
4036 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
4037 rs1 = &a->status; rs2 = &b->status;
4038 } else {
4039 rs1 = smartlist_get(ns->routerstatus_list, i-1);
4040 rs2 = smartlist_get(ns->routerstatus_list, i);
4042 if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
4043 >= 0) {
4044 log_warn(LD_DIR, "Networkstatus entries not sorted by identity digest");
4045 goto err;
4048 if (ns_type != NS_TYPE_CONSENSUS) {
4049 digest256map_t *ed_id_map = digest256map_new();
4050 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, vote_routerstatus_t *,
4051 vrs) {
4052 if (! vrs->has_ed25519_listing ||
4053 tor_mem_is_zero((const char *)vrs->ed25519_id, DIGEST256_LEN))
4054 continue;
4055 if (digest256map_get(ed_id_map, vrs->ed25519_id) != NULL) {
4056 log_warn(LD_DIR, "Vote networkstatus ed25519 identities were not "
4057 "unique");
4058 digest256map_free(ed_id_map, NULL);
4059 goto err;
4061 digest256map_set(ed_id_map, vrs->ed25519_id, (void*)1);
4062 } SMARTLIST_FOREACH_END(vrs);
4063 digest256map_free(ed_id_map, NULL);
4066 /* Parse footer; check signature. */
4067 footer_tokens = smartlist_new();
4068 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
4069 ++end_of_footer;
4070 else
4071 end_of_footer = s + strlen(s);
4072 if (tokenize_string(area,s, end_of_footer, footer_tokens,
4073 networkstatus_vote_footer_token_table, 0)) {
4074 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
4075 goto err;
4079 int found_sig = 0;
4080 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
4081 tok = _tok;
4082 if (tok->tp == K_DIRECTORY_SIGNATURE)
4083 found_sig = 1;
4084 else if (found_sig) {
4085 log_warn(LD_DIR, "Extraneous token after first directory-signature");
4086 goto err;
4088 } SMARTLIST_FOREACH_END(_tok);
4091 if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
4092 if (tok != smartlist_get(footer_tokens, 0)) {
4093 log_warn(LD_DIR, "Misplaced directory-footer token");
4094 goto err;
4098 tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
4099 if (tok) {
4100 ns->weight_params = smartlist_new();
4101 for (i = 0; i < tok->n_args; ++i) {
4102 int ok=0;
4103 char *eq = strchr(tok->args[i], '=');
4104 if (!eq) {
4105 log_warn(LD_DIR, "Bad element '%s' in weight params",
4106 escaped(tok->args[i]));
4107 goto err;
4109 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
4110 if (!ok) {
4111 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
4112 goto err;
4114 smartlist_add(ns->weight_params, tor_strdup(tok->args[i]));
4118 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
4119 char declared_identity[DIGEST_LEN];
4120 networkstatus_voter_info_t *v;
4121 document_signature_t *sig;
4122 const char *id_hexdigest = NULL;
4123 const char *sk_hexdigest = NULL;
4124 digest_algorithm_t alg = DIGEST_SHA1;
4125 tok = _tok;
4126 if (tok->tp != K_DIRECTORY_SIGNATURE)
4127 continue;
4128 tor_assert(tok->n_args >= 2);
4129 if (tok->n_args == 2) {
4130 id_hexdigest = tok->args[0];
4131 sk_hexdigest = tok->args[1];
4132 } else {
4133 const char *algname = tok->args[0];
4134 int a;
4135 id_hexdigest = tok->args[1];
4136 sk_hexdigest = tok->args[2];
4137 a = crypto_digest_algorithm_parse_name(algname);
4138 if (a<0) {
4139 log_warn(LD_DIR, "Unknown digest algorithm %s; skipping",
4140 escaped(algname));
4141 continue;
4143 alg = a;
4146 if (!tok->object_type ||
4147 strcmp(tok->object_type, "SIGNATURE") ||
4148 tok->object_size < 128 || tok->object_size > 512) {
4149 log_warn(LD_DIR, "Bad object type or length on directory-signature");
4150 goto err;
4153 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
4154 base16_decode(declared_identity, sizeof(declared_identity),
4155 id_hexdigest, HEX_DIGEST_LEN)
4156 != sizeof(declared_identity)) {
4157 log_warn(LD_DIR, "Error decoding declared identity %s in "
4158 "network-status document.", escaped(id_hexdigest));
4159 goto err;
4161 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
4162 log_warn(LD_DIR, "ID on signature on network-status document does "
4163 "not match any declared directory source.");
4164 goto err;
4166 sig = tor_malloc_zero(sizeof(document_signature_t));
4167 memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN);
4168 sig->alg = alg;
4169 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
4170 base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
4171 sk_hexdigest, HEX_DIGEST_LEN)
4172 != sizeof(sig->signing_key_digest)) {
4173 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
4174 "network-status document.", escaped(sk_hexdigest));
4175 tor_free(sig);
4176 goto err;
4179 if (ns->type != NS_TYPE_CONSENSUS) {
4180 if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest,
4181 DIGEST_LEN)) {
4182 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
4183 "network-status vote.");
4184 tor_free(sig);
4185 goto err;
4189 if (voter_get_sig_by_algorithm(v, sig->alg)) {
4190 /* We already parsed a vote with this algorithm from this voter. Use the
4191 first one. */
4192 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
4193 "that contains two signatures from the same voter with the same "
4194 "algorithm. Ignoring the second signature.");
4195 tor_free(sig);
4196 continue;
4199 if (ns->type != NS_TYPE_CONSENSUS) {
4200 if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
4201 tok, ns->cert->signing_key, 0,
4202 "network-status document")) {
4203 tor_free(sig);
4204 goto err;
4206 sig->good_signature = 1;
4207 } else {
4208 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
4209 tor_free(sig);
4210 goto err;
4212 sig->signature = tor_memdup(tok->object_body, tok->object_size);
4213 sig->signature_len = (int) tok->object_size;
4215 smartlist_add(v->sigs, sig);
4217 ++n_signatures;
4218 } SMARTLIST_FOREACH_END(_tok);
4220 if (! n_signatures) {
4221 log_warn(LD_DIR, "No signatures on networkstatus document.");
4222 goto err;
4223 } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
4224 log_warn(LD_DIR, "Received more than one signature on a "
4225 "network-status vote.");
4226 goto err;
4229 if (eos_out)
4230 *eos_out = end_of_footer;
4232 goto done;
4233 err:
4234 dump_desc(s_dup, "v3 networkstatus");
4235 networkstatus_vote_free(ns);
4236 ns = NULL;
4237 done:
4238 if (tokens) {
4239 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4240 smartlist_free(tokens);
4242 if (voter) {
4243 if (voter->sigs) {
4244 SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
4245 document_signature_free(sig));
4246 smartlist_free(voter->sigs);
4248 tor_free(voter->nickname);
4249 tor_free(voter->address);
4250 tor_free(voter->contact);
4251 tor_free(voter);
4253 if (rs_tokens) {
4254 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t));
4255 smartlist_free(rs_tokens);
4257 if (footer_tokens) {
4258 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
4259 smartlist_free(footer_tokens);
4261 if (area) {
4262 DUMP_AREA(area, "v3 networkstatus");
4263 memarea_drop_all(area);
4265 if (rs_area)
4266 memarea_drop_all(rs_area);
4267 tor_free(last_kwd);
4269 return ns;
4272 /** Return the common_digests_t that holds the digests of the
4273 * <b>flavor_name</b>-flavored networkstatus according to the detached
4274 * signatures document <b>sigs</b>, allocating a new common_digests_t as
4275 * neeeded. */
4276 static common_digests_t *
4277 detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name)
4279 common_digests_t *d = strmap_get(sigs->digests, flavor_name);
4280 if (!d) {
4281 d = tor_malloc_zero(sizeof(common_digests_t));
4282 strmap_set(sigs->digests, flavor_name, d);
4284 return d;
4287 /** Return the list of signatures of the <b>flavor_name</b>-flavored
4288 * networkstatus according to the detached signatures document <b>sigs</b>,
4289 * allocating a new common_digests_t as neeeded. */
4290 static smartlist_t *
4291 detached_get_signatures(ns_detached_signatures_t *sigs,
4292 const char *flavor_name)
4294 smartlist_t *sl = strmap_get(sigs->signatures, flavor_name);
4295 if (!sl) {
4296 sl = smartlist_new();
4297 strmap_set(sigs->signatures, flavor_name, sl);
4299 return sl;
4302 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
4303 * <b>eos</b> and return the result. Return -1 on failure. */
4304 ns_detached_signatures_t *
4305 networkstatus_parse_detached_signatures(const char *s, const char *eos)
4307 /* XXXX there is too much duplicate shared between this function and
4308 * networkstatus_parse_vote_from_string(). */
4309 directory_token_t *tok;
4310 memarea_t *area = NULL;
4311 common_digests_t *digests;
4313 smartlist_t *tokens = smartlist_new();
4314 ns_detached_signatures_t *sigs =
4315 tor_malloc_zero(sizeof(ns_detached_signatures_t));
4316 sigs->digests = strmap_new();
4317 sigs->signatures = strmap_new();
4319 if (!eos)
4320 eos = s + strlen(s);
4322 area = memarea_new();
4323 if (tokenize_string(area,s, eos, tokens,
4324 networkstatus_detached_signature_token_table, 0)) {
4325 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
4326 goto err;
4329 /* Grab all the digest-like tokens. */
4330 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
4331 const char *algname;
4332 digest_algorithm_t alg;
4333 const char *flavor;
4334 const char *hexdigest;
4335 size_t expected_length, digest_length;
4337 tok = _tok;
4339 if (tok->tp == K_CONSENSUS_DIGEST) {
4340 algname = "sha1";
4341 alg = DIGEST_SHA1;
4342 flavor = "ns";
4343 hexdigest = tok->args[0];
4344 } else if (tok->tp == K_ADDITIONAL_DIGEST) {
4345 int a = crypto_digest_algorithm_parse_name(tok->args[1]);
4346 if (a<0) {
4347 log_warn(LD_DIR, "Unrecognized algorithm name %s", tok->args[0]);
4348 continue;
4350 alg = (digest_algorithm_t) a;
4351 flavor = tok->args[0];
4352 algname = tok->args[1];
4353 hexdigest = tok->args[2];
4354 } else {
4355 continue;
4358 digest_length = crypto_digest_algorithm_get_length(alg);
4359 expected_length = digest_length * 2; /* hex encoding */
4361 if (strlen(hexdigest) != expected_length) {
4362 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
4363 "networkstatus signatures");
4364 goto err;
4366 digests = detached_get_digests(sigs, flavor);
4367 tor_assert(digests);
4368 if (!tor_mem_is_zero(digests->d[alg], digest_length)) {
4369 log_warn(LD_DIR, "Multiple digests for %s with %s on detached "
4370 "signatures document", flavor, algname);
4371 continue;
4373 if (base16_decode(digests->d[alg], digest_length,
4374 hexdigest, strlen(hexdigest)) != (int) digest_length) {
4375 log_warn(LD_DIR, "Bad encoding on consensus-digest in detached "
4376 "networkstatus signatures");
4377 goto err;
4379 } SMARTLIST_FOREACH_END(_tok);
4381 tok = find_by_keyword(tokens, K_VALID_AFTER);
4382 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
4383 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
4384 goto err;
4387 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
4388 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
4389 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
4390 goto err;
4393 tok = find_by_keyword(tokens, K_VALID_UNTIL);
4394 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
4395 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
4396 goto err;
4399 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
4400 const char *id_hexdigest;
4401 const char *sk_hexdigest;
4402 const char *algname;
4403 const char *flavor;
4404 digest_algorithm_t alg;
4406 char id_digest[DIGEST_LEN];
4407 char sk_digest[DIGEST_LEN];
4408 smartlist_t *siglist;
4409 document_signature_t *sig;
4410 int is_duplicate;
4412 tok = _tok;
4413 if (tok->tp == K_DIRECTORY_SIGNATURE) {
4414 tor_assert(tok->n_args >= 2);
4415 flavor = "ns";
4416 algname = "sha1";
4417 id_hexdigest = tok->args[0];
4418 sk_hexdigest = tok->args[1];
4419 } else if (tok->tp == K_ADDITIONAL_SIGNATURE) {
4420 tor_assert(tok->n_args >= 4);
4421 flavor = tok->args[0];
4422 algname = tok->args[1];
4423 id_hexdigest = tok->args[2];
4424 sk_hexdigest = tok->args[3];
4425 } else {
4426 continue;
4430 int a = crypto_digest_algorithm_parse_name(algname);
4431 if (a<0) {
4432 log_warn(LD_DIR, "Unrecognized algorithm name %s", algname);
4433 continue;
4435 alg = (digest_algorithm_t) a;
4438 if (!tok->object_type ||
4439 strcmp(tok->object_type, "SIGNATURE") ||
4440 tok->object_size < 128 || tok->object_size > 512) {
4441 log_warn(LD_DIR, "Bad object type or length on directory-signature");
4442 goto err;
4445 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
4446 base16_decode(id_digest, sizeof(id_digest),
4447 id_hexdigest, HEX_DIGEST_LEN) != sizeof(id_digest)) {
4448 log_warn(LD_DIR, "Error decoding declared identity %s in "
4449 "network-status vote.", escaped(id_hexdigest));
4450 goto err;
4452 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
4453 base16_decode(sk_digest, sizeof(sk_digest),
4454 sk_hexdigest, HEX_DIGEST_LEN) != sizeof(sk_digest)) {
4455 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
4456 "network-status vote.", escaped(sk_hexdigest));
4457 goto err;
4460 siglist = detached_get_signatures(sigs, flavor);
4461 is_duplicate = 0;
4462 SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
4463 if (dsig->alg == alg &&
4464 tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
4465 tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
4466 is_duplicate = 1;
4469 if (is_duplicate) {
4470 log_warn(LD_DIR, "Two signatures with identical keys and algorithm "
4471 "found.");
4472 continue;
4475 sig = tor_malloc_zero(sizeof(document_signature_t));
4476 sig->alg = alg;
4477 memcpy(sig->identity_digest, id_digest, DIGEST_LEN);
4478 memcpy(sig->signing_key_digest, sk_digest, DIGEST_LEN);
4479 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
4480 tor_free(sig);
4481 goto err;
4483 sig->signature = tor_memdup(tok->object_body, tok->object_size);
4484 sig->signature_len = (int) tok->object_size;
4486 smartlist_add(siglist, sig);
4487 } SMARTLIST_FOREACH_END(_tok);
4489 goto done;
4490 err:
4491 ns_detached_signatures_free(sigs);
4492 sigs = NULL;
4493 done:
4494 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4495 smartlist_free(tokens);
4496 if (area) {
4497 DUMP_AREA(area, "detached signatures");
4498 memarea_drop_all(area);
4500 return sigs;
4503 /** Parse the addr policy in the string <b>s</b> and return it. If
4504 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
4505 * ADDR_POLICY_REJECT) for items that specify no action.
4507 * Returns NULL on policy errors.
4509 * Set *<b>malformed_list</b> to true if the entire policy list should be
4510 * discarded. Otherwise, set it to false, and only this item should be ignored
4511 * on error - the rest of the policy list can continue to be processed and
4512 * used.
4514 * The addr_policy_t returned by this function can have its address set to
4515 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
4516 * of AF_INET and AF_INET6 items.
4518 MOCK_IMPL(addr_policy_t *,
4519 router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
4520 int *malformed_list))
4522 directory_token_t *tok = NULL;
4523 const char *cp, *eos;
4524 /* Longest possible policy is
4525 * "accept6 [ffff:ffff:..255]/128:10000-65535",
4526 * which contains a max-length IPv6 address, plus 26 characters.
4527 * But note that there can be an arbitrary amount of space between the
4528 * accept and the address:mask/port element.
4529 * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
4530 * IPv6 address. But making the buffer shorter might cause valid long lines,
4531 * which parsed in previous versions, to fail to parse in new versions.
4532 * (These lines would have to have excessive amounts of whitespace.) */
4533 char line[TOR_ADDR_BUF_LEN*2 + 32];
4534 addr_policy_t *r;
4535 memarea_t *area = NULL;
4537 tor_assert(malformed_list);
4538 *malformed_list = 0;
4540 s = eat_whitespace(s);
4541 /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
4542 * and ":" (port separator) are ambiguous */
4543 if ((*s == '*' || *s == '[' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
4544 if (tor_snprintf(line, sizeof(line), "%s %s",
4545 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
4546 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
4547 return NULL;
4549 cp = line;
4550 tor_strlower(line);
4551 } else { /* assume an already well-formed address policy line */
4552 cp = s;
4555 eos = cp + strlen(cp);
4556 area = memarea_new();
4557 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
4558 if (tok->tp == ERR_) {
4559 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
4560 goto err;
4562 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
4563 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
4564 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
4565 goto err;
4568 /* Use the extended interpretation of accept/reject *,
4569 * expanding it into an IPv4 wildcard and an IPv6 wildcard.
4570 * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
4571 r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
4572 if (!r) {
4573 goto err;
4576 /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
4577 * AF_UNSPEC addresses are only permitted on the accept/reject field type.
4578 * Unlike descriptors, torrcs exit policy accept/reject can be followed by
4579 * either an IPv4 or IPv6 address. */
4580 if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
4581 tor_addr_family(&r->addr) != AF_INET6) {
4582 /* This is a non-fatal error, just ignore this one entry. */
4583 *malformed_list = 0;
4584 log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
4585 "exit policy. Ignoring, but continuing to parse rules. (Use "
4586 "accept/reject with IPv4 addresses.)",
4587 tok->n_args == 1 ? tok->args[0] : "");
4588 addr_policy_free(r);
4589 r = NULL;
4590 goto done;
4593 goto done;
4594 err:
4595 *malformed_list = 1;
4596 r = NULL;
4597 done:
4598 token_clear(tok);
4599 if (area) {
4600 DUMP_AREA(area, "policy item");
4601 memarea_drop_all(area);
4603 return r;
4606 /** Add an exit policy stored in the token <b>tok</b> to the router info in
4607 * <b>router</b>. Return 0 on success, -1 on failure. */
4608 static int
4609 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
4611 addr_policy_t *newe;
4612 /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
4613 newe = router_parse_addr_policy(tok, 0);
4614 if (!newe)
4615 return -1;
4616 if (! router->exit_policy)
4617 router->exit_policy = smartlist_new();
4619 /* Ensure that in descriptors, accept/reject fields are followed by
4620 * IPv4 addresses, and accept6/reject6 fields are followed by
4621 * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
4622 * accept/reject followed by IPv6. */
4623 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
4624 tor_addr_family(&newe->addr) == AF_INET)
4626 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
4627 tor_addr_family(&newe->addr) == AF_INET6)) {
4628 /* There's nothing the user can do about other relays' descriptors,
4629 * so we don't provide usage advice here. */
4630 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
4631 "policy '%s'. Discarding entire router descriptor.",
4632 tok->n_args == 1 ? tok->args[0] : "");
4633 addr_policy_free(newe);
4634 return -1;
4637 smartlist_add(router->exit_policy, newe);
4639 return 0;
4642 /** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
4643 * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
4644 * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
4645 * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
4646 * policies */
4647 static addr_policy_t *
4648 router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
4650 addr_policy_t newe;
4651 char *arg;
4653 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
4654 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
4656 if (tok->n_args != 1)
4657 return NULL;
4658 arg = tok->args[0];
4660 if (!strcmpstart(arg,"private"))
4661 return router_parse_addr_policy_private(tok);
4663 memset(&newe, 0, sizeof(newe));
4665 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
4666 newe.policy_type = ADDR_POLICY_REJECT;
4667 else
4668 newe.policy_type = ADDR_POLICY_ACCEPT;
4670 /* accept6/reject6 * produces an IPv6 wildcard address only.
4671 * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
4672 if ((fmt_flags & TAPMP_EXTENDED_STAR)
4673 && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
4674 fmt_flags |= TAPMP_STAR_IPV6_ONLY;
4677 if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
4678 &newe.prt_min, &newe.prt_max) < 0) {
4679 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
4680 return NULL;
4683 return addr_policy_get_canonical_entry(&newe);
4686 /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
4687 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
4688 * router descriptors until earlier versions are obsolete.
4690 * accept/reject and accept6/reject6 private all produce rules for both
4691 * IPv4 and IPv6 addresses.
4693 static addr_policy_t *
4694 router_parse_addr_policy_private(directory_token_t *tok)
4696 const char *arg;
4697 uint16_t port_min, port_max;
4698 addr_policy_t result;
4700 arg = tok->args[0];
4701 if (strcmpstart(arg, "private"))
4702 return NULL;
4704 arg += strlen("private");
4705 arg = (char*) eat_whitespace(arg);
4706 if (!arg || *arg != ':')
4707 return NULL;
4709 if (parse_port_range(arg+1, &port_min, &port_max)<0)
4710 return NULL;
4712 memset(&result, 0, sizeof(result));
4713 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
4714 result.policy_type = ADDR_POLICY_REJECT;
4715 else
4716 result.policy_type = ADDR_POLICY_ACCEPT;
4717 result.is_private = 1;
4718 result.prt_min = port_min;
4719 result.prt_max = port_max;
4721 if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
4722 log_warn(LD_GENERAL,
4723 "'%s' expands into rules which apply to all private IPv4 and "
4724 "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
4725 "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
4728 return addr_policy_get_canonical_entry(&result);
4731 /** Log and exit if <b>t</b> is malformed */
4732 void
4733 assert_addr_policy_ok(smartlist_t *lst)
4735 if (!lst) return;
4736 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
4737 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
4738 t->policy_type == ADDR_POLICY_ACCEPT);
4739 tor_assert(t->prt_min <= t->prt_max);
4744 * Low-level tokenizer for router descriptors and directories.
4747 /** Free all resources allocated for <b>tok</b> */
4748 static void
4749 token_clear(directory_token_t *tok)
4751 if (tok->key)
4752 crypto_pk_free(tok->key);
4755 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
4756 #define ALLOC(sz) memarea_alloc(area,sz)
4757 #define STRDUP(str) memarea_strdup(area,str)
4758 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
4760 #define RET_ERR(msg) \
4761 STMT_BEGIN \
4762 if (tok) token_clear(tok); \
4763 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
4764 tok->tp = ERR_; \
4765 tok->error = STRDUP(msg); \
4766 goto done_tokenizing; \
4767 STMT_END
4769 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
4770 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
4771 * Return <b>tok</b> on success, or a new ERR_ token if the token didn't
4772 * conform to the syntax we wanted.
4774 static inline directory_token_t *
4775 token_check_object(memarea_t *area, const char *kwd,
4776 directory_token_t *tok, obj_syntax o_syn)
4778 char ebuf[128];
4779 switch (o_syn) {
4780 case NO_OBJ:
4781 /* No object is allowed for this token. */
4782 if (tok->object_body) {
4783 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
4784 RET_ERR(ebuf);
4786 if (tok->key) {
4787 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
4788 RET_ERR(ebuf);
4790 break;
4791 case NEED_OBJ:
4792 /* There must be a (non-key) object. */
4793 if (!tok->object_body) {
4794 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
4795 RET_ERR(ebuf);
4797 break;
4798 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
4799 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
4800 if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
4801 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
4802 kwd, crypto_pk_num_bits(tok->key));
4803 RET_ERR(ebuf);
4805 /* fall through */
4806 case NEED_KEY: /* There must be some kind of key. */
4807 if (!tok->key) {
4808 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
4809 RET_ERR(ebuf);
4811 if (o_syn != NEED_SKEY_1024) {
4812 if (crypto_pk_key_is_private(tok->key)) {
4813 tor_snprintf(ebuf, sizeof(ebuf),
4814 "Private key given for %s, which wants a public key", kwd);
4815 RET_ERR(ebuf);
4817 } else { /* o_syn == NEED_SKEY_1024 */
4818 if (!crypto_pk_key_is_private(tok->key)) {
4819 tor_snprintf(ebuf, sizeof(ebuf),
4820 "Public key given for %s, which wants a private key", kwd);
4821 RET_ERR(ebuf);
4824 break;
4825 case OBJ_OK:
4826 /* Anything goes with this token. */
4827 break;
4830 done_tokenizing:
4831 return tok;
4834 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
4835 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
4836 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
4837 * all storage in <b>area</b>. Return the number of arguments parsed, or
4838 * return -1 if there was an insanely high number of arguments. */
4839 static inline int
4840 get_token_arguments(memarea_t *area, directory_token_t *tok,
4841 const char *s, const char *eol)
4843 /** Largest number of arguments we'll accept to any token, ever. */
4844 #define MAX_ARGS 512
4845 char *mem = memarea_strndup(area, s, eol-s);
4846 char *cp = mem;
4847 int j = 0;
4848 char *args[MAX_ARGS];
4849 while (*cp) {
4850 if (j == MAX_ARGS)
4851 return -1;
4852 args[j++] = cp;
4853 cp = (char*)find_whitespace(cp);
4854 if (!cp || !*cp)
4855 break; /* End of the line. */
4856 *cp++ = '\0';
4857 cp = (char*)eat_whitespace(cp);
4859 tok->n_args = j;
4860 tok->args = memarea_memdup(area, args, j*sizeof(char*));
4861 return j;
4862 #undef MAX_ARGS
4865 /** Helper function: read the next token from *s, advance *s to the end of the
4866 * token, and return the parsed token. Parse *<b>s</b> according to the list
4867 * of tokens in <b>table</b>.
4869 static directory_token_t *
4870 get_next_token(memarea_t *area,
4871 const char **s, const char *eos, token_rule_t *table)
4873 /** Reject any object at least this big; it is probably an overflow, an
4874 * attack, a bug, or some other nonsense. */
4875 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
4876 /** Reject any line at least this big; it is probably an overflow, an
4877 * attack, a bug, or some other nonsense. */
4878 #define MAX_LINE_LENGTH (128*1024)
4880 const char *next, *eol, *obstart;
4881 size_t obname_len;
4882 int i;
4883 directory_token_t *tok;
4884 obj_syntax o_syn = NO_OBJ;
4885 char ebuf[128];
4886 const char *kwd = "";
4888 tor_assert(area);
4889 tok = ALLOC_ZERO(sizeof(directory_token_t));
4890 tok->tp = ERR_;
4892 /* Set *s to first token, eol to end-of-line, next to after first token */
4893 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
4894 tor_assert(eos >= *s);
4895 eol = memchr(*s, '\n', eos-*s);
4896 if (!eol)
4897 eol = eos;
4898 if (eol - *s > MAX_LINE_LENGTH) {
4899 RET_ERR("Line far too long");
4902 next = find_whitespace_eos(*s, eol);
4904 if (!strcmp_len(*s, "opt", next-*s)) {
4905 /* Skip past an "opt" at the start of the line. */
4906 *s = eat_whitespace_eos_no_nl(next, eol);
4907 next = find_whitespace_eos(*s, eol);
4908 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
4909 RET_ERR("Unexpected EOF");
4912 /* Search the table for the appropriate entry. (I tried a binary search
4913 * instead, but it wasn't any faster.) */
4914 for (i = 0; table[i].t ; ++i) {
4915 if (!strcmp_len(*s, table[i].t, next-*s)) {
4916 /* We've found the keyword. */
4917 kwd = table[i].t;
4918 tok->tp = table[i].v;
4919 o_syn = table[i].os;
4920 *s = eat_whitespace_eos_no_nl(next, eol);
4921 /* We go ahead whether there are arguments or not, so that tok->args is
4922 * always set if we want arguments. */
4923 if (table[i].concat_args) {
4924 /* The keyword takes the line as a single argument */
4925 tok->args = ALLOC(sizeof(char*));
4926 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
4927 tok->n_args = 1;
4928 } else {
4929 /* This keyword takes multiple arguments. */
4930 if (get_token_arguments(area, tok, *s, eol)<0) {
4931 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
4932 RET_ERR(ebuf);
4934 *s = eol;
4936 if (tok->n_args < table[i].min_args) {
4937 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
4938 RET_ERR(ebuf);
4939 } else if (tok->n_args > table[i].max_args) {
4940 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
4941 RET_ERR(ebuf);
4943 break;
4947 if (tok->tp == ERR_) {
4948 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
4949 if (*s < eol && **s == '@')
4950 tok->tp = A_UNKNOWN_;
4951 else
4952 tok->tp = K_OPT;
4953 tok->args = ALLOC(sizeof(char*));
4954 tok->args[0] = STRNDUP(*s, eol-*s);
4955 tok->n_args = 1;
4956 o_syn = OBJ_OK;
4959 /* Check whether there's an object present */
4960 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
4961 tor_assert(eos >= *s);
4962 eol = memchr(*s, '\n', eos-*s);
4963 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
4964 goto check_object;
4966 obstart = *s; /* Set obstart to start of object spec */
4967 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
4968 strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
4969 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
4970 RET_ERR("Malformed object: bad begin line");
4972 tok->object_type = STRNDUP(*s+11, eol-*s-16);
4973 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
4974 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
4976 /* Go to the end of the object */
4977 next = tor_memstr(*s, eos-*s, "-----END ");
4978 if (!next) {
4979 RET_ERR("Malformed object: missing object end line");
4981 tor_assert(eos >= next);
4982 eol = memchr(next, '\n', eos-next);
4983 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
4984 eol = eos;
4985 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
4986 if ((size_t)(eol-next) != 9+obname_len+5 ||
4987 strcmp_len(next+9, tok->object_type, obname_len) ||
4988 strcmp_len(eol-5, "-----", 5)) {
4989 tor_snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
4990 tok->object_type);
4991 ebuf[sizeof(ebuf)-1] = '\0';
4992 RET_ERR(ebuf);
4994 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
4995 RET_ERR("Couldn't parse object: missing footer or object much too big.");
4997 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
4998 tok->key = crypto_pk_new();
4999 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
5000 RET_ERR("Couldn't parse public key.");
5001 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
5002 tok->key = crypto_pk_new();
5003 if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
5004 RET_ERR("Couldn't parse private key.");
5005 } else { /* If it's something else, try to base64-decode it */
5006 int r;
5007 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
5008 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
5009 if (r<0)
5010 RET_ERR("Malformed object: bad base64-encoded data");
5011 tok->object_size = r;
5013 *s = eol;
5015 check_object:
5016 tok = token_check_object(area, kwd, tok, o_syn);
5018 done_tokenizing:
5019 return tok;
5021 #undef RET_ERR
5022 #undef ALLOC
5023 #undef ALLOC_ZERO
5024 #undef STRDUP
5025 #undef STRNDUP
5028 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
5029 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
5030 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
5031 * entire string.
5033 static int
5034 tokenize_string(memarea_t *area,
5035 const char *start, const char *end, smartlist_t *out,
5036 token_rule_t *table, int flags)
5038 const char **s;
5039 directory_token_t *tok = NULL;
5040 int counts[NIL_];
5041 int i;
5042 int first_nonannotation;
5043 int prev_len = smartlist_len(out);
5044 tor_assert(area);
5046 s = &start;
5047 if (!end) {
5048 end = start+strlen(start);
5049 } else {
5050 /* it's only meaningful to check for nuls if we got an end-of-string ptr */
5051 if (memchr(start, '\0', end-start)) {
5052 log_warn(LD_DIR, "parse error: internal NUL character.");
5053 return -1;
5056 for (i = 0; i < NIL_; ++i)
5057 counts[i] = 0;
5059 SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]);
5061 while (*s < end && (!tok || tok->tp != EOF_)) {
5062 tok = get_next_token(area, s, end, table);
5063 if (tok->tp == ERR_) {
5064 log_warn(LD_DIR, "parse error: %s", tok->error);
5065 token_clear(tok);
5066 return -1;
5068 ++counts[tok->tp];
5069 smartlist_add(out, tok);
5070 *s = eat_whitespace_eos(*s, end);
5073 if (flags & TS_NOCHECK)
5074 return 0;
5076 if ((flags & TS_ANNOTATIONS_OK)) {
5077 first_nonannotation = -1;
5078 for (i = 0; i < smartlist_len(out); ++i) {
5079 tok = smartlist_get(out, i);
5080 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
5081 first_nonannotation = i;
5082 break;
5085 if (first_nonannotation < 0) {
5086 log_warn(LD_DIR, "parse error: item contains only annotations");
5087 return -1;
5089 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
5090 tok = smartlist_get(out, i);
5091 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
5092 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
5093 return -1;
5096 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
5097 if (first_nonannotation != prev_len) {
5098 log_warn(LD_DIR, "parse error: Unexpected annotations.");
5099 return -1;
5102 } else {
5103 for (i=0; i < smartlist_len(out); ++i) {
5104 tok = smartlist_get(out, i);
5105 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
5106 log_warn(LD_DIR, "parse error: no annotations allowed.");
5107 return -1;
5110 first_nonannotation = 0;
5112 for (i = 0; table[i].t; ++i) {
5113 if (counts[table[i].v] < table[i].min_cnt) {
5114 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
5115 return -1;
5117 if (counts[table[i].v] > table[i].max_cnt) {
5118 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
5119 return -1;
5121 if (table[i].pos & AT_START) {
5122 if (smartlist_len(out) < 1 ||
5123 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
5124 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
5125 return -1;
5128 if (table[i].pos & AT_END) {
5129 if (smartlist_len(out) < 1 ||
5130 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
5131 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
5132 return -1;
5136 return 0;
5139 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
5140 * NULL if no such keyword is found.
5142 static directory_token_t *
5143 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
5145 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
5146 return NULL;
5149 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
5150 * with an assert if no such keyword is found.
5152 static directory_token_t *
5153 find_by_keyword_(smartlist_t *s, directory_keyword keyword,
5154 const char *keyword_as_string)
5156 directory_token_t *tok = find_opt_by_keyword(s, keyword);
5157 if (PREDICT_UNLIKELY(!tok)) {
5158 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
5159 "been validated. Internal error.", keyword_as_string, (int)keyword);
5160 tor_assert(tok);
5162 return tok;
5165 /** If there are any directory_token_t entries in <b>s</b> whose keyword is
5166 * <b>k</b>, return a newly allocated smartlist_t containing all such entries,
5167 * in the same order in which they occur in <b>s</b>. Otherwise return
5168 * NULL. */
5169 static smartlist_t *
5170 find_all_by_keyword(smartlist_t *s, directory_keyword k)
5172 smartlist_t *out = NULL;
5173 SMARTLIST_FOREACH(s, directory_token_t *, t,
5174 if (t->tp == k) {
5175 if (!out)
5176 out = smartlist_new();
5177 smartlist_add(out, t);
5179 return out;
5182 /** Return a newly allocated smartlist of all accept or reject tokens in
5183 * <b>s</b>.
5185 static smartlist_t *
5186 find_all_exitpolicy(smartlist_t *s)
5188 smartlist_t *out = smartlist_new();
5189 SMARTLIST_FOREACH(s, directory_token_t *, t,
5190 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
5191 t->tp == K_REJECT || t->tp == K_REJECT6)
5192 smartlist_add(out,t));
5193 return out;
5196 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
5197 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
5198 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
5199 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
5201 * Return 0 on success and -1 on failure.
5203 static int
5204 router_get_hash_impl_helper(const char *s, size_t s_len,
5205 const char *start_str,
5206 const char *end_str, char end_c,
5207 const char **start_out, const char **end_out)
5209 const char *start, *end;
5210 start = tor_memstr(s, s_len, start_str);
5211 if (!start) {
5212 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
5213 return -1;
5215 if (start != s && *(start-1) != '\n') {
5216 log_warn(LD_DIR,
5217 "first occurrence of \"%s\" is not at the start of a line",
5218 start_str);
5219 return -1;
5221 end = tor_memstr(start+strlen(start_str),
5222 s_len - (start-s) - strlen(start_str), end_str);
5223 if (!end) {
5224 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
5225 return -1;
5227 end = memchr(end+strlen(end_str), end_c, s_len - (end-s) - strlen(end_str));
5228 if (!end) {
5229 log_warn(LD_DIR,"couldn't find EOL");
5230 return -1;
5232 ++end;
5234 *start_out = start;
5235 *end_out = end;
5236 return 0;
5239 /** Compute the digest of the substring of <b>s</b> taken from the first
5240 * occurrence of <b>start_str</b> through the first instance of c after the
5241 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
5242 * result in <b>digest</b>; return 0 on success.
5244 * If no such substring exists, return -1.
5246 static int
5247 router_get_hash_impl(const char *s, size_t s_len, char *digest,
5248 const char *start_str,
5249 const char *end_str, char end_c,
5250 digest_algorithm_t alg)
5252 const char *start=NULL, *end=NULL;
5253 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
5254 &start,&end)<0)
5255 return -1;
5257 if (alg == DIGEST_SHA1) {
5258 if (crypto_digest(digest, start, end-start)) {
5259 log_warn(LD_BUG,"couldn't compute digest");
5260 return -1;
5262 } else {
5263 if (crypto_digest256(digest, start, end-start, alg)) {
5264 log_warn(LD_BUG,"couldn't compute digest");
5265 return -1;
5269 return 0;
5272 /** As router_get_hash_impl, but compute all hashes. */
5273 static int
5274 router_get_hashes_impl(const char *s, size_t s_len, common_digests_t *digests,
5275 const char *start_str,
5276 const char *end_str, char end_c)
5278 const char *start=NULL, *end=NULL;
5279 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
5280 &start,&end)<0)
5281 return -1;
5283 if (crypto_common_digests(digests, start, end-start)) {
5284 log_warn(LD_BUG,"couldn't compute digests");
5285 return -1;
5288 return 0;
5291 /** Assuming that s starts with a microdesc, return the start of the
5292 * *NEXT* one. Return NULL on "not found." */
5293 static const char *
5294 find_start_of_next_microdesc(const char *s, const char *eos)
5296 int started_with_annotations;
5297 s = eat_whitespace_eos(s, eos);
5298 if (!s)
5299 return NULL;
5301 #define CHECK_LENGTH() STMT_BEGIN \
5302 if (s+32 > eos) \
5303 return NULL; \
5304 STMT_END
5306 #define NEXT_LINE() STMT_BEGIN \
5307 s = memchr(s, '\n', eos-s); \
5308 if (!s || s+1 >= eos) \
5309 return NULL; \
5310 s++; \
5311 STMT_END
5313 CHECK_LENGTH();
5315 started_with_annotations = (*s == '@');
5317 if (started_with_annotations) {
5318 /* Start by advancing to the first non-annotation line. */
5319 while (*s == '@')
5320 NEXT_LINE();
5322 CHECK_LENGTH();
5324 /* Now we should be pointed at an onion-key line. If we are, then skip
5325 * it. */
5326 if (!strcmpstart(s, "onion-key"))
5327 NEXT_LINE();
5329 /* Okay, now we're pointed at the first line of the microdescriptor which is
5330 not an annotation or onion-key. The next line that _is_ an annotation or
5331 onion-key is the start of the next microdescriptor. */
5332 while (s+32 < eos) {
5333 if (*s == '@' || !strcmpstart(s, "onion-key"))
5334 return s;
5335 NEXT_LINE();
5337 return NULL;
5339 #undef CHECK_LENGTH
5340 #undef NEXT_LINE
5343 /** Parse as many microdescriptors as are found from the string starting at
5344 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
5345 * annotations we recognize and ignore ones we don't.
5347 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
5348 * descriptor in the body field of each microdesc_t.
5350 * Return all newly parsed microdescriptors in a newly allocated
5351 * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
5352 * microdesc digest to it for every microdesc that we found to be badly
5353 * formed. (This may cause duplicates) */
5354 smartlist_t *
5355 microdescs_parse_from_string(const char *s, const char *eos,
5356 int allow_annotations,
5357 saved_location_t where,
5358 smartlist_t *invalid_digests_out)
5360 smartlist_t *tokens;
5361 smartlist_t *result;
5362 microdesc_t *md = NULL;
5363 memarea_t *area;
5364 const char *start = s;
5365 const char *start_of_next_microdesc;
5366 int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0;
5367 const int copy_body = (where != SAVED_IN_CACHE);
5369 directory_token_t *tok;
5371 if (!eos)
5372 eos = s + strlen(s);
5374 s = eat_whitespace_eos(s, eos);
5375 area = memarea_new();
5376 result = smartlist_new();
5377 tokens = smartlist_new();
5379 while (s < eos) {
5380 int okay = 0;
5382 start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
5383 if (!start_of_next_microdesc)
5384 start_of_next_microdesc = eos;
5386 md = tor_malloc_zero(sizeof(microdesc_t));
5388 const char *cp = tor_memstr(s, start_of_next_microdesc-s,
5389 "onion-key");
5390 const int no_onion_key = (cp == NULL);
5391 if (no_onion_key) {
5392 cp = s; /* So that we have *some* junk to put in the body */
5395 md->bodylen = start_of_next_microdesc - cp;
5396 md->saved_location = where;
5397 if (copy_body)
5398 md->body = tor_memdup_nulterm(cp, md->bodylen);
5399 else
5400 md->body = (char*)cp;
5401 md->off = cp - start;
5402 crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
5403 if (no_onion_key) {
5404 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Malformed or truncated descriptor");
5405 goto next;
5409 if (tokenize_string(area, s, start_of_next_microdesc, tokens,
5410 microdesc_token_table, flags)) {
5411 log_warn(LD_DIR, "Unparseable microdescriptor");
5412 goto next;
5415 if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
5416 if (parse_iso_time(tok->args[0], &md->last_listed)) {
5417 log_warn(LD_DIR, "Bad last-listed time in microdescriptor");
5418 goto next;
5422 tok = find_by_keyword(tokens, K_ONION_KEY);
5423 if (!crypto_pk_public_exponent_ok(tok->key)) {
5424 log_warn(LD_DIR,
5425 "Relay's onion key had invalid exponent.");
5426 goto next;
5428 md->onion_pkey = tok->key;
5429 tok->key = NULL;
5431 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
5432 curve25519_public_key_t k;
5433 tor_assert(tok->n_args >= 1);
5434 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
5435 log_warn(LD_DIR, "Bogus ntor-onion-key in microdesc");
5436 goto next;
5438 md->onion_curve25519_pkey =
5439 tor_memdup(&k, sizeof(curve25519_public_key_t));
5442 smartlist_t *id_lines = find_all_by_keyword(tokens, K_ID);
5443 if (id_lines) {
5444 SMARTLIST_FOREACH_BEGIN(id_lines, directory_token_t *, t) {
5445 tor_assert(t->n_args >= 2);
5446 if (!strcmp(t->args[0], "ed25519")) {
5447 if (md->ed25519_identity_pkey) {
5448 log_warn(LD_DIR, "Extra ed25519 key in microdesc");
5449 goto next;
5451 ed25519_public_key_t k;
5452 if (ed25519_public_from_base64(&k, t->args[1])<0) {
5453 log_warn(LD_DIR, "Bogus ed25519 key in microdesc");
5454 goto next;
5456 md->ed25519_identity_pkey = tor_memdup(&k, sizeof(k));
5458 } SMARTLIST_FOREACH_END(t);
5459 smartlist_free(id_lines);
5463 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
5464 if (a_lines) {
5465 find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport);
5466 smartlist_free(a_lines);
5470 if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
5471 int i;
5472 md->family = smartlist_new();
5473 for (i=0;i<tok->n_args;++i) {
5474 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
5475 log_warn(LD_DIR, "Illegal nickname %s in family line",
5476 escaped(tok->args[i]));
5477 goto next;
5479 smartlist_add(md->family, tor_strdup(tok->args[i]));
5483 if ((tok = find_opt_by_keyword(tokens, K_P))) {
5484 md->exit_policy = parse_short_policy(tok->args[0]);
5486 if ((tok = find_opt_by_keyword(tokens, K_P6))) {
5487 md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
5490 smartlist_add(result, md);
5491 okay = 1;
5493 md = NULL;
5494 next:
5495 if (! okay && invalid_digests_out) {
5496 smartlist_add(invalid_digests_out,
5497 tor_memdup(md->digest, DIGEST256_LEN));
5499 microdesc_free(md);
5500 md = NULL;
5502 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5503 memarea_clear(area);
5504 smartlist_clear(tokens);
5505 s = start_of_next_microdesc;
5508 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5509 memarea_drop_all(area);
5510 smartlist_free(tokens);
5512 return result;
5515 /** Extract a Tor version from a <b>platform</b> line from a router
5516 * descriptor, and place the result in <b>router_version</b>.
5518 * Return 1 on success, -1 on parsing failure, and 0 if the
5519 * platform line does not indicate some version of Tor.
5521 * If <b>strict</b> is non-zero, finding any weird version components
5522 * (like negative numbers) counts as a parsing failure.
5525 tor_version_parse_platform(const char *platform,
5526 tor_version_t *router_version,
5527 int strict)
5529 char tmp[128];
5530 char *s, *s2, *start;
5532 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; say 0. */
5533 return 0;
5535 start = (char *)eat_whitespace(platform+3);
5536 if (!*start) return -1;
5537 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
5538 s2 = (char*)eat_whitespace(s);
5539 if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
5540 s = (char*)find_whitespace(s2);
5542 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
5543 return -1;
5544 strlcpy(tmp, start, s-start+1);
5546 if (tor_version_parse(tmp, router_version)<0) {
5547 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
5548 return -1;
5551 if (strict) {
5552 if (router_version->major < 0 ||
5553 router_version->minor < 0 ||
5554 router_version->micro < 0 ||
5555 router_version->patchlevel < 0 ||
5556 router_version->svn_revision < 0) {
5557 return -1;
5561 return 1;
5564 /** Parse the Tor version of the platform string <b>platform</b>,
5565 * and compare it to the version in <b>cutoff</b>. Return 1 if
5566 * the router is at least as new as the cutoff, else return 0.
5569 tor_version_as_new_as(const char *platform, const char *cutoff)
5571 tor_version_t cutoff_version, router_version;
5572 int r;
5573 tor_assert(platform);
5575 if (tor_version_parse(cutoff, &cutoff_version)<0) {
5576 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
5577 return 0;
5580 r = tor_version_parse_platform(platform, &router_version, 0);
5581 if (r == 0) {
5582 /* nonstandard Tor; be safe and say yes */
5583 return 1;
5584 } else if (r < 0) {
5585 /* unparseable version; be safe and say yes. */
5586 return 1;
5589 /* Here's why we don't need to do any special handling for svn revisions:
5590 * - If neither has an svn revision, we're fine.
5591 * - If the router doesn't have an svn revision, we can't assume that it
5592 * is "at least" any svn revision, so we need to return 0.
5593 * - If the target version doesn't have an svn revision, any svn revision
5594 * (or none at all) is good enough, so return 1.
5595 * - If both target and router have an svn revision, we compare them.
5598 return tor_version_compare(&router_version, &cutoff_version) >= 0;
5601 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
5602 * Return 0 on success, -1 on failure. */
5604 tor_version_parse(const char *s, tor_version_t *out)
5606 char *eos=NULL;
5607 const char *cp=NULL;
5608 int ok = 1;
5609 /* Format is:
5610 * "Tor " ? NUM dot NUM [ dot NUM [ ( pre | rc | dot ) NUM ] ] [ - tag ]
5612 tor_assert(s);
5613 tor_assert(out);
5615 memset(out, 0, sizeof(tor_version_t));
5616 out->status = VER_RELEASE;
5617 if (!strcasecmpstart(s, "Tor "))
5618 s += 4;
5620 cp = s;
5622 #define NUMBER(m) \
5623 do { \
5624 if (!cp || *cp < '0' || *cp > '9') \
5625 return -1; \
5626 out->m = (int)tor_parse_uint64(cp, 10, 0, INT32_MAX, &ok, &eos); \
5627 if (!ok) \
5628 return -1; \
5629 if (!eos || eos == cp) \
5630 return -1; \
5631 cp = eos; \
5632 } while (0)
5634 #define DOT() \
5635 do { \
5636 if (*cp != '.') \
5637 return -1; \
5638 ++cp; \
5639 } while (0)
5641 NUMBER(major);
5642 DOT();
5643 NUMBER(minor);
5644 if (*cp == 0)
5645 return 0;
5646 else if (*cp == '-')
5647 goto status_tag;
5648 DOT();
5649 NUMBER(micro);
5651 /* Get status */
5652 if (*cp == 0) {
5653 return 0;
5654 } else if (*cp == '.') {
5655 ++cp;
5656 } else if (*cp == '-') {
5657 goto status_tag;
5658 } else if (0==strncmp(cp, "pre", 3)) {
5659 out->status = VER_PRE;
5660 cp += 3;
5661 } else if (0==strncmp(cp, "rc", 2)) {
5662 out->status = VER_RC;
5663 cp += 2;
5664 } else {
5665 return -1;
5668 NUMBER(patchlevel);
5670 status_tag:
5671 /* Get status tag. */
5672 if (*cp == '-' || *cp == '.')
5673 ++cp;
5674 eos = (char*) find_whitespace(cp);
5675 if (eos-cp >= (int)sizeof(out->status_tag))
5676 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
5677 else {
5678 memcpy(out->status_tag, cp, eos-cp);
5679 out->status_tag[eos-cp] = 0;
5681 cp = eat_whitespace(eos);
5683 if (!strcmpstart(cp, "(r")) {
5684 cp += 2;
5685 out->svn_revision = (int) strtol(cp,&eos,10);
5686 } else if (!strcmpstart(cp, "(git-")) {
5687 char *close_paren = strchr(cp, ')');
5688 int hexlen;
5689 char digest[DIGEST_LEN];
5690 if (! close_paren)
5691 return -1;
5692 cp += 5;
5693 if (close_paren-cp > HEX_DIGEST_LEN)
5694 return -1;
5695 hexlen = (int)(close_paren-cp);
5696 memwipe(digest, 0, sizeof(digest));
5697 if ( hexlen == 0 || (hexlen % 2) == 1)
5698 return -1;
5699 if (base16_decode(digest, hexlen/2, cp, hexlen) != hexlen/2)
5700 return -1;
5701 memcpy(out->git_tag, digest, hexlen/2);
5702 out->git_tag_len = hexlen/2;
5705 return 0;
5706 #undef NUMBER
5707 #undef DOT
5710 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
5711 * b. */
5713 tor_version_compare(tor_version_t *a, tor_version_t *b)
5715 int i;
5716 tor_assert(a);
5717 tor_assert(b);
5719 /* We take this approach to comparison to ensure the same (bogus!) behavior
5720 * on all inputs as we would have seen before bug #21278 was fixed. The
5721 * only important difference here is that this method doesn't cause
5722 * a signed integer underflow.
5724 #define CMP(field) do { \
5725 unsigned aval = (unsigned) a->field; \
5726 unsigned bval = (unsigned) b->field; \
5727 int result = (int) (aval - bval); \
5728 if (result < 0) \
5729 return -1; \
5730 else if (result > 0) \
5731 return 1; \
5732 } while (0)
5734 CMP(major);
5735 CMP(minor);
5736 CMP(micro);
5737 CMP(status);
5738 CMP(patchlevel);
5739 if ((i = strcmp(a->status_tag, b->status_tag)))
5740 return i;
5741 CMP(svn_revision);
5742 CMP(git_tag_len);
5743 if (a->git_tag_len)
5744 return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len);
5745 else
5746 return 0;
5748 #undef CMP
5751 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
5754 tor_version_same_series(tor_version_t *a, tor_version_t *b)
5756 tor_assert(a);
5757 tor_assert(b);
5758 return ((a->major == b->major) &&
5759 (a->minor == b->minor) &&
5760 (a->micro == b->micro));
5763 /** Helper: Given pointers to two strings describing tor versions, return -1
5764 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
5765 * Used to sort a list of versions. */
5766 static int
5767 compare_tor_version_str_ptr_(const void **_a, const void **_b)
5769 const char *a = *_a, *b = *_b;
5770 int ca, cb;
5771 tor_version_t va, vb;
5772 ca = tor_version_parse(a, &va);
5773 cb = tor_version_parse(b, &vb);
5774 /* If they both parse, compare them. */
5775 if (!ca && !cb)
5776 return tor_version_compare(&va,&vb);
5777 /* If one parses, it comes first. */
5778 if (!ca && cb)
5779 return -1;
5780 if (ca && !cb)
5781 return 1;
5782 /* If neither parses, compare strings. Also, the directory server admin
5783 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
5784 return strcmp(a,b);
5787 /** Sort a list of string-representations of versions in ascending order. */
5788 void
5789 sort_version_list(smartlist_t *versions, int remove_duplicates)
5791 smartlist_sort(versions, compare_tor_version_str_ptr_);
5793 if (remove_duplicates)
5794 smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_);
5797 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
5798 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
5799 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
5800 * encrypted introduction points to the newly allocated
5801 * *<b>intro_points_encrypted_out</b>, their encrypted size to
5802 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
5803 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
5804 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
5805 * and -1 for failure.
5807 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
5808 * be strict about time formats.
5811 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
5812 char *desc_id_out,
5813 char **intro_points_encrypted_out,
5814 size_t *intro_points_encrypted_size_out,
5815 size_t *encoded_size_out,
5816 const char **next_out, const char *desc,
5817 int as_hsdir)
5819 rend_service_descriptor_t *result =
5820 tor_malloc_zero(sizeof(rend_service_descriptor_t));
5821 char desc_hash[DIGEST_LEN];
5822 const char *eos;
5823 smartlist_t *tokens = smartlist_new();
5824 directory_token_t *tok;
5825 char secret_id_part[DIGEST_LEN];
5826 int i, version, num_ok=1;
5827 smartlist_t *versions;
5828 char public_key_hash[DIGEST_LEN];
5829 char test_desc_id[DIGEST_LEN];
5830 memarea_t *area = NULL;
5831 const int strict_time_fmt = as_hsdir;
5833 tor_assert(desc);
5834 /* Check if desc starts correctly. */
5835 if (strncmp(desc, "rendezvous-service-descriptor ",
5836 strlen("rendezvous-service-descriptor "))) {
5837 log_info(LD_REND, "Descriptor does not start correctly.");
5838 goto err;
5840 /* Compute descriptor hash for later validation. */
5841 if (router_get_hash_impl(desc, strlen(desc), desc_hash,
5842 "rendezvous-service-descriptor ",
5843 "\nsignature", '\n', DIGEST_SHA1) < 0) {
5844 log_warn(LD_REND, "Couldn't compute descriptor hash.");
5845 goto err;
5847 /* Determine end of string. */
5848 eos = strstr(desc, "\nrendezvous-service-descriptor ");
5849 if (!eos)
5850 eos = desc + strlen(desc);
5851 else
5852 eos = eos + 1;
5853 /* Check length. */
5854 if (eos-desc > REND_DESC_MAX_SIZE) {
5855 /* XXXX+ If we are parsing this descriptor as a server, this
5856 * should be a protocol warning. */
5857 log_warn(LD_REND, "Descriptor length is %d which exceeds "
5858 "maximum rendezvous descriptor size of %d bytes.",
5859 (int)(eos-desc), REND_DESC_MAX_SIZE);
5860 goto err;
5862 /* Tokenize descriptor. */
5863 area = memarea_new();
5864 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
5865 log_warn(LD_REND, "Error tokenizing descriptor.");
5866 goto err;
5868 /* Set next to next descriptor, if available. */
5869 *next_out = eos;
5870 /* Set length of encoded descriptor. */
5871 *encoded_size_out = eos - desc;
5872 /* Check min allowed length of token list. */
5873 if (smartlist_len(tokens) < 7) {
5874 log_warn(LD_REND, "Impossibly short descriptor.");
5875 goto err;
5877 /* Parse base32-encoded descriptor ID. */
5878 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
5879 tor_assert(tok == smartlist_get(tokens, 0));
5880 tor_assert(tok->n_args == 1);
5881 if (!rend_valid_descriptor_id(tok->args[0])) {
5882 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
5883 goto err;
5885 if (base32_decode(desc_id_out, DIGEST_LEN,
5886 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
5887 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
5888 tok->args[0]);
5889 goto err;
5891 /* Parse descriptor version. */
5892 tok = find_by_keyword(tokens, R_VERSION);
5893 tor_assert(tok->n_args == 1);
5894 result->version =
5895 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
5896 if (result->version != 2 || !num_ok) {
5897 /* If it's <2, it shouldn't be under this format. If the number
5898 * is greater than 2, we bumped it because we broke backward
5899 * compatibility. See how version numbers in our other formats
5900 * work. */
5901 log_warn(LD_REND, "Unrecognized descriptor version: %s",
5902 escaped(tok->args[0]));
5903 goto err;
5905 /* Parse public key. */
5906 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
5907 result->pk = tok->key;
5908 tok->key = NULL; /* Prevent free */
5909 /* Parse secret ID part. */
5910 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
5911 tor_assert(tok->n_args == 1);
5912 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
5913 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
5914 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
5915 goto err;
5917 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
5918 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
5919 tok->args[0]);
5920 goto err;
5922 /* Parse publication time -- up-to-date check is done when storing the
5923 * descriptor. */
5924 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
5925 tor_assert(tok->n_args == 1);
5926 if (parse_iso_time_(tok->args[0], &result->timestamp, strict_time_fmt) < 0) {
5927 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
5928 goto err;
5930 /* Parse protocol versions. */
5931 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
5932 tor_assert(tok->n_args == 1);
5933 versions = smartlist_new();
5934 smartlist_split_string(versions, tok->args[0], ",",
5935 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
5936 for (i = 0; i < smartlist_len(versions); i++) {
5937 version = (int) tor_parse_long(smartlist_get(versions, i),
5938 10, 0, INT_MAX, &num_ok, NULL);
5939 if (!num_ok) /* It's a string; let's ignore it. */
5940 continue;
5941 if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
5942 /* Avoid undefined left-shift behaviour. */
5943 continue;
5944 result->protocols |= 1 << version;
5946 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
5947 smartlist_free(versions);
5948 /* Parse encrypted introduction points. Don't verify. */
5949 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
5950 if (tok) {
5951 if (strcmp(tok->object_type, "MESSAGE")) {
5952 log_warn(LD_DIR, "Bad object type: introduction points should be of "
5953 "type MESSAGE");
5954 goto err;
5956 *intro_points_encrypted_out = tor_memdup(tok->object_body,
5957 tok->object_size);
5958 *intro_points_encrypted_size_out = tok->object_size;
5959 } else {
5960 *intro_points_encrypted_out = NULL;
5961 *intro_points_encrypted_size_out = 0;
5963 /* Parse and verify signature. */
5964 tok = find_by_keyword(tokens, R_SIGNATURE);
5965 note_crypto_pk_op(VERIFY_RTR);
5966 if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
5967 "v2 rendezvous service descriptor") < 0)
5968 goto err;
5969 /* Verify that descriptor ID belongs to public key and secret ID part. */
5970 crypto_pk_get_digest(result->pk, public_key_hash);
5971 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
5972 secret_id_part);
5973 if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
5974 log_warn(LD_REND, "Parsed descriptor ID does not match "
5975 "computed descriptor ID.");
5976 goto err;
5978 goto done;
5979 err:
5980 rend_service_descriptor_free(result);
5981 result = NULL;
5982 done:
5983 if (tokens) {
5984 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5985 smartlist_free(tokens);
5987 if (area)
5988 memarea_drop_all(area);
5989 *parsed_out = result;
5990 if (result)
5991 return 0;
5992 return -1;
5995 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
5996 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
5997 * write the result to a newly allocated string that is pointed to by
5998 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
5999 * Return 0 if decryption was successful and -1 otherwise. */
6001 rend_decrypt_introduction_points(char **ipos_decrypted,
6002 size_t *ipos_decrypted_size,
6003 const char *descriptor_cookie,
6004 const char *ipos_encrypted,
6005 size_t ipos_encrypted_size)
6007 tor_assert(ipos_encrypted);
6008 tor_assert(descriptor_cookie);
6009 if (ipos_encrypted_size < 2) {
6010 log_warn(LD_REND, "Size of encrypted introduction points is too "
6011 "small.");
6012 return -1;
6014 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
6015 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
6016 session_key[CIPHER_KEY_LEN], *dec;
6017 int declen, client_blocks;
6018 size_t pos = 0, len, client_entries_len;
6019 crypto_digest_t *digest;
6020 crypto_cipher_t *cipher;
6021 client_blocks = (int) ipos_encrypted[1];
6022 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
6023 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
6024 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
6025 log_warn(LD_REND, "Size of encrypted introduction points is too "
6026 "small.");
6027 return -1;
6029 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
6030 digest = crypto_digest_new();
6031 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
6032 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
6033 crypto_digest_get_digest(digest, client_id,
6034 REND_BASIC_AUTH_CLIENT_ID_LEN);
6035 crypto_digest_free(digest);
6036 for (pos = 2; pos < 2 + client_entries_len;
6037 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
6038 if (tor_memeq(ipos_encrypted + pos, client_id,
6039 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
6040 /* Attempt to decrypt introduction points. */
6041 cipher = crypto_cipher_new(descriptor_cookie);
6042 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
6043 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
6044 CIPHER_KEY_LEN) < 0) {
6045 log_warn(LD_REND, "Could not decrypt session key for client.");
6046 crypto_cipher_free(cipher);
6047 return -1;
6049 crypto_cipher_free(cipher);
6051 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
6052 dec = tor_malloc_zero(len + 1);
6053 declen = crypto_cipher_decrypt_with_iv(session_key, dec, len,
6054 ipos_encrypted + 2 + client_entries_len,
6055 ipos_encrypted_size - 2 - client_entries_len);
6057 if (declen < 0) {
6058 log_warn(LD_REND, "Could not decrypt introduction point string.");
6059 tor_free(dec);
6060 return -1;
6062 if (fast_memcmpstart(dec, declen, "introduction-point ")) {
6063 log_warn(LD_REND, "Decrypted introduction points don't "
6064 "look like we could parse them.");
6065 tor_free(dec);
6066 continue;
6068 *ipos_decrypted = dec;
6069 *ipos_decrypted_size = declen;
6070 return 0;
6073 log_warn(LD_REND, "Could not decrypt introduction points. Please "
6074 "check your authorization for this service!");
6075 return -1;
6076 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
6077 char *dec;
6078 int declen;
6079 if (ipos_encrypted_size < CIPHER_IV_LEN + 2) {
6080 log_warn(LD_REND, "Size of encrypted introduction points is too "
6081 "small.");
6082 return -1;
6084 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1 + 1);
6086 declen = crypto_cipher_decrypt_with_iv(descriptor_cookie, dec,
6087 ipos_encrypted_size -
6088 CIPHER_IV_LEN - 1,
6089 ipos_encrypted + 1,
6090 ipos_encrypted_size - 1);
6092 if (declen < 0) {
6093 log_warn(LD_REND, "Decrypting introduction points failed!");
6094 tor_free(dec);
6095 return -1;
6097 *ipos_decrypted = dec;
6098 *ipos_decrypted_size = declen;
6099 return 0;
6100 } else {
6101 log_warn(LD_REND, "Unknown authorization type number: %d",
6102 ipos_encrypted[0]);
6103 return -1;
6107 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
6108 * length <b>intro_points_encoded_size</b> and write the result to the
6109 * descriptor in <b>parsed</b>; return the number of successfully parsed
6110 * introduction points or -1 in case of a failure. */
6112 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
6113 const char *intro_points_encoded,
6114 size_t intro_points_encoded_size)
6116 const char *current_ipo, *end_of_intro_points;
6117 smartlist_t *tokens = NULL;
6118 directory_token_t *tok;
6119 rend_intro_point_t *intro;
6120 extend_info_t *info;
6121 int result, num_ok=1;
6122 memarea_t *area = NULL;
6123 tor_assert(parsed);
6124 /** Function may only be invoked once. */
6125 tor_assert(!parsed->intro_nodes);
6126 if (!intro_points_encoded || intro_points_encoded_size == 0) {
6127 log_warn(LD_REND, "Empty or zero size introduction point list");
6128 goto err;
6130 /* Consider one intro point after the other. */
6131 current_ipo = intro_points_encoded;
6132 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
6133 tokens = smartlist_new();
6134 parsed->intro_nodes = smartlist_new();
6135 area = memarea_new();
6137 while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
6138 "introduction-point ")) {
6139 /* Determine end of string. */
6140 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
6141 "\nintroduction-point ");
6142 if (!eos)
6143 eos = end_of_intro_points;
6144 else
6145 eos = eos+1;
6146 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
6147 /* Free tokens and clear token list. */
6148 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
6149 smartlist_clear(tokens);
6150 memarea_clear(area);
6151 /* Tokenize string. */
6152 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
6153 log_warn(LD_REND, "Error tokenizing introduction point");
6154 goto err;
6156 /* Advance to next introduction point, if available. */
6157 current_ipo = eos;
6158 /* Check minimum allowed length of introduction point. */
6159 if (smartlist_len(tokens) < 5) {
6160 log_warn(LD_REND, "Impossibly short introduction point.");
6161 goto err;
6163 /* Allocate new intro point and extend info. */
6164 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
6165 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
6166 /* Parse identifier. */
6167 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
6168 if (base32_decode(info->identity_digest, DIGEST_LEN,
6169 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
6170 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
6171 tok->args[0]);
6172 rend_intro_point_free(intro);
6173 goto err;
6175 /* Write identifier to nickname. */
6176 info->nickname[0] = '$';
6177 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
6178 info->identity_digest, DIGEST_LEN);
6179 /* Parse IP address. */
6180 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
6181 if (tor_addr_parse(&info->addr, tok->args[0])<0) {
6182 log_warn(LD_REND, "Could not parse introduction point address.");
6183 rend_intro_point_free(intro);
6184 goto err;
6186 if (tor_addr_family(&info->addr) != AF_INET) {
6187 log_warn(LD_REND, "Introduction point address was not ipv4.");
6188 rend_intro_point_free(intro);
6189 goto err;
6192 /* Parse onion port. */
6193 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
6194 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
6195 &num_ok,NULL);
6196 if (!info->port || !num_ok) {
6197 log_warn(LD_REND, "Introduction point onion port %s is invalid",
6198 escaped(tok->args[0]));
6199 rend_intro_point_free(intro);
6200 goto err;
6202 /* Parse onion key. */
6203 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
6204 if (!crypto_pk_public_exponent_ok(tok->key)) {
6205 log_warn(LD_REND,
6206 "Introduction point's onion key had invalid exponent.");
6207 rend_intro_point_free(intro);
6208 goto err;
6210 info->onion_key = tok->key;
6211 tok->key = NULL; /* Prevent free */
6212 /* Parse service key. */
6213 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
6214 if (!crypto_pk_public_exponent_ok(tok->key)) {
6215 log_warn(LD_REND,
6216 "Introduction point key had invalid exponent.");
6217 rend_intro_point_free(intro);
6218 goto err;
6220 intro->intro_key = tok->key;
6221 tok->key = NULL; /* Prevent free */
6222 /* Add extend info to list of introduction points. */
6223 smartlist_add(parsed->intro_nodes, intro);
6225 result = smartlist_len(parsed->intro_nodes);
6226 goto done;
6228 err:
6229 result = -1;
6231 done:
6232 /* Free tokens and clear token list. */
6233 if (tokens) {
6234 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
6235 smartlist_free(tokens);
6237 if (area)
6238 memarea_drop_all(area);
6240 return result;
6243 /** Parse the content of a client_key file in <b>ckstr</b> and add
6244 * rend_authorized_client_t's for each parsed client to
6245 * <b>parsed_clients</b>. Return the number of parsed clients as result
6246 * or -1 for failure. */
6248 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
6250 int result = -1;
6251 smartlist_t *tokens;
6252 directory_token_t *tok;
6253 const char *current_entry = NULL;
6254 memarea_t *area = NULL;
6255 char *err_msg = NULL;
6256 if (!ckstr || strlen(ckstr) == 0)
6257 return -1;
6258 tokens = smartlist_new();
6259 /* Begin parsing with first entry, skipping comments or whitespace at the
6260 * beginning. */
6261 area = memarea_new();
6262 current_entry = eat_whitespace(ckstr);
6263 while (!strcmpstart(current_entry, "client-name ")) {
6264 rend_authorized_client_t *parsed_entry;
6265 /* Determine end of string. */
6266 const char *eos = strstr(current_entry, "\nclient-name ");
6267 if (!eos)
6268 eos = current_entry + strlen(current_entry);
6269 else
6270 eos = eos + 1;
6271 /* Free tokens and clear token list. */
6272 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
6273 smartlist_clear(tokens);
6274 memarea_clear(area);
6275 /* Tokenize string. */
6276 if (tokenize_string(area, current_entry, eos, tokens,
6277 client_keys_token_table, 0)) {
6278 log_warn(LD_REND, "Error tokenizing client keys file.");
6279 goto err;
6281 /* Advance to next entry, if available. */
6282 current_entry = eos;
6283 /* Check minimum allowed length of token list. */
6284 if (smartlist_len(tokens) < 2) {
6285 log_warn(LD_REND, "Impossibly short client key entry.");
6286 goto err;
6288 /* Parse client name. */
6289 tok = find_by_keyword(tokens, C_CLIENT_NAME);
6290 tor_assert(tok == smartlist_get(tokens, 0));
6291 tor_assert(tok->n_args == 1);
6293 if (!rend_valid_client_name(tok->args[0])) {
6294 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
6295 "between 1 and %d, and valid characters are "
6296 "[A-Za-z0-9+-_].)", tok->args[0], REND_CLIENTNAME_MAX_LEN);
6297 goto err;
6299 /* Check if client name is duplicate. */
6300 if (strmap_get(parsed_clients, tok->args[0])) {
6301 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
6302 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
6303 goto err;
6305 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
6306 parsed_entry->client_name = tor_strdup(tok->args[0]);
6307 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
6308 /* Parse client key. */
6309 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
6310 if (tok) {
6311 parsed_entry->client_key = tok->key;
6312 tok->key = NULL; /* Prevent free */
6315 /* Parse descriptor cookie. */
6316 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
6317 tor_assert(tok->n_args == 1);
6318 if (rend_auth_decode_cookie(tok->args[0], parsed_entry->descriptor_cookie,
6319 NULL, &err_msg) < 0) {
6320 tor_assert(err_msg);
6321 log_warn(LD_REND, "%s", err_msg);
6322 tor_free(err_msg);
6323 goto err;
6326 result = strmap_size(parsed_clients);
6327 goto done;
6328 err:
6329 result = -1;
6330 done:
6331 /* Free tokens and clear token list. */
6332 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
6333 smartlist_free(tokens);
6334 if (area)
6335 memarea_drop_all(area);
6336 return result;
6339 /** Called on startup; right now we just handle scanning the unparseable
6340 * descriptor dumps, but hang anything else we might need to do in the
6341 * future here as well.
6343 void
6344 routerparse_init(void)
6347 * Check both if the sandbox is active and whether it's configured; no
6348 * point in loading all that if we won't be able to use it after the
6349 * sandbox becomes active.
6351 if (!(sandbox_is_active() || get_options()->Sandbox)) {
6352 dump_desc_init();
6356 /** Clean up all data structures used by routerparse.c at exit */
6357 void
6358 routerparse_free_all(void)
6360 dump_desc_fifo_cleanup();