When Tor fails to parse a descriptor of any kind, dump it to disk.
[tor/rransom.git] / src / or / routerparse.c
blob9e5f37b4bd804033ba9a9da5f5df6d94f8895e35
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-2009, 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 "memarea.h"
15 /****************************************************************************/
17 /** Enumeration of possible token types. The ones starting with K_ correspond
18 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
19 * is an end-of-file marker, and _NIL is used to encode not-a-token.
21 typedef enum {
22 K_ACCEPT = 0,
23 K_ACCEPT6,
24 K_DIRECTORY_SIGNATURE,
25 K_RECOMMENDED_SOFTWARE,
26 K_REJECT,
27 K_REJECT6,
28 K_ROUTER,
29 K_SIGNED_DIRECTORY,
30 K_SIGNING_KEY,
31 K_ONION_KEY,
32 K_ROUTER_SIGNATURE,
33 K_PUBLISHED,
34 K_RUNNING_ROUTERS,
35 K_ROUTER_STATUS,
36 K_PLATFORM,
37 K_OPT,
38 K_BANDWIDTH,
39 K_CONTACT,
40 K_NETWORK_STATUS,
41 K_UPTIME,
42 K_DIR_SIGNING_KEY,
43 K_FAMILY,
44 K_FINGERPRINT,
45 K_HIBERNATING,
46 K_READ_HISTORY,
47 K_WRITE_HISTORY,
48 K_NETWORK_STATUS_VERSION,
49 K_DIR_SOURCE,
50 K_DIR_OPTIONS,
51 K_CLIENT_VERSIONS,
52 K_SERVER_VERSIONS,
53 K_P,
54 K_R,
55 K_S,
56 K_V,
57 K_W,
58 K_EVENTDNS,
59 K_EXTRA_INFO,
60 K_EXTRA_INFO_DIGEST,
61 K_CACHES_EXTRA_INFO,
62 K_HIDDEN_SERVICE_DIR,
63 K_ALLOW_SINGLE_HOP_EXITS,
65 K_DIRREQ_END,
66 K_DIRREQ_V2_IPS,
67 K_DIRREQ_V3_IPS,
68 K_DIRREQ_V2_REQS,
69 K_DIRREQ_V3_REQS,
70 K_DIRREQ_V2_SHARE,
71 K_DIRREQ_V3_SHARE,
72 K_DIRREQ_V2_RESP,
73 K_DIRREQ_V3_RESP,
74 K_DIRREQ_V2_DIR,
75 K_DIRREQ_V3_DIR,
76 K_DIRREQ_V2_TUN,
77 K_DIRREQ_V3_TUN,
78 K_ENTRY_END,
79 K_ENTRY_IPS,
80 K_CELL_END,
81 K_CELL_PROCESSED,
82 K_CELL_QUEUED,
83 K_CELL_TIME,
84 K_CELL_CIRCS,
85 K_EXIT_END,
86 K_EXIT_WRITTEN,
87 K_EXIT_READ,
88 K_EXIT_OPENED,
90 K_DIR_KEY_CERTIFICATE_VERSION,
91 K_DIR_IDENTITY_KEY,
92 K_DIR_KEY_PUBLISHED,
93 K_DIR_KEY_EXPIRES,
94 K_DIR_KEY_CERTIFICATION,
95 K_DIR_KEY_CROSSCERT,
96 K_DIR_ADDRESS,
98 K_VOTE_STATUS,
99 K_VALID_AFTER,
100 K_FRESH_UNTIL,
101 K_VALID_UNTIL,
102 K_VOTING_DELAY,
104 K_KNOWN_FLAGS,
105 K_VOTE_DIGEST,
106 K_CONSENSUS_DIGEST,
107 K_CONSENSUS_METHODS,
108 K_CONSENSUS_METHOD,
109 K_LEGACY_DIR_KEY,
111 A_PURPOSE,
112 _A_UNKNOWN,
114 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
115 R_VERSION,
116 R_PERMANENT_KEY,
117 R_SECRET_ID_PART,
118 R_PUBLICATION_TIME,
119 R_PROTOCOL_VERSIONS,
120 R_INTRODUCTION_POINTS,
121 R_SIGNATURE,
123 R_IPO_IDENTIFIER,
124 R_IPO_IP_ADDRESS,
125 R_IPO_ONION_PORT,
126 R_IPO_ONION_KEY,
127 R_IPO_SERVICE_KEY,
129 C_CLIENT_NAME,
130 C_DESCRIPTOR_COOKIE,
131 C_CLIENT_KEY,
133 _ERR,
134 _EOF,
135 _NIL
136 } directory_keyword;
138 #define MIN_ANNOTATION A_PURPOSE
139 #define MAX_ANNOTATION _A_UNKNOWN
141 /** Structure to hold a single directory token.
143 * We parse a directory by breaking it into "tokens", each consisting
144 * of a keyword, a line full of arguments, and a binary object. The
145 * arguments and object are both optional, depending on the keyword
146 * type.
148 * This structure is only allocated in memareas; do not allocate it on
149 * the heap, or token_free() won't work.
151 typedef struct directory_token_t {
152 directory_keyword tp; /**< Type of the token. */
153 int n_args:30; /**< Number of elements in args */
154 char **args; /**< Array of arguments from keyword line. */
156 char *object_type; /**< -----BEGIN [object_type]-----*/
157 size_t object_size; /**< Bytes in object_body */
158 char *object_body; /**< Contents of object, base64-decoded. */
160 crypto_pk_env_t *key; /**< For public keys only. Heap-allocated. */
162 char *error; /**< For _ERR tokens only. */
163 } directory_token_t;
165 /* ********************************************************************** */
167 /** We use a table of rules to decide how to parse each token type. */
169 /** Rules for whether the keyword needs an object. */
170 typedef enum {
171 NO_OBJ, /**< No object, ever. */
172 NEED_OBJ, /**< Object is required. */
173 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
174 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
175 NEED_KEY, /**< Object is required, and must be a public key. */
176 OBJ_OK, /**< Object is optional. */
177 } obj_syntax;
179 #define AT_START 1
180 #define AT_END 2
182 /** Determines the parsing rules for a single token type. */
183 typedef struct token_rule_t {
184 /** The string value of the keyword identifying the type of item. */
185 const char *t;
186 /** The corresponding directory_keyword enum. */
187 directory_keyword v;
188 /** Minimum number of arguments for this item */
189 int min_args;
190 /** Maximum number of arguments for this item */
191 int max_args;
192 /** If true, we concatenate all arguments for this item into a single
193 * string. */
194 int concat_args;
195 /** Requirements on object syntax for this item. */
196 obj_syntax os;
197 /** Lowest number of times this item may appear in a document. */
198 int min_cnt;
199 /** Highest number of times this item may appear in a document. */
200 int max_cnt;
201 /** One or more of AT_START/AT_END to limit where the item may appear in a
202 * document. */
203 int pos;
204 /** True iff this token is an annotation. */
205 int is_annotation;
206 } token_rule_t;
209 * Helper macros to define token tables. 's' is a string, 't' is a
210 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
211 * object syntax.
215 /** Appears to indicate the end of a table. */
216 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
217 /** An item with no restrictions: used for obsolete document types */
218 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
219 /** An item with no restrictions on multiplicity or location. */
220 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
221 /** An item that must appear exactly once */
222 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
223 /** An item that must appear exactly once, at the start of the document */
224 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
225 /** An item that must appear exactly once, at the end of the document */
226 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
227 /** An item that must appear one or more times */
228 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
229 /** An item that must appear no more than once */
230 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
231 /** An annotation that must appear no more than once */
232 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
234 /* Argument multiplicity: any number of arguments. */
235 #define ARGS 0,INT_MAX,0
236 /* Argument multiplicity: no arguments. */
237 #define NO_ARGS 0,0,0
238 /* Argument multiplicity: concatenate all arguments. */
239 #define CONCAT_ARGS 1,1,1
240 /* Argument multiplicity: at least <b>n</b> arguments. */
241 #define GE(n) n,INT_MAX,0
242 /* Argument multiplicity: exactly <b>n</b> arguments. */
243 #define EQ(n) n,n,0
245 /** List of tokens allowable in router descriptors */
246 static token_rule_t routerdesc_token_table[] = {
247 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
248 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
249 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
250 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
251 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
252 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
253 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
254 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
255 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
256 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
257 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
258 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
259 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
260 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
261 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
262 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
263 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
264 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
265 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
267 T01("family", K_FAMILY, ARGS, NO_OBJ ),
268 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
269 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
271 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
272 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
273 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
275 END_OF_TABLE
278 /** List of tokens allowable in extra-info documents. */
279 static token_rule_t extrainfo_token_table[] = {
280 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
281 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
282 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
283 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
284 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
285 T01("dirreq-stats-end", K_DIRREQ_END, ARGS, NO_OBJ ),
286 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS, ARGS, NO_OBJ ),
287 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS, ARGS, NO_OBJ ),
288 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS, ARGS, NO_OBJ ),
289 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS, ARGS, NO_OBJ ),
290 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE, ARGS, NO_OBJ ),
291 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE, ARGS, NO_OBJ ),
292 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP, ARGS, NO_OBJ ),
293 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP, ARGS, NO_OBJ ),
294 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR, ARGS, NO_OBJ ),
295 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR, ARGS, NO_OBJ ),
296 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN, ARGS, NO_OBJ ),
297 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN, ARGS, NO_OBJ ),
298 T01("entry-stats-end", K_ENTRY_END, ARGS, NO_OBJ ),
299 T01("entry-ips", K_ENTRY_IPS, ARGS, NO_OBJ ),
300 T01("cell-stats-end", K_CELL_END, ARGS, NO_OBJ ),
301 T01("cell-processed-cells", K_CELL_PROCESSED, ARGS, NO_OBJ ),
302 T01("cell-queued-cells", K_CELL_QUEUED, ARGS, NO_OBJ ),
303 T01("cell-time-in-queue", K_CELL_TIME, ARGS, NO_OBJ ),
304 T01("cell-circuits-per-decile", K_CELL_CIRCS, ARGS, NO_OBJ ),
305 T01("exit-stats-end", K_EXIT_END, ARGS, NO_OBJ ),
306 T01("exit-kibibytes-written", K_EXIT_WRITTEN, ARGS, NO_OBJ ),
307 T01("exit-kibibytes-read", K_EXIT_READ, ARGS, NO_OBJ ),
308 T01("exit-streams-opened", K_EXIT_OPENED, ARGS, NO_OBJ ),
310 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
312 END_OF_TABLE
315 /** List of tokens allowable in the body part of v2 and v3 networkstatus
316 * documents. */
317 static token_rule_t rtrstatus_token_table[] = {
318 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
319 T1( "r", K_R, GE(8), NO_OBJ ),
320 T1( "s", K_S, ARGS, NO_OBJ ),
321 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
322 T01("w", K_W, ARGS, NO_OBJ ),
323 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
324 END_OF_TABLE
327 /** List of tokens allowable in the header part of v2 networkstatus documents.
329 static token_rule_t netstatus_token_table[] = {
330 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
331 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
332 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
333 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
334 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
335 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
336 GE(1), NO_OBJ ),
337 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
338 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
339 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
340 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
342 END_OF_TABLE
345 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
346 * footers. */
347 static token_rule_t dir_footer_token_table[] = {
348 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
349 END_OF_TABLE
352 /** List of tokens allowable in v1 directory headers/footers. */
353 static token_rule_t dir_token_table[] = {
354 /* don't enforce counts; this is obsolete. */
355 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
356 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
357 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
358 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
360 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
361 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
362 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
363 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
364 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
365 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
366 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
368 END_OF_TABLE
371 /** List of tokens common to V3 authority certificates and V3 consensuses. */
372 #define CERTIFICATE_MEMBERS \
373 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
374 GE(1), NO_OBJ ), \
375 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
376 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
377 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
378 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
379 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
380 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
381 NO_ARGS, NEED_OBJ), \
382 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
384 /** List of tokens allowable in V3 authority certificates. */
385 static token_rule_t dir_key_certificate_table[] = {
386 CERTIFICATE_MEMBERS
387 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
388 END_OF_TABLE
391 /** List of tokens allowable in rendezvous service descriptors */
392 static token_rule_t desc_token_table[] = {
393 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
394 EQ(1), NO_OBJ),
395 T1("version", R_VERSION, EQ(1), NO_OBJ),
396 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
397 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
398 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
399 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
400 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
401 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
402 END_OF_TABLE
405 /** List of tokens allowed in the (encrypted) list of introduction points of
406 * rendezvous service descriptors */
407 static token_rule_t ipo_token_table[] = {
408 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
409 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
410 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
411 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
412 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
413 END_OF_TABLE
416 /** List of tokens allowed in the (possibly encrypted) list of introduction
417 * points of rendezvous service descriptors */
418 static token_rule_t client_keys_token_table[] = {
419 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
420 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
421 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
422 END_OF_TABLE
425 /** List of tokens allowed in V3 networkstatus votes. */
426 static token_rule_t networkstatus_token_table[] = {
427 T1("network-status-version", K_NETWORK_STATUS_VERSION,
428 GE(1), NO_OBJ ),
429 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
430 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
431 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
432 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
433 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
434 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
435 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
436 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
438 CERTIFICATE_MEMBERS
440 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
441 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
442 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
443 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
444 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
445 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
446 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
447 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
449 END_OF_TABLE
452 /** List of tokens allowed in V3 networkstatus consensuses. */
453 static token_rule_t networkstatus_consensus_token_table[] = {
454 T1("network-status-version", K_NETWORK_STATUS_VERSION,
455 GE(1), NO_OBJ ),
456 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
457 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
458 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
459 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
460 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
462 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
464 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
465 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
466 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
468 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
470 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
471 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
472 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
474 END_OF_TABLE
477 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
478 * footers. */
479 static token_rule_t networkstatus_vote_footer_token_table[] = {
480 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
481 END_OF_TABLE
484 /** List of tokens allowable in detached networkstatus signature documents. */
485 static token_rule_t networkstatus_detached_signature_token_table[] = {
486 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
487 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
488 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
489 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
490 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
491 END_OF_TABLE
494 #undef T
496 /* static function prototypes */
497 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
498 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok);
499 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
501 static int router_get_hash_impl(const char *s, char *digest,
502 const char *start_str, const char *end_str,
503 char end_char);
504 static void token_free(directory_token_t *tok);
505 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
506 static directory_token_t *_find_by_keyword(smartlist_t *s,
507 directory_keyword keyword,
508 const char *keyword_str);
509 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
510 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
511 directory_keyword keyword);
513 #define TS_ANNOTATIONS_OK 1
514 #define TS_NOCHECK 2
515 #define TS_NO_NEW_ANNOTATIONS 4
516 static int tokenize_string(memarea_t *area,
517 const char *start, const char *end,
518 smartlist_t *out,
519 token_rule_t *table,
520 int flags);
521 static directory_token_t *get_next_token(memarea_t *area,
522 const char **s,
523 const char *eos,
524 token_rule_t *table);
525 #define CST_CHECK_AUTHORITY (1<<0)
526 #define CST_NO_CHECK_OBJTYPE (1<<1)
527 static int check_signature_token(const char *digest,
528 directory_token_t *tok,
529 crypto_pk_env_t *pkey,
530 int flags,
531 const char *doctype);
532 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
533 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
535 #undef DEBUG_AREA_ALLOC
537 #ifdef DEBUG_AREA_ALLOC
538 #define DUMP_AREA(a,name) STMT_BEGIN \
539 size_t alloc=0, used=0; \
540 memarea_get_stats((a),&alloc,&used); \
541 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
542 name, (unsigned long)alloc, (unsigned long)used); \
543 STMT_END
544 #else
545 #define DUMP_AREA(a,name) STMT_NIL
546 #endif
548 /** Last time we dumped a descriptor to disk. */
549 static time_t last_desc_dumped = 0;
551 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
552 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
553 * than one descriptor to disk per minute. If there is already such a
554 * file in the data directory, overwrite it. */
555 static void
556 dump_desc(const char *desc, const char *type)
558 time_t now = time(NULL);
559 tor_assert(desc);
560 tor_assert(type);
561 if (!last_desc_dumped || last_desc_dumped + 60 < now) {
562 char *debugfile = get_datadir_fname("unparseable-desc");
563 size_t filelen = 50 + strlen(type) + strlen(desc);
564 char *content = tor_malloc_zero(filelen);
565 tor_snprintf(content, filelen, "Unable to parse descriptor of type "
566 "%s:\n%s", type, desc);
567 write_str_to_file(debugfile, content, 0);
568 log_info(LD_DIR, "Unable to parse descriptor of type %s. See file "
569 "unparseable-desc in data directory for details.", type);
570 tor_free(content);
571 tor_free(debugfile);
572 last_desc_dumped = now;
576 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
577 * <b>s</b>. Return 0 on success, -1 on failure.
580 router_get_dir_hash(const char *s, char *digest)
582 return router_get_hash_impl(s,digest,
583 "signed-directory","\ndirectory-signature",'\n');
586 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
587 * <b>s</b>. Return 0 on success, -1 on failure.
590 router_get_router_hash(const char *s, char *digest)
592 return router_get_hash_impl(s,digest,
593 "router ","\nrouter-signature", '\n');
596 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
597 * string in <b>s</b>. Return 0 on success, -1 on failure.
600 router_get_runningrouters_hash(const char *s, char *digest)
602 return router_get_hash_impl(s,digest,
603 "network-status","\ndirectory-signature", '\n');
606 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
607 * string in <b>s</b>. Return 0 on success, -1 on failure. */
609 router_get_networkstatus_v2_hash(const char *s, char *digest)
611 return router_get_hash_impl(s,digest,
612 "network-status-version","\ndirectory-signature",
613 '\n');
616 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
617 * string in <b>s</b>. Return 0 on success, -1 on failure. */
619 router_get_networkstatus_v3_hash(const char *s, char *digest)
621 return router_get_hash_impl(s,digest,
622 "network-status-version","\ndirectory-signature",
623 ' ');
626 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
627 * string in <b>s</b>. Return 0 on success, -1 on failure. */
629 router_get_extrainfo_hash(const char *s, char *digest)
631 return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature",'\n');
634 /** Helper: used to generate signatures for routers, directories and
635 * network-status objects. Given a digest in <b>digest</b> and a secret
636 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
637 * surround it with -----BEGIN/END----- pairs, and write it to the
638 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
639 * failure.
642 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
643 crypto_pk_env_t *private_key)
645 char *signature;
646 size_t i;
648 signature = tor_malloc(crypto_pk_keysize(private_key));
649 if (crypto_pk_private_sign(private_key, signature, digest, DIGEST_LEN) < 0) {
651 log_warn(LD_BUG,"Couldn't sign digest.");
652 goto err;
654 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
655 goto truncated;
657 i = strlen(buf);
658 if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) {
659 log_warn(LD_BUG,"couldn't base64-encode signature");
660 goto err;
663 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
664 goto truncated;
666 tor_free(signature);
667 return 0;
669 truncated:
670 log_warn(LD_BUG,"tried to exceed string length.");
671 err:
672 tor_free(signature);
673 return -1;
676 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
677 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
678 * entries. Else, return VS_OLD if every member of
679 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
680 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
681 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
682 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
683 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
684 * VS_UNRECOMMENDED.
686 * (versionlist is a comma-separated list of version strings,
687 * optionally prefixed with "Tor". Versions that can't be parsed are
688 * ignored.)
690 version_status_t
691 tor_version_is_obsolete(const char *myversion, const char *versionlist)
693 tor_version_t mine, other;
694 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
695 found_any_in_series = 0, r, same;
696 version_status_t ret = VS_UNRECOMMENDED;
697 smartlist_t *version_sl;
699 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
700 myversion, versionlist);
702 if (tor_version_parse(myversion, &mine)) {
703 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
704 tor_assert(0);
706 version_sl = smartlist_create();
707 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
709 if (!strlen(versionlist)) { /* no authorities cared or agreed */
710 ret = VS_EMPTY;
711 goto done;
714 SMARTLIST_FOREACH(version_sl, const char *, cp, {
715 if (!strcmpstart(cp, "Tor "))
716 cp += 4;
718 if (tor_version_parse(cp, &other)) {
719 /* Couldn't parse other; it can't be a match. */
720 } else {
721 same = tor_version_same_series(&mine, &other);
722 if (same)
723 found_any_in_series = 1;
724 r = tor_version_compare(&mine, &other);
725 if (r==0) {
726 ret = VS_RECOMMENDED;
727 goto done;
728 } else if (r<0) {
729 found_newer = 1;
730 if (same)
731 found_newer_in_series = 1;
732 } else if (r>0) {
733 found_older = 1;
738 /* We didn't find the listed version. Is it new or old? */
739 if (found_any_in_series && !found_newer_in_series && found_newer) {
740 ret = VS_NEW_IN_SERIES;
741 } else if (found_newer && !found_older) {
742 ret = VS_OLD;
743 } else if (found_older && !found_newer) {
744 ret = VS_NEW;
745 } else {
746 ret = VS_UNRECOMMENDED;
749 done:
750 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
751 smartlist_free(version_sl);
752 return ret;
755 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
756 * Otherwise, return -1. If we're a directory cache, cache it.
759 router_parse_directory(const char *str)
761 directory_token_t *tok;
762 char digest[DIGEST_LEN];
763 time_t published_on;
764 int r;
765 const char *end, *cp, *str_dup = str;
766 smartlist_t *tokens = NULL;
767 crypto_pk_env_t *declared_key = NULL;
768 memarea_t *area = memarea_new();
770 /* XXXX This could be simplified a lot, but it will all go away
771 * once pre-0.1.1.8 is obsolete, and for now it's better not to
772 * touch it. */
774 if (router_get_dir_hash(str, digest)) {
775 log_warn(LD_DIR, "Unable to compute digest of directory");
776 goto err;
778 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
780 /* Check signature first, before we try to tokenize. */
781 cp = str;
782 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
783 cp = end;
784 if (cp == str || !cp) {
785 log_warn(LD_DIR, "No signature found on directory."); goto err;
787 ++cp;
788 tokens = smartlist_create();
789 if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
790 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
792 if (smartlist_len(tokens) != 1) {
793 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
795 tok=smartlist_get(tokens,0);
796 if (tok->tp != K_DIRECTORY_SIGNATURE) {
797 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
799 declared_key = find_dir_signing_key(str, str+strlen(str));
800 note_crypto_pk_op(VERIFY_DIR);
801 if (check_signature_token(digest, tok, declared_key,
802 CST_CHECK_AUTHORITY, "directory")<0)
803 goto err;
805 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
806 smartlist_clear(tokens);
807 memarea_clear(area);
809 /* Now try to parse the first part of the directory. */
810 if ((end = strstr(str,"\nrouter "))) {
811 ++end;
812 } else if ((end = strstr(str, "\ndirectory-signature"))) {
813 ++end;
814 } else {
815 end = str + strlen(str);
818 if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
819 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
822 tok = find_by_keyword(tokens, K_PUBLISHED);
823 tor_assert(tok->n_args == 1);
825 if (parse_iso_time(tok->args[0], &published_on) < 0) {
826 goto err;
829 /* Now that we know the signature is okay, and we have a
830 * publication time, cache the directory. */
831 if (directory_caches_v1_dir_info(get_options()) &&
832 !authdir_mode_v1(get_options()))
833 dirserv_set_cached_directory(str, published_on, 0);
835 r = 0;
836 goto done;
837 err:
838 dump_desc(str_dup, "v1 directory");
839 r = -1;
840 done:
841 if (declared_key) crypto_free_pk_env(declared_key);
842 if (tokens) {
843 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
844 smartlist_free(tokens);
846 if (area) {
847 DUMP_AREA(area, "v1 directory");
848 memarea_drop_all(area);
850 return r;
853 /** Read a signed router status statement from <b>str</b>. If it's
854 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
855 * cache it.*/
857 router_parse_runningrouters(const char *str)
859 char digest[DIGEST_LEN];
860 directory_token_t *tok;
861 time_t published_on;
862 int r = -1;
863 crypto_pk_env_t *declared_key = NULL;
864 smartlist_t *tokens = NULL;
865 const char *eos = str + strlen(str), *str_dup = str;
866 memarea_t *area = NULL;
868 if (router_get_runningrouters_hash(str, digest)) {
869 log_warn(LD_DIR, "Unable to compute digest of running-routers");
870 goto err;
872 area = memarea_new();
873 tokens = smartlist_create();
874 if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
875 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
877 tok = smartlist_get(tokens,0);
878 if (tok->tp != K_NETWORK_STATUS) {
879 log_warn(LD_DIR, "Network-status starts with wrong token");
880 goto err;
883 tok = find_by_keyword(tokens, K_PUBLISHED);
884 tor_assert(tok->n_args == 1);
885 if (parse_iso_time(tok->args[0], &published_on) < 0) {
886 goto err;
888 if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
889 log_warn(LD_DIR, "Missing signature on running-routers");
890 goto err;
892 declared_key = find_dir_signing_key(str, eos);
893 note_crypto_pk_op(VERIFY_DIR);
894 if (check_signature_token(digest, tok, declared_key,
895 CST_CHECK_AUTHORITY, "running-routers")
896 < 0)
897 goto err;
899 /* Now that we know the signature is okay, and we have a
900 * publication time, cache the list. */
901 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
902 dirserv_set_cached_directory(str, published_on, 1);
904 r = 0;
905 err:
906 dump_desc(str_dup, "v1 running-routers");
907 if (declared_key) crypto_free_pk_env(declared_key);
908 if (tokens) {
909 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
910 smartlist_free(tokens);
912 if (area) {
913 DUMP_AREA(area, "v1 running-routers");
914 memarea_drop_all(area);
916 return r;
919 /** Given a directory or running-routers string in <b>str</b>, try to
920 * find the its dir-signing-key token (if any). If this token is
921 * present, extract and return the key. Return NULL on failure. */
922 static crypto_pk_env_t *
923 find_dir_signing_key(const char *str, const char *eos)
925 const char *cp;
926 directory_token_t *tok;
927 crypto_pk_env_t *key = NULL;
928 memarea_t *area = NULL;
929 tor_assert(str);
930 tor_assert(eos);
932 /* Is there a dir-signing-key in the directory? */
933 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
934 if (!cp)
935 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
936 if (!cp)
937 return NULL;
938 ++cp; /* Now cp points to the start of the token. */
940 area = memarea_new();
941 tok = get_next_token(area, &cp, eos, dir_token_table);
942 if (!tok) {
943 log_warn(LD_DIR, "Unparseable dir-signing-key token");
944 goto done;
946 if (tok->tp != K_DIR_SIGNING_KEY) {
947 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
948 goto done;
951 if (tok->key) {
952 key = tok->key;
953 tok->key = NULL; /* steal reference. */
954 } else {
955 log_warn(LD_DIR, "Dir-signing-key token contained no key");
958 done:
959 if (tok) token_free(tok);
960 if (area) {
961 DUMP_AREA(area, "dir-signing-key token");
962 memarea_drop_all(area);
964 return key;
967 /** Return true iff <b>key</b> is allowed to sign directories.
969 static int
970 dir_signing_key_is_trusted(crypto_pk_env_t *key)
972 char digest[DIGEST_LEN];
973 if (!key) return 0;
974 if (crypto_pk_get_digest(key, digest) < 0) {
975 log_warn(LD_DIR, "Error computing dir-signing-key digest");
976 return 0;
978 if (!router_digest_is_trusted_dir(digest)) {
979 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
980 return 0;
982 return 1;
985 /** Check whether the object body of the token in <b>tok</b> has a good
986 * signature for <b>digest</b> using key <b>pkey</b>. If
987 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
988 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
989 * the object type of the signature object. Use <b>doctype</b> as the type of
990 * the document when generating log messages. Return 0 on success, negative
991 * on failure.
993 static int
994 check_signature_token(const char *digest,
995 directory_token_t *tok,
996 crypto_pk_env_t *pkey,
997 int flags,
998 const char *doctype)
1000 char *signed_digest;
1001 const int check_authority = (flags & CST_CHECK_AUTHORITY);
1002 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
1004 tor_assert(pkey);
1005 tor_assert(tok);
1006 tor_assert(digest);
1007 tor_assert(doctype);
1009 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
1010 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
1011 doctype);
1012 return -1;
1015 if (check_objtype) {
1016 if (strcmp(tok->object_type, "SIGNATURE")) {
1017 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
1018 return -1;
1022 signed_digest = tor_malloc(tok->object_size);
1023 if (crypto_pk_public_checksig(pkey, signed_digest, tok->object_body,
1024 tok->object_size)
1025 != DIGEST_LEN) {
1026 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
1027 tor_free(signed_digest);
1028 return -1;
1030 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
1031 // hex_str(signed_digest,4));
1032 if (memcmp(digest, signed_digest, DIGEST_LEN)) {
1033 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
1034 tor_free(signed_digest);
1035 return -1;
1037 tor_free(signed_digest);
1038 return 0;
1041 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
1042 * or to the first of the annotations proceeding the next router or
1043 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
1044 * we found an extrainfo, or false if found a router. Do not scan beyond
1045 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
1046 static int
1047 find_start_of_next_router_or_extrainfo(const char **s_ptr,
1048 const char *eos,
1049 int *is_extrainfo_out)
1051 const char *annotations = NULL;
1052 const char *s = *s_ptr;
1054 s = eat_whitespace_eos(s, eos);
1056 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
1057 /* We're at the start of a line. */
1058 tor_assert(*s != '\n');
1060 if (*s == '@' && !annotations) {
1061 annotations = s;
1062 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
1063 *s_ptr = annotations ? annotations : s;
1064 *is_extrainfo_out = 0;
1065 return 0;
1066 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
1067 *s_ptr = annotations ? annotations : s;
1068 *is_extrainfo_out = 1;
1069 return 0;
1072 if (!(s = memchr(s+1, '\n', eos-(s+1))))
1073 break;
1074 s = eat_whitespace_eos(s, eos);
1076 return -1;
1079 /** Given a string *<b>s</b> containing a concatenated sequence of router
1080 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1081 * them and stores the result in <b>dest</b>. All routers are marked running
1082 * and valid. Advances *s to a point immediately following the last router
1083 * entry. Ignore any trailing router entries that are not complete.
1085 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1086 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1087 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1089 * Returns 0 on success and -1 on failure.
1092 router_parse_list_from_string(const char **s, const char *eos,
1093 smartlist_t *dest,
1094 saved_location_t saved_location,
1095 int want_extrainfo,
1096 int allow_annotations,
1097 const char *prepend_annotations)
1099 routerinfo_t *router;
1100 extrainfo_t *extrainfo;
1101 signed_descriptor_t *signed_desc;
1102 void *elt;
1103 const char *end, *start;
1104 int have_extrainfo;
1106 tor_assert(s);
1107 tor_assert(*s);
1108 tor_assert(dest);
1110 start = *s;
1111 if (!eos)
1112 eos = *s + strlen(*s);
1114 tor_assert(eos >= *s);
1116 while (1) {
1117 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1118 break;
1120 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1121 if (end)
1122 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1123 if (end)
1124 end += strlen("\n-----END SIGNATURE-----\n");
1126 if (!end)
1127 break;
1129 elt = NULL;
1131 if (have_extrainfo && want_extrainfo) {
1132 routerlist_t *rl = router_get_routerlist();
1133 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1134 saved_location != SAVED_IN_CACHE,
1135 rl->identity_map);
1136 if (extrainfo) {
1137 signed_desc = &extrainfo->cache_info;
1138 elt = extrainfo;
1140 } else if (!have_extrainfo && !want_extrainfo) {
1141 router = router_parse_entry_from_string(*s, end,
1142 saved_location != SAVED_IN_CACHE,
1143 allow_annotations,
1144 prepend_annotations);
1145 if (router) {
1146 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1147 router->nickname, router_purpose_to_string(router->purpose));
1148 signed_desc = &router->cache_info;
1149 elt = router;
1152 if (!elt) {
1153 *s = end;
1154 continue;
1156 if (saved_location != SAVED_NOWHERE) {
1157 signed_desc->saved_location = saved_location;
1158 signed_desc->saved_offset = *s - start;
1160 *s = end;
1161 smartlist_add(dest, elt);
1164 return 0;
1167 /* For debugging: define to count every descriptor digest we've seen so we
1168 * know if we need to try harder to avoid duplicate verifies. */
1169 #undef COUNT_DISTINCT_DIGESTS
1171 #ifdef COUNT_DISTINCT_DIGESTS
1172 static digestmap_t *verified_digests = NULL;
1173 #endif
1175 /** Log the total count of the number of distinct router digests we've ever
1176 * verified. When compared to the number of times we've verified routerdesc
1177 * signatures <i>in toto</i>, this will tell us if we're doing too much
1178 * multiple-verification. */
1179 void
1180 dump_distinct_digest_count(int severity)
1182 #ifdef COUNT_DISTINCT_DIGESTS
1183 if (!verified_digests)
1184 verified_digests = digestmap_new();
1185 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1186 digestmap_size(verified_digests));
1187 #else
1188 (void)severity; /* suppress "unused parameter" warning */
1189 #endif
1192 /** Helper function: reads a single router entry from *<b>s</b> ...
1193 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1194 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1195 * s through end into the signed_descriptor_body of the resulting
1196 * routerinfo_t.
1198 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1199 * before the router; if it's false, reject the router if it's annotated. If
1200 * <b>prepend_annotations</b> is set, it should contain some annotations:
1201 * append them to the front of the router before parsing it, and keep them
1202 * around when caching the router.
1204 * Only one of allow_annotations and prepend_annotations may be set.
1206 routerinfo_t *
1207 router_parse_entry_from_string(const char *s, const char *end,
1208 int cache_copy, int allow_annotations,
1209 const char *prepend_annotations)
1211 routerinfo_t *router = NULL;
1212 char digest[128];
1213 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1214 directory_token_t *tok;
1215 struct in_addr in;
1216 const char *start_of_annotations, *cp, *s_dup = s;
1217 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1218 int ok = 1;
1219 memarea_t *area = NULL;
1221 tor_assert(!allow_annotations || !prepend_annotations);
1223 if (!end) {
1224 end = s + strlen(s);
1227 /* point 'end' to a point immediately after the final newline. */
1228 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1229 --end;
1231 area = memarea_new();
1232 tokens = smartlist_create();
1233 if (prepend_annotations) {
1234 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1235 routerdesc_token_table,TS_NOCHECK)) {
1236 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1237 goto err;
1241 start_of_annotations = s;
1242 cp = tor_memstr(s, end-s, "\nrouter ");
1243 if (!cp) {
1244 if (end-s < 7 || strcmpstart(s, "router ")) {
1245 log_warn(LD_DIR, "No router keyword found.");
1246 goto err;
1248 } else {
1249 s = cp+1;
1252 if (allow_annotations && start_of_annotations != s) {
1253 if (tokenize_string(area,start_of_annotations,s,tokens,
1254 routerdesc_token_table,TS_NOCHECK)) {
1255 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1256 goto err;
1260 if (router_get_router_hash(s, digest) < 0) {
1261 log_warn(LD_DIR, "Couldn't compute router hash.");
1262 goto err;
1265 int flags = 0;
1266 if (allow_annotations)
1267 flags |= TS_ANNOTATIONS_OK;
1268 if (prepend_annotations)
1269 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1271 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1272 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1273 goto err;
1277 if (smartlist_len(tokens) < 2) {
1278 log_warn(LD_DIR, "Impossibly short router descriptor.");
1279 goto err;
1282 tok = find_by_keyword(tokens, K_ROUTER);
1283 tor_assert(tok->n_args >= 5);
1285 router = tor_malloc_zero(sizeof(routerinfo_t));
1286 router->country = -1;
1287 router->cache_info.routerlist_index = -1;
1288 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1289 router->cache_info.signed_descriptor_len = end-s;
1290 if (cache_copy) {
1291 size_t len = router->cache_info.signed_descriptor_len +
1292 router->cache_info.annotations_len;
1293 char *cp =
1294 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1295 if (prepend_annotations) {
1296 memcpy(cp, prepend_annotations, prepend_len);
1297 cp += prepend_len;
1299 /* This assertion will always succeed.
1300 * len == signed_desc_len + annotations_len
1301 * == end-s + s-start_of_annotations + prepend_len
1302 * == end-start_of_annotations + prepend_len
1303 * We already wrote prepend_len bytes into the buffer; now we're
1304 * writing end-start_of_annotations -NM. */
1305 tor_assert(cp+(end-start_of_annotations) ==
1306 router->cache_info.signed_descriptor_body+len);
1307 memcpy(cp, start_of_annotations, end-start_of_annotations);
1308 router->cache_info.signed_descriptor_body[len] = '\0';
1309 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1311 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1313 router->nickname = tor_strdup(tok->args[0]);
1314 if (!is_legal_nickname(router->nickname)) {
1315 log_warn(LD_DIR,"Router nickname is invalid");
1316 goto err;
1318 router->address = tor_strdup(tok->args[1]);
1319 if (!tor_inet_aton(router->address, &in)) {
1320 log_warn(LD_DIR,"Router address is not an IP address.");
1321 goto err;
1323 router->addr = ntohl(in.s_addr);
1325 router->or_port =
1326 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1327 if (!ok) {
1328 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1329 goto err;
1331 router->dir_port =
1332 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1333 if (!ok) {
1334 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1335 goto err;
1338 tok = find_by_keyword(tokens, K_BANDWIDTH);
1339 tor_assert(tok->n_args >= 3);
1340 router->bandwidthrate = (int)
1341 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1343 if (!ok) {
1344 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1345 escaped(tok->args[0]));
1346 goto err;
1348 router->bandwidthburst =
1349 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1350 if (!ok) {
1351 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1352 goto err;
1354 router->bandwidthcapacity = (int)
1355 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1356 if (!ok) {
1357 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1358 goto err;
1361 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1362 tor_assert(tok->n_args);
1363 router->purpose = router_purpose_from_string(tok->args[0]);
1364 } else {
1365 router->purpose = ROUTER_PURPOSE_GENERAL;
1367 router->cache_info.send_unencrypted =
1368 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1370 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1371 tor_assert(tok->n_args >= 1);
1372 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1373 if (!ok) {
1374 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1375 goto err;
1379 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1380 tor_assert(tok->n_args >= 1);
1381 router->is_hibernating
1382 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1385 tok = find_by_keyword(tokens, K_PUBLISHED);
1386 tor_assert(tok->n_args == 1);
1387 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1388 goto err;
1390 tok = find_by_keyword(tokens, K_ONION_KEY);
1391 router->onion_pkey = tok->key;
1392 tok->key = NULL; /* Prevent free */
1394 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1395 router->identity_pkey = tok->key;
1396 tok->key = NULL; /* Prevent free */
1397 if (crypto_pk_get_digest(router->identity_pkey,
1398 router->cache_info.identity_digest)) {
1399 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1402 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1403 /* If there's a fingerprint line, it must match the identity digest. */
1404 char d[DIGEST_LEN];
1405 tor_assert(tok->n_args == 1);
1406 tor_strstrip(tok->args[0], " ");
1407 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1408 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1409 escaped(tok->args[0]));
1410 goto err;
1412 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1413 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1414 tok->args[0]);
1415 goto err;
1419 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1420 router->platform = tor_strdup(tok->args[0]);
1423 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1424 router->contact_info = tor_strdup(tok->args[0]);
1427 if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
1428 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1429 } else if (router->platform) {
1430 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1431 router->has_old_dnsworkers = 1;
1434 exit_policy_tokens = find_all_exitpolicy(tokens);
1435 if (!smartlist_len(exit_policy_tokens)) {
1436 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1437 goto err;
1439 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1440 if (router_add_exit_policy(router,t)<0) {
1441 log_warn(LD_DIR,"Error in exit policy");
1442 goto err;
1444 policy_expand_private(&router->exit_policy);
1445 if (policy_is_reject_star(router->exit_policy))
1446 router->policy_is_reject_star = 1;
1448 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1449 int i;
1450 router->declared_family = smartlist_create();
1451 for (i=0;i<tok->n_args;++i) {
1452 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1453 log_warn(LD_DIR, "Illegal nickname %s in family line",
1454 escaped(tok->args[i]));
1455 goto err;
1457 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1461 if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1462 router->caches_extra_info = 1;
1464 if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
1465 router->allow_single_hop_exits = 1;
1467 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1468 tor_assert(tok->n_args >= 1);
1469 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1470 base16_decode(router->cache_info.extra_info_digest,
1471 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1472 } else {
1473 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1477 if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1478 router->wants_to_be_hs_dir = 1;
1481 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1482 note_crypto_pk_op(VERIFY_RTR);
1483 #ifdef COUNT_DISTINCT_DIGESTS
1484 if (!verified_digests)
1485 verified_digests = digestmap_new();
1486 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1487 #endif
1488 if (check_signature_token(digest, tok, router->identity_pkey, 0,
1489 "router descriptor") < 0)
1490 goto err;
1492 routerinfo_set_country(router);
1494 if (!router->or_port) {
1495 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1496 goto err;
1499 if (!router->platform) {
1500 router->platform = tor_strdup("<unknown>");
1503 goto done;
1505 err:
1506 dump_desc(s_dup, "router descriptor");
1507 routerinfo_free(router);
1508 router = NULL;
1509 done:
1510 if (tokens) {
1511 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1512 smartlist_free(tokens);
1514 if (exit_policy_tokens) {
1515 smartlist_free(exit_policy_tokens);
1517 if (area) {
1518 DUMP_AREA(area, "routerinfo");
1519 memarea_drop_all(area);
1521 return router;
1524 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1525 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1526 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1527 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1528 * as a map from router identity to routerinfo_t when looking up signing keys.
1530 extrainfo_t *
1531 extrainfo_parse_entry_from_string(const char *s, const char *end,
1532 int cache_copy, struct digest_ri_map_t *routermap)
1534 extrainfo_t *extrainfo = NULL;
1535 char digest[128];
1536 smartlist_t *tokens = NULL;
1537 directory_token_t *tok;
1538 crypto_pk_env_t *key = NULL;
1539 routerinfo_t *router = NULL;
1540 memarea_t *area = NULL;
1541 const char *s_dup = s;
1543 if (!end) {
1544 end = s + strlen(s);
1547 /* point 'end' to a point immediately after the final newline. */
1548 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1549 --end;
1551 if (router_get_extrainfo_hash(s, digest) < 0) {
1552 log_warn(LD_DIR, "Couldn't compute router hash.");
1553 goto err;
1555 tokens = smartlist_create();
1556 area = memarea_new();
1557 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1558 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1559 goto err;
1562 if (smartlist_len(tokens) < 2) {
1563 log_warn(LD_DIR, "Impossibly short extra-info document.");
1564 goto err;
1567 tok = smartlist_get(tokens,0);
1568 if (tok->tp != K_EXTRA_INFO) {
1569 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1570 goto err;
1573 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1574 extrainfo->cache_info.is_extrainfo = 1;
1575 if (cache_copy)
1576 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1577 extrainfo->cache_info.signed_descriptor_len = end-s;
1578 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1580 tor_assert(tok->n_args >= 2);
1581 if (!is_legal_nickname(tok->args[0])) {
1582 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1583 goto err;
1585 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1586 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1587 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1588 tok->args[1], HEX_DIGEST_LEN)) {
1589 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1590 escaped(tok->args[1]));
1591 goto err;
1594 tok = find_by_keyword(tokens, K_PUBLISHED);
1595 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1596 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1597 escaped(tok->args[0]));
1598 goto err;
1601 if (routermap &&
1602 (router = digestmap_get((digestmap_t*)routermap,
1603 extrainfo->cache_info.identity_digest))) {
1604 key = router->identity_pkey;
1607 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1608 if (strcmp(tok->object_type, "SIGNATURE") ||
1609 tok->object_size < 128 || tok->object_size > 512) {
1610 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1611 goto err;
1614 if (key) {
1615 note_crypto_pk_op(VERIFY_RTR);
1616 if (check_signature_token(digest, tok, key, 0, "extra-info") < 0)
1617 goto err;
1619 if (router)
1620 extrainfo->cache_info.send_unencrypted =
1621 router->cache_info.send_unencrypted;
1622 } else {
1623 extrainfo->pending_sig = tor_memdup(tok->object_body,
1624 tok->object_size);
1625 extrainfo->pending_sig_len = tok->object_size;
1628 goto done;
1629 err:
1630 dump_desc(s_dup, "extra-info descriptor");
1631 if (extrainfo)
1632 extrainfo_free(extrainfo);
1633 extrainfo = NULL;
1634 done:
1635 if (tokens) {
1636 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1637 smartlist_free(tokens);
1639 if (area) {
1640 DUMP_AREA(area, "extrainfo");
1641 memarea_drop_all(area);
1643 return extrainfo;
1646 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1647 * the first character after the certificate. */
1648 authority_cert_t *
1649 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1651 authority_cert_t *cert = NULL, *old_cert;
1652 smartlist_t *tokens = NULL;
1653 char digest[DIGEST_LEN];
1654 directory_token_t *tok;
1655 char fp_declared[DIGEST_LEN];
1656 char *eos;
1657 size_t len;
1658 int found;
1659 memarea_t *area = NULL;
1660 const char *s_dup = s;
1662 s = eat_whitespace(s);
1663 eos = strstr(s, "\ndir-key-certification");
1664 if (! eos) {
1665 log_warn(LD_DIR, "No signature found on key certificate");
1666 return NULL;
1668 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1669 if (! eos) {
1670 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1671 return NULL;
1673 eos = strchr(eos+2, '\n');
1674 tor_assert(eos);
1675 ++eos;
1676 len = eos - s;
1678 tokens = smartlist_create();
1679 area = memarea_new();
1680 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1681 log_warn(LD_DIR, "Error tokenizing key certificate");
1682 goto err;
1684 if (router_get_hash_impl(s, digest, "dir-key-certificate-version",
1685 "\ndir-key-certification", '\n') < 0)
1686 goto err;
1687 tok = smartlist_get(tokens, 0);
1688 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1689 log_warn(LD_DIR,
1690 "Key certificate does not begin with a recognized version (3).");
1691 goto err;
1694 cert = tor_malloc_zero(sizeof(authority_cert_t));
1695 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1697 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1698 tor_assert(tok->key);
1699 cert->signing_key = tok->key;
1700 tok->key = NULL;
1701 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1702 goto err;
1704 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1705 tor_assert(tok->key);
1706 cert->identity_key = tok->key;
1707 tok->key = NULL;
1709 tok = find_by_keyword(tokens, K_FINGERPRINT);
1710 tor_assert(tok->n_args);
1711 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1712 strlen(tok->args[0]))) {
1713 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1714 escaped(tok->args[0]));
1715 goto err;
1718 if (crypto_pk_get_digest(cert->identity_key,
1719 cert->cache_info.identity_digest))
1720 goto err;
1722 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1723 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1724 "fingerprint");
1725 goto err;
1728 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1729 if (tok) {
1730 struct in_addr in;
1731 char *address = NULL;
1732 tor_assert(tok->n_args);
1733 /* XXX021 use tor_addr_port_parse() below instead. -RD */
1734 if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
1735 &cert->dir_port)<0 ||
1736 tor_inet_aton(address, &in) == 0) {
1737 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1738 tor_free(address);
1739 goto err;
1741 cert->addr = ntohl(in.s_addr);
1742 tor_free(address);
1745 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1746 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1747 goto err;
1749 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1750 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1751 goto err;
1754 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1755 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1756 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1757 goto err;
1760 /* If we already have this cert, don't bother checking the signature. */
1761 old_cert = authority_cert_get_by_digests(
1762 cert->cache_info.identity_digest,
1763 cert->signing_key_digest);
1764 found = 0;
1765 if (old_cert) {
1766 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1767 * buy us much. */
1768 if (old_cert->cache_info.signed_descriptor_len == len &&
1769 old_cert->cache_info.signed_descriptor_body &&
1770 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1771 log_debug(LD_DIR, "We already checked the signature on this "
1772 "certificate; no need to do so again.");
1773 found = 1;
1774 cert->is_cross_certified = old_cert->is_cross_certified;
1777 if (!found) {
1778 if (check_signature_token(digest, tok, cert->identity_key, 0,
1779 "key certificate")) {
1780 goto err;
1783 if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
1784 /* XXXX Once all authorities generate cross-certified certificates,
1785 * make this field mandatory. */
1786 if (check_signature_token(cert->cache_info.identity_digest,
1787 tok,
1788 cert->signing_key,
1789 CST_NO_CHECK_OBJTYPE,
1790 "key cross-certification")) {
1791 goto err;
1793 cert->is_cross_certified = 1;
1797 cert->cache_info.signed_descriptor_len = len;
1798 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1799 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1800 cert->cache_info.signed_descriptor_body[len] = 0;
1801 cert->cache_info.saved_location = SAVED_NOWHERE;
1803 if (end_of_string) {
1804 *end_of_string = eat_whitespace(eos);
1806 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1807 smartlist_free(tokens);
1808 if (area) {
1809 DUMP_AREA(area, "authority cert");
1810 memarea_drop_all(area);
1812 return cert;
1813 err:
1814 dump_desc(s_dup, "authority cert");
1815 authority_cert_free(cert);
1816 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1817 smartlist_free(tokens);
1818 if (area) {
1819 DUMP_AREA(area, "authority cert");
1820 memarea_drop_all(area);
1822 return NULL;
1825 /** Helper: given a string <b>s</b>, return the start of the next router-status
1826 * object (starting with "r " at the start of a line). If none is found,
1827 * return the start of the next directory signature. If none is found, return
1828 * the end of the string. */
1829 static INLINE const char *
1830 find_start_of_next_routerstatus(const char *s)
1832 const char *eos = strstr(s, "\nr ");
1833 if (eos) {
1834 const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
1835 if (eos2 && eos2 < eos)
1836 return eos2;
1837 else
1838 return eos+1;
1839 } else {
1840 if ((eos = strstr(s, "\ndirectory-signature")))
1841 return eos+1;
1842 return s + strlen(s);
1846 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1847 * empty smartlist at <b>tokens</b>, parse and return the first router status
1848 * object in the string, and advance *<b>s</b> to just after the end of the
1849 * router status. Return NULL and advance *<b>s</b> on error.
1851 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1852 * routerstatus but use <b>vote_rs</b> instead.
1854 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1855 * consensus, and we should parse it according to the method used to
1856 * make that consensus.
1858 static routerstatus_t *
1859 routerstatus_parse_entry_from_string(memarea_t *area,
1860 const char **s, smartlist_t *tokens,
1861 networkstatus_t *vote,
1862 vote_routerstatus_t *vote_rs,
1863 int consensus_method)
1865 const char *eos, *s_dup = *s;
1866 routerstatus_t *rs = NULL;
1867 directory_token_t *tok;
1868 char timebuf[ISO_TIME_LEN+1];
1869 struct in_addr in;
1870 tor_assert(tokens);
1871 tor_assert(bool_eq(vote, vote_rs));
1873 eos = find_start_of_next_routerstatus(*s);
1875 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1876 log_warn(LD_DIR, "Error tokenizing router status");
1877 goto err;
1879 if (smartlist_len(tokens) < 1) {
1880 log_warn(LD_DIR, "Impossibly short router status");
1881 goto err;
1883 tok = find_by_keyword(tokens, K_R);
1884 tor_assert(tok->n_args >= 8);
1885 if (vote_rs) {
1886 rs = &vote_rs->status;
1887 } else {
1888 rs = tor_malloc_zero(sizeof(routerstatus_t));
1891 if (!is_legal_nickname(tok->args[0])) {
1892 log_warn(LD_DIR,
1893 "Invalid nickname %s in router status; skipping.",
1894 escaped(tok->args[0]));
1895 goto err;
1897 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1899 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1900 log_warn(LD_DIR, "Error decoding identity digest %s",
1901 escaped(tok->args[1]));
1902 goto err;
1905 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1906 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1907 escaped(tok->args[2]));
1908 goto err;
1911 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1912 tok->args[3], tok->args[4]) < 0 ||
1913 parse_iso_time(timebuf, &rs->published_on)<0) {
1914 log_warn(LD_DIR, "Error parsing time '%s %s'",
1915 tok->args[3], tok->args[4]);
1916 goto err;
1919 if (tor_inet_aton(tok->args[5], &in) == 0) {
1920 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1921 escaped(tok->args[5]));
1922 goto err;
1924 rs->addr = ntohl(in.s_addr);
1926 rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL);
1927 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL);
1929 tok = find_opt_by_keyword(tokens, K_S);
1930 if (tok && vote) {
1931 int i;
1932 vote_rs->flags = 0;
1933 for (i=0; i < tok->n_args; ++i) {
1934 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1935 if (p >= 0) {
1936 vote_rs->flags |= (1<<p);
1937 } else {
1938 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1939 escaped(tok->args[i]));
1940 goto err;
1943 } else if (tok) {
1944 int i;
1945 for (i=0; i < tok->n_args; ++i) {
1946 if (!strcmp(tok->args[i], "Exit"))
1947 rs->is_exit = 1;
1948 else if (!strcmp(tok->args[i], "Stable"))
1949 rs->is_stable = 1;
1950 else if (!strcmp(tok->args[i], "Fast"))
1951 rs->is_fast = 1;
1952 else if (!strcmp(tok->args[i], "Running"))
1953 rs->is_running = 1;
1954 else if (!strcmp(tok->args[i], "Named"))
1955 rs->is_named = 1;
1956 else if (!strcmp(tok->args[i], "Valid"))
1957 rs->is_valid = 1;
1958 else if (!strcmp(tok->args[i], "V2Dir"))
1959 rs->is_v2_dir = 1;
1960 else if (!strcmp(tok->args[i], "Guard"))
1961 rs->is_possible_guard = 1;
1962 else if (!strcmp(tok->args[i], "BadExit"))
1963 rs->is_bad_exit = 1;
1964 else if (!strcmp(tok->args[i], "BadDirectory"))
1965 rs->is_bad_directory = 1;
1966 else if (!strcmp(tok->args[i], "Authority"))
1967 rs->is_authority = 1;
1968 else if (!strcmp(tok->args[i], "Unnamed") &&
1969 consensus_method >= 2) {
1970 /* Unnamed is computed right by consensus method 2 and later. */
1971 rs->is_unnamed = 1;
1972 } else if (!strcmp(tok->args[i], "HSDir")) {
1973 rs->is_hs_dir = 1;
1977 if ((tok = find_opt_by_keyword(tokens, K_V))) {
1978 tor_assert(tok->n_args == 1);
1979 rs->version_known = 1;
1980 if (strcmpstart(tok->args[0], "Tor ")) {
1981 rs->version_supports_begindir = 1;
1982 rs->version_supports_extrainfo_upload = 1;
1983 rs->version_supports_conditional_consensus = 1;
1984 } else {
1985 rs->version_supports_begindir =
1986 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
1987 rs->version_supports_extrainfo_upload =
1988 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
1989 rs->version_supports_v3_dir =
1990 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
1991 rs->version_supports_conditional_consensus =
1992 tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
1994 if (vote_rs) {
1995 vote_rs->version = tor_strdup(tok->args[0]);
1999 /* handle weighting/bandwidth info */
2000 if ((tok = find_opt_by_keyword(tokens, K_W))) {
2001 int i;
2002 for (i=0; i < tok->n_args; ++i) {
2003 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
2004 int ok;
2005 rs->bandwidth = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10,
2006 0, UINT32_MAX, &ok, NULL);
2007 if (!ok) {
2008 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
2009 goto err;
2011 rs->has_bandwidth = 1;
2012 } else if (!strcmpstart(tok->args[i], "Measured=")) {
2013 int ok;
2014 rs->measured_bw = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10,
2015 0, UINT32_MAX, &ok, NULL);
2016 if (!ok) {
2017 log_warn(LD_DIR, "Invalid Measured Bandwidth %s",
2018 escaped(tok->args[i]));
2019 goto err;
2021 rs->has_measured_bw = 1;
2026 /* parse exit policy summaries */
2027 if ((tok = find_opt_by_keyword(tokens, K_P))) {
2028 tor_assert(tok->n_args == 1);
2029 if (strcmpstart(tok->args[0], "accept ") &&
2030 strcmpstart(tok->args[0], "reject ")) {
2031 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
2032 escaped(tok->args[0]));
2033 goto err;
2035 /* XXX weasel: parse this into ports and represent them somehow smart,
2036 * maybe not here but somewhere on if we need it for the client.
2037 * we should still parse it here to check it's valid tho.
2039 rs->exitsummary = tor_strdup(tok->args[0]);
2040 rs->has_exitsummary = 1;
2043 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
2044 rs->is_named = 0;
2046 goto done;
2047 err:
2048 dump_desc(s_dup, "routerstatus entry");
2049 if (rs && !vote_rs)
2050 routerstatus_free(rs);
2051 rs = NULL;
2052 done:
2053 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2054 smartlist_clear(tokens);
2055 if (area) {
2056 DUMP_AREA(area, "routerstatus entry");
2057 memarea_clear(area);
2059 *s = eos;
2061 return rs;
2064 /** Helper to sort a smartlist of pointers to routerstatus_t */
2066 compare_routerstatus_entries(const void **_a, const void **_b)
2068 const routerstatus_t *a = *_a, *b = *_b;
2069 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
2072 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
2073 static void
2074 _free_duplicate_routerstatus_entry(void *e)
2076 log_warn(LD_DIR,
2077 "Network-status has two entries for the same router. "
2078 "Dropping one.");
2079 routerstatus_free(e);
2082 /** Given a v2 network-status object in <b>s</b>, try to
2083 * parse it and return the result. Return NULL on failure. Check the
2084 * signature of the network status, but do not (yet) check the signing key for
2085 * authority.
2087 networkstatus_v2_t *
2088 networkstatus_v2_parse_from_string(const char *s)
2090 const char *eos, *s_dup = s;
2091 smartlist_t *tokens = smartlist_create();
2092 smartlist_t *footer_tokens = smartlist_create();
2093 networkstatus_v2_t *ns = NULL;
2094 char ns_digest[DIGEST_LEN];
2095 char tmp_digest[DIGEST_LEN];
2096 struct in_addr in;
2097 directory_token_t *tok;
2098 int i;
2099 memarea_t *area = NULL;
2101 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
2102 log_warn(LD_DIR, "Unable to compute digest of network-status");
2103 goto err;
2106 area = memarea_new();
2107 eos = find_start_of_next_routerstatus(s);
2108 if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
2109 log_warn(LD_DIR, "Error tokenizing network-status header.");
2110 goto err;
2112 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
2113 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2115 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2116 tor_assert(tok->n_args >= 1);
2117 if (strcmp(tok->args[0], "2")) {
2118 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
2119 "%s", escaped(tok->args[0]));
2120 goto err;
2123 tok = find_by_keyword(tokens, K_DIR_SOURCE);
2124 tor_assert(tok->n_args >= 3);
2125 ns->source_address = tor_strdup(tok->args[0]);
2126 if (tor_inet_aton(tok->args[1], &in) == 0) {
2127 log_warn(LD_DIR, "Error parsing network-status source address %s",
2128 escaped(tok->args[1]));
2129 goto err;
2131 ns->source_addr = ntohl(in.s_addr);
2132 ns->source_dirport =
2133 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
2134 if (ns->source_dirport == 0) {
2135 log_warn(LD_DIR, "Directory source without dirport; skipping.");
2136 goto err;
2139 tok = find_by_keyword(tokens, K_FINGERPRINT);
2140 tor_assert(tok->n_args);
2141 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
2142 strlen(tok->args[0]))) {
2143 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
2144 escaped(tok->args[0]));
2145 goto err;
2148 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2149 tor_assert(tok->n_args);
2150 ns->contact = tor_strdup(tok->args[0]);
2153 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2154 tor_assert(tok->key);
2155 ns->signing_key = tok->key;
2156 tok->key = NULL;
2158 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
2159 log_warn(LD_DIR, "Couldn't compute signing key digest");
2160 goto err;
2162 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
2163 log_warn(LD_DIR,
2164 "network-status fingerprint did not match dir-signing-key");
2165 goto err;
2168 if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
2169 for (i=0; i < tok->n_args; ++i) {
2170 if (!strcmp(tok->args[i], "Names"))
2171 ns->binds_names = 1;
2172 if (!strcmp(tok->args[i], "Versions"))
2173 ns->recommends_versions = 1;
2174 if (!strcmp(tok->args[i], "BadExits"))
2175 ns->lists_bad_exits = 1;
2176 if (!strcmp(tok->args[i], "BadDirectories"))
2177 ns->lists_bad_directories = 1;
2181 if (ns->recommends_versions) {
2182 if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2183 log_warn(LD_DIR, "Missing client-versions on versioning directory");
2184 goto err;
2186 ns->client_versions = tor_strdup(tok->args[0]);
2188 if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
2189 tok->n_args<1) {
2190 log_warn(LD_DIR, "Missing server-versions on versioning directory");
2191 goto err;
2193 ns->server_versions = tor_strdup(tok->args[0]);
2196 tok = find_by_keyword(tokens, K_PUBLISHED);
2197 tor_assert(tok->n_args == 1);
2198 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
2199 goto err;
2202 ns->entries = smartlist_create();
2203 s = eos;
2204 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2205 smartlist_clear(tokens);
2206 memarea_clear(area);
2207 while (!strcmpstart(s, "r ")) {
2208 routerstatus_t *rs;
2209 if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
2210 NULL, NULL, 0)))
2211 smartlist_add(ns->entries, rs);
2213 smartlist_sort(ns->entries, compare_routerstatus_entries);
2214 smartlist_uniq(ns->entries, compare_routerstatus_entries,
2215 _free_duplicate_routerstatus_entry);
2217 if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
2218 log_warn(LD_DIR, "Error tokenizing network-status footer.");
2219 goto err;
2221 if (smartlist_len(footer_tokens) < 1) {
2222 log_warn(LD_DIR, "Too few items in network-status footer.");
2223 goto err;
2225 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
2226 if (tok->tp != K_DIRECTORY_SIGNATURE) {
2227 log_warn(LD_DIR,
2228 "Expected network-status footer to end with a signature.");
2229 goto err;
2232 note_crypto_pk_op(VERIFY_DIR);
2233 if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
2234 "network-status") < 0)
2235 goto err;
2237 goto done;
2238 err:
2239 dump_desc(s_dup, "v2 networkstatus");
2240 if (ns)
2241 networkstatus_v2_free(ns);
2242 ns = NULL;
2243 done:
2244 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2245 smartlist_free(tokens);
2246 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2247 smartlist_free(footer_tokens);
2248 if (area) {
2249 DUMP_AREA(area, "v2 networkstatus");
2250 memarea_drop_all(area);
2252 return ns;
2255 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2256 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2257 networkstatus_t *
2258 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2259 networkstatus_type_t ns_type)
2261 smartlist_t *tokens = smartlist_create();
2262 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2263 networkstatus_voter_info_t *voter = NULL;
2264 networkstatus_t *ns = NULL;
2265 char ns_digest[DIGEST_LEN];
2266 const char *cert, *end_of_header, *end_of_footer, *s_dup = s;
2267 directory_token_t *tok;
2268 int ok;
2269 struct in_addr in;
2270 int i, inorder, n_signatures = 0;
2271 memarea_t *area = NULL, *rs_area = NULL;
2272 tor_assert(s);
2274 if (eos_out)
2275 *eos_out = NULL;
2277 if (router_get_networkstatus_v3_hash(s, ns_digest)) {
2278 log_warn(LD_DIR, "Unable to compute digest of network-status");
2279 goto err;
2282 area = memarea_new();
2283 end_of_header = find_start_of_next_routerstatus(s);
2284 if (tokenize_string(area, s, end_of_header, tokens,
2285 (ns_type == NS_TYPE_CONSENSUS) ?
2286 networkstatus_consensus_token_table :
2287 networkstatus_token_table, 0)) {
2288 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2289 goto err;
2292 ns = tor_malloc_zero(sizeof(networkstatus_t));
2293 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2295 if (ns_type != NS_TYPE_CONSENSUS) {
2296 const char *end_of_cert = NULL;
2297 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2298 goto err;
2299 ++cert;
2300 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2301 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2302 goto err;
2305 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2306 tor_assert(tok->n_args);
2307 if (!strcmp(tok->args[0], "vote")) {
2308 ns->type = NS_TYPE_VOTE;
2309 } else if (!strcmp(tok->args[0], "consensus")) {
2310 ns->type = NS_TYPE_CONSENSUS;
2311 } else if (!strcmp(tok->args[0], "opinion")) {
2312 ns->type = NS_TYPE_OPINION;
2313 } else {
2314 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2315 escaped(tok->args[0]));
2316 goto err;
2318 if (ns_type != ns->type) {
2319 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2320 goto err;
2323 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2324 tok = find_by_keyword(tokens, K_PUBLISHED);
2325 if (parse_iso_time(tok->args[0], &ns->published))
2326 goto err;
2328 ns->supported_methods = smartlist_create();
2329 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2330 if (tok) {
2331 for (i=0; i < tok->n_args; ++i)
2332 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2333 } else {
2334 smartlist_add(ns->supported_methods, tor_strdup("1"));
2336 } else {
2337 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2338 if (tok) {
2339 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2340 &ok, NULL);
2341 if (!ok)
2342 goto err;
2343 } else {
2344 ns->consensus_method = 1;
2348 tok = find_by_keyword(tokens, K_VALID_AFTER);
2349 if (parse_iso_time(tok->args[0], &ns->valid_after))
2350 goto err;
2352 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2353 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2354 goto err;
2356 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2357 if (parse_iso_time(tok->args[0], &ns->valid_until))
2358 goto err;
2360 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2361 tor_assert(tok->n_args >= 2);
2362 ns->vote_seconds =
2363 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2364 if (!ok)
2365 goto err;
2366 ns->dist_seconds =
2367 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2368 if (!ok)
2369 goto err;
2370 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2371 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2372 goto err;
2374 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2375 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2376 goto err;
2378 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2379 log_warn(LD_DIR, "Vote seconds is too short");
2380 goto err;
2382 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2383 log_warn(LD_DIR, "Dist seconds is too short");
2384 goto err;
2387 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2388 ns->client_versions = tor_strdup(tok->args[0]);
2390 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2391 ns->server_versions = tor_strdup(tok->args[0]);
2394 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2395 ns->known_flags = smartlist_create();
2396 inorder = 1;
2397 for (i = 0; i < tok->n_args; ++i) {
2398 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2399 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2400 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2401 inorder = 0;
2404 if (!inorder) {
2405 log_warn(LD_DIR, "known-flags not in order");
2406 goto err;
2409 ns->voters = smartlist_create();
2411 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
2412 tok = _tok;
2413 if (tok->tp == K_DIR_SOURCE) {
2414 tor_assert(tok->n_args >= 6);
2416 if (voter)
2417 smartlist_add(ns->voters, voter);
2418 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2419 if (ns->type != NS_TYPE_CONSENSUS)
2420 memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
2422 voter->nickname = tor_strdup(tok->args[0]);
2423 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2424 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2425 tok->args[1], HEX_DIGEST_LEN) < 0) {
2426 log_warn(LD_DIR, "Error decoding identity digest %s in "
2427 "network-status vote.", escaped(tok->args[1]));
2428 goto err;
2430 if (ns->type != NS_TYPE_CONSENSUS &&
2431 memcmp(ns->cert->cache_info.identity_digest,
2432 voter->identity_digest, DIGEST_LEN)) {
2433 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2434 goto err;
2436 voter->address = tor_strdup(tok->args[2]);
2437 if (!tor_inet_aton(tok->args[3], &in)) {
2438 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2439 escaped(tok->args[3]));
2440 goto err;
2442 voter->addr = ntohl(in.s_addr);
2443 voter->dir_port = (uint16_t)
2444 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2445 if (!ok)
2446 goto err;
2447 voter->or_port = (uint16_t)
2448 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2449 if (!ok)
2450 goto err;
2451 } else if (tok->tp == K_CONTACT) {
2452 if (!voter || voter->contact) {
2453 log_warn(LD_DIR, "contact element is out of place.");
2454 goto err;
2456 voter->contact = tor_strdup(tok->args[0]);
2457 } else if (tok->tp == K_VOTE_DIGEST) {
2458 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2459 tor_assert(tok->n_args >= 1);
2460 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2461 log_warn(LD_DIR, "vote-digest element is out of place.");
2462 goto err;
2464 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2465 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2466 tok->args[0], HEX_DIGEST_LEN) < 0) {
2467 log_warn(LD_DIR, "Error decoding vote digest %s in "
2468 "network-status consensus.", escaped(tok->args[0]));
2469 goto err;
2472 } SMARTLIST_FOREACH_END(_tok);
2473 if (voter) {
2474 smartlist_add(ns->voters, voter);
2475 voter = NULL;
2477 if (smartlist_len(ns->voters) == 0) {
2478 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2479 goto err;
2480 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
2481 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2482 goto err;
2485 if (ns->type != NS_TYPE_CONSENSUS &&
2486 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
2487 int bad = 1;
2488 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2489 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
2490 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
2491 tok->args[0], HEX_DIGEST_LEN)<0)
2492 bad = 1;
2493 else
2494 bad = 0;
2496 if (bad) {
2497 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
2498 escaped(tok->args[0]));
2502 /* Parse routerstatus lines. */
2503 rs_tokens = smartlist_create();
2504 rs_area = memarea_new();
2505 s = end_of_header;
2506 ns->routerstatus_list = smartlist_create();
2508 while (!strcmpstart(s, "r ")) {
2509 if (ns->type != NS_TYPE_CONSENSUS) {
2510 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2511 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
2512 rs, 0))
2513 smartlist_add(ns->routerstatus_list, rs);
2514 else {
2515 tor_free(rs->version);
2516 tor_free(rs);
2518 } else {
2519 routerstatus_t *rs;
2520 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
2521 NULL, NULL,
2522 ns->consensus_method)))
2523 smartlist_add(ns->routerstatus_list, rs);
2526 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2527 routerstatus_t *rs1, *rs2;
2528 if (ns->type != NS_TYPE_CONSENSUS) {
2529 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2530 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2531 rs1 = &a->status; rs2 = &b->status;
2532 } else {
2533 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2534 rs2 = smartlist_get(ns->routerstatus_list, i);
2536 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
2537 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2538 "digest");
2539 goto err;
2543 /* Parse footer; check signature. */
2544 footer_tokens = smartlist_create();
2545 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2546 ++end_of_footer;
2547 else
2548 end_of_footer = s + strlen(s);
2549 if (tokenize_string(area,s, end_of_footer, footer_tokens,
2550 networkstatus_vote_footer_token_table, 0)) {
2551 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2552 goto err;
2555 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
2557 char declared_identity[DIGEST_LEN];
2558 networkstatus_voter_info_t *v;
2559 tok = _tok;
2560 if (tok->tp != K_DIRECTORY_SIGNATURE)
2561 continue;
2562 tor_assert(tok->n_args >= 2);
2564 if (!tok->object_type ||
2565 strcmp(tok->object_type, "SIGNATURE") ||
2566 tok->object_size < 128 || tok->object_size > 512) {
2567 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2568 goto err;
2571 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2572 base16_decode(declared_identity, sizeof(declared_identity),
2573 tok->args[0], HEX_DIGEST_LEN) < 0) {
2574 log_warn(LD_DIR, "Error decoding declared identity %s in "
2575 "network-status vote.", escaped(tok->args[0]));
2576 goto err;
2578 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2579 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2580 "any declared directory source.");
2581 goto err;
2583 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2584 base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
2585 tok->args[1], HEX_DIGEST_LEN) < 0) {
2586 log_warn(LD_DIR, "Error decoding declared digest %s in "
2587 "network-status vote.", escaped(tok->args[1]));
2588 goto err;
2591 if (ns->type != NS_TYPE_CONSENSUS) {
2592 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
2593 DIGEST_LEN)) {
2594 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2595 "network-status vote.");
2596 goto err;
2600 if (ns->type != NS_TYPE_CONSENSUS) {
2601 if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
2602 "network-status vote"))
2603 goto err;
2604 v->good_signature = 1;
2605 } else {
2606 if (tok->object_size >= INT_MAX)
2607 goto err;
2608 v->signature = tor_memdup(tok->object_body, tok->object_size);
2609 v->signature_len = (int) tok->object_size;
2611 ++n_signatures;
2614 if (! n_signatures) {
2615 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2616 goto err;
2619 if (eos_out)
2620 *eos_out = end_of_footer;
2622 goto done;
2623 err:
2624 dump_desc(s_dup, "v3 networkstatus");
2625 if (ns)
2626 networkstatus_vote_free(ns);
2627 ns = NULL;
2628 done:
2629 if (tokens) {
2630 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2631 smartlist_free(tokens);
2633 if (voter) {
2634 tor_free(voter->nickname);
2635 tor_free(voter->address);
2636 tor_free(voter->contact);
2637 tor_free(voter->signature);
2638 tor_free(voter);
2640 if (rs_tokens) {
2641 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
2642 smartlist_free(rs_tokens);
2644 if (footer_tokens) {
2645 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2646 smartlist_free(footer_tokens);
2648 if (area) {
2649 DUMP_AREA(area, "v3 networkstatus");
2650 memarea_drop_all(area);
2652 if (rs_area)
2653 memarea_drop_all(rs_area);
2655 return ns;
2658 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2659 * <b>eos</b> and return the result. Return -1 on failure. */
2660 ns_detached_signatures_t *
2661 networkstatus_parse_detached_signatures(const char *s, const char *eos)
2663 /* XXXX there is too much duplicate shared between this function and
2664 * networkstatus_parse_vote_from_string(). */
2665 directory_token_t *tok;
2666 memarea_t *area = NULL;
2668 smartlist_t *tokens = smartlist_create();
2669 ns_detached_signatures_t *sigs =
2670 tor_malloc_zero(sizeof(ns_detached_signatures_t));
2672 if (!eos)
2673 eos = s + strlen(s);
2675 area = memarea_new();
2676 if (tokenize_string(area,s, eos, tokens,
2677 networkstatus_detached_signature_token_table, 0)) {
2678 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
2679 goto err;
2682 tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST);
2683 if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
2684 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
2685 "networkstatus signatures");
2686 goto err;
2688 if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
2689 tok->args[0], strlen(tok->args[0])) < 0) {
2690 log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
2691 "networkstatus signatures");
2692 goto err;
2695 tok = find_by_keyword(tokens, K_VALID_AFTER);
2696 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
2697 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
2698 goto err;
2701 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2702 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
2703 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
2704 goto err;
2707 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2708 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
2709 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
2710 goto err;
2713 sigs->signatures = smartlist_create();
2714 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2716 char id_digest[DIGEST_LEN];
2717 char sk_digest[DIGEST_LEN];
2718 networkstatus_voter_info_t *voter;
2720 tok = _tok;
2721 if (tok->tp != K_DIRECTORY_SIGNATURE)
2722 continue;
2723 tor_assert(tok->n_args >= 2);
2725 if (!tok->object_type ||
2726 strcmp(tok->object_type, "SIGNATURE") ||
2727 tok->object_size < 128 || tok->object_size > 512) {
2728 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2729 goto err;
2732 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2733 base16_decode(id_digest, sizeof(id_digest),
2734 tok->args[0], HEX_DIGEST_LEN) < 0) {
2735 log_warn(LD_DIR, "Error decoding declared identity %s in "
2736 "network-status vote.", escaped(tok->args[0]));
2737 goto err;
2739 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2740 base16_decode(sk_digest, sizeof(sk_digest),
2741 tok->args[1], HEX_DIGEST_LEN) < 0) {
2742 log_warn(LD_DIR, "Error decoding declared digest %s in "
2743 "network-status vote.", escaped(tok->args[1]));
2744 goto err;
2747 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2748 memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
2749 memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
2750 if (tok->object_size >= INT_MAX)
2751 goto err;
2752 voter->signature = tor_memdup(tok->object_body, tok->object_size);
2753 voter->signature_len = (int) tok->object_size;
2755 smartlist_add(sigs->signatures, voter);
2758 goto done;
2759 err:
2760 ns_detached_signatures_free(sigs);
2761 sigs = NULL;
2762 done:
2763 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2764 smartlist_free(tokens);
2765 if (area) {
2766 DUMP_AREA(area, "detached signatures");
2767 memarea_drop_all(area);
2769 return sigs;
2772 /** Parse the addr policy in the string <b>s</b> and return it. If
2773 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2774 * ADDR_POLICY_REJECT) for items that specify no action.
2776 addr_policy_t *
2777 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
2779 directory_token_t *tok = NULL;
2780 const char *cp, *eos;
2781 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2782 * But note that there can be an arbitrary amount of space between the
2783 * accept and the address:mask/port element. */
2784 char line[TOR_ADDR_BUF_LEN*2 + 32];
2785 addr_policy_t *r;
2786 memarea_t *area = NULL;
2788 s = eat_whitespace(s);
2789 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
2790 if (tor_snprintf(line, sizeof(line), "%s %s",
2791 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
2792 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
2793 return NULL;
2795 cp = line;
2796 tor_strlower(line);
2797 } else { /* assume an already well-formed address policy line */
2798 cp = s;
2801 eos = cp + strlen(cp);
2802 area = memarea_new();
2803 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
2804 if (tok->tp == _ERR) {
2805 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
2806 goto err;
2808 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
2809 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
2810 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
2811 goto err;
2814 r = router_parse_addr_policy(tok);
2815 goto done;
2816 err:
2817 r = NULL;
2818 done:
2819 token_free(tok);
2820 if (area) {
2821 DUMP_AREA(area, "policy item");
2822 memarea_drop_all(area);
2824 return r;
2827 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2828 * <b>router</b>. Return 0 on success, -1 on failure. */
2829 static int
2830 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
2832 addr_policy_t *newe;
2833 newe = router_parse_addr_policy(tok);
2834 if (!newe)
2835 return -1;
2836 if (! router->exit_policy)
2837 router->exit_policy = smartlist_create();
2839 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
2840 tor_addr_family(&newe->addr) == AF_INET)
2842 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
2843 tor_addr_family(&newe->addr) == AF_INET6)) {
2844 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
2845 "policy");
2846 addr_policy_free(newe);
2847 return -1;
2850 smartlist_add(router->exit_policy, newe);
2852 return 0;
2855 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2856 * a new exit_policy_t corresponding to the token. */
2857 static addr_policy_t *
2858 router_parse_addr_policy(directory_token_t *tok)
2860 addr_policy_t newe;
2861 char *arg;
2863 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
2864 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
2866 if (tok->n_args != 1)
2867 return NULL;
2868 arg = tok->args[0];
2870 if (!strcmpstart(arg,"private"))
2871 return router_parse_addr_policy_private(tok);
2873 memset(&newe, 0, sizeof(newe));
2875 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2876 newe.policy_type = ADDR_POLICY_REJECT;
2877 else
2878 newe.policy_type = ADDR_POLICY_ACCEPT;
2880 if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
2881 &newe.prt_min, &newe.prt_max) < 0) {
2882 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
2883 return NULL;
2886 return addr_policy_get_canonical_entry(&newe);
2889 /** Parse an exit policy line of the format "accept/reject private:...".
2890 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2891 * router descriptors until earlier versions are obsolete.
2893 static addr_policy_t *
2894 router_parse_addr_policy_private(directory_token_t *tok)
2896 const char *arg;
2897 uint16_t port_min, port_max;
2898 addr_policy_t result;
2900 arg = tok->args[0];
2901 if (strcmpstart(arg, "private"))
2902 return NULL;
2904 arg += strlen("private");
2905 arg = (char*) eat_whitespace(arg);
2906 if (!arg || *arg != ':')
2907 return NULL;
2909 if (parse_port_range(arg+1, &port_min, &port_max)<0)
2910 return NULL;
2912 memset(&result, 0, sizeof(result));
2913 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2914 result.policy_type = ADDR_POLICY_REJECT;
2915 else
2916 result.policy_type = ADDR_POLICY_ACCEPT;
2917 result.is_private = 1;
2918 result.prt_min = port_min;
2919 result.prt_max = port_max;
2921 return addr_policy_get_canonical_entry(&result);
2924 /** Log and exit if <b>t</b> is malformed */
2925 void
2926 assert_addr_policy_ok(smartlist_t *lst)
2928 if (!lst) return;
2929 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
2930 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
2931 t->policy_type == ADDR_POLICY_ACCEPT);
2932 tor_assert(t->prt_min <= t->prt_max);
2937 * Low-level tokenizer for router descriptors and directories.
2940 /** Free all resources allocated for <b>tok</b> */
2941 static void
2942 token_free(directory_token_t *tok)
2944 tor_assert(tok);
2945 if (tok->key)
2946 crypto_free_pk_env(tok->key);
2949 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
2950 #define ALLOC(sz) memarea_alloc(area,sz)
2951 #define STRDUP(str) memarea_strdup(area,str)
2952 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
2954 #define RET_ERR(msg) \
2955 STMT_BEGIN \
2956 if (tok) token_free(tok); \
2957 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
2958 tok->tp = _ERR; \
2959 tok->error = STRDUP(msg); \
2960 goto done_tokenizing; \
2961 STMT_END
2963 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
2964 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
2965 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
2966 * conform to the syntax we wanted.
2968 static INLINE directory_token_t *
2969 token_check_object(memarea_t *area, const char *kwd,
2970 directory_token_t *tok, obj_syntax o_syn)
2972 char ebuf[128];
2973 switch (o_syn) {
2974 case NO_OBJ:
2975 /* No object is allowed for this token. */
2976 if (tok->object_body) {
2977 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
2978 RET_ERR(ebuf);
2980 if (tok->key) {
2981 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
2982 RET_ERR(ebuf);
2984 break;
2985 case NEED_OBJ:
2986 /* There must be a (non-key) object. */
2987 if (!tok->object_body) {
2988 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
2989 RET_ERR(ebuf);
2991 break;
2992 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
2993 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
2994 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
2995 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
2996 kwd, (int)crypto_pk_keysize(tok->key));
2997 RET_ERR(ebuf);
2999 /* fall through */
3000 case NEED_KEY: /* There must be some kind of key. */
3001 if (!tok->key) {
3002 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
3003 RET_ERR(ebuf);
3005 if (o_syn != NEED_SKEY_1024) {
3006 if (crypto_pk_key_is_private(tok->key)) {
3007 tor_snprintf(ebuf, sizeof(ebuf),
3008 "Private key given for %s, which wants a public key", kwd);
3009 RET_ERR(ebuf);
3011 } else { /* o_syn == NEED_SKEY_1024 */
3012 if (!crypto_pk_key_is_private(tok->key)) {
3013 tor_snprintf(ebuf, sizeof(ebuf),
3014 "Public key given for %s, which wants a private key", kwd);
3015 RET_ERR(ebuf);
3018 break;
3019 case OBJ_OK:
3020 /* Anything goes with this token. */
3021 break;
3024 done_tokenizing:
3025 return tok;
3028 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3029 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3030 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3031 * all storage in <b>area</b>. Return the number of arguments parsed, or
3032 * return -1 if there was an insanely high number of arguments. */
3033 static INLINE int
3034 get_token_arguments(memarea_t *area, directory_token_t *tok,
3035 const char *s, const char *eol)
3037 /** Largest number of arguments we'll accept to any token, ever. */
3038 #define MAX_ARGS 512
3039 char *mem = memarea_strndup(area, s, eol-s);
3040 char *cp = mem;
3041 int j = 0;
3042 char *args[MAX_ARGS];
3043 while (*cp) {
3044 if (j == MAX_ARGS)
3045 return -1;
3046 args[j++] = cp;
3047 cp = (char*)find_whitespace(cp);
3048 if (!cp || !*cp)
3049 break; /* End of the line. */
3050 *cp++ = '\0';
3051 cp = (char*)eat_whitespace(cp);
3053 tok->n_args = j;
3054 tok->args = memarea_memdup(area, args, j*sizeof(char*));
3055 return j;
3056 #undef MAX_ARGS
3059 /** Helper function: read the next token from *s, advance *s to the end of the
3060 * token, and return the parsed token. Parse *<b>s</b> according to the list
3061 * of tokens in <b>table</b>.
3063 static directory_token_t *
3064 get_next_token(memarea_t *area,
3065 const char **s, const char *eos, token_rule_t *table)
3067 const char *next, *eol, *obstart;
3068 size_t obname_len;
3069 int i;
3070 directory_token_t *tok;
3071 obj_syntax o_syn = NO_OBJ;
3072 char ebuf[128];
3073 const char *kwd = "";
3075 tor_assert(area);
3076 tok = ALLOC_ZERO(sizeof(directory_token_t));
3077 tok->tp = _ERR;
3079 /* Set *s to first token, eol to end-of-line, next to after first token */
3080 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
3081 tor_assert(eos >= *s);
3082 eol = memchr(*s, '\n', eos-*s);
3083 if (!eol)
3084 eol = eos;
3085 next = find_whitespace_eos(*s, eol);
3087 if (!strcmp_len(*s, "opt", next-*s)) {
3088 /* Skip past an "opt" at the start of the line. */
3089 *s = eat_whitespace_eos_no_nl(next, eol);
3090 next = find_whitespace_eos(*s, eol);
3091 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
3092 RET_ERR("Unexpected EOF");
3095 /* Search the table for the appropriate entry. (I tried a binary search
3096 * instead, but it wasn't any faster.) */
3097 for (i = 0; table[i].t ; ++i) {
3098 if (!strcmp_len(*s, table[i].t, next-*s)) {
3099 /* We've found the keyword. */
3100 kwd = table[i].t;
3101 tok->tp = table[i].v;
3102 o_syn = table[i].os;
3103 *s = eat_whitespace_eos_no_nl(next, eol);
3104 /* We go ahead whether there are arguments or not, so that tok->args is
3105 * always set if we want arguments. */
3106 if (table[i].concat_args) {
3107 /* The keyword takes the line as a single argument */
3108 tok->args = ALLOC(sizeof(char*));
3109 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3110 tok->n_args = 1;
3111 } else {
3112 /* This keyword takes multiple arguments. */
3113 if (get_token_arguments(area, tok, *s, eol)<0) {
3114 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3115 RET_ERR(ebuf);
3117 *s = eol;
3119 if (tok->n_args < table[i].min_args) {
3120 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3121 RET_ERR(ebuf);
3122 } else if (tok->n_args > table[i].max_args) {
3123 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3124 RET_ERR(ebuf);
3126 break;
3130 if (tok->tp == _ERR) {
3131 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3132 if (**s == '@')
3133 tok->tp = _A_UNKNOWN;
3134 else
3135 tok->tp = K_OPT;
3136 tok->args = ALLOC(sizeof(char*));
3137 tok->args[0] = STRNDUP(*s, eol-*s);
3138 tok->n_args = 1;
3139 o_syn = OBJ_OK;
3142 /* Check whether there's an object present */
3143 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3144 tor_assert(eos >= *s);
3145 eol = memchr(*s, '\n', eos-*s);
3146 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3147 goto check_object;
3149 obstart = *s; /* Set obstart to start of object spec */
3150 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3151 strcmp_len(eol-5, "-----", 5)) { /* nuls or invalid endings */
3152 RET_ERR("Malformed object: bad begin line");
3154 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3155 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3156 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3158 /* Go to the end of the object */
3159 next = tor_memstr(*s, eos-*s, "-----END ");
3160 if (!next) {
3161 RET_ERR("Malformed object: missing object end line");
3163 tor_assert(eos >= next);
3164 eol = memchr(next, '\n', eos-next);
3165 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3166 eol = eos;
3167 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3168 if ((size_t)(eol-next) != 9+obname_len+5 ||
3169 strcmp_len(next+9, tok->object_type, obname_len) ||
3170 strcmp_len(eol-5, "-----", 5)) {
3171 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3172 tok->object_type);
3173 ebuf[sizeof(ebuf)-1] = '\0';
3174 RET_ERR(ebuf);
3176 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3177 tok->key = crypto_new_pk_env();
3178 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3179 RET_ERR("Couldn't parse public key.");
3180 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3181 tok->key = crypto_new_pk_env();
3182 if (crypto_pk_read_private_key_from_string(tok->key, obstart))
3183 RET_ERR("Couldn't parse private key.");
3184 } else { /* If it's something else, try to base64-decode it */
3185 int r;
3186 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3187 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3188 if (r<0)
3189 RET_ERR("Malformed object: bad base64-encoded data");
3190 tok->object_size = r;
3192 *s = eol;
3194 check_object:
3195 tok = token_check_object(area, kwd, tok, o_syn);
3197 done_tokenizing:
3198 return tok;
3200 #undef RET_ERR
3201 #undef ALLOC
3202 #undef ALLOC_ZERO
3203 #undef STRDUP
3204 #undef STRNDUP
3207 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3208 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3209 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3210 * entire string.
3212 static int
3213 tokenize_string(memarea_t *area,
3214 const char *start, const char *end, smartlist_t *out,
3215 token_rule_t *table, int flags)
3217 const char **s;
3218 directory_token_t *tok = NULL;
3219 int counts[_NIL];
3220 int i;
3221 int first_nonannotation;
3222 int prev_len = smartlist_len(out);
3223 tor_assert(area);
3225 s = &start;
3226 if (!end)
3227 end = start+strlen(start);
3228 for (i = 0; i < _NIL; ++i)
3229 counts[i] = 0;
3230 while (*s < end && (!tok || tok->tp != _EOF)) {
3231 tok = get_next_token(area, s, end, table);
3232 if (tok->tp == _ERR) {
3233 log_warn(LD_DIR, "parse error: %s", tok->error);
3234 token_free(tok);
3235 return -1;
3237 ++counts[tok->tp];
3238 smartlist_add(out, tok);
3239 *s = eat_whitespace_eos(*s, end);
3242 if (flags & TS_NOCHECK)
3243 return 0;
3245 if ((flags & TS_ANNOTATIONS_OK)) {
3246 first_nonannotation = -1;
3247 for (i = 0; i < smartlist_len(out); ++i) {
3248 tok = smartlist_get(out, i);
3249 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
3250 first_nonannotation = i;
3251 break;
3254 if (first_nonannotation < 0) {
3255 log_warn(LD_DIR, "parse error: item contains only annotations");
3256 return -1;
3258 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
3259 tok = smartlist_get(out, i);
3260 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3261 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
3262 return -1;
3265 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
3266 if (first_nonannotation != prev_len) {
3267 log_warn(LD_DIR, "parse error: Unexpected annotations.");
3268 return -1;
3271 } else {
3272 for (i=0; i < smartlist_len(out); ++i) {
3273 tok = smartlist_get(out, i);
3274 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3275 log_warn(LD_DIR, "parse error: no annotations allowed.");
3276 return -1;
3279 first_nonannotation = 0;
3281 for (i = 0; table[i].t; ++i) {
3282 if (counts[table[i].v] < table[i].min_cnt) {
3283 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
3284 return -1;
3286 if (counts[table[i].v] > table[i].max_cnt) {
3287 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
3288 return -1;
3290 if (table[i].pos & AT_START) {
3291 if (smartlist_len(out) < 1 ||
3292 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
3293 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
3294 return -1;
3297 if (table[i].pos & AT_END) {
3298 if (smartlist_len(out) < 1 ||
3299 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
3300 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
3301 return -1;
3305 return 0;
3308 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3309 * NULL if no such keyword is found.
3311 static directory_token_t *
3312 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
3314 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
3315 return NULL;
3318 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3319 * with an assert if no such keyword is found.
3321 static directory_token_t *
3322 _find_by_keyword(smartlist_t *s, directory_keyword keyword,
3323 const char *keyword_as_string)
3325 directory_token_t *tok = find_opt_by_keyword(s, keyword);
3326 if (PREDICT_UNLIKELY(!tok)) {
3327 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
3328 "been validated. Internal error.", keyword_as_string, (int)keyword);
3329 tor_assert(tok);
3331 return tok;
3334 /** Return a newly allocated smartlist of all accept or reject tokens in
3335 * <b>s</b>.
3337 static smartlist_t *
3338 find_all_exitpolicy(smartlist_t *s)
3340 smartlist_t *out = smartlist_create();
3341 SMARTLIST_FOREACH(s, directory_token_t *, t,
3342 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
3343 t->tp == K_REJECT || t->tp == K_REJECT6)
3344 smartlist_add(out,t));
3345 return out;
3348 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
3349 * occurrence of <b>start_str</b> through the first instance of c after the
3350 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
3351 * <b>digest</b>; return 0 on success.
3353 * If no such substring exists, return -1.
3355 static int
3356 router_get_hash_impl(const char *s, char *digest,
3357 const char *start_str,
3358 const char *end_str, char end_c)
3360 char *start, *end;
3361 start = strstr(s, start_str);
3362 if (!start) {
3363 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
3364 return -1;
3366 if (start != s && *(start-1) != '\n') {
3367 log_warn(LD_DIR,
3368 "first occurrence of \"%s\" is not at the start of a line",
3369 start_str);
3370 return -1;
3372 end = strstr(start+strlen(start_str), end_str);
3373 if (!end) {
3374 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
3375 return -1;
3377 end = strchr(end+strlen(end_str), end_c);
3378 if (!end) {
3379 log_warn(LD_DIR,"couldn't find EOL");
3380 return -1;
3382 ++end;
3384 if (crypto_digest(digest, start, end-start)) {
3385 log_warn(LD_BUG,"couldn't compute digest");
3386 return -1;
3389 return 0;
3392 /** Parse the Tor version of the platform string <b>platform</b>,
3393 * and compare it to the version in <b>cutoff</b>. Return 1 if
3394 * the router is at least as new as the cutoff, else return 0.
3397 tor_version_as_new_as(const char *platform, const char *cutoff)
3399 tor_version_t cutoff_version, router_version;
3400 char *s, *s2, *start;
3401 char tmp[128];
3403 tor_assert(platform);
3405 if (tor_version_parse(cutoff, &cutoff_version)<0) {
3406 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
3407 return 0;
3409 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
3410 return 1;
3412 start = (char *)eat_whitespace(platform+3);
3413 if (!*start) return 0;
3414 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
3415 s2 = (char*)eat_whitespace(s);
3416 if (!strcmpstart(s2, "(r") || !strcmpstart(s2, "(git-"))
3417 s = (char*)find_whitespace(s2);
3419 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
3420 return 0;
3421 strlcpy(tmp, start, s-start+1);
3423 if (tor_version_parse(tmp, &router_version)<0) {
3424 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
3425 return 1; /* be safe and say yes */
3428 /* Here's why we don't need to do any special handling for svn revisions:
3429 * - If neither has an svn revision, we're fine.
3430 * - If the router doesn't have an svn revision, we can't assume that it
3431 * is "at least" any svn revision, so we need to return 0.
3432 * - If the target version doesn't have an svn revision, any svn revision
3433 * (or none at all) is good enough, so return 1.
3434 * - If both target and router have an svn revision, we compare them.
3437 return tor_version_compare(&router_version, &cutoff_version) >= 0;
3440 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3441 * Return 0 on success, -1 on failure. */
3443 tor_version_parse(const char *s, tor_version_t *out)
3445 char *eos=NULL;
3446 const char *cp=NULL;
3447 /* Format is:
3448 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3450 tor_assert(s);
3451 tor_assert(out);
3453 memset(out, 0, sizeof(tor_version_t));
3455 if (!strcasecmpstart(s, "Tor "))
3456 s += 4;
3458 /* Get major. */
3459 out->major = (int)strtol(s,&eos,10);
3460 if (!eos || eos==s || *eos != '.') return -1;
3461 cp = eos+1;
3463 /* Get minor */
3464 out->minor = (int) strtol(cp,&eos,10);
3465 if (!eos || eos==cp || *eos != '.') return -1;
3466 cp = eos+1;
3468 /* Get micro */
3469 out->micro = (int) strtol(cp,&eos,10);
3470 if (!eos || eos==cp) return -1;
3471 if (!*eos) {
3472 out->status = VER_RELEASE;
3473 out->patchlevel = 0;
3474 return 0;
3476 cp = eos;
3478 /* Get status */
3479 if (*cp == '.') {
3480 out->status = VER_RELEASE;
3481 ++cp;
3482 } else if (0==strncmp(cp, "pre", 3)) {
3483 out->status = VER_PRE;
3484 cp += 3;
3485 } else if (0==strncmp(cp, "rc", 2)) {
3486 out->status = VER_RC;
3487 cp += 2;
3488 } else {
3489 return -1;
3492 /* Get patchlevel */
3493 out->patchlevel = (int) strtol(cp,&eos,10);
3494 if (!eos || eos==cp) return -1;
3495 cp = eos;
3497 /* Get status tag. */
3498 if (*cp == '-' || *cp == '.')
3499 ++cp;
3500 eos = (char*) find_whitespace(cp);
3501 if (eos-cp >= (int)sizeof(out->status_tag))
3502 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
3503 else {
3504 memcpy(out->status_tag, cp, eos-cp);
3505 out->status_tag[eos-cp] = 0;
3507 cp = eat_whitespace(eos);
3509 if (!strcmpstart(cp, "(r")) {
3510 cp += 2;
3511 out->svn_revision = (int) strtol(cp,&eos,10);
3512 } else if (!strcmpstart(cp, "(git-")) {
3513 char *close_paren = strchr(cp, ')');
3514 int hexlen;
3515 char digest[DIGEST_LEN];
3516 if (! close_paren)
3517 return -1;
3518 cp += 5;
3519 hexlen = (close_paren-cp);
3520 memset(digest, 0, sizeof(digest));
3521 if (hexlen > HEX_DIGEST_LEN || hexlen == 0 || (hexlen % 2) == 1)
3522 return -1;
3523 if (base16_decode(digest, hexlen/2, cp, hexlen))
3524 return -1;
3525 memcpy(out->git_tag, digest, hexlen/2);
3526 out->git_tag_len = hexlen/2;
3529 return 0;
3532 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3533 * b. */
3535 tor_version_compare(tor_version_t *a, tor_version_t *b)
3537 int i;
3538 tor_assert(a);
3539 tor_assert(b);
3540 if ((i = a->major - b->major))
3541 return i;
3542 else if ((i = a->minor - b->minor))
3543 return i;
3544 else if ((i = a->micro - b->micro))
3545 return i;
3546 else if ((i = a->status - b->status))
3547 return i;
3548 else if ((i = a->patchlevel - b->patchlevel))
3549 return i;
3550 else if ((i = strcmp(a->status_tag, b->status_tag)))
3551 return i;
3552 else if ((i = a->svn_revision - b->svn_revision))
3553 return i;
3554 else if ((i = a->git_tag_len - b->git_tag_len))
3555 return i;
3556 else if (a->git_tag_len)
3557 return memcmp(a->git_tag, b->git_tag, a->git_tag_len);
3558 else
3559 return 0;
3562 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3564 static int
3565 tor_version_same_series(tor_version_t *a, tor_version_t *b)
3567 tor_assert(a);
3568 tor_assert(b);
3569 return ((a->major == b->major) &&
3570 (a->minor == b->minor) &&
3571 (a->micro == b->micro));
3574 /** Helper: Given pointers to two strings describing tor versions, return -1
3575 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
3576 * Used to sort a list of versions. */
3577 static int
3578 _compare_tor_version_str_ptr(const void **_a, const void **_b)
3580 const char *a = *_a, *b = *_b;
3581 int ca, cb;
3582 tor_version_t va, vb;
3583 ca = tor_version_parse(a, &va);
3584 cb = tor_version_parse(b, &vb);
3585 /* If they both parse, compare them. */
3586 if (!ca && !cb)
3587 return tor_version_compare(&va,&vb);
3588 /* If one parses, it comes first. */
3589 if (!ca && cb)
3590 return -1;
3591 if (ca && !cb)
3592 return 1;
3593 /* If neither parses, compare strings. Also, the directory server admin
3594 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3595 return strcmp(a,b);
3598 /** Sort a list of string-representations of versions in ascending order. */
3599 void
3600 sort_version_list(smartlist_t *versions, int remove_duplicates)
3602 smartlist_sort(versions, _compare_tor_version_str_ptr);
3604 if (remove_duplicates)
3605 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
3608 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3609 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3610 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3611 * encrypted introduction points to the newly allocated
3612 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3613 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3614 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3615 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3616 * and -1 for failure.
3619 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
3620 char *desc_id_out,
3621 char **intro_points_encrypted_out,
3622 size_t *intro_points_encrypted_size_out,
3623 size_t *encoded_size_out,
3624 const char **next_out, const char *desc)
3626 rend_service_descriptor_t *result =
3627 tor_malloc_zero(sizeof(rend_service_descriptor_t));
3628 char desc_hash[DIGEST_LEN];
3629 const char *eos;
3630 smartlist_t *tokens = smartlist_create();
3631 directory_token_t *tok;
3632 char secret_id_part[DIGEST_LEN];
3633 int i, version, num_ok=1;
3634 smartlist_t *versions;
3635 char public_key_hash[DIGEST_LEN];
3636 char test_desc_id[DIGEST_LEN];
3637 memarea_t *area = NULL;
3638 tor_assert(desc);
3639 /* Check if desc starts correctly. */
3640 if (strncmp(desc, "rendezvous-service-descriptor ",
3641 strlen("rendezvous-service-descriptor "))) {
3642 log_info(LD_REND, "Descriptor does not start correctly.");
3643 goto err;
3645 /* Compute descriptor hash for later validation. */
3646 if (router_get_hash_impl(desc, desc_hash,
3647 "rendezvous-service-descriptor ",
3648 "\nsignature", '\n') < 0) {
3649 log_warn(LD_REND, "Couldn't compute descriptor hash.");
3650 goto err;
3652 /* Determine end of string. */
3653 eos = strstr(desc, "\nrendezvous-service-descriptor ");
3654 if (!eos)
3655 eos = desc + strlen(desc);
3656 else
3657 eos = eos + 1;
3658 /* Check length. */
3659 if (strlen(desc) > REND_DESC_MAX_SIZE) {
3660 log_warn(LD_REND, "Descriptor length is %i which exceeds "
3661 "maximum rendezvous descriptor size of %i kilobytes.",
3662 (int)strlen(desc), REND_DESC_MAX_SIZE);
3663 goto err;
3665 /* Tokenize descriptor. */
3666 area = memarea_new();
3667 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
3668 log_warn(LD_REND, "Error tokenizing descriptor.");
3669 goto err;
3671 /* Set next to next descriptor, if available. */
3672 *next_out = eos;
3673 /* Set length of encoded descriptor. */
3674 *encoded_size_out = eos - desc;
3675 /* Check min allowed length of token list. */
3676 if (smartlist_len(tokens) < 7) {
3677 log_warn(LD_REND, "Impossibly short descriptor.");
3678 goto err;
3680 /* Parse base32-encoded descriptor ID. */
3681 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
3682 tor_assert(tok == smartlist_get(tokens, 0));
3683 tor_assert(tok->n_args == 1);
3684 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
3685 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
3686 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
3687 goto err;
3689 if (base32_decode(desc_id_out, DIGEST_LEN,
3690 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
3691 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
3692 tok->args[0]);
3693 goto err;
3695 /* Parse descriptor version. */
3696 tok = find_by_keyword(tokens, R_VERSION);
3697 tor_assert(tok->n_args == 1);
3698 result->version =
3699 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
3700 if (result->version != 2 || !num_ok) {
3701 /* If it's <2, it shouldn't be under this format. If the number
3702 * is greater than 2, we bumped it because we broke backward
3703 * compatibility. See how version numbers in our other formats
3704 * work. */
3705 log_warn(LD_REND, "Unrecognized descriptor version: %s",
3706 escaped(tok->args[0]));
3707 goto err;
3709 /* Parse public key. */
3710 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
3711 result->pk = tok->key;
3712 tok->key = NULL; /* Prevent free */
3713 /* Parse secret ID part. */
3714 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
3715 tor_assert(tok->n_args == 1);
3716 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
3717 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
3718 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
3719 goto err;
3721 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
3722 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
3723 tok->args[0]);
3724 goto err;
3726 /* Parse publication time -- up-to-date check is done when storing the
3727 * descriptor. */
3728 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
3729 tor_assert(tok->n_args == 1);
3730 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
3731 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
3732 goto err;
3734 /* Parse protocol versions. */
3735 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
3736 tor_assert(tok->n_args == 1);
3737 versions = smartlist_create();
3738 smartlist_split_string(versions, tok->args[0], ",",
3739 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3740 for (i = 0; i < smartlist_len(versions); i++) {
3741 version = (int) tor_parse_long(smartlist_get(versions, i),
3742 10, 0, INT_MAX, &num_ok, NULL);
3743 if (!num_ok) /* It's a string; let's ignore it. */
3744 continue;
3745 result->protocols |= 1 << version;
3747 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
3748 smartlist_free(versions);
3749 /* Parse encrypted introduction points. Don't verify. */
3750 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
3751 if (tok) {
3752 if (strcmp(tok->object_type, "MESSAGE")) {
3753 log_warn(LD_DIR, "Bad object type: introduction points should be of "
3754 "type MESSAGE");
3755 goto err;
3757 *intro_points_encrypted_out = tor_memdup(tok->object_body,
3758 tok->object_size);
3759 *intro_points_encrypted_size_out = tok->object_size;
3760 } else {
3761 *intro_points_encrypted_out = NULL;
3762 *intro_points_encrypted_size_out = 0;
3764 /* Parse and verify signature. */
3765 tok = find_by_keyword(tokens, R_SIGNATURE);
3766 note_crypto_pk_op(VERIFY_RTR);
3767 if (check_signature_token(desc_hash, tok, result->pk, 0,
3768 "v2 rendezvous service descriptor") < 0)
3769 goto err;
3770 /* Verify that descriptor ID belongs to public key and secret ID part. */
3771 crypto_pk_get_digest(result->pk, public_key_hash);
3772 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
3773 secret_id_part);
3774 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
3775 log_warn(LD_REND, "Parsed descriptor ID does not match "
3776 "computed descriptor ID.");
3777 goto err;
3779 goto done;
3780 err:
3781 if (result)
3782 rend_service_descriptor_free(result);
3783 result = NULL;
3784 done:
3785 if (tokens) {
3786 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3787 smartlist_free(tokens);
3789 if (area)
3790 memarea_drop_all(area);
3791 *parsed_out = result;
3792 if (result)
3793 return 0;
3794 return -1;
3797 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
3798 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
3799 * write the result to a newly allocated string that is pointed to by
3800 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
3801 * Return 0 if decryption was successful and -1 otherwise. */
3803 rend_decrypt_introduction_points(char **ipos_decrypted,
3804 size_t *ipos_decrypted_size,
3805 const char *descriptor_cookie,
3806 const char *ipos_encrypted,
3807 size_t ipos_encrypted_size)
3809 tor_assert(ipos_encrypted);
3810 tor_assert(descriptor_cookie);
3811 if (ipos_encrypted_size < 2) {
3812 log_warn(LD_REND, "Size of encrypted introduction points is too "
3813 "small.");
3814 return -1;
3816 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
3817 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
3818 session_key[CIPHER_KEY_LEN], *dec;
3819 int declen, client_blocks;
3820 size_t pos = 0, len, client_entries_len;
3821 crypto_digest_env_t *digest;
3822 crypto_cipher_env_t *cipher;
3823 client_blocks = (int) ipos_encrypted[1];
3824 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
3825 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
3826 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
3827 log_warn(LD_REND, "Size of encrypted introduction points is too "
3828 "small.");
3829 return -1;
3831 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
3832 digest = crypto_new_digest_env();
3833 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
3834 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
3835 crypto_digest_get_digest(digest, client_id,
3836 REND_BASIC_AUTH_CLIENT_ID_LEN);
3837 crypto_free_digest_env(digest);
3838 for (pos = 2; pos < 2 + client_entries_len;
3839 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
3840 if (!memcmp(ipos_encrypted + pos, client_id,
3841 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
3842 /* Attempt to decrypt introduction points. */
3843 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3844 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
3845 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
3846 CIPHER_KEY_LEN) < 0) {
3847 log_warn(LD_REND, "Could not decrypt session key for client.");
3848 crypto_free_cipher_env(cipher);
3849 return -1;
3851 crypto_free_cipher_env(cipher);
3852 cipher = crypto_create_init_cipher(session_key, 0);
3853 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
3854 dec = tor_malloc(len);
3855 declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
3856 ipos_encrypted + 2 + client_entries_len,
3857 ipos_encrypted_size - 2 - client_entries_len);
3858 crypto_free_cipher_env(cipher);
3859 if (declen < 0) {
3860 log_warn(LD_REND, "Could not decrypt introduction point string.");
3861 tor_free(dec);
3862 return -1;
3864 if (memcmpstart(dec, declen, "introduction-point ")) {
3865 log_warn(LD_REND, "Decrypted introduction points don't "
3866 "look like we could parse them.");
3867 tor_free(dec);
3868 continue;
3870 *ipos_decrypted = dec;
3871 *ipos_decrypted_size = declen;
3872 return 0;
3875 log_warn(LD_REND, "Could not decrypt introduction points. Please "
3876 "check your authorization for this service!");
3877 return -1;
3878 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
3879 crypto_cipher_env_t *cipher;
3880 char *dec;
3881 int declen;
3882 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
3883 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3884 declen = crypto_cipher_decrypt_with_iv(cipher, dec,
3885 ipos_encrypted_size -
3886 CIPHER_IV_LEN - 1,
3887 ipos_encrypted + 1,
3888 ipos_encrypted_size - 1);
3889 crypto_free_cipher_env(cipher);
3890 if (declen < 0) {
3891 log_warn(LD_REND, "Decrypting introduction points failed!");
3892 tor_free(dec);
3893 return -1;
3895 *ipos_decrypted = dec;
3896 *ipos_decrypted_size = declen;
3897 return 0;
3898 } else {
3899 log_warn(LD_REND, "Unknown authorization type number: %d",
3900 ipos_encrypted[0]);
3901 return -1;
3905 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
3906 * length <b>intro_points_encoded_size</b> and write the result to the
3907 * descriptor in <b>parsed</b>; return the number of successfully parsed
3908 * introduction points or -1 in case of a failure. */
3910 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
3911 const char *intro_points_encoded,
3912 size_t intro_points_encoded_size)
3914 const char *current_ipo, *end_of_intro_points;
3915 smartlist_t *tokens;
3916 directory_token_t *tok;
3917 rend_intro_point_t *intro;
3918 extend_info_t *info;
3919 int result, num_ok=1;
3920 memarea_t *area = NULL;
3921 tor_assert(parsed);
3922 /** Function may only be invoked once. */
3923 tor_assert(!parsed->intro_nodes);
3924 tor_assert(intro_points_encoded);
3925 tor_assert(intro_points_encoded_size > 0);
3926 /* Consider one intro point after the other. */
3927 current_ipo = intro_points_encoded;
3928 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
3929 tokens = smartlist_create();
3930 parsed->intro_nodes = smartlist_create();
3931 area = memarea_new();
3933 while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
3934 "introduction-point ")) {
3935 /* Determine end of string. */
3936 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
3937 "\nintroduction-point ");
3938 if (!eos)
3939 eos = end_of_intro_points;
3940 else
3941 eos = eos+1;
3942 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
3943 /* Free tokens and clear token list. */
3944 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3945 smartlist_clear(tokens);
3946 memarea_clear(area);
3947 /* Tokenize string. */
3948 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
3949 log_warn(LD_REND, "Error tokenizing introduction point");
3950 goto err;
3952 /* Advance to next introduction point, if available. */
3953 current_ipo = eos;
3954 /* Check minimum allowed length of introduction point. */
3955 if (smartlist_len(tokens) < 5) {
3956 log_warn(LD_REND, "Impossibly short introduction point.");
3957 goto err;
3959 /* Allocate new intro point and extend info. */
3960 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3961 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
3962 /* Parse identifier. */
3963 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
3964 if (base32_decode(info->identity_digest, DIGEST_LEN,
3965 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
3966 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
3967 tok->args[0]);
3968 rend_intro_point_free(intro);
3969 goto err;
3971 /* Write identifier to nickname. */
3972 info->nickname[0] = '$';
3973 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
3974 info->identity_digest, DIGEST_LEN);
3975 /* Parse IP address. */
3976 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
3977 if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
3978 log_warn(LD_REND, "Could not parse introduction point address.");
3979 rend_intro_point_free(intro);
3980 goto err;
3982 if (tor_addr_family(&info->addr) != AF_INET) {
3983 log_warn(LD_REND, "Introduction point address was not ipv4.");
3984 rend_intro_point_free(intro);
3985 goto err;
3988 /* Parse onion port. */
3989 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
3990 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
3991 &num_ok,NULL);
3992 if (!info->port || !num_ok) {
3993 log_warn(LD_REND, "Introduction point onion port %s is invalid",
3994 escaped(tok->args[0]));
3995 rend_intro_point_free(intro);
3996 goto err;
3998 /* Parse onion key. */
3999 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
4000 info->onion_key = tok->key;
4001 tok->key = NULL; /* Prevent free */
4002 /* Parse service key. */
4003 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
4004 intro->intro_key = tok->key;
4005 tok->key = NULL; /* Prevent free */
4006 /* Add extend info to list of introduction points. */
4007 smartlist_add(parsed->intro_nodes, intro);
4009 result = smartlist_len(parsed->intro_nodes);
4010 goto done;
4012 err:
4013 result = -1;
4015 done:
4016 /* Free tokens and clear token list. */
4017 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4018 smartlist_free(tokens);
4019 if (area)
4020 memarea_drop_all(area);
4022 return result;
4025 /** Parse the content of a client_key file in <b>ckstr</b> and add
4026 * rend_authorized_client_t's for each parsed client to
4027 * <b>parsed_clients</b>. Return the number of parsed clients as result
4028 * or -1 for failure. */
4030 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
4032 int result = -1;
4033 smartlist_t *tokens;
4034 directory_token_t *tok;
4035 const char *current_entry = NULL;
4036 memarea_t *area = NULL;
4037 if (!ckstr || strlen(ckstr) == 0)
4038 return -1;
4039 tokens = smartlist_create();
4040 /* Begin parsing with first entry, skipping comments or whitespace at the
4041 * beginning. */
4042 area = memarea_new();
4043 current_entry = eat_whitespace(ckstr);
4044 while (!strcmpstart(current_entry, "client-name ")) {
4045 rend_authorized_client_t *parsed_entry;
4046 size_t len;
4047 char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
4048 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
4049 /* Determine end of string. */
4050 const char *eos = strstr(current_entry, "\nclient-name ");
4051 if (!eos)
4052 eos = current_entry + strlen(current_entry);
4053 else
4054 eos = eos + 1;
4055 /* Free tokens and clear token list. */
4056 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4057 smartlist_clear(tokens);
4058 memarea_clear(area);
4059 /* Tokenize string. */
4060 if (tokenize_string(area, current_entry, eos, tokens,
4061 client_keys_token_table, 0)) {
4062 log_warn(LD_REND, "Error tokenizing client keys file.");
4063 goto err;
4065 /* Advance to next entry, if available. */
4066 current_entry = eos;
4067 /* Check minimum allowed length of token list. */
4068 if (smartlist_len(tokens) < 2) {
4069 log_warn(LD_REND, "Impossibly short client key entry.");
4070 goto err;
4072 /* Parse client name. */
4073 tok = find_by_keyword(tokens, C_CLIENT_NAME);
4074 tor_assert(tok == smartlist_get(tokens, 0));
4075 tor_assert(tok->n_args == 1);
4077 len = strlen(tok->args[0]);
4078 if (len < 1 || len > 19 ||
4079 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
4080 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
4081 "between 1 and 19, and valid characters are "
4082 "[A-Za-z0-9+-_].)", tok->args[0]);
4083 goto err;
4085 /* Check if client name is duplicate. */
4086 if (strmap_get(parsed_clients, tok->args[0])) {
4087 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
4088 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
4089 goto err;
4091 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
4092 parsed_entry->client_name = tor_strdup(tok->args[0]);
4093 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
4094 /* Parse client key. */
4095 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
4096 if (tok) {
4097 parsed_entry->client_key = tok->key;
4098 tok->key = NULL; /* Prevent free */
4101 /* Parse descriptor cookie. */
4102 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
4103 tor_assert(tok->n_args == 1);
4104 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
4105 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
4106 escaped(tok->args[0]));
4107 goto err;
4109 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
4110 * because a base64 encoding of length 24 does not fit into 16 bytes in all
4111 * cases. */
4112 if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
4113 tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
4114 != REND_DESC_COOKIE_LEN)) {
4115 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
4116 "%s", descriptor_cookie_base64);
4117 goto err;
4119 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
4120 REND_DESC_COOKIE_LEN);
4122 result = strmap_size(parsed_clients);
4123 goto done;
4124 err:
4125 result = -1;
4126 done:
4127 /* Free tokens and clear token list. */
4128 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4129 smartlist_free(tokens);
4130 if (area)
4131 memarea_drop_all(area);
4132 return result;