In routerlist_assert_ok(), check r2 before taking &(r2->cache_info)
[tor.git] / src / or / routerparse.c
blobf990cebd827175d287f0d6378cb08cffdd6cdcae
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2013, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file routerparse.c
9 * \brief Code to parse and validate router descriptors and directories.
10 **/
12 #include "or.h"
13 #include "config.h"
14 #include "circuitstats.h"
15 #include "dirserv.h"
16 #include "dirvote.h"
17 #include "policies.h"
18 #include "rendcommon.h"
19 #include "router.h"
20 #include "routerlist.h"
21 #include "memarea.h"
22 #include "microdesc.h"
23 #include "networkstatus.h"
24 #include "rephist.h"
25 #include "routerparse.h"
26 #undef log
27 #include <math.h>
29 /****************************************************************************/
31 /** Enumeration of possible token types. The ones starting with K_ correspond
32 * to directory 'keywords'. ERR_ is an error in the tokenizing process, EOF_
33 * is an end-of-file marker, and NIL_ is used to encode not-a-token.
35 typedef enum {
36 K_ACCEPT = 0,
37 K_ACCEPT6,
38 K_DIRECTORY_SIGNATURE,
39 K_RECOMMENDED_SOFTWARE,
40 K_REJECT,
41 K_REJECT6,
42 K_ROUTER,
43 K_SIGNED_DIRECTORY,
44 K_SIGNING_KEY,
45 K_ONION_KEY,
46 K_ONION_KEY_NTOR,
47 K_ROUTER_SIGNATURE,
48 K_PUBLISHED,
49 K_RUNNING_ROUTERS,
50 K_ROUTER_STATUS,
51 K_PLATFORM,
52 K_OPT,
53 K_BANDWIDTH,
54 K_CONTACT,
55 K_NETWORK_STATUS,
56 K_UPTIME,
57 K_DIR_SIGNING_KEY,
58 K_FAMILY,
59 K_FINGERPRINT,
60 K_HIBERNATING,
61 K_READ_HISTORY,
62 K_WRITE_HISTORY,
63 K_NETWORK_STATUS_VERSION,
64 K_DIR_SOURCE,
65 K_DIR_OPTIONS,
66 K_CLIENT_VERSIONS,
67 K_SERVER_VERSIONS,
68 K_OR_ADDRESS,
69 K_P,
70 K_P6,
71 K_R,
72 K_A,
73 K_S,
74 K_V,
75 K_W,
76 K_M,
77 K_EXTRA_INFO,
78 K_EXTRA_INFO_DIGEST,
79 K_CACHES_EXTRA_INFO,
80 K_HIDDEN_SERVICE_DIR,
81 K_ALLOW_SINGLE_HOP_EXITS,
82 K_IPV6_POLICY,
84 K_DIRREQ_END,
85 K_DIRREQ_V2_IPS,
86 K_DIRREQ_V3_IPS,
87 K_DIRREQ_V2_REQS,
88 K_DIRREQ_V3_REQS,
89 K_DIRREQ_V2_SHARE,
90 K_DIRREQ_V3_SHARE,
91 K_DIRREQ_V2_RESP,
92 K_DIRREQ_V3_RESP,
93 K_DIRREQ_V2_DIR,
94 K_DIRREQ_V3_DIR,
95 K_DIRREQ_V2_TUN,
96 K_DIRREQ_V3_TUN,
97 K_ENTRY_END,
98 K_ENTRY_IPS,
99 K_CELL_END,
100 K_CELL_PROCESSED,
101 K_CELL_QUEUED,
102 K_CELL_TIME,
103 K_CELL_CIRCS,
104 K_EXIT_END,
105 K_EXIT_WRITTEN,
106 K_EXIT_READ,
107 K_EXIT_OPENED,
109 K_DIR_KEY_CERTIFICATE_VERSION,
110 K_DIR_IDENTITY_KEY,
111 K_DIR_KEY_PUBLISHED,
112 K_DIR_KEY_EXPIRES,
113 K_DIR_KEY_CERTIFICATION,
114 K_DIR_KEY_CROSSCERT,
115 K_DIR_ADDRESS,
117 K_VOTE_STATUS,
118 K_VALID_AFTER,
119 K_FRESH_UNTIL,
120 K_VALID_UNTIL,
121 K_VOTING_DELAY,
123 K_KNOWN_FLAGS,
124 K_PARAMS,
125 K_BW_WEIGHTS,
126 K_VOTE_DIGEST,
127 K_CONSENSUS_DIGEST,
128 K_ADDITIONAL_DIGEST,
129 K_ADDITIONAL_SIGNATURE,
130 K_CONSENSUS_METHODS,
131 K_CONSENSUS_METHOD,
132 K_LEGACY_DIR_KEY,
133 K_DIRECTORY_FOOTER,
135 A_PURPOSE,
136 A_LAST_LISTED,
137 A_UNKNOWN_,
139 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
140 R_VERSION,
141 R_PERMANENT_KEY,
142 R_SECRET_ID_PART,
143 R_PUBLICATION_TIME,
144 R_PROTOCOL_VERSIONS,
145 R_INTRODUCTION_POINTS,
146 R_SIGNATURE,
148 R_IPO_IDENTIFIER,
149 R_IPO_IP_ADDRESS,
150 R_IPO_ONION_PORT,
151 R_IPO_ONION_KEY,
152 R_IPO_SERVICE_KEY,
154 C_CLIENT_NAME,
155 C_DESCRIPTOR_COOKIE,
156 C_CLIENT_KEY,
158 ERR_,
159 EOF_,
160 NIL_
161 } directory_keyword;
163 #define MIN_ANNOTATION A_PURPOSE
164 #define MAX_ANNOTATION A_UNKNOWN_
166 /** Structure to hold a single directory token.
168 * We parse a directory by breaking it into "tokens", each consisting
169 * of a keyword, a line full of arguments, and a binary object. The
170 * arguments and object are both optional, depending on the keyword
171 * type.
173 * This structure is only allocated in memareas; do not allocate it on
174 * the heap, or token_clear() won't work.
176 typedef struct directory_token_t {
177 directory_keyword tp; /**< Type of the token. */
178 int n_args:30; /**< Number of elements in args */
179 char **args; /**< Array of arguments from keyword line. */
181 char *object_type; /**< -----BEGIN [object_type]-----*/
182 size_t object_size; /**< Bytes in object_body */
183 char *object_body; /**< Contents of object, base64-decoded. */
185 crypto_pk_t *key; /**< For public keys only. Heap-allocated. */
187 char *error; /**< For ERR_ tokens only. */
188 } directory_token_t;
190 /* ********************************************************************** */
192 /** We use a table of rules to decide how to parse each token type. */
194 /** Rules for whether the keyword needs an object. */
195 typedef enum {
196 NO_OBJ, /**< No object, ever. */
197 NEED_OBJ, /**< Object is required. */
198 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
199 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
200 NEED_KEY, /**< Object is required, and must be a public key. */
201 OBJ_OK, /**< Object is optional. */
202 } obj_syntax;
204 #define AT_START 1
205 #define AT_END 2
207 /** Determines the parsing rules for a single token type. */
208 typedef struct token_rule_t {
209 /** The string value of the keyword identifying the type of item. */
210 const char *t;
211 /** The corresponding directory_keyword enum. */
212 directory_keyword v;
213 /** Minimum number of arguments for this item */
214 int min_args;
215 /** Maximum number of arguments for this item */
216 int max_args;
217 /** If true, we concatenate all arguments for this item into a single
218 * string. */
219 int concat_args;
220 /** Requirements on object syntax for this item. */
221 obj_syntax os;
222 /** Lowest number of times this item may appear in a document. */
223 int min_cnt;
224 /** Highest number of times this item may appear in a document. */
225 int max_cnt;
226 /** One or more of AT_START/AT_END to limit where the item may appear in a
227 * document. */
228 int pos;
229 /** True iff this token is an annotation. */
230 int is_annotation;
231 } token_rule_t;
234 * Helper macros to define token tables. 's' is a string, 't' is a
235 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
236 * object syntax.
240 /** Appears to indicate the end of a table. */
241 #define END_OF_TABLE { NULL, NIL_, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
242 /** An item with no restrictions: used for obsolete document types */
243 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
244 /** An item with no restrictions on multiplicity or location. */
245 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
246 /** An item that must appear exactly once */
247 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
248 /** An item that must appear exactly once, at the start of the document */
249 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
250 /** An item that must appear exactly once, at the end of the document */
251 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
252 /** An item that must appear one or more times */
253 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
254 /** An item that must appear no more than once */
255 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
256 /** An annotation that must appear no more than once */
257 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
259 /* Argument multiplicity: any number of arguments. */
260 #define ARGS 0,INT_MAX,0
261 /* Argument multiplicity: no arguments. */
262 #define NO_ARGS 0,0,0
263 /* Argument multiplicity: concatenate all arguments. */
264 #define CONCAT_ARGS 1,1,1
265 /* Argument multiplicity: at least <b>n</b> arguments. */
266 #define GE(n) n,INT_MAX,0
267 /* Argument multiplicity: exactly <b>n</b> arguments. */
268 #define EQ(n) n,n,0
270 /** List of tokens recognized in router descriptors */
271 static token_rule_t routerdesc_token_table[] = {
272 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
273 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
274 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
275 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
276 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
277 T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ),
278 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
279 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
280 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
281 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
282 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
283 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
284 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
285 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
286 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
287 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
288 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
289 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
290 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
291 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
292 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
294 T01("family", K_FAMILY, ARGS, NO_OBJ ),
295 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
296 T0N("or-address", K_OR_ADDRESS, GE(1), NO_OBJ ),
298 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
299 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
300 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
302 END_OF_TABLE
305 /** List of tokens recognized in extra-info documents. */
306 static token_rule_t extrainfo_token_table[] = {
307 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
308 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
309 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
310 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
311 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
312 T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ),
313 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ),
314 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ),
315 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ),
316 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ),
317 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ),
318 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ),
319 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ),
320 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ),
321 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ),
322 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ),
323 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ),
324 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ),
325 T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ),
326 T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ),
327 T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ),
328 T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ),
329 T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ),
330 T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ),
331 T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ),
332 T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ),
333 T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ),
334 T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ),
335 T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ),
337 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
339 END_OF_TABLE
342 /** List of tokens recognized in the body part of v3 networkstatus
343 * documents. */
344 static token_rule_t rtrstatus_token_table[] = {
345 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
346 T1( "r", K_R, GE(7), NO_OBJ ),
347 T0N("a", K_A, GE(1), NO_OBJ ),
348 T1( "s", K_S, ARGS, NO_OBJ ),
349 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
350 T01("w", K_W, ARGS, NO_OBJ ),
351 T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
352 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
353 END_OF_TABLE
356 /** List of tokens common to V3 authority certificates and V3 consensuses. */
357 #define CERTIFICATE_MEMBERS \
358 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
359 GE(1), NO_OBJ ), \
360 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
361 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
362 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
363 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
364 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
365 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
366 NO_ARGS, NEED_OBJ), \
367 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
369 /** List of tokens recognized in V3 authority certificates. */
370 static token_rule_t dir_key_certificate_table[] = {
371 CERTIFICATE_MEMBERS
372 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
373 END_OF_TABLE
376 /** List of tokens recognized in rendezvous service descriptors */
377 static token_rule_t desc_token_table[] = {
378 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
379 EQ(1), NO_OBJ),
380 T1("version", R_VERSION, EQ(1), NO_OBJ),
381 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
382 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
383 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
384 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
385 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
386 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
387 END_OF_TABLE
390 /** List of tokens recognized in the (encrypted) list of introduction points of
391 * rendezvous service descriptors */
392 static token_rule_t ipo_token_table[] = {
393 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
394 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
395 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
396 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
397 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
398 END_OF_TABLE
401 /** List of tokens recognized in the (possibly encrypted) list of introduction
402 * points of rendezvous service descriptors */
403 static token_rule_t client_keys_token_table[] = {
404 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
405 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
406 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
407 END_OF_TABLE
410 /** List of tokens recognized in V3 networkstatus votes. */
411 static token_rule_t networkstatus_token_table[] = {
412 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
413 GE(1), NO_OBJ ),
414 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
415 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
416 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
417 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
418 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
419 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
420 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
421 T01("params", K_PARAMS, ARGS, NO_OBJ ),
422 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
424 CERTIFICATE_MEMBERS
426 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
427 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
428 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
429 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
430 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
431 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
432 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
433 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
435 END_OF_TABLE
438 /** List of tokens recognized in V3 networkstatus consensuses. */
439 static token_rule_t networkstatus_consensus_token_table[] = {
440 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
441 GE(1), NO_OBJ ),
442 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
443 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
444 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
445 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
446 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
448 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
450 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
451 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
452 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
454 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
456 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
457 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
458 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
459 T01("params", K_PARAMS, ARGS, NO_OBJ ),
461 END_OF_TABLE
464 /** List of tokens recognized in the footer of v1 directory footers. */
465 static token_rule_t networkstatus_vote_footer_token_table[] = {
466 T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
467 T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
468 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
469 END_OF_TABLE
472 /** List of tokens recognized in detached networkstatus signature documents. */
473 static token_rule_t networkstatus_detached_signature_token_table[] = {
474 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
475 T("additional-digest", K_ADDITIONAL_DIGEST,GE(3), NO_OBJ ),
476 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
477 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
478 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
479 T("additional-signature", K_ADDITIONAL_SIGNATURE, GE(4), NEED_OBJ ),
480 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
481 END_OF_TABLE
484 /** List of tokens recognized in microdescriptors */
485 static token_rule_t microdesc_token_table[] = {
486 T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
487 T01("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ),
488 T0N("a", K_A, GE(1), NO_OBJ ),
489 T01("family", K_FAMILY, ARGS, NO_OBJ ),
490 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
491 T01("p6", K_P6, CONCAT_ARGS, NO_OBJ ),
492 A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
493 END_OF_TABLE
496 #undef T
498 /* static function prototypes */
499 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
500 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok,
501 unsigned fmt_flags);
502 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
504 static int router_get_hash_impl(const char *s, size_t s_len, char *digest,
505 const char *start_str, const char *end_str,
506 char end_char,
507 digest_algorithm_t alg);
508 static int router_get_hashes_impl(const char *s, size_t s_len,
509 digests_t *digests,
510 const char *start_str, const char *end_str,
511 char end_char);
512 static void token_clear(directory_token_t *tok);
513 static smartlist_t *find_all_by_keyword(smartlist_t *s, directory_keyword k);
514 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
515 static directory_token_t *find_by_keyword_(smartlist_t *s,
516 directory_keyword keyword,
517 const char *keyword_str);
518 #define find_by_keyword(s, keyword) find_by_keyword_((s), (keyword), #keyword)
519 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
520 directory_keyword keyword);
522 #define TS_ANNOTATIONS_OK 1
523 #define TS_NOCHECK 2
524 #define TS_NO_NEW_ANNOTATIONS 4
525 static int tokenize_string(memarea_t *area,
526 const char *start, const char *end,
527 smartlist_t *out,
528 token_rule_t *table,
529 int flags);
530 static directory_token_t *get_next_token(memarea_t *area,
531 const char **s,
532 const char *eos,
533 token_rule_t *table);
534 #define CST_CHECK_AUTHORITY (1<<0)
535 #define CST_NO_CHECK_OBJTYPE (1<<1)
536 static int check_signature_token(const char *digest,
537 ssize_t digest_len,
538 directory_token_t *tok,
539 crypto_pk_t *pkey,
540 int flags,
541 const char *doctype);
543 #undef DEBUG_AREA_ALLOC
545 #ifdef DEBUG_AREA_ALLOC
546 #define DUMP_AREA(a,name) STMT_BEGIN \
547 size_t alloc=0, used=0; \
548 memarea_get_stats((a),&alloc,&used); \
549 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
550 name, (unsigned long)alloc, (unsigned long)used); \
551 STMT_END
552 #else
553 #define DUMP_AREA(a,name) STMT_NIL
554 #endif
556 /** Last time we dumped a descriptor to disk. */
557 static time_t last_desc_dumped = 0;
559 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
560 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
561 * than one descriptor to disk per minute. If there is already such a
562 * file in the data directory, overwrite it. */
563 static void
564 dump_desc(const char *desc, const char *type)
566 time_t now = time(NULL);
567 tor_assert(desc);
568 tor_assert(type);
569 if (!last_desc_dumped || last_desc_dumped + 60 < now) {
570 char *debugfile = get_datadir_fname("unparseable-desc");
571 size_t filelen = 50 + strlen(type) + strlen(desc);
572 char *content = tor_malloc_zero(filelen);
573 tor_snprintf(content, filelen, "Unable to parse descriptor of type "
574 "%s:\n%s", type, desc);
575 write_str_to_file(debugfile, content, 1);
576 log_info(LD_DIR, "Unable to parse descriptor of type %s. See file "
577 "unparseable-desc in data directory for details.", type);
578 tor_free(content);
579 tor_free(debugfile);
580 last_desc_dumped = now;
584 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
585 * <b>s</b>. Return 0 on success, -1 on failure.
588 router_get_dir_hash(const char *s, char *digest)
590 return router_get_hash_impl(s, strlen(s), digest,
591 "signed-directory","\ndirectory-signature",'\n',
592 DIGEST_SHA1);
595 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
596 * <b>s</b>. Return 0 on success, -1 on failure.
599 router_get_router_hash(const char *s, size_t s_len, char *digest)
601 return router_get_hash_impl(s, s_len, digest,
602 "router ","\nrouter-signature", '\n',
603 DIGEST_SHA1);
606 /** Set <b>digests</b> to all the digests of the consensus document in
607 * <b>s</b> */
609 router_get_networkstatus_v3_hashes(const char *s, digests_t *digests)
611 return router_get_hashes_impl(s,strlen(s),digests,
612 "network-status-version",
613 "\ndirectory-signature",
614 ' ');
617 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
618 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
620 router_get_extrainfo_hash(const char *s, size_t s_len, char *digest)
622 return router_get_hash_impl(s, s_len, digest, "extra-info",
623 "\nrouter-signature",'\n', DIGEST_SHA1);
626 /** Helper: used to generate signatures for routers, directories and
627 * network-status objects. Given a <b>digest_len</b>-byte digest in
628 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
629 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
630 * and return the new signature on success or NULL on failure.
632 char *
633 router_get_dirobj_signature(const char *digest,
634 size_t digest_len,
635 crypto_pk_t *private_key)
637 char *signature;
638 size_t i, keysize;
639 int siglen;
640 char *buf = NULL;
641 size_t buf_len;
642 /* overestimate of BEGIN/END lines total len. */
643 #define BEGIN_END_OVERHEAD_LEN 64
645 keysize = crypto_pk_keysize(private_key);
646 signature = tor_malloc(keysize);
647 siglen = crypto_pk_private_sign(private_key, signature, keysize,
648 digest, digest_len);
649 if (siglen < 0) {
650 log_warn(LD_BUG,"Couldn't sign digest.");
651 goto err;
654 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
655 buf_len = (siglen * 2) + BEGIN_END_OVERHEAD_LEN;
656 buf = tor_malloc(buf_len);
658 if (strlcpy(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
659 goto truncated;
661 i = strlen(buf);
662 if (base64_encode(buf+i, buf_len-i, signature, siglen) < 0) {
663 log_warn(LD_BUG,"couldn't base64-encode signature");
664 goto err;
667 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
668 goto truncated;
670 tor_free(signature);
671 return buf;
673 truncated:
674 log_warn(LD_BUG,"tried to exceed string length.");
675 err:
676 tor_free(signature);
677 tor_free(buf);
678 return NULL;
681 /** Helper: used to generate signatures for routers, directories and
682 * network-status objects. Given a digest in <b>digest</b> and a secret
683 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
684 * surround it with -----BEGIN/END----- pairs, and write it to the
685 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
686 * failure.
689 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
690 size_t digest_len, crypto_pk_t *private_key)
692 size_t sig_len, s_len;
693 char *sig = router_get_dirobj_signature(digest, digest_len, private_key);
694 if (!sig) {
695 log_warn(LD_BUG, "No signature generated");
696 return -1;
698 sig_len = strlen(sig);
699 s_len = strlen(buf);
700 if (sig_len + s_len + 1 > buf_len) {
701 log_warn(LD_BUG, "Not enough room for signature");
702 tor_free(sig);
703 return -1;
705 memcpy(buf+s_len, sig, sig_len+1);
706 tor_free(sig);
707 return 0;
710 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
711 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
712 * entries. Else, return VS_OLD if every member of
713 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
714 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
715 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
716 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
717 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
718 * VS_UNRECOMMENDED.
720 * (versionlist is a comma-separated list of version strings,
721 * optionally prefixed with "Tor". Versions that can't be parsed are
722 * ignored.)
724 version_status_t
725 tor_version_is_obsolete(const char *myversion, const char *versionlist)
727 tor_version_t mine, other;
728 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
729 found_any_in_series = 0, r, same;
730 version_status_t ret = VS_UNRECOMMENDED;
731 smartlist_t *version_sl;
733 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
734 myversion, versionlist);
736 if (tor_version_parse(myversion, &mine)) {
737 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
738 tor_assert(0);
740 version_sl = smartlist_new();
741 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
743 if (!strlen(versionlist)) { /* no authorities cared or agreed */
744 ret = VS_EMPTY;
745 goto done;
748 SMARTLIST_FOREACH_BEGIN(version_sl, const char *, cp) {
749 if (!strcmpstart(cp, "Tor "))
750 cp += 4;
752 if (tor_version_parse(cp, &other)) {
753 /* Couldn't parse other; it can't be a match. */
754 } else {
755 same = tor_version_same_series(&mine, &other);
756 if (same)
757 found_any_in_series = 1;
758 r = tor_version_compare(&mine, &other);
759 if (r==0) {
760 ret = VS_RECOMMENDED;
761 goto done;
762 } else if (r<0) {
763 found_newer = 1;
764 if (same)
765 found_newer_in_series = 1;
766 } else if (r>0) {
767 found_older = 1;
770 } SMARTLIST_FOREACH_END(cp);
772 /* We didn't find the listed version. Is it new or old? */
773 if (found_any_in_series && !found_newer_in_series && found_newer) {
774 ret = VS_NEW_IN_SERIES;
775 } else if (found_newer && !found_older) {
776 ret = VS_OLD;
777 } else if (found_older && !found_newer) {
778 ret = VS_NEW;
779 } else {
780 ret = VS_UNRECOMMENDED;
783 done:
784 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
785 smartlist_free(version_sl);
786 return ret;
789 /** Return true iff <b>key</b> is allowed to sign directories.
791 static int
792 dir_signing_key_is_trusted(crypto_pk_t *key)
794 char digest[DIGEST_LEN];
795 if (!key) return 0;
796 if (crypto_pk_get_digest(key, digest) < 0) {
797 log_warn(LD_DIR, "Error computing dir-signing-key digest");
798 return 0;
800 if (!router_digest_is_trusted_dir(digest)) {
801 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
802 return 0;
804 return 1;
807 /** Check whether the object body of the token in <b>tok</b> has a good
808 * signature for <b>digest</b> using key <b>pkey</b>. If
809 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
810 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
811 * the object type of the signature object. Use <b>doctype</b> as the type of
812 * the document when generating log messages. Return 0 on success, negative
813 * on failure.
815 static int
816 check_signature_token(const char *digest,
817 ssize_t digest_len,
818 directory_token_t *tok,
819 crypto_pk_t *pkey,
820 int flags,
821 const char *doctype)
823 char *signed_digest;
824 size_t keysize;
825 const int check_authority = (flags & CST_CHECK_AUTHORITY);
826 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
828 tor_assert(pkey);
829 tor_assert(tok);
830 tor_assert(digest);
831 tor_assert(doctype);
833 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
834 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
835 doctype);
836 return -1;
839 if (check_objtype) {
840 if (strcmp(tok->object_type, "SIGNATURE")) {
841 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
842 return -1;
846 keysize = crypto_pk_keysize(pkey);
847 signed_digest = tor_malloc(keysize);
848 if (crypto_pk_public_checksig(pkey, signed_digest, keysize,
849 tok->object_body, tok->object_size)
850 < digest_len) {
851 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
852 tor_free(signed_digest);
853 return -1;
855 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
856 // hex_str(signed_digest,4));
857 if (tor_memneq(digest, signed_digest, digest_len)) {
858 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
859 tor_free(signed_digest);
860 return -1;
862 tor_free(signed_digest);
863 return 0;
866 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
867 * or to the first of the annotations proceeding the next router or
868 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
869 * we found an extrainfo, or false if found a router. Do not scan beyond
870 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
871 static int
872 find_start_of_next_router_or_extrainfo(const char **s_ptr,
873 const char *eos,
874 int *is_extrainfo_out)
876 const char *annotations = NULL;
877 const char *s = *s_ptr;
879 s = eat_whitespace_eos(s, eos);
881 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
882 /* We're at the start of a line. */
883 tor_assert(*s != '\n');
885 if (*s == '@' && !annotations) {
886 annotations = s;
887 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
888 *s_ptr = annotations ? annotations : s;
889 *is_extrainfo_out = 0;
890 return 0;
891 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
892 *s_ptr = annotations ? annotations : s;
893 *is_extrainfo_out = 1;
894 return 0;
897 if (!(s = memchr(s+1, '\n', eos-(s+1))))
898 break;
899 s = eat_whitespace_eos(s, eos);
901 return -1;
904 /** Given a string *<b>s</b> containing a concatenated sequence of router
905 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
906 * them and stores the result in <b>dest</b>. All routers are marked running
907 * and valid. Advances *s to a point immediately following the last router
908 * entry. Ignore any trailing router entries that are not complete.
910 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
911 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
912 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
914 * Returns 0 on success and -1 on failure.
917 router_parse_list_from_string(const char **s, const char *eos,
918 smartlist_t *dest,
919 saved_location_t saved_location,
920 int want_extrainfo,
921 int allow_annotations,
922 const char *prepend_annotations)
924 routerinfo_t *router;
925 extrainfo_t *extrainfo;
926 signed_descriptor_t *signed_desc = NULL;
927 void *elt;
928 const char *end, *start;
929 int have_extrainfo;
931 tor_assert(s);
932 tor_assert(*s);
933 tor_assert(dest);
935 start = *s;
936 if (!eos)
937 eos = *s + strlen(*s);
939 tor_assert(eos >= *s);
941 while (1) {
942 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
943 break;
945 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
946 if (end)
947 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
948 if (end)
949 end += strlen("\n-----END SIGNATURE-----\n");
951 if (!end)
952 break;
954 elt = NULL;
956 if (have_extrainfo && want_extrainfo) {
957 routerlist_t *rl = router_get_routerlist();
958 extrainfo = extrainfo_parse_entry_from_string(*s, end,
959 saved_location != SAVED_IN_CACHE,
960 rl->identity_map);
961 if (extrainfo) {
962 signed_desc = &extrainfo->cache_info;
963 elt = extrainfo;
965 } else if (!have_extrainfo && !want_extrainfo) {
966 router = router_parse_entry_from_string(*s, end,
967 saved_location != SAVED_IN_CACHE,
968 allow_annotations,
969 prepend_annotations);
970 if (router) {
971 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
972 router_describe(router),
973 router_purpose_to_string(router->purpose));
974 signed_desc = &router->cache_info;
975 elt = router;
978 if (!elt) {
979 *s = end;
980 continue;
982 if (saved_location != SAVED_NOWHERE) {
983 tor_assert(signed_desc);
984 signed_desc->saved_location = saved_location;
985 signed_desc->saved_offset = *s - start;
987 *s = end;
988 smartlist_add(dest, elt);
991 return 0;
994 /* For debugging: define to count every descriptor digest we've seen so we
995 * know if we need to try harder to avoid duplicate verifies. */
996 #undef COUNT_DISTINCT_DIGESTS
998 #ifdef COUNT_DISTINCT_DIGESTS
999 static digestmap_t *verified_digests = NULL;
1000 #endif
1002 /** Log the total count of the number of distinct router digests we've ever
1003 * verified. When compared to the number of times we've verified routerdesc
1004 * signatures <i>in toto</i>, this will tell us if we're doing too much
1005 * multiple-verification. */
1006 void
1007 dump_distinct_digest_count(int severity)
1009 #ifdef COUNT_DISTINCT_DIGESTS
1010 if (!verified_digests)
1011 verified_digests = digestmap_new();
1012 tor_log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1013 digestmap_size(verified_digests));
1014 #else
1015 (void)severity; /* suppress "unused parameter" warning */
1016 #endif
1019 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1020 * with at least one argument (use GE(1) in setup). If found, store
1021 * address and port number to <b>addr_out</b> and
1022 * <b>port_out</b>. Return number of OR ports found. */
1023 static int
1024 find_single_ipv6_orport(const smartlist_t *list,
1025 tor_addr_t *addr_out,
1026 uint16_t *port_out)
1028 int ret = 0;
1029 tor_assert(list != NULL);
1030 tor_assert(addr_out != NULL);
1031 tor_assert(port_out != NULL);
1033 SMARTLIST_FOREACH_BEGIN(list, directory_token_t *, t) {
1034 tor_addr_t a;
1035 maskbits_t bits;
1036 uint16_t port_min, port_max;
1037 tor_assert(t->n_args >= 1);
1038 /* XXXX Prop186 the full spec allows much more than this. */
1039 if (tor_addr_parse_mask_ports(t->args[0], 0,
1040 &a, &bits, &port_min,
1041 &port_max) == AF_INET6 &&
1042 bits == 128 &&
1043 port_min == port_max) {
1044 /* Okay, this is one we can understand. Use it and ignore
1045 any potential more addresses in list. */
1046 tor_addr_copy(addr_out, &a);
1047 *port_out = port_min;
1048 ret = 1;
1049 break;
1051 } SMARTLIST_FOREACH_END(t);
1053 return ret;
1056 /** Helper function: reads a single router entry from *<b>s</b> ...
1057 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1058 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1059 * s through end into the signed_descriptor_body of the resulting
1060 * routerinfo_t.
1062 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1064 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1065 * before the router; if it's false, reject the router if it's annotated. If
1066 * <b>prepend_annotations</b> is set, it should contain some annotations:
1067 * append them to the front of the router before parsing it, and keep them
1068 * around when caching the router.
1070 * Only one of allow_annotations and prepend_annotations may be set.
1072 routerinfo_t *
1073 router_parse_entry_from_string(const char *s, const char *end,
1074 int cache_copy, int allow_annotations,
1075 const char *prepend_annotations)
1077 routerinfo_t *router = NULL;
1078 char digest[128];
1079 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1080 directory_token_t *tok;
1081 struct in_addr in;
1082 const char *start_of_annotations, *cp, *s_dup = s;
1083 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1084 int ok = 1;
1085 memarea_t *area = NULL;
1087 tor_assert(!allow_annotations || !prepend_annotations);
1089 if (!end) {
1090 end = s + strlen(s);
1093 /* point 'end' to a point immediately after the final newline. */
1094 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1095 --end;
1097 area = memarea_new();
1098 tokens = smartlist_new();
1099 if (prepend_annotations) {
1100 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1101 routerdesc_token_table,TS_NOCHECK)) {
1102 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1103 goto err;
1107 start_of_annotations = s;
1108 cp = tor_memstr(s, end-s, "\nrouter ");
1109 if (!cp) {
1110 if (end-s < 7 || strcmpstart(s, "router ")) {
1111 log_warn(LD_DIR, "No router keyword found.");
1112 goto err;
1114 } else {
1115 s = cp+1;
1118 if (start_of_annotations != s) { /* We have annotations */
1119 if (allow_annotations) {
1120 if (tokenize_string(area,start_of_annotations,s,tokens,
1121 routerdesc_token_table,TS_NOCHECK)) {
1122 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1123 goto err;
1125 } else {
1126 log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
1127 "loaded from disk. Dropping it.");
1128 goto err;
1132 if (router_get_router_hash(s, end - s, digest) < 0) {
1133 log_warn(LD_DIR, "Couldn't compute router hash.");
1134 goto err;
1137 int flags = 0;
1138 if (allow_annotations)
1139 flags |= TS_ANNOTATIONS_OK;
1140 if (prepend_annotations)
1141 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1143 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1144 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1145 goto err;
1149 if (smartlist_len(tokens) < 2) {
1150 log_warn(LD_DIR, "Impossibly short router descriptor.");
1151 goto err;
1154 tok = find_by_keyword(tokens, K_ROUTER);
1155 tor_assert(tok->n_args >= 5);
1157 router = tor_malloc_zero(sizeof(routerinfo_t));
1158 router->cache_info.routerlist_index = -1;
1159 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1160 router->cache_info.signed_descriptor_len = end-s;
1161 if (cache_copy) {
1162 size_t len = router->cache_info.signed_descriptor_len +
1163 router->cache_info.annotations_len;
1164 char *cp =
1165 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1166 if (prepend_annotations) {
1167 memcpy(cp, prepend_annotations, prepend_len);
1168 cp += prepend_len;
1170 /* This assertion will always succeed.
1171 * len == signed_desc_len + annotations_len
1172 * == end-s + s-start_of_annotations + prepend_len
1173 * == end-start_of_annotations + prepend_len
1174 * We already wrote prepend_len bytes into the buffer; now we're
1175 * writing end-start_of_annotations -NM. */
1176 tor_assert(cp+(end-start_of_annotations) ==
1177 router->cache_info.signed_descriptor_body+len);
1178 memcpy(cp, start_of_annotations, end-start_of_annotations);
1179 router->cache_info.signed_descriptor_body[len] = '\0';
1180 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1182 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1184 router->nickname = tor_strdup(tok->args[0]);
1185 if (!is_legal_nickname(router->nickname)) {
1186 log_warn(LD_DIR,"Router nickname is invalid");
1187 goto err;
1189 if (!tor_inet_aton(tok->args[1], &in)) {
1190 log_warn(LD_DIR,"Router address is not an IP address.");
1191 goto err;
1193 router->addr = ntohl(in.s_addr);
1195 router->or_port =
1196 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1197 if (!ok) {
1198 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1199 goto err;
1201 router->dir_port =
1202 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1203 if (!ok) {
1204 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1205 goto err;
1208 tok = find_by_keyword(tokens, K_BANDWIDTH);
1209 tor_assert(tok->n_args >= 3);
1210 router->bandwidthrate = (int)
1211 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1213 if (!ok) {
1214 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1215 escaped(tok->args[0]));
1216 goto err;
1218 router->bandwidthburst =
1219 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1220 if (!ok) {
1221 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1222 goto err;
1224 router->bandwidthcapacity = (int)
1225 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1226 if (!ok) {
1227 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1228 goto err;
1231 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1232 tor_assert(tok->n_args);
1233 router->purpose = router_purpose_from_string(tok->args[0]);
1234 } else {
1235 router->purpose = ROUTER_PURPOSE_GENERAL;
1237 router->cache_info.send_unencrypted =
1238 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1240 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1241 tor_assert(tok->n_args >= 1);
1242 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1243 if (!ok) {
1244 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1245 goto err;
1249 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1250 tor_assert(tok->n_args >= 1);
1251 router->is_hibernating
1252 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1255 tok = find_by_keyword(tokens, K_PUBLISHED);
1256 tor_assert(tok->n_args == 1);
1257 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1258 goto err;
1260 tok = find_by_keyword(tokens, K_ONION_KEY);
1261 if (!crypto_pk_public_exponent_ok(tok->key)) {
1262 log_warn(LD_DIR,
1263 "Relay's onion key had invalid exponent.");
1264 goto err;
1266 router->onion_pkey = tok->key;
1267 tok->key = NULL; /* Prevent free */
1269 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
1270 curve25519_public_key_t k;
1271 tor_assert(tok->n_args >= 1);
1272 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
1273 log_warn(LD_DIR, "Bogus ntor-onion-key in routerinfo");
1274 goto err;
1276 router->onion_curve25519_pkey =
1277 tor_memdup(&k, sizeof(curve25519_public_key_t));
1280 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1281 router->identity_pkey = tok->key;
1282 tok->key = NULL; /* Prevent free */
1283 if (crypto_pk_get_digest(router->identity_pkey,
1284 router->cache_info.identity_digest)) {
1285 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1288 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1289 /* If there's a fingerprint line, it must match the identity digest. */
1290 char d[DIGEST_LEN];
1291 tor_assert(tok->n_args == 1);
1292 tor_strstrip(tok->args[0], " ");
1293 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1294 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1295 escaped(tok->args[0]));
1296 goto err;
1298 if (tor_memneq(d,router->cache_info.identity_digest, DIGEST_LEN)) {
1299 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1300 tok->args[0]);
1301 goto err;
1305 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1306 router->platform = tor_strdup(tok->args[0]);
1309 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1310 router->contact_info = tor_strdup(tok->args[0]);
1313 if (find_opt_by_keyword(tokens, K_REJECT6) ||
1314 find_opt_by_keyword(tokens, K_ACCEPT6)) {
1315 log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
1316 "older Tors.");
1317 goto err;
1320 smartlist_t *or_addresses = find_all_by_keyword(tokens, K_OR_ADDRESS);
1321 if (or_addresses) {
1322 find_single_ipv6_orport(or_addresses, &router->ipv6_addr,
1323 &router->ipv6_orport);
1324 smartlist_free(or_addresses);
1327 exit_policy_tokens = find_all_exitpolicy(tokens);
1328 if (!smartlist_len(exit_policy_tokens)) {
1329 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1330 goto err;
1332 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1333 if (router_add_exit_policy(router,t)<0) {
1334 log_warn(LD_DIR,"Error in exit policy");
1335 goto err;
1337 policy_expand_private(&router->exit_policy);
1339 if ((tok = find_opt_by_keyword(tokens, K_IPV6_POLICY)) && tok->n_args) {
1340 router->ipv6_exit_policy = parse_short_policy(tok->args[0]);
1341 if (! router->ipv6_exit_policy) {
1342 log_warn(LD_DIR , "Error in ipv6-policy %s", escaped(tok->args[0]));
1343 goto err;
1347 if (policy_is_reject_star(router->exit_policy, AF_INET) &&
1348 (!router->ipv6_exit_policy ||
1349 short_policy_is_reject_star(router->ipv6_exit_policy)))
1350 router->policy_is_reject_star = 1;
1352 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1353 int i;
1354 router->declared_family = smartlist_new();
1355 for (i=0;i<tok->n_args;++i) {
1356 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1357 log_warn(LD_DIR, "Illegal nickname %s in family line",
1358 escaped(tok->args[i]));
1359 goto err;
1361 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1365 if (find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO))
1366 router->caches_extra_info = 1;
1368 if (find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS))
1369 router->allow_single_hop_exits = 1;
1371 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1372 tor_assert(tok->n_args >= 1);
1373 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1374 base16_decode(router->cache_info.extra_info_digest,
1375 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1376 } else {
1377 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1381 if (find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR)) {
1382 router->wants_to_be_hs_dir = 1;
1385 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1386 note_crypto_pk_op(VERIFY_RTR);
1387 #ifdef COUNT_DISTINCT_DIGESTS
1388 if (!verified_digests)
1389 verified_digests = digestmap_new();
1390 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1391 #endif
1392 if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
1393 "router descriptor") < 0)
1394 goto err;
1396 if (!router->or_port) {
1397 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1398 goto err;
1401 if (!router->platform) {
1402 router->platform = tor_strdup("<unknown>");
1405 goto done;
1407 err:
1408 dump_desc(s_dup, "router descriptor");
1409 routerinfo_free(router);
1410 router = NULL;
1411 done:
1412 if (tokens) {
1413 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1414 smartlist_free(tokens);
1416 smartlist_free(exit_policy_tokens);
1417 if (area) {
1418 DUMP_AREA(area, "routerinfo");
1419 memarea_drop_all(area);
1421 return router;
1424 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1425 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1426 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1427 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1428 * as a map from router identity to routerinfo_t when looking up signing keys.
1430 extrainfo_t *
1431 extrainfo_parse_entry_from_string(const char *s, const char *end,
1432 int cache_copy, struct digest_ri_map_t *routermap)
1434 extrainfo_t *extrainfo = NULL;
1435 char digest[128];
1436 smartlist_t *tokens = NULL;
1437 directory_token_t *tok;
1438 crypto_pk_t *key = NULL;
1439 routerinfo_t *router = NULL;
1440 memarea_t *area = NULL;
1441 const char *s_dup = s;
1443 if (!end) {
1444 end = s + strlen(s);
1447 /* point 'end' to a point immediately after the final newline. */
1448 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1449 --end;
1451 if (router_get_extrainfo_hash(s, end-s, digest) < 0) {
1452 log_warn(LD_DIR, "Couldn't compute router hash.");
1453 goto err;
1455 tokens = smartlist_new();
1456 area = memarea_new();
1457 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1458 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1459 goto err;
1462 if (smartlist_len(tokens) < 2) {
1463 log_warn(LD_DIR, "Impossibly short extra-info document.");
1464 goto err;
1467 tok = smartlist_get(tokens,0);
1468 if (tok->tp != K_EXTRA_INFO) {
1469 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1470 goto err;
1473 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1474 extrainfo->cache_info.is_extrainfo = 1;
1475 if (cache_copy)
1476 extrainfo->cache_info.signed_descriptor_body = tor_memdup_nulterm(s,end-s);
1477 extrainfo->cache_info.signed_descriptor_len = end-s;
1478 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1480 tor_assert(tok->n_args >= 2);
1481 if (!is_legal_nickname(tok->args[0])) {
1482 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1483 goto err;
1485 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1486 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1487 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1488 tok->args[1], HEX_DIGEST_LEN)) {
1489 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1490 escaped(tok->args[1]));
1491 goto err;
1494 tok = find_by_keyword(tokens, K_PUBLISHED);
1495 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1496 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1497 escaped(tok->args[0]));
1498 goto err;
1501 if (routermap &&
1502 (router = digestmap_get((digestmap_t*)routermap,
1503 extrainfo->cache_info.identity_digest))) {
1504 key = router->identity_pkey;
1507 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1508 if (strcmp(tok->object_type, "SIGNATURE") ||
1509 tok->object_size < 128 || tok->object_size > 512) {
1510 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1511 goto err;
1514 if (key) {
1515 note_crypto_pk_op(VERIFY_RTR);
1516 if (check_signature_token(digest, DIGEST_LEN, tok, key, 0,
1517 "extra-info") < 0)
1518 goto err;
1520 if (router)
1521 extrainfo->cache_info.send_unencrypted =
1522 router->cache_info.send_unencrypted;
1523 } else {
1524 extrainfo->pending_sig = tor_memdup(tok->object_body,
1525 tok->object_size);
1526 extrainfo->pending_sig_len = tok->object_size;
1529 goto done;
1530 err:
1531 dump_desc(s_dup, "extra-info descriptor");
1532 extrainfo_free(extrainfo);
1533 extrainfo = NULL;
1534 done:
1535 if (tokens) {
1536 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1537 smartlist_free(tokens);
1539 if (area) {
1540 DUMP_AREA(area, "extrainfo");
1541 memarea_drop_all(area);
1543 return extrainfo;
1546 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1547 * the first character after the certificate. */
1548 authority_cert_t *
1549 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1551 /** Reject any certificate at least this big; it is probably an overflow, an
1552 * attack, a bug, or some other nonsense. */
1553 #define MAX_CERT_SIZE (128*1024)
1555 authority_cert_t *cert = NULL, *old_cert;
1556 smartlist_t *tokens = NULL;
1557 char digest[DIGEST_LEN];
1558 directory_token_t *tok;
1559 char fp_declared[DIGEST_LEN];
1560 char *eos;
1561 size_t len;
1562 int found;
1563 memarea_t *area = NULL;
1564 const char *s_dup = s;
1566 s = eat_whitespace(s);
1567 eos = strstr(s, "\ndir-key-certification");
1568 if (! eos) {
1569 log_warn(LD_DIR, "No signature found on key certificate");
1570 return NULL;
1572 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1573 if (! eos) {
1574 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1575 return NULL;
1577 eos = strchr(eos+2, '\n');
1578 tor_assert(eos);
1579 ++eos;
1580 len = eos - s;
1582 if (len > MAX_CERT_SIZE) {
1583 log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
1584 "rejecting", (unsigned long)len);
1585 return NULL;
1588 tokens = smartlist_new();
1589 area = memarea_new();
1590 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1591 log_warn(LD_DIR, "Error tokenizing key certificate");
1592 goto err;
1594 if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
1595 "\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
1596 goto err;
1597 tok = smartlist_get(tokens, 0);
1598 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1599 log_warn(LD_DIR,
1600 "Key certificate does not begin with a recognized version (3).");
1601 goto err;
1604 cert = tor_malloc_zero(sizeof(authority_cert_t));
1605 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1607 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1608 tor_assert(tok->key);
1609 cert->signing_key = tok->key;
1610 tok->key = NULL;
1611 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1612 goto err;
1614 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1615 tor_assert(tok->key);
1616 cert->identity_key = tok->key;
1617 tok->key = NULL;
1619 tok = find_by_keyword(tokens, K_FINGERPRINT);
1620 tor_assert(tok->n_args);
1621 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1622 strlen(tok->args[0]))) {
1623 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1624 escaped(tok->args[0]));
1625 goto err;
1628 if (crypto_pk_get_digest(cert->identity_key,
1629 cert->cache_info.identity_digest))
1630 goto err;
1632 if (tor_memneq(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1633 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1634 "fingerprint");
1635 goto err;
1638 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1639 if (tok) {
1640 struct in_addr in;
1641 char *address = NULL;
1642 tor_assert(tok->n_args);
1643 /* XXX024 use some tor_addr parse function below instead. -RD */
1644 if (tor_addr_port_split(LOG_WARN, tok->args[0], &address,
1645 &cert->dir_port) < 0 ||
1646 tor_inet_aton(address, &in) == 0) {
1647 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1648 tor_free(address);
1649 goto err;
1651 cert->addr = ntohl(in.s_addr);
1652 tor_free(address);
1655 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1656 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1657 goto err;
1659 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1660 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1661 goto err;
1664 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1665 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1666 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1667 goto err;
1670 /* If we already have this cert, don't bother checking the signature. */
1671 old_cert = authority_cert_get_by_digests(
1672 cert->cache_info.identity_digest,
1673 cert->signing_key_digest);
1674 found = 0;
1675 if (old_cert) {
1676 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1677 * buy us much. */
1678 if (old_cert->cache_info.signed_descriptor_len == len &&
1679 old_cert->cache_info.signed_descriptor_body &&
1680 tor_memeq(s, old_cert->cache_info.signed_descriptor_body, len)) {
1681 log_debug(LD_DIR, "We already checked the signature on this "
1682 "certificate; no need to do so again.");
1683 found = 1;
1686 if (!found) {
1687 if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0,
1688 "key certificate")) {
1689 goto err;
1692 tok = find_by_keyword(tokens, K_DIR_KEY_CROSSCERT);
1693 if (check_signature_token(cert->cache_info.identity_digest,
1694 DIGEST_LEN,
1695 tok,
1696 cert->signing_key,
1697 CST_NO_CHECK_OBJTYPE,
1698 "key cross-certification")) {
1699 goto err;
1703 cert->cache_info.signed_descriptor_len = len;
1704 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1705 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1706 cert->cache_info.signed_descriptor_body[len] = 0;
1707 cert->cache_info.saved_location = SAVED_NOWHERE;
1709 if (end_of_string) {
1710 *end_of_string = eat_whitespace(eos);
1712 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1713 smartlist_free(tokens);
1714 if (area) {
1715 DUMP_AREA(area, "authority cert");
1716 memarea_drop_all(area);
1718 return cert;
1719 err:
1720 dump_desc(s_dup, "authority cert");
1721 authority_cert_free(cert);
1722 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1723 smartlist_free(tokens);
1724 if (area) {
1725 DUMP_AREA(area, "authority cert");
1726 memarea_drop_all(area);
1728 return NULL;
1731 /** Helper: given a string <b>s</b>, return the start of the next router-status
1732 * object (starting with "r " at the start of a line). If none is found,
1733 * return the start of the directory footer, or the next directory signature.
1734 * If none is found, return the end of the string. */
1735 static INLINE const char *
1736 find_start_of_next_routerstatus(const char *s)
1738 const char *eos, *footer, *sig;
1739 if ((eos = strstr(s, "\nr ")))
1740 ++eos;
1741 else
1742 eos = s + strlen(s);
1744 footer = tor_memstr(s, eos-s, "\ndirectory-footer");
1745 sig = tor_memstr(s, eos-s, "\ndirectory-signature");
1747 if (footer && sig)
1748 return MIN(footer, sig) + 1;
1749 else if (footer)
1750 return footer+1;
1751 else if (sig)
1752 return sig+1;
1753 else
1754 return eos;
1757 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1758 * empty smartlist at <b>tokens</b>, parse and return the first router status
1759 * object in the string, and advance *<b>s</b> to just after the end of the
1760 * router status. Return NULL and advance *<b>s</b> on error.
1762 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1763 * routerstatus but use <b>vote_rs</b> instead.
1765 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1766 * consensus, and we should parse it according to the method used to
1767 * make that consensus.
1769 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
1771 static routerstatus_t *
1772 routerstatus_parse_entry_from_string(memarea_t *area,
1773 const char **s, smartlist_t *tokens,
1774 networkstatus_t *vote,
1775 vote_routerstatus_t *vote_rs,
1776 int consensus_method,
1777 consensus_flavor_t flav)
1779 const char *eos, *s_dup = *s;
1780 routerstatus_t *rs = NULL;
1781 directory_token_t *tok;
1782 char timebuf[ISO_TIME_LEN+1];
1783 struct in_addr in;
1784 int offset = 0;
1785 tor_assert(tokens);
1786 tor_assert(bool_eq(vote, vote_rs));
1788 if (!consensus_method)
1789 flav = FLAV_NS;
1790 tor_assert(flav == FLAV_NS || flav == FLAV_MICRODESC);
1792 eos = find_start_of_next_routerstatus(*s);
1794 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1795 log_warn(LD_DIR, "Error tokenizing router status");
1796 goto err;
1798 if (smartlist_len(tokens) < 1) {
1799 log_warn(LD_DIR, "Impossibly short router status");
1800 goto err;
1802 tok = find_by_keyword(tokens, K_R);
1803 tor_assert(tok->n_args >= 7); /* guaranteed by GE(7) in K_R setup */
1804 if (flav == FLAV_NS) {
1805 if (tok->n_args < 8) {
1806 log_warn(LD_DIR, "Too few arguments to r");
1807 goto err;
1809 } else if (flav == FLAV_MICRODESC) {
1810 offset = -1; /* There is no identity digest */
1813 if (vote_rs) {
1814 rs = &vote_rs->status;
1815 } else {
1816 rs = tor_malloc_zero(sizeof(routerstatus_t));
1819 if (!is_legal_nickname(tok->args[0])) {
1820 log_warn(LD_DIR,
1821 "Invalid nickname %s in router status; skipping.",
1822 escaped(tok->args[0]));
1823 goto err;
1825 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1827 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1828 log_warn(LD_DIR, "Error decoding identity digest %s",
1829 escaped(tok->args[1]));
1830 goto err;
1833 if (flav == FLAV_NS) {
1834 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1835 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1836 escaped(tok->args[2]));
1837 goto err;
1841 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1842 tok->args[3+offset], tok->args[4+offset]) < 0 ||
1843 parse_iso_time(timebuf, &rs->published_on)<0) {
1844 log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]",
1845 tok->args[3+offset], tok->args[4+offset],
1846 offset, (int)flav);
1847 goto err;
1850 if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
1851 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1852 escaped(tok->args[5+offset]));
1853 goto err;
1855 rs->addr = ntohl(in.s_addr);
1857 rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
1858 10,0,65535,NULL,NULL);
1859 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
1860 10,0,65535,NULL,NULL);
1863 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
1864 if (a_lines) {
1865 find_single_ipv6_orport(a_lines, &rs->ipv6_addr, &rs->ipv6_orport);
1866 smartlist_free(a_lines);
1870 tok = find_opt_by_keyword(tokens, K_S);
1871 if (tok && vote) {
1872 int i;
1873 vote_rs->flags = 0;
1874 for (i=0; i < tok->n_args; ++i) {
1875 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1876 if (p >= 0) {
1877 vote_rs->flags |= (U64_LITERAL(1)<<p);
1878 } else {
1879 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1880 escaped(tok->args[i]));
1881 goto err;
1884 } else if (tok) {
1885 int i;
1886 for (i=0; i < tok->n_args; ++i) {
1887 if (!strcmp(tok->args[i], "Exit"))
1888 rs->is_exit = 1;
1889 else if (!strcmp(tok->args[i], "Stable"))
1890 rs->is_stable = 1;
1891 else if (!strcmp(tok->args[i], "Fast"))
1892 rs->is_fast = 1;
1893 else if (!strcmp(tok->args[i], "Running"))
1894 rs->is_flagged_running = 1;
1895 else if (!strcmp(tok->args[i], "Named"))
1896 rs->is_named = 1;
1897 else if (!strcmp(tok->args[i], "Valid"))
1898 rs->is_valid = 1;
1899 else if (!strcmp(tok->args[i], "Guard"))
1900 rs->is_possible_guard = 1;
1901 else if (!strcmp(tok->args[i], "BadExit"))
1902 rs->is_bad_exit = 1;
1903 else if (!strcmp(tok->args[i], "BadDirectory"))
1904 rs->is_bad_directory = 1;
1905 else if (!strcmp(tok->args[i], "Authority"))
1906 rs->is_authority = 1;
1907 else if (!strcmp(tok->args[i], "Unnamed") &&
1908 consensus_method >= 2) {
1909 /* Unnamed is computed right by consensus method 2 and later. */
1910 rs->is_unnamed = 1;
1911 } else if (!strcmp(tok->args[i], "HSDir")) {
1912 rs->is_hs_dir = 1;
1916 if ((tok = find_opt_by_keyword(tokens, K_V))) {
1917 tor_assert(tok->n_args == 1);
1918 rs->version_known = 1;
1919 if (strcmpstart(tok->args[0], "Tor ")) {
1920 rs->version_supports_microdesc_cache = 1;
1921 rs->version_supports_optimistic_data = 1;
1922 } else {
1923 rs->version_supports_microdesc_cache =
1924 tor_version_supports_microdescriptors(tok->args[0]);
1925 rs->version_supports_optimistic_data =
1926 tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
1927 rs->version_supports_extend2_cells =
1928 tor_version_as_new_as(tok->args[0], "0.2.4.8-alpha");
1930 if (vote_rs) {
1931 vote_rs->version = tor_strdup(tok->args[0]);
1935 /* handle weighting/bandwidth info */
1936 if ((tok = find_opt_by_keyword(tokens, K_W))) {
1937 int i;
1938 for (i=0; i < tok->n_args; ++i) {
1939 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
1940 int ok;
1941 rs->bandwidth_kb =
1942 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
1943 10, 0, UINT32_MAX,
1944 &ok, NULL);
1945 if (!ok) {
1946 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
1947 goto err;
1949 rs->has_bandwidth = 1;
1950 } else if (!strcmpstart(tok->args[i], "Measured=") && vote_rs) {
1951 int ok;
1952 vote_rs->measured_bw_kb =
1953 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
1954 10, 0, UINT32_MAX, &ok, NULL);
1955 if (!ok) {
1956 log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
1957 escaped(tok->args[i]));
1958 goto err;
1960 vote_rs->has_measured_bw = 1;
1961 vote->has_measured_bws = 1;
1962 } else if (!strcmpstart(tok->args[i], "Unmeasured=1")) {
1963 rs->bw_is_unmeasured = 1;
1968 /* parse exit policy summaries */
1969 if ((tok = find_opt_by_keyword(tokens, K_P))) {
1970 tor_assert(tok->n_args == 1);
1971 if (strcmpstart(tok->args[0], "accept ") &&
1972 strcmpstart(tok->args[0], "reject ")) {
1973 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
1974 escaped(tok->args[0]));
1975 goto err;
1977 /* XXX weasel: parse this into ports and represent them somehow smart,
1978 * maybe not here but somewhere on if we need it for the client.
1979 * we should still parse it here to check it's valid tho.
1981 rs->exitsummary = tor_strdup(tok->args[0]);
1982 rs->has_exitsummary = 1;
1985 if (vote_rs) {
1986 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) {
1987 if (t->tp == K_M && t->n_args) {
1988 vote_microdesc_hash_t *line =
1989 tor_malloc(sizeof(vote_microdesc_hash_t));
1990 line->next = vote_rs->microdesc;
1991 line->microdesc_hash_line = tor_strdup(t->args[0]);
1992 vote_rs->microdesc = line;
1994 } SMARTLIST_FOREACH_END(t);
1995 } else if (flav == FLAV_MICRODESC) {
1996 tok = find_opt_by_keyword(tokens, K_M);
1997 if (tok) {
1998 tor_assert(tok->n_args);
1999 if (digest256_from_base64(rs->descriptor_digest, tok->args[0])) {
2000 log_warn(LD_DIR, "Error decoding microdescriptor digest %s",
2001 escaped(tok->args[0]));
2002 goto err;
2004 } else {
2005 log_info(LD_BUG, "Found an entry in networkstatus with no "
2006 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
2007 rs->nickname, hex_str(rs->identity_digest, DIGEST_LEN),
2008 fmt_addr32(rs->addr), rs->or_port);
2012 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
2013 rs->is_named = 0;
2015 goto done;
2016 err:
2017 dump_desc(s_dup, "routerstatus entry");
2018 if (rs && !vote_rs)
2019 routerstatus_free(rs);
2020 rs = NULL;
2021 done:
2022 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2023 smartlist_clear(tokens);
2024 if (area) {
2025 DUMP_AREA(area, "routerstatus entry");
2026 memarea_clear(area);
2028 *s = eos;
2030 return rs;
2034 compare_vote_routerstatus_entries(const void **_a, const void **_b)
2036 const vote_routerstatus_t *a = *_a, *b = *_b;
2037 return fast_memcmp(a->status.identity_digest, b->status.identity_digest,
2038 DIGEST_LEN);
2041 /** Verify the bandwidth weights of a network status document */
2043 networkstatus_verify_bw_weights(networkstatus_t *ns, int consensus_method)
2045 int64_t weight_scale;
2046 int64_t G=0, M=0, E=0, D=0, T=0;
2047 double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
2048 double Gtotal=0, Mtotal=0, Etotal=0;
2049 const char *casename = NULL;
2050 int valid = 1;
2052 weight_scale = networkstatus_get_weight_scale_param(ns);
2053 Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1);
2054 Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1);
2055 Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1);
2056 Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1);
2057 Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1);
2058 Wme = networkstatus_get_bw_weight(ns, "Wme", -1);
2059 Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1);
2060 Weg = networkstatus_get_bw_weight(ns, "Weg", -1);
2061 Wem = networkstatus_get_bw_weight(ns, "Wem", -1);
2062 Wee = networkstatus_get_bw_weight(ns, "Wee", -1);
2063 Wed = networkstatus_get_bw_weight(ns, "Wed", -1);
2065 if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
2066 || Wem<0 || Wee<0 || Wed<0) {
2067 log_warn(LD_BUG, "No bandwidth weights produced in consensus!");
2068 return 0;
2071 // First, sanity check basic summing properties that hold for all cases
2072 // We use > 1 as the check for these because they are computed as integers.
2073 // Sometimes there are rounding errors.
2074 if (fabs(Wmm - weight_scale) > 1) {
2075 log_warn(LD_BUG, "Wmm=%f != "I64_FORMAT,
2076 Wmm, I64_PRINTF_ARG(weight_scale));
2077 valid = 0;
2080 if (fabs(Wem - Wee) > 1) {
2081 log_warn(LD_BUG, "Wem=%f != Wee=%f", Wem, Wee);
2082 valid = 0;
2085 if (fabs(Wgm - Wgg) > 1) {
2086 log_warn(LD_BUG, "Wgm=%f != Wgg=%f", Wgm, Wgg);
2087 valid = 0;
2090 if (fabs(Weg - Wed) > 1) {
2091 log_warn(LD_BUG, "Wed=%f != Weg=%f", Wed, Weg);
2092 valid = 0;
2095 if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
2096 log_warn(LD_BUG, "Wgg=%f != "I64_FORMAT" - Wmg=%f", Wgg,
2097 I64_PRINTF_ARG(weight_scale), Wmg);
2098 valid = 0;
2101 if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
2102 log_warn(LD_BUG, "Wee=%f != "I64_FORMAT" - Wme=%f", Wee,
2103 I64_PRINTF_ARG(weight_scale), Wme);
2104 valid = 0;
2107 if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
2108 log_warn(LD_BUG, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT,
2109 Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
2110 valid = 0;
2113 Wgg /= weight_scale;
2114 Wgm /= weight_scale;
2115 Wgd /= weight_scale;
2117 Wmg /= weight_scale;
2118 Wmm /= weight_scale;
2119 Wme /= weight_scale;
2120 Wmd /= weight_scale;
2122 Weg /= weight_scale;
2123 Wem /= weight_scale;
2124 Wee /= weight_scale;
2125 Wed /= weight_scale;
2127 // Then, gather G, M, E, D, T to determine case
2128 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
2129 int is_exit = 0;
2130 if (consensus_method >= MIN_METHOD_TO_CUT_BADEXIT_WEIGHT) {
2131 /* Bug #2203: Don't count bad exits as exits for balancing */
2132 is_exit = rs->is_exit && !rs->is_bad_exit;
2133 } else {
2134 is_exit = rs->is_exit;
2136 if (rs->has_bandwidth) {
2137 T += rs->bandwidth_kb;
2138 if (is_exit && rs->is_possible_guard) {
2139 D += rs->bandwidth_kb;
2140 Gtotal += Wgd*rs->bandwidth_kb;
2141 Mtotal += Wmd*rs->bandwidth_kb;
2142 Etotal += Wed*rs->bandwidth_kb;
2143 } else if (is_exit) {
2144 E += rs->bandwidth_kb;
2145 Mtotal += Wme*rs->bandwidth_kb;
2146 Etotal += Wee*rs->bandwidth_kb;
2147 } else if (rs->is_possible_guard) {
2148 G += rs->bandwidth_kb;
2149 Gtotal += Wgg*rs->bandwidth_kb;
2150 Mtotal += Wmg*rs->bandwidth_kb;
2151 } else {
2152 M += rs->bandwidth_kb;
2153 Mtotal += Wmm*rs->bandwidth_kb;
2155 } else {
2156 log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
2157 routerstatus_describe(rs));
2159 } SMARTLIST_FOREACH_END(rs);
2161 // Finally, check equality conditions depending upon case 1, 2 or 3
2162 // Full equality cases: 1, 3b
2163 // Partial equality cases: 2b (E=G), 3a (M=E)
2164 // Fully unknown: 2a
2165 if (3*E >= T && 3*G >= T) {
2166 // Case 1: Neither are scarce
2167 casename = "Case 1";
2168 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2169 log_warn(LD_DIR,
2170 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2171 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2172 " T="I64_FORMAT". "
2173 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2174 casename, Etotal, Mtotal,
2175 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2176 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2177 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2178 valid = 0;
2180 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2181 log_warn(LD_DIR,
2182 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2183 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2184 " T="I64_FORMAT". "
2185 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2186 casename, Etotal, Gtotal,
2187 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2188 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2189 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2190 valid = 0;
2192 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2193 log_warn(LD_DIR,
2194 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2195 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2196 " T="I64_FORMAT". "
2197 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2198 casename, Mtotal, Gtotal,
2199 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2200 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2201 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2202 valid = 0;
2204 } else if (3*E < T && 3*G < T) {
2205 int64_t R = MIN(E, G);
2206 int64_t S = MAX(E, G);
2208 * Case 2: Both Guards and Exits are scarce
2209 * Balance D between E and G, depending upon
2210 * D capacity and scarcity. Devote no extra
2211 * bandwidth to middle nodes.
2213 if (R+D < S) { // Subcase a
2214 double Rtotal, Stotal;
2215 if (E < G) {
2216 Rtotal = Etotal;
2217 Stotal = Gtotal;
2218 } else {
2219 Rtotal = Gtotal;
2220 Stotal = Etotal;
2222 casename = "Case 2a";
2223 // Rtotal < Stotal
2224 if (Rtotal > Stotal) {
2225 log_warn(LD_DIR,
2226 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
2227 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2228 " T="I64_FORMAT". "
2229 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2230 casename, Rtotal, Stotal,
2231 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2232 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2233 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2234 valid = 0;
2236 // Rtotal < T/3
2237 if (3*Rtotal > T) {
2238 log_warn(LD_DIR,
2239 "Bw Weight Failure for %s: 3*Rtotal %f > T "
2240 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2241 " D="I64_FORMAT" T="I64_FORMAT". "
2242 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2243 casename, Rtotal*3, I64_PRINTF_ARG(T),
2244 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2245 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2246 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2247 valid = 0;
2249 // Stotal < T/3
2250 if (3*Stotal > T) {
2251 log_warn(LD_DIR,
2252 "Bw Weight Failure for %s: 3*Stotal %f > T "
2253 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2254 " D="I64_FORMAT" T="I64_FORMAT". "
2255 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2256 casename, Stotal*3, I64_PRINTF_ARG(T),
2257 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2258 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2259 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2260 valid = 0;
2262 // Mtotal > T/3
2263 if (3*Mtotal < T) {
2264 log_warn(LD_DIR,
2265 "Bw Weight Failure for %s: 3*Mtotal %f < T "
2266 I64_FORMAT". "
2267 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2268 " T="I64_FORMAT". "
2269 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2270 casename, Mtotal*3, I64_PRINTF_ARG(T),
2271 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2272 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2273 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2274 valid = 0;
2276 } else { // Subcase b: R+D > S
2277 casename = "Case 2b";
2279 /* Check the rare-M redirect case. */
2280 if (D != 0 && 3*M < T) {
2281 casename = "Case 2b (balanced)";
2282 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2283 log_warn(LD_DIR,
2284 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2285 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2286 " T="I64_FORMAT". "
2287 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2288 casename, Etotal, Mtotal,
2289 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2290 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2291 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2292 valid = 0;
2294 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2295 log_warn(LD_DIR,
2296 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2297 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2298 " T="I64_FORMAT". "
2299 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2300 casename, Etotal, Gtotal,
2301 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2302 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2303 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2304 valid = 0;
2306 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2307 log_warn(LD_DIR,
2308 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2309 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2310 " T="I64_FORMAT". "
2311 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2312 casename, Mtotal, Gtotal,
2313 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2314 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2315 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2316 valid = 0;
2318 } else {
2319 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2320 log_warn(LD_DIR,
2321 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2322 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2323 " T="I64_FORMAT". "
2324 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2325 casename, Etotal, Gtotal,
2326 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2327 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2328 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2329 valid = 0;
2333 } else { // if (E < T/3 || G < T/3) {
2334 int64_t S = MIN(E, G);
2335 int64_t NS = MAX(E, G);
2336 if (3*(S+D) < T) { // Subcase a:
2337 double Stotal;
2338 double NStotal;
2339 if (G < E) {
2340 casename = "Case 3a (G scarce)";
2341 Stotal = Gtotal;
2342 NStotal = Etotal;
2343 } else { // if (G >= E) {
2344 casename = "Case 3a (E scarce)";
2345 NStotal = Gtotal;
2346 Stotal = Etotal;
2348 // Stotal < T/3
2349 if (3*Stotal > T) {
2350 log_warn(LD_DIR,
2351 "Bw Weight Failure for %s: 3*Stotal %f > T "
2352 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2353 " D="I64_FORMAT" T="I64_FORMAT". "
2354 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2355 casename, Stotal*3, I64_PRINTF_ARG(T),
2356 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2357 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2358 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2359 valid = 0;
2361 if (NS >= M) {
2362 if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
2363 log_warn(LD_DIR,
2364 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
2365 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2366 " T="I64_FORMAT". "
2367 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2368 casename, NStotal, Mtotal,
2369 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2370 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2371 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2372 valid = 0;
2374 } else {
2375 // if NS < M, NStotal > T/3 because only one of G or E is scarce
2376 if (3*NStotal < T) {
2377 log_warn(LD_DIR,
2378 "Bw Weight Failure for %s: 3*NStotal %f < T "
2379 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
2380 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
2381 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2382 casename, NStotal*3, I64_PRINTF_ARG(T),
2383 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2384 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2385 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2386 valid = 0;
2389 } else { // Subcase b: S+D >= T/3
2390 casename = "Case 3b";
2391 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2392 log_warn(LD_DIR,
2393 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
2394 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2395 " T="I64_FORMAT". "
2396 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2397 casename, Etotal, Mtotal,
2398 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2399 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2400 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2401 valid = 0;
2403 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2404 log_warn(LD_DIR,
2405 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
2406 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2407 " T="I64_FORMAT". "
2408 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2409 casename, Etotal, Gtotal,
2410 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2411 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2412 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2413 valid = 0;
2415 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2416 log_warn(LD_DIR,
2417 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
2418 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2419 " T="I64_FORMAT". "
2420 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
2421 casename, Mtotal, Gtotal,
2422 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2423 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2424 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2425 valid = 0;
2430 if (valid)
2431 log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.",
2432 casename);
2434 return valid;
2437 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2438 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2439 networkstatus_t *
2440 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2441 networkstatus_type_t ns_type)
2443 smartlist_t *tokens = smartlist_new();
2444 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2445 networkstatus_voter_info_t *voter = NULL;
2446 networkstatus_t *ns = NULL;
2447 digests_t ns_digests;
2448 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
2449 directory_token_t *tok;
2450 int ok;
2451 struct in_addr in;
2452 int i, inorder, n_signatures = 0;
2453 memarea_t *area = NULL, *rs_area = NULL;
2454 consensus_flavor_t flav = FLAV_NS;
2455 char *last_kwd=NULL;
2457 tor_assert(s);
2459 if (eos_out)
2460 *eos_out = NULL;
2462 if (router_get_networkstatus_v3_hashes(s, &ns_digests)) {
2463 log_warn(LD_DIR, "Unable to compute digest of network-status");
2464 goto err;
2467 area = memarea_new();
2468 end_of_header = find_start_of_next_routerstatus(s);
2469 if (tokenize_string(area, s, end_of_header, tokens,
2470 (ns_type == NS_TYPE_CONSENSUS) ?
2471 networkstatus_consensus_token_table :
2472 networkstatus_token_table, 0)) {
2473 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2474 goto err;
2477 ns = tor_malloc_zero(sizeof(networkstatus_t));
2478 memcpy(&ns->digests, &ns_digests, sizeof(ns_digests));
2480 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2481 tor_assert(tok);
2482 if (tok->n_args > 1) {
2483 int flavor = networkstatus_parse_flavor_name(tok->args[1]);
2484 if (flavor < 0) {
2485 log_warn(LD_DIR, "Can't parse document with unknown flavor %s",
2486 escaped(tok->args[1]));
2487 goto err;
2489 ns->flavor = flav = flavor;
2491 if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
2492 log_warn(LD_DIR, "Flavor found on non-consensus networkstatus.");
2493 goto err;
2496 if (ns_type != NS_TYPE_CONSENSUS) {
2497 const char *end_of_cert = NULL;
2498 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2499 goto err;
2500 ++cert;
2501 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2502 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2503 goto err;
2506 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2507 tor_assert(tok->n_args);
2508 if (!strcmp(tok->args[0], "vote")) {
2509 ns->type = NS_TYPE_VOTE;
2510 } else if (!strcmp(tok->args[0], "consensus")) {
2511 ns->type = NS_TYPE_CONSENSUS;
2512 } else if (!strcmp(tok->args[0], "opinion")) {
2513 ns->type = NS_TYPE_OPINION;
2514 } else {
2515 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2516 escaped(tok->args[0]));
2517 goto err;
2519 if (ns_type != ns->type) {
2520 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2521 goto err;
2524 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2525 tok = find_by_keyword(tokens, K_PUBLISHED);
2526 if (parse_iso_time(tok->args[0], &ns->published))
2527 goto err;
2529 ns->supported_methods = smartlist_new();
2530 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2531 if (tok) {
2532 for (i=0; i < tok->n_args; ++i)
2533 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2534 } else {
2535 smartlist_add(ns->supported_methods, tor_strdup("1"));
2537 } else {
2538 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2539 if (tok) {
2540 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2541 &ok, NULL);
2542 if (!ok)
2543 goto err;
2544 } else {
2545 ns->consensus_method = 1;
2549 tok = find_by_keyword(tokens, K_VALID_AFTER);
2550 if (parse_iso_time(tok->args[0], &ns->valid_after))
2551 goto err;
2553 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2554 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2555 goto err;
2557 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2558 if (parse_iso_time(tok->args[0], &ns->valid_until))
2559 goto err;
2561 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2562 tor_assert(tok->n_args >= 2);
2563 ns->vote_seconds =
2564 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2565 if (!ok)
2566 goto err;
2567 ns->dist_seconds =
2568 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2569 if (!ok)
2570 goto err;
2571 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2572 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2573 goto err;
2575 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2576 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2577 goto err;
2579 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2580 log_warn(LD_DIR, "Vote seconds is too short");
2581 goto err;
2583 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2584 log_warn(LD_DIR, "Dist seconds is too short");
2585 goto err;
2588 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2589 ns->client_versions = tor_strdup(tok->args[0]);
2591 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2592 ns->server_versions = tor_strdup(tok->args[0]);
2595 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2596 ns->known_flags = smartlist_new();
2597 inorder = 1;
2598 for (i = 0; i < tok->n_args; ++i) {
2599 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2600 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2601 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2602 inorder = 0;
2605 if (!inorder) {
2606 log_warn(LD_DIR, "known-flags not in order");
2607 goto err;
2609 if (ns->type != NS_TYPE_CONSENSUS &&
2610 smartlist_len(ns->known_flags) > MAX_KNOWN_FLAGS_IN_VOTE) {
2611 /* If we allowed more than 64 flags in votes, then parsing them would make
2612 * us invoke undefined behavior whenever we used 1<<flagnum to do a
2613 * bit-shift. This is only for votes and opinions: consensus users don't
2614 * care about flags they don't recognize, and so don't build a bitfield
2615 * for them. */
2616 log_warn(LD_DIR, "Too many known-flags in consensus vote or opinion");
2617 goto err;
2620 tok = find_opt_by_keyword(tokens, K_PARAMS);
2621 if (tok) {
2622 int any_dups = 0;
2623 inorder = 1;
2624 ns->net_params = smartlist_new();
2625 for (i = 0; i < tok->n_args; ++i) {
2626 int ok=0;
2627 char *eq = strchr(tok->args[i], '=');
2628 size_t eq_pos;
2629 if (!eq) {
2630 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2631 goto err;
2633 eq_pos = eq-tok->args[i];
2634 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
2635 if (!ok) {
2636 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2637 goto err;
2639 if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
2640 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2641 inorder = 0;
2643 if (last_kwd && eq_pos == strlen(last_kwd) &&
2644 fast_memeq(last_kwd, tok->args[i], eq_pos)) {
2645 log_warn(LD_DIR, "Duplicate value for %s parameter",
2646 escaped(tok->args[i]));
2647 any_dups = 1;
2649 tor_free(last_kwd);
2650 last_kwd = tor_strndup(tok->args[i], eq_pos);
2651 smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
2653 if (!inorder) {
2654 log_warn(LD_DIR, "params not in order");
2655 goto err;
2657 if (any_dups) {
2658 log_warn(LD_DIR, "Duplicate in parameters");
2659 goto err;
2663 ns->voters = smartlist_new();
2665 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
2666 tok = _tok;
2667 if (tok->tp == K_DIR_SOURCE) {
2668 tor_assert(tok->n_args >= 6);
2670 if (voter)
2671 smartlist_add(ns->voters, voter);
2672 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2673 voter->sigs = smartlist_new();
2674 if (ns->type != NS_TYPE_CONSENSUS)
2675 memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN);
2677 voter->nickname = tor_strdup(tok->args[0]);
2678 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2679 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2680 tok->args[1], HEX_DIGEST_LEN) < 0) {
2681 log_warn(LD_DIR, "Error decoding identity digest %s in "
2682 "network-status vote.", escaped(tok->args[1]));
2683 goto err;
2685 if (ns->type != NS_TYPE_CONSENSUS &&
2686 tor_memneq(ns->cert->cache_info.identity_digest,
2687 voter->identity_digest, DIGEST_LEN)) {
2688 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2689 goto err;
2691 if (ns->type != NS_TYPE_CONSENSUS) {
2692 if (authority_cert_is_blacklisted(ns->cert)) {
2693 log_warn(LD_DIR, "Rejecting vote signature made with blacklisted "
2694 "signing key %s",
2695 hex_str(ns->cert->signing_key_digest, DIGEST_LEN));
2696 goto err;
2699 voter->address = tor_strdup(tok->args[2]);
2700 if (!tor_inet_aton(tok->args[3], &in)) {
2701 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2702 escaped(tok->args[3]));
2703 goto err;
2705 voter->addr = ntohl(in.s_addr);
2706 voter->dir_port = (uint16_t)
2707 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2708 if (!ok)
2709 goto err;
2710 voter->or_port = (uint16_t)
2711 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2712 if (!ok)
2713 goto err;
2714 } else if (tok->tp == K_CONTACT) {
2715 if (!voter || voter->contact) {
2716 log_warn(LD_DIR, "contact element is out of place.");
2717 goto err;
2719 voter->contact = tor_strdup(tok->args[0]);
2720 } else if (tok->tp == K_VOTE_DIGEST) {
2721 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2722 tor_assert(tok->n_args >= 1);
2723 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2724 log_warn(LD_DIR, "vote-digest element is out of place.");
2725 goto err;
2727 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2728 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2729 tok->args[0], HEX_DIGEST_LEN) < 0) {
2730 log_warn(LD_DIR, "Error decoding vote digest %s in "
2731 "network-status consensus.", escaped(tok->args[0]));
2732 goto err;
2735 } SMARTLIST_FOREACH_END(_tok);
2736 if (voter) {
2737 smartlist_add(ns->voters, voter);
2738 voter = NULL;
2740 if (smartlist_len(ns->voters) == 0) {
2741 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2742 goto err;
2743 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
2744 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2745 goto err;
2748 if (ns->type != NS_TYPE_CONSENSUS &&
2749 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
2750 int bad = 1;
2751 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2752 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
2753 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
2754 tok->args[0], HEX_DIGEST_LEN)<0)
2755 bad = 1;
2756 else
2757 bad = 0;
2759 if (bad) {
2760 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
2761 escaped(tok->args[0]));
2765 /* Parse routerstatus lines. */
2766 rs_tokens = smartlist_new();
2767 rs_area = memarea_new();
2768 s = end_of_header;
2769 ns->routerstatus_list = smartlist_new();
2771 while (!strcmpstart(s, "r ")) {
2772 if (ns->type != NS_TYPE_CONSENSUS) {
2773 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2774 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
2775 rs, 0, 0))
2776 smartlist_add(ns->routerstatus_list, rs);
2777 else {
2778 tor_free(rs->version);
2779 tor_free(rs);
2781 } else {
2782 routerstatus_t *rs;
2783 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
2784 NULL, NULL,
2785 ns->consensus_method,
2786 flav)))
2787 smartlist_add(ns->routerstatus_list, rs);
2790 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2791 routerstatus_t *rs1, *rs2;
2792 if (ns->type != NS_TYPE_CONSENSUS) {
2793 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2794 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2795 rs1 = &a->status; rs2 = &b->status;
2796 } else {
2797 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2798 rs2 = smartlist_get(ns->routerstatus_list, i);
2800 if (fast_memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN)
2801 >= 0) {
2802 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2803 "digest");
2804 goto err;
2808 /* Parse footer; check signature. */
2809 footer_tokens = smartlist_new();
2810 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2811 ++end_of_footer;
2812 else
2813 end_of_footer = s + strlen(s);
2814 if (tokenize_string(area,s, end_of_footer, footer_tokens,
2815 networkstatus_vote_footer_token_table, 0)) {
2816 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2817 goto err;
2821 int found_sig = 0;
2822 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
2823 tok = _tok;
2824 if (tok->tp == K_DIRECTORY_SIGNATURE)
2825 found_sig = 1;
2826 else if (found_sig) {
2827 log_warn(LD_DIR, "Extraneous token after first directory-signature");
2828 goto err;
2830 } SMARTLIST_FOREACH_END(_tok);
2833 if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
2834 if (tok != smartlist_get(footer_tokens, 0)) {
2835 log_warn(LD_DIR, "Misplaced directory-footer token");
2836 goto err;
2840 tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
2841 if (tok) {
2842 ns->weight_params = smartlist_new();
2843 for (i = 0; i < tok->n_args; ++i) {
2844 int ok=0;
2845 char *eq = strchr(tok->args[i], '=');
2846 if (!eq) {
2847 log_warn(LD_DIR, "Bad element '%s' in weight params",
2848 escaped(tok->args[i]));
2849 goto err;
2851 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
2852 if (!ok) {
2853 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2854 goto err;
2856 smartlist_add(ns->weight_params, tor_strdup(tok->args[i]));
2860 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
2861 char declared_identity[DIGEST_LEN];
2862 networkstatus_voter_info_t *v;
2863 document_signature_t *sig;
2864 const char *id_hexdigest = NULL;
2865 const char *sk_hexdigest = NULL;
2866 digest_algorithm_t alg = DIGEST_SHA1;
2867 tok = _tok;
2868 if (tok->tp != K_DIRECTORY_SIGNATURE)
2869 continue;
2870 tor_assert(tok->n_args >= 2);
2871 if (tok->n_args == 2) {
2872 id_hexdigest = tok->args[0];
2873 sk_hexdigest = tok->args[1];
2874 } else {
2875 const char *algname = tok->args[0];
2876 int a;
2877 id_hexdigest = tok->args[1];
2878 sk_hexdigest = tok->args[2];
2879 a = crypto_digest_algorithm_parse_name(algname);
2880 if (a<0) {
2881 log_warn(LD_DIR, "Unknown digest algorithm %s; skipping",
2882 escaped(algname));
2883 continue;
2885 alg = a;
2888 if (!tok->object_type ||
2889 strcmp(tok->object_type, "SIGNATURE") ||
2890 tok->object_size < 128 || tok->object_size > 512) {
2891 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2892 goto err;
2895 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
2896 base16_decode(declared_identity, sizeof(declared_identity),
2897 id_hexdigest, HEX_DIGEST_LEN) < 0) {
2898 log_warn(LD_DIR, "Error decoding declared identity %s in "
2899 "network-status vote.", escaped(id_hexdigest));
2900 goto err;
2902 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2903 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2904 "any declared directory source.");
2905 goto err;
2907 sig = tor_malloc_zero(sizeof(document_signature_t));
2908 memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN);
2909 sig->alg = alg;
2910 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
2911 base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
2912 sk_hexdigest, HEX_DIGEST_LEN) < 0) {
2913 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
2914 "network-status vote.", escaped(sk_hexdigest));
2915 tor_free(sig);
2916 goto err;
2919 if (ns->type != NS_TYPE_CONSENSUS) {
2920 if (tor_memneq(declared_identity, ns->cert->cache_info.identity_digest,
2921 DIGEST_LEN)) {
2922 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2923 "network-status vote.");
2924 tor_free(sig);
2925 goto err;
2929 if (voter_get_sig_by_algorithm(v, sig->alg)) {
2930 /* We already parsed a vote with this algorithm from this voter. Use the
2931 first one. */
2932 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
2933 "that contains two votes from the same voter with the same "
2934 "algorithm. Ignoring the second vote.");
2935 tor_free(sig);
2936 continue;
2939 if (ns->type != NS_TYPE_CONSENSUS) {
2940 if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
2941 tok, ns->cert->signing_key, 0,
2942 "network-status vote")) {
2943 tor_free(sig);
2944 goto err;
2946 sig->good_signature = 1;
2947 } else {
2948 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
2949 tor_free(sig);
2950 goto err;
2952 sig->signature = tor_memdup(tok->object_body, tok->object_size);
2953 sig->signature_len = (int) tok->object_size;
2955 smartlist_add(v->sigs, sig);
2957 ++n_signatures;
2958 } SMARTLIST_FOREACH_END(_tok);
2960 if (! n_signatures) {
2961 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2962 goto err;
2963 } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
2964 log_warn(LD_DIR, "Received more than one signature on a "
2965 "network-status vote.");
2966 goto err;
2969 if (eos_out)
2970 *eos_out = end_of_footer;
2972 goto done;
2973 err:
2974 dump_desc(s_dup, "v3 networkstatus");
2975 networkstatus_vote_free(ns);
2976 ns = NULL;
2977 done:
2978 if (tokens) {
2979 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2980 smartlist_free(tokens);
2982 if (voter) {
2983 if (voter->sigs) {
2984 SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
2985 document_signature_free(sig));
2986 smartlist_free(voter->sigs);
2988 tor_free(voter->nickname);
2989 tor_free(voter->address);
2990 tor_free(voter->contact);
2991 tor_free(voter);
2993 if (rs_tokens) {
2994 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t));
2995 smartlist_free(rs_tokens);
2997 if (footer_tokens) {
2998 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
2999 smartlist_free(footer_tokens);
3001 if (area) {
3002 DUMP_AREA(area, "v3 networkstatus");
3003 memarea_drop_all(area);
3005 if (rs_area)
3006 memarea_drop_all(rs_area);
3007 tor_free(last_kwd);
3009 return ns;
3012 /** Return the digests_t that holds the digests of the
3013 * <b>flavor_name</b>-flavored networkstatus according to the detached
3014 * signatures document <b>sigs</b>, allocating a new digests_t as neeeded. */
3015 static digests_t *
3016 detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name)
3018 digests_t *d = strmap_get(sigs->digests, flavor_name);
3019 if (!d) {
3020 d = tor_malloc_zero(sizeof(digests_t));
3021 strmap_set(sigs->digests, flavor_name, d);
3023 return d;
3026 /** Return the list of signatures of the <b>flavor_name</b>-flavored
3027 * networkstatus according to the detached signatures document <b>sigs</b>,
3028 * allocating a new digests_t as neeeded. */
3029 static smartlist_t *
3030 detached_get_signatures(ns_detached_signatures_t *sigs,
3031 const char *flavor_name)
3033 smartlist_t *sl = strmap_get(sigs->signatures, flavor_name);
3034 if (!sl) {
3035 sl = smartlist_new();
3036 strmap_set(sigs->signatures, flavor_name, sl);
3038 return sl;
3041 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
3042 * <b>eos</b> and return the result. Return -1 on failure. */
3043 ns_detached_signatures_t *
3044 networkstatus_parse_detached_signatures(const char *s, const char *eos)
3046 /* XXXX there is too much duplicate shared between this function and
3047 * networkstatus_parse_vote_from_string(). */
3048 directory_token_t *tok;
3049 memarea_t *area = NULL;
3050 digests_t *digests;
3052 smartlist_t *tokens = smartlist_new();
3053 ns_detached_signatures_t *sigs =
3054 tor_malloc_zero(sizeof(ns_detached_signatures_t));
3055 sigs->digests = strmap_new();
3056 sigs->signatures = strmap_new();
3058 if (!eos)
3059 eos = s + strlen(s);
3061 area = memarea_new();
3062 if (tokenize_string(area,s, eos, tokens,
3063 networkstatus_detached_signature_token_table, 0)) {
3064 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
3065 goto err;
3068 /* Grab all the digest-like tokens. */
3069 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3070 const char *algname;
3071 digest_algorithm_t alg;
3072 const char *flavor;
3073 const char *hexdigest;
3074 size_t expected_length;
3076 tok = _tok;
3078 if (tok->tp == K_CONSENSUS_DIGEST) {
3079 algname = "sha1";
3080 alg = DIGEST_SHA1;
3081 flavor = "ns";
3082 hexdigest = tok->args[0];
3083 } else if (tok->tp == K_ADDITIONAL_DIGEST) {
3084 int a = crypto_digest_algorithm_parse_name(tok->args[1]);
3085 if (a<0) {
3086 log_warn(LD_DIR, "Unrecognized algorithm name %s", tok->args[0]);
3087 continue;
3089 alg = (digest_algorithm_t) a;
3090 flavor = tok->args[0];
3091 algname = tok->args[1];
3092 hexdigest = tok->args[2];
3093 } else {
3094 continue;
3097 expected_length =
3098 (alg == DIGEST_SHA1) ? HEX_DIGEST_LEN : HEX_DIGEST256_LEN;
3100 if (strlen(hexdigest) != expected_length) {
3101 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
3102 "networkstatus signatures");
3103 goto err;
3105 digests = detached_get_digests(sigs, flavor);
3106 tor_assert(digests);
3107 if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) {
3108 log_warn(LD_DIR, "Multiple digests for %s with %s on detached "
3109 "signatures document", flavor, algname);
3110 continue;
3112 if (base16_decode(digests->d[alg], DIGEST256_LEN,
3113 hexdigest, strlen(hexdigest)) < 0) {
3114 log_warn(LD_DIR, "Bad encoding on consensus-digest in detached "
3115 "networkstatus signatures");
3116 goto err;
3118 } SMARTLIST_FOREACH_END(_tok);
3120 tok = find_by_keyword(tokens, K_VALID_AFTER);
3121 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
3122 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
3123 goto err;
3126 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
3127 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
3128 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
3129 goto err;
3132 tok = find_by_keyword(tokens, K_VALID_UNTIL);
3133 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
3134 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
3135 goto err;
3138 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3139 const char *id_hexdigest;
3140 const char *sk_hexdigest;
3141 const char *algname;
3142 const char *flavor;
3143 digest_algorithm_t alg;
3145 char id_digest[DIGEST_LEN];
3146 char sk_digest[DIGEST_LEN];
3147 smartlist_t *siglist;
3148 document_signature_t *sig;
3149 int is_duplicate;
3151 tok = _tok;
3152 if (tok->tp == K_DIRECTORY_SIGNATURE) {
3153 tor_assert(tok->n_args >= 2);
3154 flavor = "ns";
3155 algname = "sha1";
3156 id_hexdigest = tok->args[0];
3157 sk_hexdigest = tok->args[1];
3158 } else if (tok->tp == K_ADDITIONAL_SIGNATURE) {
3159 tor_assert(tok->n_args >= 4);
3160 flavor = tok->args[0];
3161 algname = tok->args[1];
3162 id_hexdigest = tok->args[2];
3163 sk_hexdigest = tok->args[3];
3164 } else {
3165 continue;
3169 int a = crypto_digest_algorithm_parse_name(algname);
3170 if (a<0) {
3171 log_warn(LD_DIR, "Unrecognized algorithm name %s", algname);
3172 continue;
3174 alg = (digest_algorithm_t) a;
3177 if (!tok->object_type ||
3178 strcmp(tok->object_type, "SIGNATURE") ||
3179 tok->object_size < 128 || tok->object_size > 512) {
3180 log_warn(LD_DIR, "Bad object type or length on directory-signature");
3181 goto err;
3184 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
3185 base16_decode(id_digest, sizeof(id_digest),
3186 id_hexdigest, HEX_DIGEST_LEN) < 0) {
3187 log_warn(LD_DIR, "Error decoding declared identity %s in "
3188 "network-status vote.", escaped(id_hexdigest));
3189 goto err;
3191 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
3192 base16_decode(sk_digest, sizeof(sk_digest),
3193 sk_hexdigest, HEX_DIGEST_LEN) < 0) {
3194 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
3195 "network-status vote.", escaped(sk_hexdigest));
3196 goto err;
3199 siglist = detached_get_signatures(sigs, flavor);
3200 is_duplicate = 0;
3201 SMARTLIST_FOREACH(siglist, document_signature_t *, dsig, {
3202 if (dsig->alg == alg &&
3203 tor_memeq(id_digest, dsig->identity_digest, DIGEST_LEN) &&
3204 tor_memeq(sk_digest, dsig->signing_key_digest, DIGEST_LEN)) {
3205 is_duplicate = 1;
3208 if (is_duplicate) {
3209 log_warn(LD_DIR, "Two signatures with identical keys and algorithm "
3210 "found.");
3211 continue;
3214 sig = tor_malloc_zero(sizeof(document_signature_t));
3215 sig->alg = alg;
3216 memcpy(sig->identity_digest, id_digest, DIGEST_LEN);
3217 memcpy(sig->signing_key_digest, sk_digest, DIGEST_LEN);
3218 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
3219 tor_free(sig);
3220 goto err;
3222 sig->signature = tor_memdup(tok->object_body, tok->object_size);
3223 sig->signature_len = (int) tok->object_size;
3225 smartlist_add(siglist, sig);
3226 } SMARTLIST_FOREACH_END(_tok);
3228 goto done;
3229 err:
3230 ns_detached_signatures_free(sigs);
3231 sigs = NULL;
3232 done:
3233 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3234 smartlist_free(tokens);
3235 if (area) {
3236 DUMP_AREA(area, "detached signatures");
3237 memarea_drop_all(area);
3239 return sigs;
3242 /** Parse the addr policy in the string <b>s</b> and return it. If
3243 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
3244 * ADDR_POLICY_REJECT) for items that specify no action.
3246 * The addr_policy_t returned by this function can have its address set to
3247 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
3248 * of AF_INET and AF_INET6 items.
3250 addr_policy_t *
3251 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
3253 directory_token_t *tok = NULL;
3254 const char *cp, *eos;
3255 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
3256 * But note that there can be an arbitrary amount of space between the
3257 * accept and the address:mask/port element. */
3258 char line[TOR_ADDR_BUF_LEN*2 + 32];
3259 addr_policy_t *r;
3260 memarea_t *area = NULL;
3262 s = eat_whitespace(s);
3263 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
3264 if (tor_snprintf(line, sizeof(line), "%s %s",
3265 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
3266 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
3267 return NULL;
3269 cp = line;
3270 tor_strlower(line);
3271 } else { /* assume an already well-formed address policy line */
3272 cp = s;
3275 eos = cp + strlen(cp);
3276 area = memarea_new();
3277 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
3278 if (tok->tp == ERR_) {
3279 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
3280 goto err;
3282 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
3283 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
3284 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
3285 goto err;
3288 r = router_parse_addr_policy(tok, TAPMP_EXTENDED_STAR);
3289 goto done;
3290 err:
3291 r = NULL;
3292 done:
3293 token_clear(tok);
3294 if (area) {
3295 DUMP_AREA(area, "policy item");
3296 memarea_drop_all(area);
3298 return r;
3301 /** Add an exit policy stored in the token <b>tok</b> to the router info in
3302 * <b>router</b>. Return 0 on success, -1 on failure. */
3303 static int
3304 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
3306 addr_policy_t *newe;
3307 newe = router_parse_addr_policy(tok, 0);
3308 if (!newe)
3309 return -1;
3310 if (! router->exit_policy)
3311 router->exit_policy = smartlist_new();
3313 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
3314 tor_addr_family(&newe->addr) == AF_INET)
3316 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
3317 tor_addr_family(&newe->addr) == AF_INET6)) {
3318 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
3319 "policy");
3320 addr_policy_free(newe);
3321 return -1;
3324 smartlist_add(router->exit_policy, newe);
3326 return 0;
3329 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
3330 * a new exit_policy_t corresponding to the token. */
3331 static addr_policy_t *
3332 router_parse_addr_policy(directory_token_t *tok, unsigned fmt_flags)
3334 addr_policy_t newe;
3335 char *arg;
3337 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
3338 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
3340 if (tok->n_args != 1)
3341 return NULL;
3342 arg = tok->args[0];
3344 if (!strcmpstart(arg,"private"))
3345 return router_parse_addr_policy_private(tok);
3347 memset(&newe, 0, sizeof(newe));
3349 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3350 newe.policy_type = ADDR_POLICY_REJECT;
3351 else
3352 newe.policy_type = ADDR_POLICY_ACCEPT;
3354 if (tor_addr_parse_mask_ports(arg, fmt_flags, &newe.addr, &newe.maskbits,
3355 &newe.prt_min, &newe.prt_max) < 0) {
3356 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
3357 return NULL;
3360 return addr_policy_get_canonical_entry(&newe);
3363 /** Parse an exit policy line of the format "accept/reject private:...".
3364 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
3365 * router descriptors until earlier versions are obsolete.
3367 static addr_policy_t *
3368 router_parse_addr_policy_private(directory_token_t *tok)
3370 const char *arg;
3371 uint16_t port_min, port_max;
3372 addr_policy_t result;
3374 arg = tok->args[0];
3375 if (strcmpstart(arg, "private"))
3376 return NULL;
3378 arg += strlen("private");
3379 arg = (char*) eat_whitespace(arg);
3380 if (!arg || *arg != ':')
3381 return NULL;
3383 if (parse_port_range(arg+1, &port_min, &port_max)<0)
3384 return NULL;
3386 memset(&result, 0, sizeof(result));
3387 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3388 result.policy_type = ADDR_POLICY_REJECT;
3389 else
3390 result.policy_type = ADDR_POLICY_ACCEPT;
3391 result.is_private = 1;
3392 result.prt_min = port_min;
3393 result.prt_max = port_max;
3395 return addr_policy_get_canonical_entry(&result);
3398 /** Log and exit if <b>t</b> is malformed */
3399 void
3400 assert_addr_policy_ok(smartlist_t *lst)
3402 if (!lst) return;
3403 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
3404 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
3405 t->policy_type == ADDR_POLICY_ACCEPT);
3406 tor_assert(t->prt_min <= t->prt_max);
3411 * Low-level tokenizer for router descriptors and directories.
3414 /** Free all resources allocated for <b>tok</b> */
3415 static void
3416 token_clear(directory_token_t *tok)
3418 if (tok->key)
3419 crypto_pk_free(tok->key);
3422 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
3423 #define ALLOC(sz) memarea_alloc(area,sz)
3424 #define STRDUP(str) memarea_strdup(area,str)
3425 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
3427 #define RET_ERR(msg) \
3428 STMT_BEGIN \
3429 if (tok) token_clear(tok); \
3430 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
3431 tok->tp = ERR_; \
3432 tok->error = STRDUP(msg); \
3433 goto done_tokenizing; \
3434 STMT_END
3436 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
3437 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
3438 * Return <b>tok</b> on success, or a new ERR_ token if the token didn't
3439 * conform to the syntax we wanted.
3441 static INLINE directory_token_t *
3442 token_check_object(memarea_t *area, const char *kwd,
3443 directory_token_t *tok, obj_syntax o_syn)
3445 char ebuf[128];
3446 switch (o_syn) {
3447 case NO_OBJ:
3448 /* No object is allowed for this token. */
3449 if (tok->object_body) {
3450 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
3451 RET_ERR(ebuf);
3453 if (tok->key) {
3454 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
3455 RET_ERR(ebuf);
3457 break;
3458 case NEED_OBJ:
3459 /* There must be a (non-key) object. */
3460 if (!tok->object_body) {
3461 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
3462 RET_ERR(ebuf);
3464 break;
3465 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
3466 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
3467 if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) {
3468 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
3469 kwd, crypto_pk_num_bits(tok->key));
3470 RET_ERR(ebuf);
3472 /* fall through */
3473 case NEED_KEY: /* There must be some kind of key. */
3474 if (!tok->key) {
3475 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
3476 RET_ERR(ebuf);
3478 if (o_syn != NEED_SKEY_1024) {
3479 if (crypto_pk_key_is_private(tok->key)) {
3480 tor_snprintf(ebuf, sizeof(ebuf),
3481 "Private key given for %s, which wants a public key", kwd);
3482 RET_ERR(ebuf);
3484 } else { /* o_syn == NEED_SKEY_1024 */
3485 if (!crypto_pk_key_is_private(tok->key)) {
3486 tor_snprintf(ebuf, sizeof(ebuf),
3487 "Public key given for %s, which wants a private key", kwd);
3488 RET_ERR(ebuf);
3491 break;
3492 case OBJ_OK:
3493 /* Anything goes with this token. */
3494 break;
3497 done_tokenizing:
3498 return tok;
3501 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3502 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3503 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3504 * all storage in <b>area</b>. Return the number of arguments parsed, or
3505 * return -1 if there was an insanely high number of arguments. */
3506 static INLINE int
3507 get_token_arguments(memarea_t *area, directory_token_t *tok,
3508 const char *s, const char *eol)
3510 /** Largest number of arguments we'll accept to any token, ever. */
3511 #define MAX_ARGS 512
3512 char *mem = memarea_strndup(area, s, eol-s);
3513 char *cp = mem;
3514 int j = 0;
3515 char *args[MAX_ARGS];
3516 while (*cp) {
3517 if (j == MAX_ARGS)
3518 return -1;
3519 args[j++] = cp;
3520 cp = (char*)find_whitespace(cp);
3521 if (!cp || !*cp)
3522 break; /* End of the line. */
3523 *cp++ = '\0';
3524 cp = (char*)eat_whitespace(cp);
3526 tok->n_args = j;
3527 tok->args = memarea_memdup(area, args, j*sizeof(char*));
3528 return j;
3529 #undef MAX_ARGS
3532 /** Helper function: read the next token from *s, advance *s to the end of the
3533 * token, and return the parsed token. Parse *<b>s</b> according to the list
3534 * of tokens in <b>table</b>.
3536 static directory_token_t *
3537 get_next_token(memarea_t *area,
3538 const char **s, const char *eos, token_rule_t *table)
3540 /** Reject any object at least this big; it is probably an overflow, an
3541 * attack, a bug, or some other nonsense. */
3542 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
3543 /** Reject any line at least this big; it is probably an overflow, an
3544 * attack, a bug, or some other nonsense. */
3545 #define MAX_LINE_LENGTH (128*1024)
3547 const char *next, *eol, *obstart;
3548 size_t obname_len;
3549 int i;
3550 directory_token_t *tok;
3551 obj_syntax o_syn = NO_OBJ;
3552 char ebuf[128];
3553 const char *kwd = "";
3555 tor_assert(area);
3556 tok = ALLOC_ZERO(sizeof(directory_token_t));
3557 tok->tp = ERR_;
3559 /* Set *s to first token, eol to end-of-line, next to after first token */
3560 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
3561 tor_assert(eos >= *s);
3562 eol = memchr(*s, '\n', eos-*s);
3563 if (!eol)
3564 eol = eos;
3565 if (eol - *s > MAX_LINE_LENGTH) {
3566 RET_ERR("Line far too long");
3569 next = find_whitespace_eos(*s, eol);
3571 if (!strcmp_len(*s, "opt", next-*s)) {
3572 /* Skip past an "opt" at the start of the line. */
3573 *s = eat_whitespace_eos_no_nl(next, eol);
3574 next = find_whitespace_eos(*s, eol);
3575 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
3576 RET_ERR("Unexpected EOF");
3579 /* Search the table for the appropriate entry. (I tried a binary search
3580 * instead, but it wasn't any faster.) */
3581 for (i = 0; table[i].t ; ++i) {
3582 if (!strcmp_len(*s, table[i].t, next-*s)) {
3583 /* We've found the keyword. */
3584 kwd = table[i].t;
3585 tok->tp = table[i].v;
3586 o_syn = table[i].os;
3587 *s = eat_whitespace_eos_no_nl(next, eol);
3588 /* We go ahead whether there are arguments or not, so that tok->args is
3589 * always set if we want arguments. */
3590 if (table[i].concat_args) {
3591 /* The keyword takes the line as a single argument */
3592 tok->args = ALLOC(sizeof(char*));
3593 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3594 tok->n_args = 1;
3595 } else {
3596 /* This keyword takes multiple arguments. */
3597 if (get_token_arguments(area, tok, *s, eol)<0) {
3598 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3599 RET_ERR(ebuf);
3601 *s = eol;
3603 if (tok->n_args < table[i].min_args) {
3604 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3605 RET_ERR(ebuf);
3606 } else if (tok->n_args > table[i].max_args) {
3607 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3608 RET_ERR(ebuf);
3610 break;
3614 if (tok->tp == ERR_) {
3615 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3616 if (**s == '@')
3617 tok->tp = A_UNKNOWN_;
3618 else
3619 tok->tp = K_OPT;
3620 tok->args = ALLOC(sizeof(char*));
3621 tok->args[0] = STRNDUP(*s, eol-*s);
3622 tok->n_args = 1;
3623 o_syn = OBJ_OK;
3626 /* Check whether there's an object present */
3627 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3628 tor_assert(eos >= *s);
3629 eol = memchr(*s, '\n', eos-*s);
3630 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3631 goto check_object;
3633 obstart = *s; /* Set obstart to start of object spec */
3634 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3635 strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
3636 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
3637 RET_ERR("Malformed object: bad begin line");
3639 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3640 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3641 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3643 /* Go to the end of the object */
3644 next = tor_memstr(*s, eos-*s, "-----END ");
3645 if (!next) {
3646 RET_ERR("Malformed object: missing object end line");
3648 tor_assert(eos >= next);
3649 eol = memchr(next, '\n', eos-next);
3650 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3651 eol = eos;
3652 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3653 if ((size_t)(eol-next) != 9+obname_len+5 ||
3654 strcmp_len(next+9, tok->object_type, obname_len) ||
3655 strcmp_len(eol-5, "-----", 5)) {
3656 tor_snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3657 tok->object_type);
3658 ebuf[sizeof(ebuf)-1] = '\0';
3659 RET_ERR(ebuf);
3661 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
3662 RET_ERR("Couldn't parse object: missing footer or object much too big.");
3664 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3665 tok->key = crypto_pk_new();
3666 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3667 RET_ERR("Couldn't parse public key.");
3668 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3669 tok->key = crypto_pk_new();
3670 if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
3671 RET_ERR("Couldn't parse private key.");
3672 } else { /* If it's something else, try to base64-decode it */
3673 int r;
3674 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3675 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3676 if (r<0)
3677 RET_ERR("Malformed object: bad base64-encoded data");
3678 tok->object_size = r;
3680 *s = eol;
3682 check_object:
3683 tok = token_check_object(area, kwd, tok, o_syn);
3685 done_tokenizing:
3686 return tok;
3688 #undef RET_ERR
3689 #undef ALLOC
3690 #undef ALLOC_ZERO
3691 #undef STRDUP
3692 #undef STRNDUP
3695 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3696 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3697 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3698 * entire string.
3700 static int
3701 tokenize_string(memarea_t *area,
3702 const char *start, const char *end, smartlist_t *out,
3703 token_rule_t *table, int flags)
3705 const char **s;
3706 directory_token_t *tok = NULL;
3707 int counts[NIL_];
3708 int i;
3709 int first_nonannotation;
3710 int prev_len = smartlist_len(out);
3711 tor_assert(area);
3713 s = &start;
3714 if (!end) {
3715 end = start+strlen(start);
3716 } else {
3717 /* it's only meaningful to check for nuls if we got an end-of-string ptr */
3718 if (memchr(start, '\0', end-start)) {
3719 log_warn(LD_DIR, "parse error: internal NUL character.");
3720 return -1;
3723 for (i = 0; i < NIL_; ++i)
3724 counts[i] = 0;
3726 SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]);
3728 while (*s < end && (!tok || tok->tp != EOF_)) {
3729 tok = get_next_token(area, s, end, table);
3730 if (tok->tp == ERR_) {
3731 log_warn(LD_DIR, "parse error: %s", tok->error);
3732 token_clear(tok);
3733 return -1;
3735 ++counts[tok->tp];
3736 smartlist_add(out, tok);
3737 *s = eat_whitespace_eos(*s, end);
3740 if (flags & TS_NOCHECK)
3741 return 0;
3743 if ((flags & TS_ANNOTATIONS_OK)) {
3744 first_nonannotation = -1;
3745 for (i = 0; i < smartlist_len(out); ++i) {
3746 tok = smartlist_get(out, i);
3747 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
3748 first_nonannotation = i;
3749 break;
3752 if (first_nonannotation < 0) {
3753 log_warn(LD_DIR, "parse error: item contains only annotations");
3754 return -1;
3756 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
3757 tok = smartlist_get(out, i);
3758 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3759 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
3760 return -1;
3763 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
3764 if (first_nonannotation != prev_len) {
3765 log_warn(LD_DIR, "parse error: Unexpected annotations.");
3766 return -1;
3769 } else {
3770 for (i=0; i < smartlist_len(out); ++i) {
3771 tok = smartlist_get(out, i);
3772 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3773 log_warn(LD_DIR, "parse error: no annotations allowed.");
3774 return -1;
3777 first_nonannotation = 0;
3779 for (i = 0; table[i].t; ++i) {
3780 if (counts[table[i].v] < table[i].min_cnt) {
3781 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
3782 return -1;
3784 if (counts[table[i].v] > table[i].max_cnt) {
3785 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
3786 return -1;
3788 if (table[i].pos & AT_START) {
3789 if (smartlist_len(out) < 1 ||
3790 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
3791 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
3792 return -1;
3795 if (table[i].pos & AT_END) {
3796 if (smartlist_len(out) < 1 ||
3797 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
3798 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
3799 return -1;
3803 return 0;
3806 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3807 * NULL if no such keyword is found.
3809 static directory_token_t *
3810 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
3812 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
3813 return NULL;
3816 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3817 * with an assert if no such keyword is found.
3819 static directory_token_t *
3820 find_by_keyword_(smartlist_t *s, directory_keyword keyword,
3821 const char *keyword_as_string)
3823 directory_token_t *tok = find_opt_by_keyword(s, keyword);
3824 if (PREDICT_UNLIKELY(!tok)) {
3825 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
3826 "been validated. Internal error.", keyword_as_string, (int)keyword);
3827 tor_assert(tok);
3829 return tok;
3832 /** If there are any directory_token_t entries in <b>s</b> whose keyword is
3833 * <b>k</b>, return a newly allocated smartlist_t containing all such entries,
3834 * in the same order in which they occur in <b>s</b>. Otherwise return
3835 * NULL. */
3836 static smartlist_t *
3837 find_all_by_keyword(smartlist_t *s, directory_keyword k)
3839 smartlist_t *out = NULL;
3840 SMARTLIST_FOREACH(s, directory_token_t *, t,
3841 if (t->tp == k) {
3842 if (!out)
3843 out = smartlist_new();
3844 smartlist_add(out, t);
3846 return out;
3849 /** Return a newly allocated smartlist of all accept or reject tokens in
3850 * <b>s</b>.
3852 static smartlist_t *
3853 find_all_exitpolicy(smartlist_t *s)
3855 smartlist_t *out = smartlist_new();
3856 SMARTLIST_FOREACH(s, directory_token_t *, t,
3857 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
3858 t->tp == K_REJECT || t->tp == K_REJECT6)
3859 smartlist_add(out,t));
3860 return out;
3863 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
3864 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
3865 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
3866 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
3868 * Return 0 on success and -1 on failure.
3870 static int
3871 router_get_hash_impl_helper(const char *s, size_t s_len,
3872 const char *start_str,
3873 const char *end_str, char end_c,
3874 const char **start_out, const char **end_out)
3876 const char *start, *end;
3877 start = tor_memstr(s, s_len, start_str);
3878 if (!start) {
3879 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
3880 return -1;
3882 if (start != s && *(start-1) != '\n') {
3883 log_warn(LD_DIR,
3884 "first occurrence of \"%s\" is not at the start of a line",
3885 start_str);
3886 return -1;
3888 end = tor_memstr(start+strlen(start_str),
3889 s_len - (start-s) - strlen(start_str), end_str);
3890 if (!end) {
3891 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
3892 return -1;
3894 end = memchr(end+strlen(end_str), end_c, s_len - (end-s) - strlen(end_str));
3895 if (!end) {
3896 log_warn(LD_DIR,"couldn't find EOL");
3897 return -1;
3899 ++end;
3901 *start_out = start;
3902 *end_out = end;
3903 return 0;
3906 /** Compute the digest of the substring of <b>s</b> taken from the first
3907 * occurrence of <b>start_str</b> through the first instance of c after the
3908 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
3909 * result in <b>digest</b>; return 0 on success.
3911 * If no such substring exists, return -1.
3913 static int
3914 router_get_hash_impl(const char *s, size_t s_len, char *digest,
3915 const char *start_str,
3916 const char *end_str, char end_c,
3917 digest_algorithm_t alg)
3919 const char *start=NULL, *end=NULL;
3920 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
3921 &start,&end)<0)
3922 return -1;
3924 if (alg == DIGEST_SHA1) {
3925 if (crypto_digest(digest, start, end-start)) {
3926 log_warn(LD_BUG,"couldn't compute digest");
3927 return -1;
3929 } else {
3930 if (crypto_digest256(digest, start, end-start, alg)) {
3931 log_warn(LD_BUG,"couldn't compute digest");
3932 return -1;
3936 return 0;
3939 /** As router_get_hash_impl, but compute all hashes. */
3940 static int
3941 router_get_hashes_impl(const char *s, size_t s_len, digests_t *digests,
3942 const char *start_str,
3943 const char *end_str, char end_c)
3945 const char *start=NULL, *end=NULL;
3946 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
3947 &start,&end)<0)
3948 return -1;
3950 if (crypto_digest_all(digests, start, end-start)) {
3951 log_warn(LD_BUG,"couldn't compute digests");
3952 return -1;
3955 return 0;
3958 /** Assuming that s starts with a microdesc, return the start of the
3959 * *NEXT* one. Return NULL on "not found." */
3960 static const char *
3961 find_start_of_next_microdesc(const char *s, const char *eos)
3963 int started_with_annotations;
3964 s = eat_whitespace_eos(s, eos);
3965 if (!s)
3966 return NULL;
3968 #define CHECK_LENGTH() STMT_BEGIN \
3969 if (s+32 > eos) \
3970 return NULL; \
3971 STMT_END
3973 #define NEXT_LINE() STMT_BEGIN \
3974 s = memchr(s, '\n', eos-s); \
3975 if (!s || s+1 >= eos) \
3976 return NULL; \
3977 s++; \
3978 STMT_END
3980 CHECK_LENGTH();
3982 started_with_annotations = (*s == '@');
3984 if (started_with_annotations) {
3985 /* Start by advancing to the first non-annotation line. */
3986 while (*s == '@')
3987 NEXT_LINE();
3989 CHECK_LENGTH();
3991 /* Now we should be pointed at an onion-key line. If we are, then skip
3992 * it. */
3993 if (!strcmpstart(s, "onion-key"))
3994 NEXT_LINE();
3996 /* Okay, now we're pointed at the first line of the microdescriptor which is
3997 not an annotation or onion-key. The next line that _is_ an annotation or
3998 onion-key is the start of the next microdescriptor. */
3999 while (s+32 < eos) {
4000 if (*s == '@' || !strcmpstart(s, "onion-key"))
4001 return s;
4002 NEXT_LINE();
4004 return NULL;
4006 #undef CHECK_LENGTH
4007 #undef NEXT_LINE
4010 /** Parse as many microdescriptors as are found from the string starting at
4011 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4012 * annotations we recognize and ignore ones we don't.
4014 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
4015 * descriptor in the body field of each microdesc_t.
4017 * Return all newly
4018 * parsed microdescriptors in a newly allocated smartlist_t. */
4019 smartlist_t *
4020 microdescs_parse_from_string(const char *s, const char *eos,
4021 int allow_annotations,
4022 saved_location_t where)
4024 smartlist_t *tokens;
4025 smartlist_t *result;
4026 microdesc_t *md = NULL;
4027 memarea_t *area;
4028 const char *start = s;
4029 const char *start_of_next_microdesc;
4030 int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0;
4031 const int copy_body = (where != SAVED_IN_CACHE);
4033 directory_token_t *tok;
4035 if (!eos)
4036 eos = s + strlen(s);
4038 s = eat_whitespace_eos(s, eos);
4039 area = memarea_new();
4040 result = smartlist_new();
4041 tokens = smartlist_new();
4043 while (s < eos) {
4044 start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
4045 if (!start_of_next_microdesc)
4046 start_of_next_microdesc = eos;
4048 if (tokenize_string(area, s, start_of_next_microdesc, tokens,
4049 microdesc_token_table, flags)) {
4050 log_warn(LD_DIR, "Unparseable microdescriptor");
4051 goto next;
4054 md = tor_malloc_zero(sizeof(microdesc_t));
4056 const char *cp = tor_memstr(s, start_of_next_microdesc-s,
4057 "onion-key");
4058 tor_assert(cp);
4060 md->bodylen = start_of_next_microdesc - cp;
4061 md->saved_location = where;
4062 if (copy_body)
4063 md->body = tor_memdup_nulterm(cp, md->bodylen);
4064 else
4065 md->body = (char*)cp;
4066 md->off = cp - start;
4069 if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
4070 if (parse_iso_time(tok->args[0], &md->last_listed)) {
4071 log_warn(LD_DIR, "Bad last-listed time in microdescriptor");
4072 goto next;
4076 tok = find_by_keyword(tokens, K_ONION_KEY);
4077 if (!crypto_pk_public_exponent_ok(tok->key)) {
4078 log_warn(LD_DIR,
4079 "Relay's onion key had invalid exponent.");
4080 goto next;
4082 md->onion_pkey = tok->key;
4083 tok->key = NULL;
4085 if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) {
4086 curve25519_public_key_t k;
4087 tor_assert(tok->n_args >= 1);
4088 if (curve25519_public_from_base64(&k, tok->args[0]) < 0) {
4089 log_warn(LD_DIR, "Bogus ntor-onion-key in microdesc");
4090 goto next;
4092 md->onion_curve25519_pkey =
4093 tor_memdup(&k, sizeof(curve25519_public_key_t));
4097 smartlist_t *a_lines = find_all_by_keyword(tokens, K_A);
4098 if (a_lines) {
4099 find_single_ipv6_orport(a_lines, &md->ipv6_addr, &md->ipv6_orport);
4100 smartlist_free(a_lines);
4104 if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
4105 int i;
4106 md->family = smartlist_new();
4107 for (i=0;i<tok->n_args;++i) {
4108 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
4109 log_warn(LD_DIR, "Illegal nickname %s in family line",
4110 escaped(tok->args[i]));
4111 goto next;
4113 smartlist_add(md->family, tor_strdup(tok->args[i]));
4117 if ((tok = find_opt_by_keyword(tokens, K_P))) {
4118 md->exit_policy = parse_short_policy(tok->args[0]);
4120 if ((tok = find_opt_by_keyword(tokens, K_P6))) {
4121 md->ipv6_exit_policy = parse_short_policy(tok->args[0]);
4124 crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
4126 smartlist_add(result, md);
4128 md = NULL;
4129 next:
4130 microdesc_free(md);
4131 md = NULL;
4133 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4134 memarea_clear(area);
4135 smartlist_clear(tokens);
4136 s = start_of_next_microdesc;
4139 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4140 memarea_drop_all(area);
4141 smartlist_free(tokens);
4143 return result;
4146 /** Return true iff this Tor version can answer directory questions
4147 * about microdescriptors. */
4149 tor_version_supports_microdescriptors(const char *platform)
4151 return tor_version_as_new_as(platform, "0.2.3.1-alpha");
4154 /** Parse the Tor version of the platform string <b>platform</b>,
4155 * and compare it to the version in <b>cutoff</b>. Return 1 if
4156 * the router is at least as new as the cutoff, else return 0.
4159 tor_version_as_new_as(const char *platform, const char *cutoff)
4161 tor_version_t cutoff_version, router_version;
4162 char *s, *s2, *start;
4163 char tmp[128];
4165 tor_assert(platform);
4167 if (tor_version_parse(cutoff, &cutoff_version)<0) {
4168 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
4169 return 0;
4171 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
4172 return 1;
4174 start = (char *)eat_whitespace(platform+3);
4175 if (!*start) return 0;
4176 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
4177 s2 = (char*)eat_whitespace(s);
4178 if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
4179 s = (char*)find_whitespace(s2);
4181 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
4182 return 0;
4183 strlcpy(tmp, start, s-start+1);
4185 if (tor_version_parse(tmp, &router_version)<0) {
4186 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
4187 return 1; /* be safe and say yes */
4190 /* Here's why we don't need to do any special handling for svn revisions:
4191 * - If neither has an svn revision, we're fine.
4192 * - If the router doesn't have an svn revision, we can't assume that it
4193 * is "at least" any svn revision, so we need to return 0.
4194 * - If the target version doesn't have an svn revision, any svn revision
4195 * (or none at all) is good enough, so return 1.
4196 * - If both target and router have an svn revision, we compare them.
4199 return tor_version_compare(&router_version, &cutoff_version) >= 0;
4202 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4203 * Return 0 on success, -1 on failure. */
4205 tor_version_parse(const char *s, tor_version_t *out)
4207 char *eos=NULL;
4208 const char *cp=NULL;
4209 /* Format is:
4210 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
4212 tor_assert(s);
4213 tor_assert(out);
4215 memset(out, 0, sizeof(tor_version_t));
4217 if (!strcasecmpstart(s, "Tor "))
4218 s += 4;
4220 /* Get major. */
4221 out->major = (int)strtol(s,&eos,10);
4222 if (!eos || eos==s || *eos != '.') return -1;
4223 cp = eos+1;
4225 /* Get minor */
4226 out->minor = (int) strtol(cp,&eos,10);
4227 if (!eos || eos==cp || *eos != '.') return -1;
4228 cp = eos+1;
4230 /* Get micro */
4231 out->micro = (int) strtol(cp,&eos,10);
4232 if (!eos || eos==cp) return -1;
4233 if (!*eos) {
4234 out->status = VER_RELEASE;
4235 out->patchlevel = 0;
4236 return 0;
4238 cp = eos;
4240 /* Get status */
4241 if (*cp == '.') {
4242 out->status = VER_RELEASE;
4243 ++cp;
4244 } else if (0==strncmp(cp, "pre", 3)) {
4245 out->status = VER_PRE;
4246 cp += 3;
4247 } else if (0==strncmp(cp, "rc", 2)) {
4248 out->status = VER_RC;
4249 cp += 2;
4250 } else {
4251 return -1;
4254 /* Get patchlevel */
4255 out->patchlevel = (int) strtol(cp,&eos,10);
4256 if (!eos || eos==cp) return -1;
4257 cp = eos;
4259 /* Get status tag. */
4260 if (*cp == '-' || *cp == '.')
4261 ++cp;
4262 eos = (char*) find_whitespace(cp);
4263 if (eos-cp >= (int)sizeof(out->status_tag))
4264 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
4265 else {
4266 memcpy(out->status_tag, cp, eos-cp);
4267 out->status_tag[eos-cp] = 0;
4269 cp = eat_whitespace(eos);
4271 if (!strcmpstart(cp, "(r")) {
4272 cp += 2;
4273 out->svn_revision = (int) strtol(cp,&eos,10);
4274 } else if (!strcmpstart(cp, "(git-")) {
4275 char *close_paren = strchr(cp, ')');
4276 int hexlen;
4277 char digest[DIGEST_LEN];
4278 if (! close_paren)
4279 return -1;
4280 cp += 5;
4281 if (close_paren-cp > HEX_DIGEST_LEN)
4282 return -1;
4283 hexlen = (int)(close_paren-cp);
4284 memwipe(digest, 0, sizeof(digest));
4285 if ( hexlen == 0 || (hexlen % 2) == 1)
4286 return -1;
4287 if (base16_decode(digest, hexlen/2, cp, hexlen))
4288 return -1;
4289 memcpy(out->git_tag, digest, hexlen/2);
4290 out->git_tag_len = hexlen/2;
4293 return 0;
4296 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
4297 * b. */
4299 tor_version_compare(tor_version_t *a, tor_version_t *b)
4301 int i;
4302 tor_assert(a);
4303 tor_assert(b);
4304 if ((i = a->major - b->major))
4305 return i;
4306 else if ((i = a->minor - b->minor))
4307 return i;
4308 else if ((i = a->micro - b->micro))
4309 return i;
4310 else if ((i = a->status - b->status))
4311 return i;
4312 else if ((i = a->patchlevel - b->patchlevel))
4313 return i;
4314 else if ((i = strcmp(a->status_tag, b->status_tag)))
4315 return i;
4316 else if ((i = a->svn_revision - b->svn_revision))
4317 return i;
4318 else if ((i = a->git_tag_len - b->git_tag_len))
4319 return i;
4320 else if (a->git_tag_len)
4321 return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len);
4322 else
4323 return 0;
4326 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
4329 tor_version_same_series(tor_version_t *a, tor_version_t *b)
4331 tor_assert(a);
4332 tor_assert(b);
4333 return ((a->major == b->major) &&
4334 (a->minor == b->minor) &&
4335 (a->micro == b->micro));
4338 /** Helper: Given pointers to two strings describing tor versions, return -1
4339 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
4340 * Used to sort a list of versions. */
4341 static int
4342 compare_tor_version_str_ptr_(const void **_a, const void **_b)
4344 const char *a = *_a, *b = *_b;
4345 int ca, cb;
4346 tor_version_t va, vb;
4347 ca = tor_version_parse(a, &va);
4348 cb = tor_version_parse(b, &vb);
4349 /* If they both parse, compare them. */
4350 if (!ca && !cb)
4351 return tor_version_compare(&va,&vb);
4352 /* If one parses, it comes first. */
4353 if (!ca && cb)
4354 return -1;
4355 if (ca && !cb)
4356 return 1;
4357 /* If neither parses, compare strings. Also, the directory server admin
4358 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
4359 return strcmp(a,b);
4362 /** Sort a list of string-representations of versions in ascending order. */
4363 void
4364 sort_version_list(smartlist_t *versions, int remove_duplicates)
4366 smartlist_sort(versions, compare_tor_version_str_ptr_);
4368 if (remove_duplicates)
4369 smartlist_uniq(versions, compare_tor_version_str_ptr_, tor_free_);
4372 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
4373 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
4374 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
4375 * encrypted introduction points to the newly allocated
4376 * *<b>intro_points_encrypted_out</b>, their encrypted size to
4377 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
4378 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
4379 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
4380 * and -1 for failure.
4383 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
4384 char *desc_id_out,
4385 char **intro_points_encrypted_out,
4386 size_t *intro_points_encrypted_size_out,
4387 size_t *encoded_size_out,
4388 const char **next_out, const char *desc)
4390 rend_service_descriptor_t *result =
4391 tor_malloc_zero(sizeof(rend_service_descriptor_t));
4392 char desc_hash[DIGEST_LEN];
4393 const char *eos;
4394 smartlist_t *tokens = smartlist_new();
4395 directory_token_t *tok;
4396 char secret_id_part[DIGEST_LEN];
4397 int i, version, num_ok=1;
4398 smartlist_t *versions;
4399 char public_key_hash[DIGEST_LEN];
4400 char test_desc_id[DIGEST_LEN];
4401 memarea_t *area = NULL;
4402 tor_assert(desc);
4403 /* Check if desc starts correctly. */
4404 if (strncmp(desc, "rendezvous-service-descriptor ",
4405 strlen("rendezvous-service-descriptor "))) {
4406 log_info(LD_REND, "Descriptor does not start correctly.");
4407 goto err;
4409 /* Compute descriptor hash for later validation. */
4410 if (router_get_hash_impl(desc, strlen(desc), desc_hash,
4411 "rendezvous-service-descriptor ",
4412 "\nsignature", '\n', DIGEST_SHA1) < 0) {
4413 log_warn(LD_REND, "Couldn't compute descriptor hash.");
4414 goto err;
4416 /* Determine end of string. */
4417 eos = strstr(desc, "\nrendezvous-service-descriptor ");
4418 if (!eos)
4419 eos = desc + strlen(desc);
4420 else
4421 eos = eos + 1;
4422 /* Check length. */
4423 if (eos-desc > REND_DESC_MAX_SIZE) {
4424 /* XXX023 If we are parsing this descriptor as a server, this
4425 * should be a protocol warning. */
4426 log_warn(LD_REND, "Descriptor length is %d which exceeds "
4427 "maximum rendezvous descriptor size of %d bytes.",
4428 (int)(eos-desc), REND_DESC_MAX_SIZE);
4429 goto err;
4431 /* Tokenize descriptor. */
4432 area = memarea_new();
4433 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
4434 log_warn(LD_REND, "Error tokenizing descriptor.");
4435 goto err;
4437 /* Set next to next descriptor, if available. */
4438 *next_out = eos;
4439 /* Set length of encoded descriptor. */
4440 *encoded_size_out = eos - desc;
4441 /* Check min allowed length of token list. */
4442 if (smartlist_len(tokens) < 7) {
4443 log_warn(LD_REND, "Impossibly short descriptor.");
4444 goto err;
4446 /* Parse base32-encoded descriptor ID. */
4447 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
4448 tor_assert(tok == smartlist_get(tokens, 0));
4449 tor_assert(tok->n_args == 1);
4450 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
4451 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
4452 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
4453 goto err;
4455 if (base32_decode(desc_id_out, DIGEST_LEN,
4456 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
4457 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
4458 tok->args[0]);
4459 goto err;
4461 /* Parse descriptor version. */
4462 tok = find_by_keyword(tokens, R_VERSION);
4463 tor_assert(tok->n_args == 1);
4464 result->version =
4465 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
4466 if (result->version != 2 || !num_ok) {
4467 /* If it's <2, it shouldn't be under this format. If the number
4468 * is greater than 2, we bumped it because we broke backward
4469 * compatibility. See how version numbers in our other formats
4470 * work. */
4471 log_warn(LD_REND, "Unrecognized descriptor version: %s",
4472 escaped(tok->args[0]));
4473 goto err;
4475 /* Parse public key. */
4476 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
4477 result->pk = tok->key;
4478 tok->key = NULL; /* Prevent free */
4479 /* Parse secret ID part. */
4480 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
4481 tor_assert(tok->n_args == 1);
4482 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
4483 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
4484 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
4485 goto err;
4487 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
4488 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
4489 tok->args[0]);
4490 goto err;
4492 /* Parse publication time -- up-to-date check is done when storing the
4493 * descriptor. */
4494 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
4495 tor_assert(tok->n_args == 1);
4496 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
4497 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
4498 goto err;
4500 /* Parse protocol versions. */
4501 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
4502 tor_assert(tok->n_args == 1);
4503 versions = smartlist_new();
4504 smartlist_split_string(versions, tok->args[0], ",",
4505 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
4506 for (i = 0; i < smartlist_len(versions); i++) {
4507 version = (int) tor_parse_long(smartlist_get(versions, i),
4508 10, 0, INT_MAX, &num_ok, NULL);
4509 if (!num_ok) /* It's a string; let's ignore it. */
4510 continue;
4511 if (version >= REND_PROTOCOL_VERSION_BITMASK_WIDTH)
4512 /* Avoid undefined left-shift behaviour. */
4513 continue;
4514 result->protocols |= 1 << version;
4516 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
4517 smartlist_free(versions);
4518 /* Parse encrypted introduction points. Don't verify. */
4519 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
4520 if (tok) {
4521 if (strcmp(tok->object_type, "MESSAGE")) {
4522 log_warn(LD_DIR, "Bad object type: introduction points should be of "
4523 "type MESSAGE");
4524 goto err;
4526 *intro_points_encrypted_out = tor_memdup(tok->object_body,
4527 tok->object_size);
4528 *intro_points_encrypted_size_out = tok->object_size;
4529 } else {
4530 *intro_points_encrypted_out = NULL;
4531 *intro_points_encrypted_size_out = 0;
4533 /* Parse and verify signature. */
4534 tok = find_by_keyword(tokens, R_SIGNATURE);
4535 note_crypto_pk_op(VERIFY_RTR);
4536 if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
4537 "v2 rendezvous service descriptor") < 0)
4538 goto err;
4539 /* Verify that descriptor ID belongs to public key and secret ID part. */
4540 crypto_pk_get_digest(result->pk, public_key_hash);
4541 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
4542 secret_id_part);
4543 if (tor_memneq(desc_id_out, test_desc_id, DIGEST_LEN)) {
4544 log_warn(LD_REND, "Parsed descriptor ID does not match "
4545 "computed descriptor ID.");
4546 goto err;
4548 goto done;
4549 err:
4550 rend_service_descriptor_free(result);
4551 result = NULL;
4552 done:
4553 if (tokens) {
4554 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4555 smartlist_free(tokens);
4557 if (area)
4558 memarea_drop_all(area);
4559 *parsed_out = result;
4560 if (result)
4561 return 0;
4562 return -1;
4565 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
4566 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
4567 * write the result to a newly allocated string that is pointed to by
4568 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
4569 * Return 0 if decryption was successful and -1 otherwise. */
4571 rend_decrypt_introduction_points(char **ipos_decrypted,
4572 size_t *ipos_decrypted_size,
4573 const char *descriptor_cookie,
4574 const char *ipos_encrypted,
4575 size_t ipos_encrypted_size)
4577 tor_assert(ipos_encrypted);
4578 tor_assert(descriptor_cookie);
4579 if (ipos_encrypted_size < 2) {
4580 log_warn(LD_REND, "Size of encrypted introduction points is too "
4581 "small.");
4582 return -1;
4584 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
4585 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
4586 session_key[CIPHER_KEY_LEN], *dec;
4587 int declen, client_blocks;
4588 size_t pos = 0, len, client_entries_len;
4589 crypto_digest_t *digest;
4590 crypto_cipher_t *cipher;
4591 client_blocks = (int) ipos_encrypted[1];
4592 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
4593 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
4594 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
4595 log_warn(LD_REND, "Size of encrypted introduction points is too "
4596 "small.");
4597 return -1;
4599 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
4600 digest = crypto_digest_new();
4601 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
4602 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
4603 crypto_digest_get_digest(digest, client_id,
4604 REND_BASIC_AUTH_CLIENT_ID_LEN);
4605 crypto_digest_free(digest);
4606 for (pos = 2; pos < 2 + client_entries_len;
4607 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
4608 if (tor_memeq(ipos_encrypted + pos, client_id,
4609 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
4610 /* Attempt to decrypt introduction points. */
4611 cipher = crypto_cipher_new(descriptor_cookie);
4612 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
4613 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
4614 CIPHER_KEY_LEN) < 0) {
4615 log_warn(LD_REND, "Could not decrypt session key for client.");
4616 crypto_cipher_free(cipher);
4617 return -1;
4619 crypto_cipher_free(cipher);
4621 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
4622 dec = tor_malloc(len);
4623 declen = crypto_cipher_decrypt_with_iv(session_key, dec, len,
4624 ipos_encrypted + 2 + client_entries_len,
4625 ipos_encrypted_size - 2 - client_entries_len);
4627 if (declen < 0) {
4628 log_warn(LD_REND, "Could not decrypt introduction point string.");
4629 tor_free(dec);
4630 return -1;
4632 if (fast_memcmpstart(dec, declen, "introduction-point ")) {
4633 log_warn(LD_REND, "Decrypted introduction points don't "
4634 "look like we could parse them.");
4635 tor_free(dec);
4636 continue;
4638 *ipos_decrypted = dec;
4639 *ipos_decrypted_size = declen;
4640 return 0;
4643 log_warn(LD_REND, "Could not decrypt introduction points. Please "
4644 "check your authorization for this service!");
4645 return -1;
4646 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
4647 char *dec;
4648 int declen;
4649 if (ipos_encrypted_size < CIPHER_IV_LEN + 2) {
4650 log_warn(LD_REND, "Size of encrypted introduction points is too "
4651 "small.");
4652 return -1;
4654 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
4656 declen = crypto_cipher_decrypt_with_iv(descriptor_cookie, dec,
4657 ipos_encrypted_size -
4658 CIPHER_IV_LEN - 1,
4659 ipos_encrypted + 1,
4660 ipos_encrypted_size - 1);
4662 if (declen < 0) {
4663 log_warn(LD_REND, "Decrypting introduction points failed!");
4664 tor_free(dec);
4665 return -1;
4667 *ipos_decrypted = dec;
4668 *ipos_decrypted_size = declen;
4669 return 0;
4670 } else {
4671 log_warn(LD_REND, "Unknown authorization type number: %d",
4672 ipos_encrypted[0]);
4673 return -1;
4677 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
4678 * length <b>intro_points_encoded_size</b> and write the result to the
4679 * descriptor in <b>parsed</b>; return the number of successfully parsed
4680 * introduction points or -1 in case of a failure. */
4682 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
4683 const char *intro_points_encoded,
4684 size_t intro_points_encoded_size)
4686 const char *current_ipo, *end_of_intro_points;
4687 smartlist_t *tokens;
4688 directory_token_t *tok;
4689 rend_intro_point_t *intro;
4690 extend_info_t *info;
4691 int result, num_ok=1;
4692 memarea_t *area = NULL;
4693 tor_assert(parsed);
4694 /** Function may only be invoked once. */
4695 tor_assert(!parsed->intro_nodes);
4696 tor_assert(intro_points_encoded);
4697 tor_assert(intro_points_encoded_size > 0);
4698 /* Consider one intro point after the other. */
4699 current_ipo = intro_points_encoded;
4700 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
4701 tokens = smartlist_new();
4702 parsed->intro_nodes = smartlist_new();
4703 area = memarea_new();
4705 while (!fast_memcmpstart(current_ipo, end_of_intro_points-current_ipo,
4706 "introduction-point ")) {
4707 /* Determine end of string. */
4708 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
4709 "\nintroduction-point ");
4710 if (!eos)
4711 eos = end_of_intro_points;
4712 else
4713 eos = eos+1;
4714 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
4715 /* Free tokens and clear token list. */
4716 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4717 smartlist_clear(tokens);
4718 memarea_clear(area);
4719 /* Tokenize string. */
4720 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
4721 log_warn(LD_REND, "Error tokenizing introduction point");
4722 goto err;
4724 /* Advance to next introduction point, if available. */
4725 current_ipo = eos;
4726 /* Check minimum allowed length of introduction point. */
4727 if (smartlist_len(tokens) < 5) {
4728 log_warn(LD_REND, "Impossibly short introduction point.");
4729 goto err;
4731 /* Allocate new intro point and extend info. */
4732 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
4733 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
4734 /* Parse identifier. */
4735 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
4736 if (base32_decode(info->identity_digest, DIGEST_LEN,
4737 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
4738 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
4739 tok->args[0]);
4740 rend_intro_point_free(intro);
4741 goto err;
4743 /* Write identifier to nickname. */
4744 info->nickname[0] = '$';
4745 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
4746 info->identity_digest, DIGEST_LEN);
4747 /* Parse IP address. */
4748 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
4749 if (tor_addr_parse(&info->addr, tok->args[0])<0) {
4750 log_warn(LD_REND, "Could not parse introduction point address.");
4751 rend_intro_point_free(intro);
4752 goto err;
4754 if (tor_addr_family(&info->addr) != AF_INET) {
4755 log_warn(LD_REND, "Introduction point address was not ipv4.");
4756 rend_intro_point_free(intro);
4757 goto err;
4760 /* Parse onion port. */
4761 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
4762 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
4763 &num_ok,NULL);
4764 if (!info->port || !num_ok) {
4765 log_warn(LD_REND, "Introduction point onion port %s is invalid",
4766 escaped(tok->args[0]));
4767 rend_intro_point_free(intro);
4768 goto err;
4770 /* Parse onion key. */
4771 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
4772 if (!crypto_pk_public_exponent_ok(tok->key)) {
4773 log_warn(LD_REND,
4774 "Introduction point's onion key had invalid exponent.");
4775 rend_intro_point_free(intro);
4776 goto err;
4778 info->onion_key = tok->key;
4779 tok->key = NULL; /* Prevent free */
4780 /* Parse service key. */
4781 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
4782 if (!crypto_pk_public_exponent_ok(tok->key)) {
4783 log_warn(LD_REND,
4784 "Introduction point key had invalid exponent.");
4785 rend_intro_point_free(intro);
4786 goto err;
4788 intro->intro_key = tok->key;
4789 tok->key = NULL; /* Prevent free */
4790 /* Add extend info to list of introduction points. */
4791 smartlist_add(parsed->intro_nodes, intro);
4793 result = smartlist_len(parsed->intro_nodes);
4794 goto done;
4796 err:
4797 result = -1;
4799 done:
4800 /* Free tokens and clear token list. */
4801 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4802 smartlist_free(tokens);
4803 if (area)
4804 memarea_drop_all(area);
4806 return result;
4809 /** Parse the content of a client_key file in <b>ckstr</b> and add
4810 * rend_authorized_client_t's for each parsed client to
4811 * <b>parsed_clients</b>. Return the number of parsed clients as result
4812 * or -1 for failure. */
4814 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
4816 int result = -1;
4817 smartlist_t *tokens;
4818 directory_token_t *tok;
4819 const char *current_entry = NULL;
4820 memarea_t *area = NULL;
4821 if (!ckstr || strlen(ckstr) == 0)
4822 return -1;
4823 tokens = smartlist_new();
4824 /* Begin parsing with first entry, skipping comments or whitespace at the
4825 * beginning. */
4826 area = memarea_new();
4827 current_entry = eat_whitespace(ckstr);
4828 while (!strcmpstart(current_entry, "client-name ")) {
4829 rend_authorized_client_t *parsed_entry;
4830 size_t len;
4831 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
4832 /* Determine end of string. */
4833 const char *eos = strstr(current_entry, "\nclient-name ");
4834 if (!eos)
4835 eos = current_entry + strlen(current_entry);
4836 else
4837 eos = eos + 1;
4838 /* Free tokens and clear token list. */
4839 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4840 smartlist_clear(tokens);
4841 memarea_clear(area);
4842 /* Tokenize string. */
4843 if (tokenize_string(area, current_entry, eos, tokens,
4844 client_keys_token_table, 0)) {
4845 log_warn(LD_REND, "Error tokenizing client keys file.");
4846 goto err;
4848 /* Advance to next entry, if available. */
4849 current_entry = eos;
4850 /* Check minimum allowed length of token list. */
4851 if (smartlist_len(tokens) < 2) {
4852 log_warn(LD_REND, "Impossibly short client key entry.");
4853 goto err;
4855 /* Parse client name. */
4856 tok = find_by_keyword(tokens, C_CLIENT_NAME);
4857 tor_assert(tok == smartlist_get(tokens, 0));
4858 tor_assert(tok->n_args == 1);
4860 len = strlen(tok->args[0]);
4861 if (len < 1 || len > 19 ||
4862 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
4863 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
4864 "between 1 and 19, and valid characters are "
4865 "[A-Za-z0-9+-_].)", tok->args[0]);
4866 goto err;
4868 /* Check if client name is duplicate. */
4869 if (strmap_get(parsed_clients, tok->args[0])) {
4870 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
4871 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
4872 goto err;
4874 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
4875 parsed_entry->client_name = tor_strdup(tok->args[0]);
4876 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
4877 /* Parse client key. */
4878 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
4879 if (tok) {
4880 parsed_entry->client_key = tok->key;
4881 tok->key = NULL; /* Prevent free */
4884 /* Parse descriptor cookie. */
4885 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
4886 tor_assert(tok->n_args == 1);
4887 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
4888 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
4889 escaped(tok->args[0]));
4890 goto err;
4892 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
4893 * because a base64 encoding of length 24 does not fit into 16 bytes in all
4894 * cases. */
4895 if (base64_decode(descriptor_cookie_tmp, sizeof(descriptor_cookie_tmp),
4896 tok->args[0], strlen(tok->args[0]))
4897 != REND_DESC_COOKIE_LEN) {
4898 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
4899 "%s", escaped(tok->args[0]));
4900 goto err;
4902 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
4903 REND_DESC_COOKIE_LEN);
4905 result = strmap_size(parsed_clients);
4906 goto done;
4907 err:
4908 result = -1;
4909 done:
4910 /* Free tokens and clear token list. */
4911 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4912 smartlist_free(tokens);
4913 if (area)
4914 memarea_drop_all(area);
4915 return result;