uh, and commit the patch too.
[tor.git] / src / or / routerparse.c
blob444f22a2a20285fe7180604666d7bb491b41c965
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 */
7 /**
8 * \file routerparse.c
9 * \brief Code to parse and validate router descriptors and directories.
10 **/
12 #include "or.h"
13 #include "memarea.h"
15 /****************************************************************************/
17 /** Enumeration of possible token types. The ones starting with K_ correspond
18 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
19 * is an end-of-file marker, and _NIL is used to encode not-a-token.
21 typedef enum {
22 K_ACCEPT = 0,
23 K_ACCEPT6,
24 K_DIRECTORY_SIGNATURE,
25 K_RECOMMENDED_SOFTWARE,
26 K_REJECT,
27 K_REJECT6,
28 K_ROUTER,
29 K_SIGNED_DIRECTORY,
30 K_SIGNING_KEY,
31 K_ONION_KEY,
32 K_ROUTER_SIGNATURE,
33 K_PUBLISHED,
34 K_RUNNING_ROUTERS,
35 K_ROUTER_STATUS,
36 K_PLATFORM,
37 K_OPT,
38 K_BANDWIDTH,
39 K_CONTACT,
40 K_NETWORK_STATUS,
41 K_UPTIME,
42 K_DIR_SIGNING_KEY,
43 K_FAMILY,
44 K_FINGERPRINT,
45 K_HIBERNATING,
46 K_READ_HISTORY,
47 K_WRITE_HISTORY,
48 K_NETWORK_STATUS_VERSION,
49 K_DIR_SOURCE,
50 K_DIR_OPTIONS,
51 K_CLIENT_VERSIONS,
52 K_SERVER_VERSIONS,
53 K_P,
54 K_R,
55 K_S,
56 K_V,
57 K_W,
58 K_EVENTDNS,
59 K_EXTRA_INFO,
60 K_EXTRA_INFO_DIGEST,
61 K_CACHES_EXTRA_INFO,
62 K_HIDDEN_SERVICE_DIR,
63 K_ALLOW_SINGLE_HOP_EXITS,
65 K_DIR_KEY_CERTIFICATE_VERSION,
66 K_DIR_IDENTITY_KEY,
67 K_DIR_KEY_PUBLISHED,
68 K_DIR_KEY_EXPIRES,
69 K_DIR_KEY_CERTIFICATION,
70 K_DIR_KEY_CROSSCERT,
71 K_DIR_ADDRESS,
73 K_VOTE_STATUS,
74 K_VALID_AFTER,
75 K_FRESH_UNTIL,
76 K_VALID_UNTIL,
77 K_VOTING_DELAY,
79 K_KNOWN_FLAGS,
80 K_VOTE_DIGEST,
81 K_CONSENSUS_DIGEST,
82 K_CONSENSUS_METHODS,
83 K_CONSENSUS_METHOD,
84 K_LEGACY_DIR_KEY,
86 A_PURPOSE,
87 _A_UNKNOWN,
89 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
90 R_VERSION,
91 R_PERMANENT_KEY,
92 R_SECRET_ID_PART,
93 R_PUBLICATION_TIME,
94 R_PROTOCOL_VERSIONS,
95 R_INTRODUCTION_POINTS,
96 R_SIGNATURE,
98 R_IPO_IDENTIFIER,
99 R_IPO_IP_ADDRESS,
100 R_IPO_ONION_PORT,
101 R_IPO_ONION_KEY,
102 R_IPO_SERVICE_KEY,
104 C_CLIENT_NAME,
105 C_DESCRIPTOR_COOKIE,
106 C_CLIENT_KEY,
108 _ERR,
109 _EOF,
110 _NIL
111 } directory_keyword;
113 #define MIN_ANNOTATION A_PURPOSE
114 #define MAX_ANNOTATION _A_UNKNOWN
116 /** Structure to hold a single directory token.
118 * We parse a directory by breaking it into "tokens", each consisting
119 * of a keyword, a line full of arguments, and a binary object. The
120 * arguments and object are both optional, depending on the keyword
121 * type.
123 * This structure is only allocated in memareas; do not allocate it on
124 * the heap, or token_free() won't work.
126 typedef struct directory_token_t {
127 directory_keyword tp; /**< Type of the token. */
128 int n_args:30; /**< Number of elements in args */
129 char **args; /**< Array of arguments from keyword line. */
131 char *object_type; /**< -----BEGIN [object_type]-----*/
132 size_t object_size; /**< Bytes in object_body */
133 char *object_body; /**< Contents of object, base64-decoded. */
135 crypto_pk_env_t *key; /**< For public keys only. Heap-allocated. */
137 char *error; /**< For _ERR tokens only. */
138 } directory_token_t;
140 /* ********************************************************************** */
142 /** We use a table of rules to decide how to parse each token type. */
144 /** Rules for whether the keyword needs an object. */
145 typedef enum {
146 NO_OBJ, /**< No object, ever. */
147 NEED_OBJ, /**< Object is required. */
148 NEED_SKEY_1024,/**< Object is required, and must be a 1024 bit private key */
149 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
150 NEED_KEY, /**< Object is required, and must be a public key. */
151 OBJ_OK, /**< Object is optional. */
152 } obj_syntax;
154 #define AT_START 1
155 #define AT_END 2
157 /** Determines the parsing rules for a single token type. */
158 typedef struct token_rule_t {
159 /** The string value of the keyword identifying the type of item. */
160 const char *t;
161 /** The corresponding directory_keyword enum. */
162 directory_keyword v;
163 /** Minimum number of arguments for this item */
164 int min_args;
165 /** Maximum number of arguments for this item */
166 int max_args;
167 /** If true, we concatenate all arguments for this item into a single
168 * string. */
169 int concat_args;
170 /** Requirments on object syntax for this item. */
171 obj_syntax os;
172 /** Lowest number of times this item may appear in a document. */
173 int min_cnt;
174 /** Highest number of times this item may appear in a document. */
175 int max_cnt;
176 /** One or more of AT_START/AT_END to limit where the item may appear in a
177 * document. */
178 int pos;
179 /** True iff this token is an annotation. */
180 int is_annotation;
181 } token_rule_t;
184 * Helper macros to define token tables. 's' is a string, 't' is a
185 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
186 * object syntax.
190 /** Appears to indicate the end of a table. */
191 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
192 /** An item with no restrictions: used for obsolete document types */
193 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
194 /** An item with no restrictions on multiplicity or location. */
195 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
196 /** An item that must appear exactly once */
197 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
198 /** An item that must appear exactly once, at the start of the document */
199 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
200 /** An item that must appear exactly once, at the end of the document */
201 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
202 /** An item that must appear one or more times */
203 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
204 /** An item that must appear no more than once */
205 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
206 /** An annotation that must appear no more than once */
207 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 1 }
209 /* Argument multiplicity: any number of arguments. */
210 #define ARGS 0,INT_MAX,0
211 /* Argument multiplicity: no arguments. */
212 #define NO_ARGS 0,0,0
213 /* Argument multiplicity: concatenate all arguments. */
214 #define CONCAT_ARGS 1,1,1
215 /* Argument multiplicity: at least <b>n</b> arguments. */
216 #define GE(n) n,INT_MAX,0
217 /* Argument multiplicity: exactly <b>n</b> arguments. */
218 #define EQ(n) n,n,0
220 /** List of tokens allowable in router derscriptors */
221 static token_rule_t routerdesc_token_table[] = {
222 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
223 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
224 T0N("reject6", K_REJECT6, ARGS, NO_OBJ ),
225 T0N("accept6", K_ACCEPT6, ARGS, NO_OBJ ),
226 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
227 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
228 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
229 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
230 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
231 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
232 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
233 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
234 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
235 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
236 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
237 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
238 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
239 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
240 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS, NO_ARGS, NO_OBJ ),
242 T01("family", K_FAMILY, ARGS, NO_OBJ ),
243 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
244 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
246 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
247 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
248 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
250 END_OF_TABLE
253 /** List of tokens allowable in extra-info documents. */
254 static token_rule_t extrainfo_token_table[] = {
255 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
256 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
257 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
258 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
259 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
260 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
262 END_OF_TABLE
265 /** List of tokens allowable in the body part of v2 and v3 networkstatus
266 * documents. */
267 static token_rule_t rtrstatus_token_table[] = {
268 T01("p", K_P, CONCAT_ARGS, NO_OBJ ),
269 T1( "r", K_R, GE(8), NO_OBJ ),
270 T1( "s", K_S, ARGS, NO_OBJ ),
271 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
272 T01("w", K_W, ARGS, NO_OBJ ),
273 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
274 END_OF_TABLE
277 /** List of tokens allowable in the header part of v2 networkstatus documents.
279 static token_rule_t netstatus_token_table[] = {
280 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
281 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
282 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
283 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
284 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
285 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
286 GE(1), NO_OBJ ),
287 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
288 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
289 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
290 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
292 END_OF_TABLE
295 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
296 * footers. */
297 static token_rule_t dir_footer_token_table[] = {
298 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
299 END_OF_TABLE
302 /** List of tokens allowable in v1 directory headers/footers. */
303 static token_rule_t dir_token_table[] = {
304 /* don't enforce counts; this is obsolete. */
305 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
306 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
307 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
308 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
310 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
311 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
312 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
313 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
314 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
315 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
316 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
318 END_OF_TABLE
321 /** List of tokens common to V3 authority certificates and V3 consensuses. */
322 #define CERTIFICATE_MEMBERS \
323 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
324 GE(1), NO_OBJ ), \
325 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
326 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
327 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
328 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
329 T01("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
330 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
331 NO_ARGS, NEED_OBJ), \
332 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
334 /** List of tokens allowable in V3 authority certificates. */
335 static token_rule_t dir_key_certificate_table[] = {
336 CERTIFICATE_MEMBERS
337 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
338 END_OF_TABLE
341 /** List of tokens allowable in rendezvous service descriptors */
342 static token_rule_t desc_token_table[] = {
343 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
344 EQ(1), NO_OBJ),
345 T1("version", R_VERSION, EQ(1), NO_OBJ),
346 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
347 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
348 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
349 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
350 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
351 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
352 END_OF_TABLE
355 /** List of tokens allowed in the (encrypted) list of introduction points of
356 * rendezvous service descriptors */
357 static token_rule_t ipo_token_table[] = {
358 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
359 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
360 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
361 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
362 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
363 END_OF_TABLE
366 /** List of tokens allowed in the (possibly encrypted) list of introduction
367 * points of rendezvous service descriptors */
368 static token_rule_t client_keys_token_table[] = {
369 T1_START("client-name", C_CLIENT_NAME, CONCAT_ARGS, NO_OBJ),
370 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE, EQ(1), NO_OBJ),
371 T01("client-key", C_CLIENT_KEY, NO_ARGS, NEED_SKEY_1024),
372 END_OF_TABLE
375 /** List of tokens allowed in V3 networkstatus votes. */
376 static token_rule_t networkstatus_token_table[] = {
377 T1("network-status-version", K_NETWORK_STATUS_VERSION,
378 GE(1), NO_OBJ ),
379 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
380 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
381 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
382 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
383 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
384 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
385 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
386 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
388 CERTIFICATE_MEMBERS
390 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
391 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
392 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
393 T01("legacy-dir-key", K_LEGACY_DIR_KEY, GE(1), NO_OBJ ),
394 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
395 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
396 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
397 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
399 END_OF_TABLE
402 /** List of tokens allowed in V3 networkstatus consensuses. */
403 static token_rule_t networkstatus_consensus_token_table[] = {
404 T1("network-status-version", K_NETWORK_STATUS_VERSION,
405 GE(1), NO_OBJ ),
406 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
407 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
408 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
409 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
410 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
412 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
414 T1N("dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
415 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
416 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
418 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
420 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
421 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
422 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
424 END_OF_TABLE
427 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
428 * footers. */
429 static token_rule_t networkstatus_vote_footer_token_table[] = {
430 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
431 END_OF_TABLE
434 /** List of tokens allowable in detached networkstatus signature documents. */
435 static token_rule_t networkstatus_detached_signature_token_table[] = {
436 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
437 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
438 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
439 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
440 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
441 END_OF_TABLE
444 #undef T
446 /* static function prototypes */
447 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
448 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok);
449 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
451 static int router_get_hash_impl(const char *s, char *digest,
452 const char *start_str, const char *end_str,
453 char end_char);
454 static void token_free(directory_token_t *tok);
455 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
456 static directory_token_t *_find_by_keyword(smartlist_t *s,
457 directory_keyword keyword,
458 const char *keyword_str);
459 #define find_by_keyword(s, keyword) _find_by_keyword((s), (keyword), #keyword)
460 static directory_token_t *find_opt_by_keyword(smartlist_t *s,
461 directory_keyword keyword);
463 #define TS_ANNOTATIONS_OK 1
464 #define TS_NOCHECK 2
465 #define TS_NO_NEW_ANNOTATIONS 4
466 static int tokenize_string(memarea_t *area,
467 const char *start, const char *end,
468 smartlist_t *out,
469 token_rule_t *table,
470 int flags);
471 static directory_token_t *get_next_token(memarea_t *area,
472 const char **s,
473 const char *eos,
474 token_rule_t *table);
475 #define CST_CHECK_AUTHORITY (1<<0)
476 #define CST_NO_CHECK_OBJTYPE (1<<1)
477 static int check_signature_token(const char *digest,
478 directory_token_t *tok,
479 crypto_pk_env_t *pkey,
480 int flags,
481 const char *doctype);
482 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
483 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
485 #undef DEBUG_AREA_ALLOC
487 #ifdef DEBUG_AREA_ALLOC
488 #define DUMP_AREA(a,name) STMT_BEGIN \
489 size_t alloc=0, used=0; \
490 memarea_get_stats((a),&alloc,&used); \
491 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
492 name, (unsigned long)alloc, (unsigned long)used); \
493 STMT_END
494 #else
495 #define DUMP_AREA(a,name) STMT_NIL
496 #endif
498 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
499 * <b>s</b>. Return 0 on success, -1 on failure.
502 router_get_dir_hash(const char *s, char *digest)
504 return router_get_hash_impl(s,digest,
505 "signed-directory","\ndirectory-signature",'\n');
508 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
509 * <b>s</b>. Return 0 on success, -1 on failure.
512 router_get_router_hash(const char *s, char *digest)
514 return router_get_hash_impl(s,digest,
515 "router ","\nrouter-signature", '\n');
518 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
519 * string in <b>s</b>. Return 0 on success, -1 on failure.
522 router_get_runningrouters_hash(const char *s, char *digest)
524 return router_get_hash_impl(s,digest,
525 "network-status","\ndirectory-signature", '\n');
528 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
529 * string in <b>s</b>. Return 0 on success, -1 on failure. */
531 router_get_networkstatus_v2_hash(const char *s, char *digest)
533 return router_get_hash_impl(s,digest,
534 "network-status-version","\ndirectory-signature",
535 '\n');
538 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
539 * string in <b>s</b>. Return 0 on success, -1 on failure. */
541 router_get_networkstatus_v3_hash(const char *s, char *digest)
543 return router_get_hash_impl(s,digest,
544 "network-status-version","\ndirectory-signature",
545 ' ');
548 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
549 * string in <b>s</b>. Return 0 on success, -1 on failure. */
551 router_get_extrainfo_hash(const char *s, char *digest)
553 return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature",'\n');
556 /** Helper: used to generate signatures for routers, directories and
557 * network-status objects. Given a digest in <b>digest</b> and a secret
558 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
559 * surround it with -----BEGIN/END----- pairs, and write it to the
560 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
561 * failure.
564 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
565 crypto_pk_env_t *private_key)
567 char *signature;
568 size_t i;
570 signature = tor_malloc(crypto_pk_keysize(private_key));
571 if (crypto_pk_private_sign(private_key, signature, digest, DIGEST_LEN) < 0) {
573 log_warn(LD_BUG,"Couldn't sign digest.");
574 goto err;
576 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
577 goto truncated;
579 i = strlen(buf);
580 if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) {
581 log_warn(LD_BUG,"couldn't base64-encode signature");
582 goto err;
585 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
586 goto truncated;
588 tor_free(signature);
589 return 0;
591 truncated:
592 log_warn(LD_BUG,"tried to exceed string length.");
593 err:
594 tor_free(signature);
595 return -1;
598 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
599 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
600 * entries. Else, return VS_OLD if every member of
601 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
602 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
603 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
604 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
605 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
606 * VS_UNRECOMMENDED.
608 * (versionlist is a comma-separated list of version strings,
609 * optionally prefixed with "Tor". Versions that can't be parsed are
610 * ignored.)
612 version_status_t
613 tor_version_is_obsolete(const char *myversion, const char *versionlist)
615 tor_version_t mine, other;
616 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
617 found_any_in_series = 0, r, same;
618 version_status_t ret = VS_UNRECOMMENDED;
619 smartlist_t *version_sl;
621 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
622 myversion, versionlist);
624 if (tor_version_parse(myversion, &mine)) {
625 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
626 tor_assert(0);
628 version_sl = smartlist_create();
629 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
631 if (!strlen(versionlist)) { /* no authorities cared or agreed */
632 ret = VS_EMPTY;
633 goto done;
636 SMARTLIST_FOREACH(version_sl, const char *, cp, {
637 if (!strcmpstart(cp, "Tor "))
638 cp += 4;
640 if (tor_version_parse(cp, &other)) {
641 /* Couldn't parse other; it can't be a match. */
642 } else {
643 same = tor_version_same_series(&mine, &other);
644 if (same)
645 found_any_in_series = 1;
646 r = tor_version_compare(&mine, &other);
647 if (r==0) {
648 ret = VS_RECOMMENDED;
649 goto done;
650 } else if (r<0) {
651 found_newer = 1;
652 if (same)
653 found_newer_in_series = 1;
654 } else if (r>0) {
655 found_older = 1;
660 /* We didn't find the listed version. Is it new or old? */
661 if (found_any_in_series && !found_newer_in_series && found_newer) {
662 ret = VS_NEW_IN_SERIES;
663 } else if (found_newer && !found_older) {
664 ret = VS_OLD;
665 } else if (found_older && !found_newer) {
666 ret = VS_NEW;
667 } else {
668 ret = VS_UNRECOMMENDED;
671 done:
672 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
673 smartlist_free(version_sl);
674 return ret;
677 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
678 * Otherwise, return -1. If we're a directory cache, cache it.
681 router_parse_directory(const char *str)
683 directory_token_t *tok;
684 char digest[DIGEST_LEN];
685 time_t published_on;
686 int r;
687 const char *end, *cp;
688 smartlist_t *tokens = NULL;
689 crypto_pk_env_t *declared_key = NULL;
690 memarea_t *area = memarea_new();
692 /* XXXX This could be simplified a lot, but it will all go away
693 * once pre-0.1.1.8 is obsolete, and for now it's better not to
694 * touch it. */
696 if (router_get_dir_hash(str, digest)) {
697 log_warn(LD_DIR, "Unable to compute digest of directory");
698 goto err;
700 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
702 /* Check signature first, before we try to tokenize. */
703 cp = str;
704 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
705 cp = end;
706 if (cp == str || !cp) {
707 log_warn(LD_DIR, "No signature found on directory."); goto err;
709 ++cp;
710 tokens = smartlist_create();
711 if (tokenize_string(area,cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
712 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
714 if (smartlist_len(tokens) != 1) {
715 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
717 tok=smartlist_get(tokens,0);
718 if (tok->tp != K_DIRECTORY_SIGNATURE) {
719 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
721 declared_key = find_dir_signing_key(str, str+strlen(str));
722 note_crypto_pk_op(VERIFY_DIR);
723 if (check_signature_token(digest, tok, declared_key,
724 CST_CHECK_AUTHORITY, "directory")<0)
725 goto err;
727 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
728 smartlist_clear(tokens);
729 memarea_clear(area);
731 /* Now try to parse the first part of the directory. */
732 if ((end = strstr(str,"\nrouter "))) {
733 ++end;
734 } else if ((end = strstr(str, "\ndirectory-signature"))) {
735 ++end;
736 } else {
737 end = str + strlen(str);
740 if (tokenize_string(area,str,end,tokens,dir_token_table,0)) {
741 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
744 tok = find_by_keyword(tokens, K_PUBLISHED);
745 tor_assert(tok->n_args == 1);
747 if (parse_iso_time(tok->args[0], &published_on) < 0) {
748 goto err;
751 /* Now that we know the signature is okay, and we have a
752 * publication time, cache the directory. */
753 if (directory_caches_v1_dir_info(get_options()) &&
754 !authdir_mode_v1(get_options()))
755 dirserv_set_cached_directory(str, published_on, 0);
757 r = 0;
758 goto done;
759 err:
760 r = -1;
761 done:
762 if (declared_key) crypto_free_pk_env(declared_key);
763 if (tokens) {
764 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
765 smartlist_free(tokens);
767 if (area) {
768 DUMP_AREA(area, "v1 directory");
769 memarea_drop_all(area);
771 return r;
774 /** Read a signed router status statement from <b>str</b>. If it's
775 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
776 * cache it.*/
778 router_parse_runningrouters(const char *str)
780 char digest[DIGEST_LEN];
781 directory_token_t *tok;
782 time_t published_on;
783 int r = -1;
784 crypto_pk_env_t *declared_key = NULL;
785 smartlist_t *tokens = NULL;
786 const char *eos = str + strlen(str);
787 memarea_t *area = NULL;
789 if (router_get_runningrouters_hash(str, digest)) {
790 log_warn(LD_DIR, "Unable to compute digest of running-routers");
791 goto err;
793 area = memarea_new();
794 tokens = smartlist_create();
795 if (tokenize_string(area,str,eos,tokens,dir_token_table,0)) {
796 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
798 tok = smartlist_get(tokens,0);
799 if (tok->tp != K_NETWORK_STATUS) {
800 log_warn(LD_DIR, "Network-status starts with wrong token");
801 goto err;
804 tok = find_by_keyword(tokens, K_PUBLISHED);
805 tor_assert(tok->n_args == 1);
806 if (parse_iso_time(tok->args[0], &published_on) < 0) {
807 goto err;
809 if (!(tok = find_opt_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
810 log_warn(LD_DIR, "Missing signature on running-routers");
811 goto err;
813 declared_key = find_dir_signing_key(str, eos);
814 note_crypto_pk_op(VERIFY_DIR);
815 if (check_signature_token(digest, tok, declared_key,
816 CST_CHECK_AUTHORITY, "running-routers")
817 < 0)
818 goto err;
820 /* Now that we know the signature is okay, and we have a
821 * publication time, cache the list. */
822 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
823 dirserv_set_cached_directory(str, published_on, 1);
825 r = 0;
826 err:
827 if (declared_key) crypto_free_pk_env(declared_key);
828 if (tokens) {
829 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
830 smartlist_free(tokens);
832 if (area) {
833 DUMP_AREA(area, "v1 running-routers");
834 memarea_drop_all(area);
836 return r;
839 /** Given a directory or running-routers string in <b>str</b>, try to
840 * find the its dir-signing-key token (if any). If this token is
841 * present, extract and return the key. Return NULL on failure. */
842 static crypto_pk_env_t *
843 find_dir_signing_key(const char *str, const char *eos)
845 const char *cp;
846 directory_token_t *tok;
847 crypto_pk_env_t *key = NULL;
848 memarea_t *area = NULL;
849 tor_assert(str);
850 tor_assert(eos);
852 /* Is there a dir-signing-key in the directory? */
853 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
854 if (!cp)
855 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
856 if (!cp)
857 return NULL;
858 ++cp; /* Now cp points to the start of the token. */
860 area = memarea_new();
861 tok = get_next_token(area, &cp, eos, dir_token_table);
862 if (!tok) {
863 log_warn(LD_DIR, "Unparseable dir-signing-key token");
864 goto done;
866 if (tok->tp != K_DIR_SIGNING_KEY) {
867 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
868 goto done;
871 if (tok->key) {
872 key = tok->key;
873 tok->key = NULL; /* steal reference. */
874 } else {
875 log_warn(LD_DIR, "Dir-signing-key token contained no key");
878 done:
879 if (tok) token_free(tok);
880 if (area) {
881 DUMP_AREA(area, "dir-signing-key token");
882 memarea_drop_all(area);
884 return key;
887 /** Return true iff <b>key</b> is allowed to sign directories.
889 static int
890 dir_signing_key_is_trusted(crypto_pk_env_t *key)
892 char digest[DIGEST_LEN];
893 if (!key) return 0;
894 if (crypto_pk_get_digest(key, digest) < 0) {
895 log_warn(LD_DIR, "Error computing dir-signing-key digest");
896 return 0;
898 if (!router_digest_is_trusted_dir(digest)) {
899 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
900 return 0;
902 return 1;
905 /** Check whether the object body of the token in <b>tok</b> has a good
906 * signature for <b>digest</b> using key <b>pkey</b>. If
907 * <b>CST_CHECK_AUTHORITY</b> is set, make sure that <b>pkey</b> is the key of
908 * a directory authority. If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
909 * the object type of the signature object. Use <b>doctype</b> as the type of
910 * the document when generating log messages. Return 0 on success, negative
911 * on failure.
913 static int
914 check_signature_token(const char *digest,
915 directory_token_t *tok,
916 crypto_pk_env_t *pkey,
917 int flags,
918 const char *doctype)
920 char *signed_digest;
921 const int check_authority = (flags & CST_CHECK_AUTHORITY);
922 const int check_objtype = ! (flags & CST_NO_CHECK_OBJTYPE);
924 tor_assert(pkey);
925 tor_assert(tok);
926 tor_assert(digest);
927 tor_assert(doctype);
929 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
930 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
931 doctype);
932 return -1;
935 if (check_objtype) {
936 if (strcmp(tok->object_type, "SIGNATURE")) {
937 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
938 return -1;
942 signed_digest = tor_malloc(tok->object_size);
943 if (crypto_pk_public_checksig(pkey, signed_digest, tok->object_body,
944 tok->object_size)
945 != DIGEST_LEN) {
946 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
947 tor_free(signed_digest);
948 return -1;
950 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
951 // hex_str(signed_digest,4));
952 if (memcmp(digest, signed_digest, DIGEST_LEN)) {
953 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
954 tor_free(signed_digest);
955 return -1;
957 tor_free(signed_digest);
958 return 0;
961 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
962 * or to the first of the annotations proceeding the next router or
963 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
964 * we found an extrainfo, or false if found a router. Do not scan beyond
965 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
966 static int
967 find_start_of_next_router_or_extrainfo(const char **s_ptr,
968 const char *eos,
969 int *is_extrainfo_out)
971 const char *annotations = NULL;
972 const char *s = *s_ptr;
974 s = eat_whitespace_eos(s, eos);
976 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
977 /* We're at the start of a line. */
978 tor_assert(*s != '\n');
980 if (*s == '@' && !annotations) {
981 annotations = s;
982 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
983 *s_ptr = annotations ? annotations : s;
984 *is_extrainfo_out = 0;
985 return 0;
986 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
987 *s_ptr = annotations ? annotations : s;
988 *is_extrainfo_out = 1;
989 return 0;
992 if (!(s = memchr(s+1, '\n', eos-(s+1))))
993 break;
994 s = eat_whitespace_eos(s, eos);
996 return -1;
999 /** Given a string *<b>s</b> containing a concatenated sequence of router
1000 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1001 * them and stores the result in <b>dest</b>. All routers are marked running
1002 * and valid. Advances *s to a point immediately following the last router
1003 * entry. Ignore any trailing router entries that are not complete.
1005 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1006 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1007 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1009 * Returns 0 on success and -1 on failure.
1012 router_parse_list_from_string(const char **s, const char *eos,
1013 smartlist_t *dest,
1014 saved_location_t saved_location,
1015 int want_extrainfo,
1016 int allow_annotations,
1017 const char *prepend_annotations)
1019 routerinfo_t *router;
1020 extrainfo_t *extrainfo;
1021 signed_descriptor_t *signed_desc;
1022 void *elt;
1023 const char *end, *start;
1024 int have_extrainfo;
1026 tor_assert(s);
1027 tor_assert(*s);
1028 tor_assert(dest);
1030 start = *s;
1031 if (!eos)
1032 eos = *s + strlen(*s);
1034 tor_assert(eos >= *s);
1036 while (1) {
1037 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
1038 break;
1040 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
1041 if (end)
1042 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
1043 if (end)
1044 end += strlen("\n-----END SIGNATURE-----\n");
1046 if (!end)
1047 break;
1049 elt = NULL;
1051 if (have_extrainfo && want_extrainfo) {
1052 routerlist_t *rl = router_get_routerlist();
1053 extrainfo = extrainfo_parse_entry_from_string(*s, end,
1054 saved_location != SAVED_IN_CACHE,
1055 rl->identity_map);
1056 if (extrainfo) {
1057 signed_desc = &extrainfo->cache_info;
1058 elt = extrainfo;
1060 } else if (!have_extrainfo && !want_extrainfo) {
1061 router = router_parse_entry_from_string(*s, end,
1062 saved_location != SAVED_IN_CACHE,
1063 allow_annotations,
1064 prepend_annotations);
1065 if (router) {
1066 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
1067 router->nickname, router_purpose_to_string(router->purpose));
1068 signed_desc = &router->cache_info;
1069 elt = router;
1072 if (!elt) {
1073 *s = end;
1074 continue;
1076 if (saved_location != SAVED_NOWHERE) {
1077 signed_desc->saved_location = saved_location;
1078 signed_desc->saved_offset = *s - start;
1080 *s = end;
1081 smartlist_add(dest, elt);
1084 return 0;
1087 /* For debugging: define to count every descriptor digest we've seen so we
1088 * know if we need to try harder to avoid duplicate verifies. */
1089 #undef COUNT_DISTINCT_DIGESTS
1091 #ifdef COUNT_DISTINCT_DIGESTS
1092 static digestmap_t *verified_digests = NULL;
1093 #endif
1095 /** Log the total count of the number of distinct router digests we've ever
1096 * verified. When compared to the number of times we've verified routerdesc
1097 * signatures <i>in toto</i>, this will tell us if we're doing too much
1098 * multiple-verification. */
1099 void
1100 dump_distinct_digest_count(int severity)
1102 #ifdef COUNT_DISTINCT_DIGESTS
1103 if (!verified_digests)
1104 verified_digests = digestmap_new();
1105 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1106 digestmap_size(verified_digests));
1107 #else
1108 (void)severity; /* suppress "unused parameter" warning */
1109 #endif
1112 /** Helper function: reads a single router entry from *<b>s</b> ...
1113 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1114 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1115 * s through end into the signed_descriptor_body of the resulting
1116 * routerinfo_t.
1118 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1119 * before the router; if it's false, reject the router if it's annotated. If
1120 * <b>prepend_annotations</b> is set, it should contain some annotations:
1121 * append them to the front of the router before parsing it, and keep them
1122 * around when caching the router.
1124 * Only one of allow_annotations and prepend_annotations may be set.
1126 routerinfo_t *
1127 router_parse_entry_from_string(const char *s, const char *end,
1128 int cache_copy, int allow_annotations,
1129 const char *prepend_annotations)
1131 routerinfo_t *router = NULL;
1132 char digest[128];
1133 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1134 directory_token_t *tok;
1135 struct in_addr in;
1136 const char *start_of_annotations, *cp;
1137 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1138 int ok = 1;
1139 memarea_t *area = NULL;
1141 tor_assert(!allow_annotations || !prepend_annotations);
1143 if (!end) {
1144 end = s + strlen(s);
1147 /* point 'end' to a point immediately after the final newline. */
1148 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1149 --end;
1151 area = memarea_new();
1152 tokens = smartlist_create();
1153 if (prepend_annotations) {
1154 if (tokenize_string(area,prepend_annotations,NULL,tokens,
1155 routerdesc_token_table,TS_NOCHECK)) {
1156 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1157 goto err;
1161 start_of_annotations = s;
1162 cp = tor_memstr(s, end-s, "\nrouter ");
1163 if (!cp) {
1164 if (end-s < 7 || strcmpstart(s, "router ")) {
1165 log_warn(LD_DIR, "No router keyword found.");
1166 goto err;
1168 } else {
1169 s = cp+1;
1172 if (allow_annotations && start_of_annotations != s) {
1173 if (tokenize_string(area,start_of_annotations,s,tokens,
1174 routerdesc_token_table,TS_NOCHECK)) {
1175 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1176 goto err;
1180 if (router_get_router_hash(s, digest) < 0) {
1181 log_warn(LD_DIR, "Couldn't compute router hash.");
1182 goto err;
1185 int flags = 0;
1186 if (allow_annotations)
1187 flags |= TS_ANNOTATIONS_OK;
1188 if (prepend_annotations)
1189 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1191 if (tokenize_string(area,s,end,tokens,routerdesc_token_table, flags)) {
1192 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1193 goto err;
1197 if (smartlist_len(tokens) < 2) {
1198 log_warn(LD_DIR, "Impossibly short router descriptor.");
1199 goto err;
1202 tok = find_by_keyword(tokens, K_ROUTER);
1203 tor_assert(tok->n_args >= 5);
1205 router = tor_malloc_zero(sizeof(routerinfo_t));
1206 router->country = -1;
1207 router->cache_info.routerlist_index = -1;
1208 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1209 router->cache_info.signed_descriptor_len = end-s;
1210 if (cache_copy) {
1211 size_t len = router->cache_info.signed_descriptor_len +
1212 router->cache_info.annotations_len;
1213 char *cp =
1214 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1215 if (prepend_annotations) {
1216 memcpy(cp, prepend_annotations, prepend_len);
1217 cp += prepend_len;
1219 /* This assertion will always succeed.
1220 * len == signed_desc_len + annotations_len
1221 * == end-s + s-start_of_annotations + prepend_len
1222 * == end-start_of_annotations + prepend_len
1223 * We already wrote prepend_len bytes into the buffer; now we're
1224 * writing end-start_of_annotations -NM. */
1225 tor_assert(cp+(end-start_of_annotations) ==
1226 router->cache_info.signed_descriptor_body+len);
1227 memcpy(cp, start_of_annotations, end-start_of_annotations);
1228 router->cache_info.signed_descriptor_body[len] = '\0';
1229 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1231 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1233 router->nickname = tor_strdup(tok->args[0]);
1234 if (!is_legal_nickname(router->nickname)) {
1235 log_warn(LD_DIR,"Router nickname is invalid");
1236 goto err;
1238 router->address = tor_strdup(tok->args[1]);
1239 if (!tor_inet_aton(router->address, &in)) {
1240 log_warn(LD_DIR,"Router address is not an IP address.");
1241 goto err;
1243 router->addr = ntohl(in.s_addr);
1245 router->or_port =
1246 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1247 if (!ok) {
1248 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1249 goto err;
1251 router->dir_port =
1252 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1253 if (!ok) {
1254 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1255 goto err;
1258 tok = find_by_keyword(tokens, K_BANDWIDTH);
1259 tor_assert(tok->n_args >= 3);
1260 router->bandwidthrate = (int)
1261 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1263 if (!ok) {
1264 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1265 escaped(tok->args[0]));
1266 goto err;
1268 router->bandwidthburst =
1269 (int) tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1270 if (!ok) {
1271 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1272 goto err;
1274 router->bandwidthcapacity = (int)
1275 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1276 if (!ok) {
1277 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1278 goto err;
1281 if ((tok = find_opt_by_keyword(tokens, A_PURPOSE))) {
1282 tor_assert(tok->n_args);
1283 router->purpose = router_purpose_from_string(tok->args[0]);
1284 } else {
1285 router->purpose = ROUTER_PURPOSE_GENERAL;
1287 router->cache_info.send_unencrypted =
1288 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1290 if ((tok = find_opt_by_keyword(tokens, K_UPTIME))) {
1291 tor_assert(tok->n_args >= 1);
1292 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1293 if (!ok) {
1294 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1295 goto err;
1299 if ((tok = find_opt_by_keyword(tokens, K_HIBERNATING))) {
1300 tor_assert(tok->n_args >= 1);
1301 router->is_hibernating
1302 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1305 tok = find_by_keyword(tokens, K_PUBLISHED);
1306 tor_assert(tok->n_args == 1);
1307 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1308 goto err;
1310 tok = find_by_keyword(tokens, K_ONION_KEY);
1311 router->onion_pkey = tok->key;
1312 tok->key = NULL; /* Prevent free */
1314 tok = find_by_keyword(tokens, K_SIGNING_KEY);
1315 router->identity_pkey = tok->key;
1316 tok->key = NULL; /* Prevent free */
1317 if (crypto_pk_get_digest(router->identity_pkey,
1318 router->cache_info.identity_digest)) {
1319 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1322 if ((tok = find_opt_by_keyword(tokens, K_FINGERPRINT))) {
1323 /* If there's a fingerprint line, it must match the identity digest. */
1324 char d[DIGEST_LEN];
1325 tor_assert(tok->n_args == 1);
1326 tor_strstrip(tok->args[0], " ");
1327 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1328 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1329 escaped(tok->args[0]));
1330 goto err;
1332 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1333 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1334 tok->args[0]);
1335 goto err;
1339 if ((tok = find_opt_by_keyword(tokens, K_PLATFORM))) {
1340 router->platform = tor_strdup(tok->args[0]);
1343 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
1344 router->contact_info = tor_strdup(tok->args[0]);
1347 if ((tok = find_opt_by_keyword(tokens, K_EVENTDNS))) {
1348 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1349 } else if (router->platform) {
1350 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1351 router->has_old_dnsworkers = 1;
1354 exit_policy_tokens = find_all_exitpolicy(tokens);
1355 if (!smartlist_len(exit_policy_tokens)) {
1356 log_warn(LD_DIR, "No exit policy tokens in descriptor.");
1357 goto err;
1359 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1360 if (router_add_exit_policy(router,t)<0) {
1361 log_warn(LD_DIR,"Error in exit policy");
1362 goto err;
1364 policy_expand_private(&router->exit_policy);
1365 if (policy_is_reject_star(router->exit_policy))
1366 router->policy_is_reject_star = 1;
1368 if ((tok = find_opt_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1369 int i;
1370 router->declared_family = smartlist_create();
1371 for (i=0;i<tok->n_args;++i) {
1372 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1373 log_warn(LD_DIR, "Illegal nickname %s in family line",
1374 escaped(tok->args[i]));
1375 goto err;
1377 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1381 if ((tok = find_opt_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1382 router->caches_extra_info = 1;
1384 if ((tok = find_opt_by_keyword(tokens, K_ALLOW_SINGLE_HOP_EXITS)))
1385 router->allow_single_hop_exits = 1;
1387 if ((tok = find_opt_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1388 tor_assert(tok->n_args >= 1);
1389 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1390 base16_decode(router->cache_info.extra_info_digest,
1391 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1392 } else {
1393 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1397 if ((tok = find_opt_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1398 router->wants_to_be_hs_dir = 1;
1401 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1402 note_crypto_pk_op(VERIFY_RTR);
1403 #ifdef COUNT_DISTINCT_DIGESTS
1404 if (!verified_digests)
1405 verified_digests = digestmap_new();
1406 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1407 #endif
1408 if (check_signature_token(digest, tok, router->identity_pkey, 0,
1409 "router descriptor") < 0)
1410 goto err;
1412 routerinfo_set_country(router);
1414 if (!router->or_port) {
1415 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1416 goto err;
1419 if (!router->platform) {
1420 router->platform = tor_strdup("<unknown>");
1423 goto done;
1425 err:
1426 routerinfo_free(router);
1427 router = NULL;
1428 done:
1429 if (tokens) {
1430 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1431 smartlist_free(tokens);
1433 if (exit_policy_tokens) {
1434 smartlist_free(exit_policy_tokens);
1436 if (area) {
1437 DUMP_AREA(area, "routerinfo");
1438 memarea_drop_all(area);
1440 return router;
1443 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1444 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1445 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1446 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1447 * as a map from router identity to routerinfo_t when looking up signing keys.
1449 extrainfo_t *
1450 extrainfo_parse_entry_from_string(const char *s, const char *end,
1451 int cache_copy, struct digest_ri_map_t *routermap)
1453 extrainfo_t *extrainfo = NULL;
1454 char digest[128];
1455 smartlist_t *tokens = NULL;
1456 directory_token_t *tok;
1457 crypto_pk_env_t *key = NULL;
1458 routerinfo_t *router = NULL;
1459 memarea_t *area = NULL;
1461 if (!end) {
1462 end = s + strlen(s);
1465 /* point 'end' to a point immediately after the final newline. */
1466 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1467 --end;
1469 if (router_get_extrainfo_hash(s, digest) < 0) {
1470 log_warn(LD_DIR, "Couldn't compute router hash.");
1471 goto err;
1473 tokens = smartlist_create();
1474 area = memarea_new();
1475 if (tokenize_string(area,s,end,tokens,extrainfo_token_table,0)) {
1476 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1477 goto err;
1480 if (smartlist_len(tokens) < 2) {
1481 log_warn(LD_DIR, "Impossibly short extra-info document.");
1482 goto err;
1485 tok = smartlist_get(tokens,0);
1486 if (tok->tp != K_EXTRA_INFO) {
1487 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1488 goto err;
1491 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1492 extrainfo->cache_info.is_extrainfo = 1;
1493 if (cache_copy)
1494 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1495 extrainfo->cache_info.signed_descriptor_len = end-s;
1496 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1498 tor_assert(tok->n_args >= 2);
1499 if (!is_legal_nickname(tok->args[0])) {
1500 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1501 goto err;
1503 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1504 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1505 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1506 tok->args[1], HEX_DIGEST_LEN)) {
1507 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1508 escaped(tok->args[1]));
1509 goto err;
1512 tok = find_by_keyword(tokens, K_PUBLISHED);
1513 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1514 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1515 escaped(tok->args[0]));
1516 goto err;
1519 if (routermap &&
1520 (router = digestmap_get((digestmap_t*)routermap,
1521 extrainfo->cache_info.identity_digest))) {
1522 key = router->identity_pkey;
1525 tok = find_by_keyword(tokens, K_ROUTER_SIGNATURE);
1526 if (strcmp(tok->object_type, "SIGNATURE") ||
1527 tok->object_size < 128 || tok->object_size > 512) {
1528 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1529 goto err;
1532 if (key) {
1533 note_crypto_pk_op(VERIFY_RTR);
1534 if (check_signature_token(digest, tok, key, 0, "extra-info") < 0)
1535 goto err;
1537 if (router)
1538 extrainfo->cache_info.send_unencrypted =
1539 router->cache_info.send_unencrypted;
1540 } else {
1541 extrainfo->pending_sig = tor_memdup(tok->object_body,
1542 tok->object_size);
1543 extrainfo->pending_sig_len = tok->object_size;
1546 goto done;
1547 err:
1548 if (extrainfo)
1549 extrainfo_free(extrainfo);
1550 extrainfo = NULL;
1551 done:
1552 if (tokens) {
1553 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1554 smartlist_free(tokens);
1556 if (area) {
1557 DUMP_AREA(area, "extrainfo");
1558 memarea_drop_all(area);
1560 return extrainfo;
1563 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1564 * the first character after the certificate. */
1565 authority_cert_t *
1566 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1568 authority_cert_t *cert = NULL, *old_cert;
1569 smartlist_t *tokens = NULL;
1570 char digest[DIGEST_LEN];
1571 directory_token_t *tok;
1572 char fp_declared[DIGEST_LEN];
1573 char *eos;
1574 size_t len;
1575 int found;
1576 memarea_t *area = NULL;
1578 s = eat_whitespace(s);
1579 eos = strstr(s, "\ndir-key-certification");
1580 if (! eos) {
1581 log_warn(LD_DIR, "No signature found on key certificate");
1582 return NULL;
1584 eos = strstr(eos, "\n-----END SIGNATURE-----\n");
1585 if (! eos) {
1586 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1587 return NULL;
1589 eos = strchr(eos+2, '\n');
1590 tor_assert(eos);
1591 ++eos;
1592 len = eos - s;
1594 tokens = smartlist_create();
1595 area = memarea_new();
1596 if (tokenize_string(area,s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1597 log_warn(LD_DIR, "Error tokenizing key certificate");
1598 goto err;
1600 if (router_get_hash_impl(s, digest, "dir-key-certificate-version",
1601 "\ndir-key-certification", '\n') < 0)
1602 goto err;
1603 tok = smartlist_get(tokens, 0);
1604 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1605 log_warn(LD_DIR,
1606 "Key certificate does not begin with a recognized version (3).");
1607 goto err;
1610 cert = tor_malloc_zero(sizeof(authority_cert_t));
1611 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1613 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
1614 tor_assert(tok->key);
1615 cert->signing_key = tok->key;
1616 tok->key = NULL;
1617 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1618 goto err;
1620 tok = find_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1621 tor_assert(tok->key);
1622 cert->identity_key = tok->key;
1623 tok->key = NULL;
1625 tok = find_by_keyword(tokens, K_FINGERPRINT);
1626 tor_assert(tok->n_args);
1627 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1628 strlen(tok->args[0]))) {
1629 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1630 escaped(tok->args[0]));
1631 goto err;
1634 if (crypto_pk_get_digest(cert->identity_key,
1635 cert->cache_info.identity_digest))
1636 goto err;
1638 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1639 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1640 "fingerprint");
1641 goto err;
1644 tok = find_opt_by_keyword(tokens, K_DIR_ADDRESS);
1645 if (tok) {
1646 struct in_addr in;
1647 char *address = NULL;
1648 tor_assert(tok->n_args);
1649 /* XXX021 use tor_addr_port_parse() below instead. -RD */
1650 if (parse_addr_port(LOG_WARN, tok->args[0], &address, NULL,
1651 &cert->dir_port)<0 ||
1652 tor_inet_aton(address, &in) == 0) {
1653 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1654 tor_free(address);
1655 goto err;
1657 cert->addr = ntohl(in.s_addr);
1658 tor_free(address);
1661 tok = find_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1662 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1663 goto err;
1665 tok = find_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1666 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1667 goto err;
1670 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1671 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1672 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1673 goto err;
1676 /* If we already have this cert, don't bother checking the signature. */
1677 old_cert = authority_cert_get_by_digests(
1678 cert->cache_info.identity_digest,
1679 cert->signing_key_digest);
1680 found = 0;
1681 if (old_cert) {
1682 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1683 * buy us much. */
1684 if (old_cert->cache_info.signed_descriptor_len == len &&
1685 old_cert->cache_info.signed_descriptor_body &&
1686 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1687 log_debug(LD_DIR, "We already checked the signature on this "
1688 "certificate; no need to do so again.");
1689 found = 1;
1690 cert->is_cross_certified = old_cert->is_cross_certified;
1693 if (!found) {
1694 if (check_signature_token(digest, tok, cert->identity_key, 0,
1695 "key certificate")) {
1696 goto err;
1699 if ((tok = find_opt_by_keyword(tokens, K_DIR_KEY_CROSSCERT))) {
1700 /* XXXX Once all authorities generate cross-certified certificates,
1701 * make this field mandatory. */
1702 if (check_signature_token(cert->cache_info.identity_digest,
1703 tok,
1704 cert->signing_key,
1705 CST_NO_CHECK_OBJTYPE,
1706 "key cross-certification")) {
1707 goto err;
1709 cert->is_cross_certified = 1;
1713 cert->cache_info.signed_descriptor_len = len;
1714 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1715 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1716 cert->cache_info.signed_descriptor_body[len] = 0;
1717 cert->cache_info.saved_location = SAVED_NOWHERE;
1719 if (end_of_string) {
1720 *end_of_string = eat_whitespace(eos);
1722 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1723 smartlist_free(tokens);
1724 if (area) {
1725 DUMP_AREA(area, "authority cert");
1726 memarea_drop_all(area);
1728 return cert;
1729 err:
1730 authority_cert_free(cert);
1731 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1732 smartlist_free(tokens);
1733 if (area) {
1734 DUMP_AREA(area, "authority cert");
1735 memarea_drop_all(area);
1737 return NULL;
1740 /** Helper: given a string <b>s</b>, return the start of the next router-status
1741 * object (starting with "r " at the start of a line). If none is found,
1742 * return the start of the next directory signature. If none is found, return
1743 * the end of the string. */
1744 static INLINE const char *
1745 find_start_of_next_routerstatus(const char *s)
1747 const char *eos = strstr(s, "\nr ");
1748 if (eos) {
1749 const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
1750 if (eos2 && eos2 < eos)
1751 return eos2;
1752 else
1753 return eos+1;
1754 } else {
1755 if ((eos = strstr(s, "\ndirectory-signature")))
1756 return eos+1;
1757 return s + strlen(s);
1761 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1762 * empty smartlist at <b>tokens</b>, parse and return the first router status
1763 * object in the string, and advance *<b>s</b> to just after the end of the
1764 * router status. Return NULL and advance *<b>s</b> on error.
1766 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1767 * routerstatus but use <b>vote_rs</b> instead.
1769 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1770 * consensus, and we should parse it according to the method used to
1771 * make that consensus.
1773 static routerstatus_t *
1774 routerstatus_parse_entry_from_string(memarea_t *area,
1775 const char **s, smartlist_t *tokens,
1776 networkstatus_t *vote,
1777 vote_routerstatus_t *vote_rs,
1778 int consensus_method)
1780 const char *eos;
1781 routerstatus_t *rs = NULL;
1782 directory_token_t *tok;
1783 char timebuf[ISO_TIME_LEN+1];
1784 struct in_addr in;
1785 tor_assert(tokens);
1786 tor_assert(bool_eq(vote, vote_rs));
1788 eos = find_start_of_next_routerstatus(*s);
1790 if (tokenize_string(area,*s, eos, tokens, rtrstatus_token_table,0)) {
1791 log_warn(LD_DIR, "Error tokenizing router status");
1792 goto err;
1794 if (smartlist_len(tokens) < 1) {
1795 log_warn(LD_DIR, "Impossibly short router status");
1796 goto err;
1798 tok = find_by_keyword(tokens, K_R);
1799 tor_assert(tok->n_args >= 8);
1800 if (vote_rs) {
1801 rs = &vote_rs->status;
1802 } else {
1803 rs = tor_malloc_zero(sizeof(routerstatus_t));
1806 if (!is_legal_nickname(tok->args[0])) {
1807 log_warn(LD_DIR,
1808 "Invalid nickname %s in router status; skipping.",
1809 escaped(tok->args[0]));
1810 goto err;
1812 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1814 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1815 log_warn(LD_DIR, "Error decoding identity digest %s",
1816 escaped(tok->args[1]));
1817 goto err;
1820 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1821 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1822 escaped(tok->args[2]));
1823 goto err;
1826 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1827 tok->args[3], tok->args[4]) < 0 ||
1828 parse_iso_time(timebuf, &rs->published_on)<0) {
1829 log_warn(LD_DIR, "Error parsing time '%s %s'",
1830 tok->args[3], tok->args[4]);
1831 goto err;
1834 if (tor_inet_aton(tok->args[5], &in) == 0) {
1835 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1836 escaped(tok->args[5]));
1837 goto err;
1839 rs->addr = ntohl(in.s_addr);
1841 rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL);
1842 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL);
1844 tok = find_opt_by_keyword(tokens, K_S);
1845 if (tok && vote) {
1846 int i;
1847 vote_rs->flags = 0;
1848 for (i=0; i < tok->n_args; ++i) {
1849 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1850 if (p >= 0) {
1851 vote_rs->flags |= (1<<p);
1852 } else {
1853 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1854 escaped(tok->args[i]));
1855 goto err;
1858 } else if (tok) {
1859 int i;
1860 for (i=0; i < tok->n_args; ++i) {
1861 if (!strcmp(tok->args[i], "Exit"))
1862 rs->is_exit = 1;
1863 else if (!strcmp(tok->args[i], "Stable"))
1864 rs->is_stable = 1;
1865 else if (!strcmp(tok->args[i], "Fast"))
1866 rs->is_fast = 1;
1867 else if (!strcmp(tok->args[i], "Running"))
1868 rs->is_running = 1;
1869 else if (!strcmp(tok->args[i], "Named"))
1870 rs->is_named = 1;
1871 else if (!strcmp(tok->args[i], "Valid"))
1872 rs->is_valid = 1;
1873 else if (!strcmp(tok->args[i], "V2Dir"))
1874 rs->is_v2_dir = 1;
1875 else if (!strcmp(tok->args[i], "Guard"))
1876 rs->is_possible_guard = 1;
1877 else if (!strcmp(tok->args[i], "BadExit"))
1878 rs->is_bad_exit = 1;
1879 else if (!strcmp(tok->args[i], "BadDirectory"))
1880 rs->is_bad_directory = 1;
1881 else if (!strcmp(tok->args[i], "Authority"))
1882 rs->is_authority = 1;
1883 else if (!strcmp(tok->args[i], "Unnamed") &&
1884 consensus_method >= 2) {
1885 /* Unnamed is computed right by consensus method 2 and later. */
1886 rs->is_unnamed = 1;
1887 } else if (!strcmp(tok->args[i], "HSDir")) {
1888 rs->is_hs_dir = 1;
1892 if ((tok = find_opt_by_keyword(tokens, K_V))) {
1893 tor_assert(tok->n_args == 1);
1894 rs->version_known = 1;
1895 if (strcmpstart(tok->args[0], "Tor ")) {
1896 rs->version_supports_begindir = 1;
1897 rs->version_supports_extrainfo_upload = 1;
1898 rs->version_supports_conditional_consensus = 1;
1899 } else {
1900 rs->version_supports_begindir =
1901 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
1902 rs->version_supports_extrainfo_upload =
1903 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
1904 rs->version_supports_v3_dir =
1905 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
1906 rs->version_supports_conditional_consensus =
1907 tor_version_as_new_as(tok->args[0], "0.2.1.1-alpha");
1909 if (vote_rs) {
1910 vote_rs->version = tor_strdup(tok->args[0]);
1914 /* handle weighting/bandwidth info */
1915 if ((tok = find_opt_by_keyword(tokens, K_W))) {
1916 int i;
1917 for (i=0; i < tok->n_args; ++i) {
1918 if (!strcmpstart(tok->args[i], "Bandwidth=")) {
1919 int ok;
1920 rs->bandwidth = tor_parse_ulong(strchr(tok->args[i], '=')+1, 10,
1921 0, UINT32_MAX, &ok, NULL);
1922 if (!ok) {
1923 log_warn(LD_DIR, "Invalid Bandwidth %s", escaped(tok->args[i]));
1924 goto err;
1926 rs->has_bandwidth = 1;
1931 /* parse exit policy summaries */
1932 if ((tok = find_opt_by_keyword(tokens, K_P))) {
1933 tor_assert(tok->n_args == 1);
1934 if (strcmpstart(tok->args[0], "accept ") &&
1935 strcmpstart(tok->args[0], "reject ")) {
1936 log_err(LD_DIR, "Unknown exit policy summary type %s.",
1937 escaped(tok->args[0]));
1938 goto err;
1940 /* XXX weasel: parse this into ports and represent them somehow smart,
1941 * maybe not here but somewhere on if we need it for the client.
1942 * we should still parse it here to check it's valid tho.
1944 rs->exitsummary = tor_strdup(tok->args[0]);
1945 rs->has_exitsummary = 1;
1948 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
1949 rs->is_named = 0;
1951 goto done;
1952 err:
1953 if (rs && !vote_rs)
1954 routerstatus_free(rs);
1955 rs = NULL;
1956 done:
1957 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1958 smartlist_clear(tokens);
1959 if (area) {
1960 DUMP_AREA(area, "routerstatus entry");
1961 memarea_clear(area);
1963 *s = eos;
1965 return rs;
1968 /** Helper to sort a smartlist of pointers to routerstatus_t */
1969 static int
1970 _compare_routerstatus_entries(const void **_a, const void **_b)
1972 const routerstatus_t *a = *_a, *b = *_b;
1973 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
1976 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1977 static void
1978 _free_duplicate_routerstatus_entry(void *e)
1980 log_warn(LD_DIR,
1981 "Network-status has two entries for the same router. "
1982 "Dropping one.");
1983 routerstatus_free(e);
1986 /** Given a v2 network-status object in <b>s</b>, try to
1987 * parse it and return the result. Return NULL on failure. Check the
1988 * signature of the network status, but do not (yet) check the signing key for
1989 * authority.
1991 networkstatus_v2_t *
1992 networkstatus_v2_parse_from_string(const char *s)
1994 const char *eos;
1995 smartlist_t *tokens = smartlist_create();
1996 smartlist_t *footer_tokens = smartlist_create();
1997 networkstatus_v2_t *ns = NULL;
1998 char ns_digest[DIGEST_LEN];
1999 char tmp_digest[DIGEST_LEN];
2000 struct in_addr in;
2001 directory_token_t *tok;
2002 int i;
2003 memarea_t *area = NULL;
2005 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
2006 log_warn(LD_DIR, "Unable to compute digest of network-status");
2007 goto err;
2010 area = memarea_new();
2011 eos = find_start_of_next_routerstatus(s);
2012 if (tokenize_string(area, s, eos, tokens, netstatus_token_table,0)) {
2013 log_warn(LD_DIR, "Error tokenizing network-status header.");
2014 goto err;
2016 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
2017 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2019 tok = find_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
2020 tor_assert(tok->n_args >= 1);
2021 if (strcmp(tok->args[0], "2")) {
2022 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
2023 "%s", escaped(tok->args[0]));
2024 goto err;
2027 tok = find_by_keyword(tokens, K_DIR_SOURCE);
2028 tor_assert(tok->n_args >= 3);
2029 ns->source_address = tor_strdup(tok->args[0]);
2030 if (tor_inet_aton(tok->args[1], &in) == 0) {
2031 log_warn(LD_DIR, "Error parsing network-status source address %s",
2032 escaped(tok->args[1]));
2033 goto err;
2035 ns->source_addr = ntohl(in.s_addr);
2036 ns->source_dirport =
2037 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
2038 if (ns->source_dirport == 0) {
2039 log_warn(LD_DIR, "Directory source without dirport; skipping.");
2040 goto err;
2043 tok = find_by_keyword(tokens, K_FINGERPRINT);
2044 tor_assert(tok->n_args);
2045 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
2046 strlen(tok->args[0]))) {
2047 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
2048 escaped(tok->args[0]));
2049 goto err;
2052 if ((tok = find_opt_by_keyword(tokens, K_CONTACT))) {
2053 tor_assert(tok->n_args);
2054 ns->contact = tor_strdup(tok->args[0]);
2057 tok = find_by_keyword(tokens, K_DIR_SIGNING_KEY);
2058 tor_assert(tok->key);
2059 ns->signing_key = tok->key;
2060 tok->key = NULL;
2062 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
2063 log_warn(LD_DIR, "Couldn't compute signing key digest");
2064 goto err;
2066 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
2067 log_warn(LD_DIR,
2068 "network-status fingerprint did not match dir-signing-key");
2069 goto err;
2072 if ((tok = find_opt_by_keyword(tokens, K_DIR_OPTIONS))) {
2073 for (i=0; i < tok->n_args; ++i) {
2074 if (!strcmp(tok->args[i], "Names"))
2075 ns->binds_names = 1;
2076 if (!strcmp(tok->args[i], "Versions"))
2077 ns->recommends_versions = 1;
2078 if (!strcmp(tok->args[i], "BadExits"))
2079 ns->lists_bad_exits = 1;
2080 if (!strcmp(tok->args[i], "BadDirectories"))
2081 ns->lists_bad_directories = 1;
2085 if (ns->recommends_versions) {
2086 if (!(tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2087 log_warn(LD_DIR, "Missing client-versions on versioning directory");
2088 goto err;
2090 ns->client_versions = tor_strdup(tok->args[0]);
2092 if (!(tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS)) ||
2093 tok->n_args<1) {
2094 log_warn(LD_DIR, "Missing server-versions on versioning directory");
2095 goto err;
2097 ns->server_versions = tor_strdup(tok->args[0]);
2100 tok = find_by_keyword(tokens, K_PUBLISHED);
2101 tor_assert(tok->n_args == 1);
2102 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
2103 goto err;
2106 ns->entries = smartlist_create();
2107 s = eos;
2108 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2109 smartlist_clear(tokens);
2110 memarea_clear(area);
2111 while (!strcmpstart(s, "r ")) {
2112 routerstatus_t *rs;
2113 if ((rs = routerstatus_parse_entry_from_string(area, &s, tokens,
2114 NULL, NULL, 0)))
2115 smartlist_add(ns->entries, rs);
2117 smartlist_sort(ns->entries, _compare_routerstatus_entries);
2118 smartlist_uniq(ns->entries, _compare_routerstatus_entries,
2119 _free_duplicate_routerstatus_entry);
2121 if (tokenize_string(area,s, NULL, footer_tokens, dir_footer_token_table,0)) {
2122 log_warn(LD_DIR, "Error tokenizing network-status footer.");
2123 goto err;
2125 if (smartlist_len(footer_tokens) < 1) {
2126 log_warn(LD_DIR, "Too few items in network-status footer.");
2127 goto err;
2129 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
2130 if (tok->tp != K_DIRECTORY_SIGNATURE) {
2131 log_warn(LD_DIR,
2132 "Expected network-status footer to end with a signature.");
2133 goto err;
2136 note_crypto_pk_op(VERIFY_DIR);
2137 if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
2138 "network-status") < 0)
2139 goto err;
2141 goto done;
2142 err:
2143 if (ns)
2144 networkstatus_v2_free(ns);
2145 ns = NULL;
2146 done:
2147 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2148 smartlist_free(tokens);
2149 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2150 smartlist_free(footer_tokens);
2151 if (area) {
2152 DUMP_AREA(area, "v2 networkstatus");
2153 memarea_drop_all(area);
2155 return ns;
2158 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
2159 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
2160 networkstatus_t *
2161 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
2162 networkstatus_type_t ns_type)
2164 smartlist_t *tokens = smartlist_create();
2165 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
2166 networkstatus_voter_info_t *voter = NULL;
2167 networkstatus_t *ns = NULL;
2168 char ns_digest[DIGEST_LEN];
2169 const char *cert, *end_of_header, *end_of_footer;
2170 directory_token_t *tok;
2171 int ok;
2172 struct in_addr in;
2173 int i, inorder, n_signatures = 0;
2174 memarea_t *area = NULL, *rs_area = NULL;
2175 tor_assert(s);
2177 if (eos_out)
2178 *eos_out = NULL;
2180 if (router_get_networkstatus_v3_hash(s, ns_digest)) {
2181 log_warn(LD_DIR, "Unable to compute digest of network-status");
2182 goto err;
2185 area = memarea_new();
2186 end_of_header = find_start_of_next_routerstatus(s);
2187 if (tokenize_string(area, s, end_of_header, tokens,
2188 (ns_type == NS_TYPE_CONSENSUS) ?
2189 networkstatus_consensus_token_table :
2190 networkstatus_token_table, 0)) {
2191 log_warn(LD_DIR, "Error tokenizing network-status vote header");
2192 goto err;
2195 ns = tor_malloc_zero(sizeof(networkstatus_t));
2196 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2198 if (ns_type != NS_TYPE_CONSENSUS) {
2199 const char *end_of_cert = NULL;
2200 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2201 goto err;
2202 ++cert;
2203 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2204 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2205 goto err;
2208 tok = find_by_keyword(tokens, K_VOTE_STATUS);
2209 tor_assert(tok->n_args);
2210 if (!strcmp(tok->args[0], "vote")) {
2211 ns->type = NS_TYPE_VOTE;
2212 } else if (!strcmp(tok->args[0], "consensus")) {
2213 ns->type = NS_TYPE_CONSENSUS;
2214 } else if (!strcmp(tok->args[0], "opinion")) {
2215 ns->type = NS_TYPE_OPINION;
2216 } else {
2217 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2218 escaped(tok->args[0]));
2219 goto err;
2221 if (ns_type != ns->type) {
2222 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2223 goto err;
2226 if (ns->type == NS_TYPE_VOTE || ns->type == NS_TYPE_OPINION) {
2227 tok = find_by_keyword(tokens, K_PUBLISHED);
2228 if (parse_iso_time(tok->args[0], &ns->published))
2229 goto err;
2231 ns->supported_methods = smartlist_create();
2232 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHODS);
2233 if (tok) {
2234 for (i=0; i < tok->n_args; ++i)
2235 smartlist_add(ns->supported_methods, tor_strdup(tok->args[i]));
2236 } else {
2237 smartlist_add(ns->supported_methods, tor_strdup("1"));
2239 } else {
2240 tok = find_opt_by_keyword(tokens, K_CONSENSUS_METHOD);
2241 if (tok) {
2242 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2243 &ok, NULL);
2244 if (!ok)
2245 goto err;
2246 } else {
2247 ns->consensus_method = 1;
2251 tok = find_by_keyword(tokens, K_VALID_AFTER);
2252 if (parse_iso_time(tok->args[0], &ns->valid_after))
2253 goto err;
2255 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2256 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2257 goto err;
2259 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2260 if (parse_iso_time(tok->args[0], &ns->valid_until))
2261 goto err;
2263 tok = find_by_keyword(tokens, K_VOTING_DELAY);
2264 tor_assert(tok->n_args >= 2);
2265 ns->vote_seconds =
2266 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2267 if (!ok)
2268 goto err;
2269 ns->dist_seconds =
2270 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2271 if (!ok)
2272 goto err;
2273 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2274 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2275 goto err;
2277 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2278 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2279 goto err;
2281 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2282 log_warn(LD_DIR, "Vote seconds is too short");
2283 goto err;
2285 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2286 log_warn(LD_DIR, "Dist seconds is too short");
2287 goto err;
2290 if ((tok = find_opt_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2291 ns->client_versions = tor_strdup(tok->args[0]);
2293 if ((tok = find_opt_by_keyword(tokens, K_SERVER_VERSIONS))) {
2294 ns->server_versions = tor_strdup(tok->args[0]);
2297 tok = find_by_keyword(tokens, K_KNOWN_FLAGS);
2298 ns->known_flags = smartlist_create();
2299 inorder = 1;
2300 for (i = 0; i < tok->n_args; ++i) {
2301 smartlist_add(ns->known_flags, tor_strdup(tok->args[i]));
2302 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2303 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2304 inorder = 0;
2307 if (!inorder) {
2308 log_warn(LD_DIR, "known-flags not in order");
2309 goto err;
2312 ns->voters = smartlist_create();
2314 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2316 tok = _tok;
2317 if (tok->tp == K_DIR_SOURCE) {
2318 tor_assert(tok->n_args >= 6);
2320 if (voter)
2321 smartlist_add(ns->voters, voter);
2322 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2323 if (ns->type != NS_TYPE_CONSENSUS)
2324 memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
2326 voter->nickname = tor_strdup(tok->args[0]);
2327 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2328 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2329 tok->args[1], HEX_DIGEST_LEN) < 0) {
2330 log_warn(LD_DIR, "Error decoding identity digest %s in "
2331 "network-status vote.", escaped(tok->args[1]));
2332 goto err;
2334 if (ns->type != NS_TYPE_CONSENSUS &&
2335 memcmp(ns->cert->cache_info.identity_digest,
2336 voter->identity_digest, DIGEST_LEN)) {
2337 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2338 goto err;
2340 voter->address = tor_strdup(tok->args[2]);
2341 if (!tor_inet_aton(tok->args[3], &in)) {
2342 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2343 escaped(tok->args[3]));
2344 goto err;
2346 voter->addr = ntohl(in.s_addr);
2347 voter->dir_port = (uint16_t)
2348 tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2349 if (!ok)
2350 goto err;
2351 voter->or_port = (uint16_t)
2352 tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2353 if (!ok)
2354 goto err;
2355 } else if (tok->tp == K_CONTACT) {
2356 if (!voter || voter->contact) {
2357 log_warn(LD_DIR, "contact element is out of place.");
2358 goto err;
2360 voter->contact = tor_strdup(tok->args[0]);
2361 } else if (tok->tp == K_VOTE_DIGEST) {
2362 tor_assert(ns->type == NS_TYPE_CONSENSUS);
2363 tor_assert(tok->n_args >= 1);
2364 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2365 log_warn(LD_DIR, "vote-digest element is out of place.");
2366 goto err;
2368 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2369 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2370 tok->args[0], HEX_DIGEST_LEN) < 0) {
2371 log_warn(LD_DIR, "Error decoding vote digest %s in "
2372 "network-status consensus.", escaped(tok->args[1]));
2373 goto err;
2377 if (voter) {
2378 smartlist_add(ns->voters, voter);
2379 voter = NULL;
2381 if (smartlist_len(ns->voters) == 0) {
2382 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2383 goto err;
2384 } else if (ns->type != NS_TYPE_CONSENSUS && smartlist_len(ns->voters) != 1) {
2385 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2386 goto err;
2389 if (ns->type != NS_TYPE_CONSENSUS &&
2390 (tok = find_opt_by_keyword(tokens, K_LEGACY_DIR_KEY))) {
2391 int bad = 1;
2392 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
2393 networkstatus_voter_info_t *voter = smartlist_get(ns->voters, 0);
2394 if (base16_decode(voter->legacy_id_digest, DIGEST_LEN,
2395 tok->args[0], HEX_DIGEST_LEN)<0)
2396 bad = 1;
2397 else
2398 bad = 0;
2400 if (bad) {
2401 log_warn(LD_DIR, "Invalid legacy key digest %s on vote.",
2402 escaped(tok->args[0]));
2406 /* Parse routerstatus lines. */
2407 rs_tokens = smartlist_create();
2408 rs_area = memarea_new();
2409 s = end_of_header;
2410 ns->routerstatus_list = smartlist_create();
2412 while (!strcmpstart(s, "r ")) {
2413 if (ns->type != NS_TYPE_CONSENSUS) {
2414 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2415 if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns,
2416 rs, 0))
2417 smartlist_add(ns->routerstatus_list, rs);
2418 else {
2419 tor_free(rs->version);
2420 tor_free(rs);
2422 } else {
2423 routerstatus_t *rs;
2424 if ((rs = routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens,
2425 NULL, NULL,
2426 ns->consensus_method)))
2427 smartlist_add(ns->routerstatus_list, rs);
2430 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2431 routerstatus_t *rs1, *rs2;
2432 if (ns->type != NS_TYPE_CONSENSUS) {
2433 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2434 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2435 rs1 = &a->status; rs2 = &b->status;
2436 } else {
2437 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2438 rs2 = smartlist_get(ns->routerstatus_list, i);
2440 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
2441 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2442 "digest");
2443 goto err;
2447 /* Parse footer; check signature. */
2448 footer_tokens = smartlist_create();
2449 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2450 ++end_of_footer;
2451 else
2452 end_of_footer = s + strlen(s);
2453 if (tokenize_string(area,s, end_of_footer, footer_tokens,
2454 networkstatus_vote_footer_token_table, 0)) {
2455 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2456 goto err;
2459 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
2461 char declared_identity[DIGEST_LEN];
2462 networkstatus_voter_info_t *v;
2463 tok = _tok;
2464 if (tok->tp != K_DIRECTORY_SIGNATURE)
2465 continue;
2466 tor_assert(tok->n_args >= 2);
2468 if (!tok->object_type ||
2469 strcmp(tok->object_type, "SIGNATURE") ||
2470 tok->object_size < 128 || tok->object_size > 512) {
2471 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2472 goto err;
2475 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2476 base16_decode(declared_identity, sizeof(declared_identity),
2477 tok->args[0], HEX_DIGEST_LEN) < 0) {
2478 log_warn(LD_DIR, "Error decoding declared identity %s in "
2479 "network-status vote.", escaped(tok->args[0]));
2480 goto err;
2482 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2483 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2484 "any declared directory source.");
2485 goto err;
2487 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2488 base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
2489 tok->args[1], HEX_DIGEST_LEN) < 0) {
2490 log_warn(LD_DIR, "Error decoding declared digest %s in "
2491 "network-status vote.", escaped(tok->args[1]));
2492 goto err;
2495 if (ns->type != NS_TYPE_CONSENSUS) {
2496 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
2497 DIGEST_LEN)) {
2498 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2499 "network-status vote.");
2500 goto err;
2504 if (ns->type != NS_TYPE_CONSENSUS) {
2505 if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
2506 "network-status vote"))
2507 goto err;
2508 v->good_signature = 1;
2509 } else {
2510 if (tok->object_size >= INT_MAX)
2511 goto err;
2512 v->signature = tor_memdup(tok->object_body, tok->object_size);
2513 v->signature_len = (int) tok->object_size;
2515 ++n_signatures;
2518 if (! n_signatures) {
2519 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2520 goto err;
2523 if (eos_out)
2524 *eos_out = end_of_footer;
2526 goto done;
2527 err:
2528 if (ns)
2529 networkstatus_vote_free(ns);
2530 ns = NULL;
2531 done:
2532 if (tokens) {
2533 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2534 smartlist_free(tokens);
2536 if (voter) {
2537 tor_free(voter->nickname);
2538 tor_free(voter->address);
2539 tor_free(voter->contact);
2540 tor_free(voter->signature);
2541 tor_free(voter);
2543 if (rs_tokens) {
2544 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
2545 smartlist_free(rs_tokens);
2547 if (footer_tokens) {
2548 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2549 smartlist_free(footer_tokens);
2551 if (area) {
2552 DUMP_AREA(area, "v3 networkstatus");
2553 memarea_drop_all(area);
2555 if (rs_area)
2556 memarea_drop_all(rs_area);
2558 return ns;
2561 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2562 * <b>eos</b> and return the result. Return -1 on failure. */
2563 ns_detached_signatures_t *
2564 networkstatus_parse_detached_signatures(const char *s, const char *eos)
2566 /* XXXX there is too much duplicate shared between this function and
2567 * networkstatus_parse_vote_from_string(). */
2568 directory_token_t *tok;
2569 memarea_t *area = NULL;
2571 smartlist_t *tokens = smartlist_create();
2572 ns_detached_signatures_t *sigs =
2573 tor_malloc_zero(sizeof(ns_detached_signatures_t));
2575 if (!eos)
2576 eos = s + strlen(s);
2578 area = memarea_new();
2579 if (tokenize_string(area,s, eos, tokens,
2580 networkstatus_detached_signature_token_table, 0)) {
2581 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
2582 goto err;
2585 tok = find_by_keyword(tokens, K_CONSENSUS_DIGEST);
2586 if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
2587 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
2588 "networkstatus signatures");
2589 goto err;
2591 if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
2592 tok->args[0], strlen(tok->args[0])) < 0) {
2593 log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
2594 "networkstatus signatures");
2595 goto err;
2598 tok = find_by_keyword(tokens, K_VALID_AFTER);
2599 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
2600 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
2601 goto err;
2604 tok = find_by_keyword(tokens, K_FRESH_UNTIL);
2605 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
2606 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
2607 goto err;
2610 tok = find_by_keyword(tokens, K_VALID_UNTIL);
2611 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
2612 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
2613 goto err;
2616 sigs->signatures = smartlist_create();
2617 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2619 char id_digest[DIGEST_LEN];
2620 char sk_digest[DIGEST_LEN];
2621 networkstatus_voter_info_t *voter;
2623 tok = _tok;
2624 if (tok->tp != K_DIRECTORY_SIGNATURE)
2625 continue;
2626 tor_assert(tok->n_args >= 2);
2628 if (!tok->object_type ||
2629 strcmp(tok->object_type, "SIGNATURE") ||
2630 tok->object_size < 128 || tok->object_size > 512) {
2631 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2632 goto err;
2635 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2636 base16_decode(id_digest, sizeof(id_digest),
2637 tok->args[0], HEX_DIGEST_LEN) < 0) {
2638 log_warn(LD_DIR, "Error decoding declared identity %s in "
2639 "network-status vote.", escaped(tok->args[0]));
2640 goto err;
2642 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2643 base16_decode(sk_digest, sizeof(sk_digest),
2644 tok->args[1], HEX_DIGEST_LEN) < 0) {
2645 log_warn(LD_DIR, "Error decoding declared digest %s in "
2646 "network-status vote.", escaped(tok->args[1]));
2647 goto err;
2650 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2651 memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
2652 memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
2653 if (tok->object_size >= INT_MAX)
2654 goto err;
2655 voter->signature = tor_memdup(tok->object_body, tok->object_size);
2656 voter->signature_len = (int) tok->object_size;
2658 smartlist_add(sigs->signatures, voter);
2661 goto done;
2662 err:
2663 ns_detached_signatures_free(sigs);
2664 sigs = NULL;
2665 done:
2666 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2667 smartlist_free(tokens);
2668 if (area) {
2669 DUMP_AREA(area, "detached signatures");
2670 memarea_drop_all(area);
2672 return sigs;
2675 /** Parse the addr policy in the string <b>s</b> and return it. If
2676 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2677 * ADDR_POLICY_REJECT) for items that specify no action.
2679 addr_policy_t *
2680 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
2682 directory_token_t *tok = NULL;
2683 const char *cp, *eos;
2684 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2685 * But note that there can be an arbitrary amount of space between the
2686 * accept and the address:mask/port element. */
2687 char line[TOR_ADDR_BUF_LEN*2 + 32];
2688 addr_policy_t *r;
2689 memarea_t *area = NULL;
2691 s = eat_whitespace(s);
2692 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
2693 if (tor_snprintf(line, sizeof(line), "%s %s",
2694 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
2695 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
2696 return NULL;
2698 cp = line;
2699 tor_strlower(line);
2700 } else { /* assume an already well-formed address policy line */
2701 cp = s;
2704 eos = cp + strlen(cp);
2705 area = memarea_new();
2706 tok = get_next_token(area, &cp, eos, routerdesc_token_table);
2707 if (tok->tp == _ERR) {
2708 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
2709 goto err;
2711 if (tok->tp != K_ACCEPT && tok->tp != K_ACCEPT6 &&
2712 tok->tp != K_REJECT && tok->tp != K_REJECT6) {
2713 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
2714 goto err;
2717 r = router_parse_addr_policy(tok);
2718 goto done;
2719 err:
2720 r = NULL;
2721 done:
2722 token_free(tok);
2723 if (area) {
2724 DUMP_AREA(area, "policy item");
2725 memarea_drop_all(area);
2727 return r;
2730 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2731 * <b>router</b>. Return 0 on success, -1 on failure. */
2732 static int
2733 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
2735 addr_policy_t *newe;
2736 newe = router_parse_addr_policy(tok);
2737 if (!newe)
2738 return -1;
2739 if (! router->exit_policy)
2740 router->exit_policy = smartlist_create();
2742 if (((tok->tp == K_ACCEPT6 || tok->tp == K_REJECT6) &&
2743 tor_addr_family(&newe->addr) == AF_INET)
2745 ((tok->tp == K_ACCEPT || tok->tp == K_REJECT) &&
2746 tor_addr_family(&newe->addr) == AF_INET6)) {
2747 log_warn(LD_DIR, "Mismatch between field type and address type in exit "
2748 "policy");
2749 addr_policy_free(newe);
2750 return -1;
2753 smartlist_add(router->exit_policy, newe);
2755 return 0;
2758 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2759 * a new exit_policy_t corresponding to the token. */
2760 static addr_policy_t *
2761 router_parse_addr_policy(directory_token_t *tok)
2763 addr_policy_t newe;
2764 char *arg;
2766 tor_assert(tok->tp == K_REJECT || tok->tp == K_REJECT6 ||
2767 tok->tp == K_ACCEPT || tok->tp == K_ACCEPT6);
2769 if (tok->n_args != 1)
2770 return NULL;
2771 arg = tok->args[0];
2773 if (!strcmpstart(arg,"private"))
2774 return router_parse_addr_policy_private(tok);
2776 memset(&newe, 0, sizeof(newe));
2778 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2779 newe.policy_type = ADDR_POLICY_REJECT;
2780 else
2781 newe.policy_type = ADDR_POLICY_ACCEPT;
2783 if (tor_addr_parse_mask_ports(arg, &newe.addr, &newe.maskbits,
2784 &newe.prt_min, &newe.prt_max) < 0) {
2785 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
2786 return NULL;
2789 return addr_policy_get_canonical_entry(&newe);
2792 /** Parse an exit policy line of the format "accept/reject private:...".
2793 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2794 * router descriptors until earlier versions are obsolete.
2796 static addr_policy_t *
2797 router_parse_addr_policy_private(directory_token_t *tok)
2799 const char *arg;
2800 uint16_t port_min, port_max;
2801 addr_policy_t result;
2803 arg = tok->args[0];
2804 if (strcmpstart(arg, "private"))
2805 return NULL;
2807 arg += strlen("private");
2808 arg = (char*) eat_whitespace(arg);
2809 if (!arg || *arg != ':')
2810 return NULL;
2812 if (parse_port_range(arg+1, &port_min, &port_max)<0)
2813 return NULL;
2815 memset(&result, 0, sizeof(result));
2816 if (tok->tp == K_REJECT || tok->tp == K_REJECT6)
2817 result.policy_type = ADDR_POLICY_REJECT;
2818 else
2819 result.policy_type = ADDR_POLICY_ACCEPT;
2820 result.is_private = 1;
2821 result.prt_min = port_min;
2822 result.prt_max = port_max;
2824 return addr_policy_get_canonical_entry(&result);
2827 /** Log and exit if <b>t</b> is malformed */
2828 void
2829 assert_addr_policy_ok(smartlist_t *lst)
2831 if (!lst) return;
2832 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
2833 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
2834 t->policy_type == ADDR_POLICY_ACCEPT);
2835 tor_assert(t->prt_min <= t->prt_max);
2840 * Low-level tokenizer for router descriptors and directories.
2843 /** Free all resources allocated for <b>tok</b> */
2844 static void
2845 token_free(directory_token_t *tok)
2847 tor_assert(tok);
2848 if (tok->key)
2849 crypto_free_pk_env(tok->key);
2852 #define ALLOC_ZERO(sz) memarea_alloc_zero(area,sz)
2853 #define ALLOC(sz) memarea_alloc(area,sz)
2854 #define STRDUP(str) memarea_strdup(area,str)
2855 #define STRNDUP(str,n) memarea_strndup(area,(str),(n))
2857 #define RET_ERR(msg) \
2858 STMT_BEGIN \
2859 if (tok) token_free(tok); \
2860 tok = ALLOC_ZERO(sizeof(directory_token_t)); \
2861 tok->tp = _ERR; \
2862 tok->error = STRDUP(msg); \
2863 goto done_tokenizing; \
2864 STMT_END
2866 /** Helper: make sure that the token <b>tok</b> with keyword <b>kwd</b> obeys
2867 * the object syntax of <b>o_syn</b>. Allocate all storage in <b>area</b>.
2868 * Return <b>tok</b> on success, or a new _ERR token if the token didn't
2869 * conform to the syntax we wanted.
2871 static INLINE directory_token_t *
2872 token_check_object(memarea_t *area, const char *kwd,
2873 directory_token_t *tok, obj_syntax o_syn)
2875 char ebuf[128];
2876 switch (o_syn) {
2877 case NO_OBJ:
2878 /* No object is allowed for this token. */
2879 if (tok->object_body) {
2880 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
2881 RET_ERR(ebuf);
2883 if (tok->key) {
2884 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
2885 RET_ERR(ebuf);
2887 break;
2888 case NEED_OBJ:
2889 /* There must be a (non-key) object. */
2890 if (!tok->object_body) {
2891 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
2892 RET_ERR(ebuf);
2894 break;
2895 case NEED_KEY_1024: /* There must be a 1024-bit public key. */
2896 case NEED_SKEY_1024: /* There must be a 1024-bit private key. */
2897 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
2898 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
2899 kwd, (int)crypto_pk_keysize(tok->key));
2900 RET_ERR(ebuf);
2902 /* fall through */
2903 case NEED_KEY: /* There must be some kind of key. */
2904 if (!tok->key) {
2905 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
2907 if (o_syn != NEED_SKEY_1024) {
2908 if (crypto_pk_key_is_private(tok->key)) {
2909 tor_snprintf(ebuf, sizeof(ebuf),
2910 "Private key given for %s, which wants a public key", kwd);
2911 RET_ERR(ebuf);
2913 } else { /* o_syn == NEED_SKEY_1024 */
2914 if (!crypto_pk_key_is_private(tok->key)) {
2915 tor_snprintf(ebuf, sizeof(ebuf),
2916 "Public key given for %s, which wants a private key", kwd);
2917 RET_ERR(ebuf);
2920 break;
2921 case OBJ_OK:
2922 /* Anything goes with this token. */
2923 break;
2926 done_tokenizing:
2927 return tok;
2930 /** Helper: parse space-separated arguments from the string <b>s</b> ending at
2931 * <b>eol</b>, and store them in the args field of <b>tok</b>. Store the
2932 * number of parsed elements into the n_args field of <b>tok</b>. Allocate
2933 * all storage in <b>area</b>. Return the number of arguments parsed, or
2934 * return -1 if there was an insanely high number of arguments. */
2935 static INLINE int
2936 get_token_arguments(memarea_t *area, directory_token_t *tok,
2937 const char *s, const char *eol)
2939 /** Largest number of arguments we'll accept to any token, ever. */
2940 #define MAX_ARGS 512
2941 char *mem = memarea_strndup(area, s, eol-s);
2942 char *cp = mem;
2943 int j = 0;
2944 char *args[MAX_ARGS];
2945 while (*cp) {
2946 if (j == MAX_ARGS)
2947 return -1;
2948 args[j++] = cp;
2949 cp = (char*)find_whitespace(cp);
2950 if (!cp || !*cp)
2951 break; /* End of the line. */
2952 *cp++ = '\0';
2953 cp = (char*)eat_whitespace(cp);
2955 tok->n_args = j;
2956 tok->args = memarea_memdup(area, args, j*sizeof(char*));
2957 return j;
2958 #undef MAX_ARGS
2961 /** Helper function: read the next token from *s, advance *s to the end of the
2962 * token, and return the parsed token. Parse *<b>s</b> according to the list
2963 * of tokens in <b>table</b>.
2965 static directory_token_t *
2966 get_next_token(memarea_t *area,
2967 const char **s, const char *eos, token_rule_t *table)
2969 const char *next, *eol, *obstart;
2970 size_t obname_len;
2971 int i;
2972 directory_token_t *tok;
2973 obj_syntax o_syn = NO_OBJ;
2974 char ebuf[128];
2975 const char *kwd = "";
2977 tor_assert(area);
2978 tok = ALLOC_ZERO(sizeof(directory_token_t));
2979 tok->tp = _ERR;
2981 /* Set *s to first token, eol to end-of-line, next to after first token */
2982 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
2983 tor_assert(eos >= *s);
2984 eol = memchr(*s, '\n', eos-*s);
2985 if (!eol)
2986 eol = eos;
2987 next = find_whitespace_eos(*s, eol);
2989 if (!strcmp_len(*s, "opt", next-*s)) {
2990 /* Skip past an "opt" at the start of the line. */
2991 *s = eat_whitespace_eos_no_nl(next, eol);
2992 next = find_whitespace_eos(*s, eol);
2993 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
2994 RET_ERR("Unexpected EOF");
2997 /* Search the table for the appropriate entry. (I tried a binary search
2998 * instead, but it wasn't any faster.) */
2999 for (i = 0; table[i].t ; ++i) {
3000 if (!strcmp_len(*s, table[i].t, next-*s)) {
3001 /* We've found the keyword. */
3002 kwd = table[i].t;
3003 tok->tp = table[i].v;
3004 o_syn = table[i].os;
3005 *s = eat_whitespace_eos_no_nl(next, eol);
3006 /* We go ahead whether there are arguments or not, so that tok->args is
3007 * always set if we want arguments. */
3008 if (table[i].concat_args) {
3009 /* The keyword takes the line as a single argument */
3010 tok->args = ALLOC(sizeof(char*));
3011 tok->args[0] = STRNDUP(*s,eol-*s); /* Grab everything on line */
3012 tok->n_args = 1;
3013 } else {
3014 /* This keyword takes multiple arguments. */
3015 if (get_token_arguments(area, tok, *s, eol)<0) {
3016 tor_snprintf(ebuf, sizeof(ebuf),"Far too many arguments to %s", kwd);
3017 RET_ERR(ebuf);
3019 *s = eol;
3021 if (tok->n_args < table[i].min_args) {
3022 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
3023 RET_ERR(ebuf);
3024 } else if (tok->n_args > table[i].max_args) {
3025 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
3026 RET_ERR(ebuf);
3028 break;
3032 if (tok->tp == _ERR) {
3033 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
3034 if (**s == '@')
3035 tok->tp = _A_UNKNOWN;
3036 else
3037 tok->tp = K_OPT;
3038 tok->args = ALLOC(sizeof(char*));
3039 tok->args[0] = STRNDUP(*s, eol-*s);
3040 tok->n_args = 1;
3041 o_syn = OBJ_OK;
3044 /* Check whether there's an object present */
3045 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
3046 tor_assert(eos >= *s);
3047 eol = memchr(*s, '\n', eos-*s);
3048 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
3049 goto check_object;
3051 obstart = *s; /* Set obstart to start of object spec */
3052 tor_assert(eol >= (*s+16));
3053 if (*s+11 >= eol-5 || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
3054 strcmp_len(eol-5, "-----", 5)) { /* nuls or invalid endings */
3055 RET_ERR("Malformed object: bad begin line");
3057 tok->object_type = STRNDUP(*s+11, eol-*s-16);
3058 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
3059 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
3061 /* Go to the end of the object */
3062 next = tor_memstr(*s, eos-*s, "-----END ");
3063 if (!next) {
3064 RET_ERR("Malformed object: missing object end line");
3066 tor_assert(eos >= next);
3067 eol = memchr(next, '\n', eos-next);
3068 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
3069 eol = eos;
3070 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
3071 if ((size_t)(eol-next) != 9+obname_len+5 ||
3072 strcmp_len(next+9, tok->object_type, obname_len) ||
3073 strcmp_len(eol-5, "-----", 5)) {
3074 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
3075 tok->object_type);
3076 ebuf[sizeof(ebuf)-1] = '\0';
3077 RET_ERR(ebuf);
3079 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */
3080 tok->key = crypto_new_pk_env();
3081 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
3082 RET_ERR("Couldn't parse public key.");
3083 } else if (!strcmp(tok->object_type, "RSA PRIVATE KEY")) { /* private key */
3084 tok->key = crypto_new_pk_env();
3085 if (crypto_pk_read_private_key_from_string(tok->key, obstart))
3086 RET_ERR("Couldn't parse private key.");
3087 } else { /* If it's something else, try to base64-decode it */
3088 int r;
3089 tok->object_body = ALLOC(next-*s); /* really, this is too much RAM. */
3090 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
3091 if (r<0)
3092 RET_ERR("Malformed object: bad base64-encoded data");
3093 tok->object_size = r;
3095 *s = eol;
3097 check_object:
3098 tok = token_check_object(area, kwd, tok, o_syn);
3100 done_tokenizing:
3101 return tok;
3103 #undef RET_ERR
3104 #undef ALLOC
3105 #undef ALLOC_ZERO
3106 #undef STRDUP
3107 #undef STRNDUP
3110 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
3111 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
3112 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
3113 * entire string.
3115 static int
3116 tokenize_string(memarea_t *area,
3117 const char *start, const char *end, smartlist_t *out,
3118 token_rule_t *table, int flags)
3120 const char **s;
3121 directory_token_t *tok = NULL;
3122 int counts[_NIL];
3123 int i;
3124 int first_nonannotation;
3125 int prev_len = smartlist_len(out);
3126 tor_assert(area);
3128 s = &start;
3129 if (!end)
3130 end = start+strlen(start);
3131 for (i = 0; i < _NIL; ++i)
3132 counts[i] = 0;
3133 while (*s < end && (!tok || tok->tp != _EOF)) {
3134 tok = get_next_token(area, s, end, table);
3135 if (tok->tp == _ERR) {
3136 log_warn(LD_DIR, "parse error: %s", tok->error);
3137 token_free(tok);
3138 return -1;
3140 ++counts[tok->tp];
3141 smartlist_add(out, tok);
3142 *s = eat_whitespace_eos(*s, end);
3145 if (flags & TS_NOCHECK)
3146 return 0;
3148 if ((flags & TS_ANNOTATIONS_OK)) {
3149 first_nonannotation = -1;
3150 for (i = 0; i < smartlist_len(out); ++i) {
3151 tok = smartlist_get(out, i);
3152 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
3153 first_nonannotation = i;
3154 break;
3157 if (first_nonannotation < 0) {
3158 log_warn(LD_DIR, "parse error: item contains only annotations");
3159 return -1;
3161 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
3162 tok = smartlist_get(out, i);
3163 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3164 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
3165 return -1;
3168 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
3169 if (first_nonannotation != prev_len) {
3170 log_warn(LD_DIR, "parse error: Unexpectd annotations.");
3171 return -1;
3174 } else {
3175 for (i=0; i < smartlist_len(out); ++i) {
3176 tok = smartlist_get(out, i);
3177 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
3178 log_warn(LD_DIR, "parse error: no annotations allowed.");
3179 return -1;
3182 first_nonannotation = 0;
3184 for (i = 0; table[i].t; ++i) {
3185 if (counts[table[i].v] < table[i].min_cnt) {
3186 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
3187 return -1;
3189 if (counts[table[i].v] > table[i].max_cnt) {
3190 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
3191 return -1;
3193 if (table[i].pos & AT_START) {
3194 if (smartlist_len(out) < 1 ||
3195 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
3196 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
3197 return -1;
3200 if (table[i].pos & AT_END) {
3201 if (smartlist_len(out) < 1 ||
3202 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
3203 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
3204 return -1;
3208 return 0;
3211 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
3212 * NULL if no such keyword is found.
3214 static directory_token_t *
3215 find_opt_by_keyword(smartlist_t *s, directory_keyword keyword)
3217 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
3218 return NULL;
3221 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; fail
3222 * with an assert if no such keyword is found.
3224 static directory_token_t *
3225 _find_by_keyword(smartlist_t *s, directory_keyword keyword,
3226 const char *keyword_as_string)
3228 directory_token_t *tok = find_opt_by_keyword(s, keyword);
3229 if (PREDICT_UNLIKELY(!tok)) {
3230 log_err(LD_BUG, "Missing %s [%d] in directory object that should have "
3231 "been validated. Internal error.", keyword_as_string, (int)keyword);
3232 tor_assert(tok);
3234 return tok;
3237 /** Return a newly allocated smartlist of all accept or reject tokens in
3238 * <b>s</b>.
3240 static smartlist_t *
3241 find_all_exitpolicy(smartlist_t *s)
3243 smartlist_t *out = smartlist_create();
3244 SMARTLIST_FOREACH(s, directory_token_t *, t,
3245 if (t->tp == K_ACCEPT || t->tp == K_ACCEPT6 ||
3246 t->tp == K_REJECT || t->tp == K_REJECT6)
3247 smartlist_add(out,t));
3248 return out;
3251 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
3252 * occurrence of <b>start_str</b> through the first instance of c after the
3253 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
3254 * <b>digest</b>; return 0 on success.
3256 * If no such substring exists, return -1.
3258 static int
3259 router_get_hash_impl(const char *s, char *digest,
3260 const char *start_str,
3261 const char *end_str, char end_c)
3263 char *start, *end;
3264 start = strstr(s, start_str);
3265 if (!start) {
3266 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
3267 return -1;
3269 if (start != s && *(start-1) != '\n') {
3270 log_warn(LD_DIR,
3271 "first occurrence of \"%s\" is not at the start of a line",
3272 start_str);
3273 return -1;
3275 end = strstr(start+strlen(start_str), end_str);
3276 if (!end) {
3277 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
3278 return -1;
3280 end = strchr(end+strlen(end_str), end_c);
3281 if (!end) {
3282 log_warn(LD_DIR,"couldn't find EOL");
3283 return -1;
3285 ++end;
3287 if (crypto_digest(digest, start, end-start)) {
3288 log_warn(LD_BUG,"couldn't compute digest");
3289 return -1;
3292 return 0;
3295 /** Parse the Tor version of the platform string <b>platform</b>,
3296 * and compare it to the version in <b>cutoff</b>. Return 1 if
3297 * the router is at least as new as the cutoff, else return 0.
3300 tor_version_as_new_as(const char *platform, const char *cutoff)
3302 tor_version_t cutoff_version, router_version;
3303 char *s, *s2, *start;
3304 char tmp[128];
3306 tor_assert(platform);
3308 if (tor_version_parse(cutoff, &cutoff_version)<0) {
3309 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
3310 return 0;
3312 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
3313 return 1;
3315 start = (char *)eat_whitespace(platform+3);
3316 if (!*start) return 0;
3317 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
3318 s2 = (char*)eat_whitespace(s);
3319 if (!strcmpstart(s2, "(r"))
3320 s = (char*)find_whitespace(s2);
3322 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
3323 return 0;
3324 strlcpy(tmp, start, s-start+1);
3326 if (tor_version_parse(tmp, &router_version)<0) {
3327 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
3328 return 1; /* be safe and say yes */
3331 /* Here's why we don't need to do any special handling for svn revisions:
3332 * - If neither has an svn revision, we're fine.
3333 * - If the router doesn't have an svn revision, we can't assume that it
3334 * is "at least" any svn revision, so we need to return 0.
3335 * - If the target version doesn't have an svn revision, any svn revision
3336 * (or none at all) is good enough, so return 1.
3337 * - If both target and router have an svn revision, we compare them.
3340 return tor_version_compare(&router_version, &cutoff_version) >= 0;
3343 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3344 * Return 0 on success, -1 on failure. */
3346 tor_version_parse(const char *s, tor_version_t *out)
3348 char *eos=NULL;
3349 const char *cp=NULL;
3350 /* Format is:
3351 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3353 tor_assert(s);
3354 tor_assert(out);
3356 memset(out, 0, sizeof(tor_version_t));
3358 if (!strcasecmpstart(s, "Tor "))
3359 s += 4;
3361 /* Get major. */
3362 out->major = (int)strtol(s,&eos,10);
3363 if (!eos || eos==s || *eos != '.') return -1;
3364 cp = eos+1;
3366 /* Get minor */
3367 out->minor = (int) strtol(cp,&eos,10);
3368 if (!eos || eos==cp || *eos != '.') return -1;
3369 cp = eos+1;
3371 /* Get micro */
3372 out->micro = (int) strtol(cp,&eos,10);
3373 if (!eos || eos==cp) return -1;
3374 if (!*eos) {
3375 out->status = VER_RELEASE;
3376 out->patchlevel = 0;
3377 return 0;
3379 cp = eos;
3381 /* Get status */
3382 if (*cp == '.') {
3383 out->status = VER_RELEASE;
3384 ++cp;
3385 } else if (0==strncmp(cp, "pre", 3)) {
3386 out->status = VER_PRE;
3387 cp += 3;
3388 } else if (0==strncmp(cp, "rc", 2)) {
3389 out->status = VER_RC;
3390 cp += 2;
3391 } else {
3392 return -1;
3395 /* Get patchlevel */
3396 out->patchlevel = (int) strtol(cp,&eos,10);
3397 if (!eos || eos==cp) return -1;
3398 cp = eos;
3400 /* Get status tag. */
3401 if (*cp == '-' || *cp == '.')
3402 ++cp;
3403 eos = (char*) find_whitespace(cp);
3404 if (eos-cp >= (int)sizeof(out->status_tag))
3405 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
3406 else {
3407 memcpy(out->status_tag, cp, eos-cp);
3408 out->status_tag[eos-cp] = 0;
3410 cp = eat_whitespace(eos);
3412 if (!strcmpstart(cp, "(r")) {
3413 cp += 2;
3414 out->svn_revision = (int) strtol(cp,&eos,10);
3417 return 0;
3420 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3421 * b. */
3423 tor_version_compare(tor_version_t *a, tor_version_t *b)
3425 int i;
3426 tor_assert(a);
3427 tor_assert(b);
3428 if ((i = a->major - b->major))
3429 return i;
3430 else if ((i = a->minor - b->minor))
3431 return i;
3432 else if ((i = a->micro - b->micro))
3433 return i;
3434 else if ((i = a->status - b->status))
3435 return i;
3436 else if ((i = a->patchlevel - b->patchlevel))
3437 return i;
3438 else if ((i = strcmp(a->status_tag, b->status_tag)))
3439 return i;
3440 else
3441 return a->svn_revision - b->svn_revision;
3444 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3446 static int
3447 tor_version_same_series(tor_version_t *a, tor_version_t *b)
3449 tor_assert(a);
3450 tor_assert(b);
3451 return ((a->major == b->major) &&
3452 (a->minor == b->minor) &&
3453 (a->micro == b->micro));
3456 /** Helper: Given pointers to two strings describing tor versions, return -1
3457 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
3458 * Used to sort a list of versions. */
3459 static int
3460 _compare_tor_version_str_ptr(const void **_a, const void **_b)
3462 const char *a = *_a, *b = *_b;
3463 int ca, cb;
3464 tor_version_t va, vb;
3465 ca = tor_version_parse(a, &va);
3466 cb = tor_version_parse(b, &vb);
3467 /* If they both parse, compare them. */
3468 if (!ca && !cb)
3469 return tor_version_compare(&va,&vb);
3470 /* If one parses, it comes first. */
3471 if (!ca && cb)
3472 return -1;
3473 if (ca && !cb)
3474 return 1;
3475 /* If neither parses, compare strings. Also, the directory server admin
3476 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3477 return strcmp(a,b);
3480 /** Sort a list of string-representations of versions in ascending order. */
3481 void
3482 sort_version_list(smartlist_t *versions, int remove_duplicates)
3484 smartlist_sort(versions, _compare_tor_version_str_ptr);
3486 if (remove_duplicates)
3487 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
3490 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3491 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3492 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3493 * encrypted introduction points to the newly allocated
3494 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3495 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3496 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3497 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3498 * and -1 for failure.
3501 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
3502 char *desc_id_out,
3503 char **intro_points_encrypted_out,
3504 size_t *intro_points_encrypted_size_out,
3505 size_t *encoded_size_out,
3506 const char **next_out, const char *desc)
3508 rend_service_descriptor_t *result =
3509 tor_malloc_zero(sizeof(rend_service_descriptor_t));
3510 char desc_hash[DIGEST_LEN];
3511 const char *eos;
3512 smartlist_t *tokens = smartlist_create();
3513 directory_token_t *tok;
3514 char secret_id_part[DIGEST_LEN];
3515 int i, version, num_ok=1;
3516 smartlist_t *versions;
3517 char public_key_hash[DIGEST_LEN];
3518 char test_desc_id[DIGEST_LEN];
3519 memarea_t *area = NULL;
3520 tor_assert(desc);
3521 /* Check if desc starts correctly. */
3522 if (strncmp(desc, "rendezvous-service-descriptor ",
3523 strlen("rendezvous-service-descriptor "))) {
3524 log_info(LD_REND, "Descriptor does not start correctly.");
3525 goto err;
3527 /* Compute descriptor hash for later validation. */
3528 if (router_get_hash_impl(desc, desc_hash,
3529 "rendezvous-service-descriptor ",
3530 "\nsignature", '\n') < 0) {
3531 log_warn(LD_REND, "Couldn't compute descriptor hash.");
3532 goto err;
3534 /* Determine end of string. */
3535 eos = strstr(desc, "\nrendezvous-service-descriptor ");
3536 if (!eos)
3537 eos = desc + strlen(desc);
3538 else
3539 eos = eos + 1;
3540 /* Check length. */
3541 if (strlen(desc) > REND_DESC_MAX_SIZE) {
3542 log_warn(LD_REND, "Descriptor length is %i which exceeds "
3543 "maximum rendezvous descriptor size of %i kilobytes.",
3544 (int)strlen(desc), REND_DESC_MAX_SIZE);
3545 goto err;
3547 /* Tokenize descriptor. */
3548 area = memarea_new();
3549 if (tokenize_string(area, desc, eos, tokens, desc_token_table, 0)) {
3550 log_warn(LD_REND, "Error tokenizing descriptor.");
3551 goto err;
3553 /* Set next to next descriptor, if available. */
3554 *next_out = eos;
3555 /* Set length of encoded descriptor. */
3556 *encoded_size_out = eos - desc;
3557 /* Check min allowed length of token list. */
3558 if (smartlist_len(tokens) < 7) {
3559 log_warn(LD_REND, "Impossibly short descriptor.");
3560 goto err;
3562 /* Parse base32-encoded descriptor ID. */
3563 tok = find_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
3564 tor_assert(tok == smartlist_get(tokens, 0));
3565 tor_assert(tok->n_args == 1);
3566 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
3567 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
3568 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
3569 goto err;
3571 if (base32_decode(desc_id_out, DIGEST_LEN,
3572 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
3573 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
3574 tok->args[0]);
3575 goto err;
3577 /* Parse descriptor version. */
3578 tok = find_by_keyword(tokens, R_VERSION);
3579 tor_assert(tok->n_args == 1);
3580 result->version =
3581 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
3582 if (result->version != 2 || !num_ok) {
3583 /* If it's <2, it shouldn't be under this format. If the number
3584 * is greater than 2, we bumped it because we broke backward
3585 * compatibility. See how version numbers in our other formats
3586 * work. */
3587 log_warn(LD_REND, "Unrecognized descriptor version: %s",
3588 escaped(tok->args[0]));
3589 goto err;
3591 /* Parse public key. */
3592 tok = find_by_keyword(tokens, R_PERMANENT_KEY);
3593 result->pk = tok->key;
3594 tok->key = NULL; /* Prevent free */
3595 /* Parse secret ID part. */
3596 tok = find_by_keyword(tokens, R_SECRET_ID_PART);
3597 tor_assert(tok->n_args == 1);
3598 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
3599 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
3600 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
3601 goto err;
3603 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
3604 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
3605 tok->args[0]);
3606 goto err;
3608 /* Parse publication time -- up-to-date check is done when storing the
3609 * descriptor. */
3610 tok = find_by_keyword(tokens, R_PUBLICATION_TIME);
3611 tor_assert(tok->n_args == 1);
3612 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
3613 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
3614 goto err;
3616 /* Parse protocol versions. */
3617 tok = find_by_keyword(tokens, R_PROTOCOL_VERSIONS);
3618 tor_assert(tok->n_args == 1);
3619 versions = smartlist_create();
3620 smartlist_split_string(versions, tok->args[0], ",",
3621 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3622 for (i = 0; i < smartlist_len(versions); i++) {
3623 version = (int) tor_parse_long(smartlist_get(versions, i),
3624 10, 0, INT_MAX, &num_ok, NULL);
3625 if (!num_ok) /* It's a string; let's ignore it. */
3626 continue;
3627 result->protocols |= 1 << version;
3629 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
3630 smartlist_free(versions);
3631 /* Parse encrypted introduction points. Don't verify. */
3632 tok = find_opt_by_keyword(tokens, R_INTRODUCTION_POINTS);
3633 if (tok) {
3634 if (strcmp(tok->object_type, "MESSAGE")) {
3635 log_warn(LD_DIR, "Bad object type: introduction points should be of "
3636 "type MESSAGE");
3637 goto err;
3639 *intro_points_encrypted_out = tor_memdup(tok->object_body,
3640 tok->object_size);
3641 *intro_points_encrypted_size_out = tok->object_size;
3642 } else {
3643 *intro_points_encrypted_out = NULL;
3644 *intro_points_encrypted_size_out = 0;
3646 /* Parse and verify signature. */
3647 tok = find_by_keyword(tokens, R_SIGNATURE);
3648 note_crypto_pk_op(VERIFY_RTR);
3649 if (check_signature_token(desc_hash, tok, result->pk, 0,
3650 "v2 rendezvous service descriptor") < 0)
3651 goto err;
3652 /* Verify that descriptor ID belongs to public key and secret ID part. */
3653 crypto_pk_get_digest(result->pk, public_key_hash);
3654 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
3655 secret_id_part);
3656 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
3657 log_warn(LD_REND, "Parsed descriptor ID does not match "
3658 "computed descriptor ID.");
3659 goto err;
3661 goto done;
3662 err:
3663 if (result)
3664 rend_service_descriptor_free(result);
3665 result = NULL;
3666 done:
3667 if (tokens) {
3668 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3669 smartlist_free(tokens);
3671 if (area)
3672 memarea_drop_all(area);
3673 *parsed_out = result;
3674 if (result)
3675 return 0;
3676 return -1;
3679 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
3680 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
3681 * write the result to a newly allocated string that is pointed to by
3682 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
3683 * Return 0 if decryption was successful and -1 otherwise. */
3685 rend_decrypt_introduction_points(char **ipos_decrypted,
3686 size_t *ipos_decrypted_size,
3687 const char *descriptor_cookie,
3688 const char *ipos_encrypted,
3689 size_t ipos_encrypted_size)
3691 tor_assert(ipos_encrypted);
3692 tor_assert(descriptor_cookie);
3693 if (ipos_encrypted_size < 2) {
3694 log_warn(LD_REND, "Size of encrypted introduction points is too "
3695 "small.");
3696 return -1;
3698 if (ipos_encrypted[0] == (int)REND_BASIC_AUTH) {
3699 char iv[CIPHER_IV_LEN], client_id[REND_BASIC_AUTH_CLIENT_ID_LEN],
3700 session_key[CIPHER_KEY_LEN], *dec;
3701 int declen, client_blocks;
3702 size_t pos = 0, len, client_entries_len;
3703 crypto_digest_env_t *digest;
3704 crypto_cipher_env_t *cipher;
3705 client_blocks = (int) ipos_encrypted[1];
3706 client_entries_len = client_blocks * REND_BASIC_AUTH_CLIENT_MULTIPLE *
3707 REND_BASIC_AUTH_CLIENT_ENTRY_LEN;
3708 if (ipos_encrypted_size < 2 + client_entries_len + CIPHER_IV_LEN + 1) {
3709 log_warn(LD_REND, "Size of encrypted introduction points is too "
3710 "small.");
3711 return -1;
3713 memcpy(iv, ipos_encrypted + 2 + client_entries_len, CIPHER_IV_LEN);
3714 digest = crypto_new_digest_env();
3715 crypto_digest_add_bytes(digest, descriptor_cookie, REND_DESC_COOKIE_LEN);
3716 crypto_digest_add_bytes(digest, iv, CIPHER_IV_LEN);
3717 crypto_digest_get_digest(digest, client_id,
3718 REND_BASIC_AUTH_CLIENT_ID_LEN);
3719 crypto_free_digest_env(digest);
3720 for (pos = 2; pos < 2 + client_entries_len;
3721 pos += REND_BASIC_AUTH_CLIENT_ENTRY_LEN) {
3722 if (!memcmp(ipos_encrypted + pos, client_id,
3723 REND_BASIC_AUTH_CLIENT_ID_LEN)) {
3724 /* Attempt to decrypt introduction points. */
3725 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3726 if (crypto_cipher_decrypt(cipher, session_key, ipos_encrypted
3727 + pos + REND_BASIC_AUTH_CLIENT_ID_LEN,
3728 CIPHER_KEY_LEN) < 0) {
3729 log_warn(LD_REND, "Could not decrypt session key for client.");
3730 crypto_free_cipher_env(cipher);
3731 return -1;
3733 crypto_free_cipher_env(cipher);
3734 cipher = crypto_create_init_cipher(session_key, 0);
3735 len = ipos_encrypted_size - 2 - client_entries_len - CIPHER_IV_LEN;
3736 dec = tor_malloc(len);
3737 declen = crypto_cipher_decrypt_with_iv(cipher, dec, len,
3738 ipos_encrypted + 2 + client_entries_len,
3739 ipos_encrypted_size - 2 - client_entries_len);
3740 crypto_free_cipher_env(cipher);
3741 if (declen < 0) {
3742 log_warn(LD_REND, "Could not decrypt introduction point string.");
3743 tor_free(dec);
3744 return -1;
3746 if (memcmpstart(dec, declen, "introduction-point ")) {
3747 log_warn(LD_REND, "Decrypted introduction points don't "
3748 "look like we could parse them.");
3749 tor_free(dec);
3750 continue;
3752 *ipos_decrypted = dec;
3753 *ipos_decrypted_size = declen;
3754 return 0;
3757 log_warn(LD_REND, "Could not decrypt introduction points. Please "
3758 "check your authorization for this service!");
3759 return -1;
3760 } else if (ipos_encrypted[0] == (int)REND_STEALTH_AUTH) {
3761 crypto_cipher_env_t *cipher;
3762 char *dec;
3763 int declen;
3764 dec = tor_malloc_zero(ipos_encrypted_size - CIPHER_IV_LEN - 1);
3765 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3766 declen = crypto_cipher_decrypt_with_iv(cipher, dec,
3767 ipos_encrypted_size -
3768 CIPHER_IV_LEN - 1,
3769 ipos_encrypted + 1,
3770 ipos_encrypted_size - 1);
3771 crypto_free_cipher_env(cipher);
3772 if (declen < 0) {
3773 log_warn(LD_REND, "Decrypting introduction points failed!");
3774 tor_free(dec);
3775 return -1;
3777 *ipos_decrypted = dec;
3778 *ipos_decrypted_size = declen;
3779 return 0;
3780 } else {
3781 log_warn(LD_REND, "Unknown authorization type number: %d",
3782 ipos_encrypted[0]);
3783 return -1;
3787 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
3788 * length <b>intro_points_encoded_size</b> and write the result to the
3789 * descriptor in <b>parsed</b>; return the number of successfully parsed
3790 * introduction points or -1 in case of a failure. */
3792 rend_parse_introduction_points(rend_service_descriptor_t *parsed,
3793 const char *intro_points_encoded,
3794 size_t intro_points_encoded_size)
3796 const char *current_ipo, *end_of_intro_points;
3797 smartlist_t *tokens;
3798 directory_token_t *tok;
3799 rend_intro_point_t *intro;
3800 extend_info_t *info;
3801 int result, num_ok=1;
3802 memarea_t *area = NULL;
3803 tor_assert(parsed);
3804 /** Function may only be invoked once. */
3805 tor_assert(!parsed->intro_nodes);
3806 tor_assert(intro_points_encoded);
3807 tor_assert(intro_points_encoded_size > 0);
3808 /* Consider one intro point after the other. */
3809 current_ipo = intro_points_encoded;
3810 end_of_intro_points = intro_points_encoded + intro_points_encoded_size;
3811 tokens = smartlist_create();
3812 parsed->intro_nodes = smartlist_create();
3813 area = memarea_new();
3815 while (!memcmpstart(current_ipo, end_of_intro_points-current_ipo,
3816 "introduction-point ")) {
3817 /* Determine end of string. */
3818 const char *eos = tor_memstr(current_ipo, end_of_intro_points-current_ipo,
3819 "\nintroduction-point ");
3820 if (!eos)
3821 eos = end_of_intro_points;
3822 else
3823 eos = eos+1;
3824 tor_assert(eos <= intro_points_encoded+intro_points_encoded_size);
3825 /* Free tokens and clear token list. */
3826 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3827 smartlist_clear(tokens);
3828 memarea_clear(area);
3829 /* Tokenize string. */
3830 if (tokenize_string(area, current_ipo, eos, tokens, ipo_token_table, 0)) {
3831 log_warn(LD_REND, "Error tokenizing introduction point");
3832 goto err;
3834 /* Advance to next introduction point, if available. */
3835 current_ipo = eos;
3836 /* Check minimum allowed length of introduction point. */
3837 if (smartlist_len(tokens) < 5) {
3838 log_warn(LD_REND, "Impossibly short introduction point.");
3839 goto err;
3841 /* Allocate new intro point and extend info. */
3842 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3843 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
3844 /* Parse identifier. */
3845 tok = find_by_keyword(tokens, R_IPO_IDENTIFIER);
3846 if (base32_decode(info->identity_digest, DIGEST_LEN,
3847 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
3848 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
3849 tok->args[0]);
3850 rend_intro_point_free(intro);
3851 goto err;
3853 /* Write identifier to nickname. */
3854 info->nickname[0] = '$';
3855 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
3856 info->identity_digest, DIGEST_LEN);
3857 /* Parse IP address. */
3858 tok = find_by_keyword(tokens, R_IPO_IP_ADDRESS);
3859 if (tor_addr_from_str(&info->addr, tok->args[0])<0) {
3860 log_warn(LD_REND, "Could not parse introduction point address.");
3861 rend_intro_point_free(intro);
3862 goto err;
3864 if (tor_addr_family(&info->addr) != AF_INET) {
3865 log_warn(LD_REND, "Introduction point address was not ipv4.");
3866 rend_intro_point_free(intro);
3867 goto err;
3870 /* Parse onion port. */
3871 tok = find_by_keyword(tokens, R_IPO_ONION_PORT);
3872 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
3873 &num_ok,NULL);
3874 if (!info->port || !num_ok) {
3875 log_warn(LD_REND, "Introduction point onion port %s is invalid",
3876 escaped(tok->args[0]));
3877 rend_intro_point_free(intro);
3878 goto err;
3880 /* Parse onion key. */
3881 tok = find_by_keyword(tokens, R_IPO_ONION_KEY);
3882 info->onion_key = tok->key;
3883 tok->key = NULL; /* Prevent free */
3884 /* Parse service key. */
3885 tok = find_by_keyword(tokens, R_IPO_SERVICE_KEY);
3886 intro->intro_key = tok->key;
3887 tok->key = NULL; /* Prevent free */
3888 /* Add extend info to list of introduction points. */
3889 smartlist_add(parsed->intro_nodes, intro);
3891 result = smartlist_len(parsed->intro_nodes);
3892 goto done;
3894 err:
3895 result = -1;
3897 done:
3898 /* Free tokens and clear token list. */
3899 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3900 smartlist_free(tokens);
3901 if (area)
3902 memarea_drop_all(area);
3904 return result;
3907 /** Parse the content of a client_key file in <b>ckstr</b> and add
3908 * rend_authorized_client_t's for each parsed client to
3909 * <b>parsed_clients</b>. Return the number of parsed clients as result
3910 * or -1 for failure. */
3912 rend_parse_client_keys(strmap_t *parsed_clients, const char *ckstr)
3914 int result = -1;
3915 smartlist_t *tokens;
3916 directory_token_t *tok;
3917 const char *current_entry = NULL;
3918 memarea_t *area = NULL;
3919 if (!ckstr || strlen(ckstr) == 0)
3920 return -1;
3921 tokens = smartlist_create();
3922 /* Begin parsing with first entry, skipping comments or whitespace at the
3923 * beginning. */
3924 area = memarea_new();
3925 current_entry = eat_whitespace(ckstr);
3926 while (!strcmpstart(current_entry, "client-name ")) {
3927 rend_authorized_client_t *parsed_entry;
3928 size_t len;
3929 char descriptor_cookie_base64[REND_DESC_COOKIE_LEN_BASE64+2+1];
3930 char descriptor_cookie_tmp[REND_DESC_COOKIE_LEN+2];
3931 /* Determine end of string. */
3932 const char *eos = strstr(current_entry, "\nclient-name ");
3933 if (!eos)
3934 eos = current_entry + strlen(current_entry);
3935 else
3936 eos = eos + 1;
3937 /* Free tokens and clear token list. */
3938 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3939 smartlist_clear(tokens);
3940 memarea_clear(area);
3941 /* Tokenize string. */
3942 if (tokenize_string(area, current_entry, eos, tokens,
3943 client_keys_token_table, 0)) {
3944 log_warn(LD_REND, "Error tokenizing client keys file.");
3945 goto err;
3947 /* Advance to next entry, if available. */
3948 current_entry = eos;
3949 /* Check minimum allowed length of token list. */
3950 if (smartlist_len(tokens) < 2) {
3951 log_warn(LD_REND, "Impossibly short client key entry.");
3952 goto err;
3954 /* Parse client name. */
3955 tok = find_by_keyword(tokens, C_CLIENT_NAME);
3956 tor_assert(tok == smartlist_get(tokens, 0));
3957 tor_assert(tok->n_args == 1);
3959 len = strlen(tok->args[0]);
3960 if (len < 1 || len > 19 ||
3961 strspn(tok->args[0], REND_LEGAL_CLIENTNAME_CHARACTERS) != len) {
3962 log_warn(LD_CONFIG, "Illegal client name: %s. (Length must be "
3963 "between 1 and 19, and valid characters are "
3964 "[A-Za-z0-9+-_].)", tok->args[0]);
3965 goto err;
3967 /* Check if client name is duplicate. */
3968 if (strmap_get(parsed_clients, tok->args[0])) {
3969 log_warn(LD_CONFIG, "HiddenServiceAuthorizeClient contains a "
3970 "duplicate client name: '%s'. Ignoring.", tok->args[0]);
3971 goto err;
3973 parsed_entry = tor_malloc_zero(sizeof(rend_authorized_client_t));
3974 parsed_entry->client_name = tor_strdup(tok->args[0]);
3975 strmap_set(parsed_clients, parsed_entry->client_name, parsed_entry);
3976 /* Parse client key. */
3977 tok = find_opt_by_keyword(tokens, C_CLIENT_KEY);
3978 if (tok) {
3979 parsed_entry->client_key = tok->key;
3980 tok->key = NULL; /* Prevent free */
3983 /* Parse descriptor cookie. */
3984 tok = find_by_keyword(tokens, C_DESCRIPTOR_COOKIE);
3985 tor_assert(tok->n_args == 1);
3986 if (strlen(tok->args[0]) != REND_DESC_COOKIE_LEN_BASE64 + 2) {
3987 log_warn(LD_REND, "Descriptor cookie has illegal length: %s",
3988 escaped(tok->args[0]));
3989 goto err;
3991 /* The size of descriptor_cookie_tmp needs to be REND_DESC_COOKIE_LEN+2,
3992 * because a base64 encoding of length 24 does not fit into 16 bytes in all
3993 * cases. */
3994 if ((base64_decode(descriptor_cookie_tmp, REND_DESC_COOKIE_LEN+2,
3995 tok->args[0], REND_DESC_COOKIE_LEN_BASE64+2+1)
3996 != REND_DESC_COOKIE_LEN)) {
3997 log_warn(LD_REND, "Descriptor cookie contains illegal characters: "
3998 "%s", descriptor_cookie_base64);
3999 goto err;
4001 memcpy(parsed_entry->descriptor_cookie, descriptor_cookie_tmp,
4002 REND_DESC_COOKIE_LEN);
4004 result = strmap_size(parsed_clients);
4005 goto done;
4006 err:
4007 result = -1;
4008 done:
4009 /* Free tokens and clear token list. */
4010 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
4011 smartlist_free(tokens);
4012 if (area)
4013 memarea_drop_all(area);
4014 return result;