fix typo
[tor.git] / src / or / routerparse.c
blob6550fa67158b8bfd00eb36c9f4839ef22597dd01
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 and directories.
10 **/
12 #define ROUTERPARSE_PRIVATE
14 #include "or.h"
15 #include "config.h"
16 #include "circuitstats.h"
17 #include "dirserv.h"
18 #include "dirvote.h"
19 #include "policies.h"
20 #include "rendcommon.h"
21 #include "router.h"
22 #include "routerlist.h"
23 #include "memarea.h"
24 #include "microdesc.h"
25 #include "networkstatus.h"
26 #include "rephist.h"
27 #include "routerkeys.h"
28 #include "routerparse.h"
29 #include "entrynodes.h"
30 #include "torcert.h"
32 #undef log
33 #include <math.h>
35 /****************************************************************************/
37 /** Enumeration of possible token types. The ones starting with K_ correspond
38 * to directory 'keywords'. A_ is for an annotation, R or C is related to
39 * hidden services, ERR_ is an error in the tokenizing process, EOF_ is an
40 * end-of-file marker, and NIL_ is used to encode not-a-token.
42 typedef enum {
43 K_ACCEPT = 0,
44 K_ACCEPT6,
45 K_DIRECTORY_SIGNATURE,
46 K_RECOMMENDED_SOFTWARE,
47 K_REJECT,
48 K_REJECT6,
49 K_ROUTER,
50 K_SIGNED_DIRECTORY,
51 K_SIGNING_KEY,
52 K_ONION_KEY,
53 K_ONION_KEY_NTOR,
54 K_ROUTER_SIGNATURE,
55 K_PUBLISHED,
56 K_RUNNING_ROUTERS,
57 K_ROUTER_STATUS,
58 K_PLATFORM,
59 K_OPT,
60 K_BANDWIDTH,
61 K_CONTACT,
62 K_NETWORK_STATUS,
63 K_UPTIME,
64 K_DIR_SIGNING_KEY,
65 K_FAMILY,
66 K_FINGERPRINT,
67 K_HIBERNATING,
68 K_READ_HISTORY,
69 K_WRITE_HISTORY,
70 K_NETWORK_STATUS_VERSION,
71 K_DIR_SOURCE,
72 K_DIR_OPTIONS,
73 K_CLIENT_VERSIONS,
74 K_SERVER_VERSIONS,
75 K_OR_ADDRESS,
76 K_ID,
77 K_P,
78 K_P6,
79 K_R,
80 K_A,
81 K_S,
82 K_V,
83 K_W,
84 K_M,
85 K_EXTRA_INFO,
86 K_EXTRA_INFO_DIGEST,
87 K_CACHES_EXTRA_INFO,
88 K_HIDDEN_SERVICE_DIR,
89 K_ALLOW_SINGLE_HOP_EXITS,
90 K_IPV6_POLICY,
91 K_ROUTER_SIG_ED25519,
92 K_IDENTITY_ED25519,
93 K_MASTER_KEY_ED25519,
94 K_ONION_KEY_CROSSCERT,
95 K_NTOR_ONION_KEY_CROSSCERT,
97 K_DIRREQ_END,
98 K_DIRREQ_V2_IPS,
99 K_DIRREQ_V3_IPS,
100 K_DIRREQ_V2_REQS,
101 K_DIRREQ_V3_REQS,
102 K_DIRREQ_V2_SHARE,
103 K_DIRREQ_V3_SHARE,
104 K_DIRREQ_V2_RESP,
105 K_DIRREQ_V3_RESP,
106 K_DIRREQ_V2_DIR,
107 K_DIRREQ_V3_DIR,
108 K_DIRREQ_V2_TUN,
109 K_DIRREQ_V3_TUN,
110 K_ENTRY_END,
111 K_ENTRY_IPS,
112 K_CELL_END,
113 K_CELL_PROCESSED,
114 K_CELL_QUEUED,
115 K_CELL_TIME,
116 K_CELL_CIRCS,
117 K_EXIT_END,
118 K_EXIT_WRITTEN,
119 K_EXIT_READ,
120 K_EXIT_OPENED,
122 K_DIR_KEY_CERTIFICATE_VERSION,
123 K_DIR_IDENTITY_KEY,
124 K_DIR_KEY_PUBLISHED,
125 K_DIR_KEY_EXPIRES,
126 K_DIR_KEY_CERTIFICATION,
127 K_DIR_KEY_CROSSCERT,
128 K_DIR_ADDRESS,
129 K_DIR_TUNNELLED,
131 K_VOTE_STATUS,
132 K_VALID_AFTER,
133 K_FRESH_UNTIL,
134 K_VALID_UNTIL,
135 K_VOTING_DELAY,
137 K_KNOWN_FLAGS,
138 K_PARAMS,
139 K_BW_WEIGHTS,
140 K_VOTE_DIGEST,
141 K_CONSENSUS_DIGEST,
142 K_ADDITIONAL_DIGEST,
143 K_ADDITIONAL_SIGNATURE,
144 K_CONSENSUS_METHODS,
145 K_CONSENSUS_METHOD,
146 K_LEGACY_DIR_KEY,
147 K_DIRECTORY_FOOTER,
148 K_PACKAGE,
150 A_PURPOSE,
151 A_LAST_LISTED,
152 A_UNKNOWN_,
154 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
155 R_VERSION,
156 R_PERMANENT_KEY,
157 R_SECRET_ID_PART,
158 R_PUBLICATION_TIME,
159 R_PROTOCOL_VERSIONS,
160 R_INTRODUCTION_POINTS,
161 R_SIGNATURE,
163 R_IPO_IDENTIFIER,
164 R_IPO_IP_ADDRESS,
165 R_IPO_ONION_PORT,
166 R_IPO_ONION_KEY,
167 R_IPO_SERVICE_KEY,
169 C_CLIENT_NAME,
170 C_DESCRIPTOR_COOKIE,
171 C_CLIENT_KEY,
173 ERR_,
174 EOF_,
175 NIL_
176 } directory_keyword;
178 #define MIN_ANNOTATION A_PURPOSE
179 #define MAX_ANNOTATION A_UNKNOWN_
181 /** Structure to hold a single directory token.
183 * We parse a directory by breaking it into "tokens", each consisting
184 * of a keyword, a line full of arguments, and a binary object. The
185 * arguments and object are both optional, depending on the keyword
186 * type.
188 * This structure is only allocated in memareas; do not allocate it on
189 * the heap, or token_clear() won't work.
191 typedef struct directory_token_t {
192 directory_keyword tp; /**< Type of the token. */
193 int n_args:30; /**< Number of elements in args */
194 char **args; /**< Array of arguments from keyword line. */
196 char *object_type; /**< -----BEGIN [object_type]-----*/
197 size_t object_size; /**< Bytes in object_body */
198 char *object_body; /**< Contents of object, base64-decoded. */
200 crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
202 char *error; /**< For ERR_ tokens only. */
203 } directory_token_t;
205 /* ********************************************************************** */
207 /** We use a table of rules to decide how to parse each token type. */
209 /** Rules for whether the keyword needs an object. */
210 typedef enum {
211 NO_OBJ, /**< No object, ever. */
212 NEED_OBJ, /**< Object is required. */
213 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
214 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
215 NEED_KEY, /**< Object is required, and must be a public key. */
216 OBJ_OK, /**< Object is optional. */
217 } obj_syntax;
219 #define AT_START 1
220 #define AT_END 2
222 /** Determines the parsing rules for a single token type. */
223 typedef struct token_rule_t {
224 /** The string value of the keyword identifying the type of item. */
225 const char *t;
226 /** The corresponding directory_keyword enum. */
227 directory_keyword v;
228 /** Minimum number of arguments for this item */
229 int min_args;
230 /** Maximum number of arguments for this item */
231 int max_args;
232 /** If true, we concatenate all arguments for this item into a single
233 * string. */
234 int concat_args;
235 /** Requirements on object syntax for this item. */
236 obj_syntax os;
237 /** Lowest number of times this item may appear in a document. */
238 int min_cnt;
239 /** Highest number of times this item may appear in a document. */
240 int max_cnt;
241 /** One or more of AT_START/AT_END to limit where the item may appear in a
242 * document. */
243 int pos;
244 /** True iff this token is an annotation. */
245 int is_annotation;
246 } token_rule_t;
249 * Helper macros to define token tables. 's' is a string, 't' is a
250 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
251 * object syntax.
255 /** Appears to indicate the end of a table. */
256 #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
257 /** An item with no restrictions: used for obsolete document types */
258 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
259 /** An item with no restrictions on multiplicity or location. */
260 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
261 /** An item that must appear exactly once */
262 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
263 /** An item that must appear exactly once, at the start of the document */
264 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
265 /** An item that must appear exactly once, at the end of the document */
266 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
267 /** An item that must appear one or more times */
268 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
269 /** An item that must appear no more than once */
270 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
271 /** An annotation that must appear no more than once */
272 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
274 /* Argument multiplicity: any number of arguments. */
275 #define ARGS 0,INT_MAX,0
276 /* Argument multiplicity: no arguments. */
277 #define NO_ARGS 0,0,0
278 /* Argument multiplicity: concatenate all arguments. */
279 #define CONCAT_ARGS 1,1,1
280 /* Argument multiplicity: at least <b>n</b> arguments. */
281 #define GE(n) n,INT_MAX,0
282 /* Argument multiplicity: exactly <b>n</b> arguments. */
283 #define EQ(n) n,n,0
285 /** List of tokens recognized in router descriptors */
286 static token_rule_t routerdesc_token_table[] = {
287 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
288 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
289 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
290 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
291 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
292 T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
293 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
294 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
295 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
296 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
297 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
298 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
299 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
300 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
301 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
302 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
303 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
304 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
305 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
306 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
307 T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
308 T01("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ),
309 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
310 T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),
311 T01("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT,
312 EQ(1), NEED_OBJ ),
314 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
316 T01("family", K_FAMILY, ARGS, NO_OBJ ),
317 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
318 T0N("or-address", K_OR_ADDRESS, GE(1), NO_OBJ ),
320 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
321 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
322 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
323 T01("tunnelled-dir-server",K_DIR_TUNNELLED, NO_ARGS, NO_OBJ ),
325 END_OF_TABLE
328 /** List of tokens recognized in extra-info documents. */
329 static token_rule_t extrainfo_token_table[] = {
330 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
331 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
332 T01("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ),
333 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ),
334 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
335 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
336 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
337 T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ),
338 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ),
339 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ),
340 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ),
341 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ),
342 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ),
343 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ),
344 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ),
345 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ),
346 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ),
347 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ),
348 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ),
349 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ),
350 T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ),
351 T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ),
352 T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ),
353 T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ),
354 T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ),
355 T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ),
356 T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ),
357 T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ),
358 T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ),
359 T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ),
360 T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ),
362 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
364 END_OF_TABLE
367 /** List of tokens recognized in the body part of v3 networkstatus
368 * documents. */
369 static token_rule_t rtrstatus_token_table[] = {
370 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
371 T1( "r", K_R, GE(7), NO_OBJ ),
372 T0N("a", K_A, GE(1), NO_OBJ ),
373 T1( "s", K_S, ARGS, NO_OBJ ),
374 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
375 T01("w", K_W, ARGS, NO_OBJ ),
376 T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
377 T0N("id", K_ID, GE(2), NO_OBJ ),
378 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
379 END_OF_TABLE
382 /** List of tokens common to V3 authority certificates and V3 consensuses. */
383 #define CERTIFICATE_MEMBERS \
384 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
385 GE(1), NO_OBJ ), \
386 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
387 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
388 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
389 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
390 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
391 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
392 NO_ARGS, NEED_OBJ), \
393 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
395 /** List of tokens recognized in V3 authority certificates. */
396 static token_rule_t dir_key_certificate_table[] = {
397 CERTIFICATE_MEMBERS
398 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
399 END_OF_TABLE
402 /** List of tokens recognized in rendezvous service descriptors */
403 static token_rule_t desc_token_table[] = {
404 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
405 EQ(1), NO_OBJ),
406 T1("version", R_VERSION, EQ(1), NO_OBJ),
407 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
408 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
409 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
410 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
411 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
412 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
413 END_OF_TABLE
416 /** List of tokens recognized in the (encrypted) list of introduction points of
417 * rendezvous service descriptors */
418 static token_rule_t ipo_token_table[] = {
419 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
420 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
421 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
422 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
423 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
424 END_OF_TABLE
427 /** List of tokens recognized in the (possibly encrypted) list of introduction
428 * points of rendezvous service descriptors */
429 static token_rule_t client_keys_token_table[] = {
430 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
431 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
432 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
433 END_OF_TABLE
436 /** List of tokens recognized in V3 networkstatus votes. */
437 static token_rule_t networkstatus_token_table[] = {
438 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
439 GE(1), NO_OBJ ),
440 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
441 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
442 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
443 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
444 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
445 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
446 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
447 T01("params", K_PARAMS, ARGS, NO_OBJ ),
448 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
449 T0N("package", K_PACKAGE, CONCAT_ARGS, NO_OBJ ),
451 CERTIFICATE_MEMBERS
453 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
454 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
455 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
456 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
457 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
458 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
459 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
460 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
462 END_OF_TABLE
465 /** List of tokens recognized in V3 networkstatus consensuses. */
466 static token_rule_t networkstatus_consensus_token_table[] = {
467 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
468 GE(1), NO_OBJ ),
469 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
470 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
471 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
472 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
473 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
475 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
477 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
478 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
479 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
481 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
483 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
484 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
485 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
486 T01("params", K_PARAMS, ARGS, NO_OBJ ),
488 END_OF_TABLE
491 /** List of tokens recognized in the footer of v1 directory footers. */
492 static token_rule_t networkstatus_vote_footer_token_table[] = {
493 T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
494 T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
495 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
496 END_OF_TABLE
499 /** List of tokens recognized in detached networkstatus signature documents. */
500 static token_rule_t networkstatus_detached_signature_token_table[] = {
501 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
502 T("additional-digest", K_ADDITIONAL_DIGEST,GE(3), NO_OBJ ),
503 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
504 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
505 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
506 T("additional-signature", K_ADDITIONAL_SIGNATURE, GE(4), NEED_OBJ ),
507 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
508 END_OF_TABLE
511 /** List of tokens recognized in microdescriptors */
512 static token_rule_t microdesc_token_table[] = {
513 T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
514 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
515 T0N("id", K_ID, GE(2), NO_OBJ ),
516 T0N("a", K_A, GE(1), NO_OBJ ),
517 T01("family", K_FAMILY, ARGS, NO_OBJ ),
518 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
519 T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ),
520 A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
521 END_OF_TABLE
524 #undef T
526 /* static function prototypes */
527 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
528 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok,
529 unsigned fmt_flags);
530 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
532 static int router_get_hash_impl_helper(const char *s, size_t s_len,
533 const char *start_str,
534 const char *end_str, char end_c,
535 const char **start_out, const char **end_out);
536 static int router_get_hash_impl(const char *s, size_t s_len, char *digest,
537 const char *start_str, const char *end_str,
538 char end_char,
539 digest_algorithm_t alg);
540 static int router_get_hashes_impl(const char *s, size_t s_len,
541 common_digests_t *digests,
542 const char *start_str, const char *end_str,
543 char end_char);
544 static void token_clear(directory_token_t *tok);
545 static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k);
546 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
547 static directory_token_t *find_by_keyword_(smartlist_t *s,
548 directory_keyword keyword,
549 const char *keyword_str);
550 #define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword)
551 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
552 directory_keyword keyword);
554 #define TS_ANNOTATIONS_OK 1
555 #define TS_NOCHECK 2
556 #define TS_NO_NEW_ANNOTATIONS 4
557 static int tokenize_string(memarea_t *area,
558 const char *start, const char *end,
559 smartlist_t *out,
560 token_rule_t *table,
561 int flags);
562 static directory_token_t *get_next_token(memarea_t *area,
563 const char **s,
564 const char *eos,
565 token_rule_t *table);
566 #define CST_CHECK_AUTHORITY (1<<0)
567 #define CST_NO_CHECK_OBJTYPE (1<<1)
568 static int check_signature_token(const char *digest,
569 ssize_t digest_len,
570 directory_token_t *tok,
571 crypto_pk_t *pkey,
572 int flags,
573 const char *doctype);
575 #undef DEBUG_AREA_ALLOC
577 #ifdef DEBUG_AREA_ALLOC
578 #define DUMP_AREA(a,name) STMT_BEGIN \
579 size_t alloc=0, used=0; \
580 memarea_get_stats((a),&alloc,&used); \
581 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
582 name, (unsigned long)alloc, (unsigned long)used); \
583 STMT_END
584 #else
585 #define DUMP_AREA(a,name) STMT_NIL
586 #endif
588 /** Last time we dumped a descriptor to disk. */
589 static time_t last_desc_dumped = 0;
591 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
592 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
593 * than one descriptor to disk per minute. If there is already such a
594 * file in the data directory, overwrite it. */
595 static void
596 dump_desc(const char *desc, const char *type)
598 time_t now = time(NULL);
599 tor_assert(desc);
600 tor_assert(type);
601 if (!last_desc_dumped || last_desc_dumped + 60 < now) {
602 char *debugfile = get_datadir_fname("unparseable-desc");
603 size_t filelen = 50 + strlen(type) + strlen(desc);
604 char *content = tor_malloc_zero(filelen);
605 tor_snprintf(content, filelen, "Unable to parse descriptor of type "
606 "%s:\n%s", type, desc);
607 write_str_to_file(debugfile, content, 1);
608 log_info(LD_DIR, "Unable to parse descriptor of type %s. See file "
609 "unparseable-desc in data directory for details.", type);
610 tor_free(content);
611 tor_free(debugfile);
612 last_desc_dumped = now;
616 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
617 * <b>s</b>. Return 0 on success, -1 on failure.
620 router_get_dir_hash(const char *s, char *digest)
622 return router_get_hash_impl(s, strlen(s), digest,
623 "signed-directory","\ndirectory-signature",'\n',
624 DIGEST_SHA1);
627 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
628 * <b>s</b>. Return 0 on success, -1 on failure.
631 router_get_router_hash(const char *s, size_t s_len, char *digest)
633 return router_get_hash_impl(s, s_len, digest,
634 "router ","\nrouter-signature", '\n',
635 DIGEST_SHA1);
638 /** Set <b>digests</b> to all the digests of the consensus document in
639 * <b>s</b> */
641 router_get_networkstatus_v3_hashes(const char *s, common_digests_t *digests)
643 return router_get_hashes_impl(s,strlen(s),digests,
644 "network-status-version",
645 "\ndirectory-signature",
646 ' ');
649 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
650 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
652 router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
654 return router_get_hash_impl(s, s_len, digest, "extra-info",
655 "\nrouter-signature",'\n', DIGEST_SHA1);
658 /** Helper: used to generate signatures for routers, directories and
659 * network-status objects. Given a <b>digest_len</b>-byte digest in
660 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
661 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
662 * and return the new signature on success or NULL on failure.
664 char *
665 router_get_dirobj_signature(const char *digest,
666 size_t digest_len,
667 const crypto_pk_t *private_key)
669 char *signature;
670 size_t i, keysize;
671 int siglen;
672 char *buf = NULL;
673 size_t buf_len;
674 /* overestimate of BEGIN/END lines total len. */
675 #define BEGIN_END_OVERHEAD_LEN 64
677 keysize = crypto_pk_keysize(private_key);
678 signature = tor_malloc(keysize);
679 siglen = crypto_pk_private_sign(private_key, signature, keysize,
680 digest, digest_len);
681 if (siglen < 0) {
682 log_warn(LD_BUG,"Couldn't sign digest.");
683 goto err;
686 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
687 buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN;
688 buf = tor_malloc(buf_len);
690 if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
691 goto truncated;
693 i = strlen(buf);
694 if (base64_encode(buf+i, buf_len-i, signature, siglen,
695 BASE64_ENCODE_MULTILINE) < 0) {
696 log_warn(LD_BUG,"couldn't base64-encode signature");
697 goto err;
700 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
701 goto truncated;
703 tor_free(signature);
704 return buf;
706 truncated:
707 log_warn(LD_BUG,"tried to exceed string length.");
708 err:
709 tor_free(signature);
710 tor_free(buf);
711 return NULL;
714 /** Helper: used to generate signatures for routers, directories and
715 * network-status objects. Given a digest in <b>digest</b> and a secret
716 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
717 * surround it with -----BEGIN/END----- pairs, and write it to the
718 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
719 * failure.
722 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
723 size_t digest_len, crypto_pk_t *private_key)
725 size_t sig_len, s_len;
726 char *sig = router_get_dirobj_signature(digest, digest_len, private_key);
727 if (!sig) {
728 log_warn(LD_BUG, "No signature generated");
729 return -1;
731 sig_len = strlen(sig);
732 s_len = strlen(buf);
733 if (sig_len + s_len + 1 > buf_len) {
734 log_warn(LD_BUG, "Not enough room for signature");
735 tor_free(sig);
736 return -1;
738 memcpy(buf+s_len, sig, sig_len+1);
739 tor_free(sig);
740 return 0;
743 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
744 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
745 * entries. Else, return VS_OLD if every member of
746 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
747 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
748 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
749 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
750 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
751 * VS_UNRECOMMENDED.
753 * (versionlist is a comma-separated list of version strings,
754 * optionally prefixed with "Tor". Versions that can't be parsed are
755 * ignored.)
757 version_status_t
758 tor_version_is_obsolete(const char *myversion, const char *versionlist)
760 tor_version_t mine, other;
761 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
762 found_any_in_series = 0, r, same;
763 version_status_t ret = VS_UNRECOMMENDED;
764 smartlist_t *version_sl;
766 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
767 myversion, versionlist);
769 if (tor_version_parse(myversion, &mine)) {
770 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
771 tor_assert(0);
773 version_sl = smartlist_new();
774 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
776 if (!strlen(versionlist)) { /* no authorities cared or agreed */
777 ret = VS_EMPTY;
778 goto done;
781 SMARTLIST_FOREACH_BEGIN(version_sl, const char *, cp) {
782 if (!strcmpstart(cp, "Tor "))
783 cp += 4;
785 if (tor_version_parse(cp, &other)) {
786 /* Couldn't parse other; it can't be a match. */
787 } else {
788 same = tor_version_same_series(&mine, &other);
789 if (same)
790 found_any_in_series = 1;
791 r = tor_version_compare(&mine, &other);
792 if (r==0) {
793 ret = VS_RECOMMENDED;
794 goto done;
795 } else if (r<0) {
796 found_newer = 1;
797 if (same)
798 found_newer_in_series = 1;
799 } else if (r>0) {
800 found_older = 1;
803 } SMARTLIST_FOREACH_END(cp);
805 /* We didn't find the listed version. Is it new or old? */
806 if (found_any_in_series && !found_newer_in_series && found_newer) {
807 ret = VS_NEW_IN_SERIES;
808 } else if (found_newer && !found_older) {
809 ret = VS_OLD;
810 } else if (found_older && !found_newer) {
811 ret = VS_NEW;
812 } else {
813 ret = VS_UNRECOMMENDED;
816 done:
817 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
818 smartlist_free(version_sl);
819 return ret;
822 /** Return true iff <b>key</b> is allowed to sign directories.
824 static int
825 dir_signing_key_is_trusted(crypto_pk_t *key)
827 char digest[DIGEST_LEN];
828 if (!key) return 0;
829 if (crypto_pk_get_digest(key, digest) < 0) {
830 log_warn(LD_DIR, "Error computing dir-signing-key digest");
831 return 0;
833 if (!router_digest_is_trusted_dir(digest)) {
834 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
835 return 0;
837 return 1;
840 /** Check whether the object body of the token in <b>tok</b> has a good
841 * signature for <b>digest</b> using key <b>pkey</b>. If
842 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
843 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
844 * the object type of the signature object. Use <b>doctype</b> as the type of
845 * the document when generating log messages. Return 0 on success, negative
846 * on failure.
848 static int
849 check_signature_token(const char *digest,
850 ssize_t digest_len,
851 directory_token_t *tok,
852 crypto_pk_t *pkey,
853 int flags,
854 const char *doctype)
856 char *signed_digest;
857 size_t keysize;
858 const int check_authority = (flags & CST_CHECK_AUTHORITY);
859 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
861 tor_assert(pkey);
862 tor_assert(tok);
863 tor_assert(digest);
864 tor_assert(doctype);
866 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
867 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
868 doctype);
869 return -1;
872 if (check_objtype) {
873 if (strcmp(tok->object_type, "SIGNATURE")) {
874 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
875 return -1;
879 keysize = crypto_pk_keysize(pkey);
880 signed_digest = tor_malloc(keysize);
881 if (crypto_pk_public_checksig(pkey, signed_digest, keysize,
882 tok->object_body, tok->object_size)
883 < digest_len) {
884 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
885 tor_free(signed_digest);
886 return -1;
888 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
889 // hex_str(signed_digest,4));
890 if (tor_memneq(digest, signed_digest, digest_len)) {
891 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
892 tor_free(signed_digest);
893 return -1;
895 tor_free(signed_digest);
896 return 0;
899 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
900 * or to the first of the annotations proceeding the next router or
901 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
902 * we found an extrainfo, or false if found a router. Do not scan beyond
903 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
904 static int
905 find_start_of_next_router_or_extrainfo(const char **s_ptr,
906 const char *eos,
907 int *is_extrainfo_out)
909 const char *annotations = NULL;
910 const char *s = *s_ptr;
912 s = eat_whitespace_eos(s, eos);
914 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
915 /* We're at the start of a line. */
916 tor_assert(*s != '\n');
918 if (*s == '@' && !annotations) {
919 annotations = s;
920 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
921 *s_ptr = annotations ? annotations : s;
922 *is_extrainfo_out = 0;
923 return 0;
924 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
925 *s_ptr = annotations ? annotations : s;
926 *is_extrainfo_out = 1;
927 return 0;
930 if (!(s = memchr(s+1, '\n', eos-(s+1))))
931 break;
932 s = eat_whitespace_eos(s, eos);
934 return -1;
937 /** Given a string *<b>s</b> containing a concatenated sequence of router
938 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
939 * them and stores the result in <b>dest</b>. All routers are marked running
940 * and valid. Advances *s to a point immediately following the last router
941 * entry. Ignore any trailing router entries that are not complete.
943 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
944 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
945 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
947 * Returns 0 on success and -1 on failure. Adds a digest to
948 * <b>invalid_digests_out</b> for every entry that was unparseable or
949 * invalid. (This may cause duplicate entries.)
952 router_parse_list_from_string(const char **s, const char *eos,
953 smartlist_t *dest,
954 saved_location_t saved_location,
955 int want_extrainfo,
956 int allow_annotations,
957 const char *prepend_annotations,
958 smartlist_t *invalid_digests_out)
960 routerinfo_t *router;
961 extrainfo_t *extrainfo;
962 signed_descriptor_t *signed_desc = NULL;
963 void *elt;
964 const char *end, *start;
965 int have_extrainfo;
967 tor_assert(s);
968 tor_assert(*s);
969 tor_assert(dest);
971 start = *s;
972 if (!eos)
973 eos = *s + strlen(*s);
975 tor_assert(eos >= *s);
977 while (1) {
978 char raw_digest[DIGEST_LEN];
979 int have_raw_digest = 0;
980 int dl_again = 0;
981 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
982 break;
984 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
985 if (end)
986 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
987 if (end)
988 end += strlen("\n-----END SIGNATURE-----\n");
990 if (!end)
991 break;
993 elt = NULL;
995 if (have_extrainfo && want_extrainfo) {
996 routerlist_t *rl = router_get_routerlist();
997 have_raw_digest = router_get_extrainfo_hash(*s, end-*s, raw_digest) == 0;
998 extrainfo = extrainfo_parse_entry_from_string(*s, end,
999 saved_location != SAVED_IN_CACHE,
1000 rl->identity_map, &dl_again);
1001 if (extrainfo) {
1002 signed_desc = &extrainfo->cache_info;
1003 elt = extrainfo;
1005 } else if (!have_extrainfo && !want_extrainfo) {
1006 have_raw_digest = router_get_router_hash(*s, end-*s, raw_digest) == 0;
1007 router = router_parse_entry_from_string(*s, end,
1008 saved_location != SAVED_IN_CACHE,
1009 allow_annotations,
1010 prepend_annotations, &dl_again);
1011 if (router) {
1012 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1013 router_describe(router),
1014 router_purpose_to_string(router->purpose));
1015 signed_desc = &router->cache_info;
1016 elt = router;
1019 if (! elt && ! dl_again && have_raw_digest && invalid_digests_out) {
1020 smartlist_add(invalid_digests_out, tor_memdup(raw_digest, DIGEST_LEN));
1022 if (!elt) {
1023 *s = end;
1024 continue;
1026 if (saved_location != SAVED_NOWHERE) {
1027 tor_assert(signed_desc);
1028 signed_desc->saved_location = saved_location;
1029 signed_desc->saved_offset = *s - start;
1031 *s = end;
1032 smartlist_add(dest, elt);
1035 return 0;
1038 /* For debugging: define to count every descriptor digest we've seen so we
1039 * know if we need to try harder to avoid duplicate verifies. */
1040 #undef COUNT_DISTINCT_DIGESTS
1042 #ifdef COUNT_DISTINCT_DIGESTS
1043 static digestmap_t *verified_digests = NULL;
1044 #endif
1046 /** Log the total count of the number of distinct router digests we've ever
1047 * verified. When compared to the number of times we've verified routerdesc
1048 * signatures <i>in toto</i>, this will tell us if we're doing too much
1049 * multiple-verification. */
1050 void
1051 dump_distinct_digest_count(int severity)
1053 #ifdef COUNT_DISTINCT_DIGESTS
1054 if (!verified_digests)
1055 verified_digests = digestmap_new();
1056 tor_log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1057 digestmap_size(verified_digests));
1058 #else
1059 (void)severity; /* suppress "unused parameter" warning */
1060 #endif
1063 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1064 * with at least one argument (use GE(1) in setup). If found, store
1065 * address and port number to <b>addr_out</b> and
1066 * <b>port_out</b>. Return number of OR ports found. */
1067 static int
1068 find_single_ipv6_orport(const smartlist_t *list,
1069 tor_addr_t *addr_out,
1070 uint16_t *port_out)
1072 int ret = 0;
1073 tor_assert(list != NULL);
1074 tor_assert(addr_out != NULL);
1075 tor_assert(port_out != NULL);
1077 SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) {
1078 tor_addr_t a;
1079 maskbits_t bits;
1080 uint16_t port_min, port_max;
1081 tor_assert(t->n_args >= 1);
1082 /* XXXX Prop186 the full spec allows much more than this. */
1083 if (tor_addr_parse_mask_ports(t->args[0], 0,
1084 &a, &bits, &port_min,
1085 &port_max) == AF_INET6 &&
1086 bits == 128 &&
1087 port_min == port_max) {
1088 /* Okay, this is one we can understand. Use it and ignore
1089 any potential more addresses in list. */
1090 tor_addr_copy(addr_out, &a);
1091 *port_out = port_min;
1092 ret = 1;
1093 break;
1095 } SMARTLIST_FOREACH_END(t);
1097 return ret;
1100 /** Helper function: reads a single router entry from *<b>s</b> ...
1101 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1102 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1103 * s through end into the signed_descriptor_body of the resulting
1104 * routerinfo_t.
1106 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1108 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1109 * before the router; if it's false, reject the router if it's annotated. If
1110 * <b>prepend_annotations</b> is set, it should contain some annotations:
1111 * append them to the front of the router before parsing it, and keep them
1112 * around when caching the router.
1114 * Only one of allow_annotations and prepend_annotations may be set.
1116 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1117 * if it's okay to try to download a descriptor with this same digest again,
1118 * and 0 if it isn't. (It might not be okay to download it again if part of
1119 * the part covered by the digest is invalid.)
1121 routerinfo_t *
1122 router_parse_entry_from_string(const char *s, const char *end,
1123 int cache_copy, int allow_annotations,
1124 const char *prepend_annotations,
1125 int *can_dl_again_out)
1127 routerinfo_t *router = NULL;
1128 char digest[128];
1129 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1130 directory_token_t *tok;
1131 struct in_addr in;
1132 const char *start_of_annotations, *cp, *s_dup = s;
1133 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1134 int ok = 1;
1135 memarea_t *area = NULL;
1136 tor_cert_t *ntor_cc_cert = NULL;
1137 /* Do not set this to '1' until we have parsed everything that we intend to
1138 * parse that's covered by the hash. */
1139 int can_dl_again = 0;
1141 tor_assert(!allow_annotations || !prepend_annotations);
1143 if (!end) {
1144 end = s + strlen(s);
1147 /* point 'end' to a point immediately after the final newline. */
1148 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1149 --end;
1151 area = memarea_new();
1152 tokens = smartlist_new();
1153 if (prepend_annotations) {
1154 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1155 routerdesc_token_table,TS_NOCHECK)) {
1156 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1157 goto err;
1161 start_of_annotations = s;
1162 cp = tor_memstr(s, end-s, "\nrouter ");
1163 if (!cp) {
1164 if (end-s < 7 || strcmpstart(s, "router ")) {
1165 log_warn(LD_DIR, "No router keyword found.");
1166 goto err;
1168 } else {
1169 s = cp+1;
1172 if (start_of_annotations != s) { /* We have annotations */
1173 if (allow_annotations) {
1174 if (tokenize_string(area,start_of_annotations,s,tokens,
1175 routerdesc_token_table,TS_NOCHECK)) {
1176 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1177 goto err;
1179 } else {
1180 log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
1181 "loaded from disk. Dropping it.");
1182 goto err;
1186 if (router_get_router_hash(s, end - s, digest) < 0) {
1187 log_warn(LD_DIR, "Couldn't compute router hash.");
1188 goto err;
1191 int flags = 0;
1192 if (allow_annotations)
1193 flags |= TS_ANNOTATIONS_OK;
1194 if (prepend_annotations)
1195 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1197 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1198 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1199 goto err;
1203 if (smartlist_len(tokens) < 2) {
1204 log_warn(LD_DIR, "Impossibly short router descriptor.");
1205 goto err;
1208 tok = find_by_keyword(tokens, K_ROUTER);
1209 const int router_token_pos = smartlist_pos(tokens, tok);
1210 tor_assert(tok->n_args >= 5);
1212 router = tor_malloc_zero(sizeof(routerinfo_t));
1213 router->cert_expiration_time = TIME_MAX;
1214 router->cache_info.routerlist_index = -1;
1215 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1216 router->cache_info.signed_descriptor_len = end-s;
1217 if (cache_copy) {
1218 size_t len = router->cache_info.signed_descriptor_len +
1219 router->cache_info.annotations_len;
1220 char *cp =
1221 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1222 if (prepend_annotations) {
1223 memcpy(cp, prepend_annotations, prepend_len);
1224 cp += prepend_len;
1226 /* This assertion will always succeed.
1227 * len == signed_desc_len + annotations_len
1228 * == end-s + s-start_of_annotations + prepend_len
1229 * == end-start_of_annotations + prepend_len
1230 * We already wrote prepend_len bytes into the buffer; now we're
1231 * writing end-start_of_annotations -NM. */
1232 tor_assert(cp+(end-start_of_annotations) ==
1233 router->cache_info.signed_descriptor_body+len);
1234 memcpy(cp, start_of_annotations, end-start_of_annotations);
1235 router->cache_info.signed_descriptor_body[len] = '\0';
1236 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1238 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1240 router->nickname = tor_strdup(tok->args[0]);
1241 if (!is_legal_nickname(router->nickname)) {
1242 log_warn(LD_DIR,"Router nickname is invalid");
1243 goto err;
1245 if (!tor_inet_aton(tok->args[1], &in)) {
1246 log_warn(LD_DIR,"Router address is not an IP address.");
1247 goto err;
1249 router->addr = ntohl(in.s_addr);
1251 router->or_port =
1252 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1253 if (!ok) {
1254 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1255 goto err;
1257 router->dir_port =
1258 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1259 if (!ok) {
1260 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1261 goto err;
1264 tok = find_by_keyword(tokens, K_BANDWIDTH);
1265 tor_assert(tok->n_args >= 3);
1266 router->bandwidthrate = (int)
1267 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1269 if (!ok) {
1270 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1271 escaped(tok->args[0]));
1272 goto err;
1274 router->bandwidthburst =
1275 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1276 if (!ok) {
1277 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1278 goto err;
1280 router->bandwidthcapacity = (int)
1281 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1282 if (!ok) {
1283 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1284 goto err;
1287 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1288 tor_assert(tok->n_args);
1289 router->purpose = router_purpose_from_string(tok->args[0]);
1290 } else {
1291 router->purpose = ROUTER_PURPOSE_GENERAL;
1293 router->cache_info.send_unencrypted =
1294 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1296 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1297 tor_assert(tok->n_args >= 1);
1298 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1299 if (!ok) {
1300 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1301 goto err;
1305 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1306 tor_assert(tok->n_args >= 1);
1307 router->is_hibernating
1308 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1311 tok = find_by_keyword(tokens, K_PUBLISHED);
1312 tor_assert(tok->n_args == 1);
1313 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1314 goto err;
1316 tok = find_by_keyword(tokens, K_ONION_KEY);
1317 if (!crypto_pk_public_exponent_ok(tok->key)) {
1318 log_warn(LD_DIR,
1319 "Relay's onion key had invalid exponent.");
1320 goto err;
1322 router->onion_pkey = tok->key;
1323 tok->key = NULL; /* Prevent free */
1325 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
1326 curve25519_public_key_t k;
1327 tor_assert(tok->n_args >= 1);
1328 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
1329 log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
1330 goto err;
1332 router->onion_curve25519_pkey =
1333 tor_memdup(&k, sizeof(curve25519_public_key_t));
1336 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1337 router->identity_pkey = tok->key;
1338 tok->key = NULL; /* Prevent free */
1339 if (crypto_pk_get_digest(router->identity_pkey,
1340 router->cache_info.identity_digest)) {
1341 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1345 directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok,
1346 *master_key_tok;
1347 ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
1348 ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
1349 master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519);
1350 cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT);
1351 cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT);
1352 int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok +
1353 !!cc_tap_tok + !!cc_ntor_tok;
1354 if ((n_ed_toks != 0 && n_ed_toks != 4) ||
1355 (n_ed_toks == 4 && !router->onion_curve25519_pkey)) {
1356 log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
1357 "cross-certification support");
1358 goto err;
1360 if (master_key_tok && !ed_sig_tok) {
1361 log_warn(LD_DIR, "Router descriptor has ed25519 master key but no "
1362 "certificate");
1363 goto err;
1365 if (ed_sig_tok) {
1366 tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok);
1367 const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
1368 if (ed_cert_token_pos == -1 || router_token_pos == -1 ||
1369 (ed_cert_token_pos != router_token_pos + 1 &&
1370 ed_cert_token_pos != router_token_pos - 1)) {
1371 log_warn(LD_DIR, "Ed25519 certificate in wrong position");
1372 goto err;
1374 if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
1375 log_warn(LD_DIR, "Ed25519 signature in wrong position");
1376 goto err;
1378 if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
1379 log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
1380 goto err;
1382 if (strcmp(cc_ntor_tok->object_type, "ED25519 CERT")) {
1383 log_warn(LD_DIR, "Wrong object type on ntor-onion-key-crosscert "
1384 "in decriptor");
1385 goto err;
1387 if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) {
1388 log_warn(LD_DIR, "Wrong object type on onion-key-crosscert "
1389 "in decriptor");
1390 goto err;
1392 if (strcmp(cc_ntor_tok->args[0], "0") &&
1393 strcmp(cc_ntor_tok->args[0], "1")) {
1394 log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert");
1395 goto err;
1397 int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1");
1399 uint8_t d256[DIGEST256_LEN];
1400 const char *signed_start, *signed_end;
1401 tor_cert_t *cert = tor_cert_parse(
1402 (const uint8_t*)ed_cert_tok->object_body,
1403 ed_cert_tok->object_size);
1404 if (! cert) {
1405 log_warn(LD_DIR, "Couldn't parse ed25519 cert");
1406 goto err;
1408 /* makes sure it gets freed. */
1409 router->cache_info.signing_key_cert = cert;
1411 if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
1412 ! cert->signing_key_included) {
1413 log_warn(LD_DIR, "Invalid form for ed25519 cert");
1414 goto err;
1417 if (master_key_tok) {
1418 /* This token is optional, but if it's present, it must match
1419 * the signature in the signing cert, or supplant it. */
1420 tor_assert(master_key_tok->n_args >= 1);
1421 ed25519_public_key_t pkey;
1422 if (ed25519_public_from_base64(&pkey, master_key_tok->args[0])<0) {
1423 log_warn(LD_DIR, "Can't parse ed25519 master key");
1424 goto err;
1427 if (fast_memneq(&cert->signing_key.pubkey,
1428 pkey.pubkey, ED25519_PUBKEY_LEN)) {
1429 log_warn(LD_DIR, "Ed25519 master key does not match "
1430 "key in certificate");
1431 goto err;
1434 ntor_cc_cert = tor_cert_parse((const uint8_t*)cc_ntor_tok->object_body,
1435 cc_ntor_tok->object_size);
1436 if (!ntor_cc_cert) {
1437 log_warn(LD_DIR, "Couldn't parse ntor-onion-key-crosscert cert");
1438 goto err;
1440 if (ntor_cc_cert->cert_type != CERT_TYPE_ONION_ID ||
1441 ! ed25519_pubkey_eq(&ntor_cc_cert->signed_key, &cert->signing_key)) {
1442 log_warn(LD_DIR, "Invalid contents for ntor-onion-key-crosscert cert");
1443 goto err;
1446 ed25519_public_key_t ntor_cc_pk;
1447 if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk,
1448 router->onion_curve25519_pkey,
1449 ntor_cc_sign_bit)<0) {
1450 log_warn(LD_DIR, "Error converting onion key to ed25519");
1451 goto err;
1454 if (router_get_hash_impl_helper(s, end-s, "router ",
1455 "\nrouter-sig-ed25519",
1456 ' ', &signed_start, &signed_end) < 0) {
1457 log_warn(LD_DIR, "Can't find ed25519-signed portion of descriptor");
1458 goto err;
1460 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
1461 crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
1462 strlen(ED_DESC_SIGNATURE_PREFIX));
1463 crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
1464 crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
1465 crypto_digest_free(d);
1467 ed25519_checkable_t check[3];
1468 int check_ok[3];
1469 if (tor_cert_get_checkable_sig(&check[0], cert, NULL) < 0) {
1470 log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
1471 goto err;
1473 if (tor_cert_get_checkable_sig(&check[1],
1474 ntor_cc_cert, &ntor_cc_pk) < 0) {
1475 log_err(LD_BUG, "Couldn't create 'checkable' for ntor_cc_cert.");
1476 goto err;
1479 if (ed25519_signature_from_base64(&check[2].signature,
1480 ed_sig_tok->args[0])<0) {
1481 log_warn(LD_DIR, "Couldn't decode ed25519 signature");
1482 goto err;
1484 check[2].pubkey = &cert->signed_key;
1485 check[2].msg = d256;
1486 check[2].len = DIGEST256_LEN;
1488 if (ed25519_checksig_batch(check_ok, check, 3) < 0) {
1489 log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
1490 goto err;
1493 if (check_tap_onion_key_crosscert(
1494 (const uint8_t*)cc_tap_tok->object_body,
1495 (int)cc_tap_tok->object_size,
1496 router->onion_pkey,
1497 &cert->signing_key,
1498 (const uint8_t*)router->cache_info.identity_digest)<0) {
1499 log_warn(LD_DIR, "Incorrect TAP cross-verification");
1500 goto err;
1503 /* We check this before adding it to the routerlist. */
1504 if (cert->valid_until < ntor_cc_cert->valid_until)
1505 router->cert_expiration_time = cert->valid_until;
1506 else
1507 router->cert_expiration_time = ntor_cc_cert->valid_until;
1511 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1512 /* If there's a fingerprint line, it must match the identity digest. */
1513 char d[DIGEST_LEN];
1514 tor_assert(tok->n_args == 1);
1515 tor_strstrip(tok->args[0], " ");
1516 if (base16_decode(d, DIGEST_LEN,
1517 tok->args[0], strlen(tok->args[0])) != DIGEST_LEN) {
1518 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1519 escaped(tok->args[0]));
1520 goto err;
1522 if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
1523 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1524 tok->args[0]);
1525 goto err;
1529 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1530 router->platform = tor_strdup(tok->args[0]);
1533 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1534 router->contact_info = tor_strdup(tok->args[0]);
1537 if (find_opt_by_keyword(tokens, K_REJECT6) ||
1538 find_opt_by_keyword(tokens, K_ACCEPT6)) {
1539 log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
1540 "older Tors.");
1541 goto err;
1544 smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
1545 if (or_addresses) {
1546 find_single_ipv6_orport(or_addresses, &router->ipv6_addr,
1547 &router->ipv6_orport);
1548 smartlist_free(or_addresses);
1551 exit_policy_tokens = find_all_exitpolicy(tokens);
1552 if (!smartlist_len(exit_policy_tokens)) {
1553 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1554 goto err;
1556 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1557 if (router_add_exit_policy(router,t)<0) {
1558 log_warn(LD_DIR,"Error in exit policy");
1559 goto err;
1561 policy_expand_private(&router->exit_policy);
1563 if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) {
1564 router->ipv6_exit_policy = parse_short_policy(tok->args[0]);
1565 if (! router->ipv6_exit_policy) {
1566 log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0]));
1567 goto err;
1571 if (policy_is_reject_star(router->exit_policy, AF_INET) &&
1572 (!router->ipv6_exit_policy ||
1573 short_policy_is_reject_star(router->ipv6_exit_policy)))
1574 router->policy_is_reject_star = 1;
1576 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1577 int i;
1578 router->declared_family = smartlist_new();
1579 for (i=0;i<tok->n_args;++i) {
1580 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1581 log_warn(LD_DIR, "Illegal nickname %s in family line",
1582 escaped(tok->args[i]));
1583 goto err;
1585 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1589 if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
1590 router->caches_extra_info = 1;
1592 if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
1593 router->allow_single_hop_exits = 1;
1595 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1596 tor_assert(tok->n_args >= 1);
1597 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1598 if (base16_decode(router->cache_info.extra_info_digest, DIGEST_LEN,
1599 tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN) {
1600 log_warn(LD_DIR,"Invalid extra info digest");
1602 } else {
1603 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1606 if (tok->n_args >= 2) {
1607 if (digest256_from_base64(router->cache_info.extra_info_digest256,
1608 tok->args[1]) < 0) {
1609 log_warn(LD_DIR, "Invalid extra info digest256 %s",
1610 escaped(tok->args[1]));
1615 if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
1616 router->wants_to_be_hs_dir = 1;
1619 /* This router accepts tunnelled directory requests via begindir if it has
1620 * an open dirport or it included "tunnelled-dir-server". */
1621 if (find_opt_by_keyword(tokens, K_DIR_TUNNELLED) || router->dir_port > 0) {
1622 router->supports_tunnelled_dir_requests = 1;
1625 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1626 note_crypto_pk_op(VERIFY_RTR);
1627 #ifdef COUNT_DISTINCT_DIGESTS
1628 if (!verified_digests)
1629 verified_digests = digestmap_new();
1630 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1631 #endif
1633 if (!router->or_port) {
1634 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1635 goto err;
1638 /* We've checked everything that's covered by the hash. */
1639 can_dl_again = 1;
1640 if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
1641 "router descriptor") < 0)
1642 goto err;
1644 if (!router->platform) {
1645 router->platform = tor_strdup("<unknown>");
1647 goto done;
1649 err:
1650 dump_desc(s_dup, "router descriptor");
1651 routerinfo_free(router);
1652 router = NULL;
1653 done:
1654 tor_cert_free(ntor_cc_cert);
1655 if (tokens) {
1656 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1657 smartlist_free(tokens);
1659 smartlist_free(exit_policy_tokens);
1660 if (area) {
1661 DUMP_AREA(area, "routerinfo");
1662 memarea_drop_all(area);
1664 if (can_dl_again_out)
1665 *can_dl_again_out = can_dl_again;
1666 return router;
1669 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1670 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1671 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1672 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1673 * as a map from router identity to routerinfo_t when looking up signing keys.
1675 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1676 * if it's okay to try to download an extrainfo with this same digest again,
1677 * and 0 if it isn't. (It might not be okay to download it again if part of
1678 * the part covered by the digest is invalid.)
1680 extrainfo_t *
1681 extrainfo_parse_entry_from_string(const char *s, const char *end,
1682 int cache_copy, struct digest_ri_map_t *routermap,
1683 int *can_dl_again_out)
1685 extrainfo_t *extrainfo = NULL;
1686 char digest[128];
1687 smartlist_t *tokens = NULL;
1688 directory_token_t *tok;
1689 crypto_pk_t *key = NULL;
1690 routerinfo_t *router = NULL;
1691 memarea_t *area = NULL;
1692 const char *s_dup = s;
1693 /* Do not set this to '1' until we have parsed everything that we intend to
1694 * parse that's covered by the hash. */
1695 int can_dl_again = 0;
1697 if (!end) {
1698 end = s + strlen(s);
1701 /* point 'end' to a point immediately after the final newline. */
1702 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1703 --end;
1705 if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
1706 log_warn(LD_DIR, "Couldn't compute router hash.");
1707 goto err;
1709 tokens = smartlist_new();
1710 area = memarea_new();
1711 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1712 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1713 goto err;
1716 if (smartlist_len(tokens) < 2) {
1717 log_warn(LD_DIR, "Impossibly short extra-info document.");
1718 goto err;
1721 /* XXXX Accept this in position 1 too, and ed identity in position 0. */
1722 tok = smartlist_get(tokens,0);
1723 if (tok->tp != K_EXTRA_INFO) {
1724 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1725 goto err;
1728 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1729 extrainfo->cache_info.is_extrainfo = 1;
1730 if (cache_copy)
1731 extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s);
1732 extrainfo->cache_info.signed_descriptor_len = end-s;
1733 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1734 crypto_digest256((char*)extrainfo->digest256, s, end-s, DIGEST_SHA256);
1736 tor_assert(tok->n_args >= 2);
1737 if (!is_legal_nickname(tok->args[0])) {
1738 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1739 goto err;
1741 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1742 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1743 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1744 tok->args[1], HEX_DIGEST_LEN) != DIGEST_LEN) {
1745 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1746 escaped(tok->args[1]));
1747 goto err;
1750 tok = find_by_keyword(tokens, K_PUBLISHED);
1751 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1752 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1753 escaped(tok->args[0]));
1754 goto err;
1758 directory_token_t *ed_sig_tok, *ed_cert_tok;
1759 ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519);
1760 ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519);
1761 int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok;
1762 if (n_ed_toks != 0 && n_ed_toks != 2) {
1763 log_warn(LD_DIR, "Router descriptor with only partial ed25519/"
1764 "cross-certification support");
1765 goto err;
1767 if (ed_sig_tok) {
1768 tor_assert(ed_cert_tok);
1769 const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok);
1770 if (ed_cert_token_pos != 1) {
1771 /* Accept this in position 0 XXXX */
1772 log_warn(LD_DIR, "Ed25519 certificate in wrong position");
1773 goto err;
1775 if (ed_sig_tok != smartlist_get(tokens, smartlist_len(tokens)-2)) {
1776 log_warn(LD_DIR, "Ed25519 signature in wrong position");
1777 goto err;
1779 if (strcmp(ed_cert_tok->object_type, "ED25519 CERT")) {
1780 log_warn(LD_DIR, "Wrong object type on identity-ed25519 in decriptor");
1781 goto err;
1784 uint8_t d256[DIGEST256_LEN];
1785 const char *signed_start, *signed_end;
1786 tor_cert_t *cert = tor_cert_parse(
1787 (const uint8_t*)ed_cert_tok->object_body,
1788 ed_cert_tok->object_size);
1789 if (! cert) {
1790 log_warn(LD_DIR, "Couldn't parse ed25519 cert");
1791 goto err;
1793 /* makes sure it gets freed. */
1794 extrainfo->cache_info.signing_key_cert = cert;
1796 if (cert->cert_type != CERT_TYPE_ID_SIGNING ||
1797 ! cert->signing_key_included) {
1798 log_warn(LD_DIR, "Invalid form for ed25519 cert");
1799 goto err;
1802 if (router_get_hash_impl_helper(s, end-s, "extra-info ",
1803 "\nrouter-sig-ed25519",
1804 ' ', &signed_start, &signed_end) < 0) {
1805 log_warn(LD_DIR, "Can't find ed25519-signed portion of extrainfo");
1806 goto err;
1808 crypto_digest_t *d = crypto_digest256_new(DIGEST_SHA256);
1809 crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX,
1810 strlen(ED_DESC_SIGNATURE_PREFIX));
1811 crypto_digest_add_bytes(d, signed_start, signed_end-signed_start);
1812 crypto_digest_get_digest(d, (char*)d256, sizeof(d256));
1813 crypto_digest_free(d);
1815 ed25519_checkable_t check[2];
1816 int check_ok[2];
1817 if (tor_cert_get_checkable_sig(&check[0], cert, NULL) < 0) {
1818 log_err(LD_BUG, "Couldn't create 'checkable' for cert.");
1819 goto err;
1822 if (ed25519_signature_from_base64(&check[1].signature,
1823 ed_sig_tok->args[0])<0) {
1824 log_warn(LD_DIR, "Couldn't decode ed25519 signature");
1825 goto err;
1827 check[1].pubkey = &cert->signed_key;
1828 check[1].msg = d256;
1829 check[1].len = DIGEST256_LEN;
1831 if (ed25519_checksig_batch(check_ok, check, 2) < 0) {
1832 log_warn(LD_DIR, "Incorrect ed25519 signature(s)");
1833 goto err;
1835 /* We don't check the certificate expiration time: checking that it
1836 * matches the cert in the router descriptor is adequate. */
1840 /* We've checked everything that's covered by the hash. */
1841 can_dl_again = 1;
1843 if (routermap &&
1844 (router = digestmap_get((digestmap_t*)routermap,
1845 extrainfo->cache_info.identity_digest))) {
1846 key = router->identity_pkey;
1849 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1850 if (strcmp(tok->object_type, "SIGNATURE") ||
1851 tok->object_size < 128 || tok->object_size > 512) {
1852 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1853 goto err;
1856 if (key) {
1857 note_crypto_pk_op(VERIFY_RTR);
1858 if (check_signature_token(digest, DIGEST_LEN, tok, key, 0,
1859 "extra-info") < 0)
1860 goto err;
1862 if (router)
1863 extrainfo->cache_info.send_unencrypted =
1864 router->cache_info.send_unencrypted;
1865 } else {
1866 extrainfo->pending_sig = tor_memdup(tok->object_body,
1867 tok->object_size);
1868 extrainfo->pending_sig_len = tok->object_size;
1871 goto done;
1872 err:
1873 dump_desc(s_dup, "extra-info descriptor");
1874 extrainfo_free(extrainfo);
1875 extrainfo = NULL;
1876 done:
1877 if (tokens) {
1878 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1879 smartlist_free(tokens);
1881 if (area) {
1882 DUMP_AREA(area, "extrainfo");
1883 memarea_drop_all(area);
1885 if (can_dl_again_out)
1886 *can_dl_again_out = can_dl_again;
1887 return extrainfo;
1890 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1891 * the first character after the certificate. */
1892 authority_cert_t *
1893 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1895 /** Reject any certificate at least this big; it is probably an overflow, an
1896 * attack, a bug, or some other nonsense. */
1897 #define MAX_CERT_SIZE (128*1024)
1899 authority_cert_t *cert = NULL, *old_cert;
1900 smartlist_t *tokens = NULL;
1901 char digest[DIGEST_LEN];
1902 directory_token_t *tok;
1903 char fp_declared[DIGEST_LEN];
1904 char *eos;
1905 size_t len;
1906 int found;
1907 memarea_t *area = NULL;
1908 const char *s_dup = s;
1910 s = eat_whitespace(s);
1911 eos = strstr(s, "\ndir-key-certification");
1912 if (! eos) {
1913 log_warn(LD_DIR, "No signature found on key certificate");
1914 return NULL;
1916 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1917 if (! eos) {
1918 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1919 return NULL;
1921 eos = strchr(eos+2, '\n');
1922 tor_assert(eos);
1923 ++eos;
1924 len = eos - s;
1926 if (len > MAX_CERT_SIZE) {
1927 log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
1928 "rejecting", (unsigned long)len);
1929 return NULL;
1932 tokens = smartlist_new();
1933 area = memarea_new();
1934 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1935 log_warn(LD_DIR, "Error tokenizing key certificate");
1936 goto err;
1938 if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
1939 "\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
1940 goto err;
1941 tok = smartlist_get(tokens, 0);
1942 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1943 log_warn(LD_DIR,
1944 "Key certificate does not begin with a recognized version (3).");
1945 goto err;
1948 cert = tor_malloc_zero(sizeof(authority_cert_t));
1949 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1951 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1952 tor_assert(tok->key);
1953 cert->signing_key = tok->key;
1954 tok->key = NULL;
1955 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1956 goto err;
1958 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1959 tor_assert(tok->key);
1960 cert->identity_key = tok->key;
1961 tok->key = NULL;
1963 tok = find_by_keyword(tokens, K_FINGERPRINT);
1964 tor_assert(tok->n_args);
1965 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1966 strlen(tok->args[0])) != DIGEST_LEN) {
1967 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1968 escaped(tok->args[0]));
1969 goto err;
1972 if (crypto_pk_get_digest(cert->identity_key,
1973 cert->cache_info.identity_digest))
1974 goto err;
1976 if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1977 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1978 "fingerprint");
1979 goto err;
1982 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1983 if (tok) {
1984 struct in_addr in;
1985 char *address = NULL;
1986 tor_assert(tok->n_args);
1987 /* XXX++ use some tor_addr parse function below instead. -RD */
1988 if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
1989 &cert->dir_port) < 0 ||
1990 tor_inet_aton(address, &in) == 0) {
1991 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1992 tor_free(address);
1993 goto err;
1995 cert->addr = ntohl(in.s_addr);
1996 tor_free(address);
1999 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
2000 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
2001 goto err;
2003 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
2004 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
2005 goto err;
2008 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
2009 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
2010 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
2011 goto err;
2014 /* If we already have this cert, don't bother checking the signature. */
2015 old_cert = authority_cert_get_by_digests(
2016 cert->cache_info.identity_digest,
2017 cert->signing_key_digest);
2018 found = 0;
2019 if (old_cert) {
2020 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
2021 * buy us much. */
2022 if (old_cert->cache_info.signed_descriptor_len == len &&
2023 old_cert->cache_info.signed_descriptor_body &&
2024 tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) {
2025 log_debug(LD_DIR, "We already checked the signature on this "
2026 "certificate; no need to do so again.");
2027 found = 1;
2030 if (!found) {
2031 if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0,
2032 "key certificate")) {
2033 goto err;
2036 tok = find_by_keyword(tokens, K_DIR_KEY_CROSSCERT);
2037 if (check_signature_token(cert->cache_info.identity_digest,
2038 DIGEST_LEN,
2039 tok,
2040 cert->signing_key,
2041 CST_NO_CHECK_OBJTYPE,
2042 "key cross-certification")) {
2043 goto err;
2047 cert->cache_info.signed_descriptor_len = len;
2048 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
2049 memcpy(cert->cache_info.signed_descriptor_body, s, len);
2050 cert->cache_info.signed_descriptor_body[len] = 0;
2051 cert->cache_info.saved_location = SAVED_NOWHERE;
2053 if (end_of_string) {
2054 *end_of_string = eat_whitespace(eos);
2056 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2057 smartlist_free(tokens);
2058 if (area) {
2059 DUMP_AREA(area, "authority cert");
2060 memarea_drop_all(area);
2062 return cert;
2063 err:
2064 dump_desc(s_dup, "authority cert");
2065 authority_cert_free(cert);
2066 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2067 smartlist_free(tokens);
2068 if (area) {
2069 DUMP_AREA(area, "authority cert");
2070 memarea_drop_all(area);
2072 return NULL;
2075 /** Helper: given a string <b>s</b>, return the start of the next router-status
2076 * object (starting with "r " at the start of a line). If none is found,
2077 * return the start of the directory footer, or the next directory signature.
2078 * If none is found, return the end of the string. */
2079 static inline const char *
2080 find_start_of_next_routerstatus(const char *s)
2082 const char *eos, *footer, *sig;
2083 if ((eos = strstr(s, "\nr ")))
2084 ++eos;
2085 else
2086 eos = s + strlen(s);
2088 footer = tor_memstr(s, eos-s, "\ndirectory-footer");
2089 sig = tor_memstr(s, eos-s, "\ndirectory-signature");
2091 if (footer && sig)
2092 return MIN(footer, sig) + 1;
2093 else if (footer)
2094 return footer+1;
2095 else if (sig)
2096 return sig+1;
2097 else
2098 return eos;
2101 /** Parse the GuardFraction string from a consensus or vote.
2103 * If <b>vote</b> or <b>vote_rs</b> are set the document getting
2104 * parsed is a vote routerstatus. Otherwise it's a consensus. This is
2105 * the same semantic as in routerstatus_parse_entry_from_string(). */
2106 STATIC int
2107 routerstatus_parse_guardfraction(const char *guardfraction_str,
2108 networkstatus_t *vote,
2109 vote_routerstatus_t *vote_rs,
2110 routerstatus_t *rs)
2112 int ok;
2113 const char *end_of_header = NULL;
2114 int is_consensus = !vote_rs;
2115 uint32_t guardfraction;
2117 tor_assert(bool_eq(vote, vote_rs));
2119 /* If this info comes from a consensus, but we should't apply
2120 guardfraction, just exit. */
2121 if (is_consensus && !should_apply_guardfraction(NULL)) {
2122 return 0;
2125 end_of_header = strchr(guardfraction_str, '=');
2126 if (!end_of_header) {
2127 return -1;
2130 guardfraction = (uint32_t)tor_parse_ulong(end_of_header+1,
2131 10, 0, 100, &ok, NULL);
2132 if (!ok) {
2133 log_warn(LD_DIR, "Invalid GuardFraction %s", escaped(guardfraction_str));
2134 return -1;
2137 log_debug(LD_GENERAL, "[*] Parsed %s guardfraction '%s' for '%s'.",
2138 is_consensus ? "consensus" : "vote",
2139 guardfraction_str, rs->nickname);
2141 if (!is_consensus) { /* We are parsing a vote */
2142 vote_rs->status.guardfraction_percentage = guardfraction;
2143 vote_rs->status.has_guardfraction = 1;
2144 } else {
2145 /* We are parsing a consensus. Only apply guardfraction to guards. */
2146 if (rs->is_possible_guard) {
2147 rs->guardfraction_percentage = guardfraction;
2148 rs->has_guardfraction = 1;
2149 } else {
2150 log_warn(LD_BUG, "Got GuardFraction for non-guard %s. "
2151 "This is not supposed to happen. Not applying. ", rs->nickname);
2155 return 0;
2158 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
2159 * empty smartlist at <b>tokens</b>, parse and return the first router status
2160 * object in the string, and advance *<b>s</b> to just after the end of the
2161 * router status. Return NULL and advance *<b>s</b> on error.
2163 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
2164 * routerstatus but use <b>vote_rs</b> instead.
2166 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
2167 * consensus, and we should parse it according to the method used to
2168 * make that consensus.
2170 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
2172 static routerstatus_t *
2173 routerstatus_parse_entry_from_string(memarea_t *area,
2174 const char **s, smartlist_t *tokens,
2175 networkstatus_t *vote,
2176 vote_routerstatus_t *vote_rs,
2177 int consensus_method,
2178 consensus_flavor_t flav)
2180 const char *eos, *s_dup = *s;
2181 routerstatus_t *rs = NULL;
2182 directory_token_t *tok;
2183 char timebuf[ISO_TIME_LEN+1];
2184 struct in_addr in;
2185 int offset = 0;
2186 tor_assert(tokens);
2187 tor_assert(bool_eq(vote, vote_rs));
2189 if (!consensus_method)
2190 flav = FLAV_NS;
2191 tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
2193 eos = find_start_of_next_routerstatus(*s);
2195 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
2196 log_warn(LD_DIR, "Error tokenizing router status");
2197 goto err;
2199 if (smartlist_len(tokens) < 1) {
2200 log_warn(LD_DIR, "Impossibly short router status");
2201 goto err;
2203 tok = find_by_keyword(tokens, K_R);
2204 tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
2205 if (flav == FLAV_NS) {
2206 if (tok->n_args < 8) {
2207 log_warn(LD_DIR, "Too few arguments to r");
2208 goto err;
2210 } else if (flav == FLAV_MICRODESC) {
2211 offset = -1; /* There is no identity digest */
2214 if (vote_rs) {
2215 rs = &vote_rs->status;
2216 } else {
2217 rs = tor_malloc_zero(sizeof(routerstatus_t));
2220 if (!is_legal_nickname(tok->args[0])) {
2221 log_warn(LD_DIR,
2222 "Invalid nickname %s in router status; skipping.",
2223 escaped(tok->args[0]));
2224 goto err;
2226 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
2228 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
2229 log_warn(LD_DIR, "Error decoding identity digest %s",
2230 escaped(tok->args[1]));
2231 goto err;
2234 if (flav == FLAV_NS) {
2235 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
2236 log_warn(LD_DIR, "Error decoding descriptor digest %s",
2237 escaped(tok->args[2]));
2238 goto err;
2242 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
2243 tok->args[3+offset], tok->args[4+offset]) < 0 ||
2244 parse_iso_time(timebuf, &rs->published_on)<0) {
2245 log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]",
2246 tok->args[3+offset], tok->args[4+offset],
2247 offset, (int)flav);
2248 goto err;
2251 if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
2252 log_warn(LD_DIR, "Error parsing router address in network-status %s",
2253 escaped(tok->args[5+offset]));
2254 goto err;
2256 rs->addr = ntohl(in.s_addr);
2258 rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
2259 10,0,65535,NULL,NULL);
2260 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
2261 10,0,65535,NULL,NULL);
2264 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
2265 if (a_lines) {
2266 find_single_ipv6_orport(a_lines, &rs->ipv6_addr, &rs->ipv6_orport);
2267 smartlist_free(a_lines);
2271 tok = find_opt_by_keyword(tokens, K_S);
2272 if (tok && vote) {
2273 int i;
2274 vote_rs->flags = 0;
2275 for (i=0; i < tok->n_args; ++i) {
2276 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
2277 if (p >= 0) {
2278 vote_rs->flags |= (U64_LITERAL(1)<<p);
2279 } else {
2280 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
2281 escaped(tok->args[i]));
2282 goto err;
2285 } else if (tok) {
2286 int i;
2287 for (i=0; i < tok->n_args; ++i) {
2288 if (!strcmp(tok->args[i], "Exit"))
2289 rs->is_exit = 1;
2290 else if (!strcmp(tok->args[i], "Stable"))
2291 rs->is_stable = 1;
2292 else if (!strcmp(tok->args[i], "Fast"))
2293 rs->is_fast = 1;
2294 else if (!strcmp(tok->args[i], "Running"))
2295 rs->is_flagged_running = 1;
2296 else if (!strcmp(tok->args[i], "Named"))
2297 rs->is_named = 1;
2298 else if (!strcmp(tok->args[i], "Valid"))
2299 rs->is_valid = 1;
2300 else if (!strcmp(tok->args[i], "Guard"))
2301 rs->is_possible_guard = 1;
2302 else if (!strcmp(tok->args[i], "BadExit"))
2303 rs->is_bad_exit = 1;
2304 else if (!strcmp(tok->args[i], "Authority"))
2305 rs->is_authority = 1;
2306 else if (!strcmp(tok->args[i], "Unnamed") &&
2307 consensus_method >= 2) {
2308 /* Unnamed is computed right by consensus method 2 and later. */
2309 rs->is_unnamed = 1;
2310 } else if (!strcmp(tok->args[i], "HSDir")) {
2311 rs->is_hs_dir = 1;
2312 } else if (!strcmp(tok->args[i], "V2Dir")) {
2313 rs->is_v2_dir = 1;
2317 if ((tok = find_opt_by_keyword(tokens, K_V))) {
2318 tor_assert(tok->n_args == 1);
2319 rs->version_known = 1;
2320 if (strcmpstart(tok->args[0], "Tor ")) {
2321 } else {
2322 rs->version_supports_extend2_cells =
2323 tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
2325 if (vote_rs) {
2326 vote_rs->version = tor_strdup(tok->args[0]);
2330 /* handle weighting/bandwidth info */
2331 if ((tok = find_opt_by_keyword(tokens, K_W))) {
2332 int i;
2333 for (i=0; i < tok->n_args; ++i) {
2334 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
2335 int ok;
2336 rs->bandwidth_kb =
2337 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
2338 10, 0, UINT32_MAX,
2339 &ok, NULL);
2340 if (!ok) {
2341 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
2342 goto err;
2344 rs->has_bandwidth = 1;
2345 } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) {
2346 int ok;
2347 vote_rs->measured_bw_kb =
2348 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
2349 10, 0, UINT32_MAX, &ok, NULL);
2350 if (!ok) {
2351 log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
2352 escaped(tok->args[i]));
2353 goto err;
2355 vote_rs->has_measured_bw = 1;
2356 vote->has_measured_bws = 1;
2357 } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
2358 rs->bw_is_unmeasured = 1;
2359 } else if (!strcmpstart(tok->args[i], "GuardFraction=")) {
2360 if (routerstatus_parse_guardfraction(tok->args[i],
2361 vote, vote_rs, rs) < 0) {
2362 goto err;
2368 /* parse exit policy summaries */
2369 if ((tok = find_opt_by_keyword(tokens, K_P))) {
2370 tor_assert(tok->n_args == 1);
2371 if (strcmpstart(tok->args[0], "accept ") &&
2372 strcmpstart(tok->args[0], "reject ")) {
2373 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
2374 escaped(tok->args[0]));
2375 goto err;
2377 /* XXX weasel: parse this into ports and represent them somehow smart,
2378 * maybe not here but somewhere on if we need it for the client.
2379 * we should still parse it here to check it's valid tho.
2381 rs->exitsummary = tor_strdup(tok->args[0]);
2382 rs->has_exitsummary = 1;
2385 if (vote_rs) {
2386 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) {
2387 if (t->tp == K_M && t->n_args) {
2388 vote_microdesc_hash_t *line =
2389 tor_malloc(sizeof(vote_microdesc_hash_t));
2390 line->next = vote_rs->microdesc;
2391 line->microdesc_hash_line = tor_strdup(t->args[0]);
2392 vote_rs->microdesc = line;
2394 if (t->tp == K_ID) {
2395 tor_assert(t->n_args >= 2);
2396 if (!strcmp(t->args[0], "ed25519")) {
2397 vote_rs->has_ed25519_listing = 1;
2398 if (strcmp(t->args[1], "none") &&
2399 digest256_from_base64((char*)vote_rs->ed25519_id,
2400 t->args[1])<0) {
2401 log_warn(LD_DIR, "Bogus ed25519 key in networkstatus vote");
2402 goto err;
2406 } SMARTLIST_FOREACH_END(t);
2407 } else if (flav == FLAV_MICRODESC) {
2408 tok = find_opt_by_keyword(tokens, K_M);
2409 if (tok) {
2410 tor_assert(tok->n_args);
2411 if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
2412 log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
2413 escaped(tok->args[0]));
2414 goto err;
2416 } else {
2417 log_info(LD_BUG, "Found an entry in networkstatus with no "
2418 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
2419 rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
2420 fmt_addr32(rs->addr), rs->or_port);
2424 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
2425 rs->is_named = 0;
2427 goto done;
2428 err:
2429 dump_desc(s_dup, "routerstatus entry");
2430 if (rs && !vote_rs)
2431 routerstatus_free(rs);
2432 rs = NULL;
2433 done:
2434 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2435 smartlist_clear(tokens);
2436 if (area) {
2437 DUMP_AREA(area, "routerstatus entry");
2438 memarea_clear(area);
2440 *s = eos;
2442 return rs;
2446 compare_vote_routerstatus_entries(const void **_a, const void **_b)
2448 const vote_routerstatus_t *a = *_a, *b = *_b;
2449 return fast_memcmp(a->status.identity_digest, b->status.identity_digest,
2450 DIGEST_LEN);
2453 /** Verify the bandwidth weights of a network status document */
2455 networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
2457 int64_t weight_scale;
2458 int64_t G=0, M=0, E=0, D=0, T=0;
2459 double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
2460 double Gtotal=0, Mtotal=0, Etotal=0;
2461 const char *casename = NULL;
2462 int valid = 1;
2463 (void) consensus_method;
2465 weight_scale = networkstatus_get_weight_scale_param(ns);
2466 Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1);
2467 Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1);
2468 Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1);
2469 Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1);
2470 Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1);
2471 Wme = networkstatus_get_bw_weight(ns, "Wme", -1);
2472 Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1);
2473 Weg = networkstatus_get_bw_weight(ns, "Weg", -1);
2474 Wem = networkstatus_get_bw_weight(ns, "Wem", -1);
2475 Wee = networkstatus_get_bw_weight(ns, "Wee", -1);
2476 Wed = networkstatus_get_bw_weight(ns, "Wed", -1);
2478 if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
2479 || Wem<0 || Wee<0 || Wed<0) {
2480 log_warn(LD_BUG, "No bandwidth weights produced in consensus!");
2481 return 0;
2484 // First, sanity check basic summing properties that hold for all cases
2485 // We use > 1 as the check for these because they are computed as integers.
2486 // Sometimes there are rounding errors.
2487 if (fabs(Wmm - weight_scale) > 1) {
2488 log_warn(LD_BUG, "Wmm=%f != "I64_FORMAT,
2489 Wmm, I64_PRINTF_ARG(weight_scale));
2490 valid = 0;
2493 if (fabs(Wem - Wee) > 1) {
2494 log_warn(LD_BUG, "Wem=%f != Wee=%f", Wem, Wee);
2495 valid = 0;
2498 if (fabs(Wgm - Wgg) > 1) {
2499 log_warn(LD_BUG, "Wgm=%f != Wgg=%f", Wgm, Wgg);
2500 valid = 0;
2503 if (fabs(Weg - Wed) > 1) {
2504 log_warn(LD_BUG, "Wed=%f != Weg=%f", Wed, Weg);
2505 valid = 0;
2508 if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
2509 log_warn(LD_BUG, "Wgg=%f != "I64_FORMAT" - Wmg=%f", Wgg,
2510 I64_PRINTF_ARG(weight_scale), Wmg);
2511 valid = 0;
2514 if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
2515 log_warn(LD_BUG, "Wee=%f != "I64_FORMAT" - Wme=%f", Wee,
2516 I64_PRINTF_ARG(weight_scale), Wme);
2517 valid = 0;
2520 if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
2521 log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT,
2522 Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
2523 valid = 0;
2526 Wgg /= weight_scale;
2527 Wgm /= weight_scale;
2528 Wgd /= weight_scale;
2530 Wmg /= weight_scale;
2531 Wmm /= weight_scale;
2532 Wme /= weight_scale;
2533 Wmd /= weight_scale;
2535 Weg /= weight_scale;
2536 Wem /= weight_scale;
2537 Wee /= weight_scale;
2538 Wed /= weight_scale;
2540 // Then, gather G, M, E, D, T to determine case
2541 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
2542 int is_exit = 0;
2543 /* Bug #2203: Don't count bad exits as exits for balancing */
2544 is_exit = rs->is_exit && !rs->is_bad_exit;
2545 if (rs->has_bandwidth) {
2546 T += rs->bandwidth_kb;
2547 if (is_exit && rs->is_possible_guard) {
2548 D += rs->bandwidth_kb;
2549 Gtotal += Wgd*rs->bandwidth_kb;
2550 Mtotal += Wmd*rs->bandwidth_kb;
2551 Etotal += Wed*rs->bandwidth_kb;
2552 } else if (is_exit) {
2553 E += rs->bandwidth_kb;
2554 Mtotal += Wme*rs->bandwidth_kb;
2555 Etotal += Wee*rs->bandwidth_kb;
2556 } else if (rs->is_possible_guard) {
2557 G += rs->bandwidth_kb;
2558 Gtotal += Wgg*rs->bandwidth_kb;
2559 Mtotal += Wmg*rs->bandwidth_kb;
2560 } else {
2561 M += rs->bandwidth_kb;
2562 Mtotal += Wmm*rs->bandwidth_kb;
2564 } else {
2565 log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
2566 routerstatus_describe(rs));
2568 } SMARTLIST_FOREACH_END(rs);
2570 // Finally, check equality conditions depending upon case 1, 2 or 3
2571 // Full equality cases: 1, 3b
2572 // Partial equality cases: 2b (E=G), 3a (M=E)
2573 // Fully unknown: 2a
2574 if (3*E >= T && 3*G >= T) {
2575 // Case 1: Neither are scarce
2576 casename = "Case 1";
2577 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2578 log_warn(LD_DIR,
2579 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2580 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2581 " T="I64_FORMAT". "
2582 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2583 casename, Etotal, Mtotal,
2584 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2585 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2586 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2587 valid = 0;
2589 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2590 log_warn(LD_DIR,
2591 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2592 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2593 " T="I64_FORMAT". "
2594 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2595 casename, Etotal, Gtotal,
2596 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2597 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2598 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2599 valid = 0;
2601 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2602 log_warn(LD_DIR,
2603 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2604 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2605 " T="I64_FORMAT". "
2606 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2607 casename, Mtotal, Gtotal,
2608 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2609 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2610 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2611 valid = 0;
2613 } else if (3*E < T && 3*G < T) {
2614 int64_t R = MIN(E, G);
2615 int64_t S = MAX(E, G);
2617 * Case 2: Both Guards and Exits are scarce
2618 * Balance D between E and G, depending upon
2619 * D capacity and scarcity. Devote no extra
2620 * bandwidth to middle nodes.
2622 if (R+D < S) { // Subcase a
2623 double Rtotal, Stotal;
2624 if (E < G) {
2625 Rtotal = Etotal;
2626 Stotal = Gtotal;
2627 } else {
2628 Rtotal = Gtotal;
2629 Stotal = Etotal;
2631 casename = "Case 2a";
2632 // Rtotal < Stotal
2633 if (Rtotal > Stotal) {
2634 log_warn(LD_DIR,
2635 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
2636 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2637 " T="I64_FORMAT". "
2638 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2639 casename, Rtotal, Stotal,
2640 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2641 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2642 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2643 valid = 0;
2645 // Rtotal < T/3
2646 if (3*Rtotal > T) {
2647 log_warn(LD_DIR,
2648 "Bw Weight Failure for %s: 3*Rtotal %f > T "
2649 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2650 " D="I64_FORMAT" T="I64_FORMAT". "
2651 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2652 casename, Rtotal*3, I64_PRINTF_ARG(T),
2653 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2654 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2655 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2656 valid = 0;
2658 // Stotal < T/3
2659 if (3*Stotal > T) {
2660 log_warn(LD_DIR,
2661 "Bw Weight Failure for %s: 3*Stotal %f > T "
2662 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2663 " D="I64_FORMAT" T="I64_FORMAT". "
2664 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2665 casename, Stotal*3, I64_PRINTF_ARG(T),
2666 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2667 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2668 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2669 valid = 0;
2671 // Mtotal > T/3
2672 if (3*Mtotal < T) {
2673 log_warn(LD_DIR,
2674 "Bw Weight Failure for %s: 3*Mtotal %f < T "
2675 I64_FORMAT". "
2676 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2677 " T="I64_FORMAT". "
2678 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2679 casename, Mtotal*3, I64_PRINTF_ARG(T),
2680 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2681 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2682 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2683 valid = 0;
2685 } else { // Subcase b: R+D > S
2686 casename = "Case 2b";
2688 /* Check the rare-M redirect case. */
2689 if (D != 0 && 3*M < T) {
2690 casename = "Case 2b (balanced)";
2691 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2692 log_warn(LD_DIR,
2693 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2694 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2695 " T="I64_FORMAT". "
2696 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2697 casename, Etotal, Mtotal,
2698 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2699 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2700 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2701 valid = 0;
2703 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2704 log_warn(LD_DIR,
2705 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2706 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2707 " T="I64_FORMAT". "
2708 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2709 casename, Etotal, Gtotal,
2710 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2711 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2712 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2713 valid = 0;
2715 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2716 log_warn(LD_DIR,
2717 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2718 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2719 " T="I64_FORMAT". "
2720 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2721 casename, Mtotal, Gtotal,
2722 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2723 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2724 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2725 valid = 0;
2727 } else {
2728 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2729 log_warn(LD_DIR,
2730 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2731 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2732 " T="I64_FORMAT". "
2733 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2734 casename, Etotal, Gtotal,
2735 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2736 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2737 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2738 valid = 0;
2742 } else { // if (E < T/3 || G < T/3) {
2743 int64_t S = MIN(E, G);
2744 int64_t NS = MAX(E, G);
2745 if (3*(S+D) < T) { // Subcase a:
2746 double Stotal;
2747 double NStotal;
2748 if (G < E) {
2749 casename = "Case 3a (G scarce)";
2750 Stotal = Gtotal;
2751 NStotal = Etotal;
2752 } else { // if (G >= E) {
2753 casename = "Case 3a (E scarce)";
2754 NStotal = Gtotal;
2755 Stotal = Etotal;
2757 // Stotal < T/3
2758 if (3*Stotal > T) {
2759 log_warn(LD_DIR,
2760 "Bw Weight Failure for %s: 3*Stotal %f > T "
2761 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2762 " D="I64_FORMAT" T="I64_FORMAT". "
2763 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2764 casename, Stotal*3, I64_PRINTF_ARG(T),
2765 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2766 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2767 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2768 valid = 0;
2770 if (NS >= M) {
2771 if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
2772 log_warn(LD_DIR,
2773 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
2774 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2775 " T="I64_FORMAT". "
2776 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2777 casename, NStotal, Mtotal,
2778 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2779 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2780 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2781 valid = 0;
2783 } else {
2784 // if NS < M, NStotal > T/3 because only one of G or E is scarce
2785 if (3*NStotal < T) {
2786 log_warn(LD_DIR,
2787 "Bw Weight Failure for %s: 3*NStotal %f < T "
2788 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
2789 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
2790 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2791 casename, NStotal*3, I64_PRINTF_ARG(T),
2792 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2793 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2794 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2795 valid = 0;
2798 } else { // Subcase b: S+D >= T/3
2799 casename = "Case 3b";
2800 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2801 log_warn(LD_DIR,
2802 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2803 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2804 " T="I64_FORMAT". "
2805 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2806 casename, Etotal, Mtotal,
2807 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2808 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2809 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2810 valid = 0;
2812 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2813 log_warn(LD_DIR,
2814 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2815 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2816 " T="I64_FORMAT". "
2817 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2818 casename, Etotal, Gtotal,
2819 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2820 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2821 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2822 valid = 0;
2824 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2825 log_warn(LD_DIR,
2826 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2827 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2828 " T="I64_FORMAT". "
2829 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2830 casename, Mtotal, Gtotal,
2831 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2832 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2833 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2834 valid = 0;
2839 if (valid)
2840 log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.",
2841 casename);
2843 return valid;
2846 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2847 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2848 networkstatus_t *
2849 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2850 networkstatus_type_t ns_type)
2852 smartlist_t *tokens = smartlist_new();
2853 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2854 networkstatus_voter_info_t *voter = NULL;
2855 networkstatus_t *ns = NULL;
2856 common_digests_t ns_digests;
2857 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
2858 directory_token_t *tok;
2859 int ok;
2860 struct in_addr in;
2861 int i, inorder, n_signatures = 0;
2862 memarea_t *area = NULL, *rs_area = NULL;
2863 consensus_flavor_t flav = FLAV_NS;
2864 char *last_kwd=NULL;
2866 tor_assert(s);
2868 if (eos_out)
2869 *eos_out = NULL;
2871 if (router_get_networkstatus_v3_hashes(s, &ns_digests)) {
2872 log_warn(LD_DIR, "Unable to compute digest of network-status");
2873 goto err;
2876 area = memarea_new();
2877 end_of_header = find_start_of_next_routerstatus(s);
2878 if (tokenize_string(area, s, end_of_header, tokens,
2879 (ns_type == NS_TYPE_CONSENSUS) ?
2880 networkstatus_consensus_token_table :
2881 networkstatus_token_table, 0)) {
2882 log_warn(LD_DIR, "Error tokenizing network-status header");
2883 goto err;
2886 ns = tor_malloc_zero(sizeof(networkstatus_t));
2887 memcpy(&ns->digests, &ns_digests, sizeof(ns_digests));
2889 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2890 tor_assert(tok);
2891 if (tok->n_args > 1) {
2892 int flavor = networkstatus_parse_flavor_name(tok->args[1]);
2893 if (flavor < 0) {
2894 log_warn(LD_DIR, "Can't parse document with unknown flavor %s",
2895 escaped(tok->args[1]));
2896 goto err;
2898 ns->flavor = flav = flavor;
2900 if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
2901 log_warn(LD_DIR, "Flavor found on non-consensus networkstatus.");
2902 goto err;
2905 if (ns_type != NS_TYPE_CONSENSUS) {
2906 const char *end_of_cert = NULL;
2907 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2908 goto err;
2909 ++cert;
2910 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2911 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2912 goto err;
2915 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2916 tor_assert(tok->n_args);
2917 if (!strcmp(tok->args[0], "vote")) {
2918 ns->type = NS_TYPE_VOTE;
2919 } else if (!strcmp(tok->args[0], "consensus")) {
2920 ns->type = NS_TYPE_CONSENSUS;
2921 } else if (!strcmp(tok->args[0], "opinion")) {
2922 ns->type = NS_TYPE_OPINION;
2923 } else {
2924 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2925 escaped(tok->args[0]));
2926 goto err;
2928 if (ns_type != ns->type) {
2929 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2930 goto err;
2933 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2934 tok = find_by_keyword(tokens, K_PUBLISHED);
2935 if (parse_iso_time(tok->args[0], &ns->published))
2936 goto err;
2938 ns->supported_methods = smartlist_new();
2939 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2940 if (tok) {
2941 for (i=0; i < tok->n_args; ++i)
2942 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2943 } else {
2944 smartlist_add(ns->supported_methods, tor_strdup("1"));
2946 } else {
2947 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2948 if (tok) {
2949 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2950 &ok, NULL);
2951 if (!ok)
2952 goto err;
2953 } else {
2954 ns->consensus_method = 1;
2958 tok = find_by_keyword(tokens, K_VALID_AFTER);
2959 if (parse_iso_time(tok->args[0], &ns->valid_after))
2960 goto err;
2962 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2963 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2964 goto err;
2966 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2967 if (parse_iso_time(tok->args[0], &ns->valid_until))
2968 goto err;
2970 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2971 tor_assert(tok->n_args >= 2);
2972 ns->vote_seconds =
2973 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2974 if (!ok)
2975 goto err;
2976 ns->dist_seconds =
2977 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2978 if (!ok)
2979 goto err;
2980 if (ns->valid_after +
2981 (get_options()->TestingTorNetwork ?
2982 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL) > ns->fresh_until) {
2983 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2984 goto err;
2986 if (ns->valid_after +
2987 (get_options()->TestingTorNetwork ?
2988 MIN_VOTE_INTERVAL_TESTING : MIN_VOTE_INTERVAL)*2 > ns->valid_until) {
2989 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2990 goto err;
2992 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2993 log_warn(LD_DIR, "Vote seconds is too short");
2994 goto err;
2996 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2997 log_warn(LD_DIR, "Dist seconds is too short");
2998 goto err;
3001 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
3002 ns->client_versions = tor_strdup(tok->args[0]);
3004 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
3005 ns->server_versions = tor_strdup(tok->args[0]);
3009 smartlist_t *package_lst = find_all_by_keyword(tokens, K_PACKAGE);
3010 ns->package_lines = smartlist_new();
3011 if (package_lst) {
3012 SMARTLIST_FOREACH(package_lst, directory_token_t *, t,
3013 smartlist_add(ns->package_lines, tor_strdup(t->args[0])));
3015 smartlist_free(package_lst);
3018 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
3019 ns->known_flags = smartlist_new();
3020 inorder = 1;
3021 for (i = 0; i < tok->n_args; ++i) {
3022 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
3023 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
3024 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
3025 inorder = 0;
3028 if (!inorder) {
3029 log_warn(LD_DIR, "known-flags not in order");
3030 goto err;
3032 if (ns->type != NS_TYPE_CONSENSUS &&
3033 smartlist_len(ns->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
3034 /* If we allowed more than 64 flags in votes, then parsing them would make
3035 * us invoke undefined behavior whenever we used 1<<flagnum to do a
3036 * bit-shift. This is only for votes and opinions: consensus users don't
3037 * care about flags they don't recognize, and so don't build a bitfield
3038 * for them. */
3039 log_warn(LD_DIR, "Too many known-flags in consensus vote or opinion");
3040 goto err;
3043 tok = find_opt_by_keyword(tokens, K_PARAMS);
3044 if (tok) {
3045 int any_dups = 0;
3046 inorder = 1;
3047 ns->net_params = smartlist_new();
3048 for (i = 0; i < tok->n_args; ++i) {
3049 int ok=0;
3050 char *eq = strchr(tok->args[i], '=');
3051 size_t eq_pos;
3052 if (!eq) {
3053 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3054 goto err;
3056 eq_pos = eq-tok->args[i];
3057 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
3058 if (!ok) {
3059 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3060 goto err;
3062 if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
3063 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
3064 inorder = 0;
3066 if (last_kwd && eq_pos == strlen(last_kwd) &&
3067 fast_memeq(last_kwd, tok->args[i], eq_pos)) {
3068 log_warn(LD_DIR, "Duplicate value for %s parameter",
3069 escaped(tok->args[i]));
3070 any_dups = 1;
3072 tor_free(last_kwd);
3073 last_kwd = tor_strndup(tok->args[i], eq_pos);
3074 smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
3076 if (!inorder) {
3077 log_warn(LD_DIR, "params not in order");
3078 goto err;
3080 if (any_dups) {
3081 log_warn(LD_DIR, "Duplicate in parameters");
3082 goto err;
3086 ns->voters = smartlist_new();
3088 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3089 tok = _tok;
3090 if (tok->tp == K_DIR_SOURCE) {
3091 tor_assert(tok->n_args >= 6);
3093 if (voter)
3094 smartlist_add(ns->voters, voter);
3095 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
3096 voter->sigs = smartlist_new();
3097 if (ns->type != NS_TYPE_CONSENSUS)
3098 memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN);
3100 voter->nickname = tor_strdup(tok->args[0]);
3101 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
3102 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
3103 tok->args[1], HEX_DIGEST_LEN)
3104 != sizeof(voter->identity_digest)) {
3105 log_warn(LD_DIR, "Error decoding identity digest %s in "
3106 "network-status document.", escaped(tok->args[1]));
3107 goto err;
3109 if (ns->type != NS_TYPE_CONSENSUS &&
3110 tor_memneq(ns->cert->cache_info.identity_digest,
3111 voter->identity_digest, DIGEST_LEN)) {
3112 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
3113 goto err;
3115 if (ns->type != NS_TYPE_CONSENSUS) {
3116 if (authority_cert_is_blacklisted(ns->cert)) {
3117 log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
3118 "signing key %s",
3119 hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
3120 goto err;
3123 voter->address = tor_strdup(tok->args[2]);
3124 if (!tor_inet_aton(tok->args[3], &in)) {
3125 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
3126 escaped(tok->args[3]));
3127 goto err;
3129 voter->addr = ntohl(in.s_addr);
3130 voter->dir_port = (uint16_t)
3131 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
3132 if (!ok)
3133 goto err;
3134 voter->or_port = (uint16_t)
3135 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
3136 if (!ok)
3137 goto err;
3138 } else if (tok->tp == K_CONTACT) {
3139 if (!voter || voter->contact) {
3140 log_warn(LD_DIR, "contact element is out of place.");
3141 goto err;
3143 voter->contact = tor_strdup(tok->args[0]);
3144 } else if (tok->tp == K_VOTE_DIGEST) {
3145 tor_assert(ns->type == NS_TYPE_CONSENSUS);
3146 tor_assert(tok->n_args >= 1);
3147 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
3148 log_warn(LD_DIR, "vote-digest element is out of place.");
3149 goto err;
3151 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
3152 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
3153 tok->args[0], HEX_DIGEST_LEN)
3154 != sizeof(voter->vote_digest)) {
3155 log_warn(LD_DIR, "Error decoding vote digest %s in "
3156 "network-status consensus.", escaped(tok->args[0]));
3157 goto err;
3160 } SMARTLIST_FOREACH_END(_tok);
3161 if (voter) {
3162 smartlist_add(ns->voters, voter);
3163 voter = NULL;
3165 if (smartlist_len(ns->voters) == 0) {
3166 log_warn(LD_DIR, "Missing dir-source elements in a networkstatus.");
3167 goto err;
3168 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
3169 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
3170 goto err;
3173 if (ns->type != NS_TYPE_CONSENSUS &&
3174 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
3175 int bad = 1;
3176 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
3177 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
3178 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
3179 tok->args[0], HEX_DIGEST_LEN) != DIGEST_LEN)
3180 bad = 1;
3181 else
3182 bad = 0;
3184 if (bad) {
3185 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
3186 escaped(tok->args[0]));
3190 /* Parse routerstatus lines. */
3191 rs_tokens = smartlist_new();
3192 rs_area = memarea_new();
3193 s = end_of_header;
3194 ns->routerstatus_list = smartlist_new();
3196 while (!strcmpstart(s, "r ")) {
3197 if (ns->type != NS_TYPE_CONSENSUS) {
3198 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
3199 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
3200 rs, 0, 0))
3201 smartlist_add(ns->routerstatus_list, rs);
3202 else {
3203 tor_free(rs->version);
3204 tor_free(rs);
3206 } else {
3207 routerstatus_t *rs;
3208 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
3209 NULL, NULL,
3210 ns->consensus_method,
3211 flav))) {
3212 /* Use exponential-backoff scheduling when downloading microdescs */
3213 rs->dl_status.backoff = DL_SCHED_RANDOM_EXPONENTIAL;
3214 smartlist_add(ns->routerstatus_list, rs);
3218 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
3219 routerstatus_t *rs1, *rs2;
3220 if (ns->type != NS_TYPE_CONSENSUS) {
3221 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
3222 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
3223 rs1 = &a->status; rs2 = &b->status;
3224 } else {
3225 rs1 = smartlist_get(ns->routerstatus_list, i-1);
3226 rs2 = smartlist_get(ns->routerstatus_list, i);
3228 if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
3229 >= 0) {
3230 log_warn(LD_DIR, "Networkstatus entries not sorted by identity digest");
3231 goto err;
3234 if (ns_type != NS_TYPE_CONSENSUS) {
3235 digest256map_t *ed_id_map = digest256map_new();
3236 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, vote_routerstatus_t *,
3237 vrs) {
3238 if (! vrs->has_ed25519_listing ||
3239 tor_mem_is_zero((const char *)vrs->ed25519_id, DIGEST256_LEN))
3240 continue;
3241 if (digest256map_get(ed_id_map, vrs->ed25519_id) != NULL) {
3242 log_warn(LD_DIR, "Vote networkstatus ed25519 identities were not "
3243 "unique");
3244 digest256map_free(ed_id_map, NULL);
3245 goto err;
3247 digest256map_set(ed_id_map, vrs->ed25519_id, (void*)1);
3248 } SMARTLIST_FOREACH_END(vrs);
3249 digest256map_free(ed_id_map, NULL);
3252 /* Parse footer; check signature. */
3253 footer_tokens = smartlist_new();
3254 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
3255 ++end_of_footer;
3256 else
3257 end_of_footer = s + strlen(s);
3258 if (tokenize_string(area,s, end_of_footer, footer_tokens,
3259 networkstatus_vote_footer_token_table, 0)) {
3260 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
3261 goto err;
3265 int found_sig = 0;
3266 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
3267 tok = _tok;
3268 if (tok->tp == K_DIRECTORY_SIGNATURE)
3269 found_sig = 1;
3270 else if (found_sig) {
3271 log_warn(LD_DIR, "Extraneous token after first directory-signature");
3272 goto err;
3274 } SMARTLIST_FOREACH_END(_tok);
3277 if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
3278 if (tok != smartlist_get(footer_tokens, 0)) {
3279 log_warn(LD_DIR, "Misplaced directory-footer token");
3280 goto err;
3284 tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
3285 if (tok) {
3286 ns->weight_params = smartlist_new();
3287 for (i = 0; i < tok->n_args; ++i) {
3288 int ok=0;
3289 char *eq = strchr(tok->args[i], '=');
3290 if (!eq) {
3291 log_warn(LD_DIR, "Bad element '%s' in weight params",
3292 escaped(tok->args[i]));
3293 goto err;
3295 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
3296 if (!ok) {
3297 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3298 goto err;
3300 smartlist_add(ns->weight_params, tor_strdup(tok->args[i]));
3304 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
3305 char declared_identity[DIGEST_LEN];
3306 networkstatus_voter_info_t *v;
3307 document_signature_t *sig;
3308 const char *id_hexdigest = NULL;
3309 const char *sk_hexdigest = NULL;
3310 digest_algorithm_t alg = DIGEST_SHA1;
3311 tok = _tok;
3312 if (tok->tp != K_DIRECTORY_SIGNATURE)
3313 continue;
3314 tor_assert(tok->n_args >= 2);
3315 if (tok->n_args == 2) {
3316 id_hexdigest = tok->args[0];
3317 sk_hexdigest = tok->args[1];
3318 } else {
3319 const char *algname = tok->args[0];
3320 int a;
3321 id_hexdigest = tok->args[1];
3322 sk_hexdigest = tok->args[2];
3323 a = crypto_digest_algorithm_parse_name(algname);
3324 if (a<0) {
3325 log_warn(LD_DIR, "Unknown digest algorithm %s; skipping",
3326 escaped(algname));
3327 continue;
3329 alg = a;
3332 if (!tok->object_type ||
3333 strcmp(tok->object_type, "SIGNATURE") ||
3334 tok->object_size < 128 || tok->object_size > 512) {
3335 log_warn(LD_DIR, "Bad object type or length on directory-signature");
3336 goto err;
3339 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
3340 base16_decode(declared_identity, sizeof(declared_identity),
3341 id_hexdigest, HEX_DIGEST_LEN)
3342 != sizeof(declared_identity)) {
3343 log_warn(LD_DIR, "Error decoding declared identity %s in "
3344 "network-status document.", escaped(id_hexdigest));
3345 goto err;
3347 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
3348 log_warn(LD_DIR, "ID on signature on network-status document does "
3349 "not match any declared directory source.");
3350 goto err;
3352 sig = tor_malloc_zero(sizeof(document_signature_t));
3353 memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN);
3354 sig->alg = alg;
3355 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
3356 base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
3357 sk_hexdigest, HEX_DIGEST_LEN)
3358 != sizeof(sig->signing_key_digest)) {
3359 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
3360 "network-status document.", escaped(sk_hexdigest));
3361 tor_free(sig);
3362 goto err;
3365 if (ns->type != NS_TYPE_CONSENSUS) {
3366 if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest,
3367 DIGEST_LEN)) {
3368 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
3369 "network-status vote.");
3370 tor_free(sig);
3371 goto err;
3375 if (voter_get_sig_by_algorithm(v, sig->alg)) {
3376 /* We already parsed a vote with this algorithm from this voter. Use the
3377 first one. */
3378 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
3379 "that contains two signatures from the same voter with the same "
3380 "algorithm. Ignoring the second signature.");
3381 tor_free(sig);
3382 continue;
3385 if (ns->type != NS_TYPE_CONSENSUS) {
3386 if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
3387 tok, ns->cert->signing_key, 0,
3388 "network-status document")) {
3389 tor_free(sig);
3390 goto err;
3392 sig->good_signature = 1;
3393 } else {
3394 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
3395 tor_free(sig);
3396 goto err;
3398 sig->signature = tor_memdup(tok->object_body, tok->object_size);
3399 sig->signature_len = (int) tok->object_size;
3401 smartlist_add(v->sigs, sig);
3403 ++n_signatures;
3404 } SMARTLIST_FOREACH_END(_tok);
3406 if (! n_signatures) {
3407 log_warn(LD_DIR, "No signatures on networkstatus document.");
3408 goto err;
3409 } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
3410 log_warn(LD_DIR, "Received more than one signature on a "
3411 "network-status vote.");
3412 goto err;
3415 if (eos_out)
3416 *eos_out = end_of_footer;
3418 goto done;
3419 err:
3420 dump_desc(s_dup, "v3 networkstatus");
3421 networkstatus_vote_free(ns);
3422 ns = NULL;
3423 done:
3424 if (tokens) {
3425 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3426 smartlist_free(tokens);
3428 if (voter) {
3429 if (voter->sigs) {
3430 SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
3431 document_signature_free(sig));
3432 smartlist_free(voter->sigs);
3434 tor_free(voter->nickname);
3435 tor_free(voter->address);
3436 tor_free(voter->contact);
3437 tor_free(voter);
3439 if (rs_tokens) {
3440 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t));
3441 smartlist_free(rs_tokens);
3443 if (footer_tokens) {
3444 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
3445 smartlist_free(footer_tokens);
3447 if (area) {
3448 DUMP_AREA(area, "v3 networkstatus");
3449 memarea_drop_all(area);
3451 if (rs_area)
3452 memarea_drop_all(rs_area);
3453 tor_free(last_kwd);
3455 return ns;
3458 /** Return the common_digests_t that holds the digests of the
3459 * <b>flavor_name</b>-flavored networkstatus according to the detached
3460 * signatures document <b>sigs</b>, allocating a new common_digests_t as
3461 * neeeded. */
3462 static common_digests_t *
3463 detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name)
3465 common_digests_t *d = strmap_get(sigs->digests, flavor_name);
3466 if (!d) {
3467 d = tor_malloc_zero(sizeof(common_digests_t));
3468 strmap_set(sigs->digests, flavor_name, d);
3470 return d;
3473 /** Return the list of signatures of the <b>flavor_name</b>-flavored
3474 * networkstatus according to the detached signatures document <b>sigs</b>,
3475 * allocating a new common_digests_t as neeeded. */
3476 static smartlist_t *
3477 detached_get_signatures(ns_detached_signatures_t *sigs,
3478 const char *flavor_name)
3480 smartlist_t *sl = strmap_get(sigs->signatures, flavor_name);
3481 if (!sl) {
3482 sl = smartlist_new();
3483 strmap_set(sigs->signatures, flavor_name, sl);
3485 return sl;
3488 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
3489 * <b>eos</b> and return the result. Return -1 on failure. */
3490 ns_detached_signatures_t *
3491 networkstatus_parse_detached_signatures(const char *s, const char *eos)
3493 /* XXXX there is too much duplicate shared between this function and
3494 * networkstatus_parse_vote_from_string(). */
3495 directory_token_t *tok;
3496 memarea_t *area = NULL;
3497 common_digests_t *digests;
3499 smartlist_t *tokens = smartlist_new();
3500 ns_detached_signatures_t *sigs =
3501 tor_malloc_zero(sizeof(ns_detached_signatures_t));
3502 sigs->digests = strmap_new();
3503 sigs->signatures = strmap_new();
3505 if (!eos)
3506 eos = s + strlen(s);
3508 area = memarea_new();
3509 if (tokenize_string(area,s, eos, tokens,
3510 networkstatus_detached_signature_token_table, 0)) {
3511 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
3512 goto err;
3515 /* Grab all the digest-like tokens. */
3516 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3517 const char *algname;
3518 digest_algorithm_t alg;
3519 const char *flavor;
3520 const char *hexdigest;
3521 size_t expected_length, digest_length;
3523 tok = _tok;
3525 if (tok->tp == K_CONSENSUS_DIGEST) {
3526 algname = "sha1";
3527 alg = DIGEST_SHA1;
3528 flavor = "ns";
3529 hexdigest = tok->args[0];
3530 } else if (tok->tp == K_ADDITIONAL_DIGEST) {
3531 int a = crypto_digest_algorithm_parse_name(tok->args[1]);
3532 if (a<0) {
3533 log_warn(LD_DIR, "Unrecognized algorithm name %s", tok->args[0]);
3534 continue;
3536 alg = (digest_algorithm_t) a;
3537 flavor = tok->args[0];
3538 algname = tok->args[1];
3539 hexdigest = tok->args[2];
3540 } else {
3541 continue;
3544 digest_length = crypto_digest_algorithm_get_length(alg);
3545 expected_length = digest_length * 2; /* hex encoding */
3547 if (strlen(hexdigest) != expected_length) {
3548 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
3549 "networkstatus signatures");
3550 goto err;
3552 digests = detached_get_digests(sigs, flavor);
3553 tor_assert(digests);
3554 if (!tor_mem_is_zero(digests->d[alg], digest_length)) {
3555 log_warn(LD_DIR, "Multiple digests for %s with %s on detached "
3556 "signatures document", flavor, algname);
3557 continue;
3559 if (base16_decode(digests->d[alg], digest_length,
3560 hexdigest, strlen(hexdigest)) != (int) digest_length) {
3561 log_warn(LD_DIR, "Bad encoding on consensus-digest in detached "
3562 "networkstatus signatures");
3563 goto err;
3565 } SMARTLIST_FOREACH_END(_tok);
3567 tok = find_by_keyword(tokens, K_VALID_AFTER);
3568 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
3569 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
3570 goto err;
3573 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
3574 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
3575 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
3576 goto err;
3579 tok = find_by_keyword(tokens, K_VALID_UNTIL);
3580 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
3581 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
3582 goto err;
3585 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3586 const char *id_hexdigest;
3587 const char *sk_hexdigest;
3588 const char *algname;
3589 const char *flavor;
3590 digest_algorithm_t alg;
3592 char id_digest[DIGEST_LEN];
3593 char sk_digest[DIGEST_LEN];
3594 smartlist_t *siglist;
3595 document_signature_t *sig;
3596 int is_duplicate;
3598 tok = _tok;
3599 if (tok->tp == K_DIRECTORY_SIGNATURE) {
3600 tor_assert(tok->n_args >= 2);
3601 flavor = "ns";
3602 algname = "sha1";
3603 id_hexdigest = tok->args[0];
3604 sk_hexdigest = tok->args[1];
3605 } else if (tok->tp == K_ADDITIONAL_SIGNATURE) {
3606 tor_assert(tok->n_args >= 4);
3607 flavor = tok->args[0];
3608 algname = tok->args[1];
3609 id_hexdigest = tok->args[2];
3610 sk_hexdigest = tok->args[3];
3611 } else {
3612 continue;
3616 int a = crypto_digest_algorithm_parse_name(algname);
3617 if (a<0) {
3618 log_warn(LD_DIR, "Unrecognized algorithm name %s", algname);
3619 continue;
3621 alg = (digest_algorithm_t) a;
3624 if (!tok->object_type ||
3625 strcmp(tok->object_type, "SIGNATURE") ||
3626 tok->object_size < 128 || tok->object_size > 512) {
3627 log_warn(LD_DIR, "Bad object type or length on directory-signature");
3628 goto err;
3631 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
3632 base16_decode(id_digest, sizeof(id_digest),
3633 id_hexdigest, HEX_DIGEST_LEN) != sizeof(id_digest)) {
3634 log_warn(LD_DIR, "Error decoding declared identity %s in "
3635 "network-status vote.", escaped(id_hexdigest));
3636 goto err;
3638 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
3639 base16_decode(sk_digest, sizeof(sk_digest),
3640 sk_hexdigest, HEX_DIGEST_LEN) != sizeof(sk_digest)) {
3641 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
3642 "network-status vote.", escaped(sk_hexdigest));
3643 goto err;
3646 siglist = detached_get_signatures(sigs, flavor);
3647 is_duplicate = 0;
3648 SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
3649 if (dsig->alg == alg &&
3650 tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
3651 tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
3652 is_duplicate = 1;
3655 if (is_duplicate) {
3656 log_warn(LD_DIR, "Two signatures with identical keys and algorithm "
3657 "found.");
3658 continue;
3661 sig = tor_malloc_zero(sizeof(document_signature_t));
3662 sig->alg = alg;
3663 memcpy(sig->identity_digest, id_digest, DIGEST_LEN);
3664 memcpy(sig->signing_key_digest, sk_digest, DIGEST_LEN);
3665 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
3666 tor_free(sig);
3667 goto err;
3669 sig->signature = tor_memdup(tok->object_body, tok->object_size);
3670 sig->signature_len = (int) tok->object_size;
3672 smartlist_add(siglist, sig);
3673 } SMARTLIST_FOREACH_END(_tok);
3675 goto done;
3676 err:
3677 ns_detached_signatures_free(sigs);
3678 sigs = NULL;
3679 done:
3680 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3681 smartlist_free(tokens);
3682 if (area) {
3683 DUMP_AREA(area, "detached signatures");
3684 memarea_drop_all(area);
3686 return sigs;
3689 /** Parse the addr policy in the string <b>s</b> and return it. If
3690 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
3691 * ADDR_POLICY_REJECT) for items that specify no action.
3693 * Returns NULL on policy errors.
3695 * Set *<b>malformed_list</b> to true if the entire policy list should be
3696 * discarded. Otherwise, set it to false, and only this item should be ignored
3697 * on error - the rest of the policy list can continue to be processed and
3698 * used.
3700 * The addr_policy_t returned by this function can have its address set to
3701 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
3702 * of AF_INET and AF_INET6 items.
3704 MOCK_IMPL(addr_policy_t *,
3705 router_parse_addr_policy_item_from_string,(const char *s, int assume_action,
3706 int *malformed_list))
3708 directory_token_t *tok = NULL;
3709 const char *cp, *eos;
3710 /* Longest possible policy is
3711 * "accept6 [ffff:ffff:..255]/128:10000-65535",
3712 * which contains a max-length IPv6 address, plus 26 characters.
3713 * But note that there can be an arbitrary amount of space between the
3714 * accept and the address:mask/port element.
3715 * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
3716 * IPv6 address. But making the buffer shorter might cause valid long lines,
3717 * which parsed in previous versions, to fail to parse in new versions.
3718 * (These lines would have to have excessive amounts of whitespace.) */
3719 char line[TOR_ADDR_BUF_LEN*2 + 32];
3720 addr_policy_t *r;
3721 memarea_t *area = NULL;
3723 tor_assert(malformed_list);
3724 *malformed_list = 0;
3726 s = eat_whitespace(s);
3727 /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
3728 * and ":" (port separator) are ambiguous */
3729 if ((*s == '*' || *s == '[' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
3730 if (tor_snprintf(line, sizeof(line), "%s %s",
3731 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
3732 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
3733 return NULL;
3735 cp = line;
3736 tor_strlower(line);
3737 } else { /* assume an already well-formed address policy line */
3738 cp = s;
3741 eos = cp + strlen(cp);
3742 area = memarea_new();
3743 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
3744 if (tok->tp == ERR_) {
3745 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
3746 goto err;
3748 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
3749 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
3750 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
3751 goto err;
3754 /* Use the extended interpretation of accept/reject *,
3755 * expanding it into an IPv4 wildcard and an IPv6 wildcard.
3756 * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
3757 r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
3758 if (!r) {
3759 goto err;
3762 /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
3763 * AF_UNSPEC addresses are only permitted on the accept/reject field type.
3764 * Unlike descriptors, torrcs exit policy accept/reject can be followed by
3765 * either an IPv4 or IPv6 address. */
3766 if ((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
3767 tor_addr_family(&r->addr) != AF_INET6) {
3768 /* This is a non-fatal error, just ignore this one entry. */
3769 *malformed_list = 0;
3770 log_warn(LD_DIR, "IPv4 address '%s' with accept6/reject6 field type in "
3771 "exit policy. Ignoring, but continuing to parse rules. (Use "
3772 "accept/reject with IPv4 addresses.)",
3773 tok->n_args == 1 ? tok->args[0] : "");
3774 addr_policy_free(r);
3775 r = NULL;
3776 goto done;
3779 goto done;
3780 err:
3781 *malformed_list = 1;
3782 r = NULL;
3783 done:
3784 token_clear(tok);
3785 if (area) {
3786 DUMP_AREA(area, "policy item");
3787 memarea_drop_all(area);
3789 return r;
3792 /** Add an exit policy stored in the token <b>tok</b> to the router info in
3793 * <b>router</b>. Return 0 on success, -1 on failure. */
3794 static int
3795 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
3797 addr_policy_t *newe;
3798 /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
3799 newe = router_parse_addr_policy(tok, 0);
3800 if (!newe)
3801 return -1;
3802 if (! router->exit_policy)
3803 router->exit_policy = smartlist_new();
3805 /* Ensure that in descriptors, accept/reject fields are followed by
3806 * IPv4 addresses, and accept6/reject6 fields are followed by
3807 * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
3808 * accept/reject followed by IPv6. */
3809 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
3810 tor_addr_family(&newe->addr) == AF_INET)
3812 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
3813 tor_addr_family(&newe->addr) == AF_INET6)) {
3814 /* There's nothing the user can do about other relays' descriptors,
3815 * so we don't provide usage advice here. */
3816 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
3817 "policy '%s'. Discarding entire router descriptor.",
3818 tok->n_args == 1 ? tok->args[0] : "");
3819 addr_policy_free(newe);
3820 return -1;
3823 smartlist_add(router->exit_policy, newe);
3825 return 0;
3828 /** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
3829 * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
3830 * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
3831 * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
3832 * policies */
3833 static addr_policy_t *
3834 router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
3836 addr_policy_t newe;
3837 char *arg;
3839 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
3840 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
3842 if (tok->n_args != 1)
3843 return NULL;
3844 arg = tok->args[0];
3846 if (!strcmpstart(arg,"private"))
3847 return router_parse_addr_policy_private(tok);
3849 memset(&newe, 0, sizeof(newe));
3851 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3852 newe.policy_type = ADDR_POLICY_REJECT;
3853 else
3854 newe.policy_type = ADDR_POLICY_ACCEPT;
3856 /* accept6/reject6 * produces an IPv6 wildcard address only.
3857 * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
3858 if ((fmt_flags & TAPMP_EXTENDED_STAR)
3859 && (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6)) {
3860 fmt_flags |= TAPMP_STAR_IPV6_ONLY;
3863 if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
3864 &newe.prt_min, &newe.prt_max) < 0) {
3865 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
3866 return NULL;
3869 return addr_policy_get_canonical_entry(&newe);
3872 /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
3873 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
3874 * router descriptors until earlier versions are obsolete.
3876 * accept/reject and accept6/reject6 private all produce rules for both
3877 * IPv4 and IPv6 addresses.
3879 static addr_policy_t *
3880 router_parse_addr_policy_private(directory_token_t *tok)
3882 const char *arg;
3883 uint16_t port_min, port_max;
3884 addr_policy_t result;
3886 arg = tok->args[0];
3887 if (strcmpstart(arg, "private"))
3888 return NULL;
3890 arg += strlen("private");
3891 arg = (char*) eat_whitespace(arg);
3892 if (!arg || *arg != ':')
3893 return NULL;
3895 if (parse_port_range(arg+1, &port_min, &port_max)<0)
3896 return NULL;
3898 memset(&result, 0, sizeof(result));
3899 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3900 result.policy_type = ADDR_POLICY_REJECT;
3901 else
3902 result.policy_type = ADDR_POLICY_ACCEPT;
3903 result.is_private = 1;
3904 result.prt_min = port_min;
3905 result.prt_max = port_max;
3907 if (tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) {
3908 log_warn(LD_GENERAL,
3909 "'%s' expands into rules which apply to all private IPv4 and "
3910 "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
3911 "IPv6.)", tok->n_args == 1 ? tok->args[0] : "");
3914 return addr_policy_get_canonical_entry(&result);
3917 /** Log and exit if <b>t</b> is malformed */
3918 void
3919 assert_addr_policy_ok(smartlist_t *lst)
3921 if (!lst) return;
3922 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
3923 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
3924 t->policy_type == ADDR_POLICY_ACCEPT);
3925 tor_assert(t->prt_min <= t->prt_max);
3930 * Low-level tokenizer for router descriptors and directories.
3933 /** Free all resources allocated for <b>tok</b> */
3934 static void
3935 token_clear(directory_token_t *tok)
3937 if (tok->key)
3938 crypto_pk_free(tok->key);
3941 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
3942 #define ALLOC(sz) memarea_alloc(area,sz)
3943 #define STRDUP(str) memarea_strdup(area,str)
3944 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
3946 #define RET_ERR(msg) \
3947 STMT_BEGIN \
3948 if (tok) token_clear(tok); \
3949 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
3950 tok->tp = ERR_; \
3951 tok->error = STRDUP(msg); \
3952 goto done_tokenizing; \
3953 STMT_END
3955 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
3956 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
3957 * Return <b>tok</b> on success, or a new ERR_ token if the token didn't
3958 * conform to the syntax we wanted.
3960 static inline directory_token_t *
3961 token_check_object(memarea_t *area, const char *kwd,
3962 directory_token_t *tok, obj_syntax o_syn)
3964 char ebuf[128];
3965 switch (o_syn) {
3966 case NO_OBJ:
3967 /* No object is allowed for this token. */
3968 if (tok->object_body) {
3969 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
3970 RET_ERR(ebuf);
3972 if (tok->key) {
3973 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
3974 RET_ERR(ebuf);
3976 break;
3977 case NEED_OBJ:
3978 /* There must be a (non-key) object. */
3979 if (!tok->object_body) {
3980 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
3981 RET_ERR(ebuf);
3983 break;
3984 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
3985 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
3986 if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
3987 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
3988 kwd, crypto_pk_num_bits(tok->key));
3989 RET_ERR(ebuf);
3991 /* fall through */
3992 case NEED_KEY: /* There must be some kind of key. */
3993 if (!tok->key) {
3994 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
3995 RET_ERR(ebuf);
3997 if (o_syn != NEED_SKEY_1024) {
3998 if (crypto_pk_key_is_private(tok->key)) {
3999 tor_snprintf(ebuf, sizeof(ebuf),
4000 "Private key given for %s, which wants a public key", kwd);
4001 RET_ERR(ebuf);
4003 } else { /* o_syn == NEED_SKEY_1024 */
4004 if (!crypto_pk_key_is_private(tok->key)) {
4005 tor_snprintf(ebuf, sizeof(ebuf),
4006 "Public key given for %s, which wants a private key", kwd);
4007 RET_ERR(ebuf);
4010 break;
4011 case OBJ_OK:
4012 /* Anything goes with this token. */
4013 break;
4016 done_tokenizing:
4017 return tok;
4020 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
4021 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
4022 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
4023 * all storage in <b>area</b>. Return the number of arguments parsed, or
4024 * return -1 if there was an insanely high number of arguments. */
4025 static inline int
4026 get_token_arguments(memarea_t *area, directory_token_t *tok,
4027 const char *s, const char *eol)
4029 /** Largest number of arguments we'll accept to any token, ever. */
4030 #define MAX_ARGS 512
4031 char *mem = memarea_strndup(area, s, eol-s);
4032 char *cp = mem;
4033 int j = 0;
4034 char *args[MAX_ARGS];
4035 while (*cp) {
4036 if (j == MAX_ARGS)
4037 return -1;
4038 args[j++] = cp;
4039 cp = (char*)find_whitespace(cp);
4040 if (!cp || !*cp)
4041 break; /* End of the line. */
4042 *cp++ = '\0';
4043 cp = (char*)eat_whitespace(cp);
4045 tok->n_args = j;
4046 tok->args = memarea_memdup(area, args, j*sizeof(char*));
4047 return j;
4048 #undef MAX_ARGS
4051 /** Helper function: read the next token from *s, advance *s to the end of the
4052 * token, and return the parsed token. Parse *<b>s</b> according to the list
4053 * of tokens in <b>table</b>.
4055 static directory_token_t *
4056 get_next_token(memarea_t *area,
4057 const char **s, const char *eos, token_rule_t *table)
4059 /** Reject any object at least this big; it is probably an overflow, an
4060 * attack, a bug, or some other nonsense. */
4061 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
4062 /** Reject any line at least this big; it is probably an overflow, an
4063 * attack, a bug, or some other nonsense. */
4064 #define MAX_LINE_LENGTH (128*1024)
4066 const char *next, *eol, *obstart;
4067 size_t obname_len;
4068 int i;
4069 directory_token_t *tok;
4070 obj_syntax o_syn = NO_OBJ;
4071 char ebuf[128];
4072 const char *kwd = "";
4074 tor_assert(area);
4075 tok = ALLOC_ZERO(sizeof(directory_token_t));
4076 tok->tp = ERR_;
4078 /* Set *s to first token, eol to end-of-line, next to after first token */
4079 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
4080 tor_assert(eos >= *s);
4081 eol = memchr(*s, '\n', eos-*s);
4082 if (!eol)
4083 eol = eos;
4084 if (eol - *s > MAX_LINE_LENGTH) {
4085 RET_ERR("Line far too long");
4088 next = find_whitespace_eos(*s, eol);
4090 if (!strcmp_len(*s, "opt", next-*s)) {
4091 /* Skip past an "opt" at the start of the line. */
4092 *s = eat_whitespace_eos_no_nl(next, eol);
4093 next = find_whitespace_eos(*s, eol);
4094 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
4095 RET_ERR("Unexpected EOF");
4098 /* Search the table for the appropriate entry. (I tried a binary search
4099 * instead, but it wasn't any faster.) */
4100 for (i = 0; table[i].t ; ++i) {
4101 if (!strcmp_len(*s, table[i].t, next-*s)) {
4102 /* We've found the keyword. */
4103 kwd = table[i].t;
4104 tok->tp = table[i].v;
4105 o_syn = table[i].os;
4106 *s = eat_whitespace_eos_no_nl(next, eol);
4107 /* We go ahead whether there are arguments or not, so that tok->args is
4108 * always set if we want arguments. */
4109 if (table[i].concat_args) {
4110 /* The keyword takes the line as a single argument */
4111 tok->args = ALLOC(sizeof(char*));
4112 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
4113 tok->n_args = 1;
4114 } else {
4115 /* This keyword takes multiple arguments. */
4116 if (get_token_arguments(area, tok, *s, eol)<0) {
4117 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
4118 RET_ERR(ebuf);
4120 *s = eol;
4122 if (tok->n_args < table[i].min_args) {
4123 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
4124 RET_ERR(ebuf);
4125 } else if (tok->n_args > table[i].max_args) {
4126 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
4127 RET_ERR(ebuf);
4129 break;
4133 if (tok->tp == ERR_) {
4134 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
4135 if (**s == '@')
4136 tok->tp = A_UNKNOWN_;
4137 else
4138 tok->tp = K_OPT;
4139 tok->args = ALLOC(sizeof(char*));
4140 tok->args[0] = STRNDUP(*s, eol-*s);
4141 tok->n_args = 1;
4142 o_syn = OBJ_OK;
4145 /* Check whether there's an object present */
4146 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
4147 tor_assert(eos >= *s);
4148 eol = memchr(*s, '\n', eos-*s);
4149 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
4150 goto check_object;
4152 obstart = *s; /* Set obstart to start of object spec */
4153 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
4154 strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
4155 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
4156 RET_ERR("Malformed object: bad begin line");
4158 tok->object_type = STRNDUP(*s+11, eol-*s-16);
4159 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
4160 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
4162 /* Go to the end of the object */
4163 next = tor_memstr(*s, eos-*s, "-----END ");
4164 if (!next) {
4165 RET_ERR("Malformed object: missing object end line");
4167 tor_assert(eos >= next);
4168 eol = memchr(next, '\n', eos-next);
4169 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
4170 eol = eos;
4171 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
4172 if ((size_t)(eol-next) != 9+obname_len+5 ||
4173 strcmp_len(next+9, tok->object_type, obname_len) ||
4174 strcmp_len(eol-5, "-----", 5)) {
4175 tor_snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
4176 tok->object_type);
4177 ebuf[sizeof(ebuf)-1] = '\0';
4178 RET_ERR(ebuf);
4180 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
4181 RET_ERR("Couldn't parse object: missing footer or object much too big.");
4183 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
4184 tok->key = crypto_pk_new();
4185 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
4186 RET_ERR("Couldn't parse public key.");
4187 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
4188 tok->key = crypto_pk_new();
4189 if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
4190 RET_ERR("Couldn't parse private key.");
4191 } else { /* If it's something else, try to base64-decode it */
4192 int r;
4193 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
4194 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
4195 if (r<0)
4196 RET_ERR("Malformed object: bad base64-encoded data");
4197 tok->object_size = r;
4199 *s = eol;
4201 check_object:
4202 tok = token_check_object(area, kwd, tok, o_syn);
4204 done_tokenizing:
4205 return tok;
4207 #undef RET_ERR
4208 #undef ALLOC
4209 #undef ALLOC_ZERO
4210 #undef STRDUP
4211 #undef STRNDUP
4214 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
4215 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
4216 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
4217 * entire string.
4219 static int
4220 tokenize_string(memarea_t *area,
4221 const char *start, const char *end, smartlist_t *out,
4222 token_rule_t *table, int flags)
4224 const char **s;
4225 directory_token_t *tok = NULL;
4226 int counts[NIL_];
4227 int i;
4228 int first_nonannotation;
4229 int prev_len = smartlist_len(out);
4230 tor_assert(area);
4232 s = &start;
4233 if (!end) {
4234 end = start+strlen(start);
4235 } else {
4236 /* it's only meaningful to check for nuls if we got an end-of-string ptr */
4237 if (memchr(start, '\0', end-start)) {
4238 log_warn(LD_DIR, "parse error: internal NUL character.");
4239 return -1;
4242 for (i = 0; i < NIL_; ++i)
4243 counts[i] = 0;
4245 SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]);
4247 while (*s < end && (!tok || tok->tp != EOF_)) {
4248 tok = get_next_token(area, s, end, table);
4249 if (tok->tp == ERR_) {
4250 log_warn(LD_DIR, "parse error: %s", tok->error);
4251 token_clear(tok);
4252 return -1;
4254 ++counts[tok->tp];
4255 smartlist_add(out, tok);
4256 *s = eat_whitespace_eos(*s, end);
4259 if (flags & TS_NOCHECK)
4260 return 0;
4262 if ((flags & TS_ANNOTATIONS_OK)) {
4263 first_nonannotation = -1;
4264 for (i = 0; i < smartlist_len(out); ++i) {
4265 tok = smartlist_get(out, i);
4266 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
4267 first_nonannotation = i;
4268 break;
4271 if (first_nonannotation < 0) {
4272 log_warn(LD_DIR, "parse error: item contains only annotations");
4273 return -1;
4275 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
4276 tok = smartlist_get(out, i);
4277 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
4278 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
4279 return -1;
4282 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
4283 if (first_nonannotation != prev_len) {
4284 log_warn(LD_DIR, "parse error: Unexpected annotations.");
4285 return -1;
4288 } else {
4289 for (i=0; i < smartlist_len(out); ++i) {
4290 tok = smartlist_get(out, i);
4291 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
4292 log_warn(LD_DIR, "parse error: no annotations allowed.");
4293 return -1;
4296 first_nonannotation = 0;
4298 for (i = 0; table[i].t; ++i) {
4299 if (counts[table[i].v] < table[i].min_cnt) {
4300 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
4301 return -1;
4303 if (counts[table[i].v] > table[i].max_cnt) {
4304 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
4305 return -1;
4307 if (table[i].pos & AT_START) {
4308 if (smartlist_len(out) < 1 ||
4309 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
4310 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
4311 return -1;
4314 if (table[i].pos & AT_END) {
4315 if (smartlist_len(out) < 1 ||
4316 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
4317 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
4318 return -1;
4322 return 0;
4325 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
4326 * NULL if no such keyword is found.
4328 static directory_token_t *
4329 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
4331 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
4332 return NULL;
4335 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
4336 * with an assert if no such keyword is found.
4338 static directory_token_t *
4339 find_by_keyword_(smartlist_t *s, directory_keyword keyword,
4340 const char *keyword_as_string)
4342 directory_token_t *tok = find_opt_by_keyword(s, keyword);
4343 if (PREDICT_UNLIKELY(!tok)) {
4344 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
4345 "been validated. Internal error.", keyword_as_string, (int)keyword);
4346 tor_assert(tok);
4348 return tok;
4351 /** If there are any directory_token_t entries in <b>s</b> whose keyword is
4352 * <b>k</b>, return a newly allocated smartlist_t containing all such entries,
4353 * in the same order in which they occur in <b>s</b>. Otherwise return
4354 * NULL. */
4355 static smartlist_t *
4356 find_all_by_keyword(smartlist_t *s, directory_keyword k)
4358 smartlist_t *out = NULL;
4359 SMARTLIST_FOREACH(s, directory_token_t *, t,
4360 if (t->tp == k) {
4361 if (!out)
4362 out = smartlist_new();
4363 smartlist_add(out, t);
4365 return out;
4368 /** Return a newly allocated smartlist of all accept or reject tokens in
4369 * <b>s</b>.
4371 static smartlist_t *
4372 find_all_exitpolicy(smartlist_t *s)
4374 smartlist_t *out = smartlist_new();
4375 SMARTLIST_FOREACH(s, directory_token_t *, t,
4376 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
4377 t->tp == K_REJECT || t->tp == K_REJECT6)
4378 smartlist_add(out,t));
4379 return out;
4382 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
4383 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
4384 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
4385 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
4387 * Return 0 on success and -1 on failure.
4389 static int
4390 router_get_hash_impl_helper(const char *s, size_t s_len,
4391 const char *start_str,
4392 const char *end_str, char end_c,
4393 const char **start_out, const char **end_out)
4395 const char *start, *end;
4396 start = tor_memstr(s, s_len, start_str);
4397 if (!start) {
4398 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
4399 return -1;
4401 if (start != s && *(start-1) != '\n') {
4402 log_warn(LD_DIR,
4403 "first occurrence of \"%s\" is not at the start of a line",
4404 start_str);
4405 return -1;
4407 end = tor_memstr(start+strlen(start_str),
4408 s_len - (start-s) - strlen(start_str), end_str);
4409 if (!end) {
4410 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
4411 return -1;
4413 end = memchr(end+strlen(end_str), end_c, s_len - (end-s) - strlen(end_str));
4414 if (!end) {
4415 log_warn(LD_DIR,"couldn't find EOL");
4416 return -1;
4418 ++end;
4420 *start_out = start;
4421 *end_out = end;
4422 return 0;
4425 /** Compute the digest of the substring of <b>s</b> taken from the first
4426 * occurrence of <b>start_str</b> through the first instance of c after the
4427 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
4428 * result in <b>digest</b>; return 0 on success.
4430 * If no such substring exists, return -1.
4432 static int
4433 router_get_hash_impl(const char *s, size_t s_len, char *digest,
4434 const char *start_str,
4435 const char *end_str, char end_c,
4436 digest_algorithm_t alg)
4438 const char *start=NULL, *end=NULL;
4439 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
4440 &start,&end)<0)
4441 return -1;
4443 if (alg == DIGEST_SHA1) {
4444 if (crypto_digest(digest, start, end-start)) {
4445 log_warn(LD_BUG,"couldn't compute digest");
4446 return -1;
4448 } else {
4449 if (crypto_digest256(digest, start, end-start, alg)) {
4450 log_warn(LD_BUG,"couldn't compute digest");
4451 return -1;
4455 return 0;
4458 /** As router_get_hash_impl, but compute all hashes. */
4459 static int
4460 router_get_hashes_impl(const char *s, size_t s_len, common_digests_t *digests,
4461 const char *start_str,
4462 const char *end_str, char end_c)
4464 const char *start=NULL, *end=NULL;
4465 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
4466 &start,&end)<0)
4467 return -1;
4469 if (crypto_common_digests(digests, start, end-start)) {
4470 log_warn(LD_BUG,"couldn't compute digests");
4471 return -1;
4474 return 0;
4477 /** Assuming that s starts with a microdesc, return the start of the
4478 * *NEXT* one. Return NULL on "not found." */
4479 static const char *
4480 find_start_of_next_microdesc(const char *s, const char *eos)
4482 int started_with_annotations;
4483 s = eat_whitespace_eos(s, eos);
4484 if (!s)
4485 return NULL;
4487 #define CHECK_LENGTH() STMT_BEGIN \
4488 if (s+32 > eos) \
4489 return NULL; \
4490 STMT_END
4492 #define NEXT_LINE() STMT_BEGIN \
4493 s = memchr(s, '\n', eos-s); \
4494 if (!s || s+1 >= eos) \
4495 return NULL; \
4496 s++; \
4497 STMT_END
4499 CHECK_LENGTH();
4501 started_with_annotations = (*s == '@');
4503 if (started_with_annotations) {
4504 /* Start by advancing to the first non-annotation line. */
4505 while (*s == '@')
4506 NEXT_LINE();
4508 CHECK_LENGTH();
4510 /* Now we should be pointed at an onion-key line. If we are, then skip
4511 * it. */
4512 if (!strcmpstart(s, "onion-key"))
4513 NEXT_LINE();
4515 /* Okay, now we're pointed at the first line of the microdescriptor which is
4516 not an annotation or onion-key. The next line that _is_ an annotation or
4517 onion-key is the start of the next microdescriptor. */
4518 while (s+32 < eos) {
4519 if (*s == '@' || !strcmpstart(s, "onion-key"))
4520 return s;
4521 NEXT_LINE();
4523 return NULL;
4525 #undef CHECK_LENGTH
4526 #undef NEXT_LINE
4529 /** Parse as many microdescriptors as are found from the string starting at
4530 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4531 * annotations we recognize and ignore ones we don't.
4533 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
4534 * descriptor in the body field of each microdesc_t.
4536 * Return all newly parsed microdescriptors in a newly allocated
4537 * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
4538 * microdesc digest to it for every microdesc that we found to be badly
4539 * formed. (This may cause duplicates) */
4540 smartlist_t *
4541 microdescs_parse_from_string(const char *s, const char *eos,
4542 int allow_annotations,
4543 saved_location_t where,
4544 smartlist_t *invalid_digests_out)
4546 smartlist_t *tokens;
4547 smartlist_t *result;
4548 microdesc_t *md = NULL;
4549 memarea_t *area;
4550 const char *start = s;
4551 const char *start_of_next_microdesc;
4552 int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0;
4553 const int copy_body = (where != SAVED_IN_CACHE);
4555 directory_token_t *tok;
4557 if (!eos)
4558 eos = s + strlen(s);
4560 s = eat_whitespace_eos(s, eos);
4561 area = memarea_new();
4562 result = smartlist_new();
4563 tokens = smartlist_new();
4565 while (s < eos) {
4566 int okay = 0;
4568 start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
4569 if (!start_of_next_microdesc)
4570 start_of_next_microdesc = eos;
4572 md = tor_malloc_zero(sizeof(microdesc_t));
4574 const char *cp = tor_memstr(s, start_of_next_microdesc-s,
4575 "onion-key");
4576 const int no_onion_key = (cp == NULL);
4577 if (no_onion_key) {
4578 cp = s; /* So that we have *some* junk to put in the body */
4581 md->bodylen = start_of_next_microdesc - cp;
4582 md->saved_location = where;
4583 if (copy_body)
4584 md->body = tor_memdup_nulterm(cp, md->bodylen);
4585 else
4586 md->body = (char*)cp;
4587 md->off = cp - start;
4588 crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
4589 if (no_onion_key) {
4590 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "Malformed or truncated descriptor");
4591 goto next;
4595 if (tokenize_string(area, s, start_of_next_microdesc, tokens,
4596 microdesc_token_table, flags)) {
4597 log_warn(LD_DIR, "Unparseable microdescriptor");
4598 goto next;
4601 if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
4602 if (parse_iso_time(tok->args[0], &md->last_listed)) {
4603 log_warn(LD_DIR, "Bad last-listed time in microdescriptor");
4604 goto next;
4608 tok = find_by_keyword(tokens, K_ONION_KEY);
4609 if (!crypto_pk_public_exponent_ok(tok->key)) {
4610 log_warn(LD_DIR,
4611 "Relay's onion key had invalid exponent.");
4612 goto next;
4614 md->onion_pkey = tok->key;
4615 tok->key = NULL;
4617 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
4618 curve25519_public_key_t k;
4619 tor_assert(tok->n_args >= 1);
4620 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
4621 log_warn(LD_DIR, "Bogus ntor-onion-key in microdesc");
4622 goto next;
4624 md->onion_curve25519_pkey =
4625 tor_memdup(&k, sizeof(curve25519_public_key_t));
4628 smartlist_t *id_lines = find_all_by_keyword(tokens, K_ID);
4629 if (id_lines) {
4630 SMARTLIST_FOREACH_BEGIN(id_lines, directory_token_t *, t) {
4631 tor_assert(t->n_args >= 2);
4632 if (!strcmp(t->args[0], "ed25519")) {
4633 if (md->ed25519_identity_pkey) {
4634 log_warn(LD_DIR, "Extra ed25519 key in microdesc");
4635 goto next;
4637 ed25519_public_key_t k;
4638 if (ed25519_public_from_base64(&k, t->args[1])<0) {
4639 log_warn(LD_DIR, "Bogus ed25519 key in microdesc");
4640 goto next;
4642 md->ed25519_identity_pkey = tor_memdup(&k, sizeof(k));
4644 } SMARTLIST_FOREACH_END(t);
4645 smartlist_free(id_lines);
4649 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
4650 if (a_lines) {
4651 find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport);
4652 smartlist_free(a_lines);
4656 if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
4657 int i;
4658 md->family = smartlist_new();
4659 for (i=0;i<tok->n_args;++i) {
4660 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
4661 log_warn(LD_DIR, "Illegal nickname %s in family line",
4662 escaped(tok->args[i]));
4663 goto next;
4665 smartlist_add(md->family, tor_strdup(tok->args[i]));
4669 if ((tok = find_opt_by_keyword(tokens, K_P))) {
4670 md->exit_policy = parse_short_policy(tok->args[0]);
4672 if ((tok = find_opt_by_keyword(tokens, K_P6))) {
4673 md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
4676 smartlist_add(result, md);
4677 okay = 1;
4679 md = NULL;
4680 next:
4681 if (! okay && invalid_digests_out) {
4682 smartlist_add(invalid_digests_out,
4683 tor_memdup(md->digest, DIGEST256_LEN));
4685 microdesc_free(md);
4686 md = NULL;
4688 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4689 memarea_clear(area);
4690 smartlist_clear(tokens);
4691 s = start_of_next_microdesc;
4694 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4695 memarea_drop_all(area);
4696 smartlist_free(tokens);
4698 return result;
4701 /** Parse the Tor version of the platform string <b>platform</b>,
4702 * and compare it to the version in <b>cutoff</b>. Return 1 if
4703 * the router is at least as new as the cutoff, else return 0.
4706 tor_version_as_new_as(const char *platform, const char *cutoff)
4708 tor_version_t cutoff_version, router_version;
4709 char *s, *s2, *start;
4710 char tmp[128];
4712 tor_assert(platform);
4714 if (tor_version_parse(cutoff, &cutoff_version)<0) {
4715 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
4716 return 0;
4718 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
4719 return 1;
4721 start = (char *)eat_whitespace(platform+3);
4722 if (!*start) return 0;
4723 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
4724 s2 = (char*)eat_whitespace(s);
4725 if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
4726 s = (char*)find_whitespace(s2);
4728 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
4729 return 0;
4730 strlcpy(tmp, start, s-start+1);
4732 if (tor_version_parse(tmp, &router_version)<0) {
4733 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
4734 return 1; /* be safe and say yes */
4737 /* Here's why we don't need to do any special handling for svn revisions:
4738 * - If neither has an svn revision, we're fine.
4739 * - If the router doesn't have an svn revision, we can't assume that it
4740 * is "at least" any svn revision, so we need to return 0.
4741 * - If the target version doesn't have an svn revision, any svn revision
4742 * (or none at all) is good enough, so return 1.
4743 * - If both target and router have an svn revision, we compare them.
4746 return tor_version_compare(&router_version, &cutoff_version) >= 0;
4749 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4750 * Return 0 on success, -1 on failure. */
4752 tor_version_parse(const char *s, tor_version_t *out)
4754 char *eos=NULL;
4755 const char *cp=NULL;
4756 /* Format is:
4757 * "Tor " ? NUM dot NUM [ dot NUM [ ( pre | rc | dot ) NUM ] ] [ - tag ]
4759 tor_assert(s);
4760 tor_assert(out);
4762 memset(out, 0, sizeof(tor_version_t));
4763 out->status = VER_RELEASE;
4764 if (!strcasecmpstart(s, "Tor "))
4765 s += 4;
4767 cp = s;
4769 #define NUMBER(m) \
4770 do { \
4771 out->m = (int)strtol(cp, &eos, 10); \
4772 if (!eos || eos == cp) \
4773 return -1; \
4774 cp = eos; \
4775 } while (0)
4777 #define DOT() \
4778 do { \
4779 if (*cp != '.') \
4780 return -1; \
4781 ++cp; \
4782 } while (0)
4784 NUMBER(major);
4785 DOT();
4786 NUMBER(minor);
4787 if (*cp == 0)
4788 return 0;
4789 else if (*cp == '-')
4790 goto status_tag;
4791 DOT();
4792 NUMBER(micro);
4794 /* Get status */
4795 if (*cp == 0) {
4796 return 0;
4797 } else if (*cp == '.') {
4798 ++cp;
4799 } else if (*cp == '-') {
4800 goto status_tag;
4801 } else if (0==strncmp(cp, "pre", 3)) {
4802 out->status = VER_PRE;
4803 cp += 3;
4804 } else if (0==strncmp(cp, "rc", 2)) {
4805 out->status = VER_RC;
4806 cp += 2;
4807 } else {
4808 return -1;
4811 NUMBER(patchlevel);
4813 status_tag:
4814 /* Get status tag. */
4815 if (*cp == '-' || *cp == '.')
4816 ++cp;
4817 eos = (char*) find_whitespace(cp);
4818 if (eos-cp >= (int)sizeof(out->status_tag))
4819 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
4820 else {
4821 memcpy(out->status_tag, cp, eos-cp);
4822 out->status_tag[eos-cp] = 0;
4824 cp = eat_whitespace(eos);
4826 if (!strcmpstart(cp, "(r")) {
4827 cp += 2;
4828 out->svn_revision = (int) strtol(cp,&eos,10);
4829 } else if (!strcmpstart(cp, "(git-")) {
4830 char *close_paren = strchr(cp, ')');
4831 int hexlen;
4832 char digest[DIGEST_LEN];
4833 if (! close_paren)
4834 return -1;
4835 cp += 5;
4836 if (close_paren-cp > HEX_DIGEST_LEN)
4837 return -1;
4838 hexlen = (int)(close_paren-cp);
4839 memwipe(digest, 0, sizeof(digest));
4840 if ( hexlen == 0 || (hexlen % 2) == 1)
4841 return -1;
4842 if (base16_decode(digest, hexlen/2, cp, hexlen) != hexlen/2)
4843 return -1;
4844 memcpy(out->git_tag, digest, hexlen/2);
4845 out->git_tag_len = hexlen/2;
4848 return 0;
4849 #undef NUMBER
4850 #undef DOT
4853 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
4854 * b. */
4856 tor_version_compare(tor_version_t *a, tor_version_t *b)
4858 int i;
4859 tor_assert(a);
4860 tor_assert(b);
4861 if ((i = a->major - b->major))
4862 return i;
4863 else if ((i = a->minor - b->minor))
4864 return i;
4865 else if ((i = a->micro - b->micro))
4866 return i;
4867 else if ((i = a->status - b->status))
4868 return i;
4869 else if ((i = a->patchlevel - b->patchlevel))
4870 return i;
4871 else if ((i = strcmp(a->status_tag, b->status_tag)))
4872 return i;
4873 else if ((i = a->svn_revision - b->svn_revision))
4874 return i;
4875 else if ((i = a->git_tag_len - b->git_tag_len))
4876 return i;
4877 else if (a->git_tag_len)
4878 return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len);
4879 else
4880 return 0;
4883 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
4886 tor_version_same_series(tor_version_t *a, tor_version_t *b)
4888 tor_assert(a);
4889 tor_assert(b);
4890 return ((a->major == b->major) &&
4891 (a->minor == b->minor) &&
4892 (a->micro == b->micro));
4895 /** Helper: Given pointers to two strings describing tor versions, return -1
4896 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
4897 * Used to sort a list of versions. */
4898 static int
4899 compare_tor_version_str_ptr_(const void **_a, const void **_b)
4901 const char *a = *_a, *b = *_b;
4902 int ca, cb;
4903 tor_version_t va, vb;
4904 ca = tor_version_parse(a, &va);
4905 cb = tor_version_parse(b, &vb);
4906 /* If they both parse, compare them. */
4907 if (!ca && !cb)
4908 return tor_version_compare(&va,&vb);
4909 /* If one parses, it comes first. */
4910 if (!ca && cb)
4911 return -1;
4912 if (ca && !cb)
4913 return 1;
4914 /* If neither parses, compare strings. Also, the directory server admin
4915 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
4916 return strcmp(a,b);
4919 /** Sort a list of string-representations of versions in ascending order. */
4920 void
4921 sort_version_list(smartlist_t *versions, int remove_duplicates)
4923 smartlist_sort(versions, compare_tor_version_str_ptr_);
4925 if (remove_duplicates)
4926 smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_);
4929 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
4930 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
4931 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
4932 * encrypted introduction points to the newly allocated
4933 * *<b>intro_points_encrypted_out</b>, their encrypted size to
4934 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
4935 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
4936 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
4937 * and -1 for failure.
4939 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
4940 * be strict about time formats.
4943 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
4944 char *desc_id_out,
4945 char **intro_points_encrypted_out,
4946 size_t *intro_points_encrypted_size_out,
4947 size_t *encoded_size_out,
4948 const char **next_out, const char *desc,
4949 int as_hsdir)
4951 rend_service_descriptor_t *result =
4952 tor_malloc_zero(sizeof(rend_service_descriptor_t));
4953 char desc_hash[DIGEST_LEN];
4954 const char *eos;
4955 smartlist_t *tokens = smartlist_new();
4956 directory_token_t *tok;
4957 char secret_id_part[DIGEST_LEN];
4958 int i, version, num_ok=1;
4959 smartlist_t *versions;
4960 char public_key_hash[DIGEST_LEN];
4961 char test_desc_id[DIGEST_LEN];
4962 memarea_t *area = NULL;
4963 const int strict_time_fmt = as_hsdir;
4965 tor_assert(desc);
4966 /* Check if desc starts correctly. */
4967 if (strncmp(desc, "rendezvous-service-descriptor ",
4968 strlen("rendezvous-service-descriptor "))) {
4969 log_info(LD_REND, "Descriptor does not start correctly.");
4970 goto err;
4972 /* Compute descriptor hash for later validation. */
4973 if (router_get_hash_impl(desc, strlen(desc), desc_hash,
4974 "rendezvous-service-descriptor ",
4975 "\nsignature", '\n', DIGEST_SHA1) < 0) {
4976 log_warn(LD_REND, "Couldn't compute descriptor hash.");
4977 goto err;
4979 /* Determine end of string. */
4980 eos = strstr(desc, "\nrendezvous-service-descriptor ");
4981 if (!eos)
4982 eos = desc + strlen(desc);
4983 else
4984 eos = eos + 1;
4985 /* Check length. */
4986 if (eos-desc > REND_DESC_MAX_SIZE) {
4987 /* XXXX+ If we are parsing this descriptor as a server, this
4988 * should be a protocol warning. */
4989 log_warn(LD_REND, "Descriptor length is %d which exceeds "
4990 "maximum rendezvous descriptor size of %d bytes.",
4991 (int)(eos-desc), REND_DESC_MAX_SIZE);
4992 goto err;
4994 /* Tokenize descriptor. */
4995 area = memarea_new();
4996 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
4997 log_warn(LD_REND, "Error tokenizing descriptor.");
4998 goto err;
5000 /* Set next to next descriptor, if available. */
5001 *next_out = eos;
5002 /* Set length of encoded descriptor. */
5003 *encoded_size_out = eos - desc;
5004 /* Check min allowed length of token list. */
5005 if (smartlist_len(tokens) < 7) {
5006 log_warn(LD_REND, "Impossibly short descriptor.");
5007 goto err;
5009 /* Parse base32-encoded descriptor ID. */
5010 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
5011 tor_assert(tok == smartlist_get(tokens, 0));
5012 tor_assert(tok->n_args == 1);
5013 if (!rend_valid_descriptor_id(tok->args[0])) {
5014 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
5015 goto err;
5017 if (base32_decode(desc_id_out, DIGEST_LEN,
5018 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
5019 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
5020 tok->args[0]);
5021 goto err;
5023 /* Parse descriptor version. */
5024 tok = find_by_keyword(tokens, R_VERSION);
5025 tor_assert(tok->n_args == 1);
5026 result->version =
5027 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
5028 if (result->version != 2 || !num_ok) {
5029 /* If it's <2, it shouldn't be under this format. If the number
5030 * is greater than 2, we bumped it because we broke backward
5031 * compatibility. See how version numbers in our other formats
5032 * work. */
5033 log_warn(LD_REND, "Unrecognized descriptor version: %s",
5034 escaped(tok->args[0]));
5035 goto err;
5037 /* Parse public key. */
5038 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
5039 result->pk = tok->key;
5040 tok->key = NULL; /* Prevent free */
5041 /* Parse secret ID part. */
5042 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
5043 tor_assert(tok->n_args == 1);
5044 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
5045 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
5046 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
5047 goto err;
5049 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
5050 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
5051 tok->args[0]);
5052 goto err;
5054 /* Parse publication time -- up-to-date check is done when storing the
5055 * descriptor. */
5056 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
5057 tor_assert(tok->n_args == 1);
5058 if (parse_iso_time_(tok->args[0], &result->timestamp, strict_time_fmt) < 0) {
5059 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
5060 goto err;
5062 /* Parse protocol versions. */
5063 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
5064 tor_assert(tok->n_args == 1);
5065 versions = smartlist_new();
5066 smartlist_split_string(versions, tok->args[0], ",",
5067 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
5068 for (i = 0; i < smartlist_len(versions); i++) {
5069 version = (int) tor_parse_long(smartlist_get(versions, i),
5070 10, 0, INT_MAX, &num_ok, NULL);
5071 if (!num_ok) /* It's a string; let's ignore it. */
5072 continue;
5073 if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
5074 /* Avoid undefined left-shift behaviour. */
5075 continue;
5076 result->protocols |= 1 << version;
5078 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
5079 smartlist_free(versions);
5080 /* Parse encrypted introduction points. Don't verify. */
5081 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
5082 if (tok) {
5083 if (strcmp(tok->object_type, "MESSAGE")) {
5084 log_warn(LD_DIR, "Bad object type: introduction points should be of "
5085 "type MESSAGE");
5086 goto err;
5088 *intro_points_encrypted_out = tor_memdup(tok->object_body,
5089 tok->object_size);
5090 *intro_points_encrypted_size_out = tok->object_size;
5091 } else {
5092 *intro_points_encrypted_out = NULL;
5093 *intro_points_encrypted_size_out = 0;
5095 /* Parse and verify signature. */
5096 tok = find_by_keyword(tokens, R_SIGNATURE);
5097 note_crypto_pk_op(VERIFY_RTR);
5098 if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
5099 "v2 rendezvous service descriptor") < 0)
5100 goto err;
5101 /* Verify that descriptor ID belongs to public key and secret ID part. */
5102 crypto_pk_get_digest(result->pk, public_key_hash);
5103 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
5104 secret_id_part);
5105 if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
5106 log_warn(LD_REND, "Parsed descriptor ID does not match "
5107 "computed descriptor ID.");
5108 goto err;
5110 goto done;
5111 err:
5112 rend_service_descriptor_free(result);
5113 result = NULL;
5114 done:
5115 if (tokens) {
5116 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5117 smartlist_free(tokens);
5119 if (area)
5120 memarea_drop_all(area);
5121 *parsed_out = result;
5122 if (result)
5123 return 0;
5124 return -1;
5127 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
5128 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
5129 * write the result to a newly allocated string that is pointed to by
5130 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
5131 * Return 0 if decryption was successful and -1 otherwise. */
5133 rend_decrypt_introduction_points(char **ipos_decrypted,
5134 size_t *ipos_decrypted_size,
5135 const char *descriptor_cookie,
5136 const char *ipos_encrypted,
5137 size_t ipos_encrypted_size)
5139 tor_assert(ipos_encrypted);
5140 tor_assert(descriptor_cookie);
5141 if (ipos_encrypted_size < 2) {
5142 log_warn(LD_REND, "Size of encrypted introduction points is too "
5143 "small.");
5144 return -1;
5146 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
5147 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
5148 session_key[CIPHER_KEY_LEN], *dec;
5149 int declen, client_blocks;
5150 size_t pos = 0, len, client_entries_len;
5151 crypto_digest_t *digest;
5152 crypto_cipher_t *cipher;
5153 client_blocks = (int) ipos_encrypted[1];
5154 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
5155 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
5156 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
5157 log_warn(LD_REND, "Size of encrypted introduction points is too "
5158 "small.");
5159 return -1;
5161 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
5162 digest = crypto_digest_new();
5163 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
5164 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
5165 crypto_digest_get_digest(digest, client_id,
5166 REND_BASIC_AUTH_CLIENT_ID_LEN);
5167 crypto_digest_free(digest);
5168 for (pos = 2; pos < 2 + client_entries_len;
5169 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
5170 if (tor_memeq(ipos_encrypted + pos, client_id,
5171 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
5172 /* Attempt to decrypt introduction points. */
5173 cipher = crypto_cipher_new(descriptor_cookie);
5174 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
5175 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
5176 CIPHER_KEY_LEN) < 0) {
5177 log_warn(LD_REND, "Could not decrypt session key for client.");
5178 crypto_cipher_free(cipher);
5179 return -1;
5181 crypto_cipher_free(cipher);
5183 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
5184 dec = tor_malloc(len);
5185 declen = crypto_cipher_decrypt_with_iv(session_key, dec, len,
5186 ipos_encrypted + 2 + client_entries_len,
5187 ipos_encrypted_size - 2 - client_entries_len);
5189 if (declen < 0) {
5190 log_warn(LD_REND, "Could not decrypt introduction point string.");
5191 tor_free(dec);
5192 return -1;
5194 if (fast_memcmpstart(dec, declen, "introduction-point ")) {
5195 log_warn(LD_REND, "Decrypted introduction points don't "
5196 "look like we could parse them.");
5197 tor_free(dec);
5198 continue;
5200 *ipos_decrypted = dec;
5201 *ipos_decrypted_size = declen;
5202 return 0;
5205 log_warn(LD_REND, "Could not decrypt introduction points. Please "
5206 "check your authorization for this service!");
5207 return -1;
5208 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
5209 char *dec;
5210 int declen;
5211 if (ipos_encrypted_size < CIPHER_IV_LEN + 2) {
5212 log_warn(LD_REND, "Size of encrypted introduction points is too "
5213 "small.");
5214 return -1;
5216 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
5218 declen = crypto_cipher_decrypt_with_iv(descriptor_cookie, dec,
5219 ipos_encrypted_size -
5220 CIPHER_IV_LEN - 1,
5221 ipos_encrypted + 1,
5222 ipos_encrypted_size - 1);
5224 if (declen < 0) {
5225 log_warn(LD_REND, "Decrypting introduction points failed!");
5226 tor_free(dec);
5227 return -1;
5229 *ipos_decrypted = dec;
5230 *ipos_decrypted_size = declen;
5231 return 0;
5232 } else {
5233 log_warn(LD_REND, "Unknown authorization type number: %d",
5234 ipos_encrypted[0]);
5235 return -1;
5239 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
5240 * length <b>intro_points_encoded_size</b> and write the result to the
5241 * descriptor in <b>parsed</b>; return the number of successfully parsed
5242 * introduction points or -1 in case of a failure. */
5244 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
5245 const char *intro_points_encoded,
5246 size_t intro_points_encoded_size)
5248 const char *current_ipo, *end_of_intro_points;
5249 smartlist_t *tokens = NULL;
5250 directory_token_t *tok;
5251 rend_intro_point_t *intro;
5252 extend_info_t *info;
5253 int result, num_ok=1;
5254 memarea_t *area = NULL;
5255 tor_assert(parsed);
5256 /** Function may only be invoked once. */
5257 tor_assert(!parsed->intro_nodes);
5258 if (!intro_points_encoded || intro_points_encoded_size == 0) {
5259 log_warn(LD_REND, "Empty or zero size introduction point list");
5260 goto err;
5262 /* Consider one intro point after the other. */
5263 current_ipo = intro_points_encoded;
5264 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
5265 tokens = smartlist_new();
5266 parsed->intro_nodes = smartlist_new();
5267 area = memarea_new();
5269 while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
5270 "introduction-point ")) {
5271 /* Determine end of string. */
5272 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
5273 "\nintroduction-point ");
5274 if (!eos)
5275 eos = end_of_intro_points;
5276 else
5277 eos = eos+1;
5278 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
5279 /* Free tokens and clear token list. */
5280 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5281 smartlist_clear(tokens);
5282 memarea_clear(area);
5283 /* Tokenize string. */
5284 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
5285 log_warn(LD_REND, "Error tokenizing introduction point");
5286 goto err;
5288 /* Advance to next introduction point, if available. */
5289 current_ipo = eos;
5290 /* Check minimum allowed length of introduction point. */
5291 if (smartlist_len(tokens) < 5) {
5292 log_warn(LD_REND, "Impossibly short introduction point.");
5293 goto err;
5295 /* Allocate new intro point and extend info. */
5296 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
5297 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
5298 /* Parse identifier. */
5299 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
5300 if (base32_decode(info->identity_digest, DIGEST_LEN,
5301 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
5302 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
5303 tok->args[0]);
5304 rend_intro_point_free(intro);
5305 goto err;
5307 /* Write identifier to nickname. */
5308 info->nickname[0] = '$';
5309 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
5310 info->identity_digest, DIGEST_LEN);
5311 /* Parse IP address. */
5312 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
5313 if (tor_addr_parse(&info->addr, tok->args[0])<0) {
5314 log_warn(LD_REND, "Could not parse introduction point address.");
5315 rend_intro_point_free(intro);
5316 goto err;
5318 if (tor_addr_family(&info->addr) != AF_INET) {
5319 log_warn(LD_REND, "Introduction point address was not ipv4.");
5320 rend_intro_point_free(intro);
5321 goto err;
5324 /* Parse onion port. */
5325 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
5326 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
5327 &num_ok,NULL);
5328 if (!info->port || !num_ok) {
5329 log_warn(LD_REND, "Introduction point onion port %s is invalid",
5330 escaped(tok->args[0]));
5331 rend_intro_point_free(intro);
5332 goto err;
5334 /* Parse onion key. */
5335 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
5336 if (!crypto_pk_public_exponent_ok(tok->key)) {
5337 log_warn(LD_REND,
5338 "Introduction point's onion key had invalid exponent.");
5339 rend_intro_point_free(intro);
5340 goto err;
5342 info->onion_key = tok->key;
5343 tok->key = NULL; /* Prevent free */
5344 /* Parse service key. */
5345 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
5346 if (!crypto_pk_public_exponent_ok(tok->key)) {
5347 log_warn(LD_REND,
5348 "Introduction point key had invalid exponent.");
5349 rend_intro_point_free(intro);
5350 goto err;
5352 intro->intro_key = tok->key;
5353 tok->key = NULL; /* Prevent free */
5354 /* Add extend info to list of introduction points. */
5355 smartlist_add(parsed->intro_nodes, intro);
5357 result = smartlist_len(parsed->intro_nodes);
5358 goto done;
5360 err:
5361 result = -1;
5363 done:
5364 /* Free tokens and clear token list. */
5365 if (tokens) {
5366 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5367 smartlist_free(tokens);
5369 if (area)
5370 memarea_drop_all(area);
5372 return result;
5375 /** Parse the content of a client_key file in <b>ckstr</b> and add
5376 * rend_authorized_client_t's for each parsed client to
5377 * <b>parsed_clients</b>. Return the number of parsed clients as result
5378 * or -1 for failure. */
5380 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
5382 int result = -1;
5383 smartlist_t *tokens;
5384 directory_token_t *tok;
5385 const char *current_entry = NULL;
5386 memarea_t *area = NULL;
5387 char *err_msg = NULL;
5388 if (!ckstr || strlen(ckstr) == 0)
5389 return -1;
5390 tokens = smartlist_new();
5391 /* Begin parsing with first entry, skipping comments or whitespace at the
5392 * beginning. */
5393 area = memarea_new();
5394 current_entry = eat_whitespace(ckstr);
5395 while (!strcmpstart(current_entry, "client-name ")) {
5396 rend_authorized_client_t *parsed_entry;
5397 /* Determine end of string. */
5398 const char *eos = strstr(current_entry, "\nclient-name ");
5399 if (!eos)
5400 eos = current_entry + strlen(current_entry);
5401 else
5402 eos = eos + 1;
5403 /* Free tokens and clear token list. */
5404 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5405 smartlist_clear(tokens);
5406 memarea_clear(area);
5407 /* Tokenize string. */
5408 if (tokenize_string(area, current_entry, eos, tokens,
5409 client_keys_token_table, 0)) {
5410 log_warn(LD_REND, "Error tokenizing client keys file.");
5411 goto err;
5413 /* Advance to next entry, if available. */
5414 current_entry = eos;
5415 /* Check minimum allowed length of token list. */
5416 if (smartlist_len(tokens) < 2) {
5417 log_warn(LD_REND, "Impossibly short client key entry.");
5418 goto err;
5420 /* Parse client name. */
5421 tok = find_by_keyword(tokens, C_CLIENT_NAME);
5422 tor_assert(tok == smartlist_get(tokens, 0));
5423 tor_assert(tok->n_args == 1);
5425 if (!rend_valid_client_name(tok->args[0])) {
5426 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
5427 "between 1 and %d, and valid characters are "
5428 "[A-Za-z0-9+-_].)", tok->args[0], REND_CLIENTNAME_MAX_LEN);
5429 goto err;
5431 /* Check if client name is duplicate. */
5432 if (strmap_get(parsed_clients, tok->args[0])) {
5433 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
5434 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
5435 goto err;
5437 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
5438 parsed_entry->client_name = tor_strdup(tok->args[0]);
5439 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
5440 /* Parse client key. */
5441 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
5442 if (tok) {
5443 parsed_entry->client_key = tok->key;
5444 tok->key = NULL; /* Prevent free */
5447 /* Parse descriptor cookie. */
5448 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
5449 tor_assert(tok->n_args == 1);
5450 if (rend_auth_decode_cookie(tok->args[0], parsed_entry->descriptor_cookie,
5451 NULL, &err_msg) < 0) {
5452 tor_assert(err_msg);
5453 log_warn(LD_REND, "%s", err_msg);
5454 tor_free(err_msg);
5455 goto err;
5458 result = strmap_size(parsed_clients);
5459 goto done;
5460 err:
5461 result = -1;
5462 done:
5463 /* Free tokens and clear token list. */
5464 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5465 smartlist_free(tokens);
5466 if (area)
5467 memarea_drop_all(area);
5468 return result;