Merge branch 'maint-0.2.1' into maint-0.2.2
[tor/rransom.git] / src / or / routerparse.c
blobe034c6c9b8d3fb154d8e80f5e472a6a59cb6359c
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-2011, 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 "circuitbuild.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_ROUTER_SIGNATURE,
47 K_PUBLISHED,
48 K_RUNNING_ROUTERS,
49 K_ROUTER_STATUS,
50 K_PLATFORM,
51 K_OPT,
52 K_BANDWIDTH,
53 K_CONTACT,
54 K_NETWORK_STATUS,
55 K_UPTIME,
56 K_DIR_SIGNING_KEY,
57 K_FAMILY,
58 K_FINGERPRINT,
59 K_HIBERNATING,
60 K_READ_HISTORY,
61 K_WRITE_HISTORY,
62 K_NETWORK_STATUS_VERSION,
63 K_DIR_SOURCE,
64 K_DIR_OPTIONS,
65 K_CLIENT_VERSIONS,
66 K_SERVER_VERSIONS,
67 K_P,
68 K_R,
69 K_S,
70 K_V,
71 K_W,
72 K_M,
73 K_EVENTDNS,
74 K_EXTRA_INFO,
75 K_EXTRA_INFO_DIGEST,
76 K_CACHES_EXTRA_INFO,
77 K_HIDDEN_SERVICE_DIR,
78 K_ALLOW_SINGLE_HOP_EXITS,
80 K_DIRREQ_END,
81 K_DIRREQ_V2_IPS,
82 K_DIRREQ_V3_IPS,
83 K_DIRREQ_V2_REQS,
84 K_DIRREQ_V3_REQS,
85 K_DIRREQ_V2_SHARE,
86 K_DIRREQ_V3_SHARE,
87 K_DIRREQ_V2_RESP,
88 K_DIRREQ_V3_RESP,
89 K_DIRREQ_V2_DIR,
90 K_DIRREQ_V3_DIR,
91 K_DIRREQ_V2_TUN,
92 K_DIRREQ_V3_TUN,
93 K_ENTRY_END,
94 K_ENTRY_IPS,
95 K_CELL_END,
96 K_CELL_PROCESSED,
97 K_CELL_QUEUED,
98 K_CELL_TIME,
99 K_CELL_CIRCS,
100 K_EXIT_END,
101 K_EXIT_WRITTEN,
102 K_EXIT_READ,
103 K_EXIT_OPENED,
105 K_DIR_KEY_CERTIFICATE_VERSION,
106 K_DIR_IDENTITY_KEY,
107 K_DIR_KEY_PUBLISHED,
108 K_DIR_KEY_EXPIRES,
109 K_DIR_KEY_CERTIFICATION,
110 K_DIR_KEY_CROSSCERT,
111 K_DIR_ADDRESS,
113 K_VOTE_STATUS,
114 K_VALID_AFTER,
115 K_FRESH_UNTIL,
116 K_VALID_UNTIL,
117 K_VOTING_DELAY,
119 K_KNOWN_FLAGS,
120 K_PARAMS,
121 K_BW_WEIGHTS,
122 K_VOTE_DIGEST,
123 K_CONSENSUS_DIGEST,
124 K_ADDITIONAL_DIGEST,
125 K_ADDITIONAL_SIGNATURE,
126 K_CONSENSUS_METHODS,
127 K_CONSENSUS_METHOD,
128 K_LEGACY_DIR_KEY,
129 K_DIRECTORY_FOOTER,
131 A_PURPOSE,
132 A_LAST_LISTED,
133 _A_UNKNOWN,
135 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
136 R_VERSION,
137 R_PERMANENT_KEY,
138 R_SECRET_ID_PART,
139 R_PUBLICATION_TIME,
140 R_PROTOCOL_VERSIONS,
141 R_INTRODUCTION_POINTS,
142 R_SIGNATURE,
144 R_IPO_IDENTIFIER,
145 R_IPO_IP_ADDRESS,
146 R_IPO_ONION_PORT,
147 R_IPO_ONION_KEY,
148 R_IPO_SERVICE_KEY,
150 C_CLIENT_NAME,
151 C_DESCRIPTOR_COOKIE,
152 C_CLIENT_KEY,
154 _ERR,
155 _EOF,
156 _NIL
157 } directory_keyword;
159 #define MIN_ANNOTATION A_PURPOSE
160 #define MAX_ANNOTATION _A_UNKNOWN
162 /** Structure to hold a single directory token.
164 * We parse a directory by breaking it into "tokens", each consisting
165 * of a keyword, a line full of arguments, and a binary object. The
166 * arguments and object are both optional, depending on the keyword
167 * type.
169 * This structure is only allocated in memareas; do not allocate it on
170 * the heap, or token_clear() won't work.
172 typedef struct directory_token_t {
173 directory_keyword tp; /**< Type of the token. */
174 int n_args:30; /**< Number of elements in args */
175 char **args; /**< Array of arguments from keyword line. */
177 char *object_type; /**< -----BEGIN [object_type]-----*/
178 size_t object_size; /**< Bytes in object_body */
179 char *object_body; /**< Contents of object, base64-decoded. */
181 crypto_pk_env_t *key; /**< For public keys only. Heap-allocated. */
183 char *error; /**< For _ERR tokens only. */
184 } directory_token_t;
186 /* ********************************************************************** */
188 /** We use a table of rules to decide how to parse each token type. */
190 /** Rules for whether the keyword needs an object. */
191 typedef enum {
192 NO_OBJ, /**< No object, ever. */
193 NEED_OBJ, /**< Object is required. */
194 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
195 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
196 NEED_KEY, /**< Object is required, and must be a public key. */
197 OBJ_OK, /**< Object is optional. */
198 } obj_syntax;
200 #define AT_START 1
201 #define AT_END 2
203 /** Determines the parsing rules for a single token type. */
204 typedef struct token_rule_t {
205 /** The string value of the keyword identifying the type of item. */
206 const char *t;
207 /** The corresponding directory_keyword enum. */
208 directory_keyword v;
209 /** Minimum number of arguments for this item */
210 int min_args;
211 /** Maximum number of arguments for this item */
212 int max_args;
213 /** If true, we concatenate all arguments for this item into a single
214 * string. */
215 int concat_args;
216 /** Requirements on object syntax for this item. */
217 obj_syntax os;
218 /** Lowest number of times this item may appear in a document. */
219 int min_cnt;
220 /** Highest number of times this item may appear in a document. */
221 int max_cnt;
222 /** One or more of AT_START/AT_END to limit where the item may appear in a
223 * document. */
224 int pos;
225 /** True iff this token is an annotation. */
226 int is_annotation;
227 } token_rule_t;
230 * Helper macros to define token tables. 's' is a string, 't' is a
231 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
232 * object syntax.
236 /** Appears to indicate the end of a table. */
237 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
238 /** An item with no restrictions: used for obsolete document types */
239 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
240 /** An item with no restrictions on multiplicity or location. */
241 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
242 /** An item that must appear exactly once */
243 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
244 /** An item that must appear exactly once, at the start of the document */
245 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
246 /** An item that must appear exactly once, at the end of the document */
247 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
248 /** An item that must appear one or more times */
249 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
250 /** An item that must appear no more than once */
251 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
252 /** An annotation that must appear no more than once */
253 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
255 /* Argument multiplicity: any number of arguments. */
256 #define ARGS 0,INT_MAX,0
257 /* Argument multiplicity: no arguments. */
258 #define NO_ARGS 0,0,0
259 /* Argument multiplicity: concatenate all arguments. */
260 #define CONCAT_ARGS 1,1,1
261 /* Argument multiplicity: at least <b>n</b> arguments. */
262 #define GE(n) n,INT_MAX,0
263 /* Argument multiplicity: exactly <b>n</b> arguments. */
264 #define EQ(n) n,n,0
266 /** List of tokens allowable in router descriptors */
267 static token_rule_t routerdesc_token_table[] = {
268 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
269 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
270 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
271 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
272 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
273 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
274 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
275 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
276 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
277 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
278 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
279 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
280 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
281 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
282 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
283 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
284 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
286 T01("family", K_FAMILY, ARGS, NO_OBJ ),
287 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
288 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
290 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
291 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
292 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
294 END_OF_TABLE
297 /** List of tokens allowable in extra-info documents. */
298 static token_rule_t extrainfo_token_table[] = {
299 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
300 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
301 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
302 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
303 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
304 T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ),
305 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ),
306 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ),
307 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ),
308 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ),
309 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ),
310 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ),
311 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ),
312 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ),
313 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ),
314 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ),
315 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ),
316 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ),
317 T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ),
318 T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ),
319 T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ),
320 T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ),
321 T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ),
322 T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ),
323 T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ),
324 T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ),
325 T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ),
326 T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ),
327 T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ),
329 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
331 END_OF_TABLE
334 /** List of tokens allowable in the body part of v2 and v3 networkstatus
335 * documents. */
336 static token_rule_t rtrstatus_token_table[] = {
337 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
338 T1( "r", K_R, GE(7), NO_OBJ ),
339 T1( "s", K_S, ARGS, NO_OBJ ),
340 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
341 T01("w", K_W, ARGS, NO_OBJ ),
342 T0N("m", K_M, CONCAT_ARGS, NO_OBJ ),
343 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
344 END_OF_TABLE
347 /** List of tokens allowable in the header part of v2 networkstatus documents.
349 static token_rule_t netstatus_token_table[] = {
350 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
351 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
352 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
353 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
354 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
355 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
356 GE(1), NO_OBJ ),
357 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
358 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
359 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
360 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
362 END_OF_TABLE
365 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
366 * footers. */
367 static token_rule_t dir_footer_token_table[] = {
368 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
369 END_OF_TABLE
372 /** List of tokens allowable in v1 directory headers/footers. */
373 static token_rule_t dir_token_table[] = {
374 /* don't enforce counts; this is obsolete. */
375 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
376 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
377 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
378 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
380 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
381 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
382 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
383 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
384 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
385 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
386 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
388 END_OF_TABLE
391 /** List of tokens common to V3 authority certificates and V3 consensuses. */
392 #define CERTIFICATE_MEMBERS \
393 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
394 GE(1), NO_OBJ ), \
395 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
396 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
397 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
398 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
399 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
400 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
401 NO_ARGS, NEED_OBJ), \
402 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
404 /** List of tokens allowable in V3 authority certificates. */
405 static token_rule_t dir_key_certificate_table[] = {
406 CERTIFICATE_MEMBERS
407 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
408 END_OF_TABLE
411 /** List of tokens allowable in rendezvous service descriptors */
412 static token_rule_t desc_token_table[] = {
413 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
414 EQ(1), NO_OBJ),
415 T1("version", R_VERSION, EQ(1), NO_OBJ),
416 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
417 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
418 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
419 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
420 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
421 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
422 END_OF_TABLE
425 /** List of tokens allowed in the (encrypted) list of introduction points of
426 * rendezvous service descriptors */
427 static token_rule_t ipo_token_table[] = {
428 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
429 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
430 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
431 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
432 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
433 END_OF_TABLE
436 /** List of tokens allowed in the (possibly encrypted) list of introduction
437 * points of rendezvous service descriptors */
438 static token_rule_t client_keys_token_table[] = {
439 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
440 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
441 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
442 END_OF_TABLE
445 /** List of tokens allowed in V3 networkstatus votes. */
446 static token_rule_t networkstatus_token_table[] = {
447 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
448 GE(1), NO_OBJ ),
449 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
450 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
451 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
452 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
453 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
454 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
455 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
456 T01("params", K_PARAMS, ARGS, NO_OBJ ),
457 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
459 CERTIFICATE_MEMBERS
461 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
462 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
463 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
464 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
465 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
466 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
467 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
468 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
470 END_OF_TABLE
473 /** List of tokens allowed in V3 networkstatus consensuses. */
474 static token_rule_t networkstatus_consensus_token_table[] = {
475 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
476 GE(1), NO_OBJ ),
477 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
478 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
479 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
480 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
481 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
483 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
485 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
486 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
487 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
489 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
491 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
492 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
493 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
494 T01("params", K_PARAMS, ARGS, NO_OBJ ),
496 END_OF_TABLE
499 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
500 * footers. */
501 static token_rule_t networkstatus_vote_footer_token_table[] = {
502 T01("directory-footer", K_DIRECTORY_FOOTER, NO_ARGS, NO_OBJ ),
503 T01("bandwidth-weights", K_BW_WEIGHTS, ARGS, NO_OBJ ),
504 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
505 END_OF_TABLE
508 /** List of tokens allowable in detached networkstatus signature documents. */
509 static token_rule_t networkstatus_detached_signature_token_table[] = {
510 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
511 T("additional-digest", K_ADDITIONAL_DIGEST,GE(3), NO_OBJ ),
512 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
513 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
514 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
515 T("additional-signature", K_ADDITIONAL_SIGNATURE, GE(4), NEED_OBJ ),
516 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
517 END_OF_TABLE
520 static token_rule_t microdesc_token_table[] = {
521 T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024),
522 T01("family", K_FAMILY, ARGS, NO_OBJ ),
523 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
524 A01("@last-listed", A_LAST_LISTED, CONCAT_ARGS, NO_OBJ ),
525 END_OF_TABLE
528 #undef T
530 /* static function prototypes */
531 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
532 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok);
533 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
535 static int router_get_hash_impl(const char *s, size_t s_len, char *digest,
536 const char *start_str, const char *end_str,
537 char end_char,
538 digest_algorithm_t alg);
539 static int router_get_hashes_impl(const char *s, size_t s_len,
540 digests_t *digests,
541 const char *start_str, const char *end_str,
542 char end_char);
543 static void token_clear(directory_token_t *tok);
544 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
545 static directory_token_t *_find_by_keyword(smartlist_t *s,
546 directory_keyword keyword,
547 const char *keyword_str);
548 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
549 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
550 directory_keyword keyword);
552 #define TS_ANNOTATIONS_OK 1
553 #define TS_NOCHECK 2
554 #define TS_NO_NEW_ANNOTATIONS 4
555 static int tokenize_string(memarea_t *area,
556 const char *start, const char *end,
557 smartlist_t *out,
558 token_rule_t *table,
559 int flags);
560 static directory_token_t *get_next_token(memarea_t *area,
561 const char **s,
562 const char *eos,
563 token_rule_t *table);
564 #define CST_CHECK_AUTHORITY (1<<0)
565 #define CST_NO_CHECK_OBJTYPE (1<<1)
566 static int check_signature_token(const char *digest,
567 ssize_t digest_len,
568 directory_token_t *tok,
569 crypto_pk_env_t *pkey,
570 int flags,
571 const char *doctype);
572 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
573 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
575 #undef DEBUG_AREA_ALLOC
577 #ifdef DEBUG_AREA_ALLOC
578 #define DUMP_AREA(a,name) STMT_BEGIN \
579 size_t alloc=0, used=0; \
580 memarea_get_stats((a),&alloc,&used); \
581 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
582 name, (unsigned long)alloc, (unsigned long)used); \
583 STMT_END
584 #else
585 #define DUMP_AREA(a,name) STMT_NIL
586 #endif
588 /** Last time we dumped a descriptor to disk. */
589 static time_t last_desc_dumped = 0;
591 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
592 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
593 * than one descriptor to disk per minute. If there is already such a
594 * file in the data directory, overwrite it. */
595 static void
596 dump_desc(const char *desc, const char *type)
598 time_t now = time(NULL);
599 tor_assert(desc);
600 tor_assert(type);
601 if (!last_desc_dumped || last_desc_dumped + 60 < now) {
602 char *debugfile = get_datadir_fname("unparseable-desc");
603 size_t filelen = 50 + strlen(type) + strlen(desc);
604 char *content = tor_malloc_zero(filelen);
605 tor_snprintf(content, filelen, "Unable to parse descriptor of type "
606 "%s:\n%s", type, desc);
607 write_str_to_file(debugfile, content, 0);
608 log_info(LD_DIR, "Unable to parse descriptor of type %s. See file "
609 "unparseable-desc in data directory for details.", type);
610 tor_free(content);
611 tor_free(debugfile);
612 last_desc_dumped = now;
616 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
617 * <b>s</b>. Return 0 on success, -1 on failure.
620 router_get_dir_hash(const char *s, char *digest)
622 return router_get_hash_impl(s, strlen(s), digest,
623 "signed-directory","\ndirectory-signature",'\n',
624 DIGEST_SHA1);
627 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
628 * <b>s</b>. Return 0 on success, -1 on failure.
631 router_get_router_hash(const char *s, size_t s_len, char *digest)
633 return router_get_hash_impl(s, s_len, digest,
634 "router ","\nrouter-signature", '\n',
635 DIGEST_SHA1);
638 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
639 * string in <b>s</b>. Return 0 on success, -1 on failure.
642 router_get_runningrouters_hash(const char *s, char *digest)
644 return router_get_hash_impl(s, strlen(s), digest,
645 "network-status","\ndirectory-signature", '\n',
646 DIGEST_SHA1);
649 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
650 * string in <b>s</b>. Return 0 on success, -1 on failure. */
652 router_get_networkstatus_v2_hash(const char *s, char *digest)
654 return router_get_hash_impl(s, strlen(s), digest,
655 "network-status-version","\ndirectory-signature",
656 '\n',
657 DIGEST_SHA1);
660 /** Set <b>digests</b> to all the digests of the consensus document in
661 * <b>s</b> */
663 router_get_networkstatus_v3_hashes(const char *s, digests_t *digests)
665 return router_get_hashes_impl(s,strlen(s),digests,
666 "network-status-version",
667 "\ndirectory-signature",
668 ' ');
671 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
672 * string in <b>s</b>. Return 0 on success, -1 on failure. */
674 router_get_networkstatus_v3_hash(const char *s, char *digest,
675 digest_algorithm_t alg)
677 return router_get_hash_impl(s, strlen(s), digest,
678 "network-status-version",
679 "\ndirectory-signature",
680 ' ', alg);
683 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
684 * string in <b>s</b>. Return 0 on success, -1 on failure. */
686 router_get_extrainfo_hash(const char *s, char *digest)
688 return router_get_hash_impl(s, strlen(s), digest, "extra-info",
689 "\nrouter-signature",'\n', DIGEST_SHA1);
692 /** Helper: used to generate signatures for routers, directories and
693 * network-status objects. Given a digest in <b>digest</b> and a secret
694 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
695 * surround it with -----BEGIN/END----- pairs, and write it to the
696 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
697 * failure.
700 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
701 size_t digest_len, crypto_pk_env_t *private_key)
703 char *signature;
704 size_t i, keysize;
705 int siglen;
707 keysize = crypto_pk_keysize(private_key);
708 signature = tor_malloc(keysize);
709 siglen = crypto_pk_private_sign(private_key, signature, keysize,
710 digest, digest_len);
711 if (siglen < 0) {
712 log_warn(LD_BUG,"Couldn't sign digest.");
713 goto err;
715 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
716 goto truncated;
718 i = strlen(buf);
719 if (base64_encode(buf+i, buf_len-i, signature, siglen) < 0) {
720 log_warn(LD_BUG,"couldn't base64-encode signature");
721 goto err;
724 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
725 goto truncated;
727 tor_free(signature);
728 return 0;
730 truncated:
731 log_warn(LD_BUG,"tried to exceed string length.");
732 err:
733 tor_free(signature);
734 return -1;
737 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
738 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
739 * entries. Else, return VS_OLD if every member of
740 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
741 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
742 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
743 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
744 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
745 * VS_UNRECOMMENDED.
747 * (versionlist is a comma-separated list of version strings,
748 * optionally prefixed with "Tor". Versions that can't be parsed are
749 * ignored.)
751 version_status_t
752 tor_version_is_obsolete(const char *myversion, const char *versionlist)
754 tor_version_t mine, other;
755 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
756 found_any_in_series = 0, r, same;
757 version_status_t ret = VS_UNRECOMMENDED;
758 smartlist_t *version_sl;
760 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
761 myversion, versionlist);
763 if (tor_version_parse(myversion, &mine)) {
764 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
765 tor_assert(0);
767 version_sl = smartlist_create();
768 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
770 if (!strlen(versionlist)) { /* no authorities cared or agreed */
771 ret = VS_EMPTY;
772 goto done;
775 SMARTLIST_FOREACH(version_sl, const char *, cp, {
776 if (!strcmpstart(cp, "Tor "))
777 cp += 4;
779 if (tor_version_parse(cp, &other)) {
780 /* Couldn't parse other; it can't be a match. */
781 } else {
782 same = tor_version_same_series(&mine, &other);
783 if (same)
784 found_any_in_series = 1;
785 r = tor_version_compare(&mine, &other);
786 if (r==0) {
787 ret = VS_RECOMMENDED;
788 goto done;
789 } else if (r<0) {
790 found_newer = 1;
791 if (same)
792 found_newer_in_series = 1;
793 } else if (r>0) {
794 found_older = 1;
799 /* We didn't find the listed version. Is it new or old? */
800 if (found_any_in_series && !found_newer_in_series && found_newer) {
801 ret = VS_NEW_IN_SERIES;
802 } else if (found_newer && !found_older) {
803 ret = VS_OLD;
804 } else if (found_older && !found_newer) {
805 ret = VS_NEW;
806 } else {
807 ret = VS_UNRECOMMENDED;
810 done:
811 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
812 smartlist_free(version_sl);
813 return ret;
816 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
817 * Otherwise, return -1. If we're a directory cache, cache it.
820 router_parse_directory(const char *str)
822 directory_token_t *tok;
823 char digest[DIGEST_LEN];
824 time_t published_on;
825 int r;
826 const char *end, *cp, *str_dup = str;
827 smartlist_t *tokens = NULL;
828 crypto_pk_env_t *declared_key = NULL;
829 memarea_t *area = memarea_new();
831 /* XXXX This could be simplified a lot, but it will all go away
832 * once pre-0.1.1.8 is obsolete, and for now it's better not to
833 * touch it. */
835 if (router_get_dir_hash(str, digest)) {
836 log_warn(LD_DIR, "Unable to compute digest of directory");
837 goto err;
839 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
841 /* Check signature first, before we try to tokenize. */
842 cp = str;
843 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
844 cp = end;
845 if (cp == str || !cp) {
846 log_warn(LD_DIR, "No signature found on directory."); goto err;
848 ++cp;
849 tokens = smartlist_create();
850 if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
851 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
853 if (smartlist_len(tokens) != 1) {
854 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
856 tok=smartlist_get(tokens,0);
857 if (tok->tp != K_DIRECTORY_SIGNATURE) {
858 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
860 declared_key = find_dir_signing_key(str, str+strlen(str));
861 note_crypto_pk_op(VERIFY_DIR);
862 if (check_signature_token(digest, DIGEST_LEN, tok, declared_key,
863 CST_CHECK_AUTHORITY, "directory")<0)
864 goto err;
866 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
867 smartlist_clear(tokens);
868 memarea_clear(area);
870 /* Now try to parse the first part of the directory. */
871 if ((end = strstr(str,"\nrouter "))) {
872 ++end;
873 } else if ((end = strstr(str, "\ndirectory-signature"))) {
874 ++end;
875 } else {
876 end = str + strlen(str);
879 if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
880 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
883 tok = find_by_keyword(tokens, K_PUBLISHED);
884 tor_assert(tok->n_args == 1);
886 if (parse_iso_time(tok->args[0], &published_on) < 0) {
887 goto err;
890 /* Now that we know the signature is okay, and we have a
891 * publication time, cache the directory. */
892 if (directory_caches_v1_dir_info(get_options()) &&
893 !authdir_mode_v1(get_options()))
894 dirserv_set_cached_directory(str, published_on, 0);
896 r = 0;
897 goto done;
898 err:
899 dump_desc(str_dup, "v1 directory");
900 r = -1;
901 done:
902 if (declared_key) crypto_free_pk_env(declared_key);
903 if (tokens) {
904 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
905 smartlist_free(tokens);
907 if (area) {
908 DUMP_AREA(area, "v1 directory");
909 memarea_drop_all(area);
911 return r;
914 /** Read a signed router status statement from <b>str</b>. If it's
915 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
916 * cache it.*/
918 router_parse_runningrouters(const char *str)
920 char digest[DIGEST_LEN];
921 directory_token_t *tok;
922 time_t published_on;
923 int r = -1;
924 crypto_pk_env_t *declared_key = NULL;
925 smartlist_t *tokens = NULL;
926 const char *eos = str + strlen(str), *str_dup = str;
927 memarea_t *area = NULL;
929 if (router_get_runningrouters_hash(str, digest)) {
930 log_warn(LD_DIR, "Unable to compute digest of running-routers");
931 goto err;
933 area = memarea_new();
934 tokens = smartlist_create();
935 if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
936 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
938 tok = smartlist_get(tokens,0);
939 if (tok->tp != K_NETWORK_STATUS) {
940 log_warn(LD_DIR, "Network-status starts with wrong token");
941 goto err;
944 tok = find_by_keyword(tokens, K_PUBLISHED);
945 tor_assert(tok->n_args == 1);
946 if (parse_iso_time(tok->args[0], &published_on) < 0) {
947 goto err;
949 if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
950 log_warn(LD_DIR, "Missing signature on running-routers");
951 goto err;
953 declared_key = find_dir_signing_key(str, eos);
954 note_crypto_pk_op(VERIFY_DIR);
955 if (check_signature_token(digest, DIGEST_LEN, tok, declared_key,
956 CST_CHECK_AUTHORITY, "running-routers")
957 < 0)
958 goto err;
960 /* Now that we know the signature is okay, and we have a
961 * publication time, cache the list. */
962 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
963 dirserv_set_cached_directory(str, published_on, 1);
965 r = 0;
966 err:
967 dump_desc(str_dup, "v1 running-routers");
968 if (declared_key) crypto_free_pk_env(declared_key);
969 if (tokens) {
970 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
971 smartlist_free(tokens);
973 if (area) {
974 DUMP_AREA(area, "v1 running-routers");
975 memarea_drop_all(area);
977 return r;
980 /** Given a directory or running-routers string in <b>str</b>, try to
981 * find the its dir-signing-key token (if any). If this token is
982 * present, extract and return the key. Return NULL on failure. */
983 static crypto_pk_env_t *
984 find_dir_signing_key(const char *str, const char *eos)
986 const char *cp;
987 directory_token_t *tok;
988 crypto_pk_env_t *key = NULL;
989 memarea_t *area = NULL;
990 tor_assert(str);
991 tor_assert(eos);
993 /* Is there a dir-signing-key in the directory? */
994 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
995 if (!cp)
996 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
997 if (!cp)
998 return NULL;
999 ++cp; /* Now cp points to the start of the token. */
1001 area = memarea_new();
1002 tok = get_next_token(area, &cp, eos, dir_token_table);
1003 if (!tok) {
1004 log_warn(LD_DIR, "Unparseable dir-signing-key token");
1005 goto done;
1007 if (tok->tp != K_DIR_SIGNING_KEY) {
1008 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
1009 goto done;
1012 if (tok->key) {
1013 key = tok->key;
1014 tok->key = NULL; /* steal reference. */
1015 } else {
1016 log_warn(LD_DIR, "Dir-signing-key token contained no key");
1019 done:
1020 if (tok) token_clear(tok);
1021 if (area) {
1022 DUMP_AREA(area, "dir-signing-key token");
1023 memarea_drop_all(area);
1025 return key;
1028 /** Return true iff <b>key</b> is allowed to sign directories.
1030 static int
1031 dir_signing_key_is_trusted(crypto_pk_env_t *key)
1033 char digest[DIGEST_LEN];
1034 if (!key) return 0;
1035 if (crypto_pk_get_digest(key, digest) < 0) {
1036 log_warn(LD_DIR, "Error computing dir-signing-key digest");
1037 return 0;
1039 if (!router_digest_is_trusted_dir(digest)) {
1040 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
1041 return 0;
1043 return 1;
1046 /** Check whether the object body of the token in <b>tok</b> has a good
1047 * signature for <b>digest</b> using key <b>pkey</b>. If
1048 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
1049 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
1050 * the object type of the signature object. Use <b>doctype</b> as the type of
1051 * the document when generating log messages. Return 0 on success, negative
1052 * on failure.
1054 static int
1055 check_signature_token(const char *digest,
1056 ssize_t digest_len,
1057 directory_token_t *tok,
1058 crypto_pk_env_t *pkey,
1059 int flags,
1060 const char *doctype)
1062 char *signed_digest;
1063 size_t keysize;
1064 const int check_authority = (flags & CST_CHECK_AUTHORITY);
1065 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
1067 tor_assert(pkey);
1068 tor_assert(tok);
1069 tor_assert(digest);
1070 tor_assert(doctype);
1072 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
1073 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
1074 doctype);
1075 return -1;
1078 if (check_objtype) {
1079 if (strcmp(tok->object_type, "SIGNATURE")) {
1080 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
1081 return -1;
1085 keysize = crypto_pk_keysize(pkey);
1086 signed_digest = tor_malloc(keysize);
1087 if (crypto_pk_public_checksig(pkey, signed_digest, keysize,
1088 tok->object_body, tok->object_size)
1089 < digest_len) {
1090 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
1091 tor_free(signed_digest);
1092 return -1;
1094 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
1095 // hex_str(signed_digest,4));
1096 if (memcmp(digest, signed_digest, digest_len)) {
1097 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
1098 tor_free(signed_digest);
1099 return -1;
1101 tor_free(signed_digest);
1102 return 0;
1105 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
1106 * or to the first of the annotations proceeding the next router or
1107 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
1108 * we found an extrainfo, or false if found a router. Do not scan beyond
1109 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
1110 static int
1111 find_start_of_next_router_or_extrainfo(const char **s_ptr,
1112 const char *eos,
1113 int *is_extrainfo_out)
1115 const char *annotations = NULL;
1116 const char *s = *s_ptr;
1118 s = eat_whitespace_eos(s, eos);
1120 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
1121 /* We're at the start of a line. */
1122 tor_assert(*s != '\n');
1124 if (*s == '@' && !annotations) {
1125 annotations = s;
1126 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
1127 *s_ptr = annotations ? annotations : s;
1128 *is_extrainfo_out = 0;
1129 return 0;
1130 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
1131 *s_ptr = annotations ? annotations : s;
1132 *is_extrainfo_out = 1;
1133 return 0;
1136 if (!(s = memchr(s+1, '\n', eos-(s+1))))
1137 break;
1138 s = eat_whitespace_eos(s, eos);
1140 return -1;
1143 /** Given a string *<b>s</b> containing a concatenated sequence of router
1144 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1145 * them and stores the result in <b>dest</b>. All routers are marked running
1146 * and valid. Advances *s to a point immediately following the last router
1147 * entry. Ignore any trailing router entries that are not complete.
1149 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1150 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1151 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1153 * Returns 0 on success and -1 on failure.
1156 router_parse_list_from_string(const char **s, const char *eos,
1157 smartlist_t *dest,
1158 saved_location_t saved_location,
1159 int want_extrainfo,
1160 int allow_annotations,
1161 const char *prepend_annotations)
1163 routerinfo_t *router;
1164 extrainfo_t *extrainfo;
1165 signed_descriptor_t *signed_desc;
1166 void *elt;
1167 const char *end, *start;
1168 int have_extrainfo;
1170 tor_assert(s);
1171 tor_assert(*s);
1172 tor_assert(dest);
1174 start = *s;
1175 if (!eos)
1176 eos = *s + strlen(*s);
1178 tor_assert(eos >= *s);
1180 while (1) {
1181 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1182 break;
1184 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1185 if (end)
1186 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1187 if (end)
1188 end += strlen("\n-----END SIGNATURE-----\n");
1190 if (!end)
1191 break;
1193 elt = NULL;
1195 if (have_extrainfo && want_extrainfo) {
1196 routerlist_t *rl = router_get_routerlist();
1197 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1198 saved_location != SAVED_IN_CACHE,
1199 rl->identity_map);
1200 if (extrainfo) {
1201 signed_desc = &extrainfo->cache_info;
1202 elt = extrainfo;
1204 } else if (!have_extrainfo && !want_extrainfo) {
1205 router = router_parse_entry_from_string(*s, end,
1206 saved_location != SAVED_IN_CACHE,
1207 allow_annotations,
1208 prepend_annotations);
1209 if (router) {
1210 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1211 router->nickname, router_purpose_to_string(router->purpose));
1212 signed_desc = &router->cache_info;
1213 elt = router;
1216 if (!elt) {
1217 *s = end;
1218 continue;
1220 if (saved_location != SAVED_NOWHERE) {
1221 signed_desc->saved_location = saved_location;
1222 signed_desc->saved_offset = *s - start;
1224 *s = end;
1225 smartlist_add(dest, elt);
1228 return 0;
1231 /* For debugging: define to count every descriptor digest we've seen so we
1232 * know if we need to try harder to avoid duplicate verifies. */
1233 #undef COUNT_DISTINCT_DIGESTS
1235 #ifdef COUNT_DISTINCT_DIGESTS
1236 static digestmap_t *verified_digests = NULL;
1237 #endif
1239 /** Log the total count of the number of distinct router digests we've ever
1240 * verified. When compared to the number of times we've verified routerdesc
1241 * signatures <i>in toto</i>, this will tell us if we're doing too much
1242 * multiple-verification. */
1243 void
1244 dump_distinct_digest_count(int severity)
1246 #ifdef COUNT_DISTINCT_DIGESTS
1247 if (!verified_digests)
1248 verified_digests = digestmap_new();
1249 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1250 digestmap_size(verified_digests));
1251 #else
1252 (void)severity; /* suppress "unused parameter" warning */
1253 #endif
1256 /** Helper function: reads a single router entry from *<b>s</b> ...
1257 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1258 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1259 * s through end into the signed_descriptor_body of the resulting
1260 * routerinfo_t.
1262 * If <b>end</b> is NULL, <b>s</b> must be properly NULL-terminated.
1264 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1265 * before the router; if it's false, reject the router if it's annotated. If
1266 * <b>prepend_annotations</b> is set, it should contain some annotations:
1267 * append them to the front of the router before parsing it, and keep them
1268 * around when caching the router.
1270 * Only one of allow_annotations and prepend_annotations may be set.
1272 routerinfo_t *
1273 router_parse_entry_from_string(const char *s, const char *end,
1274 int cache_copy, int allow_annotations,
1275 const char *prepend_annotations)
1277 routerinfo_t *router = NULL;
1278 char digest[128];
1279 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1280 directory_token_t *tok;
1281 struct in_addr in;
1282 const char *start_of_annotations, *cp, *s_dup = s;
1283 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1284 int ok = 1;
1285 memarea_t *area = NULL;
1287 tor_assert(!allow_annotations || !prepend_annotations);
1289 if (!end) {
1290 end = s + strlen(s);
1293 /* point 'end' to a point immediately after the final newline. */
1294 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1295 --end;
1297 area = memarea_new();
1298 tokens = smartlist_create();
1299 if (prepend_annotations) {
1300 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1301 routerdesc_token_table,TS_NOCHECK)) {
1302 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1303 goto err;
1307 start_of_annotations = s;
1308 cp = tor_memstr(s, end-s, "\nrouter ");
1309 if (!cp) {
1310 if (end-s < 7 || strcmpstart(s, "router ")) {
1311 log_warn(LD_DIR, "No router keyword found.");
1312 goto err;
1314 } else {
1315 s = cp+1;
1318 if (start_of_annotations != s) { /* We have annotations */
1319 if (allow_annotations) {
1320 if (tokenize_string(area,start_of_annotations,s,tokens,
1321 routerdesc_token_table,TS_NOCHECK)) {
1322 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1323 goto err;
1325 } else {
1326 log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
1327 "loaded from disk. Dropping it.");
1328 goto err;
1332 if (router_get_router_hash(s, end - s, digest) < 0) {
1333 log_warn(LD_DIR, "Couldn't compute router hash.");
1334 goto err;
1337 int flags = 0;
1338 if (allow_annotations)
1339 flags |= TS_ANNOTATIONS_OK;
1340 if (prepend_annotations)
1341 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1343 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1344 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1345 goto err;
1349 if (smartlist_len(tokens) < 2) {
1350 log_warn(LD_DIR, "Impossibly short router descriptor.");
1351 goto err;
1354 tok = find_by_keyword(tokens, K_ROUTER);
1355 tor_assert(tok->n_args >= 5);
1357 router = tor_malloc_zero(sizeof(routerinfo_t));
1358 router->country = -1;
1359 router->cache_info.routerlist_index = -1;
1360 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1361 router->cache_info.signed_descriptor_len = end-s;
1362 if (cache_copy) {
1363 size_t len = router->cache_info.signed_descriptor_len +
1364 router->cache_info.annotations_len;
1365 char *cp =
1366 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1367 if (prepend_annotations) {
1368 memcpy(cp, prepend_annotations, prepend_len);
1369 cp += prepend_len;
1371 /* This assertion will always succeed.
1372 * len == signed_desc_len + annotations_len
1373 * == end-s + s-start_of_annotations + prepend_len
1374 * == end-start_of_annotations + prepend_len
1375 * We already wrote prepend_len bytes into the buffer; now we're
1376 * writing end-start_of_annotations -NM. */
1377 tor_assert(cp+(end-start_of_annotations) ==
1378 router->cache_info.signed_descriptor_body+len);
1379 memcpy(cp, start_of_annotations, end-start_of_annotations);
1380 router->cache_info.signed_descriptor_body[len] = '\0';
1381 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1383 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1385 router->nickname = tor_strdup(tok->args[0]);
1386 if (!is_legal_nickname(router->nickname)) {
1387 log_warn(LD_DIR,"Router nickname is invalid");
1388 goto err;
1390 router->address = tor_strdup(tok->args[1]);
1391 if (!tor_inet_aton(router->address, &in)) {
1392 log_warn(LD_DIR,"Router address is not an IP address.");
1393 goto err;
1395 router->addr = ntohl(in.s_addr);
1397 router->or_port =
1398 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1399 if (!ok) {
1400 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1401 goto err;
1403 router->dir_port =
1404 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1405 if (!ok) {
1406 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1407 goto err;
1410 tok = find_by_keyword(tokens, K_BANDWIDTH);
1411 tor_assert(tok->n_args >= 3);
1412 router->bandwidthrate = (int)
1413 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1415 if (!ok) {
1416 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1417 escaped(tok->args[0]));
1418 goto err;
1420 router->bandwidthburst =
1421 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1422 if (!ok) {
1423 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1424 goto err;
1426 router->bandwidthcapacity = (int)
1427 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1428 if (!ok) {
1429 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1430 goto err;
1433 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1434 tor_assert(tok->n_args);
1435 router->purpose = router_purpose_from_string(tok->args[0]);
1436 } else {
1437 router->purpose = ROUTER_PURPOSE_GENERAL;
1439 router->cache_info.send_unencrypted =
1440 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1442 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1443 tor_assert(tok->n_args >= 1);
1444 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1445 if (!ok) {
1446 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1447 goto err;
1451 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1452 tor_assert(tok->n_args >= 1);
1453 router->is_hibernating
1454 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1457 tok = find_by_keyword(tokens, K_PUBLISHED);
1458 tor_assert(tok->n_args == 1);
1459 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1460 goto err;
1462 tok = find_by_keyword(tokens, K_ONION_KEY);
1463 router->onion_pkey = tok->key;
1464 tok->key = NULL; /* Prevent free */
1466 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1467 router->identity_pkey = tok->key;
1468 tok->key = NULL; /* Prevent free */
1469 if (crypto_pk_get_digest(router->identity_pkey,
1470 router->cache_info.identity_digest)) {
1471 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1474 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1475 /* If there's a fingerprint line, it must match the identity digest. */
1476 char d[DIGEST_LEN];
1477 tor_assert(tok->n_args == 1);
1478 tor_strstrip(tok->args[0], " ");
1479 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1480 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1481 escaped(tok->args[0]));
1482 goto err;
1484 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1485 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1486 tok->args[0]);
1487 goto err;
1491 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1492 router->platform = tor_strdup(tok->args[0]);
1495 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1496 router->contact_info = tor_strdup(tok->args[0]);
1499 if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
1500 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1501 } else if (router->platform) {
1502 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1503 router->has_old_dnsworkers = 1;
1506 exit_policy_tokens = find_all_exitpolicy(tokens);
1507 if (!smartlist_len(exit_policy_tokens)) {
1508 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1509 goto err;
1511 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1512 if (router_add_exit_policy(router,t)<0) {
1513 log_warn(LD_DIR,"Error in exit policy");
1514 goto err;
1516 policy_expand_private(&router->exit_policy);
1517 if (policy_is_reject_star(router->exit_policy))
1518 router->policy_is_reject_star = 1;
1520 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1521 int i;
1522 router->declared_family = smartlist_create();
1523 for (i=0;i<tok->n_args;++i) {
1524 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1525 log_warn(LD_DIR, "Illegal nickname %s in family line",
1526 escaped(tok->args[i]));
1527 goto err;
1529 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1533 if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1534 router->caches_extra_info = 1;
1536 if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
1537 router->allow_single_hop_exits = 1;
1539 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1540 tor_assert(tok->n_args >= 1);
1541 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1542 base16_decode(router->cache_info.extra_info_digest,
1543 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1544 } else {
1545 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1549 if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1550 router->wants_to_be_hs_dir = 1;
1553 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1554 note_crypto_pk_op(VERIFY_RTR);
1555 #ifdef COUNT_DISTINCT_DIGESTS
1556 if (!verified_digests)
1557 verified_digests = digestmap_new();
1558 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1559 #endif
1560 if (check_signature_token(digest, DIGEST_LEN, tok, router->identity_pkey, 0,
1561 "router descriptor") < 0)
1562 goto err;
1564 routerinfo_set_country(router);
1566 if (!router->or_port) {
1567 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1568 goto err;
1571 if (!router->platform) {
1572 router->platform = tor_strdup("<unknown>");
1575 goto done;
1577 err:
1578 dump_desc(s_dup, "router descriptor");
1579 routerinfo_free(router);
1580 router = NULL;
1581 done:
1582 if (tokens) {
1583 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1584 smartlist_free(tokens);
1586 smartlist_free(exit_policy_tokens);
1587 if (area) {
1588 DUMP_AREA(area, "routerinfo");
1589 memarea_drop_all(area);
1591 return router;
1594 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1595 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1596 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1597 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1598 * as a map from router identity to routerinfo_t when looking up signing keys.
1600 extrainfo_t *
1601 extrainfo_parse_entry_from_string(const char *s, const char *end,
1602 int cache_copy, struct digest_ri_map_t *routermap)
1604 extrainfo_t *extrainfo = NULL;
1605 char digest[128];
1606 smartlist_t *tokens = NULL;
1607 directory_token_t *tok;
1608 crypto_pk_env_t *key = NULL;
1609 routerinfo_t *router = NULL;
1610 memarea_t *area = NULL;
1611 const char *s_dup = s;
1613 if (!end) {
1614 end = s + strlen(s);
1617 /* point 'end' to a point immediately after the final newline. */
1618 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1619 --end;
1621 if (router_get_extrainfo_hash(s, digest) < 0) {
1622 log_warn(LD_DIR, "Couldn't compute router hash.");
1623 goto err;
1625 tokens = smartlist_create();
1626 area = memarea_new();
1627 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1628 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1629 goto err;
1632 if (smartlist_len(tokens) < 2) {
1633 log_warn(LD_DIR, "Impossibly short extra-info document.");
1634 goto err;
1637 tok = smartlist_get(tokens,0);
1638 if (tok->tp != K_EXTRA_INFO) {
1639 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1640 goto err;
1643 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1644 extrainfo->cache_info.is_extrainfo = 1;
1645 if (cache_copy)
1646 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1647 extrainfo->cache_info.signed_descriptor_len = end-s;
1648 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1650 tor_assert(tok->n_args >= 2);
1651 if (!is_legal_nickname(tok->args[0])) {
1652 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1653 goto err;
1655 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1656 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1657 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1658 tok->args[1], HEX_DIGEST_LEN)) {
1659 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1660 escaped(tok->args[1]));
1661 goto err;
1664 tok = find_by_keyword(tokens, K_PUBLISHED);
1665 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1666 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1667 escaped(tok->args[0]));
1668 goto err;
1671 if (routermap &&
1672 (router = digestmap_get((digestmap_t*)routermap,
1673 extrainfo->cache_info.identity_digest))) {
1674 key = router->identity_pkey;
1677 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1678 if (strcmp(tok->object_type, "SIGNATURE") ||
1679 tok->object_size < 128 || tok->object_size > 512) {
1680 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1681 goto err;
1684 if (key) {
1685 note_crypto_pk_op(VERIFY_RTR);
1686 if (check_signature_token(digest, DIGEST_LEN, tok, key, 0,
1687 "extra-info") < 0)
1688 goto err;
1690 if (router)
1691 extrainfo->cache_info.send_unencrypted =
1692 router->cache_info.send_unencrypted;
1693 } else {
1694 extrainfo->pending_sig = tor_memdup(tok->object_body,
1695 tok->object_size);
1696 extrainfo->pending_sig_len = tok->object_size;
1699 goto done;
1700 err:
1701 dump_desc(s_dup, "extra-info descriptor");
1702 extrainfo_free(extrainfo);
1703 extrainfo = NULL;
1704 done:
1705 if (tokens) {
1706 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1707 smartlist_free(tokens);
1709 if (area) {
1710 DUMP_AREA(area, "extrainfo");
1711 memarea_drop_all(area);
1713 return extrainfo;
1716 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1717 * the first character after the certificate. */
1718 authority_cert_t *
1719 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1721 /** Reject any certificate at least this big; it is probably an overflow, an
1722 * attack, a bug, or some other nonsense. */
1723 #define MAX_CERT_SIZE (128*1024)
1725 authority_cert_t *cert = NULL, *old_cert;
1726 smartlist_t *tokens = NULL;
1727 char digest[DIGEST_LEN];
1728 directory_token_t *tok;
1729 char fp_declared[DIGEST_LEN];
1730 char *eos;
1731 size_t len;
1732 int found;
1733 memarea_t *area = NULL;
1734 const char *s_dup = s;
1736 s = eat_whitespace(s);
1737 eos = strstr(s, "\ndir-key-certification");
1738 if (! eos) {
1739 log_warn(LD_DIR, "No signature found on key certificate");
1740 return NULL;
1742 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1743 if (! eos) {
1744 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1745 return NULL;
1747 eos = strchr(eos+2, '\n');
1748 tor_assert(eos);
1749 ++eos;
1750 len = eos - s;
1752 if (len > MAX_CERT_SIZE) {
1753 log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
1754 "rejecting", (unsigned long)len);
1755 return NULL;
1758 tokens = smartlist_create();
1759 area = memarea_new();
1760 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1761 log_warn(LD_DIR, "Error tokenizing key certificate");
1762 goto err;
1764 if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
1765 "\ndir-key-certification", '\n', DIGEST_SHA1) < 0)
1766 goto err;
1767 tok = smartlist_get(tokens, 0);
1768 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1769 log_warn(LD_DIR,
1770 "Key certificate does not begin with a recognized version (3).");
1771 goto err;
1774 cert = tor_malloc_zero(sizeof(authority_cert_t));
1775 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1777 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1778 tor_assert(tok->key);
1779 cert->signing_key = tok->key;
1780 tok->key = NULL;
1781 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1782 goto err;
1784 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1785 tor_assert(tok->key);
1786 cert->identity_key = tok->key;
1787 tok->key = NULL;
1789 tok = find_by_keyword(tokens, K_FINGERPRINT);
1790 tor_assert(tok->n_args);
1791 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1792 strlen(tok->args[0]))) {
1793 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1794 escaped(tok->args[0]));
1795 goto err;
1798 if (crypto_pk_get_digest(cert->identity_key,
1799 cert->cache_info.identity_digest))
1800 goto err;
1802 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1803 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1804 "fingerprint");
1805 goto err;
1808 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1809 if (tok) {
1810 struct in_addr in;
1811 char *address = NULL;
1812 tor_assert(tok->n_args);
1813 /* XXX021 use tor_addr_port_parse() below instead. -RD */
1814 if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
1815 &cert->dir_port)<0 ||
1816 tor_inet_aton(address, &in) == 0) {
1817 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1818 tor_free(address);
1819 goto err;
1821 cert->addr = ntohl(in.s_addr);
1822 tor_free(address);
1825 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1826 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1827 goto err;
1829 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1830 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1831 goto err;
1834 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1835 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1836 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1837 goto err;
1840 /* If we already have this cert, don't bother checking the signature. */
1841 old_cert = authority_cert_get_by_digests(
1842 cert->cache_info.identity_digest,
1843 cert->signing_key_digest);
1844 found = 0;
1845 if (old_cert) {
1846 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1847 * buy us much. */
1848 if (old_cert->cache_info.signed_descriptor_len == len &&
1849 old_cert->cache_info.signed_descriptor_body &&
1850 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1851 log_debug(LD_DIR, "We already checked the signature on this "
1852 "certificate; no need to do so again.");
1853 found = 1;
1854 cert->is_cross_certified = old_cert->is_cross_certified;
1857 if (!found) {
1858 if (check_signature_token(digest, DIGEST_LEN, tok, cert->identity_key, 0,
1859 "key certificate")) {
1860 goto err;
1863 if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
1864 /* XXXX Once all authorities generate cross-certified certificates,
1865 * make this field mandatory. */
1866 if (check_signature_token(cert->cache_info.identity_digest,
1867 DIGEST_LEN,
1868 tok,
1869 cert->signing_key,
1870 CST_NO_CHECK_OBJTYPE,
1871 "key cross-certification")) {
1872 goto err;
1874 cert->is_cross_certified = 1;
1878 cert->cache_info.signed_descriptor_len = len;
1879 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1880 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1881 cert->cache_info.signed_descriptor_body[len] = 0;
1882 cert->cache_info.saved_location = SAVED_NOWHERE;
1884 if (end_of_string) {
1885 *end_of_string = eat_whitespace(eos);
1887 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1888 smartlist_free(tokens);
1889 if (area) {
1890 DUMP_AREA(area, "authority cert");
1891 memarea_drop_all(area);
1893 return cert;
1894 err:
1895 dump_desc(s_dup, "authority cert");
1896 authority_cert_free(cert);
1897 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
1898 smartlist_free(tokens);
1899 if (area) {
1900 DUMP_AREA(area, "authority cert");
1901 memarea_drop_all(area);
1903 return NULL;
1906 /** Helper: given a string <b>s</b>, return the start of the next router-status
1907 * object (starting with "r " at the start of a line). If none is found,
1908 * return the start of the directory footer, or the next directory signature.
1909 * If none is found, return the end of the string. */
1910 static INLINE const char *
1911 find_start_of_next_routerstatus(const char *s)
1913 const char *eos, *footer, *sig;
1914 if ((eos = strstr(s, "\nr ")))
1915 ++eos;
1916 else
1917 eos = s + strlen(s);
1919 footer = tor_memstr(s, eos-s, "\ndirectory-footer");
1920 sig = tor_memstr(s, eos-s, "\ndirectory-signature");
1922 if (footer && sig)
1923 return MIN(footer, sig) + 1;
1924 else if (footer)
1925 return footer+1;
1926 else if (sig)
1927 return sig+1;
1928 else
1929 return eos;
1932 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1933 * empty smartlist at <b>tokens</b>, parse and return the first router status
1934 * object in the string, and advance *<b>s</b> to just after the end of the
1935 * router status. Return NULL and advance *<b>s</b> on error.
1937 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1938 * routerstatus but use <b>vote_rs</b> instead.
1940 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1941 * consensus, and we should parse it according to the method used to
1942 * make that consensus.
1944 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
1946 static routerstatus_t *
1947 routerstatus_parse_entry_from_string(memarea_t *area,
1948 const char **s, smartlist_t *tokens,
1949 networkstatus_t *vote,
1950 vote_routerstatus_t *vote_rs,
1951 int consensus_method,
1952 consensus_flavor_t flav)
1954 const char *eos, *s_dup = *s;
1955 routerstatus_t *rs = NULL;
1956 directory_token_t *tok;
1957 char timebuf[ISO_TIME_LEN+1];
1958 struct in_addr in;
1959 int offset = 0;
1960 tor_assert(tokens);
1961 tor_assert(bool_eq(vote, vote_rs));
1963 if (!consensus_method)
1964 flav = FLAV_NS;
1966 eos = find_start_of_next_routerstatus(*s);
1968 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1969 log_warn(LD_DIR, "Error tokenizing router status");
1970 goto err;
1972 if (smartlist_len(tokens) < 1) {
1973 log_warn(LD_DIR, "Impossibly short router status");
1974 goto err;
1976 tok = find_by_keyword(tokens, K_R);
1977 tor_assert(tok->n_args >= 7);
1978 if (flav == FLAV_NS) {
1979 if (tok->n_args < 8) {
1980 log_warn(LD_DIR, "Too few arguments to r");
1981 goto err;
1983 } else {
1984 offset = -1;
1986 if (vote_rs) {
1987 rs = &vote_rs->status;
1988 } else {
1989 rs = tor_malloc_zero(sizeof(routerstatus_t));
1992 if (!is_legal_nickname(tok->args[0])) {
1993 log_warn(LD_DIR,
1994 "Invalid nickname %s in router status; skipping.",
1995 escaped(tok->args[0]));
1996 goto err;
1998 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
2000 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
2001 log_warn(LD_DIR, "Error decoding identity digest %s",
2002 escaped(tok->args[1]));
2003 goto err;
2006 if (flav == FLAV_NS) {
2007 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
2008 log_warn(LD_DIR, "Error decoding descriptor digest %s",
2009 escaped(tok->args[2]));
2010 goto err;
2014 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
2015 tok->args[3+offset], tok->args[4+offset]) < 0 ||
2016 parse_iso_time(timebuf, &rs->published_on)<0) {
2017 log_warn(LD_DIR, "Error parsing time '%s %s' [%d %d]",
2018 tok->args[3+offset], tok->args[4+offset],
2019 offset, (int)flav);
2020 goto err;
2023 if (tor_inet_aton(tok->args[5+offset], &in) == 0) {
2024 log_warn(LD_DIR, "Error parsing router address in network-status %s",
2025 escaped(tok->args[5+offset]));
2026 goto err;
2028 rs->addr = ntohl(in.s_addr);
2030 rs->or_port = (uint16_t) tor_parse_long(tok->args[6+offset],
2031 10,0,65535,NULL,NULL);
2032 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7+offset],
2033 10,0,65535,NULL,NULL);
2035 tok = find_opt_by_keyword(tokens, K_S);
2036 if (tok && vote) {
2037 int i;
2038 vote_rs->flags = 0;
2039 for (i=0; i < tok->n_args; ++i) {
2040 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
2041 if (p >= 0) {
2042 vote_rs->flags |= (1<<p);
2043 } else {
2044 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
2045 escaped(tok->args[i]));
2046 goto err;
2049 } else if (tok) {
2050 int i;
2051 for (i=0; i < tok->n_args; ++i) {
2052 if (!strcmp(tok->args[i], "Exit"))
2053 rs->is_exit = 1;
2054 else if (!strcmp(tok->args[i], "Stable"))
2055 rs->is_stable = 1;
2056 else if (!strcmp(tok->args[i], "Fast"))
2057 rs->is_fast = 1;
2058 else if (!strcmp(tok->args[i], "Running"))
2059 rs->is_running = 1;
2060 else if (!strcmp(tok->args[i], "Named"))
2061 rs->is_named = 1;
2062 else if (!strcmp(tok->args[i], "Valid"))
2063 rs->is_valid = 1;
2064 else if (!strcmp(tok->args[i], "V2Dir"))
2065 rs->is_v2_dir = 1;
2066 else if (!strcmp(tok->args[i], "Guard"))
2067 rs->is_possible_guard = 1;
2068 else if (!strcmp(tok->args[i], "BadExit"))
2069 rs->is_bad_exit = 1;
2070 else if (!strcmp(tok->args[i], "BadDirectory"))
2071 rs->is_bad_directory = 1;
2072 else if (!strcmp(tok->args[i], "Authority"))
2073 rs->is_authority = 1;
2074 else if (!strcmp(tok->args[i], "Unnamed") &&
2075 consensus_method >= 2) {
2076 /* Unnamed is computed right by consensus method 2 and later. */
2077 rs->is_unnamed = 1;
2078 } else if (!strcmp(tok->args[i], "HSDir")) {
2079 rs->is_hs_dir = 1;
2083 if ((tok = find_opt_by_keyword(tokens, K_V))) {
2084 tor_assert(tok->n_args == 1);
2085 rs->version_known = 1;
2086 if (strcmpstart(tok->args[0], "Tor ")) {
2087 rs->version_supports_begindir = 1;
2088 rs->version_supports_extrainfo_upload = 1;
2089 rs->version_supports_conditional_consensus = 1;
2090 } else {
2091 rs->version_supports_begindir =
2092 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
2093 rs->version_supports_extrainfo_upload =
2094 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
2095 rs->version_supports_v3_dir =
2096 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
2097 rs->version_supports_conditional_consensus =
2098 tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
2100 if (vote_rs) {
2101 vote_rs->version = tor_strdup(tok->args[0]);
2105 /* handle weighting/bandwidth info */
2106 if ((tok = find_opt_by_keyword(tokens, K_W))) {
2107 int i;
2108 for (i=0; i < tok->n_args; ++i) {
2109 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
2110 int ok;
2111 rs->bandwidth = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
2112 10, 0, UINT32_MAX,
2113 &ok, NULL);
2114 if (!ok) {
2115 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
2116 goto err;
2118 rs->has_bandwidth = 1;
2119 } else if (!strcmpstart(tok->args[i], "Measured=")) {
2120 int ok;
2121 rs->measured_bw =
2122 (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
2123 10, 0, UINT32_MAX, &ok, NULL);
2124 if (!ok) {
2125 log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
2126 escaped(tok->args[i]));
2127 goto err;
2129 rs->has_measured_bw = 1;
2134 /* parse exit policy summaries */
2135 if ((tok = find_opt_by_keyword(tokens, K_P))) {
2136 tor_assert(tok->n_args == 1);
2137 if (strcmpstart(tok->args[0], "accept ") &&
2138 strcmpstart(tok->args[0], "reject ")) {
2139 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
2140 escaped(tok->args[0]));
2141 goto err;
2143 /* XXX weasel: parse this into ports and represent them somehow smart,
2144 * maybe not here but somewhere on if we need it for the client.
2145 * we should still parse it here to check it's valid tho.
2147 rs->exitsummary = tor_strdup(tok->args[0]);
2148 rs->has_exitsummary = 1;
2151 if (vote_rs) {
2152 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, t) {
2153 if (t->tp == K_M && t->n_args) {
2154 vote_microdesc_hash_t *line =
2155 tor_malloc(sizeof(vote_microdesc_hash_t));
2156 line->next = vote_rs->microdesc;
2157 line->microdesc_hash_line = tor_strdup(t->args[0]);
2158 vote_rs->microdesc = line;
2160 } SMARTLIST_FOREACH_END(t);
2163 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
2164 rs->is_named = 0;
2166 goto done;
2167 err:
2168 dump_desc(s_dup, "routerstatus entry");
2169 if (rs && !vote_rs)
2170 routerstatus_free(rs);
2171 rs = NULL;
2172 done:
2173 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2174 smartlist_clear(tokens);
2175 if (area) {
2176 DUMP_AREA(area, "routerstatus entry");
2177 memarea_clear(area);
2179 *s = eos;
2181 return rs;
2184 /** Helper to sort a smartlist of pointers to routerstatus_t */
2186 compare_routerstatus_entries(const void **_a, const void **_b)
2188 const routerstatus_t *a = *_a, *b = *_b;
2189 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
2192 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
2193 static void
2194 _free_duplicate_routerstatus_entry(void *e)
2196 log_warn(LD_DIR,
2197 "Network-status has two entries for the same router. "
2198 "Dropping one.");
2199 routerstatus_free(e);
2202 /** Given a v2 network-status object in <b>s</b>, try to
2203 * parse it and return the result. Return NULL on failure. Check the
2204 * signature of the network status, but do not (yet) check the signing key for
2205 * authority.
2207 networkstatus_v2_t *
2208 networkstatus_v2_parse_from_string(const char *s)
2210 const char *eos, *s_dup = s;
2211 smartlist_t *tokens = smartlist_create();
2212 smartlist_t *footer_tokens = smartlist_create();
2213 networkstatus_v2_t *ns = NULL;
2214 char ns_digest[DIGEST_LEN];
2215 char tmp_digest[DIGEST_LEN];
2216 struct in_addr in;
2217 directory_token_t *tok;
2218 int i;
2219 memarea_t *area = NULL;
2221 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
2222 log_warn(LD_DIR, "Unable to compute digest of network-status");
2223 goto err;
2226 area = memarea_new();
2227 eos = find_start_of_next_routerstatus(s);
2228 if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
2229 log_warn(LD_DIR, "Error tokenizing network-status header.");
2230 goto err;
2232 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
2233 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2235 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2236 tor_assert(tok->n_args >= 1);
2237 if (strcmp(tok->args[0], "2")) {
2238 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
2239 "%s", escaped(tok->args[0]));
2240 goto err;
2243 tok = find_by_keyword(tokens, K_DIR_SOURCE);
2244 tor_assert(tok->n_args >= 3);
2245 ns->source_address = tor_strdup(tok->args[0]);
2246 if (tor_inet_aton(tok->args[1], &in) == 0) {
2247 log_warn(LD_DIR, "Error parsing network-status source address %s",
2248 escaped(tok->args[1]));
2249 goto err;
2251 ns->source_addr = ntohl(in.s_addr);
2252 ns->source_dirport =
2253 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
2254 if (ns->source_dirport == 0) {
2255 log_warn(LD_DIR, "Directory source without dirport; skipping.");
2256 goto err;
2259 tok = find_by_keyword(tokens, K_FINGERPRINT);
2260 tor_assert(tok->n_args);
2261 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
2262 strlen(tok->args[0]))) {
2263 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
2264 escaped(tok->args[0]));
2265 goto err;
2268 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2269 tor_assert(tok->n_args);
2270 ns->contact = tor_strdup(tok->args[0]);
2273 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2274 tor_assert(tok->key);
2275 ns->signing_key = tok->key;
2276 tok->key = NULL;
2278 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
2279 log_warn(LD_DIR, "Couldn't compute signing key digest");
2280 goto err;
2282 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
2283 log_warn(LD_DIR,
2284 "network-status fingerprint did not match dir-signing-key");
2285 goto err;
2288 if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
2289 for (i=0; i < tok->n_args; ++i) {
2290 if (!strcmp(tok->args[i], "Names"))
2291 ns->binds_names = 1;
2292 if (!strcmp(tok->args[i], "Versions"))
2293 ns->recommends_versions = 1;
2294 if (!strcmp(tok->args[i], "BadExits"))
2295 ns->lists_bad_exits = 1;
2296 if (!strcmp(tok->args[i], "BadDirectories"))
2297 ns->lists_bad_directories = 1;
2301 if (ns->recommends_versions) {
2302 if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2303 log_warn(LD_DIR, "Missing client-versions on versioning directory");
2304 goto err;
2306 ns->client_versions = tor_strdup(tok->args[0]);
2308 if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
2309 tok->n_args<1) {
2310 log_warn(LD_DIR, "Missing server-versions on versioning directory");
2311 goto err;
2313 ns->server_versions = tor_strdup(tok->args[0]);
2316 tok = find_by_keyword(tokens, K_PUBLISHED);
2317 tor_assert(tok->n_args == 1);
2318 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
2319 goto err;
2322 ns->entries = smartlist_create();
2323 s = eos;
2324 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2325 smartlist_clear(tokens);
2326 memarea_clear(area);
2327 while (!strcmpstart(s, "r ")) {
2328 routerstatus_t *rs;
2329 if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
2330 NULL, NULL, 0, 0)))
2331 smartlist_add(ns->entries, rs);
2333 smartlist_sort(ns->entries, compare_routerstatus_entries);
2334 smartlist_uniq(ns->entries, compare_routerstatus_entries,
2335 _free_duplicate_routerstatus_entry);
2337 if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
2338 log_warn(LD_DIR, "Error tokenizing network-status footer.");
2339 goto err;
2341 if (smartlist_len(footer_tokens) < 1) {
2342 log_warn(LD_DIR, "Too few items in network-status footer.");
2343 goto err;
2345 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
2346 if (tok->tp != K_DIRECTORY_SIGNATURE) {
2347 log_warn(LD_DIR,
2348 "Expected network-status footer to end with a signature.");
2349 goto err;
2352 note_crypto_pk_op(VERIFY_DIR);
2353 if (check_signature_token(ns_digest, DIGEST_LEN, tok, ns->signing_key, 0,
2354 "network-status") < 0)
2355 goto err;
2357 goto done;
2358 err:
2359 dump_desc(s_dup, "v2 networkstatus");
2360 networkstatus_v2_free(ns);
2361 ns = NULL;
2362 done:
2363 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
2364 smartlist_free(tokens);
2365 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
2366 smartlist_free(footer_tokens);
2367 if (area) {
2368 DUMP_AREA(area, "v2 networkstatus");
2369 memarea_drop_all(area);
2371 return ns;
2374 /** Verify the bandwidth weights of a network status document */
2376 networkstatus_verify_bw_weights(networkstatus_t *ns)
2378 int64_t weight_scale;
2379 int64_t G=0, M=0, E=0, D=0, T=0;
2380 double Wgg, Wgm, Wgd, Wmg, Wmm, Wme, Wmd, Weg, Wem, Wee, Wed;
2381 double Gtotal=0, Mtotal=0, Etotal=0;
2382 const char *casename = NULL;
2383 int valid = 1;
2385 weight_scale = circuit_build_times_get_bw_scale(ns);
2386 Wgg = networkstatus_get_bw_weight(ns, "Wgg", -1);
2387 Wgm = networkstatus_get_bw_weight(ns, "Wgm", -1);
2388 Wgd = networkstatus_get_bw_weight(ns, "Wgd", -1);
2389 Wmg = networkstatus_get_bw_weight(ns, "Wmg", -1);
2390 Wmm = networkstatus_get_bw_weight(ns, "Wmm", -1);
2391 Wme = networkstatus_get_bw_weight(ns, "Wme", -1);
2392 Wmd = networkstatus_get_bw_weight(ns, "Wmd", -1);
2393 Weg = networkstatus_get_bw_weight(ns, "Weg", -1);
2394 Wem = networkstatus_get_bw_weight(ns, "Wem", -1);
2395 Wee = networkstatus_get_bw_weight(ns, "Wee", -1);
2396 Wed = networkstatus_get_bw_weight(ns, "Wed", -1);
2398 if (Wgg<0 || Wgm<0 || Wgd<0 || Wmg<0 || Wmm<0 || Wme<0 || Wmd<0 || Weg<0
2399 || Wem<0 || Wee<0 || Wed<0) {
2400 log_warn(LD_BUG, "No bandwidth weights produced in consensus!");
2401 return 0;
2404 // First, sanity check basic summing properties that hold for all cases
2405 // We use > 1 as the check for these because they are computed as integers.
2406 // Sometimes there are rounding errors.
2407 if (fabs(Wmm - weight_scale) > 1) {
2408 log_warn(LD_BUG, "Wmm=%lf != "I64_FORMAT,
2409 Wmm, I64_PRINTF_ARG(weight_scale));
2410 valid = 0;
2413 if (fabs(Wem - Wee) > 1) {
2414 log_warn(LD_BUG, "Wem=%lf != Wee=%lf", Wem, Wee);
2415 valid = 0;
2418 if (fabs(Wgm - Wgg) > 1) {
2419 log_warn(LD_BUG, "Wgm=%lf != Wgg=%lf", Wgm, Wgg);
2420 valid = 0;
2423 if (fabs(Weg - Wed) > 1) {
2424 log_warn(LD_BUG, "Wed=%lf != Weg=%lf", Wed, Weg);
2425 valid = 0;
2428 if (fabs(Wgg + Wmg - weight_scale) > 0.001*weight_scale) {
2429 log_warn(LD_BUG, "Wgg=%lf != "I64_FORMAT" - Wmg=%lf", Wgg,
2430 I64_PRINTF_ARG(weight_scale), Wmg);
2431 valid = 0;
2434 if (fabs(Wee + Wme - weight_scale) > 0.001*weight_scale) {
2435 log_warn(LD_BUG, "Wee=%lf != "I64_FORMAT" - Wme=%lf", Wee,
2436 I64_PRINTF_ARG(weight_scale), Wme);
2437 valid = 0;
2440 if (fabs(Wgd + Wmd + Wed - weight_scale) > 0.001*weight_scale) {
2441 log_warn(LD_BUG, "Wgd=%lf + Wmd=%lf + Wed=%lf != "I64_FORMAT,
2442 Wgd, Wmd, Wed, I64_PRINTF_ARG(weight_scale));
2443 valid = 0;
2446 Wgg /= weight_scale;
2447 Wgm /= weight_scale;
2448 Wgd /= weight_scale;
2450 Wmg /= weight_scale;
2451 Wmm /= weight_scale;
2452 Wme /= weight_scale;
2453 Wmd /= weight_scale;
2455 Weg /= weight_scale;
2456 Wem /= weight_scale;
2457 Wee /= weight_scale;
2458 Wed /= weight_scale;
2460 // Then, gather G, M, E, D, T to determine case
2461 SMARTLIST_FOREACH_BEGIN(ns->routerstatus_list, routerstatus_t *, rs) {
2462 if (rs->has_bandwidth) {
2463 T += rs->bandwidth;
2464 if (rs->is_exit && rs->is_possible_guard) {
2465 D += rs->bandwidth;
2466 Gtotal += Wgd*rs->bandwidth;
2467 Mtotal += Wmd*rs->bandwidth;
2468 Etotal += Wed*rs->bandwidth;
2469 } else if (rs->is_exit) {
2470 E += rs->bandwidth;
2471 Mtotal += Wme*rs->bandwidth;
2472 Etotal += Wee*rs->bandwidth;
2473 } else if (rs->is_possible_guard) {
2474 G += rs->bandwidth;
2475 Gtotal += Wgg*rs->bandwidth;
2476 Mtotal += Wmg*rs->bandwidth;
2477 } else {
2478 M += rs->bandwidth;
2479 Mtotal += Wmm*rs->bandwidth;
2481 } else {
2482 log_warn(LD_BUG, "Missing consensus bandwidth for router %s",
2483 rs->nickname);
2485 } SMARTLIST_FOREACH_END(rs);
2487 // Finally, check equality conditions depending upon case 1, 2 or 3
2488 // Full equality cases: 1, 3b
2489 // Partial equality cases: 2b (E=G), 3a (M=E)
2490 // Fully unknown: 2a
2491 if (3*E >= T && 3*G >= T) {
2492 // Case 1: Neither are scarce
2493 casename = "Case 1";
2494 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2495 log_warn(LD_DIR,
2496 "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
2497 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2498 " T="I64_FORMAT". "
2499 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2500 casename, Etotal, Mtotal,
2501 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2502 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2503 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2504 valid = 0;
2506 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2507 log_warn(LD_DIR,
2508 "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
2509 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2510 " T="I64_FORMAT". "
2511 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2512 casename, Etotal, Gtotal,
2513 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2514 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2515 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2516 valid = 0;
2518 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2519 log_warn(LD_DIR,
2520 "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
2521 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2522 " T="I64_FORMAT". "
2523 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2524 casename, Mtotal, Gtotal,
2525 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2526 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2527 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2528 valid = 0;
2530 } else if (3*E < T && 3*G < T) {
2531 int64_t R = MIN(E, G);
2532 int64_t S = MAX(E, G);
2534 * Case 2: Both Guards and Exits are scarce
2535 * Balance D between E and G, depending upon
2536 * D capacity and scarcity. Devote no extra
2537 * bandwidth to middle nodes.
2539 if (R+D < S) { // Subcase a
2540 double Rtotal, Stotal;
2541 if (E < G) {
2542 Rtotal = Etotal;
2543 Stotal = Gtotal;
2544 } else {
2545 Rtotal = Gtotal;
2546 Stotal = Etotal;
2548 casename = "Case 2a";
2549 // Rtotal < Stotal
2550 if (Rtotal > Stotal) {
2551 log_warn(LD_DIR,
2552 "Bw Weight Failure for %s: Rtotal %lf > Stotal %lf. "
2553 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2554 " T="I64_FORMAT". "
2555 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2556 casename, Rtotal, Stotal,
2557 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2558 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2559 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2560 valid = 0;
2562 // Rtotal < T/3
2563 if (3*Rtotal > T) {
2564 log_warn(LD_DIR,
2565 "Bw Weight Failure for %s: 3*Rtotal %lf > T "
2566 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2567 " D="I64_FORMAT" T="I64_FORMAT". "
2568 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2569 casename, Rtotal*3, I64_PRINTF_ARG(T),
2570 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2571 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2572 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2573 valid = 0;
2575 // Stotal < T/3
2576 if (3*Stotal > T) {
2577 log_warn(LD_DIR,
2578 "Bw Weight Failure for %s: 3*Stotal %lf > T "
2579 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2580 " D="I64_FORMAT" T="I64_FORMAT". "
2581 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2582 casename, Stotal*3, I64_PRINTF_ARG(T),
2583 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2584 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2585 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2586 valid = 0;
2588 // Mtotal > T/3
2589 if (3*Mtotal < T) {
2590 log_warn(LD_DIR,
2591 "Bw Weight Failure for %s: 3*Mtotal %lf < T "
2592 I64_FORMAT". "
2593 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2594 " T="I64_FORMAT". "
2595 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2596 casename, Mtotal*3, I64_PRINTF_ARG(T),
2597 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2598 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2599 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2600 valid = 0;
2602 } else { // Subcase b: R+D > S
2603 casename = "Case 2b";
2605 /* Check the rare-M redirect case. */
2606 if (D != 0 && 3*M < T) {
2607 casename = "Case 2b (balanced)";
2608 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2609 log_warn(LD_DIR,
2610 "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
2611 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2612 " T="I64_FORMAT". "
2613 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2614 casename, Etotal, Mtotal,
2615 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2616 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2617 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2618 valid = 0;
2620 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2621 log_warn(LD_DIR,
2622 "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
2623 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2624 " T="I64_FORMAT". "
2625 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2626 casename, Etotal, Gtotal,
2627 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2628 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2629 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2630 valid = 0;
2632 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2633 log_warn(LD_DIR,
2634 "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
2635 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2636 " T="I64_FORMAT". "
2637 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2638 casename, Mtotal, Gtotal,
2639 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2640 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2641 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2642 valid = 0;
2644 } else {
2645 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2646 log_warn(LD_DIR,
2647 "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
2648 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2649 " T="I64_FORMAT". "
2650 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2651 casename, Etotal, Gtotal,
2652 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2653 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2654 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2655 valid = 0;
2659 } else { // if (E < T/3 || G < T/3) {
2660 int64_t S = MIN(E, G);
2661 int64_t NS = MAX(E, G);
2662 if (3*(S+D) < T) { // Subcase a:
2663 double Stotal;
2664 double NStotal;
2665 if (G < E) {
2666 casename = "Case 3a (G scarce)";
2667 Stotal = Gtotal;
2668 NStotal = Etotal;
2669 } else { // if (G >= E) {
2670 casename = "Case 3a (E scarce)";
2671 NStotal = Gtotal;
2672 Stotal = Etotal;
2674 // Stotal < T/3
2675 if (3*Stotal > T) {
2676 log_warn(LD_DIR,
2677 "Bw Weight Failure for %s: 3*Stotal %lf > T "
2678 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT
2679 " D="I64_FORMAT" T="I64_FORMAT". "
2680 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2681 casename, Stotal*3, I64_PRINTF_ARG(T),
2682 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2683 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2684 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2685 valid = 0;
2687 if (NS >= M) {
2688 if (fabs(NStotal-Mtotal) > 0.01*MAX(NStotal,Mtotal)) {
2689 log_warn(LD_DIR,
2690 "Bw Weight Failure for %s: NStotal %lf != Mtotal %lf. "
2691 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2692 " T="I64_FORMAT". "
2693 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2694 casename, NStotal, Mtotal,
2695 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2696 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2697 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2698 valid = 0;
2700 } else {
2701 // if NS < M, NStotal > T/3 because only one of G or E is scarce
2702 if (3*NStotal < T) {
2703 log_warn(LD_DIR,
2704 "Bw Weight Failure for %s: 3*NStotal %lf < T "
2705 I64_FORMAT". G="I64_FORMAT" M="I64_FORMAT
2706 " E="I64_FORMAT" D="I64_FORMAT" T="I64_FORMAT". "
2707 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2708 casename, NStotal*3, I64_PRINTF_ARG(T),
2709 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2710 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2711 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2712 valid = 0;
2715 } else { // Subcase b: S+D >= T/3
2716 casename = "Case 3b";
2717 if (fabs(Etotal-Mtotal) > 0.01*MAX(Etotal,Mtotal)) {
2718 log_warn(LD_DIR,
2719 "Bw Weight Failure for %s: Etotal %lf != Mtotal %lf. "
2720 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2721 " T="I64_FORMAT". "
2722 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2723 casename, Etotal, Mtotal,
2724 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2725 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2726 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2727 valid = 0;
2729 if (fabs(Etotal-Gtotal) > 0.01*MAX(Etotal,Gtotal)) {
2730 log_warn(LD_DIR,
2731 "Bw Weight Failure for %s: Etotal %lf != Gtotal %lf. "
2732 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2733 " T="I64_FORMAT". "
2734 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2735 casename, Etotal, Gtotal,
2736 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2737 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2738 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2739 valid = 0;
2741 if (fabs(Gtotal-Mtotal) > 0.01*MAX(Gtotal,Mtotal)) {
2742 log_warn(LD_DIR,
2743 "Bw Weight Failure for %s: Mtotal %lf != Gtotal %lf. "
2744 "G="I64_FORMAT" M="I64_FORMAT" E="I64_FORMAT" D="I64_FORMAT
2745 " T="I64_FORMAT". "
2746 "Wgg=%lf Wgd=%lf Wmg=%lf Wme=%lf Wmd=%lf Wee=%lf Wed=%lf",
2747 casename, Mtotal, Gtotal,
2748 I64_PRINTF_ARG(G), I64_PRINTF_ARG(M), I64_PRINTF_ARG(E),
2749 I64_PRINTF_ARG(D), I64_PRINTF_ARG(T),
2750 Wgg, Wgd, Wmg, Wme, Wmd, Wee, Wed);
2751 valid = 0;
2756 if (valid)
2757 log_notice(LD_DIR, "Bandwidth-weight %s is verified and valid.",
2758 casename);
2760 return valid;
2763 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2764 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2765 networkstatus_t *
2766 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2767 networkstatus_type_t ns_type)
2769 smartlist_t *tokens = smartlist_create();
2770 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2771 networkstatus_voter_info_t *voter = NULL;
2772 networkstatus_t *ns = NULL;
2773 digests_t ns_digests;
2774 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
2775 directory_token_t *tok;
2776 int ok;
2777 struct in_addr in;
2778 int i, inorder, n_signatures = 0;
2779 memarea_t *area = NULL, *rs_area = NULL;
2780 consensus_flavor_t flav = FLAV_NS;
2782 tor_assert(s);
2784 if (eos_out)
2785 *eos_out = NULL;
2787 if (router_get_networkstatus_v3_hashes(s, &ns_digests)) {
2788 log_warn(LD_DIR, "Unable to compute digest of network-status");
2789 goto err;
2792 area = memarea_new();
2793 end_of_header = find_start_of_next_routerstatus(s);
2794 if (tokenize_string(area, s, end_of_header, tokens,
2795 (ns_type == NS_TYPE_CONSENSUS) ?
2796 networkstatus_consensus_token_table :
2797 networkstatus_token_table, 0)) {
2798 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2799 goto err;
2802 ns = tor_malloc_zero(sizeof(networkstatus_t));
2803 memcpy(&ns->digests, &ns_digests, sizeof(ns_digests));
2805 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2806 tor_assert(tok);
2807 if (tok->n_args > 1) {
2808 int flavor = networkstatus_parse_flavor_name(tok->args[1]);
2809 if (flavor < 0) {
2810 log_warn(LD_DIR, "Can't parse document with unknown flavor %s",
2811 escaped(tok->args[2]));
2812 goto err;
2814 ns->flavor = flav = flavor;
2816 if (flav != FLAV_NS && ns_type != NS_TYPE_CONSENSUS) {
2817 log_warn(LD_DIR, "Flavor found on non-consenus networkstatus.");
2818 goto err;
2821 if (ns_type != NS_TYPE_CONSENSUS) {
2822 const char *end_of_cert = NULL;
2823 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2824 goto err;
2825 ++cert;
2826 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2827 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2828 goto err;
2831 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2832 tor_assert(tok->n_args);
2833 if (!strcmp(tok->args[0], "vote")) {
2834 ns->type = NS_TYPE_VOTE;
2835 } else if (!strcmp(tok->args[0], "consensus")) {
2836 ns->type = NS_TYPE_CONSENSUS;
2837 } else if (!strcmp(tok->args[0], "opinion")) {
2838 ns->type = NS_TYPE_OPINION;
2839 } else {
2840 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2841 escaped(tok->args[0]));
2842 goto err;
2844 if (ns_type != ns->type) {
2845 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2846 goto err;
2849 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2850 tok = find_by_keyword(tokens, K_PUBLISHED);
2851 if (parse_iso_time(tok->args[0], &ns->published))
2852 goto err;
2854 ns->supported_methods = smartlist_create();
2855 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2856 if (tok) {
2857 for (i=0; i < tok->n_args; ++i)
2858 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2859 } else {
2860 smartlist_add(ns->supported_methods, tor_strdup("1"));
2862 } else {
2863 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2864 if (tok) {
2865 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2866 &ok, NULL);
2867 if (!ok)
2868 goto err;
2869 } else {
2870 ns->consensus_method = 1;
2874 tok = find_by_keyword(tokens, K_VALID_AFTER);
2875 if (parse_iso_time(tok->args[0], &ns->valid_after))
2876 goto err;
2878 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2879 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2880 goto err;
2882 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2883 if (parse_iso_time(tok->args[0], &ns->valid_until))
2884 goto err;
2886 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2887 tor_assert(tok->n_args >= 2);
2888 ns->vote_seconds =
2889 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2890 if (!ok)
2891 goto err;
2892 ns->dist_seconds =
2893 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2894 if (!ok)
2895 goto err;
2896 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2897 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2898 goto err;
2900 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2901 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2902 goto err;
2904 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2905 log_warn(LD_DIR, "Vote seconds is too short");
2906 goto err;
2908 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2909 log_warn(LD_DIR, "Dist seconds is too short");
2910 goto err;
2913 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2914 ns->client_versions = tor_strdup(tok->args[0]);
2916 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2917 ns->server_versions = tor_strdup(tok->args[0]);
2920 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2921 ns->known_flags = smartlist_create();
2922 inorder = 1;
2923 for (i = 0; i < tok->n_args; ++i) {
2924 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2925 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2926 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2927 inorder = 0;
2930 if (!inorder) {
2931 log_warn(LD_DIR, "known-flags not in order");
2932 goto err;
2935 tok = find_opt_by_keyword(tokens, K_PARAMS);
2936 if (tok) {
2937 inorder = 1;
2938 ns->net_params = smartlist_create();
2939 for (i = 0; i < tok->n_args; ++i) {
2940 int ok=0;
2941 char *eq = strchr(tok->args[i], '=');
2942 if (!eq) {
2943 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2944 goto err;
2946 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
2947 if (!ok) {
2948 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2949 goto err;
2951 if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
2952 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2953 inorder = 0;
2955 smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
2957 if (!inorder) {
2958 log_warn(LD_DIR, "params not in order");
2959 goto err;
2963 ns->voters = smartlist_create();
2965 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
2966 tok = _tok;
2967 if (tok->tp == K_DIR_SOURCE) {
2968 tor_assert(tok->n_args >= 6);
2970 if (voter)
2971 smartlist_add(ns->voters, voter);
2972 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2973 voter->sigs = smartlist_create();
2974 if (ns->type != NS_TYPE_CONSENSUS)
2975 memcpy(voter->vote_digest, ns_digests.d[DIGEST_SHA1], DIGEST_LEN);
2977 voter->nickname = tor_strdup(tok->args[0]);
2978 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2979 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2980 tok->args[1], HEX_DIGEST_LEN) < 0) {
2981 log_warn(LD_DIR, "Error decoding identity digest %s in "
2982 "network-status vote.", escaped(tok->args[1]));
2983 goto err;
2985 if (ns->type != NS_TYPE_CONSENSUS &&
2986 memcmp(ns->cert->cache_info.identity_digest,
2987 voter->identity_digest, DIGEST_LEN)) {
2988 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2989 goto err;
2991 voter->address = tor_strdup(tok->args[2]);
2992 if (!tor_inet_aton(tok->args[3], &in)) {
2993 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2994 escaped(tok->args[3]));
2995 goto err;
2997 voter->addr = ntohl(in.s_addr);
2998 voter->dir_port = (uint16_t)
2999 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
3000 if (!ok)
3001 goto err;
3002 voter->or_port = (uint16_t)
3003 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
3004 if (!ok)
3005 goto err;
3006 } else if (tok->tp == K_CONTACT) {
3007 if (!voter || voter->contact) {
3008 log_warn(LD_DIR, "contact element is out of place.");
3009 goto err;
3011 voter->contact = tor_strdup(tok->args[0]);
3012 } else if (tok->tp == K_VOTE_DIGEST) {
3013 tor_assert(ns->type == NS_TYPE_CONSENSUS);
3014 tor_assert(tok->n_args >= 1);
3015 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
3016 log_warn(LD_DIR, "vote-digest element is out of place.");
3017 goto err;
3019 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
3020 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
3021 tok->args[0], HEX_DIGEST_LEN) < 0) {
3022 log_warn(LD_DIR, "Error decoding vote digest %s in "
3023 "network-status consensus.", escaped(tok->args[0]));
3024 goto err;
3027 } SMARTLIST_FOREACH_END(_tok);
3028 if (voter) {
3029 smartlist_add(ns->voters, voter);
3030 voter = NULL;
3032 if (smartlist_len(ns->voters) == 0) {
3033 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
3034 goto err;
3035 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
3036 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
3037 goto err;
3040 if (ns->type != NS_TYPE_CONSENSUS &&
3041 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
3042 int bad = 1;
3043 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
3044 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
3045 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
3046 tok->args[0], HEX_DIGEST_LEN)<0)
3047 bad = 1;
3048 else
3049 bad = 0;
3051 if (bad) {
3052 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
3053 escaped(tok->args[0]));
3057 /* Parse routerstatus lines. */
3058 rs_tokens = smartlist_create();
3059 rs_area = memarea_new();
3060 s = end_of_header;
3061 ns->routerstatus_list = smartlist_create();
3063 while (!strcmpstart(s, "r ")) {
3064 if (ns->type != NS_TYPE_CONSENSUS) {
3065 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
3066 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
3067 rs, 0, 0))
3068 smartlist_add(ns->routerstatus_list, rs);
3069 else {
3070 tor_free(rs->version);
3071 tor_free(rs);
3073 } else {
3074 routerstatus_t *rs;
3075 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
3076 NULL, NULL,
3077 ns->consensus_method,
3078 flav)))
3079 smartlist_add(ns->routerstatus_list, rs);
3082 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
3083 routerstatus_t *rs1, *rs2;
3084 if (ns->type != NS_TYPE_CONSENSUS) {
3085 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
3086 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
3087 rs1 = &a->status; rs2 = &b->status;
3088 } else {
3089 rs1 = smartlist_get(ns->routerstatus_list, i-1);
3090 rs2 = smartlist_get(ns->routerstatus_list, i);
3092 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
3093 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
3094 "digest");
3095 goto err;
3099 /* Parse footer; check signature. */
3100 footer_tokens = smartlist_create();
3101 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
3102 ++end_of_footer;
3103 else
3104 end_of_footer = s + strlen(s);
3105 if (tokenize_string(area,s, end_of_footer, footer_tokens,
3106 networkstatus_vote_footer_token_table, 0)) {
3107 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
3108 goto err;
3112 int found_sig = 0;
3113 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
3114 tok = _tok;
3115 if (tok->tp == K_DIRECTORY_SIGNATURE)
3116 found_sig = 1;
3117 else if (found_sig) {
3118 log_warn(LD_DIR, "Extraneous token after first directory-signature");
3119 goto err;
3121 } SMARTLIST_FOREACH_END(_tok);
3124 if ((tok = find_opt_by_keyword(footer_tokens, K_DIRECTORY_FOOTER))) {
3125 if (tok != smartlist_get(footer_tokens, 0)) {
3126 log_warn(LD_DIR, "Misplaced directory-footer token");
3127 goto err;
3131 tok = find_opt_by_keyword(footer_tokens, K_BW_WEIGHTS);
3132 if (tok) {
3133 ns->weight_params = smartlist_create();
3134 for (i = 0; i < tok->n_args; ++i) {
3135 int ok=0;
3136 char *eq = strchr(tok->args[i], '=');
3137 if (!eq) {
3138 log_warn(LD_DIR, "Bad element '%s' in weight params",
3139 escaped(tok->args[i]));
3140 goto err;
3142 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
3143 if (!ok) {
3144 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
3145 goto err;
3147 smartlist_add(ns->weight_params, tor_strdup(tok->args[i]));
3151 SMARTLIST_FOREACH_BEGIN(footer_tokens, directory_token_t *, _tok) {
3152 char declared_identity[DIGEST_LEN];
3153 networkstatus_voter_info_t *v;
3154 document_signature_t *sig;
3155 const char *id_hexdigest = NULL;
3156 const char *sk_hexdigest = NULL;
3157 digest_algorithm_t alg = DIGEST_SHA1;
3158 tok = _tok;
3159 if (tok->tp != K_DIRECTORY_SIGNATURE)
3160 continue;
3161 tor_assert(tok->n_args >= 2);
3162 if (tok->n_args == 2) {
3163 id_hexdigest = tok->args[0];
3164 sk_hexdigest = tok->args[1];
3165 } else {
3166 const char *algname = tok->args[0];
3167 int a;
3168 id_hexdigest = tok->args[1];
3169 sk_hexdigest = tok->args[2];
3170 a = crypto_digest_algorithm_parse_name(algname);
3171 if (a<0) {
3172 log_warn(LD_DIR, "Unknown digest algorithm %s; skipping",
3173 escaped(algname));
3174 continue;
3176 alg = a;
3179 if (!tok->object_type ||
3180 strcmp(tok->object_type, "SIGNATURE") ||
3181 tok->object_size < 128 || tok->object_size > 512) {
3182 log_warn(LD_DIR, "Bad object type or length on directory-signature");
3183 goto err;
3186 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
3187 base16_decode(declared_identity, sizeof(declared_identity),
3188 id_hexdigest, HEX_DIGEST_LEN) < 0) {
3189 log_warn(LD_DIR, "Error decoding declared identity %s in "
3190 "network-status vote.", escaped(id_hexdigest));
3191 goto err;
3193 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
3194 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
3195 "any declared directory source.");
3196 goto err;
3198 sig = tor_malloc_zero(sizeof(document_signature_t));
3199 memcpy(sig->identity_digest, v->identity_digest, DIGEST_LEN);
3200 sig->alg = alg;
3201 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
3202 base16_decode(sig->signing_key_digest, sizeof(sig->signing_key_digest),
3203 sk_hexdigest, HEX_DIGEST_LEN) < 0) {
3204 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
3205 "network-status vote.", escaped(sk_hexdigest));
3206 tor_free(sig);
3207 goto err;
3210 if (ns->type != NS_TYPE_CONSENSUS) {
3211 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
3212 DIGEST_LEN)) {
3213 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
3214 "network-status vote.");
3215 tor_free(sig);
3216 goto err;
3220 if (voter_get_sig_by_algorithm(v, sig->alg)) {
3221 /* We already parsed a vote with this algorithm from this voter. Use the
3222 first one. */
3223 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
3224 "that contains two votes from the same voter with the same "
3225 "algorithm. Ignoring the second vote.");
3226 tor_free(sig);
3227 continue;
3230 if (ns->type != NS_TYPE_CONSENSUS) {
3231 if (check_signature_token(ns_digests.d[DIGEST_SHA1], DIGEST_LEN,
3232 tok, ns->cert->signing_key, 0,
3233 "network-status vote")) {
3234 tor_free(sig);
3235 goto err;
3237 sig->good_signature = 1;
3238 } else {
3239 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
3240 tor_free(sig);
3241 goto err;
3243 sig->signature = tor_memdup(tok->object_body, tok->object_size);
3244 sig->signature_len = (int) tok->object_size;
3246 smartlist_add(v->sigs, sig);
3248 ++n_signatures;
3249 } SMARTLIST_FOREACH_END(_tok);
3251 if (! n_signatures) {
3252 log_warn(LD_DIR, "No signatures on networkstatus vote.");
3253 goto err;
3254 } else if (ns->type == NS_TYPE_VOTE && n_signatures != 1) {
3255 log_warn(LD_DIR, "Received more than one signature on a "
3256 "network-status vote.");
3257 goto err;
3260 if (eos_out)
3261 *eos_out = end_of_footer;
3263 goto done;
3264 err:
3265 dump_desc(s_dup, "v3 networkstatus");
3266 networkstatus_vote_free(ns);
3267 ns = NULL;
3268 done:
3269 if (tokens) {
3270 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3271 smartlist_free(tokens);
3273 if (voter) {
3274 if (voter->sigs) {
3275 SMARTLIST_FOREACH(voter->sigs, document_signature_t *, sig,
3276 document_signature_free(sig));
3277 smartlist_free(voter->sigs);
3279 tor_free(voter->nickname);
3280 tor_free(voter->address);
3281 tor_free(voter->contact);
3282 tor_free(voter);
3284 if (rs_tokens) {
3285 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_clear(t));
3286 smartlist_free(rs_tokens);
3288 if (footer_tokens) {
3289 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_clear(t));
3290 smartlist_free(footer_tokens);
3292 if (area) {
3293 DUMP_AREA(area, "v3 networkstatus");
3294 memarea_drop_all(area);
3296 if (rs_area)
3297 memarea_drop_all(rs_area);
3299 return ns;
3302 /** Return the digests_t that holds the digests of the
3303 * <b>flavor_name</b>-flavored networkstatus according to the detached
3304 * signatures document <b>sigs</b>, allocating a new digests_t as neeeded. */
3305 static digests_t *
3306 detached_get_digests(ns_detached_signatures_t *sigs, const char *flavor_name)
3308 digests_t *d = strmap_get(sigs->digests, flavor_name);
3309 if (!d) {
3310 d = tor_malloc_zero(sizeof(digests_t));
3311 strmap_set(sigs->digests, flavor_name, d);
3313 return d;
3316 /** Return the list of signatures of the <b>flavor_name</b>-flavored
3317 * networkstatus according to the detached signatures document <b>sigs</b>,
3318 * allocating a new digests_t as neeeded. */
3319 static smartlist_t *
3320 detached_get_signatures(ns_detached_signatures_t *sigs,
3321 const char *flavor_name)
3323 smartlist_t *sl = strmap_get(sigs->signatures, flavor_name);
3324 if (!sl) {
3325 sl = smartlist_create();
3326 strmap_set(sigs->signatures, flavor_name, sl);
3328 return sl;
3331 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
3332 * <b>eos</b> and return the result. Return -1 on failure. */
3333 ns_detached_signatures_t *
3334 networkstatus_parse_detached_signatures(const char *s, const char *eos)
3336 /* XXXX there is too much duplicate shared between this function and
3337 * networkstatus_parse_vote_from_string(). */
3338 directory_token_t *tok;
3339 memarea_t *area = NULL;
3340 digests_t *digests;
3342 smartlist_t *tokens = smartlist_create();
3343 ns_detached_signatures_t *sigs =
3344 tor_malloc_zero(sizeof(ns_detached_signatures_t));
3345 sigs->digests = strmap_new();
3346 sigs->signatures = strmap_new();
3348 if (!eos)
3349 eos = s + strlen(s);
3351 area = memarea_new();
3352 if (tokenize_string(area,s, eos, tokens,
3353 networkstatus_detached_signature_token_table, 0)) {
3354 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
3355 goto err;
3358 /* Grab all the digest-like tokens. */
3359 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3360 const char *algname;
3361 digest_algorithm_t alg;
3362 const char *flavor;
3363 const char *hexdigest;
3364 size_t expected_length;
3366 tok = _tok;
3368 if (tok->tp == K_CONSENSUS_DIGEST) {
3369 algname = "sha1";
3370 alg = DIGEST_SHA1;
3371 flavor = "ns";
3372 hexdigest = tok->args[0];
3373 } else if (tok->tp == K_ADDITIONAL_DIGEST) {
3374 int a = crypto_digest_algorithm_parse_name(tok->args[1]);
3375 if (a<0) {
3376 log_warn(LD_DIR, "Unrecognized algorithm name %s", tok->args[0]);
3377 continue;
3379 alg = (digest_algorithm_t) a;
3380 flavor = tok->args[0];
3381 algname = tok->args[1];
3382 hexdigest = tok->args[2];
3383 } else {
3384 continue;
3387 expected_length =
3388 (alg == DIGEST_SHA1) ? HEX_DIGEST_LEN : HEX_DIGEST256_LEN;
3390 if (strlen(hexdigest) != expected_length) {
3391 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
3392 "networkstatus signatures");
3393 goto err;
3395 digests = detached_get_digests(sigs, flavor);
3396 tor_assert(digests);
3397 if (!tor_mem_is_zero(digests->d[alg], DIGEST256_LEN)) {
3398 log_warn(LD_DIR, "Multiple digests for %s with %s on detached "
3399 "signatures document", flavor, algname);
3400 continue;
3402 if (base16_decode(digests->d[alg], DIGEST256_LEN,
3403 hexdigest, strlen(hexdigest)) < 0) {
3404 log_warn(LD_DIR, "Bad encoding on consensus-digest in detached "
3405 "networkstatus signatures");
3406 goto err;
3408 } SMARTLIST_FOREACH_END(_tok);
3410 tok = find_by_keyword(tokens, K_VALID_AFTER);
3411 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
3412 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
3413 goto err;
3416 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
3417 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
3418 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
3419 goto err;
3422 tok = find_by_keyword(tokens, K_VALID_UNTIL);
3423 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
3424 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
3425 goto err;
3428 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
3429 const char *id_hexdigest;
3430 const char *sk_hexdigest;
3431 const char *algname;
3432 const char *flavor;
3433 digest_algorithm_t alg;
3435 char id_digest[DIGEST_LEN];
3436 char sk_digest[DIGEST_LEN];
3437 smartlist_t *siglist;
3438 document_signature_t *sig;
3439 int is_duplicate;
3441 tok = _tok;
3442 if (tok->tp == K_DIRECTORY_SIGNATURE) {
3443 tor_assert(tok->n_args >= 2);
3444 flavor = "ns";
3445 algname = "sha1";
3446 id_hexdigest = tok->args[0];
3447 sk_hexdigest = tok->args[1];
3448 } else if (tok->tp == K_ADDITIONAL_SIGNATURE) {
3449 tor_assert(tok->n_args >= 4);
3450 flavor = tok->args[0];
3451 algname = tok->args[1];
3452 id_hexdigest = tok->args[2];
3453 sk_hexdigest = tok->args[3];
3454 } else {
3455 continue;
3459 int a = crypto_digest_algorithm_parse_name(algname);
3460 if (a<0) {
3461 log_warn(LD_DIR, "Unrecognized algorithm name %s", algname);
3462 continue;
3464 alg = (digest_algorithm_t) a;
3467 if (!tok->object_type ||
3468 strcmp(tok->object_type, "SIGNATURE") ||
3469 tok->object_size < 128 || tok->object_size > 512) {
3470 log_warn(LD_DIR, "Bad object type or length on directory-signature");
3471 goto err;
3474 if (strlen(id_hexdigest) != HEX_DIGEST_LEN ||
3475 base16_decode(id_digest, sizeof(id_digest),
3476 id_hexdigest, HEX_DIGEST_LEN) < 0) {
3477 log_warn(LD_DIR, "Error decoding declared identity %s in "
3478 "network-status vote.", escaped(id_hexdigest));
3479 goto err;
3481 if (strlen(sk_hexdigest) != HEX_DIGEST_LEN ||
3482 base16_decode(sk_digest, sizeof(sk_digest),
3483 sk_hexdigest, HEX_DIGEST_LEN) < 0) {
3484 log_warn(LD_DIR, "Error decoding declared signing key digest %s in "
3485 "network-status vote.", escaped(sk_hexdigest));
3486 goto err;
3489 siglist = detached_get_signatures(sigs, flavor);
3490 is_duplicate = 0;
3491 SMARTLIST_FOREACH(siglist, document_signature_t *, s, {
3492 if (s->alg == alg &&
3493 !memcmp(id_digest, s->identity_digest, DIGEST_LEN) &&
3494 !memcmp(sk_digest, s->signing_key_digest, DIGEST_LEN)) {
3495 is_duplicate = 1;
3498 if (is_duplicate) {
3499 log_warn(LD_DIR, "Two signatures with identical keys and algorithm "
3500 "found.");
3501 continue;
3504 sig = tor_malloc_zero(sizeof(document_signature_t));
3505 sig->alg = alg;
3506 memcpy(sig->identity_digest, id_digest, DIGEST_LEN);
3507 memcpy(sig->signing_key_digest, sk_digest, DIGEST_LEN);
3508 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING) {
3509 tor_free(sig);
3510 goto err;
3512 sig->signature = tor_memdup(tok->object_body, tok->object_size);
3513 sig->signature_len = (int) tok->object_size;
3515 smartlist_add(siglist, sig);
3516 } SMARTLIST_FOREACH_END(_tok);
3518 goto done;
3519 err:
3520 ns_detached_signatures_free(sigs);
3521 sigs = NULL;
3522 done:
3523 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
3524 smartlist_free(tokens);
3525 if (area) {
3526 DUMP_AREA(area, "detached signatures");
3527 memarea_drop_all(area);
3529 return sigs;
3532 /** Parse the addr policy in the string <b>s</b> and return it. If
3533 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
3534 * ADDR_POLICY_REJECT) for items that specify no action.
3536 addr_policy_t *
3537 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
3539 directory_token_t *tok = NULL;
3540 const char *cp, *eos;
3541 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
3542 * But note that there can be an arbitrary amount of space between the
3543 * accept and the address:mask/port element. */
3544 char line[TOR_ADDR_BUF_LEN*2 + 32];
3545 addr_policy_t *r;
3546 memarea_t *area = NULL;
3548 s = eat_whitespace(s);
3549 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
3550 if (tor_snprintf(line, sizeof(line), "%s %s",
3551 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
3552 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
3553 return NULL;
3555 cp = line;
3556 tor_strlower(line);
3557 } else { /* assume an already well-formed address policy line */
3558 cp = s;
3561 eos = cp + strlen(cp);
3562 area = memarea_new();
3563 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
3564 if (tok->tp == _ERR) {
3565 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
3566 goto err;
3568 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
3569 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
3570 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
3571 goto err;
3574 r = router_parse_addr_policy(tok);
3575 goto done;
3576 err:
3577 r = NULL;
3578 done:
3579 token_clear(tok);
3580 if (area) {
3581 DUMP_AREA(area, "policy item");
3582 memarea_drop_all(area);
3584 return r;
3587 /** Add an exit policy stored in the token <b>tok</b> to the router info in
3588 * <b>router</b>. Return 0 on success, -1 on failure. */
3589 static int
3590 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
3592 addr_policy_t *newe;
3593 newe = router_parse_addr_policy(tok);
3594 if (!newe)
3595 return -1;
3596 if (! router->exit_policy)
3597 router->exit_policy = smartlist_create();
3599 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
3600 tor_addr_family(&newe->addr) == AF_INET)
3602 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
3603 tor_addr_family(&newe->addr) == AF_INET6)) {
3604 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
3605 "policy");
3606 addr_policy_free(newe);
3607 return -1;
3610 smartlist_add(router->exit_policy, newe);
3612 return 0;
3615 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
3616 * a new exit_policy_t corresponding to the token. */
3617 static addr_policy_t *
3618 router_parse_addr_policy(directory_token_t *tok)
3620 addr_policy_t newe;
3621 char *arg;
3623 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
3624 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
3626 if (tok->n_args != 1)
3627 return NULL;
3628 arg = tok->args[0];
3630 if (!strcmpstart(arg,"private"))
3631 return router_parse_addr_policy_private(tok);
3633 memset(&newe, 0, sizeof(newe));
3635 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3636 newe.policy_type = ADDR_POLICY_REJECT;
3637 else
3638 newe.policy_type = ADDR_POLICY_ACCEPT;
3640 if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
3641 &newe.prt_min, &newe.prt_max) < 0) {
3642 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
3643 return NULL;
3646 return addr_policy_get_canonical_entry(&newe);
3649 /** Parse an exit policy line of the format "accept/reject private:...".
3650 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
3651 * router descriptors until earlier versions are obsolete.
3653 static addr_policy_t *
3654 router_parse_addr_policy_private(directory_token_t *tok)
3656 const char *arg;
3657 uint16_t port_min, port_max;
3658 addr_policy_t result;
3660 arg = tok->args[0];
3661 if (strcmpstart(arg, "private"))
3662 return NULL;
3664 arg += strlen("private");
3665 arg = (char*) eat_whitespace(arg);
3666 if (!arg || *arg != ':')
3667 return NULL;
3669 if (parse_port_range(arg+1, &port_min, &port_max)<0)
3670 return NULL;
3672 memset(&result, 0, sizeof(result));
3673 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
3674 result.policy_type = ADDR_POLICY_REJECT;
3675 else
3676 result.policy_type = ADDR_POLICY_ACCEPT;
3677 result.is_private = 1;
3678 result.prt_min = port_min;
3679 result.prt_max = port_max;
3681 return addr_policy_get_canonical_entry(&result);
3684 /** Log and exit if <b>t</b> is malformed */
3685 void
3686 assert_addr_policy_ok(smartlist_t *lst)
3688 if (!lst) return;
3689 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
3690 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
3691 t->policy_type == ADDR_POLICY_ACCEPT);
3692 tor_assert(t->prt_min <= t->prt_max);
3697 * Low-level tokenizer for router descriptors and directories.
3700 /** Free all resources allocated for <b>tok</b> */
3701 static void
3702 token_clear(directory_token_t *tok)
3704 if (tok->key)
3705 crypto_free_pk_env(tok->key);
3708 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
3709 #define ALLOC(sz) memarea_alloc(area,sz)
3710 #define STRDUP(str) memarea_strdup(area,str)
3711 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
3713 #define RET_ERR(msg) \
3714 STMT_BEGIN \
3715 if (tok) token_clear(tok); \
3716 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
3717 tok->tp = _ERR; \
3718 tok->error = STRDUP(msg); \
3719 goto done_tokenizing; \
3720 STMT_END
3722 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
3723 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
3724 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
3725 * conform to the syntax we wanted.
3727 static INLINE directory_token_t *
3728 token_check_object(memarea_t *area, const char *kwd,
3729 directory_token_t *tok, obj_syntax o_syn)
3731 char ebuf[128];
3732 switch (o_syn) {
3733 case NO_OBJ:
3734 /* No object is allowed for this token. */
3735 if (tok->object_body) {
3736 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
3737 RET_ERR(ebuf);
3739 if (tok->key) {
3740 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
3741 RET_ERR(ebuf);
3743 break;
3744 case NEED_OBJ:
3745 /* There must be a (non-key) object. */
3746 if (!tok->object_body) {
3747 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
3748 RET_ERR(ebuf);
3750 break;
3751 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
3752 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
3753 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
3754 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
3755 kwd, (int)crypto_pk_keysize(tok->key));
3756 RET_ERR(ebuf);
3758 /* fall through */
3759 case NEED_KEY: /* There must be some kind of key. */
3760 if (!tok->key) {
3761 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
3762 RET_ERR(ebuf);
3764 if (o_syn != NEED_SKEY_1024) {
3765 if (crypto_pk_key_is_private(tok->key)) {
3766 tor_snprintf(ebuf, sizeof(ebuf),
3767 "Private key given for %s, which wants a public key", kwd);
3768 RET_ERR(ebuf);
3770 } else { /* o_syn == NEED_SKEY_1024 */
3771 if (!crypto_pk_key_is_private(tok->key)) {
3772 tor_snprintf(ebuf, sizeof(ebuf),
3773 "Public key given for %s, which wants a private key", kwd);
3774 RET_ERR(ebuf);
3777 break;
3778 case OBJ_OK:
3779 /* Anything goes with this token. */
3780 break;
3783 done_tokenizing:
3784 return tok;
3787 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3788 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3789 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3790 * all storage in <b>area</b>. Return the number of arguments parsed, or
3791 * return -1 if there was an insanely high number of arguments. */
3792 static INLINE int
3793 get_token_arguments(memarea_t *area, directory_token_t *tok,
3794 const char *s, const char *eol)
3796 /** Largest number of arguments we'll accept to any token, ever. */
3797 #define MAX_ARGS 512
3798 char *mem = memarea_strndup(area, s, eol-s);
3799 char *cp = mem;
3800 int j = 0;
3801 char *args[MAX_ARGS];
3802 while (*cp) {
3803 if (j == MAX_ARGS)
3804 return -1;
3805 args[j++] = cp;
3806 cp = (char*)find_whitespace(cp);
3807 if (!cp || !*cp)
3808 break; /* End of the line. */
3809 *cp++ = '\0';
3810 cp = (char*)eat_whitespace(cp);
3812 tok->n_args = j;
3813 tok->args = memarea_memdup(area, args, j*sizeof(char*));
3814 return j;
3815 #undef MAX_ARGS
3818 /** Helper function: read the next token from *s, advance *s to the end of the
3819 * token, and return the parsed token. Parse *<b>s</b> according to the list
3820 * of tokens in <b>table</b>.
3822 static directory_token_t *
3823 get_next_token(memarea_t *area,
3824 const char **s, const char *eos, token_rule_t *table)
3826 /** Reject any object at least this big; it is probably an overflow, an
3827 * attack, a bug, or some other nonsense. */
3828 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
3829 /** Reject any line at least this big; it is probably an overflow, an
3830 * attack, a bug, or some other nonsense. */
3831 #define MAX_LINE_LENGTH (128*1024)
3833 const char *next, *eol, *obstart;
3834 size_t obname_len;
3835 int i;
3836 directory_token_t *tok;
3837 obj_syntax o_syn = NO_OBJ;
3838 char ebuf[128];
3839 const char *kwd = "";
3841 tor_assert(area);
3842 tok = ALLOC_ZERO(sizeof(directory_token_t));
3843 tok->tp = _ERR;
3845 /* Set *s to first token, eol to end-of-line, next to after first token */
3846 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
3847 tor_assert(eos >= *s);
3848 eol = memchr(*s, '\n', eos-*s);
3849 if (!eol)
3850 eol = eos;
3851 if (eol - *s > MAX_LINE_LENGTH) {
3852 RET_ERR("Line far too long");
3855 next = find_whitespace_eos(*s, eol);
3857 if (!strcmp_len(*s, "opt", next-*s)) {
3858 /* Skip past an "opt" at the start of the line. */
3859 *s = eat_whitespace_eos_no_nl(next, eol);
3860 next = find_whitespace_eos(*s, eol);
3861 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
3862 RET_ERR("Unexpected EOF");
3865 /* Search the table for the appropriate entry. (I tried a binary search
3866 * instead, but it wasn't any faster.) */
3867 for (i = 0; table[i].t ; ++i) {
3868 if (!strcmp_len(*s, table[i].t, next-*s)) {
3869 /* We've found the keyword. */
3870 kwd = table[i].t;
3871 tok->tp = table[i].v;
3872 o_syn = table[i].os;
3873 *s = eat_whitespace_eos_no_nl(next, eol);
3874 /* We go ahead whether there are arguments or not, so that tok->args is
3875 * always set if we want arguments. */
3876 if (table[i].concat_args) {
3877 /* The keyword takes the line as a single argument */
3878 tok->args = ALLOC(sizeof(char*));
3879 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3880 tok->n_args = 1;
3881 } else {
3882 /* This keyword takes multiple arguments. */
3883 if (get_token_arguments(area, tok, *s, eol)<0) {
3884 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3885 RET_ERR(ebuf);
3887 *s = eol;
3889 if (tok->n_args < table[i].min_args) {
3890 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3891 RET_ERR(ebuf);
3892 } else if (tok->n_args > table[i].max_args) {
3893 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3894 RET_ERR(ebuf);
3896 break;
3900 if (tok->tp == _ERR) {
3901 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3902 if (**s == '@')
3903 tok->tp = _A_UNKNOWN;
3904 else
3905 tok->tp = K_OPT;
3906 tok->args = ALLOC(sizeof(char*));
3907 tok->args[0] = STRNDUP(*s, eol-*s);
3908 tok->n_args = 1;
3909 o_syn = OBJ_OK;
3912 /* Check whether there's an object present */
3913 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3914 tor_assert(eos >= *s);
3915 eol = memchr(*s, '\n', eos-*s);
3916 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3917 goto check_object;
3919 obstart = *s; /* Set obstart to start of object spec */
3920 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3921 strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
3922 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
3923 RET_ERR("Malformed object: bad begin line");
3925 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3926 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3927 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3929 /* Go to the end of the object */
3930 next = tor_memstr(*s, eos-*s, "-----END ");
3931 if (!next) {
3932 RET_ERR("Malformed object: missing object end line");
3934 tor_assert(eos >= next);
3935 eol = memchr(next, '\n', eos-next);
3936 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3937 eol = eos;
3938 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3939 if ((size_t)(eol-next) != 9+obname_len+5 ||
3940 strcmp_len(next+9, tok->object_type, obname_len) ||
3941 strcmp_len(eol-5, "-----", 5)) {
3942 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3943 tok->object_type);
3944 ebuf[sizeof(ebuf)-1] = '\0';
3945 RET_ERR(ebuf);
3947 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
3948 RET_ERR("Couldn't parse object: missing footer or object much too big.");
3950 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3951 tok->key = crypto_new_pk_env();
3952 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3953 RET_ERR("Couldn't parse public key.");
3954 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3955 tok->key = crypto_new_pk_env();
3956 if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
3957 RET_ERR("Couldn't parse private key.");
3958 } else { /* If it's something else, try to base64-decode it */
3959 int r;
3960 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3961 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3962 if (r<0)
3963 RET_ERR("Malformed object: bad base64-encoded data");
3964 tok->object_size = r;
3966 *s = eol;
3968 check_object:
3969 tok = token_check_object(area, kwd, tok, o_syn);
3971 done_tokenizing:
3972 return tok;
3974 #undef RET_ERR
3975 #undef ALLOC
3976 #undef ALLOC_ZERO
3977 #undef STRDUP
3978 #undef STRNDUP
3981 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3982 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3983 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3984 * entire string.
3986 static int
3987 tokenize_string(memarea_t *area,
3988 const char *start, const char *end, smartlist_t *out,
3989 token_rule_t *table, int flags)
3991 const char **s;
3992 directory_token_t *tok = NULL;
3993 int counts[_NIL];
3994 int i;
3995 int first_nonannotation;
3996 int prev_len = smartlist_len(out);
3997 tor_assert(area);
3999 s = &start;
4000 if (!end)
4001 end = start+strlen(start);
4002 for (i = 0; i < _NIL; ++i)
4003 counts[i] = 0;
4005 SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]);
4007 while (*s < end && (!tok || tok->tp != _EOF)) {
4008 tok = get_next_token(area, s, end, table);
4009 if (tok->tp == _ERR) {
4010 log_warn(LD_DIR, "parse error: %s", tok->error);
4011 token_clear(tok);
4012 return -1;
4014 ++counts[tok->tp];
4015 smartlist_add(out, tok);
4016 *s = eat_whitespace_eos(*s, end);
4019 if (flags & TS_NOCHECK)
4020 return 0;
4022 if ((flags & TS_ANNOTATIONS_OK)) {
4023 first_nonannotation = -1;
4024 for (i = 0; i < smartlist_len(out); ++i) {
4025 tok = smartlist_get(out, i);
4026 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
4027 first_nonannotation = i;
4028 break;
4031 if (first_nonannotation < 0) {
4032 log_warn(LD_DIR, "parse error: item contains only annotations");
4033 return -1;
4035 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
4036 tok = smartlist_get(out, i);
4037 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
4038 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
4039 return -1;
4042 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
4043 if (first_nonannotation != prev_len) {
4044 log_warn(LD_DIR, "parse error: Unexpected annotations.");
4045 return -1;
4048 } else {
4049 for (i=0; i < smartlist_len(out); ++i) {
4050 tok = smartlist_get(out, i);
4051 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
4052 log_warn(LD_DIR, "parse error: no annotations allowed.");
4053 return -1;
4056 first_nonannotation = 0;
4058 for (i = 0; table[i].t; ++i) {
4059 if (counts[table[i].v] < table[i].min_cnt) {
4060 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
4061 return -1;
4063 if (counts[table[i].v] > table[i].max_cnt) {
4064 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
4065 return -1;
4067 if (table[i].pos & AT_START) {
4068 if (smartlist_len(out) < 1 ||
4069 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
4070 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
4071 return -1;
4074 if (table[i].pos & AT_END) {
4075 if (smartlist_len(out) < 1 ||
4076 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
4077 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
4078 return -1;
4082 return 0;
4085 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
4086 * NULL if no such keyword is found.
4088 static directory_token_t *
4089 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
4091 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
4092 return NULL;
4095 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
4096 * with an assert if no such keyword is found.
4098 static directory_token_t *
4099 _find_by_keyword(smartlist_t *s, directory_keyword keyword,
4100 const char *keyword_as_string)
4102 directory_token_t *tok = find_opt_by_keyword(s, keyword);
4103 if (PREDICT_UNLIKELY(!tok)) {
4104 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
4105 "been validated. Internal error.", keyword_as_string, (int)keyword);
4106 tor_assert(tok);
4108 return tok;
4111 /** Return a newly allocated smartlist of all accept or reject tokens in
4112 * <b>s</b>.
4114 static smartlist_t *
4115 find_all_exitpolicy(smartlist_t *s)
4117 smartlist_t *out = smartlist_create();
4118 SMARTLIST_FOREACH(s, directory_token_t *, t,
4119 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
4120 t->tp == K_REJECT || t->tp == K_REJECT6)
4121 smartlist_add(out,t));
4122 return out;
4125 static int
4126 router_get_hash_impl_helper(const char *s, size_t s_len,
4127 const char *start_str,
4128 const char *end_str, char end_c,
4129 const char **start_out, const char **end_out)
4131 const char *start, *end;
4132 start = tor_memstr(s, s_len, start_str);
4133 if (!start) {
4134 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
4135 return -1;
4137 if (start != s && *(start-1) != '\n') {
4138 log_warn(LD_DIR,
4139 "first occurrence of \"%s\" is not at the start of a line",
4140 start_str);
4141 return -1;
4143 end = tor_memstr(start+strlen(start_str),
4144 s_len - (start-s) - strlen(start_str), end_str);
4145 if (!end) {
4146 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
4147 return -1;
4149 end = memchr(end+strlen(end_str), end_c, s_len - (end-s) - strlen(end_str));
4150 if (!end) {
4151 log_warn(LD_DIR,"couldn't find EOL");
4152 return -1;
4154 ++end;
4156 *start_out = start;
4157 *end_out = end;
4158 return 0;
4161 /** Compute the digest of the substring of <b>s</b> taken from the first
4162 * occurrence of <b>start_str</b> through the first instance of c after the
4163 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
4164 * <b>digest</b>; return 0 on success.
4166 * If no such substring exists, return -1.
4168 static int
4169 router_get_hash_impl(const char *s, size_t s_len, char *digest,
4170 const char *start_str,
4171 const char *end_str, char end_c,
4172 digest_algorithm_t alg)
4174 const char *start=NULL, *end=NULL;
4175 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
4176 &start,&end)<0)
4177 return -1;
4179 if (alg == DIGEST_SHA1) {
4180 if (crypto_digest(digest, start, end-start)) {
4181 log_warn(LD_BUG,"couldn't compute digest");
4182 return -1;
4184 } else {
4185 if (crypto_digest256(digest, start, end-start, alg)) {
4186 log_warn(LD_BUG,"couldn't compute digest");
4187 return -1;
4191 return 0;
4194 /** As router_get_hash_impl, but compute all hashes. */
4195 static int
4196 router_get_hashes_impl(const char *s, size_t s_len, digests_t *digests,
4197 const char *start_str,
4198 const char *end_str, char end_c)
4200 const char *start=NULL, *end=NULL;
4201 if (router_get_hash_impl_helper(s,s_len,start_str,end_str,end_c,
4202 &start,&end)<0)
4203 return -1;
4205 if (crypto_digest_all(digests, start, end-start)) {
4206 log_warn(LD_BUG,"couldn't compute digests");
4207 return -1;
4210 return 0;
4213 /** Assuming that s starts with a microdesc, return the start of the
4214 * *NEXT* one. Return NULL on "not found." */
4215 static const char *
4216 find_start_of_next_microdesc(const char *s, const char *eos)
4218 int started_with_annotations;
4219 s = eat_whitespace_eos(s, eos);
4220 if (!s)
4221 return NULL;
4223 #define CHECK_LENGTH() STMT_BEGIN \
4224 if (s+32 > eos) \
4225 return NULL; \
4226 STMT_END
4228 #define NEXT_LINE() STMT_BEGIN \
4229 s = memchr(s, '\n', eos-s); \
4230 if (!s || s+1 >= eos) \
4231 return NULL; \
4232 s++; \
4233 STMT_END
4235 CHECK_LENGTH();
4237 started_with_annotations = (*s == '@');
4239 if (started_with_annotations) {
4240 /* Start by advancing to the first non-annotation line. */
4241 while (*s == '@')
4242 NEXT_LINE();
4244 CHECK_LENGTH();
4246 /* Now we should be pointed at an onion-key line. If we are, then skip
4247 * it. */
4248 if (!strcmpstart(s, "onion-key"))
4249 NEXT_LINE();
4251 /* Okay, now we're pointed at the first line of the microdescriptor which is
4252 not an annotation or onion-key. The next line that _is_ an annotation or
4253 onion-key is the start of the next microdescriptor. */
4254 while (s+32 < eos) {
4255 if (*s == '@' || !strcmpstart(s, "onion-key"))
4256 return s;
4257 NEXT_LINE();
4259 return NULL;
4261 #undef CHECK_LENGTH
4262 #undef NEXT_LINE
4265 /** Parse as many microdescriptors as are found from the string starting at
4266 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4267 * annotations we recognize and ignore ones we don't. If <b>copy_body</b> is
4268 * true, then strdup the bodies of the microdescriptors. Return all newly
4269 * parsed microdescriptors in a newly allocated smartlist_t. */
4270 smartlist_t *
4271 microdescs_parse_from_string(const char *s, const char *eos,
4272 int allow_annotations, int copy_body)
4274 smartlist_t *tokens;
4275 smartlist_t *result;
4276 microdesc_t *md = NULL;
4277 memarea_t *area;
4278 const char *start = s;
4279 const char *start_of_next_microdesc;
4280 int flags = allow_annotations ? TS_ANNOTATIONS_OK : 0;
4282 directory_token_t *tok;
4284 if (!eos)
4285 eos = s + strlen(s);
4287 s = eat_whitespace_eos(s, eos);
4288 area = memarea_new();
4289 result = smartlist_create();
4290 tokens = smartlist_create();
4292 while (s < eos) {
4293 start_of_next_microdesc = find_start_of_next_microdesc(s, eos);
4294 if (!start_of_next_microdesc)
4295 start_of_next_microdesc = eos;
4297 if (tokenize_string(area, s, start_of_next_microdesc, tokens,
4298 microdesc_token_table, flags)) {
4299 log_warn(LD_DIR, "Unparseable microdescriptor");
4300 goto next;
4303 md = tor_malloc_zero(sizeof(microdesc_t));
4305 const char *cp = tor_memstr(s, start_of_next_microdesc-s,
4306 "onion-key");
4307 tor_assert(cp);
4309 md->bodylen = start_of_next_microdesc - cp;
4310 if (copy_body)
4311 md->body = tor_strndup(cp, md->bodylen);
4312 else
4313 md->body = (char*)cp;
4314 md->off = cp - start;
4317 if ((tok = find_opt_by_keyword(tokens, A_LAST_LISTED))) {
4318 if (parse_iso_time(tok->args[0], &md->last_listed)) {
4319 log_warn(LD_DIR, "Bad last-listed time in microdescriptor");
4320 goto next;
4324 tok = find_by_keyword(tokens, K_ONION_KEY);
4325 md->onion_pkey = tok->key;
4326 tok->key = NULL;
4328 if ((tok = find_opt_by_keyword(tokens, K_FAMILY))) {
4329 int i;
4330 md->family = smartlist_create();
4331 for (i=0;i<tok->n_args;++i) {
4332 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
4333 log_warn(LD_DIR, "Illegal nickname %s in family line",
4334 escaped(tok->args[i]));
4335 goto next;
4337 smartlist_add(md->family, tor_strdup(tok->args[i]));
4341 if ((tok = find_opt_by_keyword(tokens, K_P))) {
4342 md->exitsummary = tor_strdup(tok->args[0]);
4345 crypto_digest256(md->digest, md->body, md->bodylen, DIGEST_SHA256);
4347 smartlist_add(result, md);
4349 md = NULL;
4350 next:
4351 microdesc_free(md);
4353 memarea_clear(area);
4354 smartlist_clear(tokens);
4355 s = start_of_next_microdesc;
4358 memarea_drop_all(area);
4359 smartlist_free(tokens);
4361 return result;
4364 /** Parse the Tor version of the platform string <b>platform</b>,
4365 * and compare it to the version in <b>cutoff</b>. Return 1 if
4366 * the router is at least as new as the cutoff, else return 0.
4369 tor_version_as_new_as(const char *platform, const char *cutoff)
4371 tor_version_t cutoff_version, router_version;
4372 char *s, *s2, *start;
4373 char tmp[128];
4375 tor_assert(platform);
4377 if (tor_version_parse(cutoff, &cutoff_version)<0) {
4378 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
4379 return 0;
4381 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
4382 return 1;
4384 start = (char *)eat_whitespace(platform+3);
4385 if (!*start) return 0;
4386 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
4387 s2 = (char*)eat_whitespace(s);
4388 if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
4389 s = (char*)find_whitespace(s2);
4391 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
4392 return 0;
4393 strlcpy(tmp, start, s-start+1);
4395 if (tor_version_parse(tmp, &router_version)<0) {
4396 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
4397 return 1; /* be safe and say yes */
4400 /* Here's why we don't need to do any special handling for svn revisions:
4401 * - If neither has an svn revision, we're fine.
4402 * - If the router doesn't have an svn revision, we can't assume that it
4403 * is "at least" any svn revision, so we need to return 0.
4404 * - If the target version doesn't have an svn revision, any svn revision
4405 * (or none at all) is good enough, so return 1.
4406 * - If both target and router have an svn revision, we compare them.
4409 return tor_version_compare(&router_version, &cutoff_version) >= 0;
4412 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4413 * Return 0 on success, -1 on failure. */
4415 tor_version_parse(const char *s, tor_version_t *out)
4417 char *eos=NULL;
4418 const char *cp=NULL;
4419 /* Format is:
4420 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
4422 tor_assert(s);
4423 tor_assert(out);
4425 memset(out, 0, sizeof(tor_version_t));
4427 if (!strcasecmpstart(s, "Tor "))
4428 s += 4;
4430 /* Get major. */
4431 out->major = (int)strtol(s,&eos,10);
4432 if (!eos || eos==s || *eos != '.') return -1;
4433 cp = eos+1;
4435 /* Get minor */
4436 out->minor = (int) strtol(cp,&eos,10);
4437 if (!eos || eos==cp || *eos != '.') return -1;
4438 cp = eos+1;
4440 /* Get micro */
4441 out->micro = (int) strtol(cp,&eos,10);
4442 if (!eos || eos==cp) return -1;
4443 if (!*eos) {
4444 out->status = VER_RELEASE;
4445 out->patchlevel = 0;
4446 return 0;
4448 cp = eos;
4450 /* Get status */
4451 if (*cp == '.') {
4452 out->status = VER_RELEASE;
4453 ++cp;
4454 } else if (0==strncmp(cp, "pre", 3)) {
4455 out->status = VER_PRE;
4456 cp += 3;
4457 } else if (0==strncmp(cp, "rc", 2)) {
4458 out->status = VER_RC;
4459 cp += 2;
4460 } else {
4461 return -1;
4464 /* Get patchlevel */
4465 out->patchlevel = (int) strtol(cp,&eos,10);
4466 if (!eos || eos==cp) return -1;
4467 cp = eos;
4469 /* Get status tag. */
4470 if (*cp == '-' || *cp == '.')
4471 ++cp;
4472 eos = (char*) find_whitespace(cp);
4473 if (eos-cp >= (int)sizeof(out->status_tag))
4474 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
4475 else {
4476 memcpy(out->status_tag, cp, eos-cp);
4477 out->status_tag[eos-cp] = 0;
4479 cp = eat_whitespace(eos);
4481 if (!strcmpstart(cp, "(r")) {
4482 cp += 2;
4483 out->svn_revision = (int) strtol(cp,&eos,10);
4484 } else if (!strcmpstart(cp, "(git-")) {
4485 char *close_paren = strchr(cp, ')');
4486 int hexlen;
4487 char digest[DIGEST_LEN];
4488 if (! close_paren)
4489 return -1;
4490 cp += 5;
4491 if (close_paren-cp > HEX_DIGEST_LEN)
4492 return -1;
4493 hexlen = (int)(close_paren-cp);
4494 memset(digest, 0, sizeof(digest));
4495 if ( hexlen == 0 || (hexlen % 2) == 1)
4496 return -1;
4497 if (base16_decode(digest, hexlen/2, cp, hexlen))
4498 return -1;
4499 memcpy(out->git_tag, digest, hexlen/2);
4500 out->git_tag_len = hexlen/2;
4503 return 0;
4506 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
4507 * b. */
4509 tor_version_compare(tor_version_t *a, tor_version_t *b)
4511 int i;
4512 tor_assert(a);
4513 tor_assert(b);
4514 if ((i = a->major - b->major))
4515 return i;
4516 else if ((i = a->minor - b->minor))
4517 return i;
4518 else if ((i = a->micro - b->micro))
4519 return i;
4520 else if ((i = a->status - b->status))
4521 return i;
4522 else if ((i = a->patchlevel - b->patchlevel))
4523 return i;
4524 else if ((i = strcmp(a->status_tag, b->status_tag)))
4525 return i;
4526 else if ((i = a->svn_revision - b->svn_revision))
4527 return i;
4528 else if ((i = a->git_tag_len - b->git_tag_len))
4529 return i;
4530 else if (a->git_tag_len)
4531 return memcmp(a->git_tag, b->git_tag, a->git_tag_len);
4532 else
4533 return 0;
4536 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
4538 static int
4539 tor_version_same_series(tor_version_t *a, tor_version_t *b)
4541 tor_assert(a);
4542 tor_assert(b);
4543 return ((a->major == b->major) &&
4544 (a->minor == b->minor) &&
4545 (a->micro == b->micro));
4548 /** Helper: Given pointers to two strings describing tor versions, return -1
4549 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
4550 * Used to sort a list of versions. */
4551 static int
4552 _compare_tor_version_str_ptr(const void **_a, const void **_b)
4554 const char *a = *_a, *b = *_b;
4555 int ca, cb;
4556 tor_version_t va, vb;
4557 ca = tor_version_parse(a, &va);
4558 cb = tor_version_parse(b, &vb);
4559 /* If they both parse, compare them. */
4560 if (!ca && !cb)
4561 return tor_version_compare(&va,&vb);
4562 /* If one parses, it comes first. */
4563 if (!ca && cb)
4564 return -1;
4565 if (ca && !cb)
4566 return 1;
4567 /* If neither parses, compare strings. Also, the directory server admin
4568 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
4569 return strcmp(a,b);
4572 /** Sort a list of string-representations of versions in ascending order. */
4573 void
4574 sort_version_list(smartlist_t *versions, int remove_duplicates)
4576 smartlist_sort(versions, _compare_tor_version_str_ptr);
4578 if (remove_duplicates)
4579 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
4582 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
4583 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
4584 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
4585 * encrypted introduction points to the newly allocated
4586 * *<b>intro_points_encrypted_out</b>, their encrypted size to
4587 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
4588 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
4589 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
4590 * and -1 for failure.
4593 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
4594 char *desc_id_out,
4595 char **intro_points_encrypted_out,
4596 size_t *intro_points_encrypted_size_out,
4597 size_t *encoded_size_out,
4598 const char **next_out, const char *desc)
4600 rend_service_descriptor_t *result =
4601 tor_malloc_zero(sizeof(rend_service_descriptor_t));
4602 char desc_hash[DIGEST_LEN];
4603 const char *eos;
4604 smartlist_t *tokens = smartlist_create();
4605 directory_token_t *tok;
4606 char secret_id_part[DIGEST_LEN];
4607 int i, version, num_ok=1;
4608 smartlist_t *versions;
4609 char public_key_hash[DIGEST_LEN];
4610 char test_desc_id[DIGEST_LEN];
4611 memarea_t *area = NULL;
4612 tor_assert(desc);
4613 /* Check if desc starts correctly. */
4614 if (strncmp(desc, "rendezvous-service-descriptor ",
4615 strlen("rendezvous-service-descriptor "))) {
4616 log_info(LD_REND, "Descriptor does not start correctly.");
4617 goto err;
4619 /* Compute descriptor hash for later validation. */
4620 if (router_get_hash_impl(desc, strlen(desc), desc_hash,
4621 "rendezvous-service-descriptor ",
4622 "\nsignature", '\n', DIGEST_SHA1) < 0) {
4623 log_warn(LD_REND, "Couldn't compute descriptor hash.");
4624 goto err;
4626 /* Determine end of string. */
4627 eos = strstr(desc, "\nrendezvous-service-descriptor ");
4628 if (!eos)
4629 eos = desc + strlen(desc);
4630 else
4631 eos = eos + 1;
4632 /* Check length. */
4633 if (strlen(desc) > REND_DESC_MAX_SIZE) {
4634 log_warn(LD_REND, "Descriptor length is %i which exceeds "
4635 "maximum rendezvous descriptor size of %i kilobytes.",
4636 (int)strlen(desc), REND_DESC_MAX_SIZE);
4637 goto err;
4639 /* Tokenize descriptor. */
4640 area = memarea_new();
4641 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
4642 log_warn(LD_REND, "Error tokenizing descriptor.");
4643 goto err;
4645 /* Set next to next descriptor, if available. */
4646 *next_out = eos;
4647 /* Set length of encoded descriptor. */
4648 *encoded_size_out = eos - desc;
4649 /* Check min allowed length of token list. */
4650 if (smartlist_len(tokens) < 7) {
4651 log_warn(LD_REND, "Impossibly short descriptor.");
4652 goto err;
4654 /* Parse base32-encoded descriptor ID. */
4655 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
4656 tor_assert(tok == smartlist_get(tokens, 0));
4657 tor_assert(tok->n_args == 1);
4658 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
4659 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
4660 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
4661 goto err;
4663 if (base32_decode(desc_id_out, DIGEST_LEN,
4664 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
4665 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
4666 tok->args[0]);
4667 goto err;
4669 /* Parse descriptor version. */
4670 tok = find_by_keyword(tokens, R_VERSION);
4671 tor_assert(tok->n_args == 1);
4672 result->version =
4673 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
4674 if (result->version != 2 || !num_ok) {
4675 /* If it's <2, it shouldn't be under this format. If the number
4676 * is greater than 2, we bumped it because we broke backward
4677 * compatibility. See how version numbers in our other formats
4678 * work. */
4679 log_warn(LD_REND, "Unrecognized descriptor version: %s",
4680 escaped(tok->args[0]));
4681 goto err;
4683 /* Parse public key. */
4684 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
4685 result->pk = tok->key;
4686 tok->key = NULL; /* Prevent free */
4687 /* Parse secret ID part. */
4688 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
4689 tor_assert(tok->n_args == 1);
4690 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
4691 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
4692 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
4693 goto err;
4695 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
4696 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
4697 tok->args[0]);
4698 goto err;
4700 /* Parse publication time -- up-to-date check is done when storing the
4701 * descriptor. */
4702 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
4703 tor_assert(tok->n_args == 1);
4704 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
4705 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
4706 goto err;
4708 /* Parse protocol versions. */
4709 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
4710 tor_assert(tok->n_args == 1);
4711 versions = smartlist_create();
4712 smartlist_split_string(versions, tok->args[0], ",",
4713 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
4714 for (i = 0; i < smartlist_len(versions); i++) {
4715 version = (int) tor_parse_long(smartlist_get(versions, i),
4716 10, 0, INT_MAX, &num_ok, NULL);
4717 if (!num_ok) /* It's a string; let's ignore it. */
4718 continue;
4719 result->protocols |= 1 << version;
4721 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
4722 smartlist_free(versions);
4723 /* Parse encrypted introduction points. Don't verify. */
4724 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
4725 if (tok) {
4726 if (strcmp(tok->object_type, "MESSAGE")) {
4727 log_warn(LD_DIR, "Bad object type: introduction points should be of "
4728 "type MESSAGE");
4729 goto err;
4731 *intro_points_encrypted_out = tor_memdup(tok->object_body,
4732 tok->object_size);
4733 *intro_points_encrypted_size_out = tok->object_size;
4734 } else {
4735 *intro_points_encrypted_out = NULL;
4736 *intro_points_encrypted_size_out = 0;
4738 /* Parse and verify signature. */
4739 tok = find_by_keyword(tokens, R_SIGNATURE);
4740 note_crypto_pk_op(VERIFY_RTR);
4741 if (check_signature_token(desc_hash, DIGEST_LEN, tok, result->pk, 0,
4742 "v2 rendezvous service descriptor") < 0)
4743 goto err;
4744 /* Verify that descriptor ID belongs to public key and secret ID part. */
4745 crypto_pk_get_digest(result->pk, public_key_hash);
4746 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
4747 secret_id_part);
4748 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
4749 log_warn(LD_REND, "Parsed descriptor ID does not match "
4750 "computed descriptor ID.");
4751 goto err;
4753 goto done;
4754 err:
4755 rend_service_descriptor_free(result);
4756 result = NULL;
4757 done:
4758 if (tokens) {
4759 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4760 smartlist_free(tokens);
4762 if (area)
4763 memarea_drop_all(area);
4764 *parsed_out = result;
4765 if (result)
4766 return 0;
4767 return -1;
4770 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
4771 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
4772 * write the result to a newly allocated string that is pointed to by
4773 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
4774 * Return 0 if decryption was successful and -1 otherwise. */
4776 rend_decrypt_introduction_points(char **ipos_decrypted,
4777 size_t *ipos_decrypted_size,
4778 const char *descriptor_cookie,
4779 const char *ipos_encrypted,
4780 size_t ipos_encrypted_size)
4782 tor_assert(ipos_encrypted);
4783 tor_assert(descriptor_cookie);
4784 if (ipos_encrypted_size < 2) {
4785 log_warn(LD_REND, "Size of encrypted introduction points is too "
4786 "small.");
4787 return -1;
4789 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
4790 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
4791 session_key[CIPHER_KEY_LEN], *dec;
4792 int declen, client_blocks;
4793 size_t pos = 0, len, client_entries_len;
4794 crypto_digest_env_t *digest;
4795 crypto_cipher_env_t *cipher;
4796 client_blocks = (int) ipos_encrypted[1];
4797 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
4798 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
4799 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
4800 log_warn(LD_REND, "Size of encrypted introduction points is too "
4801 "small.");
4802 return -1;
4804 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
4805 digest = crypto_new_digest_env();
4806 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
4807 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
4808 crypto_digest_get_digest(digest, client_id,
4809 REND_BASIC_AUTH_CLIENT_ID_LEN);
4810 crypto_free_digest_env(digest);
4811 for (pos = 2; pos < 2 + client_entries_len;
4812 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
4813 if (!memcmp(ipos_encrypted + pos, client_id,
4814 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
4815 /* Attempt to decrypt introduction points. */
4816 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
4817 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
4818 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
4819 CIPHER_KEY_LEN) < 0) {
4820 log_warn(LD_REND, "Could not decrypt session key for client.");
4821 crypto_free_cipher_env(cipher);
4822 return -1;
4824 crypto_free_cipher_env(cipher);
4825 cipher = crypto_create_init_cipher(session_key, 0);
4826 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
4827 dec = tor_malloc(len);
4828 declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
4829 ipos_encrypted + 2 + client_entries_len,
4830 ipos_encrypted_size - 2 - client_entries_len);
4831 crypto_free_cipher_env(cipher);
4832 if (declen < 0) {
4833 log_warn(LD_REND, "Could not decrypt introduction point string.");
4834 tor_free(dec);
4835 return -1;
4837 if (memcmpstart(dec, declen, "introduction-point ")) {
4838 log_warn(LD_REND, "Decrypted introduction points don't "
4839 "look like we could parse them.");
4840 tor_free(dec);
4841 continue;
4843 *ipos_decrypted = dec;
4844 *ipos_decrypted_size = declen;
4845 return 0;
4848 log_warn(LD_REND, "Could not decrypt introduction points. Please "
4849 "check your authorization for this service!");
4850 return -1;
4851 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
4852 crypto_cipher_env_t *cipher;
4853 char *dec;
4854 int declen;
4855 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
4856 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
4857 declen = crypto_cipher_decrypt_with_iv(cipher, dec,
4858 ipos_encrypted_size -
4859 CIPHER_IV_LEN - 1,
4860 ipos_encrypted + 1,
4861 ipos_encrypted_size - 1);
4862 crypto_free_cipher_env(cipher);
4863 if (declen < 0) {
4864 log_warn(LD_REND, "Decrypting introduction points failed!");
4865 tor_free(dec);
4866 return -1;
4868 *ipos_decrypted = dec;
4869 *ipos_decrypted_size = declen;
4870 return 0;
4871 } else {
4872 log_warn(LD_REND, "Unknown authorization type number: %d",
4873 ipos_encrypted[0]);
4874 return -1;
4878 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
4879 * length <b>intro_points_encoded_size</b> and write the result to the
4880 * descriptor in <b>parsed</b>; return the number of successfully parsed
4881 * introduction points or -1 in case of a failure. */
4883 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
4884 const char *intro_points_encoded,
4885 size_t intro_points_encoded_size)
4887 const char *current_ipo, *end_of_intro_points;
4888 smartlist_t *tokens;
4889 directory_token_t *tok;
4890 rend_intro_point_t *intro;
4891 extend_info_t *info;
4892 int result, num_ok=1;
4893 memarea_t *area = NULL;
4894 tor_assert(parsed);
4895 /** Function may only be invoked once. */
4896 tor_assert(!parsed->intro_nodes);
4897 tor_assert(intro_points_encoded);
4898 tor_assert(intro_points_encoded_size > 0);
4899 /* Consider one intro point after the other. */
4900 current_ipo = intro_points_encoded;
4901 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
4902 tokens = smartlist_create();
4903 parsed->intro_nodes = smartlist_create();
4904 area = memarea_new();
4906 while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
4907 "introduction-point ")) {
4908 /* Determine end of string. */
4909 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
4910 "\nintroduction-point ");
4911 if (!eos)
4912 eos = end_of_intro_points;
4913 else
4914 eos = eos+1;
4915 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
4916 /* Free tokens and clear token list. */
4917 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4918 smartlist_clear(tokens);
4919 memarea_clear(area);
4920 /* Tokenize string. */
4921 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
4922 log_warn(LD_REND, "Error tokenizing introduction point");
4923 goto err;
4925 /* Advance to next introduction point, if available. */
4926 current_ipo = eos;
4927 /* Check minimum allowed length of introduction point. */
4928 if (smartlist_len(tokens) < 5) {
4929 log_warn(LD_REND, "Impossibly short introduction point.");
4930 goto err;
4932 /* Allocate new intro point and extend info. */
4933 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
4934 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
4935 /* Parse identifier. */
4936 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
4937 if (base32_decode(info->identity_digest, DIGEST_LEN,
4938 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
4939 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
4940 tok->args[0]);
4941 rend_intro_point_free(intro);
4942 goto err;
4944 /* Write identifier to nickname. */
4945 info->nickname[0] = '$';
4946 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
4947 info->identity_digest, DIGEST_LEN);
4948 /* Parse IP address. */
4949 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
4950 if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
4951 log_warn(LD_REND, "Could not parse introduction point address.");
4952 rend_intro_point_free(intro);
4953 goto err;
4955 if (tor_addr_family(&info->addr) != AF_INET) {
4956 log_warn(LD_REND, "Introduction point address was not ipv4.");
4957 rend_intro_point_free(intro);
4958 goto err;
4961 /* Parse onion port. */
4962 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
4963 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
4964 &num_ok,NULL);
4965 if (!info->port || !num_ok) {
4966 log_warn(LD_REND, "Introduction point onion port %s is invalid",
4967 escaped(tok->args[0]));
4968 rend_intro_point_free(intro);
4969 goto err;
4971 /* Parse onion key. */
4972 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
4973 info->onion_key = tok->key;
4974 tok->key = NULL; /* Prevent free */
4975 /* Parse service key. */
4976 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
4977 intro->intro_key = tok->key;
4978 tok->key = NULL; /* Prevent free */
4979 /* Add extend info to list of introduction points. */
4980 smartlist_add(parsed->intro_nodes, intro);
4982 result = smartlist_len(parsed->intro_nodes);
4983 goto done;
4985 err:
4986 result = -1;
4988 done:
4989 /* Free tokens and clear token list. */
4990 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
4991 smartlist_free(tokens);
4992 if (area)
4993 memarea_drop_all(area);
4995 return result;
4998 /** Parse the content of a client_key file in <b>ckstr</b> and add
4999 * rend_authorized_client_t's for each parsed client to
5000 * <b>parsed_clients</b>. Return the number of parsed clients as result
5001 * or -1 for failure. */
5003 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
5005 int result = -1;
5006 smartlist_t *tokens;
5007 directory_token_t *tok;
5008 const char *current_entry = NULL;
5009 memarea_t *area = NULL;
5010 if (!ckstr || strlen(ckstr) == 0)
5011 return -1;
5012 tokens = smartlist_create();
5013 /* Begin parsing with first entry, skipping comments or whitespace at the
5014 * beginning. */
5015 area = memarea_new();
5016 current_entry = eat_whitespace(ckstr);
5017 while (!strcmpstart(current_entry, "client-name ")) {
5018 rend_authorized_client_t *parsed_entry;
5019 size_t len;
5020 char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
5021 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
5022 /* Determine end of string. */
5023 const char *eos = strstr(current_entry, "\nclient-name ");
5024 if (!eos)
5025 eos = current_entry + strlen(current_entry);
5026 else
5027 eos = eos + 1;
5028 /* Free tokens and clear token list. */
5029 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5030 smartlist_clear(tokens);
5031 memarea_clear(area);
5032 /* Tokenize string. */
5033 if (tokenize_string(area, current_entry, eos, tokens,
5034 client_keys_token_table, 0)) {
5035 log_warn(LD_REND, "Error tokenizing client keys file.");
5036 goto err;
5038 /* Advance to next entry, if available. */
5039 current_entry = eos;
5040 /* Check minimum allowed length of token list. */
5041 if (smartlist_len(tokens) < 2) {
5042 log_warn(LD_REND, "Impossibly short client key entry.");
5043 goto err;
5045 /* Parse client name. */
5046 tok = find_by_keyword(tokens, C_CLIENT_NAME);
5047 tor_assert(tok == smartlist_get(tokens, 0));
5048 tor_assert(tok->n_args == 1);
5050 len = strlen(tok->args[0]);
5051 if (len < 1 || len > 19 ||
5052 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
5053 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
5054 "between 1 and 19, and valid characters are "
5055 "[A-Za-z0-9+-_].)", tok->args[0]);
5056 goto err;
5058 /* Check if client name is duplicate. */
5059 if (strmap_get(parsed_clients, tok->args[0])) {
5060 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
5061 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
5062 goto err;
5064 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
5065 parsed_entry->client_name = tor_strdup(tok->args[0]);
5066 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
5067 /* Parse client key. */
5068 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
5069 if (tok) {
5070 parsed_entry->client_key = tok->key;
5071 tok->key = NULL; /* Prevent free */
5074 /* Parse descriptor cookie. */
5075 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
5076 tor_assert(tok->n_args == 1);
5077 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
5078 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
5079 escaped(tok->args[0]));
5080 goto err;
5082 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
5083 * because a base64 encoding of length 24 does not fit into 16 bytes in all
5084 * cases. */
5085 if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
5086 tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
5087 != REND_DESC_COOKIE_LEN)) {
5088 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
5089 "%s", descriptor_cookie_base64);
5090 goto err;
5092 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
5093 REND_DESC_COOKIE_LEN);
5095 result = strmap_size(parsed_clients);
5096 goto done;
5097 err:
5098 result = -1;
5099 done:
5100 /* Free tokens and clear token list. */
5101 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_clear(t));
5102 smartlist_free(tokens);
5103 if (area)
5104 memarea_drop_all(area);
5105 return result;