Oops, here's the *REAL* fix for the ipv6 issue
[tor/rransom.git] / src / or / routerparse.c
blob1faa177edf192599d1778f6f01e3405956133f91
1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2011, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
7 /**
8 * \file routerparse.c
9 * \brief Code to parse and validate router descriptors and directories.
10 **/
12 #include "or.h"
13 #include "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_DIR_KEY_CERTIFICATE_VERSION,
66 K_DIR_IDENTITY_KEY,
67 K_DIR_KEY_PUBLISHED,
68 K_DIR_KEY_EXPIRES,
69 K_DIR_KEY_CERTIFICATION,
70 K_DIR_KEY_CROSSCERT,
71 K_DIR_ADDRESS,
73 K_VOTE_STATUS,
74 K_VALID_AFTER,
75 K_FRESH_UNTIL,
76 K_VALID_UNTIL,
77 K_VOTING_DELAY,
79 K_KNOWN_FLAGS,
80 K_PARAMS,
81 K_VOTE_DIGEST,
82 K_CONSENSUS_DIGEST,
83 K_CONSENSUS_METHODS,
84 K_CONSENSUS_METHOD,
85 K_LEGACY_DIR_KEY,
87 A_PURPOSE,
88 _A_UNKNOWN,
90 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
91 R_VERSION,
92 R_PERMANENT_KEY,
93 R_SECRET_ID_PART,
94 R_PUBLICATION_TIME,
95 R_PROTOCOL_VERSIONS,
96 R_INTRODUCTION_POINTS,
97 R_SIGNATURE,
99 R_IPO_IDENTIFIER,
100 R_IPO_IP_ADDRESS,
101 R_IPO_ONION_PORT,
102 R_IPO_ONION_KEY,
103 R_IPO_SERVICE_KEY,
105 C_CLIENT_NAME,
106 C_DESCRIPTOR_COOKIE,
107 C_CLIENT_KEY,
109 _ERR,
110 _EOF,
111 _NIL
112 } directory_keyword;
114 #define MIN_ANNOTATION A_PURPOSE
115 #define MAX_ANNOTATION _A_UNKNOWN
117 /** Structure to hold a single directory token.
119 * We parse a directory by breaking it into "tokens", each consisting
120 * of a keyword, a line full of arguments, and a binary object. The
121 * arguments and object are both optional, depending on the keyword
122 * type.
124 * This structure is only allocated in memareas; do not allocate it on
125 * the heap, or token_free() won't work.
127 typedef struct directory_token_t {
128 directory_keyword tp; /**< Type of the token. */
129 int n_args:30; /**< Number of elements in args */
130 char **args; /**< Array of arguments from keyword line. */
132 char *object_type; /**< -----BEGIN [object_type]-----*/
133 size_t object_size; /**< Bytes in object_body */
134 char *object_body; /**< Contents of object, base64-decoded. */
136 crypto_pk_env_t *key; /**< For public keys only. Heap-allocated. */
138 char *error; /**< For _ERR tokens only. */
139 } directory_token_t;
141 /* ********************************************************************** */
143 /** We use a table of rules to decide how to parse each token type. */
145 /** Rules for whether the keyword needs an object. */
146 typedef enum {
147 NO_OBJ, /**< No object, ever. */
148 NEED_OBJ, /**< Object is required. */
149 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
150 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
151 NEED_KEY, /**< Object is required, and must be a public key. */
152 OBJ_OK, /**< Object is optional. */
153 } obj_syntax;
155 #define AT_START 1
156 #define AT_END 2
158 /** Determines the parsing rules for a single token type. */
159 typedef struct token_rule_t {
160 /** The string value of the keyword identifying the type of item. */
161 const char *t;
162 /** The corresponding directory_keyword enum. */
163 directory_keyword v;
164 /** Minimum number of arguments for this item */
165 int min_args;
166 /** Maximum number of arguments for this item */
167 int max_args;
168 /** If true, we concatenate all arguments for this item into a single
169 * string. */
170 int concat_args;
171 /** Requirements on object syntax for this item. */
172 obj_syntax os;
173 /** Lowest number of times this item may appear in a document. */
174 int min_cnt;
175 /** Highest number of times this item may appear in a document. */
176 int max_cnt;
177 /** One or more of AT_START/AT_END to limit where the item may appear in a
178 * document. */
179 int pos;
180 /** True iff this token is an annotation. */
181 int is_annotation;
182 } token_rule_t;
185 * Helper macros to define token tables. 's' is a string, 't' is a
186 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
187 * object syntax.
191 /** Appears to indicate the end of a table. */
192 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
193 /** An item with no restrictions: used for obsolete document types */
194 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
195 /** An item with no restrictions on multiplicity or location. */
196 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
197 /** An item that must appear exactly once */
198 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
199 /** An item that must appear exactly once, at the start of the document */
200 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
201 /** An item that must appear exactly once, at the end of the document */
202 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
203 /** An item that must appear one or more times */
204 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
205 /** An item that must appear no more than once */
206 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
207 /** An annotation that must appear no more than once */
208 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
210 /* Argument multiplicity: any number of arguments. */
211 #define ARGS 0,INT_MAX,0
212 /* Argument multiplicity: no arguments. */
213 #define NO_ARGS 0,0,0
214 /* Argument multiplicity: concatenate all arguments. */
215 #define CONCAT_ARGS 1,1,1
216 /* Argument multiplicity: at least <b>n</b> arguments. */
217 #define GE(n) n,INT_MAX,0
218 /* Argument multiplicity: exactly <b>n</b> arguments. */
219 #define EQ(n) n,n,0
221 /** List of tokens allowable in router descriptors */
222 static token_rule_t routerdesc_token_table[] = {
223 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
224 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
225 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
226 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
227 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
228 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
229 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
230 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
231 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
232 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
233 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
234 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
235 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
236 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
237 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
238 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
239 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
240 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
241 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
243 T01("family", K_FAMILY, ARGS, NO_OBJ ),
244 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
245 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
247 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
248 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
249 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
251 END_OF_TABLE
254 /** List of tokens allowable in extra-info documents. */
255 static token_rule_t extrainfo_token_table[] = {
256 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
257 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
258 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
259 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
260 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
261 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
263 END_OF_TABLE
266 /** List of tokens allowable in the body part of v2 and v3 networkstatus
267 * documents. */
268 static token_rule_t rtrstatus_token_table[] = {
269 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
270 T1( "r", K_R, GE(8), NO_OBJ ),
271 T1( "s", K_S, ARGS, NO_OBJ ),
272 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
273 T01("w", K_W, ARGS, NO_OBJ ),
274 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
275 END_OF_TABLE
278 /** List of tokens allowable in the header part of v2 networkstatus documents.
280 static token_rule_t netstatus_token_table[] = {
281 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
282 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
283 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
284 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
285 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
286 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
287 GE(1), NO_OBJ ),
288 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
289 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
290 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
291 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
293 END_OF_TABLE
296 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
297 * footers. */
298 static token_rule_t dir_footer_token_table[] = {
299 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
300 END_OF_TABLE
303 /** List of tokens allowable in v1 directory headers/footers. */
304 static token_rule_t dir_token_table[] = {
305 /* don't enforce counts; this is obsolete. */
306 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
307 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
308 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
309 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
311 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
312 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
313 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
314 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
315 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
316 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
317 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
319 END_OF_TABLE
322 /** List of tokens common to V3 authority certificates and V3 consensuses. */
323 #define CERTIFICATE_MEMBERS \
324 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
325 GE(1), NO_OBJ ), \
326 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
327 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
328 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
329 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
330 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
331 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
332 NO_ARGS, NEED_OBJ), \
333 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
335 /** List of tokens allowable in V3 authority certificates. */
336 static token_rule_t dir_key_certificate_table[] = {
337 CERTIFICATE_MEMBERS
338 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
339 END_OF_TABLE
342 /** List of tokens allowable in rendezvous service descriptors */
343 static token_rule_t desc_token_table[] = {
344 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
345 EQ(1), NO_OBJ),
346 T1("version", R_VERSION, EQ(1), NO_OBJ),
347 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
348 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
349 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
350 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
351 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
352 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
353 END_OF_TABLE
356 /** List of tokens allowed in the (encrypted) list of introduction points of
357 * rendezvous service descriptors */
358 static token_rule_t ipo_token_table[] = {
359 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
360 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
361 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
362 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
363 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
364 END_OF_TABLE
367 /** List of tokens allowed in the (possibly encrypted) list of introduction
368 * points of rendezvous service descriptors */
369 static token_rule_t client_keys_token_table[] = {
370 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
371 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
372 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
373 END_OF_TABLE
376 /** List of tokens allowed in V3 networkstatus votes. */
377 static token_rule_t networkstatus_token_table[] = {
378 T1("network-status-version", K_NETWORK_STATUS_VERSION,
379 GE(1), NO_OBJ ),
380 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
381 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
382 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
383 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
384 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
385 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
386 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
387 T01("params", K_PARAMS, ARGS, NO_OBJ ),
388 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
390 CERTIFICATE_MEMBERS
392 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
393 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
394 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
395 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
396 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
397 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
398 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
399 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
401 END_OF_TABLE
404 /** List of tokens allowed in V3 networkstatus consensuses. */
405 static token_rule_t networkstatus_consensus_token_table[] = {
406 T1("network-status-version", K_NETWORK_STATUS_VERSION,
407 GE(1), NO_OBJ ),
408 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
409 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
410 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
411 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
412 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
414 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
416 T1N("dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
417 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
418 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
420 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
422 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
423 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
424 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
425 T01("params", K_PARAMS, ARGS, NO_OBJ ),
427 END_OF_TABLE
430 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
431 * footers. */
432 static token_rule_t networkstatus_vote_footer_token_table[] = {
433 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
434 END_OF_TABLE
437 /** List of tokens allowable in detached networkstatus signature documents. */
438 static token_rule_t networkstatus_detached_signature_token_table[] = {
439 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
440 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
441 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
442 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
443 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
444 END_OF_TABLE
447 #undef T
449 /* static function prototypes */
450 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
451 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok);
452 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
454 static int router_get_hash_impl(const char *s, size_t s_len, char *digest,
455 const char *start_str, const char *end_str,
456 char end_char);
458 static void token_free(directory_token_t *tok);
459 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
460 static directory_token_t *_find_by_keyword(smartlist_t *s,
461 directory_keyword keyword,
462 const char *keyword_str);
463 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
464 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
465 directory_keyword keyword);
467 #define TS_ANNOTATIONS_OK 1
468 #define TS_NOCHECK 2
469 #define TS_NO_NEW_ANNOTATIONS 4
470 static int tokenize_string(memarea_t *area,
471 const char *start, const char *end,
472 smartlist_t *out,
473 token_rule_t *table,
474 int flags);
475 static directory_token_t *get_next_token(memarea_t *area,
476 const char **s,
477 const char *eos,
478 token_rule_t *table);
479 #define CST_CHECK_AUTHORITY (1<<0)
480 #define CST_NO_CHECK_OBJTYPE (1<<1)
481 static int check_signature_token(const char *digest,
482 directory_token_t *tok,
483 crypto_pk_env_t *pkey,
484 int flags,
485 const char *doctype);
486 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
487 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
489 #undef DEBUG_AREA_ALLOC
491 #ifdef DEBUG_AREA_ALLOC
492 #define DUMP_AREA(a,name) STMT_BEGIN \
493 size_t alloc=0, used=0; \
494 memarea_get_stats((a),&alloc,&used); \
495 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
496 name, (unsigned long)alloc, (unsigned long)used); \
497 STMT_END
498 #else
499 #define DUMP_AREA(a,name) STMT_NIL
500 #endif
502 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
503 * <b>s</b>. Return 0 on success, -1 on failure.
506 router_get_dir_hash(const char *s, char *digest)
508 return router_get_hash_impl(s, strlen(s), digest,
509 "signed-directory","\ndirectory-signature",'\n');
512 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
513 * <b>s</b>. Return 0 on success, -1 on failure.
516 router_get_router_hash(const char *s, size_t s_len, char *digest)
518 return router_get_hash_impl(s, s_len, digest,
519 "router ","\nrouter-signature", '\n');
522 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
523 * string in <b>s</b>. Return 0 on success, -1 on failure.
526 router_get_runningrouters_hash(const char *s, char *digest)
528 return router_get_hash_impl(s, strlen(s), digest,
529 "network-status","\ndirectory-signature", '\n');
532 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
533 * string in <b>s</b>. Return 0 on success, -1 on failure. */
535 router_get_networkstatus_v2_hash(const char *s, char *digest)
537 return router_get_hash_impl(s, strlen(s), digest,
538 "network-status-version","\ndirectory-signature",
539 '\n');
542 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
543 * string in <b>s</b>. Return 0 on success, -1 on failure. */
545 router_get_networkstatus_v3_hash(const char *s, char *digest)
547 return router_get_hash_impl(s, strlen(s), digest,
548 "network-status-version",
549 "\ndirectory-signature",
550 ' ');
553 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
554 * string in <b>s</b>. Return 0 on success, -1 on failure. */
556 router_get_extrainfo_hash(const char *s, char *digest)
558 return router_get_hash_impl(s, strlen(s), digest, "extra-info",
559 "\nrouter-signature",'\n');
562 /** Helper: used to generate signatures for routers, directories and
563 * network-status objects. Given a digest in <b>digest</b> and a secret
564 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
565 * surround it with -----BEGIN/END----- pairs, and write it to the
566 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
567 * failure.
570 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
571 crypto_pk_env_t *private_key)
573 char *signature;
574 size_t i, keysize;
576 keysize = crypto_pk_keysize(private_key);
577 signature = tor_malloc(keysize);
578 if (crypto_pk_private_sign(private_key, signature, keysize,
579 digest, DIGEST_LEN) < 0) {
581 log_warn(LD_BUG,"Couldn't sign digest.");
582 goto err;
584 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
585 goto truncated;
587 i = strlen(buf);
588 if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) {
589 log_warn(LD_BUG,"couldn't base64-encode signature");
590 goto err;
593 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
594 goto truncated;
596 tor_free(signature);
597 return 0;
599 truncated:
600 log_warn(LD_BUG,"tried to exceed string length.");
601 err:
602 tor_free(signature);
603 return -1;
606 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
607 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
608 * entries. Else, return VS_OLD if every member of
609 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
610 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
611 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
612 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
613 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
614 * VS_UNRECOMMENDED.
616 * (versionlist is a comma-separated list of version strings,
617 * optionally prefixed with "Tor". Versions that can't be parsed are
618 * ignored.)
620 version_status_t
621 tor_version_is_obsolete(const char *myversion, const char *versionlist)
623 tor_version_t mine, other;
624 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
625 found_any_in_series = 0, r, same;
626 version_status_t ret = VS_UNRECOMMENDED;
627 smartlist_t *version_sl;
629 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
630 myversion, versionlist);
632 if (tor_version_parse(myversion, &mine)) {
633 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
634 tor_assert(0);
636 version_sl = smartlist_create();
637 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
639 if (!strlen(versionlist)) { /* no authorities cared or agreed */
640 ret = VS_EMPTY;
641 goto done;
644 SMARTLIST_FOREACH(version_sl, const char *, cp, {
645 if (!strcmpstart(cp, "Tor "))
646 cp += 4;
648 if (tor_version_parse(cp, &other)) {
649 /* Couldn't parse other; it can't be a match. */
650 } else {
651 same = tor_version_same_series(&mine, &other);
652 if (same)
653 found_any_in_series = 1;
654 r = tor_version_compare(&mine, &other);
655 if (r==0) {
656 ret = VS_RECOMMENDED;
657 goto done;
658 } else if (r<0) {
659 found_newer = 1;
660 if (same)
661 found_newer_in_series = 1;
662 } else if (r>0) {
663 found_older = 1;
668 /* We didn't find the listed version. Is it new or old? */
669 if (found_any_in_series && !found_newer_in_series && found_newer) {
670 ret = VS_NEW_IN_SERIES;
671 } else if (found_newer && !found_older) {
672 ret = VS_OLD;
673 } else if (found_older && !found_newer) {
674 ret = VS_NEW;
675 } else {
676 ret = VS_UNRECOMMENDED;
679 done:
680 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
681 smartlist_free(version_sl);
682 return ret;
685 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
686 * Otherwise, return -1. If we're a directory cache, cache it.
689 router_parse_directory(const char *str)
691 directory_token_t *tok;
692 char digest[DIGEST_LEN];
693 time_t published_on;
694 int r;
695 const char *end, *cp;
696 smartlist_t *tokens = NULL;
697 crypto_pk_env_t *declared_key = NULL;
698 memarea_t *area = memarea_new();
700 /* XXXX This could be simplified a lot, but it will all go away
701 * once pre-0.1.1.8 is obsolete, and for now it's better not to
702 * touch it. */
704 if (router_get_dir_hash(str, digest)) {
705 log_warn(LD_DIR, "Unable to compute digest of directory");
706 goto err;
708 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
710 /* Check signature first, before we try to tokenize. */
711 cp = str;
712 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
713 cp = end;
714 if (cp == str || !cp) {
715 log_warn(LD_DIR, "No signature found on directory."); goto err;
717 ++cp;
718 tokens = smartlist_create();
719 if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
720 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
722 if (smartlist_len(tokens) != 1) {
723 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
725 tok=smartlist_get(tokens,0);
726 if (tok->tp != K_DIRECTORY_SIGNATURE) {
727 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
729 declared_key = find_dir_signing_key(str, str+strlen(str));
730 note_crypto_pk_op(VERIFY_DIR);
731 if (check_signature_token(digest, tok, declared_key,
732 CST_CHECK_AUTHORITY, "directory")<0)
733 goto err;
735 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
736 smartlist_clear(tokens);
737 memarea_clear(area);
739 /* Now try to parse the first part of the directory. */
740 if ((end = strstr(str,"\nrouter "))) {
741 ++end;
742 } else if ((end = strstr(str, "\ndirectory-signature"))) {
743 ++end;
744 } else {
745 end = str + strlen(str);
748 if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
749 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
752 tok = find_by_keyword(tokens, K_PUBLISHED);
753 tor_assert(tok->n_args == 1);
755 if (parse_iso_time(tok->args[0], &published_on) < 0) {
756 goto err;
759 /* Now that we know the signature is okay, and we have a
760 * publication time, cache the directory. */
761 if (directory_caches_v1_dir_info(get_options()) &&
762 !authdir_mode_v1(get_options()))
763 dirserv_set_cached_directory(str, published_on, 0);
765 r = 0;
766 goto done;
767 err:
768 r = -1;
769 done:
770 if (declared_key) crypto_free_pk_env(declared_key);
771 if (tokens) {
772 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
773 smartlist_free(tokens);
775 if (area) {
776 DUMP_AREA(area, "v1 directory");
777 memarea_drop_all(area);
779 return r;
782 /** Read a signed router status statement from <b>str</b>. If it's
783 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
784 * cache it.*/
786 router_parse_runningrouters(const char *str)
788 char digest[DIGEST_LEN];
789 directory_token_t *tok;
790 time_t published_on;
791 int r = -1;
792 crypto_pk_env_t *declared_key = NULL;
793 smartlist_t *tokens = NULL;
794 const char *eos = str + strlen(str);
795 memarea_t *area = NULL;
797 if (router_get_runningrouters_hash(str, digest)) {
798 log_warn(LD_DIR, "Unable to compute digest of running-routers");
799 goto err;
801 area = memarea_new();
802 tokens = smartlist_create();
803 if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
804 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
806 tok = smartlist_get(tokens,0);
807 if (tok->tp != K_NETWORK_STATUS) {
808 log_warn(LD_DIR, "Network-status starts with wrong token");
809 goto err;
812 tok = find_by_keyword(tokens, K_PUBLISHED);
813 tor_assert(tok->n_args == 1);
814 if (parse_iso_time(tok->args[0], &published_on) < 0) {
815 goto err;
817 if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
818 log_warn(LD_DIR, "Missing signature on running-routers");
819 goto err;
821 declared_key = find_dir_signing_key(str, eos);
822 note_crypto_pk_op(VERIFY_DIR);
823 if (check_signature_token(digest, tok, declared_key,
824 CST_CHECK_AUTHORITY, "running-routers")
825 < 0)
826 goto err;
828 /* Now that we know the signature is okay, and we have a
829 * publication time, cache the list. */
830 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
831 dirserv_set_cached_directory(str, published_on, 1);
833 r = 0;
834 err:
835 if (declared_key) crypto_free_pk_env(declared_key);
836 if (tokens) {
837 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
838 smartlist_free(tokens);
840 if (area) {
841 DUMP_AREA(area, "v1 running-routers");
842 memarea_drop_all(area);
844 return r;
847 /** Given a directory or running-routers string in <b>str</b>, try to
848 * find the its dir-signing-key token (if any). If this token is
849 * present, extract and return the key. Return NULL on failure. */
850 static crypto_pk_env_t *
851 find_dir_signing_key(const char *str, const char *eos)
853 const char *cp;
854 directory_token_t *tok;
855 crypto_pk_env_t *key = NULL;
856 memarea_t *area = NULL;
857 tor_assert(str);
858 tor_assert(eos);
860 /* Is there a dir-signing-key in the directory? */
861 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
862 if (!cp)
863 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
864 if (!cp)
865 return NULL;
866 ++cp; /* Now cp points to the start of the token. */
868 area = memarea_new();
869 tok = get_next_token(area, &cp, eos, dir_token_table);
870 if (!tok) {
871 log_warn(LD_DIR, "Unparseable dir-signing-key token");
872 goto done;
874 if (tok->tp != K_DIR_SIGNING_KEY) {
875 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
876 goto done;
879 if (tok->key) {
880 key = tok->key;
881 tok->key = NULL; /* steal reference. */
882 } else {
883 log_warn(LD_DIR, "Dir-signing-key token contained no key");
886 done:
887 if (tok) token_free(tok);
888 if (area) {
889 DUMP_AREA(area, "dir-signing-key token");
890 memarea_drop_all(area);
892 return key;
895 /** Return true iff <b>key</b> is allowed to sign directories.
897 static int
898 dir_signing_key_is_trusted(crypto_pk_env_t *key)
900 char digest[DIGEST_LEN];
901 if (!key) return 0;
902 if (crypto_pk_get_digest(key, digest) < 0) {
903 log_warn(LD_DIR, "Error computing dir-signing-key digest");
904 return 0;
906 if (!router_digest_is_trusted_dir(digest)) {
907 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
908 return 0;
910 return 1;
913 /** Check whether the object body of the token in <b>tok</b> has a good
914 * signature for <b>digest</b> using key <b>pkey</b>. If
915 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
916 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
917 * the object type of the signature object. Use <b>doctype</b> as the type of
918 * the document when generating log messages. Return 0 on success, negative
919 * on failure.
921 static int
922 check_signature_token(const char *digest,
923 directory_token_t *tok,
924 crypto_pk_env_t *pkey,
925 int flags,
926 const char *doctype)
928 char *signed_digest;
929 size_t keysize;
930 const int check_authority = (flags & CST_CHECK_AUTHORITY);
931 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
933 tor_assert(pkey);
934 tor_assert(tok);
935 tor_assert(digest);
936 tor_assert(doctype);
938 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
939 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
940 doctype);
941 return -1;
944 if (check_objtype) {
945 if (strcmp(tok->object_type, "SIGNATURE")) {
946 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
947 return -1;
951 keysize = crypto_pk_keysize(pkey);
952 signed_digest = tor_malloc(keysize);
953 if (crypto_pk_public_checksig(pkey, signed_digest, keysize,
954 tok->object_body, tok->object_size)
955 != DIGEST_LEN) {
956 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
957 tor_free(signed_digest);
958 return -1;
960 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
961 // hex_str(signed_digest,4));
962 if (memcmp(digest, signed_digest, DIGEST_LEN)) {
963 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
964 tor_free(signed_digest);
965 return -1;
967 tor_free(signed_digest);
968 return 0;
971 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
972 * or to the first of the annotations proceeding the next router or
973 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
974 * we found an extrainfo, or false if found a router. Do not scan beyond
975 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
976 static int
977 find_start_of_next_router_or_extrainfo(const char **s_ptr,
978 const char *eos,
979 int *is_extrainfo_out)
981 const char *annotations = NULL;
982 const char *s = *s_ptr;
984 s = eat_whitespace_eos(s, eos);
986 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
987 /* We're at the start of a line. */
988 tor_assert(*s != '\n');
990 if (*s == '@' && !annotations) {
991 annotations = s;
992 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
993 *s_ptr = annotations ? annotations : s;
994 *is_extrainfo_out = 0;
995 return 0;
996 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
997 *s_ptr = annotations ? annotations : s;
998 *is_extrainfo_out = 1;
999 return 0;
1002 if (!(s = memchr(s+1, '\n', eos-(s+1))))
1003 break;
1004 s = eat_whitespace_eos(s, eos);
1006 return -1;
1009 /** Given a string *<b>s</b> containing a concatenated sequence of router
1010 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1011 * them and stores the result in <b>dest</b>. All routers are marked running
1012 * and valid. Advances *s to a point immediately following the last router
1013 * entry. Ignore any trailing router entries that are not complete.
1015 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1016 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1017 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1019 * Returns 0 on success and -1 on failure.
1022 router_parse_list_from_string(const char **s, const char *eos,
1023 smartlist_t *dest,
1024 saved_location_t saved_location,
1025 int want_extrainfo,
1026 int allow_annotations,
1027 const char *prepend_annotations)
1029 routerinfo_t *router;
1030 extrainfo_t *extrainfo;
1031 signed_descriptor_t *signed_desc;
1032 void *elt;
1033 const char *end, *start;
1034 int have_extrainfo;
1036 tor_assert(s);
1037 tor_assert(*s);
1038 tor_assert(dest);
1040 start = *s;
1041 if (!eos)
1042 eos = *s + strlen(*s);
1044 tor_assert(eos >= *s);
1046 while (1) {
1047 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1048 break;
1050 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1051 if (end)
1052 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1053 if (end)
1054 end += strlen("\n-----END SIGNATURE-----\n");
1056 if (!end)
1057 break;
1059 elt = NULL;
1061 if (have_extrainfo && want_extrainfo) {
1062 routerlist_t *rl = router_get_routerlist();
1063 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1064 saved_location != SAVED_IN_CACHE,
1065 rl->identity_map);
1066 if (extrainfo) {
1067 signed_desc = &extrainfo->cache_info;
1068 elt = extrainfo;
1070 } else if (!have_extrainfo && !want_extrainfo) {
1071 router = router_parse_entry_from_string(*s, end,
1072 saved_location != SAVED_IN_CACHE,
1073 allow_annotations,
1074 prepend_annotations);
1075 if (router) {
1076 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1077 router->nickname, router_purpose_to_string(router->purpose));
1078 signed_desc = &router->cache_info;
1079 elt = router;
1082 if (!elt) {
1083 *s = end;
1084 continue;
1086 if (saved_location != SAVED_NOWHERE) {
1087 signed_desc->saved_location = saved_location;
1088 signed_desc->saved_offset = *s - start;
1090 *s = end;
1091 smartlist_add(dest, elt);
1094 return 0;
1097 /* For debugging: define to count every descriptor digest we've seen so we
1098 * know if we need to try harder to avoid duplicate verifies. */
1099 #undef COUNT_DISTINCT_DIGESTS
1101 #ifdef COUNT_DISTINCT_DIGESTS
1102 static digestmap_t *verified_digests = NULL;
1103 #endif
1105 /** Log the total count of the number of distinct router digests we've ever
1106 * verified. When compared to the number of times we've verified routerdesc
1107 * signatures <i>in toto</i>, this will tell us if we're doing too much
1108 * multiple-verification. */
1109 void
1110 dump_distinct_digest_count(int severity)
1112 #ifdef COUNT_DISTINCT_DIGESTS
1113 if (!verified_digests)
1114 verified_digests = digestmap_new();
1115 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1116 digestmap_size(verified_digests));
1117 #else
1118 (void)severity; /* suppress "unused parameter" warning */
1119 #endif
1122 /** Helper function: reads a single router entry from *<b>s</b> ...
1123 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1124 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1125 * s through end into the signed_descriptor_body of the resulting
1126 * routerinfo_t.
1128 * If <b>end</b> is NULL, <b>s</b> must be properly NULL-terminated.
1130 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1131 * before the router; if it's false, reject the router if it's annotated. If
1132 * <b>prepend_annotations</b> is set, it should contain some annotations:
1133 * append them to the front of the router before parsing it, and keep them
1134 * around when caching the router.
1136 * Only one of allow_annotations and prepend_annotations may be set.
1138 routerinfo_t *
1139 router_parse_entry_from_string(const char *s, const char *end,
1140 int cache_copy, int allow_annotations,
1141 const char *prepend_annotations)
1143 routerinfo_t *router = NULL;
1144 char digest[128];
1145 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1146 directory_token_t *tok;
1147 struct in_addr in;
1148 const char *start_of_annotations, *cp;
1149 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1150 int ok = 1;
1151 memarea_t *area = NULL;
1153 tor_assert(!allow_annotations || !prepend_annotations);
1155 if (!end) {
1156 end = s + strlen(s);
1159 /* point 'end' to a point immediately after the final newline. */
1160 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1161 --end;
1163 area = memarea_new();
1164 tokens = smartlist_create();
1165 if (prepend_annotations) {
1166 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1167 routerdesc_token_table,TS_NOCHECK)) {
1168 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1169 goto err;
1173 start_of_annotations = s;
1174 cp = tor_memstr(s, end-s, "\nrouter ");
1175 if (!cp) {
1176 if (end-s < 7 || strcmpstart(s, "router ")) {
1177 log_warn(LD_DIR, "No router keyword found.");
1178 goto err;
1180 } else {
1181 s = cp+1;
1184 if (start_of_annotations != s) { /* We have annotations */
1185 if (allow_annotations) {
1186 if (tokenize_string(area,start_of_annotations,s,tokens,
1187 routerdesc_token_table,TS_NOCHECK)) {
1188 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1189 goto err;
1191 } else {
1192 log_warn(LD_DIR, "Found unexpected annotations on router descriptor not "
1193 "loaded from disk. Dropping it.");
1194 goto err;
1198 if (router_get_router_hash(s, end - s, digest) < 0) {
1199 log_warn(LD_DIR, "Couldn't compute router hash.");
1200 goto err;
1203 int flags = 0;
1204 if (allow_annotations)
1205 flags |= TS_ANNOTATIONS_OK;
1206 if (prepend_annotations)
1207 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1209 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1210 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1211 goto err;
1215 if (smartlist_len(tokens) < 2) {
1216 log_warn(LD_DIR, "Impossibly short router descriptor.");
1217 goto err;
1220 tok = find_by_keyword(tokens, K_ROUTER);
1221 tor_assert(tok->n_args >= 5);
1223 router = tor_malloc_zero(sizeof(routerinfo_t));
1224 router->country = -1;
1225 router->cache_info.routerlist_index = -1;
1226 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1227 router->cache_info.signed_descriptor_len = end-s;
1228 if (cache_copy) {
1229 size_t len = router->cache_info.signed_descriptor_len +
1230 router->cache_info.annotations_len;
1231 char *cp =
1232 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1233 if (prepend_annotations) {
1234 memcpy(cp, prepend_annotations, prepend_len);
1235 cp += prepend_len;
1237 /* This assertion will always succeed.
1238 * len == signed_desc_len + annotations_len
1239 * == end-s + s-start_of_annotations + prepend_len
1240 * == end-start_of_annotations + prepend_len
1241 * We already wrote prepend_len bytes into the buffer; now we're
1242 * writing end-start_of_annotations -NM. */
1243 tor_assert(cp+(end-start_of_annotations) ==
1244 router->cache_info.signed_descriptor_body+len);
1245 memcpy(cp, start_of_annotations, end-start_of_annotations);
1246 router->cache_info.signed_descriptor_body[len] = '\0';
1247 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1249 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1251 router->nickname = tor_strdup(tok->args[0]);
1252 if (!is_legal_nickname(router->nickname)) {
1253 log_warn(LD_DIR,"Router nickname is invalid");
1254 goto err;
1256 router->address = tor_strdup(tok->args[1]);
1257 if (!tor_inet_aton(router->address, &in)) {
1258 log_warn(LD_DIR,"Router address is not an IP address.");
1259 goto err;
1261 router->addr = ntohl(in.s_addr);
1263 router->or_port =
1264 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1265 if (!ok) {
1266 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1267 goto err;
1269 router->dir_port =
1270 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1271 if (!ok) {
1272 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1273 goto err;
1276 tok = find_by_keyword(tokens, K_BANDWIDTH);
1277 tor_assert(tok->n_args >= 3);
1278 router->bandwidthrate = (int)
1279 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1281 if (!ok) {
1282 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1283 escaped(tok->args[0]));
1284 goto err;
1286 router->bandwidthburst =
1287 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1288 if (!ok) {
1289 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1290 goto err;
1292 router->bandwidthcapacity = (int)
1293 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1294 if (!ok) {
1295 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1296 goto err;
1299 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1300 tor_assert(tok->n_args);
1301 router->purpose = router_purpose_from_string(tok->args[0]);
1302 } else {
1303 router->purpose = ROUTER_PURPOSE_GENERAL;
1305 router->cache_info.send_unencrypted =
1306 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1308 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1309 tor_assert(tok->n_args >= 1);
1310 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1311 if (!ok) {
1312 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1313 goto err;
1317 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1318 tor_assert(tok->n_args >= 1);
1319 router->is_hibernating
1320 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1323 tok = find_by_keyword(tokens, K_PUBLISHED);
1324 tor_assert(tok->n_args == 1);
1325 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1326 goto err;
1328 tok = find_by_keyword(tokens, K_ONION_KEY);
1329 router->onion_pkey = tok->key;
1330 tok->key = NULL; /* Prevent free */
1332 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1333 router->identity_pkey = tok->key;
1334 tok->key = NULL; /* Prevent free */
1335 if (crypto_pk_get_digest(router->identity_pkey,
1336 router->cache_info.identity_digest)) {
1337 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1340 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1341 /* If there's a fingerprint line, it must match the identity digest. */
1342 char d[DIGEST_LEN];
1343 tor_assert(tok->n_args == 1);
1344 tor_strstrip(tok->args[0], " ");
1345 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1346 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1347 escaped(tok->args[0]));
1348 goto err;
1350 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1351 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1352 tok->args[0]);
1353 goto err;
1357 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1358 router->platform = tor_strdup(tok->args[0]);
1361 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1362 router->contact_info = tor_strdup(tok->args[0]);
1365 if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
1366 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1367 } else if (router->platform) {
1368 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1369 router->has_old_dnsworkers = 1;
1372 if (find_opt_by_keyword(tokens, K_REJECT6) ||
1373 find_opt_by_keyword(tokens, K_ACCEPT6)) {
1374 log_warn(LD_DIR, "Rejecting router with reject6/accept6 line: they crash "
1375 "older Tors.");
1376 goto err;
1378 exit_policy_tokens = find_all_exitpolicy(tokens);
1379 if (!smartlist_len(exit_policy_tokens)) {
1380 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1381 goto err;
1383 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1384 if (router_add_exit_policy(router,t)<0) {
1385 log_warn(LD_DIR,"Error in exit policy");
1386 goto err;
1388 policy_expand_private(&router->exit_policy);
1389 if (policy_is_reject_star(router->exit_policy))
1390 router->policy_is_reject_star = 1;
1392 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1393 int i;
1394 router->declared_family = smartlist_create();
1395 for (i=0;i<tok->n_args;++i) {
1396 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1397 log_warn(LD_DIR, "Illegal nickname %s in family line",
1398 escaped(tok->args[i]));
1399 goto err;
1401 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1405 if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1406 router->caches_extra_info = 1;
1408 if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
1409 router->allow_single_hop_exits = 1;
1411 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1412 tor_assert(tok->n_args >= 1);
1413 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1414 base16_decode(router->cache_info.extra_info_digest,
1415 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1416 } else {
1417 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1421 if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1422 router->wants_to_be_hs_dir = 1;
1425 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1426 note_crypto_pk_op(VERIFY_RTR);
1427 #ifdef COUNT_DISTINCT_DIGESTS
1428 if (!verified_digests)
1429 verified_digests = digestmap_new();
1430 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1431 #endif
1432 if (check_signature_token(digest, tok, router->identity_pkey, 0,
1433 "router descriptor") < 0)
1434 goto err;
1436 routerinfo_set_country(router);
1438 if (!router->or_port) {
1439 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1440 goto err;
1443 if (!router->platform) {
1444 router->platform = tor_strdup("<unknown>");
1447 goto done;
1449 err:
1450 routerinfo_free(router);
1451 router = NULL;
1452 done:
1453 if (tokens) {
1454 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1455 smartlist_free(tokens);
1457 if (exit_policy_tokens) {
1458 smartlist_free(exit_policy_tokens);
1460 if (area) {
1461 DUMP_AREA(area, "routerinfo");
1462 memarea_drop_all(area);
1464 return router;
1467 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1468 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1469 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1470 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1471 * as a map from router identity to routerinfo_t when looking up signing keys.
1473 extrainfo_t *
1474 extrainfo_parse_entry_from_string(const char *s, const char *end,
1475 int cache_copy, struct digest_ri_map_t *routermap)
1477 extrainfo_t *extrainfo = NULL;
1478 char digest[128];
1479 smartlist_t *tokens = NULL;
1480 directory_token_t *tok;
1481 crypto_pk_env_t *key = NULL;
1482 routerinfo_t *router = NULL;
1483 memarea_t *area = NULL;
1485 if (!end) {
1486 end = s + strlen(s);
1489 /* point 'end' to a point immediately after the final newline. */
1490 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1491 --end;
1493 if (router_get_extrainfo_hash(s, digest) < 0) {
1494 log_warn(LD_DIR, "Couldn't compute router hash.");
1495 goto err;
1497 tokens = smartlist_create();
1498 area = memarea_new();
1499 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1500 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1501 goto err;
1504 if (smartlist_len(tokens) < 2) {
1505 log_warn(LD_DIR, "Impossibly short extra-info document.");
1506 goto err;
1509 tok = smartlist_get(tokens,0);
1510 if (tok->tp != K_EXTRA_INFO) {
1511 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1512 goto err;
1515 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1516 extrainfo->cache_info.is_extrainfo = 1;
1517 if (cache_copy)
1518 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1519 extrainfo->cache_info.signed_descriptor_len = end-s;
1520 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1522 tor_assert(tok->n_args >= 2);
1523 if (!is_legal_nickname(tok->args[0])) {
1524 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1525 goto err;
1527 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1528 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1529 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1530 tok->args[1], HEX_DIGEST_LEN)) {
1531 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1532 escaped(tok->args[1]));
1533 goto err;
1536 tok = find_by_keyword(tokens, K_PUBLISHED);
1537 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1538 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1539 escaped(tok->args[0]));
1540 goto err;
1543 if (routermap &&
1544 (router = digestmap_get((digestmap_t*)routermap,
1545 extrainfo->cache_info.identity_digest))) {
1546 key = router->identity_pkey;
1549 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1550 if (strcmp(tok->object_type, "SIGNATURE") ||
1551 tok->object_size < 128 || tok->object_size > 512) {
1552 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1553 goto err;
1556 if (key) {
1557 note_crypto_pk_op(VERIFY_RTR);
1558 if (check_signature_token(digest, tok, key, 0, "extra-info") < 0)
1559 goto err;
1561 if (router)
1562 extrainfo->cache_info.send_unencrypted =
1563 router->cache_info.send_unencrypted;
1564 } else {
1565 extrainfo->pending_sig = tor_memdup(tok->object_body,
1566 tok->object_size);
1567 extrainfo->pending_sig_len = tok->object_size;
1570 goto done;
1571 err:
1572 if (extrainfo)
1573 extrainfo_free(extrainfo);
1574 extrainfo = NULL;
1575 done:
1576 if (tokens) {
1577 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1578 smartlist_free(tokens);
1580 if (area) {
1581 DUMP_AREA(area, "extrainfo");
1582 memarea_drop_all(area);
1584 return extrainfo;
1587 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1588 * the first character after the certificate. */
1589 authority_cert_t *
1590 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1592 /** Reject any certificate at least this big; it is probably an overflow, an
1593 * attack, a bug, or some other nonsense. */
1594 #define MAX_CERT_SIZE (128*1024)
1596 authority_cert_t *cert = NULL, *old_cert;
1597 smartlist_t *tokens = NULL;
1598 char digest[DIGEST_LEN];
1599 directory_token_t *tok;
1600 char fp_declared[DIGEST_LEN];
1601 char *eos;
1602 size_t len;
1603 int found;
1604 memarea_t *area = NULL;
1606 s = eat_whitespace(s);
1607 eos = strstr(s, "\ndir-key-certification");
1608 if (! eos) {
1609 log_warn(LD_DIR, "No signature found on key certificate");
1610 return NULL;
1612 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1613 if (! eos) {
1614 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1615 return NULL;
1617 eos = strchr(eos+2, '\n');
1618 tor_assert(eos);
1619 ++eos;
1620 len = eos - s;
1622 if (len > MAX_CERT_SIZE) {
1623 log_warn(LD_DIR, "Certificate is far too big (at %lu bytes long); "
1624 "rejecting", (unsigned long)len);
1625 return NULL;
1628 tokens = smartlist_create();
1629 area = memarea_new();
1630 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1631 log_warn(LD_DIR, "Error tokenizing key certificate");
1632 goto err;
1634 if (router_get_hash_impl(s, strlen(s), digest, "dir-key-certificate-version",
1635 "\ndir-key-certification", '\n') < 0)
1636 goto err;
1637 tok = smartlist_get(tokens, 0);
1638 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1639 log_warn(LD_DIR,
1640 "Key certificate does not begin with a recognized version (3).");
1641 goto err;
1644 cert = tor_malloc_zero(sizeof(authority_cert_t));
1645 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1647 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1648 tor_assert(tok->key);
1649 cert->signing_key = tok->key;
1650 tok->key = NULL;
1651 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1652 goto err;
1654 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1655 tor_assert(tok->key);
1656 cert->identity_key = tok->key;
1657 tok->key = NULL;
1659 tok = find_by_keyword(tokens, K_FINGERPRINT);
1660 tor_assert(tok->n_args);
1661 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1662 strlen(tok->args[0]))) {
1663 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1664 escaped(tok->args[0]));
1665 goto err;
1668 if (crypto_pk_get_digest(cert->identity_key,
1669 cert->cache_info.identity_digest))
1670 goto err;
1672 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1673 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1674 "fingerprint");
1675 goto err;
1678 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1679 if (tok) {
1680 struct in_addr in;
1681 char *address = NULL;
1682 tor_assert(tok->n_args);
1683 /* XXX021 use tor_addr_port_parse() below instead. -RD */
1684 if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
1685 &cert->dir_port)<0 ||
1686 tor_inet_aton(address, &in) == 0) {
1687 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1688 tor_free(address);
1689 goto err;
1691 cert->addr = ntohl(in.s_addr);
1692 tor_free(address);
1695 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1696 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1697 goto err;
1699 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1700 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1701 goto err;
1704 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1705 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1706 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1707 goto err;
1710 /* If we already have this cert, don't bother checking the signature. */
1711 old_cert = authority_cert_get_by_digests(
1712 cert->cache_info.identity_digest,
1713 cert->signing_key_digest);
1714 found = 0;
1715 if (old_cert) {
1716 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1717 * buy us much. */
1718 if (old_cert->cache_info.signed_descriptor_len == len &&
1719 old_cert->cache_info.signed_descriptor_body &&
1720 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1721 log_debug(LD_DIR, "We already checked the signature on this "
1722 "certificate; no need to do so again.");
1723 found = 1;
1724 cert->is_cross_certified = old_cert->is_cross_certified;
1727 if (!found) {
1728 if (check_signature_token(digest, tok, cert->identity_key, 0,
1729 "key certificate")) {
1730 goto err;
1733 if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
1734 /* XXXX Once all authorities generate cross-certified certificates,
1735 * make this field mandatory. */
1736 if (check_signature_token(cert->cache_info.identity_digest,
1737 tok,
1738 cert->signing_key,
1739 CST_NO_CHECK_OBJTYPE,
1740 "key cross-certification")) {
1741 goto err;
1743 cert->is_cross_certified = 1;
1747 cert->cache_info.signed_descriptor_len = len;
1748 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1749 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1750 cert->cache_info.signed_descriptor_body[len] = 0;
1751 cert->cache_info.saved_location = SAVED_NOWHERE;
1753 if (end_of_string) {
1754 *end_of_string = eat_whitespace(eos);
1756 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1757 smartlist_free(tokens);
1758 if (area) {
1759 DUMP_AREA(area, "authority cert");
1760 memarea_drop_all(area);
1762 return cert;
1763 err:
1764 authority_cert_free(cert);
1765 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1766 smartlist_free(tokens);
1767 if (area) {
1768 DUMP_AREA(area, "authority cert");
1769 memarea_drop_all(area);
1771 return NULL;
1774 /** Helper: given a string <b>s</b>, return the start of the next router-status
1775 * object (starting with "r " at the start of a line). If none is found,
1776 * return the start of the next directory signature. If none is found, return
1777 * the end of the string. */
1778 static INLINE const char *
1779 find_start_of_next_routerstatus(const char *s)
1781 const char *eos = strstr(s, "\nr ");
1782 if (eos) {
1783 const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
1784 if (eos2 && eos2 < eos)
1785 return eos2;
1786 else
1787 return eos+1;
1788 } else {
1789 if ((eos = strstr(s, "\ndirectory-signature")))
1790 return eos+1;
1791 return s + strlen(s);
1795 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1796 * empty smartlist at <b>tokens</b>, parse and return the first router status
1797 * object in the string, and advance *<b>s</b> to just after the end of the
1798 * router status. Return NULL and advance *<b>s</b> on error.
1800 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1801 * routerstatus but use <b>vote_rs</b> instead.
1803 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1804 * consensus, and we should parse it according to the method used to
1805 * make that consensus.
1807 static routerstatus_t *
1808 routerstatus_parse_entry_from_string(memarea_t *area,
1809 const char **s, smartlist_t *tokens,
1810 networkstatus_t *vote,
1811 vote_routerstatus_t *vote_rs,
1812 int consensus_method)
1814 const char *eos;
1815 routerstatus_t *rs = NULL;
1816 directory_token_t *tok;
1817 char timebuf[ISO_TIME_LEN+1];
1818 struct in_addr in;
1819 tor_assert(tokens);
1820 tor_assert(bool_eq(vote, vote_rs));
1822 eos = find_start_of_next_routerstatus(*s);
1824 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1825 log_warn(LD_DIR, "Error tokenizing router status");
1826 goto err;
1828 if (smartlist_len(tokens) < 1) {
1829 log_warn(LD_DIR, "Impossibly short router status");
1830 goto err;
1832 tok = find_by_keyword(tokens, K_R);
1833 tor_assert(tok->n_args >= 8);
1834 if (vote_rs) {
1835 rs = &vote_rs->status;
1836 } else {
1837 rs = tor_malloc_zero(sizeof(routerstatus_t));
1840 if (!is_legal_nickname(tok->args[0])) {
1841 log_warn(LD_DIR,
1842 "Invalid nickname %s in router status; skipping.",
1843 escaped(tok->args[0]));
1844 goto err;
1846 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1848 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1849 log_warn(LD_DIR, "Error decoding identity digest %s",
1850 escaped(tok->args[1]));
1851 goto err;
1854 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1855 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1856 escaped(tok->args[2]));
1857 goto err;
1860 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1861 tok->args[3], tok->args[4]) < 0 ||
1862 parse_iso_time(timebuf, &rs->published_on)<0) {
1863 log_warn(LD_DIR, "Error parsing time '%s %s'",
1864 tok->args[3], tok->args[4]);
1865 goto err;
1868 if (tor_inet_aton(tok->args[5], &in) == 0) {
1869 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1870 escaped(tok->args[5]));
1871 goto err;
1873 rs->addr = ntohl(in.s_addr);
1875 rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL);
1876 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL);
1878 tok = find_opt_by_keyword(tokens, K_S);
1879 if (tok && vote) {
1880 int i;
1881 vote_rs->flags = 0;
1882 for (i=0; i < tok->n_args; ++i) {
1883 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1884 if (p >= 0) {
1885 vote_rs->flags |= (1<<p);
1886 } else {
1887 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1888 escaped(tok->args[i]));
1889 goto err;
1892 } else if (tok) {
1893 int i;
1894 for (i=0; i < tok->n_args; ++i) {
1895 if (!strcmp(tok->args[i], "Exit"))
1896 rs->is_exit = 1;
1897 else if (!strcmp(tok->args[i], "Stable"))
1898 rs->is_stable = 1;
1899 else if (!strcmp(tok->args[i], "Fast"))
1900 rs->is_fast = 1;
1901 else if (!strcmp(tok->args[i], "Running"))
1902 rs->is_running = 1;
1903 else if (!strcmp(tok->args[i], "Named"))
1904 rs->is_named = 1;
1905 else if (!strcmp(tok->args[i], "Valid"))
1906 rs->is_valid = 1;
1907 else if (!strcmp(tok->args[i], "V2Dir"))
1908 rs->is_v2_dir = 1;
1909 else if (!strcmp(tok->args[i], "Guard"))
1910 rs->is_possible_guard = 1;
1911 else if (!strcmp(tok->args[i], "BadExit"))
1912 rs->is_bad_exit = 1;
1913 else if (!strcmp(tok->args[i], "BadDirectory"))
1914 rs->is_bad_directory = 1;
1915 else if (!strcmp(tok->args[i], "Authority"))
1916 rs->is_authority = 1;
1917 else if (!strcmp(tok->args[i], "Unnamed") &&
1918 consensus_method >= 2) {
1919 /* Unnamed is computed right by consensus method 2 and later. */
1920 rs->is_unnamed = 1;
1921 } else if (!strcmp(tok->args[i], "HSDir")) {
1922 rs->is_hs_dir = 1;
1926 if ((tok = find_opt_by_keyword(tokens, K_V))) {
1927 tor_assert(tok->n_args == 1);
1928 rs->version_known = 1;
1929 if (strcmpstart(tok->args[0], "Tor ")) {
1930 rs->version_supports_begindir = 1;
1931 rs->version_supports_extrainfo_upload = 1;
1932 rs->version_supports_conditional_consensus = 1;
1933 } else {
1934 rs->version_supports_begindir =
1935 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
1936 rs->version_supports_extrainfo_upload =
1937 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
1938 rs->version_supports_v3_dir =
1939 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
1940 rs->version_supports_conditional_consensus =
1941 tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
1943 if (vote_rs) {
1944 vote_rs->version = tor_strdup(tok->args[0]);
1948 /* handle weighting/bandwidth info */
1949 if ((tok = find_opt_by_keyword(tokens, K_W))) {
1950 int i;
1951 for (i=0; i < tok->n_args; ++i) {
1952 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
1953 int ok;
1954 rs->bandwidth = (uint32_t)tor_parse_ulong(strchr(tok->args[i], '=')+1,
1955 10, 0, UINT32_MAX,
1956 &ok, NULL);
1957 if (!ok) {
1958 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
1959 goto err;
1961 rs->has_bandwidth = 1;
1966 /* parse exit policy summaries */
1967 if ((tok = find_opt_by_keyword(tokens, K_P))) {
1968 tor_assert(tok->n_args == 1);
1969 if (strcmpstart(tok->args[0], "accept ") &&
1970 strcmpstart(tok->args[0], "reject ")) {
1971 log_warn(LD_DIR, "Unknown exit policy summary type %s.",
1972 escaped(tok->args[0]));
1973 goto err;
1975 /* XXX weasel: parse this into ports and represent them somehow smart,
1976 * maybe not here but somewhere on if we need it for the client.
1977 * we should still parse it here to check it's valid tho.
1979 rs->exitsummary = tor_strdup(tok->args[0]);
1980 rs->has_exitsummary = 1;
1983 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
1984 rs->is_named = 0;
1986 goto done;
1987 err:
1988 if (rs && !vote_rs)
1989 routerstatus_free(rs);
1990 rs = NULL;
1991 done:
1992 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1993 smartlist_clear(tokens);
1994 if (area) {
1995 DUMP_AREA(area, "routerstatus entry");
1996 memarea_clear(area);
1998 *s = eos;
2000 return rs;
2003 /** Helper to sort a smartlist of pointers to routerstatus_t */
2004 static int
2005 _compare_routerstatus_entries(const void **_a, const void **_b)
2007 const routerstatus_t *a = *_a, *b = *_b;
2008 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
2011 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
2012 static void
2013 _free_duplicate_routerstatus_entry(void *e)
2015 log_warn(LD_DIR,
2016 "Network-status has two entries for the same router. "
2017 "Dropping one.");
2018 routerstatus_free(e);
2021 /** Given a v2 network-status object in <b>s</b>, try to
2022 * parse it and return the result. Return NULL on failure. Check the
2023 * signature of the network status, but do not (yet) check the signing key for
2024 * authority.
2026 networkstatus_v2_t *
2027 networkstatus_v2_parse_from_string(const char *s)
2029 const char *eos;
2030 smartlist_t *tokens = smartlist_create();
2031 smartlist_t *footer_tokens = smartlist_create();
2032 networkstatus_v2_t *ns = NULL;
2033 char ns_digest[DIGEST_LEN];
2034 char tmp_digest[DIGEST_LEN];
2035 struct in_addr in;
2036 directory_token_t *tok;
2037 int i;
2038 memarea_t *area = NULL;
2040 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
2041 log_warn(LD_DIR, "Unable to compute digest of network-status");
2042 goto err;
2045 area = memarea_new();
2046 eos = find_start_of_next_routerstatus(s);
2047 if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
2048 log_warn(LD_DIR, "Error tokenizing network-status header.");
2049 goto err;
2051 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
2052 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2054 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2055 tor_assert(tok->n_args >= 1);
2056 if (strcmp(tok->args[0], "2")) {
2057 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
2058 "%s", escaped(tok->args[0]));
2059 goto err;
2062 tok = find_by_keyword(tokens, K_DIR_SOURCE);
2063 tor_assert(tok->n_args >= 3);
2064 ns->source_address = tor_strdup(tok->args[0]);
2065 if (tor_inet_aton(tok->args[1], &in) == 0) {
2066 log_warn(LD_DIR, "Error parsing network-status source address %s",
2067 escaped(tok->args[1]));
2068 goto err;
2070 ns->source_addr = ntohl(in.s_addr);
2071 ns->source_dirport =
2072 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
2073 if (ns->source_dirport == 0) {
2074 log_warn(LD_DIR, "Directory source without dirport; skipping.");
2075 goto err;
2078 tok = find_by_keyword(tokens, K_FINGERPRINT);
2079 tor_assert(tok->n_args);
2080 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
2081 strlen(tok->args[0]))) {
2082 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
2083 escaped(tok->args[0]));
2084 goto err;
2087 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2088 tor_assert(tok->n_args);
2089 ns->contact = tor_strdup(tok->args[0]);
2092 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2093 tor_assert(tok->key);
2094 ns->signing_key = tok->key;
2095 tok->key = NULL;
2097 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
2098 log_warn(LD_DIR, "Couldn't compute signing key digest");
2099 goto err;
2101 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
2102 log_warn(LD_DIR,
2103 "network-status fingerprint did not match dir-signing-key");
2104 goto err;
2107 if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
2108 for (i=0; i < tok->n_args; ++i) {
2109 if (!strcmp(tok->args[i], "Names"))
2110 ns->binds_names = 1;
2111 if (!strcmp(tok->args[i], "Versions"))
2112 ns->recommends_versions = 1;
2113 if (!strcmp(tok->args[i], "BadExits"))
2114 ns->lists_bad_exits = 1;
2115 if (!strcmp(tok->args[i], "BadDirectories"))
2116 ns->lists_bad_directories = 1;
2120 if (ns->recommends_versions) {
2121 if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2122 log_warn(LD_DIR, "Missing client-versions on versioning directory");
2123 goto err;
2125 ns->client_versions = tor_strdup(tok->args[0]);
2127 if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
2128 tok->n_args<1) {
2129 log_warn(LD_DIR, "Missing server-versions on versioning directory");
2130 goto err;
2132 ns->server_versions = tor_strdup(tok->args[0]);
2135 tok = find_by_keyword(tokens, K_PUBLISHED);
2136 tor_assert(tok->n_args == 1);
2137 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
2138 goto err;
2141 ns->entries = smartlist_create();
2142 s = eos;
2143 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2144 smartlist_clear(tokens);
2145 memarea_clear(area);
2146 while (!strcmpstart(s, "r ")) {
2147 routerstatus_t *rs;
2148 if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
2149 NULL, NULL, 0)))
2150 smartlist_add(ns->entries, rs);
2152 smartlist_sort(ns->entries, _compare_routerstatus_entries);
2153 smartlist_uniq(ns->entries, _compare_routerstatus_entries,
2154 _free_duplicate_routerstatus_entry);
2156 if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
2157 log_warn(LD_DIR, "Error tokenizing network-status footer.");
2158 goto err;
2160 if (smartlist_len(footer_tokens) < 1) {
2161 log_warn(LD_DIR, "Too few items in network-status footer.");
2162 goto err;
2164 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
2165 if (tok->tp != K_DIRECTORY_SIGNATURE) {
2166 log_warn(LD_DIR,
2167 "Expected network-status footer to end with a signature.");
2168 goto err;
2171 note_crypto_pk_op(VERIFY_DIR);
2172 if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
2173 "network-status") < 0)
2174 goto err;
2176 goto done;
2177 err:
2178 if (ns)
2179 networkstatus_v2_free(ns);
2180 ns = NULL;
2181 done:
2182 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2183 smartlist_free(tokens);
2184 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2185 smartlist_free(footer_tokens);
2186 if (area) {
2187 DUMP_AREA(area, "v2 networkstatus");
2188 memarea_drop_all(area);
2190 return ns;
2193 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2194 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2195 networkstatus_t *
2196 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2197 networkstatus_type_t ns_type)
2199 smartlist_t *tokens = smartlist_create();
2200 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2201 networkstatus_voter_info_t *voter = NULL;
2202 networkstatus_t *ns = NULL;
2203 char ns_digest[DIGEST_LEN];
2204 const char *cert, *end_of_header, *end_of_footer;
2205 directory_token_t *tok;
2206 int ok;
2207 struct in_addr in;
2208 int i, inorder, n_signatures = 0;
2209 memarea_t *area = NULL, *rs_area = NULL;
2210 tor_assert(s);
2212 if (eos_out)
2213 *eos_out = NULL;
2215 if (router_get_networkstatus_v3_hash(s, ns_digest)) {
2216 log_warn(LD_DIR, "Unable to compute digest of network-status");
2217 goto err;
2220 area = memarea_new();
2221 end_of_header = find_start_of_next_routerstatus(s);
2222 if (tokenize_string(area, s, end_of_header, tokens,
2223 (ns_type == NS_TYPE_CONSENSUS) ?
2224 networkstatus_consensus_token_table :
2225 networkstatus_token_table, 0)) {
2226 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2227 goto err;
2230 ns = tor_malloc_zero(sizeof(networkstatus_t));
2231 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2233 if (ns_type != NS_TYPE_CONSENSUS) {
2234 const char *end_of_cert = NULL;
2235 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2236 goto err;
2237 ++cert;
2238 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2239 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2240 goto err;
2243 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2244 tor_assert(tok->n_args);
2245 if (!strcmp(tok->args[0], "vote")) {
2246 ns->type = NS_TYPE_VOTE;
2247 } else if (!strcmp(tok->args[0], "consensus")) {
2248 ns->type = NS_TYPE_CONSENSUS;
2249 } else if (!strcmp(tok->args[0], "opinion")) {
2250 ns->type = NS_TYPE_OPINION;
2251 } else {
2252 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2253 escaped(tok->args[0]));
2254 goto err;
2256 if (ns_type != ns->type) {
2257 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2258 goto err;
2261 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2262 tok = find_by_keyword(tokens, K_PUBLISHED);
2263 if (parse_iso_time(tok->args[0], &ns->published))
2264 goto err;
2266 ns->supported_methods = smartlist_create();
2267 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2268 if (tok) {
2269 for (i=0; i < tok->n_args; ++i)
2270 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2271 } else {
2272 smartlist_add(ns->supported_methods, tor_strdup("1"));
2274 } else {
2275 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2276 if (tok) {
2277 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2278 &ok, NULL);
2279 if (!ok)
2280 goto err;
2281 } else {
2282 ns->consensus_method = 1;
2286 tok = find_by_keyword(tokens, K_VALID_AFTER);
2287 if (parse_iso_time(tok->args[0], &ns->valid_after))
2288 goto err;
2290 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2291 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2292 goto err;
2294 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2295 if (parse_iso_time(tok->args[0], &ns->valid_until))
2296 goto err;
2298 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2299 tor_assert(tok->n_args >= 2);
2300 ns->vote_seconds =
2301 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2302 if (!ok)
2303 goto err;
2304 ns->dist_seconds =
2305 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2306 if (!ok)
2307 goto err;
2308 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2309 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2310 goto err;
2312 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2313 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2314 goto err;
2316 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2317 log_warn(LD_DIR, "Vote seconds is too short");
2318 goto err;
2320 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2321 log_warn(LD_DIR, "Dist seconds is too short");
2322 goto err;
2325 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2326 ns->client_versions = tor_strdup(tok->args[0]);
2328 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2329 ns->server_versions = tor_strdup(tok->args[0]);
2332 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2333 ns->known_flags = smartlist_create();
2334 inorder = 1;
2335 for (i = 0; i < tok->n_args; ++i) {
2336 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2337 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2338 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2339 inorder = 0;
2342 if (!inorder) {
2343 log_warn(LD_DIR, "known-flags not in order");
2344 goto err;
2347 tok = find_opt_by_keyword(tokens, K_PARAMS);
2348 if (tok) {
2349 inorder = 1;
2350 ns->net_params = smartlist_create();
2351 for (i = 0; i < tok->n_args; ++i) {
2352 int ok=0;
2353 char *eq = strchr(tok->args[i], '=');
2354 if (!eq) {
2355 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2356 goto err;
2358 tor_parse_long(eq+1, 10, INT32_MIN, INT32_MAX, &ok, NULL);
2359 if (!ok) {
2360 log_warn(LD_DIR, "Bad element '%s' in params", escaped(tok->args[i]));
2361 goto err;
2363 if (i > 0 && strcmp(tok->args[i-1], tok->args[i]) >= 0) {
2364 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2365 inorder = 0;
2367 smartlist_add(ns->net_params, tor_strdup(tok->args[i]));
2369 if (!inorder) {
2370 log_warn(LD_DIR, "params not in order");
2371 goto err;
2375 ns->voters = smartlist_create();
2377 SMARTLIST_FOREACH_BEGIN(tokens, directory_token_t *, _tok) {
2378 tok = _tok;
2379 if (tok->tp == K_DIR_SOURCE) {
2380 tor_assert(tok->n_args >= 6);
2382 if (voter)
2383 smartlist_add(ns->voters, voter);
2384 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2385 if (ns->type != NS_TYPE_CONSENSUS)
2386 memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
2388 voter->nickname = tor_strdup(tok->args[0]);
2389 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2390 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2391 tok->args[1], HEX_DIGEST_LEN) < 0) {
2392 log_warn(LD_DIR, "Error decoding identity digest %s in "
2393 "network-status vote.", escaped(tok->args[1]));
2394 goto err;
2396 if (ns->type != NS_TYPE_CONSENSUS &&
2397 memcmp(ns->cert->cache_info.identity_digest,
2398 voter->identity_digest, DIGEST_LEN)) {
2399 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2400 goto err;
2402 voter->address = tor_strdup(tok->args[2]);
2403 if (!tor_inet_aton(tok->args[3], &in)) {
2404 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2405 escaped(tok->args[3]));
2406 goto err;
2408 voter->addr = ntohl(in.s_addr);
2409 voter->dir_port = (uint16_t)
2410 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2411 if (!ok)
2412 goto err;
2413 voter->or_port = (uint16_t)
2414 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2415 if (!ok)
2416 goto err;
2417 } else if (tok->tp == K_CONTACT) {
2418 if (!voter || voter->contact) {
2419 log_warn(LD_DIR, "contact element is out of place.");
2420 goto err;
2422 voter->contact = tor_strdup(tok->args[0]);
2423 } else if (tok->tp == K_VOTE_DIGEST) {
2424 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2425 tor_assert(tok->n_args >= 1);
2426 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2427 log_warn(LD_DIR, "vote-digest element is out of place.");
2428 goto err;
2430 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2431 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2432 tok->args[0], HEX_DIGEST_LEN) < 0) {
2433 log_warn(LD_DIR, "Error decoding vote digest %s in "
2434 "network-status consensus.", escaped(tok->args[0]));
2435 goto err;
2438 } SMARTLIST_FOREACH_END(_tok);
2439 if (voter) {
2440 smartlist_add(ns->voters, voter);
2441 voter = NULL;
2443 if (smartlist_len(ns->voters) == 0) {
2444 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2445 goto err;
2446 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
2447 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2448 goto err;
2451 if (ns->type != NS_TYPE_CONSENSUS &&
2452 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
2453 int bad = 1;
2454 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2455 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
2456 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
2457 tok->args[0], HEX_DIGEST_LEN)<0)
2458 bad = 1;
2459 else
2460 bad = 0;
2462 if (bad) {
2463 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
2464 escaped(tok->args[0]));
2468 /* Parse routerstatus lines. */
2469 rs_tokens = smartlist_create();
2470 rs_area = memarea_new();
2471 s = end_of_header;
2472 ns->routerstatus_list = smartlist_create();
2474 while (!strcmpstart(s, "r ")) {
2475 if (ns->type != NS_TYPE_CONSENSUS) {
2476 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2477 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
2478 rs, 0))
2479 smartlist_add(ns->routerstatus_list, rs);
2480 else {
2481 tor_free(rs->version);
2482 tor_free(rs);
2484 } else {
2485 routerstatus_t *rs;
2486 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
2487 NULL, NULL,
2488 ns->consensus_method)))
2489 smartlist_add(ns->routerstatus_list, rs);
2492 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2493 routerstatus_t *rs1, *rs2;
2494 if (ns->type != NS_TYPE_CONSENSUS) {
2495 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2496 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2497 rs1 = &a->status; rs2 = &b->status;
2498 } else {
2499 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2500 rs2 = smartlist_get(ns->routerstatus_list, i);
2502 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
2503 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2504 "digest");
2505 goto err;
2509 /* Parse footer; check signature. */
2510 footer_tokens = smartlist_create();
2511 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2512 ++end_of_footer;
2513 else
2514 end_of_footer = s + strlen(s);
2515 if (tokenize_string(area,s, end_of_footer, footer_tokens,
2516 networkstatus_vote_footer_token_table, 0)) {
2517 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2518 goto err;
2521 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
2523 char declared_identity[DIGEST_LEN];
2524 networkstatus_voter_info_t *v;
2525 tok = _tok;
2526 if (tok->tp != K_DIRECTORY_SIGNATURE)
2527 continue;
2528 tor_assert(tok->n_args >= 2);
2530 if (!tok->object_type ||
2531 strcmp(tok->object_type, "SIGNATURE") ||
2532 tok->object_size < 128 || tok->object_size > 512) {
2533 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2534 goto err;
2537 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2538 base16_decode(declared_identity, sizeof(declared_identity),
2539 tok->args[0], HEX_DIGEST_LEN) < 0) {
2540 log_warn(LD_DIR, "Error decoding declared identity %s in "
2541 "network-status vote.", escaped(tok->args[0]));
2542 goto err;
2544 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2545 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2546 "any declared directory source.");
2547 goto err;
2549 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2550 base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
2551 tok->args[1], HEX_DIGEST_LEN) < 0) {
2552 log_warn(LD_DIR, "Error decoding declared digest %s in "
2553 "network-status vote.", escaped(tok->args[1]));
2554 goto err;
2557 if (ns->type != NS_TYPE_CONSENSUS) {
2558 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
2559 DIGEST_LEN)) {
2560 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2561 "network-status vote.");
2562 goto err;
2566 if (ns->type != NS_TYPE_CONSENSUS) {
2567 if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
2568 "network-status vote"))
2569 goto err;
2570 v->good_signature = 1;
2571 } else {
2572 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING)
2573 goto err;
2574 /* We already parsed a vote from this voter. Use the first one. */
2575 if (v->signature) {
2576 log_fn(LOG_PROTOCOL_WARN, LD_DIR, "We received a networkstatus "
2577 "that contains two votes from the same voter. Ignoring "
2578 "the second vote.");
2579 continue;
2582 v->signature = tor_memdup(tok->object_body, tok->object_size);
2583 v->signature_len = (int) tok->object_size;
2585 ++n_signatures;
2588 if (! n_signatures) {
2589 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2590 goto err;
2593 if (eos_out)
2594 *eos_out = end_of_footer;
2596 goto done;
2597 err:
2598 if (ns)
2599 networkstatus_vote_free(ns);
2600 ns = NULL;
2601 done:
2602 if (tokens) {
2603 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2604 smartlist_free(tokens);
2606 if (voter) {
2607 tor_free(voter->nickname);
2608 tor_free(voter->address);
2609 tor_free(voter->contact);
2610 tor_free(voter->signature);
2611 tor_free(voter);
2613 if (rs_tokens) {
2614 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
2615 smartlist_free(rs_tokens);
2617 if (footer_tokens) {
2618 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2619 smartlist_free(footer_tokens);
2621 if (area) {
2622 DUMP_AREA(area, "v3 networkstatus");
2623 memarea_drop_all(area);
2625 if (rs_area)
2626 memarea_drop_all(rs_area);
2628 return ns;
2631 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2632 * <b>eos</b> and return the result. Return -1 on failure. */
2633 ns_detached_signatures_t *
2634 networkstatus_parse_detached_signatures(const char *s, const char *eos)
2636 /* XXXX there is too much duplicate shared between this function and
2637 * networkstatus_parse_vote_from_string(). */
2638 directory_token_t *tok;
2639 memarea_t *area = NULL;
2641 smartlist_t *tokens = smartlist_create();
2642 ns_detached_signatures_t *sigs =
2643 tor_malloc_zero(sizeof(ns_detached_signatures_t));
2645 if (!eos)
2646 eos = s + strlen(s);
2648 area = memarea_new();
2649 if (tokenize_string(area,s, eos, tokens,
2650 networkstatus_detached_signature_token_table, 0)) {
2651 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
2652 goto err;
2655 tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST);
2656 if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
2657 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
2658 "networkstatus signatures");
2659 goto err;
2661 if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
2662 tok->args[0], strlen(tok->args[0])) < 0) {
2663 log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
2664 "networkstatus signatures");
2665 goto err;
2668 tok = find_by_keyword(tokens, K_VALID_AFTER);
2669 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
2670 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
2671 goto err;
2674 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2675 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
2676 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
2677 goto err;
2680 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2681 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
2682 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
2683 goto err;
2686 sigs->signatures = smartlist_create();
2687 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2689 char id_digest[DIGEST_LEN];
2690 char sk_digest[DIGEST_LEN];
2691 networkstatus_voter_info_t *voter;
2693 tok = _tok;
2694 if (tok->tp != K_DIRECTORY_SIGNATURE)
2695 continue;
2696 tor_assert(tok->n_args >= 2);
2698 if (!tok->object_type ||
2699 strcmp(tok->object_type, "SIGNATURE") ||
2700 tok->object_size < 128 || tok->object_size > 512) {
2701 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2702 goto err;
2705 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2706 base16_decode(id_digest, sizeof(id_digest),
2707 tok->args[0], HEX_DIGEST_LEN) < 0) {
2708 log_warn(LD_DIR, "Error decoding declared identity %s in "
2709 "network-status vote.", escaped(tok->args[0]));
2710 goto err;
2712 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2713 base16_decode(sk_digest, sizeof(sk_digest),
2714 tok->args[1], HEX_DIGEST_LEN) < 0) {
2715 log_warn(LD_DIR, "Error decoding declared digest %s in "
2716 "network-status vote.", escaped(tok->args[1]));
2717 goto err;
2720 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2721 memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
2722 memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
2723 if (tok->object_size >= INT_MAX || tok->object_size >= SIZE_T_CEILING)
2724 goto err;
2725 voter->signature = tor_memdup(tok->object_body, tok->object_size);
2726 voter->signature_len = (int) tok->object_size;
2728 smartlist_add(sigs->signatures, voter);
2731 goto done;
2732 err:
2733 ns_detached_signatures_free(sigs);
2734 sigs = NULL;
2735 done:
2736 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2737 smartlist_free(tokens);
2738 if (area) {
2739 DUMP_AREA(area, "detached signatures");
2740 memarea_drop_all(area);
2742 return sigs;
2745 /** Parse the addr policy in the string <b>s</b> and return it. If
2746 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2747 * ADDR_POLICY_REJECT) for items that specify no action.
2749 addr_policy_t *
2750 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
2752 directory_token_t *tok = NULL;
2753 const char *cp, *eos;
2754 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2755 * But note that there can be an arbitrary amount of space between the
2756 * accept and the address:mask/port element. */
2757 char line[TOR_ADDR_BUF_LEN*2 + 32];
2758 addr_policy_t *r;
2759 memarea_t *area = NULL;
2761 s = eat_whitespace(s);
2762 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
2763 if (tor_snprintf(line, sizeof(line), "%s %s",
2764 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
2765 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
2766 return NULL;
2768 cp = line;
2769 tor_strlower(line);
2770 } else { /* assume an already well-formed address policy line */
2771 cp = s;
2774 eos = cp + strlen(cp);
2775 area = memarea_new();
2776 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
2777 if (tok->tp == _ERR) {
2778 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
2779 goto err;
2781 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
2782 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
2783 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
2784 goto err;
2787 r = router_parse_addr_policy(tok);
2788 goto done;
2789 err:
2790 r = NULL;
2791 done:
2792 token_free(tok);
2793 if (area) {
2794 DUMP_AREA(area, "policy item");
2795 memarea_drop_all(area);
2797 return r;
2800 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2801 * <b>router</b>. Return 0 on success, -1 on failure. */
2802 static int
2803 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
2805 addr_policy_t *newe;
2806 newe = router_parse_addr_policy(tok);
2807 if (!newe)
2808 return -1;
2809 if (! router->exit_policy)
2810 router->exit_policy = smartlist_create();
2812 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
2813 tor_addr_family(&newe->addr) == AF_INET)
2815 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
2816 tor_addr_family(&newe->addr) == AF_INET6)) {
2817 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
2818 "policy");
2819 addr_policy_free(newe);
2820 return -1;
2823 smartlist_add(router->exit_policy, newe);
2825 return 0;
2828 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2829 * a new exit_policy_t corresponding to the token. */
2830 static addr_policy_t *
2831 router_parse_addr_policy(directory_token_t *tok)
2833 addr_policy_t newe;
2834 char *arg;
2836 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
2837 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
2839 if (tok->n_args != 1)
2840 return NULL;
2841 arg = tok->args[0];
2843 if (!strcmpstart(arg,"private"))
2844 return router_parse_addr_policy_private(tok);
2846 memset(&newe, 0, sizeof(newe));
2848 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2849 newe.policy_type = ADDR_POLICY_REJECT;
2850 else
2851 newe.policy_type = ADDR_POLICY_ACCEPT;
2853 if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
2854 &newe.prt_min, &newe.prt_max) < 0) {
2855 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
2856 return NULL;
2859 return addr_policy_get_canonical_entry(&newe);
2862 /** Parse an exit policy line of the format "accept/reject private:...".
2863 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2864 * router descriptors until earlier versions are obsolete.
2866 static addr_policy_t *
2867 router_parse_addr_policy_private(directory_token_t *tok)
2869 const char *arg;
2870 uint16_t port_min, port_max;
2871 addr_policy_t result;
2873 arg = tok->args[0];
2874 if (strcmpstart(arg, "private"))
2875 return NULL;
2877 arg += strlen("private");
2878 arg = (char*) eat_whitespace(arg);
2879 if (!arg || *arg != ':')
2880 return NULL;
2882 if (parse_port_range(arg+1, &port_min, &port_max)<0)
2883 return NULL;
2885 memset(&result, 0, sizeof(result));
2886 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2887 result.policy_type = ADDR_POLICY_REJECT;
2888 else
2889 result.policy_type = ADDR_POLICY_ACCEPT;
2890 result.is_private = 1;
2891 result.prt_min = port_min;
2892 result.prt_max = port_max;
2894 return addr_policy_get_canonical_entry(&result);
2897 /** Log and exit if <b>t</b> is malformed */
2898 void
2899 assert_addr_policy_ok(smartlist_t *lst)
2901 if (!lst) return;
2902 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
2903 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
2904 t->policy_type == ADDR_POLICY_ACCEPT);
2905 tor_assert(t->prt_min <= t->prt_max);
2910 * Low-level tokenizer for router descriptors and directories.
2913 /** Free all resources allocated for <b>tok</b> */
2914 static void
2915 token_free(directory_token_t *tok)
2917 tor_assert(tok);
2918 if (tok->key)
2919 crypto_free_pk_env(tok->key);
2922 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
2923 #define ALLOC(sz) memarea_alloc(area,sz)
2924 #define STRDUP(str) memarea_strdup(area,str)
2925 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
2927 #define RET_ERR(msg) \
2928 STMT_BEGIN \
2929 if (tok) token_free(tok); \
2930 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
2931 tok->tp = _ERR; \
2932 tok->error = STRDUP(msg); \
2933 goto done_tokenizing; \
2934 STMT_END
2936 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
2937 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
2938 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
2939 * conform to the syntax we wanted.
2941 static INLINE directory_token_t *
2942 token_check_object(memarea_t *area, const char *kwd,
2943 directory_token_t *tok, obj_syntax o_syn)
2945 char ebuf[128];
2946 switch (o_syn) {
2947 case NO_OBJ:
2948 /* No object is allowed for this token. */
2949 if (tok->object_body) {
2950 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
2951 RET_ERR(ebuf);
2953 if (tok->key) {
2954 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
2955 RET_ERR(ebuf);
2957 break;
2958 case NEED_OBJ:
2959 /* There must be a (non-key) object. */
2960 if (!tok->object_body) {
2961 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
2962 RET_ERR(ebuf);
2964 break;
2965 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
2966 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
2967 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
2968 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
2969 kwd, (int)crypto_pk_keysize(tok->key));
2970 RET_ERR(ebuf);
2972 /* fall through */
2973 case NEED_KEY: /* There must be some kind of key. */
2974 if (!tok->key) {
2975 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
2976 RET_ERR(ebuf);
2978 if (o_syn != NEED_SKEY_1024) {
2979 if (crypto_pk_key_is_private(tok->key)) {
2980 tor_snprintf(ebuf, sizeof(ebuf),
2981 "Private key given for %s, which wants a public key", kwd);
2982 RET_ERR(ebuf);
2984 } else { /* o_syn == NEED_SKEY_1024 */
2985 if (!crypto_pk_key_is_private(tok->key)) {
2986 tor_snprintf(ebuf, sizeof(ebuf),
2987 "Public key given for %s, which wants a private key", kwd);
2988 RET_ERR(ebuf);
2991 break;
2992 case OBJ_OK:
2993 /* Anything goes with this token. */
2994 break;
2997 done_tokenizing:
2998 return tok;
3001 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
3002 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
3003 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
3004 * all storage in <b>area</b>. Return the number of arguments parsed, or
3005 * return -1 if there was an insanely high number of arguments. */
3006 static INLINE int
3007 get_token_arguments(memarea_t *area, directory_token_t *tok,
3008 const char *s, const char *eol)
3010 /** Largest number of arguments we'll accept to any token, ever. */
3011 #define MAX_ARGS 512
3012 char *mem = memarea_strndup(area, s, eol-s);
3013 char *cp = mem;
3014 int j = 0;
3015 char *args[MAX_ARGS];
3016 while (*cp) {
3017 if (j == MAX_ARGS)
3018 return -1;
3019 args[j++] = cp;
3020 cp = (char*)find_whitespace(cp);
3021 if (!cp || !*cp)
3022 break; /* End of the line. */
3023 *cp++ = '\0';
3024 cp = (char*)eat_whitespace(cp);
3026 tok->n_args = j;
3027 tok->args = memarea_memdup(area, args, j*sizeof(char*));
3028 return j;
3029 #undef MAX_ARGS
3032 /** Helper function: read the next token from *s, advance *s to the end of the
3033 * token, and return the parsed token. Parse *<b>s</b> according to the list
3034 * of tokens in <b>table</b>.
3036 static directory_token_t *
3037 get_next_token(memarea_t *area,
3038 const char **s, const char *eos, token_rule_t *table)
3040 /** Reject any object at least this big; it is probably an overflow, an
3041 * attack, a bug, or some other nonsense. */
3042 #define MAX_UNPARSED_OBJECT_SIZE (128*1024)
3043 /** Reject any line at least this big; it is probably an overflow, an
3044 * attack, a bug, or some other nonsense. */
3045 #define MAX_LINE_LENGTH (128*1024)
3047 const char *next, *eol, *obstart;
3048 size_t obname_len;
3049 int i;
3050 directory_token_t *tok;
3051 obj_syntax o_syn = NO_OBJ;
3052 char ebuf[128];
3053 const char *kwd = "";
3055 tor_assert(area);
3056 tok = ALLOC_ZERO(sizeof(directory_token_t));
3057 tok->tp = _ERR;
3059 /* Set *s to first token, eol to end-of-line, next to after first token */
3060 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
3061 tor_assert(eos >= *s);
3062 eol = memchr(*s, '\n', eos-*s);
3063 if (!eol)
3064 eol = eos;
3065 if (eol - *s > MAX_LINE_LENGTH) {
3066 RET_ERR("Line far too long");
3069 next = find_whitespace_eos(*s, eol);
3071 if (!strcmp_len(*s, "opt", next-*s)) {
3072 /* Skip past an "opt" at the start of the line. */
3073 *s = eat_whitespace_eos_no_nl(next, eol);
3074 next = find_whitespace_eos(*s, eol);
3075 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
3076 RET_ERR("Unexpected EOF");
3079 /* Search the table for the appropriate entry. (I tried a binary search
3080 * instead, but it wasn't any faster.) */
3081 for (i = 0; table[i].t ; ++i) {
3082 if (!strcmp_len(*s, table[i].t, next-*s)) {
3083 /* We've found the keyword. */
3084 kwd = table[i].t;
3085 tok->tp = table[i].v;
3086 o_syn = table[i].os;
3087 *s = eat_whitespace_eos_no_nl(next, eol);
3088 /* We go ahead whether there are arguments or not, so that tok->args is
3089 * always set if we want arguments. */
3090 if (table[i].concat_args) {
3091 /* The keyword takes the line as a single argument */
3092 tok->args = ALLOC(sizeof(char*));
3093 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3094 tok->n_args = 1;
3095 } else {
3096 /* This keyword takes multiple arguments. */
3097 if (get_token_arguments(area, tok, *s, eol)<0) {
3098 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3099 RET_ERR(ebuf);
3101 *s = eol;
3103 if (tok->n_args < table[i].min_args) {
3104 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3105 RET_ERR(ebuf);
3106 } else if (tok->n_args > table[i].max_args) {
3107 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3108 RET_ERR(ebuf);
3110 break;
3114 if (tok->tp == _ERR) {
3115 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3116 if (**s == '@')
3117 tok->tp = _A_UNKNOWN;
3118 else
3119 tok->tp = K_OPT;
3120 tok->args = ALLOC(sizeof(char*));
3121 tok->args[0] = STRNDUP(*s, eol-*s);
3122 tok->n_args = 1;
3123 o_syn = OBJ_OK;
3126 /* Check whether there's an object present */
3127 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3128 tor_assert(eos >= *s);
3129 eol = memchr(*s, '\n', eos-*s);
3130 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3131 goto check_object;
3133 obstart = *s; /* Set obstart to start of object spec */
3134 if (*s+16 >= eol || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3135 strcmp_len(eol-5, "-----", 5) || /* nuls or invalid endings */
3136 (eol-*s) > MAX_UNPARSED_OBJECT_SIZE) { /* name too long */
3137 RET_ERR("Malformed object: bad begin line");
3139 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3140 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3141 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3143 /* Go to the end of the object */
3144 next = tor_memstr(*s, eos-*s, "-----END ");
3145 if (!next) {
3146 RET_ERR("Malformed object: missing object end line");
3148 tor_assert(eos >= next);
3149 eol = memchr(next, '\n', eos-next);
3150 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3151 eol = eos;
3152 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3153 if ((size_t)(eol-next) != 9+obname_len+5 ||
3154 strcmp_len(next+9, tok->object_type, obname_len) ||
3155 strcmp_len(eol-5, "-----", 5)) {
3156 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3157 tok->object_type);
3158 ebuf[sizeof(ebuf)-1] = '\0';
3159 RET_ERR(ebuf);
3161 if (next - *s > MAX_UNPARSED_OBJECT_SIZE)
3162 RET_ERR("Couldn't parse object: missing footer or object much too big.");
3164 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3165 tok->key = crypto_new_pk_env();
3166 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3167 RET_ERR("Couldn't parse public key.");
3168 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3169 tok->key = crypto_new_pk_env();
3170 if (crypto_pk_read_private_key_from_string(tok->key, obstart, eol-obstart))
3171 RET_ERR("Couldn't parse private key.");
3172 } else { /* If it's something else, try to base64-decode it */
3173 int r;
3174 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3175 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3176 if (r<0)
3177 RET_ERR("Malformed object: bad base64-encoded data");
3178 tok->object_size = r;
3180 *s = eol;
3182 check_object:
3183 tok = token_check_object(area, kwd, tok, o_syn);
3185 done_tokenizing:
3186 return tok;
3188 #undef RET_ERR
3189 #undef ALLOC
3190 #undef ALLOC_ZERO
3191 #undef STRDUP
3192 #undef STRNDUP
3195 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3196 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3197 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3198 * entire string.
3200 static int
3201 tokenize_string(memarea_t *area,
3202 const char *start, const char *end, smartlist_t *out,
3203 token_rule_t *table, int flags)
3205 const char **s;
3206 directory_token_t *tok = NULL;
3207 int counts[_NIL];
3208 int i;
3209 int first_nonannotation;
3210 int prev_len = smartlist_len(out);
3211 tor_assert(area);
3213 s = &start;
3214 if (!end)
3215 end = start+strlen(start);
3216 for (i = 0; i < _NIL; ++i)
3217 counts[i] = 0;
3219 SMARTLIST_FOREACH(out, const directory_token_t *, t, ++counts[t->tp]);
3221 while (*s < end && (!tok || tok->tp != _EOF)) {
3222 tok = get_next_token(area, s, end, table);
3223 if (tok->tp == _ERR) {
3224 log_warn(LD_DIR, "parse error: %s", tok->error);
3225 token_free(tok);
3226 return -1;
3228 ++counts[tok->tp];
3229 smartlist_add(out, tok);
3230 *s = eat_whitespace_eos(*s, end);
3233 if (flags & TS_NOCHECK)
3234 return 0;
3236 if ((flags & TS_ANNOTATIONS_OK)) {
3237 first_nonannotation = -1;
3238 for (i = 0; i < smartlist_len(out); ++i) {
3239 tok = smartlist_get(out, i);
3240 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
3241 first_nonannotation = i;
3242 break;
3245 if (first_nonannotation < 0) {
3246 log_warn(LD_DIR, "parse error: item contains only annotations");
3247 return -1;
3249 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
3250 tok = smartlist_get(out, i);
3251 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3252 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
3253 return -1;
3256 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
3257 if (first_nonannotation != prev_len) {
3258 log_warn(LD_DIR, "parse error: Unexpected annotations.");
3259 return -1;
3262 } else {
3263 for (i=0; i < smartlist_len(out); ++i) {
3264 tok = smartlist_get(out, i);
3265 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3266 log_warn(LD_DIR, "parse error: no annotations allowed.");
3267 return -1;
3270 first_nonannotation = 0;
3272 for (i = 0; table[i].t; ++i) {
3273 if (counts[table[i].v] < table[i].min_cnt) {
3274 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
3275 return -1;
3277 if (counts[table[i].v] > table[i].max_cnt) {
3278 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
3279 return -1;
3281 if (table[i].pos & AT_START) {
3282 if (smartlist_len(out) < 1 ||
3283 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
3284 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
3285 return -1;
3288 if (table[i].pos & AT_END) {
3289 if (smartlist_len(out) < 1 ||
3290 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
3291 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
3292 return -1;
3296 return 0;
3299 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3300 * NULL if no such keyword is found.
3302 static directory_token_t *
3303 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
3305 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
3306 return NULL;
3309 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3310 * with an assert if no such keyword is found.
3312 static directory_token_t *
3313 _find_by_keyword(smartlist_t *s, directory_keyword keyword,
3314 const char *keyword_as_string)
3316 directory_token_t *tok = find_opt_by_keyword(s, keyword);
3317 if (PREDICT_UNLIKELY(!tok)) {
3318 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
3319 "been validated. Internal error.", keyword_as_string, (int)keyword);
3320 tor_assert(tok);
3322 return tok;
3325 /** Return a newly allocated smartlist of all accept or reject tokens in
3326 * <b>s</b>.
3328 static smartlist_t *
3329 find_all_exitpolicy(smartlist_t *s)
3331 smartlist_t *out = smartlist_create();
3332 SMARTLIST_FOREACH(s, directory_token_t *, t,
3333 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
3334 t->tp == K_REJECT || t->tp == K_REJECT6)
3335 smartlist_add(out,t));
3336 return out;
3339 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
3340 * occurrence of <b>start_str</b> through the first instance of c after the
3341 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
3342 * <b>digest</b>; return 0 on success.
3344 * If no such substring exists, return -1.
3346 static int
3347 router_get_hash_impl(const char *s, size_t s_len, char *digest,
3348 const char *start_str,
3349 const char *end_str, char end_c)
3351 const char *start, *end;
3352 start = tor_memstr(s, s_len, start_str);
3353 if (!start) {
3354 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
3355 return -1;
3357 if (start != s && *(start-1) != '\n') {
3358 log_warn(LD_DIR,
3359 "first occurrence of \"%s\" is not at the start of a line",
3360 start_str);
3361 return -1;
3363 end = tor_memstr(start+strlen(start_str),
3364 s_len - (start-s) - strlen(start_str), end_str);
3365 if (!end) {
3366 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
3367 return -1;
3369 end = memchr(end+strlen(end_str), end_c, s_len - (end-s) - strlen(end_str));
3370 if (!end) {
3371 log_warn(LD_DIR,"couldn't find EOL");
3372 return -1;
3374 ++end;
3376 if (crypto_digest(digest, start, end-start)) {
3377 log_warn(LD_BUG,"couldn't compute digest");
3378 return -1;
3381 return 0;
3384 /** Parse the Tor version of the platform string <b>platform</b>,
3385 * and compare it to the version in <b>cutoff</b>. Return 1 if
3386 * the router is at least as new as the cutoff, else return 0.
3389 tor_version_as_new_as(const char *platform, const char *cutoff)
3391 tor_version_t cutoff_version, router_version;
3392 char *s, *s2, *start;
3393 char tmp[128];
3395 tor_assert(platform);
3397 if (tor_version_parse(cutoff, &cutoff_version)<0) {
3398 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
3399 return 0;
3401 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
3402 return 1;
3404 start = (char *)eat_whitespace(platform+3);
3405 if (!*start) return 0;
3406 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
3407 s2 = (char*)eat_whitespace(s);
3408 if (!strcmpstart(s2, "(r"))
3409 s = (char*)find_whitespace(s2);
3411 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
3412 return 0;
3413 strlcpy(tmp, start, s-start+1);
3415 if (tor_version_parse(tmp, &router_version)<0) {
3416 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
3417 return 1; /* be safe and say yes */
3420 /* Here's why we don't need to do any special handling for svn revisions:
3421 * - If neither has an svn revision, we're fine.
3422 * - If the router doesn't have an svn revision, we can't assume that it
3423 * is "at least" any svn revision, so we need to return 0.
3424 * - If the target version doesn't have an svn revision, any svn revision
3425 * (or none at all) is good enough, so return 1.
3426 * - If both target and router have an svn revision, we compare them.
3429 return tor_version_compare(&router_version, &cutoff_version) >= 0;
3432 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3433 * Return 0 on success, -1 on failure. */
3435 tor_version_parse(const char *s, tor_version_t *out)
3437 char *eos=NULL;
3438 const char *cp=NULL;
3439 /* Format is:
3440 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3442 tor_assert(s);
3443 tor_assert(out);
3445 memset(out, 0, sizeof(tor_version_t));
3447 if (!strcasecmpstart(s, "Tor "))
3448 s += 4;
3450 /* Get major. */
3451 out->major = (int)strtol(s,&eos,10);
3452 if (!eos || eos==s || *eos != '.') return -1;
3453 cp = eos+1;
3455 /* Get minor */
3456 out->minor = (int) strtol(cp,&eos,10);
3457 if (!eos || eos==cp || *eos != '.') return -1;
3458 cp = eos+1;
3460 /* Get micro */
3461 out->micro = (int) strtol(cp,&eos,10);
3462 if (!eos || eos==cp) return -1;
3463 if (!*eos) {
3464 out->status = VER_RELEASE;
3465 out->patchlevel = 0;
3466 return 0;
3468 cp = eos;
3470 /* Get status */
3471 if (*cp == '.') {
3472 out->status = VER_RELEASE;
3473 ++cp;
3474 } else if (0==strncmp(cp, "pre", 3)) {
3475 out->status = VER_PRE;
3476 cp += 3;
3477 } else if (0==strncmp(cp, "rc", 2)) {
3478 out->status = VER_RC;
3479 cp += 2;
3480 } else {
3481 return -1;
3484 /* Get patchlevel */
3485 out->patchlevel = (int) strtol(cp,&eos,10);
3486 if (!eos || eos==cp) return -1;
3487 cp = eos;
3489 /* Get status tag. */
3490 if (*cp == '-' || *cp == '.')
3491 ++cp;
3492 eos = (char*) find_whitespace(cp);
3493 if (eos-cp >= (int)sizeof(out->status_tag))
3494 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
3495 else {
3496 memcpy(out->status_tag, cp, eos-cp);
3497 out->status_tag[eos-cp] = 0;
3499 cp = eat_whitespace(eos);
3501 if (!strcmpstart(cp, "(r")) {
3502 cp += 2;
3503 out->svn_revision = (int) strtol(cp,&eos,10);
3506 return 0;
3509 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3510 * b. */
3512 tor_version_compare(tor_version_t *a, tor_version_t *b)
3514 int i;
3515 tor_assert(a);
3516 tor_assert(b);
3517 if ((i = a->major - b->major))
3518 return i;
3519 else if ((i = a->minor - b->minor))
3520 return i;
3521 else if ((i = a->micro - b->micro))
3522 return i;
3523 else if ((i = a->status - b->status))
3524 return i;
3525 else if ((i = a->patchlevel - b->patchlevel))
3526 return i;
3527 else if ((i = strcmp(a->status_tag, b->status_tag)))
3528 return i;
3529 else
3530 return a->svn_revision - b->svn_revision;
3533 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3535 static int
3536 tor_version_same_series(tor_version_t *a, tor_version_t *b)
3538 tor_assert(a);
3539 tor_assert(b);
3540 return ((a->major == b->major) &&
3541 (a->minor == b->minor) &&
3542 (a->micro == b->micro));
3545 /** Helper: Given pointers to two strings describing tor versions, return -1
3546 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
3547 * Used to sort a list of versions. */
3548 static int
3549 _compare_tor_version_str_ptr(const void **_a, const void **_b)
3551 const char *a = *_a, *b = *_b;
3552 int ca, cb;
3553 tor_version_t va, vb;
3554 ca = tor_version_parse(a, &va);
3555 cb = tor_version_parse(b, &vb);
3556 /* If they both parse, compare them. */
3557 if (!ca && !cb)
3558 return tor_version_compare(&va,&vb);
3559 /* If one parses, it comes first. */
3560 if (!ca && cb)
3561 return -1;
3562 if (ca && !cb)
3563 return 1;
3564 /* If neither parses, compare strings. Also, the directory server admin
3565 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3566 return strcmp(a,b);
3569 /** Sort a list of string-representations of versions in ascending order. */
3570 void
3571 sort_version_list(smartlist_t *versions, int remove_duplicates)
3573 smartlist_sort(versions, _compare_tor_version_str_ptr);
3575 if (remove_duplicates)
3576 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
3579 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3580 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3581 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3582 * encrypted introduction points to the newly allocated
3583 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3584 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3585 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3586 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3587 * and -1 for failure.
3590 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
3591 char *desc_id_out,
3592 char **intro_points_encrypted_out,
3593 size_t *intro_points_encrypted_size_out,
3594 size_t *encoded_size_out,
3595 const char **next_out, const char *desc)
3597 rend_service_descriptor_t *result =
3598 tor_malloc_zero(sizeof(rend_service_descriptor_t));
3599 char desc_hash[DIGEST_LEN];
3600 const char *eos;
3601 smartlist_t *tokens = smartlist_create();
3602 directory_token_t *tok;
3603 char secret_id_part[DIGEST_LEN];
3604 int i, version, num_ok=1;
3605 smartlist_t *versions;
3606 char public_key_hash[DIGEST_LEN];
3607 char test_desc_id[DIGEST_LEN];
3608 memarea_t *area = NULL;
3609 tor_assert(desc);
3610 /* Check if desc starts correctly. */
3611 if (strncmp(desc, "rendezvous-service-descriptor ",
3612 strlen("rendezvous-service-descriptor "))) {
3613 log_info(LD_REND, "Descriptor does not start correctly.");
3614 goto err;
3616 /* Compute descriptor hash for later validation. */
3617 if (router_get_hash_impl(desc, strlen(desc), desc_hash,
3618 "rendezvous-service-descriptor ",
3619 "\nsignature", '\n') < 0) {
3620 log_warn(LD_REND, "Couldn't compute descriptor hash.");
3621 goto err;
3623 /* Determine end of string. */
3624 eos = strstr(desc, "\nrendezvous-service-descriptor ");
3625 if (!eos)
3626 eos = desc + strlen(desc);
3627 else
3628 eos = eos + 1;
3629 /* Check length. */
3630 if (strlen(desc) > REND_DESC_MAX_SIZE) {
3631 log_warn(LD_REND, "Descriptor length is %i which exceeds "
3632 "maximum rendezvous descriptor size of %i kilobytes.",
3633 (int)strlen(desc), REND_DESC_MAX_SIZE);
3634 goto err;
3636 /* Tokenize descriptor. */
3637 area = memarea_new();
3638 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
3639 log_warn(LD_REND, "Error tokenizing descriptor.");
3640 goto err;
3642 /* Set next to next descriptor, if available. */
3643 *next_out = eos;
3644 /* Set length of encoded descriptor. */
3645 *encoded_size_out = eos - desc;
3646 /* Check min allowed length of token list. */
3647 if (smartlist_len(tokens) < 7) {
3648 log_warn(LD_REND, "Impossibly short descriptor.");
3649 goto err;
3651 /* Parse base32-encoded descriptor ID. */
3652 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
3653 tor_assert(tok == smartlist_get(tokens, 0));
3654 tor_assert(tok->n_args == 1);
3655 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
3656 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
3657 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
3658 goto err;
3660 if (base32_decode(desc_id_out, DIGEST_LEN,
3661 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
3662 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
3663 tok->args[0]);
3664 goto err;
3666 /* Parse descriptor version. */
3667 tok = find_by_keyword(tokens, R_VERSION);
3668 tor_assert(tok->n_args == 1);
3669 result->version =
3670 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
3671 if (result->version != 2 || !num_ok) {
3672 /* If it's <2, it shouldn't be under this format. If the number
3673 * is greater than 2, we bumped it because we broke backward
3674 * compatibility. See how version numbers in our other formats
3675 * work. */
3676 log_warn(LD_REND, "Unrecognized descriptor version: %s",
3677 escaped(tok->args[0]));
3678 goto err;
3680 /* Parse public key. */
3681 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
3682 result->pk = tok->key;
3683 tok->key = NULL; /* Prevent free */
3684 /* Parse secret ID part. */
3685 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
3686 tor_assert(tok->n_args == 1);
3687 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
3688 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
3689 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
3690 goto err;
3692 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
3693 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
3694 tok->args[0]);
3695 goto err;
3697 /* Parse publication time -- up-to-date check is done when storing the
3698 * descriptor. */
3699 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
3700 tor_assert(tok->n_args == 1);
3701 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
3702 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
3703 goto err;
3705 /* Parse protocol versions. */
3706 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
3707 tor_assert(tok->n_args == 1);
3708 versions = smartlist_create();
3709 smartlist_split_string(versions, tok->args[0], ",",
3710 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3711 for (i = 0; i < smartlist_len(versions); i++) {
3712 version = (int) tor_parse_long(smartlist_get(versions, i),
3713 10, 0, INT_MAX, &num_ok, NULL);
3714 if (!num_ok) /* It's a string; let's ignore it. */
3715 continue;
3716 result->protocols |= 1 << version;
3718 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
3719 smartlist_free(versions);
3720 /* Parse encrypted introduction points. Don't verify. */
3721 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
3722 if (tok) {
3723 if (strcmp(tok->object_type, "MESSAGE")) {
3724 log_warn(LD_DIR, "Bad object type: introduction points should be of "
3725 "type MESSAGE");
3726 goto err;
3728 *intro_points_encrypted_out = tor_memdup(tok->object_body,
3729 tok->object_size);
3730 *intro_points_encrypted_size_out = tok->object_size;
3731 } else {
3732 *intro_points_encrypted_out = NULL;
3733 *intro_points_encrypted_size_out = 0;
3735 /* Parse and verify signature. */
3736 tok = find_by_keyword(tokens, R_SIGNATURE);
3737 note_crypto_pk_op(VERIFY_RTR);
3738 if (check_signature_token(desc_hash, tok, result->pk, 0,
3739 "v2 rendezvous service descriptor") < 0)
3740 goto err;
3741 /* Verify that descriptor ID belongs to public key and secret ID part. */
3742 crypto_pk_get_digest(result->pk, public_key_hash);
3743 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
3744 secret_id_part);
3745 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
3746 log_warn(LD_REND, "Parsed descriptor ID does not match "
3747 "computed descriptor ID.");
3748 goto err;
3750 goto done;
3751 err:
3752 if (result)
3753 rend_service_descriptor_free(result);
3754 result = NULL;
3755 done:
3756 if (tokens) {
3757 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3758 smartlist_free(tokens);
3760 if (area)
3761 memarea_drop_all(area);
3762 *parsed_out = result;
3763 if (result)
3764 return 0;
3765 return -1;
3768 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
3769 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
3770 * write the result to a newly allocated string that is pointed to by
3771 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
3772 * Return 0 if decryption was successful and -1 otherwise. */
3774 rend_decrypt_introduction_points(char **ipos_decrypted,
3775 size_t *ipos_decrypted_size,
3776 const char *descriptor_cookie,
3777 const char *ipos_encrypted,
3778 size_t ipos_encrypted_size)
3780 tor_assert(ipos_encrypted);
3781 tor_assert(descriptor_cookie);
3782 if (ipos_encrypted_size < 2) {
3783 log_warn(LD_REND, "Size of encrypted introduction points is too "
3784 "small.");
3785 return -1;
3787 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
3788 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
3789 session_key[CIPHER_KEY_LEN], *dec;
3790 int declen, client_blocks;
3791 size_t pos = 0, len, client_entries_len;
3792 crypto_digest_env_t *digest;
3793 crypto_cipher_env_t *cipher;
3794 client_blocks = (int) ipos_encrypted[1];
3795 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
3796 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
3797 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
3798 log_warn(LD_REND, "Size of encrypted introduction points is too "
3799 "small.");
3800 return -1;
3802 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
3803 digest = crypto_new_digest_env();
3804 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
3805 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
3806 crypto_digest_get_digest(digest, client_id,
3807 REND_BASIC_AUTH_CLIENT_ID_LEN);
3808 crypto_free_digest_env(digest);
3809 for (pos = 2; pos < 2 + client_entries_len;
3810 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
3811 if (!memcmp(ipos_encrypted + pos, client_id,
3812 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
3813 /* Attempt to decrypt introduction points. */
3814 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3815 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
3816 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
3817 CIPHER_KEY_LEN) < 0) {
3818 log_warn(LD_REND, "Could not decrypt session key for client.");
3819 crypto_free_cipher_env(cipher);
3820 return -1;
3822 crypto_free_cipher_env(cipher);
3823 cipher = crypto_create_init_cipher(session_key, 0);
3824 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
3825 dec = tor_malloc(len);
3826 declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
3827 ipos_encrypted + 2 + client_entries_len,
3828 ipos_encrypted_size - 2 - client_entries_len);
3829 crypto_free_cipher_env(cipher);
3830 if (declen < 0) {
3831 log_warn(LD_REND, "Could not decrypt introduction point string.");
3832 tor_free(dec);
3833 return -1;
3835 if (memcmpstart(dec, declen, "introduction-point ")) {
3836 log_warn(LD_REND, "Decrypted introduction points don't "
3837 "look like we could parse them.");
3838 tor_free(dec);
3839 continue;
3841 *ipos_decrypted = dec;
3842 *ipos_decrypted_size = declen;
3843 return 0;
3846 log_warn(LD_REND, "Could not decrypt introduction points. Please "
3847 "check your authorization for this service!");
3848 return -1;
3849 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
3850 crypto_cipher_env_t *cipher;
3851 char *dec;
3852 int declen;
3853 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
3854 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3855 declen = crypto_cipher_decrypt_with_iv(cipher, dec,
3856 ipos_encrypted_size -
3857 CIPHER_IV_LEN - 1,
3858 ipos_encrypted + 1,
3859 ipos_encrypted_size - 1);
3860 crypto_free_cipher_env(cipher);
3861 if (declen < 0) {
3862 log_warn(LD_REND, "Decrypting introduction points failed!");
3863 tor_free(dec);
3864 return -1;
3866 *ipos_decrypted = dec;
3867 *ipos_decrypted_size = declen;
3868 return 0;
3869 } else {
3870 log_warn(LD_REND, "Unknown authorization type number: %d",
3871 ipos_encrypted[0]);
3872 return -1;
3876 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
3877 * length <b>intro_points_encoded_size</b> and write the result to the
3878 * descriptor in <b>parsed</b>; return the number of successfully parsed
3879 * introduction points or -1 in case of a failure. */
3881 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
3882 const char *intro_points_encoded,
3883 size_t intro_points_encoded_size)
3885 const char *current_ipo, *end_of_intro_points;
3886 smartlist_t *tokens;
3887 directory_token_t *tok;
3888 rend_intro_point_t *intro;
3889 extend_info_t *info;
3890 int result, num_ok=1;
3891 memarea_t *area = NULL;
3892 tor_assert(parsed);
3893 /** Function may only be invoked once. */
3894 tor_assert(!parsed->intro_nodes);
3895 tor_assert(intro_points_encoded);
3896 tor_assert(intro_points_encoded_size > 0);
3897 /* Consider one intro point after the other. */
3898 current_ipo = intro_points_encoded;
3899 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
3900 tokens = smartlist_create();
3901 parsed->intro_nodes = smartlist_create();
3902 area = memarea_new();
3904 while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
3905 "introduction-point ")) {
3906 /* Determine end of string. */
3907 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
3908 "\nintroduction-point ");
3909 if (!eos)
3910 eos = end_of_intro_points;
3911 else
3912 eos = eos+1;
3913 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
3914 /* Free tokens and clear token list. */
3915 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3916 smartlist_clear(tokens);
3917 memarea_clear(area);
3918 /* Tokenize string. */
3919 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
3920 log_warn(LD_REND, "Error tokenizing introduction point");
3921 goto err;
3923 /* Advance to next introduction point, if available. */
3924 current_ipo = eos;
3925 /* Check minimum allowed length of introduction point. */
3926 if (smartlist_len(tokens) < 5) {
3927 log_warn(LD_REND, "Impossibly short introduction point.");
3928 goto err;
3930 /* Allocate new intro point and extend info. */
3931 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3932 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
3933 /* Parse identifier. */
3934 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
3935 if (base32_decode(info->identity_digest, DIGEST_LEN,
3936 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
3937 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
3938 tok->args[0]);
3939 rend_intro_point_free(intro);
3940 goto err;
3942 /* Write identifier to nickname. */
3943 info->nickname[0] = '$';
3944 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
3945 info->identity_digest, DIGEST_LEN);
3946 /* Parse IP address. */
3947 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
3948 if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
3949 log_warn(LD_REND, "Could not parse introduction point address.");
3950 rend_intro_point_free(intro);
3951 goto err;
3953 if (tor_addr_family(&info->addr) != AF_INET) {
3954 log_warn(LD_REND, "Introduction point address was not ipv4.");
3955 rend_intro_point_free(intro);
3956 goto err;
3959 /* Parse onion port. */
3960 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
3961 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
3962 &num_ok,NULL);
3963 if (!info->port || !num_ok) {
3964 log_warn(LD_REND, "Introduction point onion port %s is invalid",
3965 escaped(tok->args[0]));
3966 rend_intro_point_free(intro);
3967 goto err;
3969 /* Parse onion key. */
3970 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
3971 info->onion_key = tok->key;
3972 tok->key = NULL; /* Prevent free */
3973 /* Parse service key. */
3974 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
3975 intro->intro_key = tok->key;
3976 tok->key = NULL; /* Prevent free */
3977 /* Add extend info to list of introduction points. */
3978 smartlist_add(parsed->intro_nodes, intro);
3980 result = smartlist_len(parsed->intro_nodes);
3981 goto done;
3983 err:
3984 result = -1;
3986 done:
3987 /* Free tokens and clear token list. */
3988 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3989 smartlist_free(tokens);
3990 if (area)
3991 memarea_drop_all(area);
3993 return result;
3996 /** Parse the content of a client_key file in <b>ckstr</b> and add
3997 * rend_authorized_client_t's for each parsed client to
3998 * <b>parsed_clients</b>. Return the number of parsed clients as result
3999 * or -1 for failure. */
4001 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
4003 int result = -1;
4004 smartlist_t *tokens;
4005 directory_token_t *tok;
4006 const char *current_entry = NULL;
4007 memarea_t *area = NULL;
4008 if (!ckstr || strlen(ckstr) == 0)
4009 return -1;
4010 tokens = smartlist_create();
4011 /* Begin parsing with first entry, skipping comments or whitespace at the
4012 * beginning. */
4013 area = memarea_new();
4014 current_entry = eat_whitespace(ckstr);
4015 while (!strcmpstart(current_entry, "client-name ")) {
4016 rend_authorized_client_t *parsed_entry;
4017 size_t len;
4018 char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
4019 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
4020 /* Determine end of string. */
4021 const char *eos = strstr(current_entry, "\nclient-name ");
4022 if (!eos)
4023 eos = current_entry + strlen(current_entry);
4024 else
4025 eos = eos + 1;
4026 /* Free tokens and clear token list. */
4027 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4028 smartlist_clear(tokens);
4029 memarea_clear(area);
4030 /* Tokenize string. */
4031 if (tokenize_string(area, current_entry, eos, tokens,
4032 client_keys_token_table, 0)) {
4033 log_warn(LD_REND, "Error tokenizing client keys file.");
4034 goto err;
4036 /* Advance to next entry, if available. */
4037 current_entry = eos;
4038 /* Check minimum allowed length of token list. */
4039 if (smartlist_len(tokens) < 2) {
4040 log_warn(LD_REND, "Impossibly short client key entry.");
4041 goto err;
4043 /* Parse client name. */
4044 tok = find_by_keyword(tokens, C_CLIENT_NAME);
4045 tor_assert(tok == smartlist_get(tokens, 0));
4046 tor_assert(tok->n_args == 1);
4048 len = strlen(tok->args[0]);
4049 if (len < 1 || len > 19 ||
4050 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
4051 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
4052 "between 1 and 19, and valid characters are "
4053 "[A-Za-z0-9+-_].)", tok->args[0]);
4054 goto err;
4056 /* Check if client name is duplicate. */
4057 if (strmap_get(parsed_clients, tok->args[0])) {
4058 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
4059 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
4060 goto err;
4062 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
4063 parsed_entry->client_name = tor_strdup(tok->args[0]);
4064 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
4065 /* Parse client key. */
4066 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
4067 if (tok) {
4068 parsed_entry->client_key = tok->key;
4069 tok->key = NULL; /* Prevent free */
4072 /* Parse descriptor cookie. */
4073 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
4074 tor_assert(tok->n_args == 1);
4075 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
4076 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
4077 escaped(tok->args[0]));
4078 goto err;
4080 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
4081 * because a base64 encoding of length 24 does not fit into 16 bytes in all
4082 * cases. */
4083 if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
4084 tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
4085 != REND_DESC_COOKIE_LEN)) {
4086 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
4087 "%s", descriptor_cookie_base64);
4088 goto err;
4090 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
4091 REND_DESC_COOKIE_LEN);
4093 result = strmap_size(parsed_clients);
4094 goto done;
4095 err:
4096 result = -1;
4097 done:
4098 /* Free tokens and clear token list. */
4099 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4100 smartlist_free(tokens);
4101 if (area)
4102 memarea_drop_all(area);
4103 return result;