Extact parse-the-token-arguments to its own function, and change it to a single-pass...
[tor/rransom.git] / src / or / routerparse.c
blobe0bbac003fc5db84f5664b7629d907c3292d8ece
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-2008, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 /* $Id$ */
7 const char routerparse_c_id[] =
8 "$Id$";
10 /**
11 * \file routerparse.c
12 * \brief Code to parse and validate router descriptors and directories.
13 **/
15 #include "or.h"
16 #include "memarea.h"
18 /****************************************************************************/
20 /** Enumeration of possible token types. The ones starting with K_ correspond
21 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
22 * is an end-of-file marker, and _NIL is used to encode not-a-token.
24 typedef enum {
25 K_ACCEPT = 0,
26 K_ACCEPT6,
27 K_DIRECTORY_SIGNATURE,
28 K_RECOMMENDED_SOFTWARE,
29 K_REJECT,
30 K_REJECT6,
31 K_ROUTER,
32 K_SIGNED_DIRECTORY,
33 K_SIGNING_KEY,
34 K_ONION_KEY,
35 K_ROUTER_SIGNATURE,
36 K_PUBLISHED,
37 K_RUNNING_ROUTERS,
38 K_ROUTER_STATUS,
39 K_PLATFORM,
40 K_OPT,
41 K_BANDWIDTH,
42 K_CONTACT,
43 K_NETWORK_STATUS,
44 K_UPTIME,
45 K_DIR_SIGNING_KEY,
46 K_FAMILY,
47 K_FINGERPRINT,
48 K_HIBERNATING,
49 K_READ_HISTORY,
50 K_WRITE_HISTORY,
51 K_NETWORK_STATUS_VERSION,
52 K_DIR_SOURCE,
53 K_DIR_OPTIONS,
54 K_CLIENT_VERSIONS,
55 K_SERVER_VERSIONS,
56 K_P,
57 K_R,
58 K_S,
59 K_V,
60 K_W,
61 K_EVENTDNS,
62 K_EXTRA_INFO,
63 K_EXTRA_INFO_DIGEST,
64 K_CACHES_EXTRA_INFO,
65 K_HIDDEN_SERVICE_DIR,
66 K_ALLOW_SINGLE_HOP_EXITS,
68 K_DIR_KEY_CERTIFICATE_VERSION,
69 K_DIR_IDENTITY_KEY,
70 K_DIR_KEY_PUBLISHED,
71 K_DIR_KEY_EXPIRES,
72 K_DIR_KEY_CERTIFICATION,
73 K_DIR_KEY_CROSSCERT,
74 K_DIR_ADDRESS,
76 K_VOTE_STATUS,
77 K_VALID_AFTER,
78 K_FRESH_UNTIL,
79 K_VALID_UNTIL,
80 K_VOTING_DELAY,
82 K_KNOWN_FLAGS,
83 K_VOTE_DIGEST,
84 K_CONSENSUS_DIGEST,
85 K_CONSENSUS_METHODS,
86 K_CONSENSUS_METHOD,
87 K_LEGACY_DIR_KEY,
89 A_PURPOSE,
90 _A_UNKNOWN,
92 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
93 R_VERSION,
94 R_PERMANENT_KEY,
95 R_SECRET_ID_PART,
96 R_PUBLICATION_TIME,
97 R_PROTOCOL_VERSIONS,
98 R_INTRODUCTION_POINTS,
99 R_SIGNATURE,
101 R_IPO_IDENTIFIER,
102 R_IPO_IP_ADDRESS,
103 R_IPO_ONION_PORT,
104 R_IPO_ONION_KEY,
105 R_IPO_SERVICE_KEY,
107 C_CLIENT_NAME,
108 C_DESCRIPTOR_COOKIE,
109 C_CLIENT_KEY,
111 _ERR,
112 _EOF,
113 _NIL
114 } directory_keyword;
116 #define MIN_ANNOTATION A_PURPOSE
117 #define MAX_ANNOTATION _A_UNKNOWN
119 /** Structure to hold a single directory token.
121 * We parse a directory by breaking it into "tokens", each consisting
122 * of a keyword, a line full of arguments, and a binary object. The
123 * arguments and object are both optional, depending on the keyword
124 * type.
126 * This structure is only allocated in memareas; do not allocate it on
127 * the heap, or token_free() won't work.
129 typedef struct directory_token_t {
130 directory_keyword tp; /**< Type of the token. */
131 int n_args:30; /**< Number of elements in args */
132 char **args; /**< Array of arguments from keyword line. */
134 char *object_type; /**< -----BEGIN [object_type]-----*/
135 size_t object_size; /**< Bytes in object_body */
136 char *object_body; /**< Contents of object, base64-decoded. */
138 crypto_pk_env_t *key; /**< For public keys only. Heap-allocated. */
140 char *error; /**< For _ERR tokens only. */
141 } directory_token_t;
143 /* ********************************************************************** */
145 /** We use a table of rules to decide how to parse each token type. */
147 /** Rules for whether the keyword needs an object. */
148 typedef enum {
149 NO_OBJ, /**< No object, ever. */
150 NEED_OBJ, /**< Object is required. */
151 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
152 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
153 NEED_KEY, /**< Object is required, and must be a public key. */
154 OBJ_OK, /**< Object is optional. */
155 } obj_syntax;
157 #define AT_START 1
158 #define AT_END 2
160 /** Determines the parsing rules for a single token type. */
161 typedef struct token_rule_t {
162 /** The string value of the keyword identifying the type of item. */
163 const char *t;
164 /** The corresponding directory_keyword enum. */
165 directory_keyword v;
166 /** Minimum number of arguments for this item */
167 int min_args;
168 /** Maximum number of arguments for this item */
169 int max_args;
170 /** If true, we concatenate all arguments for this item into a single
171 * string. */
172 int concat_args;
173 /** Requirments on object syntax for this item. */
174 obj_syntax os;
175 /** Lowest number of times this item may appear in a document. */
176 int min_cnt;
177 /** Highest number of times this item may appear in a document. */
178 int max_cnt;
179 /** One or more of AT_START/AT_END to limit where the item may appear in a
180 * document. */
181 int pos;
182 /** True iff this token is an annotation. */
183 int is_annotation;
184 } token_rule_t;
187 * Helper macros to define token tables. 's' is a string, 't' is a
188 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
189 * object syntax.
193 /** Appears to indicate the end of a table. */
194 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
195 /** An item with no restrictions: used for obsolete document types */
196 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
197 /** An item with no restrictions on multiplicity or location. */
198 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
199 /** An item that must appear exactly once */
200 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
201 /** An item that must appear exactly once, at the start of the document */
202 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
203 /** An item that must appear exactly once, at the end of the document */
204 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
205 /** An item that must appear one or more times */
206 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
207 /** An item that must appear no more than once */
208 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
209 /** An annotation that must appear no more than once */
210 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
212 /* Argument multiplicity: any number of arguments. */
213 #define ARGS 0,INT_MAX,0
214 /* Argument multiplicity: no arguments. */
215 #define NO_ARGS 0,0,0
216 /* Argument multiplicity: concatenate all arguments. */
217 #define CONCAT_ARGS 1,1,1
218 /* Argument multiplicity: at least <b>n</b> arguments. */
219 #define GE(n) n,INT_MAX,0
220 /* Argument multiplicity: exactly <b>n</b> arguments. */
221 #define EQ(n) n,n,0
223 /** List of tokens allowable in router derscriptors */
224 static token_rule_t routerdesc_token_table[] = {
225 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
226 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
227 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
228 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
229 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
230 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
231 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
232 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
233 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
234 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
235 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
236 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
237 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
238 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
239 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
240 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
241 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
242 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
243 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
245 T01("family", K_FAMILY, ARGS, NO_OBJ ),
246 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
247 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
249 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
250 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
251 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
253 END_OF_TABLE
256 /** List of tokens allowable in extra-info documents. */
257 static token_rule_t extrainfo_token_table[] = {
258 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
259 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
260 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
261 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
262 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
263 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
265 END_OF_TABLE
268 /** List of tokens allowable in the body part of v2 and v3 networkstatus
269 * documents. */
270 static token_rule_t rtrstatus_token_table[] = {
271 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
272 T1( "r", K_R, GE(8), NO_OBJ ),
273 T1( "s", K_S, ARGS, NO_OBJ ),
274 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
275 T01("w", K_W, ARGS, NO_OBJ ),
276 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
277 END_OF_TABLE
280 /** List of tokens allowable in the header part of v2 networkstatus documents.
282 static token_rule_t netstatus_token_table[] = {
283 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
284 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
285 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
286 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
287 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
288 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
289 GE(1), NO_OBJ ),
290 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
291 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
292 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
293 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
295 END_OF_TABLE
298 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
299 * footers. */
300 static token_rule_t dir_footer_token_table[] = {
301 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
302 END_OF_TABLE
305 /** List of tokens allowable in v1 directory headers/footers. */
306 static token_rule_t dir_token_table[] = {
307 /* don't enforce counts; this is obsolete. */
308 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
309 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
310 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
311 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
313 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
314 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
315 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
316 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
317 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
318 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
319 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
321 END_OF_TABLE
324 /** List of tokens common to V3 authority certificates and V3 consensuses. */
325 #define CERTIFICATE_MEMBERS \
326 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
327 GE(1), NO_OBJ ), \
328 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
329 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
330 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
331 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
332 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
333 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
334 NO_ARGS, NEED_OBJ), \
335 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
337 /** List of tokens allowable in V3 authority certificates. */
338 static token_rule_t dir_key_certificate_table[] = {
339 CERTIFICATE_MEMBERS
340 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
341 END_OF_TABLE
344 /** List of tokens allowable in rendezvous service descriptors */
345 static token_rule_t desc_token_table[] = {
346 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
347 EQ(1), NO_OBJ),
348 T1("version", R_VERSION, EQ(1), NO_OBJ),
349 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
350 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
351 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
352 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
353 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
354 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
355 END_OF_TABLE
358 /** List of tokens allowed in the (encrypted) list of introduction points of
359 * rendezvous service descriptors */
360 static token_rule_t ipo_token_table[] = {
361 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
362 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
363 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
364 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
365 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
366 END_OF_TABLE
369 /** List of tokens allowed in the (possibly encrypted) list of introduction
370 * points of rendezvous service descriptors */
371 static token_rule_t client_keys_token_table[] = {
372 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
373 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
374 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
375 END_OF_TABLE
378 /** List of tokens allowed in V3 networkstatus votes. */
379 static token_rule_t networkstatus_token_table[] = {
380 T1("network-status-version", K_NETWORK_STATUS_VERSION,
381 GE(1), NO_OBJ ),
382 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
383 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
384 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
385 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
386 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
387 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
388 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
389 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
391 CERTIFICATE_MEMBERS
393 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
394 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
395 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
396 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
397 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
398 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
399 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
400 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
402 END_OF_TABLE
405 /** List of tokens allowed in V3 networkstatus consensuses. */
406 static token_rule_t networkstatus_consensus_token_table[] = {
407 T1("network-status-version", K_NETWORK_STATUS_VERSION,
408 GE(1), NO_OBJ ),
409 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
410 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
411 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
412 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
413 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
415 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
417 T1N("dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
418 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
419 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
421 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
423 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
424 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
425 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), 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, char *digest,
455 const char *start_str, const char *end_str,
456 char end_char);
457 static void token_free(directory_token_t *tok);
458 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
459 static directory_token_t *_find_by_keyword(smartlist_t *s,
460 directory_keyword keyword,
461 const char *keyword_str);
462 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
463 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
464 directory_keyword keyword);
466 #define TS_ANNOTATIONS_OK 1
467 #define TS_NOCHECK 2
468 #define TS_NO_NEW_ANNOTATIONS 4
469 static int tokenize_string(memarea_t *area,
470 const char *start, const char *end,
471 smartlist_t *out,
472 token_rule_t *table,
473 int flags);
474 static directory_token_t *get_next_token(memarea_t *area,
475 const char **s,
476 const char *eos,
477 token_rule_t *table);
478 #define CST_CHECK_AUTHORITY (1<<0)
479 #define CST_NO_CHECK_OBJTYPE (1<<1)
480 static int check_signature_token(const char *digest,
481 directory_token_t *tok,
482 crypto_pk_env_t *pkey,
483 int flags,
484 const char *doctype);
485 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
486 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
488 #undef DEBUG_AREA_ALLOC
490 #ifdef DEBUG_AREA_ALLOC
491 #define DUMP_AREA(a,name) STMT_BEGIN \
492 size_t alloc=0, used=0; \
493 memarea_get_stats((a),&alloc,&used); \
494 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
495 name, (unsigned long)alloc, (unsigned long)used); \
496 STMT_END
497 #else
498 #define DUMP_AREA(a,name) STMT_NIL
499 #endif
501 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
502 * <b>s</b>. Return 0 on success, -1 on failure.
505 router_get_dir_hash(const char *s, char *digest)
507 return router_get_hash_impl(s,digest,
508 "signed-directory","\ndirectory-signature",'\n');
511 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
512 * <b>s</b>. Return 0 on success, -1 on failure.
515 router_get_router_hash(const char *s, char *digest)
517 return router_get_hash_impl(s,digest,
518 "router ","\nrouter-signature", '\n');
521 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
522 * string in <b>s</b>. Return 0 on success, -1 on failure.
525 router_get_runningrouters_hash(const char *s, char *digest)
527 return router_get_hash_impl(s,digest,
528 "network-status","\ndirectory-signature", '\n');
531 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
532 * string in <b>s</b>. Return 0 on success, -1 on failure. */
534 router_get_networkstatus_v2_hash(const char *s, char *digest)
536 return router_get_hash_impl(s,digest,
537 "network-status-version","\ndirectory-signature",
538 '\n');
541 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
542 * string in <b>s</b>. Return 0 on success, -1 on failure. */
544 router_get_networkstatus_v3_hash(const char *s, char *digest)
546 return router_get_hash_impl(s,digest,
547 "network-status-version","\ndirectory-signature",
548 ' ');
551 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
552 * string in <b>s</b>. Return 0 on success, -1 on failure. */
554 router_get_extrainfo_hash(const char *s, char *digest)
556 return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature",'\n');
559 /** Helper: used to generate signatures for routers, directories and
560 * network-status objects. Given a digest in <b>digest</b> and a secret
561 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
562 * surround it with -----BEGIN/END----- pairs, and write it to the
563 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
564 * failure.
567 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
568 crypto_pk_env_t *private_key)
570 char *signature;
571 size_t i;
573 signature = tor_malloc(crypto_pk_keysize(private_key));
574 if (crypto_pk_private_sign(private_key, signature, digest, DIGEST_LEN) < 0) {
576 log_warn(LD_BUG,"Couldn't sign digest.");
577 goto err;
579 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
580 goto truncated;
582 i = strlen(buf);
583 if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) {
584 log_warn(LD_BUG,"couldn't base64-encode signature");
585 goto err;
588 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
589 goto truncated;
591 tor_free(signature);
592 return 0;
594 truncated:
595 log_warn(LD_BUG,"tried to exceed string length.");
596 err:
597 tor_free(signature);
598 return -1;
601 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
602 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
603 * entries. Else, return VS_OLD if every member of
604 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
605 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
606 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
607 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
608 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
609 * VS_UNRECOMMENDED.
611 * (versionlist is a comma-separated list of version strings,
612 * optionally prefixed with "Tor". Versions that can't be parsed are
613 * ignored.)
615 version_status_t
616 tor_version_is_obsolete(const char *myversion, const char *versionlist)
618 tor_version_t mine, other;
619 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
620 found_any_in_series = 0, r, same;
621 version_status_t ret = VS_UNRECOMMENDED;
622 smartlist_t *version_sl;
624 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
625 myversion, versionlist);
627 if (tor_version_parse(myversion, &mine)) {
628 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
629 tor_assert(0);
631 version_sl = smartlist_create();
632 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
634 if (!strlen(versionlist)) { /* no authorities cared or agreed */
635 ret = VS_EMPTY;
636 goto done;
639 SMARTLIST_FOREACH(version_sl, const char *, cp, {
640 if (!strcmpstart(cp, "Tor "))
641 cp += 4;
643 if (tor_version_parse(cp, &other)) {
644 /* Couldn't parse other; it can't be a match. */
645 } else {
646 same = tor_version_same_series(&mine, &other);
647 if (same)
648 found_any_in_series = 1;
649 r = tor_version_compare(&mine, &other);
650 if (r==0) {
651 ret = VS_RECOMMENDED;
652 goto done;
653 } else if (r<0) {
654 found_newer = 1;
655 if (same)
656 found_newer_in_series = 1;
657 } else if (r>0) {
658 found_older = 1;
663 /* We didn't find the listed version. Is it new or old? */
664 if (found_any_in_series && !found_newer_in_series && found_newer) {
665 ret = VS_NEW_IN_SERIES;
666 } else if (found_newer && !found_older) {
667 ret = VS_OLD;
668 } else if (found_older && !found_newer) {
669 ret = VS_NEW;
670 } else {
671 ret = VS_UNRECOMMENDED;
674 done:
675 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
676 smartlist_free(version_sl);
677 return ret;
680 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
681 * Otherwise, return -1. If we're a directory cache, cache it.
684 router_parse_directory(const char *str)
686 directory_token_t *tok;
687 char digest[DIGEST_LEN];
688 time_t published_on;
689 int r;
690 const char *end, *cp;
691 smartlist_t *tokens = NULL;
692 crypto_pk_env_t *declared_key = NULL;
693 memarea_t *area = memarea_new();
695 /* XXXX This could be simplified a lot, but it will all go away
696 * once pre-0.1.1.8 is obsolete, and for now it's better not to
697 * touch it. */
699 if (router_get_dir_hash(str, digest)) {
700 log_warn(LD_DIR, "Unable to compute digest of directory");
701 goto err;
703 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
705 /* Check signature first, before we try to tokenize. */
706 cp = str;
707 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
708 cp = end;
709 if (cp == str || !cp) {
710 log_warn(LD_DIR, "No signature found on directory."); goto err;
712 ++cp;
713 tokens = smartlist_create();
714 if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
715 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
717 if (smartlist_len(tokens) != 1) {
718 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
720 tok=smartlist_get(tokens,0);
721 if (tok->tp != K_DIRECTORY_SIGNATURE) {
722 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
724 declared_key = find_dir_signing_key(str, str+strlen(str));
725 note_crypto_pk_op(VERIFY_DIR);
726 if (check_signature_token(digest, tok, declared_key,
727 CST_CHECK_AUTHORITY, "directory")<0)
728 goto err;
730 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
731 smartlist_clear(tokens);
732 memarea_clear(area);
734 /* Now try to parse the first part of the directory. */
735 if ((end = strstr(str,"\nrouter "))) {
736 ++end;
737 } else if ((end = strstr(str, "\ndirectory-signature"))) {
738 ++end;
739 } else {
740 end = str + strlen(str);
743 if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
744 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
747 tok = find_by_keyword(tokens, K_PUBLISHED);
748 tor_assert(tok->n_args == 1);
750 if (parse_iso_time(tok->args[0], &published_on) < 0) {
751 goto err;
754 /* Now that we know the signature is okay, and we have a
755 * publication time, cache the directory. */
756 if (directory_caches_v1_dir_info(get_options()) &&
757 !authdir_mode_v1(get_options()))
758 dirserv_set_cached_directory(str, published_on, 0);
760 r = 0;
761 goto done;
762 err:
763 r = -1;
764 done:
765 if (declared_key) crypto_free_pk_env(declared_key);
766 if (tokens) {
767 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
768 smartlist_free(tokens);
770 if (area) {
771 DUMP_AREA(area, "v1 directory");
772 memarea_drop_all(area);
774 return r;
777 /** Read a signed router status statement from <b>str</b>. If it's
778 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
779 * cache it.*/
781 router_parse_runningrouters(const char *str)
783 char digest[DIGEST_LEN];
784 directory_token_t *tok;
785 time_t published_on;
786 int r = -1;
787 crypto_pk_env_t *declared_key = NULL;
788 smartlist_t *tokens = NULL;
789 const char *eos = str + strlen(str);
790 memarea_t *area = NULL;
792 if (router_get_runningrouters_hash(str, digest)) {
793 log_warn(LD_DIR, "Unable to compute digest of running-routers");
794 goto err;
796 area = memarea_new();
797 tokens = smartlist_create();
798 if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
799 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
801 tok = smartlist_get(tokens,0);
802 if (tok->tp != K_NETWORK_STATUS) {
803 log_warn(LD_DIR, "Network-status starts with wrong token");
804 goto err;
807 tok = find_by_keyword(tokens, K_PUBLISHED);
808 tor_assert(tok->n_args == 1);
809 if (parse_iso_time(tok->args[0], &published_on) < 0) {
810 goto err;
812 if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
813 log_warn(LD_DIR, "Missing signature on running-routers");
814 goto err;
816 declared_key = find_dir_signing_key(str, eos);
817 note_crypto_pk_op(VERIFY_DIR);
818 if (check_signature_token(digest, tok, declared_key,
819 CST_CHECK_AUTHORITY, "running-routers")
820 < 0)
821 goto err;
823 /* Now that we know the signature is okay, and we have a
824 * publication time, cache the list. */
825 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
826 dirserv_set_cached_directory(str, published_on, 1);
828 r = 0;
829 err:
830 if (declared_key) crypto_free_pk_env(declared_key);
831 if (tokens) {
832 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
833 smartlist_free(tokens);
835 if (area) {
836 DUMP_AREA(area, "v1 running-routers");
837 memarea_drop_all(area);
839 return r;
842 /** Given a directory or running-routers string in <b>str</b>, try to
843 * find the its dir-signing-key token (if any). If this token is
844 * present, extract and return the key. Return NULL on failure. */
845 static crypto_pk_env_t *
846 find_dir_signing_key(const char *str, const char *eos)
848 const char *cp;
849 directory_token_t *tok;
850 crypto_pk_env_t *key = NULL;
851 memarea_t *area = NULL;
852 tor_assert(str);
853 tor_assert(eos);
855 /* Is there a dir-signing-key in the directory? */
856 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
857 if (!cp)
858 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
859 if (!cp)
860 return NULL;
861 ++cp; /* Now cp points to the start of the token. */
863 area = memarea_new();
864 tok = get_next_token(area, &cp, eos, dir_token_table);
865 if (!tok) {
866 log_warn(LD_DIR, "Unparseable dir-signing-key token");
867 goto done;
869 if (tok->tp != K_DIR_SIGNING_KEY) {
870 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
871 goto done;
874 if (tok->key) {
875 key = tok->key;
876 tok->key = NULL; /* steal reference. */
877 } else {
878 log_warn(LD_DIR, "Dir-signing-key token contained no key");
881 done:
882 if (tok) token_free(tok);
883 if (area) {
884 DUMP_AREA(area, "dir-signing-key token");
885 memarea_drop_all(area);
887 return key;
890 /** Return true iff <b>key</b> is allowed to sign directories.
892 static int
893 dir_signing_key_is_trusted(crypto_pk_env_t *key)
895 char digest[DIGEST_LEN];
896 if (!key) return 0;
897 if (crypto_pk_get_digest(key, digest) < 0) {
898 log_warn(LD_DIR, "Error computing dir-signing-key digest");
899 return 0;
901 if (!router_digest_is_trusted_dir(digest)) {
902 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
903 return 0;
905 return 1;
908 /** Check whether the object body of the token in <b>tok</b> has a good
909 * signature for <b>digest</b> using key <b>pkey</b>. If
910 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
911 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
912 * the object type of the signature object. Use <b>doctype</b> as the type of
913 * the document when generating log messages. Return 0 on success, negative
914 * on failure.
916 static int
917 check_signature_token(const char *digest,
918 directory_token_t *tok,
919 crypto_pk_env_t *pkey,
920 int flags,
921 const char *doctype)
923 char *signed_digest;
924 const int check_authority = (flags & CST_CHECK_AUTHORITY);
925 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
927 tor_assert(pkey);
928 tor_assert(tok);
929 tor_assert(digest);
930 tor_assert(doctype);
932 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
933 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
934 doctype);
935 return -1;
938 if (check_objtype) {
939 if (strcmp(tok->object_type, "SIGNATURE")) {
940 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
941 return -1;
945 signed_digest = tor_malloc(tok->object_size);
946 if (crypto_pk_public_checksig(pkey, signed_digest, tok->object_body,
947 tok->object_size)
948 != DIGEST_LEN) {
949 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
950 tor_free(signed_digest);
951 return -1;
953 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
954 // hex_str(signed_digest,4));
955 if (memcmp(digest, signed_digest, DIGEST_LEN)) {
956 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
957 tor_free(signed_digest);
958 return -1;
960 tor_free(signed_digest);
961 return 0;
964 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
965 * or to the first of the annotations proceeding the next router or
966 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
967 * we found an extrainfo, or false if found a router. Do not scan beyond
968 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
969 static int
970 find_start_of_next_router_or_extrainfo(const char **s_ptr,
971 const char *eos,
972 int *is_extrainfo_out)
974 const char *annotations = NULL;
975 const char *s = *s_ptr;
977 s = eat_whitespace_eos(s, eos);
979 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
980 /* We're at the start of a line. */
981 tor_assert(*s != '\n');
983 if (*s == '@' && !annotations) {
984 annotations = s;
985 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
986 *s_ptr = annotations ? annotations : s;
987 *is_extrainfo_out = 0;
988 return 0;
989 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
990 *s_ptr = annotations ? annotations : s;
991 *is_extrainfo_out = 1;
992 return 0;
995 if (!(s = memchr(s+1, '\n', eos-(s+1))))
996 break;
997 s = eat_whitespace_eos(s, eos);
999 return -1;
1002 /** Given a string *<b>s</b> containing a concatenated sequence of router
1003 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1004 * them and stores the result in <b>dest</b>. All routers are marked running
1005 * and valid. Advances *s to a point immediately following the last router
1006 * entry. Ignore any trailing router entries that are not complete.
1008 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1009 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1010 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1012 * Returns 0 on success and -1 on failure.
1015 router_parse_list_from_string(const char **s, const char *eos,
1016 smartlist_t *dest,
1017 saved_location_t saved_location,
1018 int want_extrainfo,
1019 int allow_annotations,
1020 const char *prepend_annotations)
1022 routerinfo_t *router;
1023 extrainfo_t *extrainfo;
1024 signed_descriptor_t *signed_desc;
1025 void *elt;
1026 const char *end, *start;
1027 int have_extrainfo;
1029 tor_assert(s);
1030 tor_assert(*s);
1031 tor_assert(dest);
1033 start = *s;
1034 if (!eos)
1035 eos = *s + strlen(*s);
1037 tor_assert(eos >= *s);
1039 while (1) {
1040 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1041 break;
1043 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1044 if (end)
1045 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1046 if (end)
1047 end += strlen("\n-----END SIGNATURE-----\n");
1049 if (!end)
1050 break;
1052 elt = NULL;
1054 if (have_extrainfo && want_extrainfo) {
1055 routerlist_t *rl = router_get_routerlist();
1056 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1057 saved_location != SAVED_IN_CACHE,
1058 rl->identity_map);
1059 if (extrainfo) {
1060 signed_desc = &extrainfo->cache_info;
1061 elt = extrainfo;
1063 } else if (!have_extrainfo && !want_extrainfo) {
1064 router = router_parse_entry_from_string(*s, end,
1065 saved_location != SAVED_IN_CACHE,
1066 allow_annotations,
1067 prepend_annotations);
1068 if (router) {
1069 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1070 router->nickname, router_purpose_to_string(router->purpose));
1071 signed_desc = &router->cache_info;
1072 elt = router;
1075 if (!elt) {
1076 *s = end;
1077 continue;
1079 if (saved_location != SAVED_NOWHERE) {
1080 signed_desc->saved_location = saved_location;
1081 signed_desc->saved_offset = *s - start;
1083 *s = end;
1084 smartlist_add(dest, elt);
1087 return 0;
1090 /* For debugging: define to count every descriptor digest we've seen so we
1091 * know if we need to try harder to avoid duplicate verifies. */
1092 #undef COUNT_DISTINCT_DIGESTS
1094 #ifdef COUNT_DISTINCT_DIGESTS
1095 static digestmap_t *verified_digests = NULL;
1096 #endif
1098 /** Log the total count of the number of distinct router digests we've ever
1099 * verified. When compared to the number of times we've verified routerdesc
1100 * signatures <i>in toto</i>, this will tell us if we're doing too much
1101 * multiple-verification. */
1102 void
1103 dump_distinct_digest_count(int severity)
1105 #ifdef COUNT_DISTINCT_DIGESTS
1106 if (!verified_digests)
1107 verified_digests = digestmap_new();
1108 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1109 digestmap_size(verified_digests));
1110 #else
1111 (void)severity; /* suppress "unused parameter" warning */
1112 #endif
1115 /** Helper function: reads a single router entry from *<b>s</b> ...
1116 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1117 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1118 * s through end into the signed_descriptor_body of the resulting
1119 * routerinfo_t.
1121 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1122 * before the router; if it's false, reject the router if it's annotated. If
1123 * <b>prepend_annotations</b> is set, it should contain some annotations:
1124 * append them to the front of the router before parsing it, and keep them
1125 * around when caching the router.
1127 * Only one of allow_annotations and prepend_annotations may be set.
1129 routerinfo_t *
1130 router_parse_entry_from_string(const char *s, const char *end,
1131 int cache_copy, int allow_annotations,
1132 const char *prepend_annotations)
1134 routerinfo_t *router = NULL;
1135 char digest[128];
1136 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1137 directory_token_t *tok;
1138 struct in_addr in;
1139 const char *start_of_annotations, *cp;
1140 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1141 int ok = 1;
1142 memarea_t *area = NULL;
1144 tor_assert(!allow_annotations || !prepend_annotations);
1146 if (!end) {
1147 end = s + strlen(s);
1150 /* point 'end' to a point immediately after the final newline. */
1151 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1152 --end;
1154 area = memarea_new();
1155 tokens = smartlist_create();
1156 if (prepend_annotations) {
1157 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1158 routerdesc_token_table,TS_NOCHECK)) {
1159 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1160 goto err;
1164 start_of_annotations = s;
1165 cp = tor_memstr(s, end-s, "\nrouter ");
1166 if (!cp) {
1167 if (end-s < 7 || strcmpstart(s, "router ")) {
1168 log_warn(LD_DIR, "No router keyword found.");
1169 goto err;
1171 } else {
1172 s = cp+1;
1175 if (allow_annotations && start_of_annotations != s) {
1176 if (tokenize_string(area,start_of_annotations,s,tokens,
1177 routerdesc_token_table,TS_NOCHECK)) {
1178 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1179 goto err;
1183 if (router_get_router_hash(s, digest) < 0) {
1184 log_warn(LD_DIR, "Couldn't compute router hash.");
1185 goto err;
1188 int flags = 0;
1189 if (allow_annotations)
1190 flags |= TS_ANNOTATIONS_OK;
1191 if (prepend_annotations)
1192 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1194 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1195 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1196 goto err;
1200 if (smartlist_len(tokens) < 2) {
1201 log_warn(LD_DIR, "Impossibly short router descriptor.");
1202 goto err;
1205 tok = find_by_keyword(tokens, K_ROUTER);
1206 tor_assert(tok->n_args >= 5);
1208 router = tor_malloc_zero(sizeof(routerinfo_t));
1209 router->country = -1;
1210 router->cache_info.routerlist_index = -1;
1211 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1212 router->cache_info.signed_descriptor_len = end-s;
1213 if (cache_copy) {
1214 size_t len = router->cache_info.signed_descriptor_len +
1215 router->cache_info.annotations_len;
1216 char *cp =
1217 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1218 if (prepend_annotations) {
1219 memcpy(cp, prepend_annotations, prepend_len);
1220 cp += prepend_len;
1222 /* This assertion will always succeed.
1223 * len == signed_desc_len + annotations_len
1224 * == end-s + s-start_of_annotations + prepend_len
1225 * == end-start_of_annotations + prepend_len
1226 * We already wrote prepend_len bytes into the buffer; now we're
1227 * writing end-start_of_annotations -NM. */
1228 tor_assert(cp+(end-start_of_annotations) ==
1229 router->cache_info.signed_descriptor_body+len);
1230 memcpy(cp, start_of_annotations, end-start_of_annotations);
1231 router->cache_info.signed_descriptor_body[len] = '\0';
1232 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1234 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1236 router->nickname = tor_strdup(tok->args[0]);
1237 if (!is_legal_nickname(router->nickname)) {
1238 log_warn(LD_DIR,"Router nickname is invalid");
1239 goto err;
1241 router->address = tor_strdup(tok->args[1]);
1242 if (!tor_inet_aton(router->address, &in)) {
1243 log_warn(LD_DIR,"Router address is not an IP address.");
1244 goto err;
1246 router->addr = ntohl(in.s_addr);
1248 router->or_port =
1249 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1250 if (!ok) {
1251 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1252 goto err;
1254 router->dir_port =
1255 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1256 if (!ok) {
1257 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1258 goto err;
1261 tok = find_by_keyword(tokens, K_BANDWIDTH);
1262 tor_assert(tok->n_args >= 3);
1263 router->bandwidthrate = (int)
1264 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1266 if (!ok) {
1267 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1268 escaped(tok->args[0]));
1269 goto err;
1271 router->bandwidthburst =
1272 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1273 if (!ok) {
1274 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1275 goto err;
1277 router->bandwidthcapacity = (int)
1278 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1279 if (!ok) {
1280 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1281 goto err;
1284 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1285 tor_assert(tok->n_args);
1286 router->purpose = router_purpose_from_string(tok->args[0]);
1287 } else {
1288 router->purpose = ROUTER_PURPOSE_GENERAL;
1290 router->cache_info.send_unencrypted =
1291 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1293 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1294 tor_assert(tok->n_args >= 1);
1295 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1296 if (!ok) {
1297 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1298 goto err;
1302 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1303 tor_assert(tok->n_args >= 1);
1304 router->is_hibernating
1305 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1308 tok = find_by_keyword(tokens, K_PUBLISHED);
1309 tor_assert(tok->n_args == 1);
1310 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1311 goto err;
1313 tok = find_by_keyword(tokens, K_ONION_KEY);
1314 router->onion_pkey = tok->key;
1315 tok->key = NULL; /* Prevent free */
1317 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1318 router->identity_pkey = tok->key;
1319 tok->key = NULL; /* Prevent free */
1320 if (crypto_pk_get_digest(router->identity_pkey,
1321 router->cache_info.identity_digest)) {
1322 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1325 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1326 /* If there's a fingerprint line, it must match the identity digest. */
1327 char d[DIGEST_LEN];
1328 tor_assert(tok->n_args == 1);
1329 tor_strstrip(tok->args[0], " ");
1330 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1331 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1332 escaped(tok->args[0]));
1333 goto err;
1335 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1336 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1337 tok->args[0]);
1338 goto err;
1342 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1343 router->platform = tor_strdup(tok->args[0]);
1346 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1347 router->contact_info = tor_strdup(tok->args[0]);
1350 if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
1351 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1352 } else if (router->platform) {
1353 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1354 router->has_old_dnsworkers = 1;
1357 exit_policy_tokens = find_all_exitpolicy(tokens);
1358 if (!smartlist_len(exit_policy_tokens)) {
1359 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1360 goto err;
1362 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1363 if (router_add_exit_policy(router,t)<0) {
1364 log_warn(LD_DIR,"Error in exit policy");
1365 goto err;
1367 policy_expand_private(&router->exit_policy);
1368 if (policy_is_reject_star(router->exit_policy))
1369 router->policy_is_reject_star = 1;
1371 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1372 int i;
1373 router->declared_family = smartlist_create();
1374 for (i=0;i<tok->n_args;++i) {
1375 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1376 log_warn(LD_DIR, "Illegal nickname %s in family line",
1377 escaped(tok->args[i]));
1378 goto err;
1380 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1384 if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1385 router->caches_extra_info = 1;
1387 if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
1388 router->allow_single_hop_exits = 1;
1390 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1391 tor_assert(tok->n_args >= 1);
1392 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1393 base16_decode(router->cache_info.extra_info_digest,
1394 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1395 } else {
1396 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1400 if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1401 router->wants_to_be_hs_dir = 1;
1404 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1405 note_crypto_pk_op(VERIFY_RTR);
1406 #ifdef COUNT_DISTINCT_DIGESTS
1407 if (!verified_digests)
1408 verified_digests = digestmap_new();
1409 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1410 #endif
1411 if (check_signature_token(digest, tok, router->identity_pkey, 0,
1412 "router descriptor") < 0)
1413 goto err;
1415 routerinfo_set_country(router);
1417 if (!router->or_port) {
1418 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1419 goto err;
1422 if (!router->platform) {
1423 router->platform = tor_strdup("<unknown>");
1426 goto done;
1428 err:
1429 routerinfo_free(router);
1430 router = NULL;
1431 done:
1432 if (tokens) {
1433 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1434 smartlist_free(tokens);
1436 if (exit_policy_tokens) {
1437 smartlist_free(exit_policy_tokens);
1439 if (area) {
1440 DUMP_AREA(area, "routerinfo");
1441 memarea_drop_all(area);
1443 return router;
1446 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1447 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1448 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1449 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1450 * as a map from router identity to routerinfo_t when looking up signing keys.
1452 extrainfo_t *
1453 extrainfo_parse_entry_from_string(const char *s, const char *end,
1454 int cache_copy, struct digest_ri_map_t *routermap)
1456 extrainfo_t *extrainfo = NULL;
1457 char digest[128];
1458 smartlist_t *tokens = NULL;
1459 directory_token_t *tok;
1460 crypto_pk_env_t *key = NULL;
1461 routerinfo_t *router = NULL;
1462 memarea_t *area = NULL;
1464 if (!end) {
1465 end = s + strlen(s);
1468 /* point 'end' to a point immediately after the final newline. */
1469 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1470 --end;
1472 if (router_get_extrainfo_hash(s, digest) < 0) {
1473 log_warn(LD_DIR, "Couldn't compute router hash.");
1474 return NULL;
1476 tokens = smartlist_create();
1477 area = memarea_new();
1478 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1479 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1480 goto err;
1483 if (smartlist_len(tokens) < 2) {
1484 log_warn(LD_DIR, "Impossibly short extra-info document.");
1485 goto err;
1488 tok = smartlist_get(tokens,0);
1489 if (tok->tp != K_EXTRA_INFO) {
1490 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1491 goto err;
1494 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1495 extrainfo->cache_info.is_extrainfo = 1;
1496 if (cache_copy)
1497 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1498 extrainfo->cache_info.signed_descriptor_len = end-s;
1499 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1501 tor_assert(tok->n_args >= 2);
1502 if (!is_legal_nickname(tok->args[0])) {
1503 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1504 goto err;
1506 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1507 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1508 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1509 tok->args[1], HEX_DIGEST_LEN)) {
1510 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1511 escaped(tok->args[1]));
1512 goto err;
1515 tok = find_by_keyword(tokens, K_PUBLISHED);
1516 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1517 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1518 escaped(tok->args[0]));
1519 goto err;
1522 if (routermap &&
1523 (router = digestmap_get((digestmap_t*)routermap,
1524 extrainfo->cache_info.identity_digest))) {
1525 key = router->identity_pkey;
1528 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1529 if (strcmp(tok->object_type, "SIGNATURE") ||
1530 tok->object_size < 128 || tok->object_size > 512) {
1531 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1532 goto err;
1535 if (key) {
1536 note_crypto_pk_op(VERIFY_RTR);
1537 if (check_signature_token(digest, tok, key, 0, "extra-info") < 0)
1538 goto err;
1540 if (router)
1541 extrainfo->cache_info.send_unencrypted =
1542 router->cache_info.send_unencrypted;
1543 } else {
1544 extrainfo->pending_sig = tor_memdup(tok->object_body,
1545 tok->object_size);
1546 extrainfo->pending_sig_len = tok->object_size;
1549 goto done;
1550 err:
1551 if (extrainfo)
1552 extrainfo_free(extrainfo);
1553 extrainfo = NULL;
1554 done:
1555 if (tokens) {
1556 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1557 smartlist_free(tokens);
1559 if (area) {
1560 DUMP_AREA(area, "extrainfo");
1561 memarea_drop_all(area);
1563 return extrainfo;
1566 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1567 * the first character after the certificate. */
1568 authority_cert_t *
1569 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1571 authority_cert_t *cert = NULL, *old_cert;
1572 smartlist_t *tokens = NULL;
1573 char digest[DIGEST_LEN];
1574 directory_token_t *tok;
1575 char fp_declared[DIGEST_LEN];
1576 char *eos;
1577 size_t len;
1578 int found;
1579 memarea_t *area = NULL;
1581 s = eat_whitespace(s);
1582 eos = strstr(s, "\ndir-key-certification");
1583 if (! eos) {
1584 log_warn(LD_DIR, "No signature found on key certificate");
1585 return NULL;
1587 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1588 if (! eos) {
1589 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1590 return NULL;
1592 eos = strchr(eos+2, '\n');
1593 tor_assert(eos);
1594 ++eos;
1595 len = eos - s;
1597 tokens = smartlist_create();
1598 area = memarea_new();
1599 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1600 log_warn(LD_DIR, "Error tokenizing key certificate");
1601 goto err;
1603 if (router_get_hash_impl(s, digest, "dir-key-certificate-version",
1604 "\ndir-key-certification", '\n') < 0)
1605 goto err;
1606 tok = smartlist_get(tokens, 0);
1607 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1608 log_warn(LD_DIR,
1609 "Key certificate does not begin with a recognized version (3).");
1610 goto err;
1613 cert = tor_malloc_zero(sizeof(authority_cert_t));
1614 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1616 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1617 tor_assert(tok->key);
1618 cert->signing_key = tok->key;
1619 tok->key = NULL;
1620 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1621 goto err;
1623 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1624 tor_assert(tok->key);
1625 cert->identity_key = tok->key;
1626 tok->key = NULL;
1628 tok = find_by_keyword(tokens, K_FINGERPRINT);
1629 tor_assert(tok->n_args);
1630 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1631 strlen(tok->args[0]))) {
1632 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1633 escaped(tok->args[0]));
1634 goto err;
1637 if (crypto_pk_get_digest(cert->identity_key,
1638 cert->cache_info.identity_digest))
1639 goto err;
1641 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1642 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1643 "fingerprint");
1644 goto err;
1647 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1648 if (tok) {
1649 tor_assert(tok->n_args);
1650 if (parse_addr_port(LOG_WARN, tok->args[0], NULL, &cert->addr,
1651 &cert->dir_port)<0) {
1652 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1653 goto err;
1657 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1658 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1659 goto err;
1661 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1662 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1663 goto err;
1666 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1667 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1668 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1669 goto err;
1672 /* If we already have this cert, don't bother checking the signature. */
1673 old_cert = authority_cert_get_by_digests(
1674 cert->cache_info.identity_digest,
1675 cert->signing_key_digest);
1676 found = 0;
1677 if (old_cert) {
1678 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1679 * buy us much. */
1680 if (old_cert->cache_info.signed_descriptor_len == len &&
1681 old_cert->cache_info.signed_descriptor_body &&
1682 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1683 log_debug(LD_DIR, "We already checked the signature on this "
1684 "certificate; no need to do so again.");
1685 found = 1;
1686 cert->is_cross_certified = old_cert->is_cross_certified;
1689 if (!found) {
1690 if (check_signature_token(digest, tok, cert->identity_key, 0,
1691 "key certificate")) {
1692 goto err;
1695 if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
1696 /* XXXX Once all authorities generate cross-certified certificates,
1697 * make this field mandatory. */
1698 if (check_signature_token(cert->cache_info.identity_digest,
1699 tok,
1700 cert->signing_key,
1701 CST_NO_CHECK_OBJTYPE,
1702 "key cross-certification")) {
1703 goto err;
1705 cert->is_cross_certified = 1;
1709 cert->cache_info.signed_descriptor_len = len;
1710 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1711 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1712 cert->cache_info.signed_descriptor_body[len] = 0;
1713 cert->cache_info.saved_location = SAVED_NOWHERE;
1715 if (end_of_string) {
1716 *end_of_string = eat_whitespace(eos);
1718 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1719 smartlist_free(tokens);
1720 if (area) {
1721 DUMP_AREA(area, "authority cert");
1722 memarea_drop_all(area);
1724 return cert;
1725 err:
1726 authority_cert_free(cert);
1727 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1728 smartlist_free(tokens);
1729 if (area) {
1730 DUMP_AREA(area, "authority cert");
1731 memarea_drop_all(area);
1733 return NULL;
1736 /** Helper: given a string <b>s</b>, return the start of the next router-status
1737 * object (starting with "r " at the start of a line). If none is found,
1738 * return the start of the next directory signature. If none is found, return
1739 * the end of the string. */
1740 static INLINE const char *
1741 find_start_of_next_routerstatus(const char *s)
1743 const char *eos = strstr(s, "\nr ");
1744 if (eos) {
1745 const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
1746 if (eos2 && eos2 < eos)
1747 return eos2;
1748 else
1749 return eos+1;
1750 } else {
1751 if ((eos = strstr(s, "\ndirectory-signature")))
1752 return eos+1;
1753 return s + strlen(s);
1757 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1758 * empty smartlist at <b>tokens</b>, parse and return the first router status
1759 * object in the string, and advance *<b>s</b> to just after the end of the
1760 * router status. Return NULL and advance *<b>s</b> on error.
1762 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1763 * routerstatus but use <b>vote_rs</b> instead.
1765 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1766 * consensus, and we should parse it according to the method used to
1767 * make that consensus.
1769 static routerstatus_t *
1770 routerstatus_parse_entry_from_string(memarea_t *area,
1771 const char **s, smartlist_t *tokens,
1772 networkstatus_t *vote,
1773 vote_routerstatus_t *vote_rs,
1774 int consensus_method)
1776 const char *eos;
1777 routerstatus_t *rs = NULL;
1778 directory_token_t *tok;
1779 char timebuf[ISO_TIME_LEN+1];
1780 struct in_addr in;
1781 tor_assert(tokens);
1782 tor_assert(bool_eq(vote, vote_rs));
1784 eos = find_start_of_next_routerstatus(*s);
1786 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1787 log_warn(LD_DIR, "Error tokenizing router status");
1788 goto err;
1790 if (smartlist_len(tokens) < 1) {
1791 log_warn(LD_DIR, "Impossibly short router status");
1792 goto err;
1794 tok = find_by_keyword(tokens, K_R);
1795 tor_assert(tok->n_args >= 8);
1796 if (vote_rs) {
1797 rs = &vote_rs->status;
1798 } else {
1799 rs = tor_malloc_zero(sizeof(routerstatus_t));
1802 if (!is_legal_nickname(tok->args[0])) {
1803 log_warn(LD_DIR,
1804 "Invalid nickname %s in router status; skipping.",
1805 escaped(tok->args[0]));
1806 goto err;
1808 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1810 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1811 log_warn(LD_DIR, "Error decoding identity digest %s",
1812 escaped(tok->args[1]));
1813 goto err;
1816 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1817 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1818 escaped(tok->args[2]));
1819 goto err;
1822 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1823 tok->args[3], tok->args[4]) < 0 ||
1824 parse_iso_time(timebuf, &rs->published_on)<0) {
1825 log_warn(LD_DIR, "Error parsing time '%s %s'",
1826 tok->args[3], tok->args[4]);
1827 goto err;
1830 if (tor_inet_aton(tok->args[5], &in) == 0) {
1831 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1832 escaped(tok->args[5]));
1833 goto err;
1835 rs->addr = ntohl(in.s_addr);
1837 rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL);
1838 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL);
1840 tok = find_opt_by_keyword(tokens, K_S);
1841 if (tok && vote) {
1842 int i;
1843 vote_rs->flags = 0;
1844 for (i=0; i < tok->n_args; ++i) {
1845 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1846 if (p >= 0) {
1847 vote_rs->flags |= (1<<p);
1848 } else {
1849 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1850 escaped(tok->args[i]));
1851 goto err;
1854 } else if (tok) {
1855 int i;
1856 for (i=0; i < tok->n_args; ++i) {
1857 if (!strcmp(tok->args[i], "Exit"))
1858 rs->is_exit = 1;
1859 else if (!strcmp(tok->args[i], "Stable"))
1860 rs->is_stable = 1;
1861 else if (!strcmp(tok->args[i], "Fast"))
1862 rs->is_fast = 1;
1863 else if (!strcmp(tok->args[i], "Running"))
1864 rs->is_running = 1;
1865 else if (!strcmp(tok->args[i], "Named"))
1866 rs->is_named = 1;
1867 else if (!strcmp(tok->args[i], "Valid"))
1868 rs->is_valid = 1;
1869 else if (!strcmp(tok->args[i], "V2Dir"))
1870 rs->is_v2_dir = 1;
1871 else if (!strcmp(tok->args[i], "Guard"))
1872 rs->is_possible_guard = 1;
1873 else if (!strcmp(tok->args[i], "BadExit"))
1874 rs->is_bad_exit = 1;
1875 else if (!strcmp(tok->args[i], "BadDirectory"))
1876 rs->is_bad_directory = 1;
1877 else if (!strcmp(tok->args[i], "Authority"))
1878 rs->is_authority = 1;
1879 else if (!strcmp(tok->args[i], "Unnamed") &&
1880 consensus_method >= 2) {
1881 /* Unnamed is computed right by consensus method 2 and later. */
1882 rs->is_unnamed = 1;
1883 } else if (!strcmp(tok->args[i], "HSDir")) {
1884 rs->is_hs_dir = 1;
1888 if ((tok = find_opt_by_keyword(tokens, K_V))) {
1889 tor_assert(tok->n_args == 1);
1890 rs->version_known = 1;
1891 if (strcmpstart(tok->args[0], "Tor ")) {
1892 rs->version_supports_begindir = 1;
1893 rs->version_supports_extrainfo_upload = 1;
1894 rs->version_supports_conditional_consensus = 1;
1895 } else {
1896 rs->version_supports_begindir =
1897 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
1898 rs->version_supports_extrainfo_upload =
1899 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
1900 rs->version_supports_v3_dir =
1901 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
1902 rs->version_supports_conditional_consensus =
1903 tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
1905 if (vote_rs) {
1906 vote_rs->version = tor_strdup(tok->args[0]);
1910 /* handle weighting/bandwidth info */
1911 if ((tok = find_opt_by_keyword(tokens, K_W))) {
1912 int i;
1913 for (i=0; i < tok->n_args; ++i) {
1914 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
1915 int ok;
1916 rs->bandwidth = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10,
1917 0, UINT32_MAX, &ok, NULL);
1918 if (!ok) {
1919 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
1920 goto err;
1922 rs->has_bandwidth = 1;
1927 /* parse exit policy summaries */
1928 if ((tok = find_opt_by_keyword(tokens, K_P))) {
1929 tor_assert(tok->n_args == 1);
1930 if (strcmpstart(tok->args[0], "accept ") &&
1931 strcmpstart(tok->args[0], "reject ")) {
1932 log_err(LD_DIR, "Unknown exit policy summary type %s.",
1933 escaped(tok->args[0]));
1934 goto err;
1936 /* XXX weasel: parse this into ports and represent them somehow smart,
1937 * maybe not here but somewhere on if we need it for the client.
1938 * we should still parse it here to check it's valid tho.
1940 rs->exitsummary = tor_strdup(tok->args[0]);
1941 rs->has_exitsummary = 1;
1944 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
1945 rs->is_named = 0;
1947 goto done;
1948 err:
1949 if (rs && !vote_rs)
1950 routerstatus_free(rs);
1951 rs = NULL;
1952 done:
1953 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1954 smartlist_clear(tokens);
1955 if (area) {
1956 DUMP_AREA(area, "routerstatus entry");
1957 memarea_clear(area);
1959 *s = eos;
1961 return rs;
1964 /** Helper to sort a smartlist of pointers to routerstatus_t */
1965 static int
1966 _compare_routerstatus_entries(const void **_a, const void **_b)
1968 const routerstatus_t *a = *_a, *b = *_b;
1969 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
1972 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1973 static void
1974 _free_duplicate_routerstatus_entry(void *e)
1976 log_warn(LD_DIR,
1977 "Network-status has two entries for the same router. "
1978 "Dropping one.");
1979 routerstatus_free(e);
1982 /** Given a v2 network-status object in <b>s</b>, try to
1983 * parse it and return the result. Return NULL on failure. Check the
1984 * signature of the network status, but do not (yet) check the signing key for
1985 * authority.
1987 networkstatus_v2_t *
1988 networkstatus_v2_parse_from_string(const char *s)
1990 const char *eos;
1991 smartlist_t *tokens = smartlist_create();
1992 smartlist_t *footer_tokens = smartlist_create();
1993 networkstatus_v2_t *ns = NULL;
1994 char ns_digest[DIGEST_LEN];
1995 char tmp_digest[DIGEST_LEN];
1996 struct in_addr in;
1997 directory_token_t *tok;
1998 int i;
1999 memarea_t *area = NULL;
2001 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
2002 log_warn(LD_DIR, "Unable to compute digest of network-status");
2003 goto err;
2006 area = memarea_new();
2007 eos = find_start_of_next_routerstatus(s);
2008 if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
2009 log_warn(LD_DIR, "Error tokenizing network-status header.");
2010 goto err;
2012 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
2013 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2015 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2016 tor_assert(tok->n_args >= 1);
2017 if (strcmp(tok->args[0], "2")) {
2018 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
2019 "%s", escaped(tok->args[0]));
2020 goto err;
2023 tok = find_by_keyword(tokens, K_DIR_SOURCE);
2024 tor_assert(tok->n_args >= 3);
2025 ns->source_address = tor_strdup(tok->args[0]);
2026 if (tor_inet_aton(tok->args[1], &in) == 0) {
2027 log_warn(LD_DIR, "Error parsing network-status source address %s",
2028 escaped(tok->args[1]));
2029 goto err;
2031 ns->source_addr = ntohl(in.s_addr);
2032 ns->source_dirport =
2033 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
2034 if (ns->source_dirport == 0) {
2035 log_warn(LD_DIR, "Directory source without dirport; skipping.");
2036 goto err;
2039 tok = find_by_keyword(tokens, K_FINGERPRINT);
2040 tor_assert(tok->n_args);
2041 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
2042 strlen(tok->args[0]))) {
2043 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
2044 escaped(tok->args[0]));
2045 goto err;
2048 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2049 tor_assert(tok->n_args);
2050 ns->contact = tor_strdup(tok->args[0]);
2053 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2054 tor_assert(tok->key);
2055 ns->signing_key = tok->key;
2056 tok->key = NULL;
2058 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
2059 log_warn(LD_DIR, "Couldn't compute signing key digest");
2060 goto err;
2062 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
2063 log_warn(LD_DIR,
2064 "network-status fingerprint did not match dir-signing-key");
2065 goto err;
2068 if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
2069 for (i=0; i < tok->n_args; ++i) {
2070 if (!strcmp(tok->args[i], "Names"))
2071 ns->binds_names = 1;
2072 if (!strcmp(tok->args[i], "Versions"))
2073 ns->recommends_versions = 1;
2074 if (!strcmp(tok->args[i], "BadExits"))
2075 ns->lists_bad_exits = 1;
2076 if (!strcmp(tok->args[i], "BadDirectories"))
2077 ns->lists_bad_directories = 1;
2081 if (ns->recommends_versions) {
2082 if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2083 log_warn(LD_DIR, "Missing client-versions on versioning directory");
2084 goto err;
2086 ns->client_versions = tor_strdup(tok->args[0]);
2088 if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
2089 tok->n_args<1) {
2090 log_warn(LD_DIR, "Missing server-versions on versioning directory");
2091 goto err;
2093 ns->server_versions = tor_strdup(tok->args[0]);
2096 tok = find_by_keyword(tokens, K_PUBLISHED);
2097 tor_assert(tok->n_args == 1);
2098 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
2099 goto err;
2102 ns->entries = smartlist_create();
2103 s = eos;
2104 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2105 smartlist_clear(tokens);
2106 memarea_clear(area);
2107 while (!strcmpstart(s, "r ")) {
2108 routerstatus_t *rs;
2109 if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
2110 NULL, NULL, 0)))
2111 smartlist_add(ns->entries, rs);
2113 smartlist_sort(ns->entries, _compare_routerstatus_entries);
2114 smartlist_uniq(ns->entries, _compare_routerstatus_entries,
2115 _free_duplicate_routerstatus_entry);
2117 if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
2118 log_warn(LD_DIR, "Error tokenizing network-status footer.");
2119 goto err;
2121 if (smartlist_len(footer_tokens) < 1) {
2122 log_warn(LD_DIR, "Too few items in network-status footer.");
2123 goto err;
2125 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
2126 if (tok->tp != K_DIRECTORY_SIGNATURE) {
2127 log_warn(LD_DIR,
2128 "Expected network-status footer to end with a signature.");
2129 goto err;
2132 note_crypto_pk_op(VERIFY_DIR);
2133 if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
2134 "network-status") < 0)
2135 goto err;
2137 goto done;
2138 err:
2139 if (ns)
2140 networkstatus_v2_free(ns);
2141 ns = NULL;
2142 done:
2143 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2144 smartlist_free(tokens);
2145 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2146 smartlist_free(footer_tokens);
2147 if (area) {
2148 DUMP_AREA(area, "v2 networkstatus");
2149 memarea_drop_all(area);
2151 return ns;
2154 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2155 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2156 networkstatus_t *
2157 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2158 networkstatus_type_t ns_type)
2160 smartlist_t *tokens = smartlist_create();
2161 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2162 networkstatus_voter_info_t *voter = NULL;
2163 networkstatus_t *ns = NULL;
2164 char ns_digest[DIGEST_LEN];
2165 const char *cert, *end_of_header, *end_of_footer;
2166 directory_token_t *tok;
2167 int ok;
2168 struct in_addr in;
2169 int i, inorder, n_signatures = 0;
2170 memarea_t *area = NULL, *rs_area = NULL;
2171 tor_assert(s);
2173 if (router_get_networkstatus_v3_hash(s, ns_digest)) {
2174 log_warn(LD_DIR, "Unable to compute digest of network-status");
2175 goto err;
2178 area = memarea_new();
2179 end_of_header = find_start_of_next_routerstatus(s);
2180 if (tokenize_string(area, s, end_of_header, tokens,
2181 (ns_type == NS_TYPE_CONSENSUS) ?
2182 networkstatus_consensus_token_table :
2183 networkstatus_token_table, 0)) {
2184 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2185 goto err;
2188 ns = tor_malloc_zero(sizeof(networkstatus_t));
2189 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2191 if (ns_type != NS_TYPE_CONSENSUS) {
2192 const char *end_of_cert = NULL;
2193 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2194 goto err;
2195 ++cert;
2196 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2197 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2198 goto err;
2201 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2202 tor_assert(tok->n_args);
2203 if (!strcmp(tok->args[0], "vote")) {
2204 ns->type = NS_TYPE_VOTE;
2205 } else if (!strcmp(tok->args[0], "consensus")) {
2206 ns->type = NS_TYPE_CONSENSUS;
2207 } else if (!strcmp(tok->args[0], "opinion")) {
2208 ns->type = NS_TYPE_OPINION;
2209 } else {
2210 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2211 escaped(tok->args[0]));
2212 goto err;
2214 if (ns_type != ns->type) {
2215 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2216 goto err;
2219 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2220 tok = find_by_keyword(tokens, K_PUBLISHED);
2221 if (parse_iso_time(tok->args[0], &ns->published))
2222 goto err;
2224 ns->supported_methods = smartlist_create();
2225 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2226 if (tok) {
2227 for (i=0; i < tok->n_args; ++i)
2228 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2229 } else {
2230 smartlist_add(ns->supported_methods, tor_strdup("1"));
2232 } else {
2233 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2234 if (tok) {
2235 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2236 &ok, NULL);
2237 if (!ok)
2238 goto err;
2239 } else {
2240 ns->consensus_method = 1;
2244 tok = find_by_keyword(tokens, K_VALID_AFTER);
2245 if (parse_iso_time(tok->args[0], &ns->valid_after))
2246 goto err;
2248 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2249 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2250 goto err;
2252 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2253 if (parse_iso_time(tok->args[0], &ns->valid_until))
2254 goto err;
2256 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2257 tor_assert(tok->n_args >= 2);
2258 ns->vote_seconds =
2259 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2260 if (!ok)
2261 goto err;
2262 ns->dist_seconds =
2263 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2264 if (!ok)
2265 goto err;
2266 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2267 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2268 goto err;
2270 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2271 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2272 goto err;
2274 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2275 log_warn(LD_DIR, "Vote seconds is too short");
2276 goto err;
2278 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2279 log_warn(LD_DIR, "Dist seconds is too short");
2280 goto err;
2283 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2284 ns->client_versions = tor_strdup(tok->args[0]);
2286 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2287 ns->server_versions = tor_strdup(tok->args[0]);
2290 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2291 ns->known_flags = smartlist_create();
2292 inorder = 1;
2293 for (i = 0; i < tok->n_args; ++i) {
2294 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2295 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2296 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2297 inorder = 0;
2300 if (!inorder) {
2301 log_warn(LD_DIR, "known-flags not in order");
2302 goto err;
2305 ns->voters = smartlist_create();
2307 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2309 tok = _tok;
2310 if (tok->tp == K_DIR_SOURCE) {
2311 tor_assert(tok->n_args >= 6);
2313 if (voter)
2314 smartlist_add(ns->voters, voter);
2315 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2316 if (ns->type != NS_TYPE_CONSENSUS)
2317 memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
2319 voter->nickname = tor_strdup(tok->args[0]);
2320 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2321 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2322 tok->args[1], HEX_DIGEST_LEN) < 0) {
2323 log_warn(LD_DIR, "Error decoding identity digest %s in "
2324 "network-status vote.", escaped(tok->args[1]));
2325 goto err;
2327 if (ns->type != NS_TYPE_CONSENSUS &&
2328 memcmp(ns->cert->cache_info.identity_digest,
2329 voter->identity_digest, DIGEST_LEN)) {
2330 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2331 goto err;
2333 voter->address = tor_strdup(tok->args[2]);
2334 if (!tor_inet_aton(tok->args[3], &in)) {
2335 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2336 escaped(tok->args[3]));
2337 goto err;
2339 voter->addr = ntohl(in.s_addr);
2340 voter->dir_port = (uint16_t)
2341 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2342 if (!ok)
2343 goto err;
2344 voter->or_port = (uint16_t)
2345 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2346 if (!ok)
2347 goto err;
2348 } else if (tok->tp == K_CONTACT) {
2349 if (!voter || voter->contact) {
2350 log_warn(LD_DIR, "contact element is out of place.");
2351 goto err;
2353 voter->contact = tor_strdup(tok->args[0]);
2354 } else if (tok->tp == K_VOTE_DIGEST) {
2355 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2356 tor_assert(tok->n_args >= 1);
2357 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2358 log_warn(LD_DIR, "vote-digest element is out of place.");
2359 goto err;
2361 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2362 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2363 tok->args[0], HEX_DIGEST_LEN) < 0) {
2364 log_warn(LD_DIR, "Error decoding vote digest %s in "
2365 "network-status consensus.", escaped(tok->args[1]));
2366 goto err;
2370 if (voter) {
2371 smartlist_add(ns->voters, voter);
2372 voter = NULL;
2374 if (smartlist_len(ns->voters) == 0) {
2375 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2376 goto err;
2377 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
2378 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2379 goto err;
2382 if (ns->type != NS_TYPE_CONSENSUS &&
2383 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
2384 int bad = 1;
2385 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2386 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
2387 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
2388 tok->args[0], HEX_DIGEST_LEN)<0)
2389 bad = 1;
2390 else
2391 bad = 0;
2393 if (bad) {
2394 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
2395 escaped(tok->args[0]));
2399 /* Parse routerstatus lines. */
2400 rs_tokens = smartlist_create();
2401 rs_area = memarea_new();
2402 s = end_of_header;
2403 ns->routerstatus_list = smartlist_create();
2405 while (!strcmpstart(s, "r ")) {
2406 if (ns->type != NS_TYPE_CONSENSUS) {
2407 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2408 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
2409 rs, 0))
2410 smartlist_add(ns->routerstatus_list, rs);
2411 else {
2412 tor_free(rs->version);
2413 tor_free(rs);
2415 } else {
2416 routerstatus_t *rs;
2417 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
2418 NULL, NULL,
2419 ns->consensus_method)))
2420 smartlist_add(ns->routerstatus_list, rs);
2423 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2424 routerstatus_t *rs1, *rs2;
2425 if (ns->type != NS_TYPE_CONSENSUS) {
2426 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2427 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2428 rs1 = &a->status; rs2 = &b->status;
2429 } else {
2430 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2431 rs2 = smartlist_get(ns->routerstatus_list, i);
2433 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
2434 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2435 "digest");
2436 goto err;
2440 /* Parse footer; check signature. */
2441 footer_tokens = smartlist_create();
2442 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2443 ++end_of_footer;
2444 else
2445 end_of_footer = s + strlen(s);
2446 if (tokenize_string(area,s, end_of_footer, footer_tokens,
2447 networkstatus_vote_footer_token_table, 0)) {
2448 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2449 goto err;
2452 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
2454 char declared_identity[DIGEST_LEN];
2455 networkstatus_voter_info_t *v;
2456 tok = _tok;
2457 if (tok->tp != K_DIRECTORY_SIGNATURE)
2458 continue;
2459 tor_assert(tok->n_args >= 2);
2461 if (!tok->object_type ||
2462 strcmp(tok->object_type, "SIGNATURE") ||
2463 tok->object_size < 128 || tok->object_size > 512) {
2464 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2465 goto err;
2468 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2469 base16_decode(declared_identity, sizeof(declared_identity),
2470 tok->args[0], HEX_DIGEST_LEN) < 0) {
2471 log_warn(LD_DIR, "Error decoding declared identity %s in "
2472 "network-status vote.", escaped(tok->args[0]));
2473 goto err;
2475 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2476 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2477 "any declared directory source.");
2478 goto err;
2480 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2481 base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
2482 tok->args[1], HEX_DIGEST_LEN) < 0) {
2483 log_warn(LD_DIR, "Error decoding declared digest %s in "
2484 "network-status vote.", escaped(tok->args[1]));
2485 goto err;
2488 if (ns->type != NS_TYPE_CONSENSUS) {
2489 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
2490 DIGEST_LEN)) {
2491 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2492 "network-status vote.");
2493 goto err;
2497 if (ns->type != NS_TYPE_CONSENSUS) {
2498 if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
2499 "network-status vote"))
2500 goto err;
2501 v->good_signature = 1;
2502 } else {
2503 if (tok->object_size >= INT_MAX)
2504 goto err;
2505 v->signature = tor_memdup(tok->object_body, tok->object_size);
2506 v->signature_len = (int) tok->object_size;
2508 ++n_signatures;
2511 if (! n_signatures) {
2512 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2513 goto err;
2516 if (eos_out)
2517 *eos_out = end_of_footer;
2519 goto done;
2520 err:
2521 if (ns)
2522 networkstatus_vote_free(ns);
2523 ns = NULL;
2524 done:
2525 if (tokens) {
2526 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2527 smartlist_free(tokens);
2529 if (voter) {
2530 tor_free(voter->nickname);
2531 tor_free(voter->address);
2532 tor_free(voter->contact);
2533 tor_free(voter->signature);
2534 tor_free(voter);
2536 if (rs_tokens) {
2537 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
2538 smartlist_free(rs_tokens);
2540 if (footer_tokens) {
2541 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2542 smartlist_free(footer_tokens);
2544 if (area) {
2545 DUMP_AREA(area, "v3 networkstatus");
2546 memarea_drop_all(area);
2548 if (rs_area)
2549 memarea_drop_all(rs_area);
2551 return ns;
2554 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2555 * <b>eos</b> and return the result. Return -1 on failure. */
2556 ns_detached_signatures_t *
2557 networkstatus_parse_detached_signatures(const char *s, const char *eos)
2559 /* XXXX021 there is too much duplicate code here. */
2560 directory_token_t *tok;
2561 memarea_t *area = NULL;
2563 smartlist_t *tokens = smartlist_create();
2564 ns_detached_signatures_t *sigs =
2565 tor_malloc_zero(sizeof(ns_detached_signatures_t));
2567 if (!eos)
2568 eos = s + strlen(s);
2570 area = memarea_new();
2571 if (tokenize_string(area,s, eos, tokens,
2572 networkstatus_detached_signature_token_table, 0)) {
2573 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
2574 goto err;
2577 tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST);
2578 if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
2579 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
2580 "networkstatus signatures");
2581 goto err;
2583 if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
2584 tok->args[0], strlen(tok->args[0])) < 0) {
2585 log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
2586 "networkstatus signatures");
2587 goto err;
2590 tok = find_by_keyword(tokens, K_VALID_AFTER);
2591 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
2592 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
2593 goto err;
2596 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2597 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
2598 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
2599 goto err;
2602 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2603 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
2604 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
2605 goto err;
2608 sigs->signatures = smartlist_create();
2609 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2611 char id_digest[DIGEST_LEN];
2612 char sk_digest[DIGEST_LEN];
2613 networkstatus_voter_info_t *voter;
2615 tok = _tok;
2616 if (tok->tp != K_DIRECTORY_SIGNATURE)
2617 continue;
2618 tor_assert(tok->n_args >= 2);
2620 if (!tok->object_type ||
2621 strcmp(tok->object_type, "SIGNATURE") ||
2622 tok->object_size < 128 || tok->object_size > 512) {
2623 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2624 goto err;
2627 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2628 base16_decode(id_digest, sizeof(id_digest),
2629 tok->args[0], HEX_DIGEST_LEN) < 0) {
2630 log_warn(LD_DIR, "Error decoding declared identity %s in "
2631 "network-status vote.", escaped(tok->args[0]));
2632 goto err;
2634 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2635 base16_decode(sk_digest, sizeof(sk_digest),
2636 tok->args[1], HEX_DIGEST_LEN) < 0) {
2637 log_warn(LD_DIR, "Error decoding declared digest %s in "
2638 "network-status vote.", escaped(tok->args[1]));
2639 goto err;
2642 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2643 memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
2644 memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
2645 if (tok->object_size >= INT_MAX)
2646 goto err;
2647 voter->signature = tor_memdup(tok->object_body, tok->object_size);
2648 voter->signature_len = (int) tok->object_size;
2650 smartlist_add(sigs->signatures, voter);
2653 goto done;
2654 err:
2655 ns_detached_signatures_free(sigs);
2656 sigs = NULL;
2657 done:
2658 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2659 smartlist_free(tokens);
2660 if (area) {
2661 DUMP_AREA(area, "detached signatures");
2662 memarea_drop_all(area);
2664 return sigs;
2667 /** Parse the addr policy in the string <b>s</b> and return it. If
2668 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2669 * ADDR_POLICY_REJECT) for items that specify no action.
2671 addr_policy_t *
2672 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
2674 directory_token_t *tok = NULL;
2675 const char *cp, *eos;
2676 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2677 * But note that there can be an arbitrary amount of space between the
2678 * accept and the address:mask/port element. */
2679 char line[TOR_ADDR_BUF_LEN*2 + 32];
2680 addr_policy_t *r;
2681 memarea_t *area = NULL;
2683 s = eat_whitespace(s);
2684 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
2685 if (tor_snprintf(line, sizeof(line), "%s %s",
2686 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
2687 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
2688 return NULL;
2690 cp = line;
2691 tor_strlower(line);
2692 } else { /* assume an already well-formed address policy line */
2693 cp = s;
2696 eos = cp + strlen(cp);
2697 area = memarea_new();
2698 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
2699 if (tok->tp == _ERR) {
2700 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
2701 goto err;
2703 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
2704 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
2705 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
2706 goto err;
2709 r = router_parse_addr_policy(tok);
2710 goto done;
2711 err:
2712 r = NULL;
2713 done:
2714 token_free(tok);
2715 if (area) {
2716 DUMP_AREA(area, "policy item");
2717 memarea_drop_all(area);
2719 return r;
2722 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2723 * <b>router</b>. Return 0 on success, -1 on failure. */
2724 static int
2725 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
2727 addr_policy_t *newe;
2728 newe = router_parse_addr_policy(tok);
2729 if (!newe)
2730 return -1;
2731 if (! router->exit_policy)
2732 router->exit_policy = smartlist_create();
2734 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
2735 tor_addr_family(&newe->addr) == AF_INET)
2737 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
2738 tor_addr_family(&newe->addr) == AF_INET6)) {
2739 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
2740 "policy");
2741 addr_policy_free(newe);
2742 return -1;
2745 smartlist_add(router->exit_policy, newe);
2747 return 0;
2750 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2751 * a new exit_policy_t corresponding to the token. */
2752 static addr_policy_t *
2753 router_parse_addr_policy(directory_token_t *tok)
2755 addr_policy_t newe;
2756 char *arg;
2758 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
2759 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
2761 if (tok->n_args != 1)
2762 return NULL;
2763 arg = tok->args[0];
2765 if (!strcmpstart(arg,"private"))
2766 return router_parse_addr_policy_private(tok);
2768 memset(&newe, 0, sizeof(newe));
2770 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2771 newe.policy_type = ADDR_POLICY_REJECT;
2772 else
2773 newe.policy_type = ADDR_POLICY_ACCEPT;
2775 if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
2776 &newe.prt_min, &newe.prt_max) < 0) {
2777 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
2778 return NULL;
2781 return addr_policy_get_canonical_entry(&newe);
2784 /** Parse an exit policy line of the format "accept/reject private:...".
2785 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2786 * router descriptors until earlier versions are obsolete.
2788 static addr_policy_t *
2789 router_parse_addr_policy_private(directory_token_t *tok)
2791 const char *arg;
2792 uint16_t port_min, port_max;
2793 addr_policy_t result;
2795 arg = tok->args[0];
2796 if (strcmpstart(arg, "private"))
2797 return NULL;
2799 arg += strlen("private");
2800 arg = (char*) eat_whitespace(arg);
2801 if (!arg || *arg != ':')
2802 return NULL;
2804 if (parse_port_range(arg+1, &port_min, &port_max)<0)
2805 return NULL;
2807 memset(&result, 0, sizeof(result));
2808 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2809 result.policy_type = ADDR_POLICY_REJECT;
2810 else
2811 result.policy_type = ADDR_POLICY_ACCEPT;
2812 result.is_private = 1;
2813 result.prt_min = port_min;
2814 result.prt_max = port_max;
2816 return addr_policy_get_canonical_entry(&result);
2819 /** Log and exit if <b>t</b> is malformed */
2820 void
2821 assert_addr_policy_ok(smartlist_t *lst)
2823 if (!lst) return;
2824 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
2825 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
2826 t->policy_type == ADDR_POLICY_ACCEPT);
2827 tor_assert(t->prt_min <= t->prt_max);
2832 * Low-level tokenizer for router descriptors and directories.
2835 /** Free all resources allocated for <b>tok</b> */
2836 static void
2837 token_free(directory_token_t *tok)
2839 tor_assert(tok);
2840 if (tok->key)
2841 crypto_free_pk_env(tok->key);
2844 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
2845 #define ALLOC(sz) memarea_alloc(area,sz)
2846 #define STRDUP(str) memarea_strdup(area,str)
2847 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
2849 #define RET_ERR(msg) \
2850 STMT_BEGIN \
2851 if (tok) token_free(tok); \
2852 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
2853 tok->tp = _ERR; \
2854 tok->error = STRDUP(msg); \
2855 goto done_tokenizing; \
2856 STMT_END
2858 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
2859 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
2860 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
2861 * conform to the syntax we wanted.
2863 static INLINE directory_token_t *
2864 token_check_object(memarea_t *area, const char *kwd,
2865 directory_token_t *tok, obj_syntax o_syn)
2867 char ebuf[128];
2868 switch (o_syn) {
2869 case NO_OBJ:
2870 /* No object is allowed for this token. */
2871 if (tok->object_body) {
2872 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
2873 RET_ERR(ebuf);
2875 if (tok->key) {
2876 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
2877 RET_ERR(ebuf);
2879 break;
2880 case NEED_OBJ:
2881 /* There must be a (non-key) object. */
2882 if (!tok->object_body) {
2883 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
2884 RET_ERR(ebuf);
2886 break;
2887 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
2888 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
2889 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
2890 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
2891 kwd, (int)crypto_pk_keysize(tok->key));
2892 RET_ERR(ebuf);
2894 /* fall through */
2895 case NEED_KEY: /* There must be some kind of key. */
2896 if (!tok->key) {
2897 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
2899 if (o_syn != NEED_SKEY_1024) {
2900 if (crypto_pk_key_is_private(tok->key)) {
2901 tor_snprintf(ebuf, sizeof(ebuf),
2902 "Private key given for %s, which wants a public key", kwd);
2903 RET_ERR(ebuf);
2905 } else { /* o_syn == NEED_SKEY_1024 */
2906 if (!crypto_pk_key_is_private(tok->key)) {
2907 tor_snprintf(ebuf, sizeof(ebuf),
2908 "Public key given for %s, which wants a private key", kwd);
2909 RET_ERR(ebuf);
2912 break;
2913 case OBJ_OK:
2914 /* Anything goes with this token. */
2915 break;
2918 done_tokenizing:
2919 return tok;
2922 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
2923 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
2924 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
2925 * all storage in <b>area</b>. Return the number of arguments parsed, or
2926 * return -1 if there was an insanely high number of arguments. */
2927 static INLINE int
2928 get_token_arguments(memarea_t *area, directory_token_t *tok,
2929 const char *s, const char *eol)
2931 /** Largest number of arguments we'll accept to any token, ever. */
2932 #define MAX_ARGS 512
2933 char *mem = memarea_strndup(area, s, eol-s);
2934 char *cp = mem;
2935 int j = 0;
2936 char *args[MAX_ARGS];
2937 while (*cp) {
2938 if (j == MAX_ARGS)
2939 return -1;
2940 args[j++] = cp;
2941 cp = (char*)find_whitespace(cp);
2942 if (!cp || !*cp)
2943 break; /* End of the line. */
2944 *cp++ = '\0';
2945 cp = (char*)eat_whitespace(cp);
2947 tok->n_args = j;
2948 tok->args = memarea_memdup(area, args, j*sizeof(char*));
2949 return j;
2950 #undef MAX_ARGS
2953 /** Helper function: read the next token from *s, advance *s to the end of the
2954 * token, and return the parsed token. Parse *<b>s</b> according to the list
2955 * of tokens in <b>table</b>.
2957 static directory_token_t *
2958 get_next_token(memarea_t *area,
2959 const char **s, const char *eos, token_rule_t *table)
2961 const char *next, *eol, *obstart;
2962 size_t obname_len;
2963 int i;
2964 directory_token_t *tok;
2965 obj_syntax o_syn = NO_OBJ;
2966 char ebuf[128];
2967 const char *kwd = "";
2969 tor_assert(area);
2970 tok = ALLOC_ZERO(sizeof(directory_token_t));
2971 tok->tp = _ERR;
2973 /* Set *s to first token, eol to end-of-line, next to after first token */
2974 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
2975 tor_assert(eos >= *s);
2976 eol = memchr(*s, '\n', eos-*s);
2977 if (!eol)
2978 eol = eos;
2979 next = find_whitespace_eos(*s, eol);
2981 if (!strcmp_len(*s, "opt", next-*s)) {
2982 /* Skip past an "opt" at the start of the line. */
2983 *s = eat_whitespace_eos_no_nl(next, eol);
2984 next = find_whitespace_eos(*s, eol);
2985 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
2986 RET_ERR("Unexpected EOF");
2989 /* Search the table for the appropriate entry. (I tried a binary search
2990 * instead, but it wasn't any faster.) */
2991 for (i = 0; table[i].t ; ++i) {
2992 if (!strcmp_len(*s, table[i].t, next-*s)) {
2993 /* We've found the keyword. */
2994 kwd = table[i].t;
2995 tok->tp = table[i].v;
2996 o_syn = table[i].os;
2997 *s = eat_whitespace_eos_no_nl(next, eol);
2998 /* We go ahead whether there are arguments or not, so that tok->args is
2999 * always set if we want arguments. */
3000 if (table[i].concat_args) {
3001 /* The keyword takes the line as a single argument */
3002 tok->args = ALLOC(sizeof(char*));
3003 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3004 tok->n_args = 1;
3005 } else {
3006 /* This keyword takes multiple arguments. */
3007 if (get_token_arguments(area, tok, *s, eol)<0) {
3008 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3009 RET_ERR(ebuf);
3011 *s = eol;
3013 if (tok->n_args < table[i].min_args) {
3014 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3015 RET_ERR(ebuf);
3016 } else if (tok->n_args > table[i].max_args) {
3017 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3018 RET_ERR(ebuf);
3020 break;
3024 if (tok->tp == _ERR) {
3025 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3026 if (**s == '@')
3027 tok->tp = _A_UNKNOWN;
3028 else
3029 tok->tp = K_OPT;
3030 tok->args = ALLOC(sizeof(char*));
3031 tok->args[0] = STRNDUP(*s, eol-*s);
3032 tok->n_args = 1;
3033 o_syn = OBJ_OK;
3036 /* Check whether there's an object present */
3037 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3038 tor_assert(eos >= *s);
3039 eol = memchr(*s, '\n', eos-*s);
3040 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3041 goto check_object;
3043 obstart = *s; /* Set obstart to start of object spec */
3044 tor_assert(eol >= (*s+16));
3045 if (*s+11 >= eol-5 || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3046 strcmp_len(eol-5, "-----", 5)) { /* nuls or invalid endings */
3047 RET_ERR("Malformed object: bad begin line");
3049 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3050 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3051 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3053 /* Go to the end of the object */
3054 next = tor_memstr(*s, eos-*s, "-----END ");
3055 if (!next) {
3056 RET_ERR("Malformed object: missing object end line");
3058 tor_assert(eos >= next);
3059 eol = memchr(next, '\n', eos-next);
3060 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3061 eol = eos;
3062 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3063 if ((size_t)(eol-next) != 9+obname_len+5 ||
3064 strcmp_len(next+9, tok->object_type, obname_len) ||
3065 strcmp_len(eol-5, "-----", 5)) {
3066 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3067 tok->object_type);
3068 ebuf[sizeof(ebuf)-1] = '\0';
3069 RET_ERR(ebuf);
3071 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3072 tok->key = crypto_new_pk_env();
3073 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3074 RET_ERR("Couldn't parse public key.");
3075 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3076 tok->key = crypto_new_pk_env();
3077 if (crypto_pk_read_private_key_from_string(tok->key, obstart))
3078 RET_ERR("Couldn't parse private key.");
3079 } else { /* If it's something else, try to base64-decode it */
3080 int r;
3081 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3082 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3083 if (r<0)
3084 RET_ERR("Malformed object: bad base64-encoded data");
3085 tok->object_size = r;
3087 *s = eol;
3089 check_object:
3090 tok = token_check_object(area, kwd, tok, o_syn);
3092 done_tokenizing:
3093 return tok;
3095 #undef RET_ERR
3096 #undef ALLOC
3097 #undef ALLOC_ZERO
3098 #undef STRDUP
3099 #undef STRNDUP
3102 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3103 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3104 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3105 * entire string.
3107 static int
3108 tokenize_string(memarea_t *area,
3109 const char *start, const char *end, smartlist_t *out,
3110 token_rule_t *table, int flags)
3112 const char **s;
3113 directory_token_t *tok = NULL;
3114 int counts[_NIL];
3115 int i;
3116 int first_nonannotation;
3117 int prev_len = smartlist_len(out);
3118 tor_assert(area);
3120 s = &start;
3121 if (!end)
3122 end = start+strlen(start);
3123 for (i = 0; i < _NIL; ++i)
3124 counts[i] = 0;
3125 while (*s < end && (!tok || tok->tp != _EOF)) {
3126 tok = get_next_token(area, s, end, table);
3127 if (tok->tp == _ERR) {
3128 log_warn(LD_DIR, "parse error: %s", tok->error);
3129 token_free(tok);
3130 return -1;
3132 ++counts[tok->tp];
3133 smartlist_add(out, tok);
3134 *s = eat_whitespace_eos(*s, end);
3137 if (flags & TS_NOCHECK)
3138 return 0;
3140 if ((flags & TS_ANNOTATIONS_OK)) {
3141 first_nonannotation = -1;
3142 for (i = 0; i < smartlist_len(out); ++i) {
3143 tok = smartlist_get(out, i);
3144 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
3145 first_nonannotation = i;
3146 break;
3149 if (first_nonannotation < 0) {
3150 log_warn(LD_DIR, "parse error: item contains only annotations");
3151 return -1;
3153 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
3154 tok = smartlist_get(out, i);
3155 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3156 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
3157 return -1;
3160 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
3161 if (first_nonannotation != prev_len) {
3162 log_warn(LD_DIR, "parse error: Unexpectd annotations.");
3163 return -1;
3166 } else {
3167 for (i=0; i < smartlist_len(out); ++i) {
3168 tok = smartlist_get(out, i);
3169 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3170 log_warn(LD_DIR, "parse error: no annotations allowed.");
3171 return -1;
3174 first_nonannotation = 0;
3176 for (i = 0; table[i].t; ++i) {
3177 if (counts[table[i].v] < table[i].min_cnt) {
3178 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
3179 return -1;
3181 if (counts[table[i].v] > table[i].max_cnt) {
3182 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
3183 return -1;
3185 if (table[i].pos & AT_START) {
3186 if (smartlist_len(out) < 1 ||
3187 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
3188 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
3189 return -1;
3192 if (table[i].pos & AT_END) {
3193 if (smartlist_len(out) < 1 ||
3194 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
3195 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
3196 return -1;
3200 return 0;
3203 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3204 * NULL if no such keyword is found.
3206 static directory_token_t *
3207 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
3209 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
3210 return NULL;
3213 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3214 * with an assert if no such keyword is found.
3216 static directory_token_t *
3217 _find_by_keyword(smartlist_t *s, directory_keyword keyword,
3218 const char *keyword_as_string)
3220 directory_token_t *tok = find_opt_by_keyword(s, keyword);
3221 if (PREDICT_UNLIKELY(!tok)) {
3222 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
3223 "been validated. Internal error.", keyword_as_string, (int)keyword);
3224 tor_assert(tok);
3226 return tok;
3229 /** Return a newly allocated smartlist of all accept or reject tokens in
3230 * <b>s</b>.
3232 static smartlist_t *
3233 find_all_exitpolicy(smartlist_t *s)
3235 smartlist_t *out = smartlist_create();
3236 SMARTLIST_FOREACH(s, directory_token_t *, t,
3237 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
3238 t->tp == K_REJECT || t->tp == K_REJECT6)
3239 smartlist_add(out,t));
3240 return out;
3243 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
3244 * occurrence of <b>start_str</b> through the first instance of c after the
3245 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
3246 * <b>digest</b>; return 0 on success.
3248 * If no such substring exists, return -1.
3250 static int
3251 router_get_hash_impl(const char *s, char *digest,
3252 const char *start_str,
3253 const char *end_str, char end_c)
3255 char *start, *end;
3256 start = strstr(s, start_str);
3257 if (!start) {
3258 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
3259 return -1;
3261 if (start != s && *(start-1) != '\n') {
3262 log_warn(LD_DIR,
3263 "first occurrence of \"%s\" is not at the start of a line",
3264 start_str);
3265 return -1;
3267 end = strstr(start+strlen(start_str), end_str);
3268 if (!end) {
3269 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
3270 return -1;
3272 end = strchr(end+strlen(end_str), end_c);
3273 if (!end) {
3274 log_warn(LD_DIR,"couldn't find EOL");
3275 return -1;
3277 ++end;
3279 if (crypto_digest(digest, start, end-start)) {
3280 log_warn(LD_BUG,"couldn't compute digest");
3281 return -1;
3284 return 0;
3287 /** Parse the Tor version of the platform string <b>platform</b>,
3288 * and compare it to the version in <b>cutoff</b>. Return 1 if
3289 * the router is at least as new as the cutoff, else return 0.
3292 tor_version_as_new_as(const char *platform, const char *cutoff)
3294 tor_version_t cutoff_version, router_version;
3295 char *s, *s2, *start;
3296 char tmp[128];
3298 tor_assert(platform);
3300 if (tor_version_parse(cutoff, &cutoff_version)<0) {
3301 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
3302 return 0;
3304 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
3305 return 1;
3307 start = (char *)eat_whitespace(platform+3);
3308 if (!*start) return 0;
3309 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
3310 s2 = (char*)eat_whitespace(s);
3311 if (!strcmpstart(s2, "(r"))
3312 s = (char*)find_whitespace(s2);
3314 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
3315 return 0;
3316 strlcpy(tmp, start, s-start+1);
3318 if (tor_version_parse(tmp, &router_version)<0) {
3319 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
3320 return 1; /* be safe and say yes */
3323 /* Here's why we don't need to do any special handling for svn revisions:
3324 * - If neither has an svn revision, we're fine.
3325 * - If the router doesn't have an svn revision, we can't assume that it
3326 * is "at least" any svn revision, so we need to return 0.
3327 * - If the target version doesn't have an svn revision, any svn revision
3328 * (or none at all) is good enough, so return 1.
3329 * - If both target and router have an svn revision, we compare them.
3332 return tor_version_compare(&router_version, &cutoff_version) >= 0;
3335 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3336 * Return 0 on success, -1 on failure. */
3338 tor_version_parse(const char *s, tor_version_t *out)
3340 char *eos=NULL;
3341 const char *cp=NULL;
3342 /* Format is:
3343 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3345 tor_assert(s);
3346 tor_assert(out);
3348 memset(out, 0, sizeof(tor_version_t));
3350 if (!strcasecmpstart(s, "Tor "))
3351 s += 4;
3353 /* Get major. */
3354 out->major = (int)strtol(s,&eos,10);
3355 if (!eos || eos==s || *eos != '.') return -1;
3356 cp = eos+1;
3358 /* Get minor */
3359 out->minor = (int) strtol(cp,&eos,10);
3360 if (!eos || eos==cp || *eos != '.') return -1;
3361 cp = eos+1;
3363 /* Get micro */
3364 out->micro = (int) strtol(cp,&eos,10);
3365 if (!eos || eos==cp) return -1;
3366 if (!*eos) {
3367 out->status = VER_RELEASE;
3368 out->patchlevel = 0;
3369 return 0;
3371 cp = eos;
3373 /* Get status */
3374 if (*cp == '.') {
3375 out->status = VER_RELEASE;
3376 ++cp;
3377 } else if (0==strncmp(cp, "pre", 3)) {
3378 out->status = VER_PRE;
3379 cp += 3;
3380 } else if (0==strncmp(cp, "rc", 2)) {
3381 out->status = VER_RC;
3382 cp += 2;
3383 } else {
3384 return -1;
3387 /* Get patchlevel */
3388 out->patchlevel = (int) strtol(cp,&eos,10);
3389 if (!eos || eos==cp) return -1;
3390 cp = eos;
3392 /* Get status tag. */
3393 if (*cp == '-' || *cp == '.')
3394 ++cp;
3395 eos = (char*) find_whitespace(cp);
3396 if (eos-cp >= (int)sizeof(out->status_tag))
3397 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
3398 else {
3399 memcpy(out->status_tag, cp, eos-cp);
3400 out->status_tag[eos-cp] = 0;
3402 cp = eat_whitespace(eos);
3404 if (!strcmpstart(cp, "(r")) {
3405 cp += 2;
3406 out->svn_revision = (int) strtol(cp,&eos,10);
3409 return 0;
3412 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3413 * b. */
3415 tor_version_compare(tor_version_t *a, tor_version_t *b)
3417 int i;
3418 tor_assert(a);
3419 tor_assert(b);
3420 if ((i = a->major - b->major))
3421 return i;
3422 else if ((i = a->minor - b->minor))
3423 return i;
3424 else if ((i = a->micro - b->micro))
3425 return i;
3426 else if ((i = a->status - b->status))
3427 return i;
3428 else if ((i = a->patchlevel - b->patchlevel))
3429 return i;
3430 else if ((i = strcmp(a->status_tag, b->status_tag)))
3431 return i;
3432 else
3433 return a->svn_revision - b->svn_revision;
3436 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3438 static int
3439 tor_version_same_series(tor_version_t *a, tor_version_t *b)
3441 tor_assert(a);
3442 tor_assert(b);
3443 return ((a->major == b->major) &&
3444 (a->minor == b->minor) &&
3445 (a->micro == b->micro));
3448 /** Helper: Given pointers to two strings describing tor versions, return -1
3449 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
3450 * Used to sort a list of versions. */
3451 static int
3452 _compare_tor_version_str_ptr(const void **_a, const void **_b)
3454 const char *a = *_a, *b = *_b;
3455 int ca, cb;
3456 tor_version_t va, vb;
3457 ca = tor_version_parse(a, &va);
3458 cb = tor_version_parse(b, &vb);
3459 /* If they both parse, compare them. */
3460 if (!ca && !cb)
3461 return tor_version_compare(&va,&vb);
3462 /* If one parses, it comes first. */
3463 if (!ca && cb)
3464 return -1;
3465 if (ca && !cb)
3466 return 1;
3467 /* If neither parses, compare strings. Also, the directory server admin
3468 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3469 return strcmp(a,b);
3472 /** Sort a list of string-representations of versions in ascending order. */
3473 void
3474 sort_version_list(smartlist_t *versions, int remove_duplicates)
3476 smartlist_sort(versions, _compare_tor_version_str_ptr);
3478 if (remove_duplicates)
3479 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
3482 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3483 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3484 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3485 * encrypted introduction points to the newly allocated
3486 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3487 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3488 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3489 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3490 * and -1 for failure.
3493 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
3494 char *desc_id_out,
3495 char **intro_points_encrypted_out,
3496 size_t *intro_points_encrypted_size_out,
3497 size_t *encoded_size_out,
3498 const char **next_out, const char *desc)
3500 rend_service_descriptor_t *result =
3501 tor_malloc_zero(sizeof(rend_service_descriptor_t));
3502 char desc_hash[DIGEST_LEN];
3503 const char *eos;
3504 smartlist_t *tokens = smartlist_create();
3505 directory_token_t *tok;
3506 char secret_id_part[DIGEST_LEN];
3507 int i, version, num_ok=1;
3508 smartlist_t *versions;
3509 char public_key_hash[DIGEST_LEN];
3510 char test_desc_id[DIGEST_LEN];
3511 memarea_t *area = NULL;
3512 tor_assert(desc);
3513 /* Check if desc starts correctly. */
3514 if (strncmp(desc, "rendezvous-service-descriptor ",
3515 strlen("rendezvous-service-descriptor "))) {
3516 log_info(LD_REND, "Descriptor does not start correctly.");
3517 goto err;
3519 /* Compute descriptor hash for later validation. */
3520 if (router_get_hash_impl(desc, desc_hash,
3521 "rendezvous-service-descriptor ",
3522 "\nsignature", '\n') < 0) {
3523 log_warn(LD_REND, "Couldn't compute descriptor hash.");
3524 goto err;
3526 /* Determine end of string. */
3527 eos = strstr(desc, "\nrendezvous-service-descriptor ");
3528 if (!eos)
3529 eos = desc + strlen(desc);
3530 else
3531 eos = eos + 1;
3532 /* Check length. */
3533 if (strlen(desc) > REND_DESC_MAX_SIZE) {
3534 log_warn(LD_REND, "Descriptor length is %i which exceeds "
3535 "maximum rendezvous descriptor size of %i kilobytes.",
3536 (int)strlen(desc), REND_DESC_MAX_SIZE);
3537 goto err;
3539 /* Tokenize descriptor. */
3540 area = memarea_new();
3541 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
3542 log_warn(LD_REND, "Error tokenizing descriptor.");
3543 goto err;
3545 /* Set next to next descriptor, if available. */
3546 *next_out = eos;
3547 /* Set length of encoded descriptor. */
3548 *encoded_size_out = eos - desc;
3549 /* Check min allowed length of token list. */
3550 if (smartlist_len(tokens) < 7) {
3551 log_warn(LD_REND, "Impossibly short descriptor.");
3552 goto err;
3554 /* Parse base32-encoded descriptor ID. */
3555 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
3556 tor_assert(tok == smartlist_get(tokens, 0));
3557 tor_assert(tok->n_args == 1);
3558 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
3559 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
3560 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
3561 goto err;
3563 if (base32_decode(desc_id_out, DIGEST_LEN,
3564 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
3565 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
3566 tok->args[0]);
3567 goto err;
3569 /* Parse descriptor version. */
3570 tok = find_by_keyword(tokens, R_VERSION);
3571 tor_assert(tok->n_args == 1);
3572 result->version =
3573 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
3574 if (result->version != 2 || !num_ok) {
3575 /* If it's <2, it shouldn't be under this format. If the number
3576 * is greater than 2, we bumped it because we broke backward
3577 * compatibility. See how version numbers in our other formats
3578 * work. */
3579 log_warn(LD_REND, "Unrecognized descriptor version: %s",
3580 escaped(tok->args[0]));
3581 goto err;
3583 /* Parse public key. */
3584 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
3585 result->pk = tok->key;
3586 tok->key = NULL; /* Prevent free */
3587 /* Parse secret ID part. */
3588 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
3589 tor_assert(tok->n_args == 1);
3590 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
3591 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
3592 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
3593 goto err;
3595 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
3596 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
3597 tok->args[0]);
3598 goto err;
3600 /* Parse publication time -- up-to-date check is done when storing the
3601 * descriptor. */
3602 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
3603 tor_assert(tok->n_args == 1);
3604 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
3605 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
3606 goto err;
3608 /* Parse protocol versions. */
3609 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
3610 tor_assert(tok->n_args == 1);
3611 versions = smartlist_create();
3612 smartlist_split_string(versions, tok->args[0], ",",
3613 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3614 for (i = 0; i < smartlist_len(versions); i++) {
3615 version = (int) tor_parse_long(smartlist_get(versions, i),
3616 10, 0, INT_MAX, &num_ok, NULL);
3617 if (!num_ok) /* It's a string; let's ignore it. */
3618 continue;
3619 result->protocols |= 1 << version;
3621 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
3622 smartlist_free(versions);
3623 /* Parse encrypted introduction points. Don't verify. */
3624 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
3625 if (tok) {
3626 if (strcmp(tok->object_type, "MESSAGE")) {
3627 log_warn(LD_DIR, "Bad object type: introduction points should be of "
3628 "type MESSAGE");
3629 goto err;
3631 *intro_points_encrypted_out = tor_memdup(tok->object_body,
3632 tok->object_size);
3633 *intro_points_encrypted_size_out = tok->object_size;
3634 } else {
3635 *intro_points_encrypted_out = NULL;
3636 *intro_points_encrypted_size_out = 0;
3638 /* Parse and verify signature. */
3639 tok = find_by_keyword(tokens, R_SIGNATURE);
3640 note_crypto_pk_op(VERIFY_RTR);
3641 if (check_signature_token(desc_hash, tok, result->pk, 0,
3642 "v2 rendezvous service descriptor") < 0)
3643 goto err;
3644 /* Verify that descriptor ID belongs to public key and secret ID part. */
3645 crypto_pk_get_digest(result->pk, public_key_hash);
3646 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
3647 secret_id_part);
3648 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
3649 log_warn(LD_REND, "Parsed descriptor ID does not match "
3650 "computed descriptor ID.");
3651 goto err;
3653 goto done;
3654 err:
3655 if (result)
3656 rend_service_descriptor_free(result);
3657 result = NULL;
3658 done:
3659 if (tokens) {
3660 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3661 smartlist_free(tokens);
3663 if (area)
3664 memarea_drop_all(area);
3665 *parsed_out = result;
3666 if (result)
3667 return 0;
3668 return -1;
3671 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
3672 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
3673 * write the result to a newly allocated string that is pointed to by
3674 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
3675 * Return 0 if decryption was successful and -1 otherwise. */
3677 rend_decrypt_introduction_points(char **ipos_decrypted,
3678 size_t *ipos_decrypted_size,
3679 const char *descriptor_cookie,
3680 const char *ipos_encrypted,
3681 size_t ipos_encrypted_size)
3683 tor_assert(ipos_encrypted);
3684 tor_assert(descriptor_cookie);
3685 if (ipos_encrypted_size < 2) {
3686 log_warn(LD_REND, "Size of encrypted introduction points is too "
3687 "small.");
3688 return -1;
3690 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
3691 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
3692 session_key[CIPHER_KEY_LEN], *dec;
3693 int declen, client_blocks;
3694 size_t pos = 0, len, client_entries_len;
3695 crypto_digest_env_t *digest;
3696 crypto_cipher_env_t *cipher;
3697 client_blocks = (int) ipos_encrypted[1];
3698 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
3699 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
3700 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
3701 log_warn(LD_REND, "Size of encrypted introduction points is too "
3702 "small.");
3703 return -1;
3705 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
3706 digest = crypto_new_digest_env();
3707 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
3708 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
3709 crypto_digest_get_digest(digest, client_id,
3710 REND_BASIC_AUTH_CLIENT_ID_LEN);
3711 crypto_free_digest_env(digest);
3712 for (pos = 2; pos < 2 + client_entries_len;
3713 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
3714 if (!memcmp(ipos_encrypted + pos, client_id,
3715 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
3716 /* Attempt to decrypt introduction points. */
3717 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3718 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
3719 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
3720 CIPHER_KEY_LEN) < 0) {
3721 log_warn(LD_REND, "Could not decrypt session key for client.");
3722 crypto_free_cipher_env(cipher);
3723 return -1;
3725 crypto_free_cipher_env(cipher);
3726 cipher = crypto_create_init_cipher(session_key, 0);
3727 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
3728 dec = tor_malloc(len);
3729 declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
3730 ipos_encrypted + 2 + client_entries_len,
3731 ipos_encrypted_size - 2 - client_entries_len);
3732 crypto_free_cipher_env(cipher);
3733 if (declen < 0) {
3734 log_warn(LD_REND, "Could not decrypt introduction point string.");
3735 tor_free(dec);
3736 return -1;
3738 if (memcmpstart(dec, declen, "introduction-point ")) {
3739 log_warn(LD_REND, "Decrypted introduction points don't "
3740 "look like we could parse them.");
3741 tor_free(dec);
3742 continue;
3744 *ipos_decrypted = dec;
3745 *ipos_decrypted_size = declen;
3746 return 0;
3749 log_warn(LD_REND, "Could not decrypt introduction points. Please "
3750 "check your authorization for this service!");
3751 return -1;
3752 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
3753 crypto_cipher_env_t *cipher;
3754 char *dec;
3755 int declen;
3756 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
3757 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3758 declen = crypto_cipher_decrypt_with_iv(cipher, dec,
3759 ipos_encrypted_size -
3760 CIPHER_IV_LEN - 1,
3761 ipos_encrypted + 1,
3762 ipos_encrypted_size - 1);
3763 crypto_free_cipher_env(cipher);
3764 if (declen < 0) {
3765 log_warn(LD_REND, "Decrypting introduction points failed!");
3766 tor_free(dec);
3767 return -1;
3769 *ipos_decrypted = dec;
3770 *ipos_decrypted_size = declen;
3771 return 0;
3772 } else {
3773 log_warn(LD_REND, "Unknown authorization type number: %d",
3774 ipos_encrypted[0]);
3775 return -1;
3779 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
3780 * length <b>intro_points_encoded_size</b> and write the result to the
3781 * descriptor in <b>parsed</b>; return the number of successfully parsed
3782 * introduction points or -1 in case of a failure. */
3784 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
3785 const char *intro_points_encoded,
3786 size_t intro_points_encoded_size)
3788 const char *current_ipo, *end_of_intro_points;
3789 smartlist_t *tokens;
3790 directory_token_t *tok;
3791 rend_intro_point_t *intro;
3792 extend_info_t *info;
3793 int result, num_ok=1;
3794 memarea_t *area = NULL;
3795 tor_assert(parsed);
3796 /** Function may only be invoked once. */
3797 tor_assert(!parsed->intro_nodes);
3798 tor_assert(intro_points_encoded);
3799 tor_assert(intro_points_encoded_size > 0);
3800 /* Consider one intro point after the other. */
3801 current_ipo = intro_points_encoded;
3802 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
3803 tokens = smartlist_create();
3804 parsed->intro_nodes = smartlist_create();
3805 area = memarea_new();
3807 while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
3808 "introduction-point ")) {
3809 /* Determine end of string. */
3810 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
3811 "\nintroduction-point ");
3812 if (!eos)
3813 eos = end_of_intro_points;
3814 else
3815 eos = eos+1;
3816 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
3817 /* Free tokens and clear token list. */
3818 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3819 smartlist_clear(tokens);
3820 memarea_clear(area);
3821 /* Tokenize string. */
3822 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
3823 log_warn(LD_REND, "Error tokenizing introduction point");
3824 goto err;
3826 /* Advance to next introduction point, if available. */
3827 current_ipo = eos;
3828 /* Check minimum allowed length of introduction point. */
3829 if (smartlist_len(tokens) < 5) {
3830 log_warn(LD_REND, "Impossibly short introduction point.");
3831 goto err;
3833 /* Allocate new intro point and extend info. */
3834 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3835 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
3836 /* Parse identifier. */
3837 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
3838 if (base32_decode(info->identity_digest, DIGEST_LEN,
3839 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
3840 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
3841 tok->args[0]);
3842 rend_intro_point_free(intro);
3843 goto err;
3845 /* Write identifier to nickname. */
3846 info->nickname[0] = '$';
3847 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
3848 info->identity_digest, DIGEST_LEN);
3849 /* Parse IP address. */
3850 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
3851 if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
3852 log_warn(LD_REND, "Could not parse introduction point address.");
3853 rend_intro_point_free(intro);
3854 goto err;
3856 if (tor_addr_family(&info->addr) != AF_INET) {
3857 log_warn(LD_REND, "Introduction point address was not ipv4.");
3858 rend_intro_point_free(intro);
3859 goto err;
3862 /* Parse onion port. */
3863 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
3864 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
3865 &num_ok,NULL);
3866 if (!info->port || !num_ok) {
3867 log_warn(LD_REND, "Introduction point onion port %s is invalid",
3868 escaped(tok->args[0]));
3869 rend_intro_point_free(intro);
3870 goto err;
3872 /* Parse onion key. */
3873 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
3874 info->onion_key = tok->key;
3875 tok->key = NULL; /* Prevent free */
3876 /* Parse service key. */
3877 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
3878 intro->intro_key = tok->key;
3879 tok->key = NULL; /* Prevent free */
3880 /* Add extend info to list of introduction points. */
3881 smartlist_add(parsed->intro_nodes, intro);
3883 result = smartlist_len(parsed->intro_nodes);
3884 goto done;
3886 err:
3887 result = -1;
3889 done:
3890 /* Free tokens and clear token list. */
3891 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3892 smartlist_free(tokens);
3893 if (area)
3894 memarea_drop_all(area);
3896 return result;
3899 /** Parse the content of a client_key file in <b>ckstr</b> and add
3900 * rend_authorized_client_t's for each parsed client to
3901 * <b>parsed_clients</b>. Return the number of parsed clients as result
3902 * or -1 for failure. */
3904 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
3906 int result = -1;
3907 smartlist_t *tokens;
3908 directory_token_t *tok;
3909 const char *current_entry = NULL;
3910 memarea_t *area = NULL;
3911 if (!ckstr || strlen(ckstr) == 0)
3912 return -1;
3913 tokens = smartlist_create();
3914 /* Begin parsing with first entry, skipping comments or whitespace at the
3915 * beginning. */
3916 area = memarea_new();
3917 current_entry = eat_whitespace(ckstr);
3918 while (!strcmpstart(current_entry, "client-name ")) {
3919 rend_authorized_client_t *parsed_entry;
3920 size_t len;
3921 char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
3922 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
3923 /* Determine end of string. */
3924 const char *eos = strstr(current_entry, "\nclient-name ");
3925 if (!eos)
3926 eos = current_entry + strlen(current_entry);
3927 else
3928 eos = eos + 1;
3929 /* Free tokens and clear token list. */
3930 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3931 smartlist_clear(tokens);
3932 memarea_clear(area);
3933 /* Tokenize string. */
3934 if (tokenize_string(area, current_entry, eos, tokens,
3935 client_keys_token_table, 0)) {
3936 log_warn(LD_REND, "Error tokenizing client keys file.");
3937 goto err;
3939 /* Advance to next entry, if available. */
3940 current_entry = eos;
3941 /* Check minimum allowed length of token list. */
3942 if (smartlist_len(tokens) < 2) {
3943 log_warn(LD_REND, "Impossibly short client key entry.");
3944 goto err;
3946 /* Parse client name. */
3947 tok = find_by_keyword(tokens, C_CLIENT_NAME);
3948 tor_assert(tok == smartlist_get(tokens, 0));
3949 tor_assert(tok->n_args == 1);
3951 len = strlen(tok->args[0]);
3952 if (len < 1 || len > 19 ||
3953 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
3954 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
3955 "between 1 and 19, and valid characters are "
3956 "[A-Za-z0-9+-_].)", tok->args[0]);
3957 goto err;
3959 /* Check if client name is duplicate. */
3960 if (strmap_get(parsed_clients, tok->args[0])) {
3961 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
3962 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
3963 goto err;
3965 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
3966 parsed_entry->client_name = tor_strdup(tok->args[0]);
3967 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
3968 /* Parse client key. */
3969 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
3970 if (tok) {
3971 parsed_entry->client_key = tok->key;
3972 tok->key = NULL; /* Prevent free */
3975 /* Parse descriptor cookie. */
3976 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
3977 tor_assert(tok->n_args == 1);
3978 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
3979 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
3980 escaped(tok->args[0]));
3981 goto err;
3983 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
3984 * because a base64 encoding of length 24 does not fit into 16 bytes in all
3985 * cases. */
3986 if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
3987 tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
3988 != REND_DESC_COOKIE_LEN)) {
3989 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
3990 "%s", descriptor_cookie_base64);
3991 goto err;
3993 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
3994 REND_DESC_COOKIE_LEN);
3996 result = strmap_size(parsed_clients);
3997 goto done;
3998 err:
3999 result = -1;
4000 done:
4001 /* Free tokens and clear token list. */
4002 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4003 smartlist_free(tokens);
4004 if (area)
4005 memarea_drop_all(area);
4006 return result;