If the networkstatus consensus lists no recommended versions, don't
[tor.git] / src / or / routerparse.c
blobc4ebe857ff170d6f6454d5243ca3bee7fa4be32e
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, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
6 /* $Id$ */
7 const char routerparse_c_id[] =
8 "$Id$";
10 /**
11 * \file routerparse.c
12 * \brief Code to parse and validate router descriptors and directories.
13 **/
15 #include "or.h"
17 /****************************************************************************/
19 /** Enumeration of possible token types. The ones starting with K_ correspond
20 * to directory 'keywords'. _ERR is an error in the tokenizing process, _EOF
21 * is an end-of-file marker, and _NIL is used to encode not-a-token.
23 typedef enum {
24 K_ACCEPT = 0,
25 K_DIRECTORY_SIGNATURE,
26 K_RECOMMENDED_SOFTWARE,
27 K_REJECT,
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_PORTS,
40 K_CONTACT,
41 K_NETWORK_STATUS,
42 K_UPTIME,
43 K_DIR_SIGNING_KEY,
44 K_FAMILY,
45 K_FINGERPRINT,
46 K_HIBERNATING,
47 K_READ_HISTORY,
48 K_WRITE_HISTORY,
49 K_NETWORK_STATUS_VERSION,
50 K_DIR_SOURCE,
51 K_DIR_OPTIONS,
52 K_CLIENT_VERSIONS,
53 K_SERVER_VERSIONS,
54 K_R,
55 K_S,
56 K_V,
57 K_EVENTDNS,
58 K_EXTRA_INFO,
59 K_EXTRA_INFO_DIGEST,
60 K_CACHES_EXTRA_INFO,
61 K_HIDDEN_SERVICE_DIR,
63 K_DIR_KEY_CERTIFICATE_VERSION,
64 K_DIR_IDENTITY_KEY,
65 K_DIR_KEY_PUBLISHED,
66 K_DIR_KEY_EXPIRES,
67 K_DIR_KEY_CERTIFICATION,
68 K_DIR_ADDRESS,
70 K_VOTE_STATUS,
71 K_VALID_AFTER,
72 K_FRESH_UNTIL,
73 K_VALID_UNTIL,
74 K_VOTING_DELAY,
76 K_KNOWN_FLAGS,
77 K_VOTE_DIGEST,
78 K_CONSENSUS_DIGEST,
79 K_CONSENSUS_METHODS,
80 K_CONSENSUS_METHOD,
82 A_PURPOSE,
83 _A_UNKNOWN,
85 R_RENDEZVOUS_SERVICE_DESCRIPTOR,
86 R_VERSION,
87 R_PERMANENT_KEY,
88 R_SECRET_ID_PART,
89 R_PUBLICATION_TIME,
90 R_PROTOCOL_VERSIONS,
91 R_INTRODUCTION_POINTS,
92 R_SIGNATURE,
94 R_IPO_IDENTIFIER,
95 R_IPO_IP_ADDRESS,
96 R_IPO_ONION_PORT,
97 R_IPO_ONION_KEY,
98 R_IPO_SERVICE_KEY,
100 _UNRECOGNIZED,
101 _ERR,
102 _EOF,
103 _NIL
104 } directory_keyword;
106 #define MIN_ANNOTATION A_PURPOSE
107 #define MAX_ANNOTATION _A_UNKNOWN
109 /** Structure to hold a single directory token.
111 * We parse a directory by breaking it into "tokens", each consisting
112 * of a keyword, a line full of arguments, and a binary object. The
113 * arguments and object are both optional, depending on the keyword
114 * type.
116 typedef struct directory_token_t {
117 directory_keyword tp; /**< Type of the token. */
118 int n_args; /**< Number of elements in args */
119 char **args; /**< Array of arguments from keyword line. */
120 char *object_type; /**< -----BEGIN [object_type]-----*/
121 size_t object_size; /**< Bytes in object_body */
122 char *object_body; /**< Contents of object, base64-decoded. */
123 crypto_pk_env_t *key; /**< For public keys only. */
124 char *error; /**< For _ERR tokens only. */
125 } directory_token_t;
127 /* ********************************************************************** */
129 /** We use a table of rules to decide how to parse each token type. */
131 /** Rules for whether the keyword needs an object. */
132 typedef enum {
133 NO_OBJ, /**< No object, ever. */
134 NEED_OBJ, /**< Object is required. */
135 NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */
136 NEED_KEY, /**< Object is required, and must be a public key. */
137 OBJ_OK, /**< Object is optional. */
138 } obj_syntax;
140 #define AT_START 1
141 #define AT_END 2
143 /** Determines the parsing rules for a single token type. */
144 typedef struct token_rule_t {
145 /** The string value of the keyword identifying the type of item. */
146 const char *t;
147 /** The corresponding directory_keyword enum. */
148 directory_keyword v;
149 /** Minimum number of arguments for this item */
150 int min_args;
151 /** Maximum number of arguments for this item */
152 int max_args;
153 /** If true, we concatenate all arguments for this item into a single
154 * string. */
155 int concat_args;
156 /** Requirments on object syntax for this item. */
157 obj_syntax os;
158 /** Lowest number of times this item may appear in a document. */
159 int min_cnt;
160 /** Highest number of times this item may appear in a document. */
161 int max_cnt;
162 /** One or more of AT_START/AT_END to limit where the item may appear in a
163 * document. */
164 int pos;
165 /** True iff this token is an annotation. */
166 int is_annotation;
167 } token_rule_t;
170 * Helper macros to define token tables. 's' is a string, 't' is a
171 * directory_keyword, 'a' is a trio of argument multiplicities, and 'o' is an
172 * object syntax.
176 /** Appears to indicate the end of a table. */
177 #define END_OF_TABLE { NULL, _NIL, 0,0,0, NO_OBJ, 0, INT_MAX, 0, 0 }
178 /** An item with no restrictions: used for obsolete document types */
179 #define T(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
180 /** An item with no restrictions on multiplicity or location. */
181 #define T0N(s,t,a,o) { s, t, a, o, 0, INT_MAX, 0, 0 }
182 /** An item that must appear exactly once */
183 #define T1(s,t,a,o) { s, t, a, o, 1, 1, 0, 0 }
184 /** An item that must appear exactly once, at the start of the document */
185 #define T1_START(s,t,a,o) { s, t, a, o, 1, 1, AT_START, 0 }
186 /** An item that must appear exactly once, at the end of the document */
187 #define T1_END(s,t,a,o) { s, t, a, o, 1, 1, AT_END, 0 }
188 /** An item that must appear one or more times */
189 #define T1N(s,t,a,o) { s, t, a, o, 1, INT_MAX, 0, 0 }
190 /** An item that must appear no more than once */
191 #define T01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
192 /** An annotation that must appear no more than once */
193 #define A01(s,t,a,o) { s, t, a, o, 0, 1, 0, 0 }
195 /* Argument multiplicity: any number of arguments. */
196 #define ARGS 0,INT_MAX,0
197 /* Argument multiplicity: no arguments. */
198 #define NO_ARGS 0,0,0
199 /* Argument multiplicity: concatenate all arguments. */
200 #define CONCAT_ARGS 1,1,1
201 /* Argument multiplicity: at least <b>n</b> arguments. */
202 #define GE(n) n,INT_MAX,0
203 /* Argument multiplicity: exactly <b>n</b> arguments. */
204 #define EQ(n) n,n,0
206 /** List of tokens allowable in router derscriptors */
207 static token_rule_t routerdesc_token_table[] = {
208 T0N("reject", K_REJECT, ARGS, NO_OBJ ),
209 T0N("accept", K_ACCEPT, ARGS, NO_OBJ ),
210 T1_START( "router", K_ROUTER, GE(5), NO_OBJ ),
211 T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
212 T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ),
213 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
214 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
215 T01("uptime", K_UPTIME, GE(1), NO_OBJ ),
216 T01("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
217 T01("hibernating", K_HIBERNATING, GE(1), NO_OBJ ),
218 T01("platform", K_PLATFORM, CONCAT_ARGS, NO_OBJ ),
219 T01("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
220 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
221 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
222 T01("extra-info-digest", K_EXTRA_INFO_DIGEST, GE(1), NO_OBJ ),
223 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR, NO_ARGS, NO_OBJ ),
225 T01("family", K_FAMILY, ARGS, NO_OBJ ),
226 T01("caches-extra-info", K_CACHES_EXTRA_INFO, NO_ARGS, NO_OBJ ),
227 T01("eventdns", K_EVENTDNS, ARGS, NO_OBJ ),
229 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
230 T1( "bandwidth", K_BANDWIDTH, GE(3), NO_OBJ ),
231 A01("@purpose", A_PURPOSE, GE(1), NO_OBJ ),
233 END_OF_TABLE
236 /** List of tokens allowable in extra-info documents. */
237 static token_rule_t extrainfo_token_table[] = {
238 T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ),
239 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
240 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
241 T01("read-history", K_READ_HISTORY, ARGS, NO_OBJ ),
242 T01("write-history", K_WRITE_HISTORY, ARGS, NO_OBJ ),
243 T1_START( "extra-info", K_EXTRA_INFO, GE(2), NO_OBJ ),
245 END_OF_TABLE
248 /** List of tokens allowable in the body part of v2 and v3 networkstatus
249 * documents. */
250 static token_rule_t rtrstatus_token_table[] = {
251 T1( "r", K_R, GE(8), NO_OBJ ),
252 T1( "s", K_S, ARGS, NO_OBJ ),
253 T01("v", K_V, CONCAT_ARGS, NO_OBJ ),
254 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
255 END_OF_TABLE
258 /** List of tokens allowable in the header part of v2 networkstatus documents.
260 static token_rule_t netstatus_token_table[] = {
261 T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
262 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
263 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
264 T1( "dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ),
265 T1( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
266 T1_START("network-status-version", K_NETWORK_STATUS_VERSION,
267 GE(1), NO_OBJ ),
268 T1( "dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
269 T01("dir-options", K_DIR_OPTIONS, ARGS, NO_OBJ ),
270 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
271 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
273 END_OF_TABLE
276 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
277 * footers. */
278 static token_rule_t dir_footer_token_table[] = {
279 T1("directory-signature", K_DIRECTORY_SIGNATURE, EQ(1), NEED_OBJ ),
280 END_OF_TABLE
283 /** List of tokens allowable in v1 directory headers/footers. */
284 static token_rule_t dir_token_table[] = {
285 /* don't enforce counts; this is obsolete. */
286 T( "network-status", K_NETWORK_STATUS, NO_ARGS, NO_OBJ ),
287 T( "directory-signature", K_DIRECTORY_SIGNATURE, ARGS, NEED_OBJ ),
288 T( "recommended-software",K_RECOMMENDED_SOFTWARE,CONCAT_ARGS, NO_OBJ ),
289 T( "signed-directory", K_SIGNED_DIRECTORY, NO_ARGS, NO_OBJ ),
291 T( "running-routers", K_RUNNING_ROUTERS, ARGS, NO_OBJ ),
292 T( "router-status", K_ROUTER_STATUS, ARGS, NO_OBJ ),
293 T( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
294 T( "opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
295 T( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
296 T( "dir-signing-key", K_DIR_SIGNING_KEY, ARGS, OBJ_OK ),
297 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
299 END_OF_TABLE
302 #define CERTIFICATE_MEMBERS \
303 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
304 GE(1), NO_OBJ ), \
305 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
306 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
307 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
308 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
309 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
310 NO_ARGS, NEED_OBJ), \
311 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
313 static token_rule_t dir_key_certificate_table[] = {
314 CERTIFICATE_MEMBERS
315 T1("fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
316 END_OF_TABLE
319 /** List of tokens allowable in rendezvous service descriptors */
320 static token_rule_t desc_token_table[] = {
321 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR,
322 EQ(1), NO_OBJ),
323 T1("version", R_VERSION, EQ(1), NO_OBJ),
324 T1("permanent-key", R_PERMANENT_KEY, NO_ARGS, NEED_KEY_1024),
325 T1("secret-id-part", R_SECRET_ID_PART, EQ(1), NO_OBJ),
326 T1("publication-time", R_PUBLICATION_TIME, CONCAT_ARGS, NO_OBJ),
327 T1("protocol-versions", R_PROTOCOL_VERSIONS, EQ(1), NO_OBJ),
328 T01("introduction-points", R_INTRODUCTION_POINTS, NO_ARGS, NEED_OBJ),
329 T1_END("signature", R_SIGNATURE, NO_ARGS, NEED_OBJ),
330 END_OF_TABLE
333 /** List of tokens allowed in the (encrypted) list of introduction points of
334 * rendezvous service descriptors */
335 static token_rule_t ipo_token_table[] = {
336 T1_START("introduction-point", R_IPO_IDENTIFIER, EQ(1), NO_OBJ),
337 T1("ip-address", R_IPO_IP_ADDRESS, EQ(1), NO_OBJ),
338 T1("onion-port", R_IPO_ONION_PORT, EQ(1), NO_OBJ),
339 T1("onion-key", R_IPO_ONION_KEY, NO_ARGS, NEED_KEY_1024),
340 T1("service-key", R_IPO_SERVICE_KEY, NO_ARGS, NEED_KEY_1024),
341 END_OF_TABLE
344 static token_rule_t networkstatus_token_table[] = {
345 T1("network-status-version", K_NETWORK_STATUS_VERSION,
346 GE(1), NO_OBJ ),
347 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
348 T1("published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ),
349 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
350 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
351 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
352 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
353 T1("known-flags", K_KNOWN_FLAGS, ARGS, NO_OBJ ),
354 T( "fingerprint", K_FINGERPRINT, CONCAT_ARGS, NO_OBJ ),
356 CERTIFICATE_MEMBERS
358 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
359 T1( "contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
360 T1( "dir-source", K_DIR_SOURCE, GE(6), NO_OBJ ),
361 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
362 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
363 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
364 T1( "consensus-methods", K_CONSENSUS_METHODS, GE(1), NO_OBJ ),
366 END_OF_TABLE
368 static token_rule_t networkstatus_consensus_token_table[] = {
369 T1("network-status-version", K_NETWORK_STATUS_VERSION,
370 GE(1), NO_OBJ ),
371 T1("vote-status", K_VOTE_STATUS, GE(1), NO_OBJ ),
372 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
373 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
374 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
375 T1("voting-delay", K_VOTING_DELAY, GE(2), NO_OBJ ),
377 T0N("opt", K_OPT, CONCAT_ARGS, OBJ_OK ),
379 T1N("dir-source", K_DIR_SOURCE, GE(3), NO_OBJ ),
380 T1N("contact", K_CONTACT, CONCAT_ARGS, NO_OBJ ),
381 T1N("vote-digest", K_VOTE_DIGEST, GE(1), NO_OBJ ),
383 T1( "known-flags", K_KNOWN_FLAGS, CONCAT_ARGS, NO_OBJ ),
385 T01("client-versions", K_CLIENT_VERSIONS, CONCAT_ARGS, NO_OBJ ),
386 T01("server-versions", K_SERVER_VERSIONS, CONCAT_ARGS, NO_OBJ ),
387 T01("consensus-method", K_CONSENSUS_METHOD, EQ(1), NO_OBJ),
389 END_OF_TABLE
392 /** List of tokens allowable in the footer of v1/v2 directory/networkstatus
393 * footers. */
394 static token_rule_t networkstatus_vote_footer_token_table[] = {
395 T( "directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
396 END_OF_TABLE
399 static token_rule_t networkstatus_detached_signature_token_table[] = {
400 T1_START("consensus-digest", K_CONSENSUS_DIGEST, GE(1), NO_OBJ ),
401 T1("valid-after", K_VALID_AFTER, CONCAT_ARGS, NO_OBJ ),
402 T1("fresh-until", K_FRESH_UNTIL, CONCAT_ARGS, NO_OBJ ),
403 T1("valid-until", K_VALID_UNTIL, CONCAT_ARGS, NO_OBJ ),
404 T1N("directory-signature", K_DIRECTORY_SIGNATURE, GE(2), NEED_OBJ ),
405 END_OF_TABLE
408 #undef T
410 /* static function prototypes */
411 static int router_add_exit_policy(routerinfo_t *router,directory_token_t *tok);
412 static addr_policy_t *router_parse_addr_policy(directory_token_t *tok);
413 static addr_policy_t *router_parse_addr_policy_private(directory_token_t *tok);
415 static int router_get_hash_impl(const char *s, char *digest,
416 const char *start_str, const char *end_str,
417 char end_char);
418 static void token_free(directory_token_t *tok);
419 static smartlist_t *find_all_exitpolicy(smartlist_t *s);
420 static directory_token_t *find_first_by_keyword(smartlist_t *s,
421 directory_keyword keyword);
422 #define TS_ANNOTATIONS_OK 1
423 #define TS_NOCHECK 2
424 #define TS_NO_NEW_ANNOTATIONS 4
425 static int tokenize_string(const char *start, const char *end,
426 smartlist_t *out,
427 token_rule_t *table,
428 int flags);
429 static directory_token_t *get_next_token(const char **s,
430 const char *eos,
431 token_rule_t *table);
432 static int check_signature_token(const char *digest,
433 directory_token_t *tok,
434 crypto_pk_env_t *pkey,
435 int check_authority,
436 const char *doctype);
437 static crypto_pk_env_t *find_dir_signing_key(const char *str, const char *eos);
438 static int tor_version_same_series(tor_version_t *a, tor_version_t *b);
440 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
441 * <b>s</b>. Return 0 on success, -1 on failure.
444 router_get_dir_hash(const char *s, char *digest)
446 return router_get_hash_impl(s,digest,
447 "signed-directory","\ndirectory-signature",'\n');
450 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
451 * <b>s</b>. Return 0 on success, -1 on failure.
454 router_get_router_hash(const char *s, char *digest)
456 return router_get_hash_impl(s,digest,
457 "router ","\nrouter-signature", '\n');
460 /** Set <b>digest</b> to the SHA-1 digest of the hash of the running-routers
461 * string in <b>s</b>. Return 0 on success, -1 on failure.
464 router_get_runningrouters_hash(const char *s, char *digest)
466 return router_get_hash_impl(s,digest,
467 "network-status","\ndirectory-signature", '\n');
470 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
471 * string in <b>s</b>. Return 0 on success, -1 on failure. */
473 router_get_networkstatus_v2_hash(const char *s, char *digest)
475 return router_get_hash_impl(s,digest,
476 "network-status-version","\ndirectory-signature",
477 '\n');
480 /** Set <b>digest</b> to the SHA-1 digest of the hash of the network-status
481 * string in <b>s</b>. Return 0 on success, -1 on failure. */
483 router_get_networkstatus_v3_hash(const char *s, char *digest)
485 return router_get_hash_impl(s,digest,
486 "network-status-version","\ndirectory-signature",
487 ' ');
490 /** Set <b>digest</b> to the SHA-1 digest of the hash of the extrainfo
491 * string in <b>s</b>. Return 0 on success, -1 on failure. */
493 router_get_extrainfo_hash(const char *s, char *digest)
495 return router_get_hash_impl(s,digest,"extra-info","\nrouter-signature",'\n');
498 /** Helper: used to generate signatures for routers, directories and
499 * network-status objects. Given a digest in <b>digest</b> and a secret
500 * <b>private_key</b>, generate an PKCS1-padded signature, BASE64-encode it,
501 * surround it with -----BEGIN/END----- pairs, and write it to the
502 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
503 * failure.
506 router_append_dirobj_signature(char *buf, size_t buf_len, const char *digest,
507 crypto_pk_env_t *private_key)
509 char *signature;
510 int i;
512 signature = tor_malloc(crypto_pk_keysize(private_key));
513 if (crypto_pk_private_sign(private_key, signature, digest, DIGEST_LEN) < 0) {
515 log_warn(LD_BUG,"Couldn't sign digest.");
516 goto err;
518 if (strlcat(buf, "-----BEGIN SIGNATURE-----\n", buf_len) >= buf_len)
519 goto truncated;
521 i = strlen(buf);
522 if (base64_encode(buf+i, buf_len-i, signature, 128) < 0) {
523 log_warn(LD_BUG,"couldn't base64-encode signature");
524 goto err;
527 if (strlcat(buf, "-----END SIGNATURE-----\n", buf_len) >= buf_len)
528 goto truncated;
530 tor_free(signature);
531 return 0;
533 truncated:
534 log_warn(LD_BUG,"tried to exceed string length.");
535 err:
536 tor_free(signature);
537 return -1;
540 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
541 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
542 * entries. Else, return VS_OLD if every member of
543 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
544 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
545 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
546 * is newer than <b>myversion.</b>. Else, return VS_NEW if every memeber of
547 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
548 * VS_UNRECOMMENDED.
550 * (versionlist is a comma-separated list of version strings,
551 * optionally prefixed with "Tor". Versions that can't be parsed are
552 * ignored.)
554 version_status_t
555 tor_version_is_obsolete(const char *myversion, const char *versionlist)
557 tor_version_t mine, other;
558 int found_newer = 0, found_older = 0, found_newer_in_series = 0,
559 found_any_in_series = 0, r, same;
560 version_status_t ret = VS_UNRECOMMENDED;
561 smartlist_t *version_sl;
563 log_debug(LD_CONFIG,"Checking whether version '%s' is in '%s'",
564 myversion, versionlist);
566 if (tor_version_parse(myversion, &mine)) {
567 log_err(LD_BUG,"I couldn't parse my own version (%s)", myversion);
568 tor_assert(0);
570 version_sl = smartlist_create();
571 smartlist_split_string(version_sl, versionlist, ",", SPLIT_SKIP_SPACE, 0);
573 if (!strlen(versionlist)) { /* no authorities cared or agreed */
574 ret = VS_EMPTY;
575 goto done;
578 SMARTLIST_FOREACH(version_sl, const char *, cp, {
579 if (!strcmpstart(cp, "Tor "))
580 cp += 4;
582 if (tor_version_parse(cp, &other)) {
583 /* Couldn't parse other; it can't be a match. */
584 } else {
585 same = tor_version_same_series(&mine, &other);
586 if (same)
587 found_any_in_series = 1;
588 r = tor_version_compare(&mine, &other);
589 if (r==0) {
590 ret = VS_RECOMMENDED;
591 goto done;
592 } else if (r<0) {
593 found_newer = 1;
594 if (same)
595 found_newer_in_series = 1;
596 } else if (r>0) {
597 found_older = 1;
602 /* We didn't find the listed version. Is it new or old? */
603 if (found_any_in_series && !found_newer_in_series && found_newer) {
604 ret = VS_NEW_IN_SERIES;
605 } else if (found_newer && !found_older) {
606 ret = VS_OLD;
607 } else if (found_older && !found_newer) {
608 ret = VS_NEW;
609 } else {
610 ret = VS_UNRECOMMENDED;
613 done:
614 SMARTLIST_FOREACH(version_sl, char *, version, tor_free(version));
615 smartlist_free(version_sl);
616 return ret;
619 /** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
620 * Otherwise, return -1. If we're a directory cache, cache it.
623 router_parse_directory(const char *str)
625 directory_token_t *tok;
626 char digest[DIGEST_LEN];
627 time_t published_on;
628 int r;
629 const char *end, *cp;
630 smartlist_t *tokens = NULL;
631 crypto_pk_env_t *declared_key = NULL;
633 /* XXXX This could be simplified a lot, but it will all go away
634 * once pre-0.1.1.8 is obsolete, and for now it's better not to
635 * touch it. */
637 if (router_get_dir_hash(str, digest)) {
638 log_warn(LD_DIR, "Unable to compute digest of directory");
639 goto err;
641 log_debug(LD_DIR,"Received directory hashes to %s",hex_str(digest,4));
643 /* Check signature first, before we try to tokenize. */
644 cp = str;
645 while (cp && (end = strstr(cp+1, "\ndirectory-signature")))
646 cp = end;
647 if (cp == str || !cp) {
648 log_warn(LD_DIR, "No signature found on directory."); goto err;
650 ++cp;
651 tokens = smartlist_create();
652 if (tokenize_string(cp,strchr(cp,'\0'),tokens,dir_token_table,0)) {
653 log_warn(LD_DIR, "Error tokenizing directory signature"); goto err;
655 if (smartlist_len(tokens) != 1) {
656 log_warn(LD_DIR, "Unexpected number of tokens in signature"); goto err;
658 tok=smartlist_get(tokens,0);
659 if (tok->tp != K_DIRECTORY_SIGNATURE) {
660 log_warn(LD_DIR,"Expected a single directory signature"); goto err;
662 declared_key = find_dir_signing_key(str, str+strlen(str));
663 note_crypto_pk_op(VERIFY_DIR);
664 if (check_signature_token(digest, tok, declared_key, 1, "directory")<0)
665 goto err;
667 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
668 smartlist_free(tokens);
669 tokens = NULL;
671 /* Now try to parse the first part of the directory. */
672 if ((end = strstr(str,"\nrouter "))) {
673 ++end;
674 } else if ((end = strstr(str, "\ndirectory-signature"))) {
675 ++end;
676 } else {
677 end = str + strlen(str);
680 tokens = smartlist_create();
681 if (tokenize_string(str,end,tokens,dir_token_table,0)) {
682 log_warn(LD_DIR, "Error tokenizing directory"); goto err;
685 tok = find_first_by_keyword(tokens, K_PUBLISHED);
686 tor_assert(tok);
687 tor_assert(tok->n_args == 1);
689 if (parse_iso_time(tok->args[0], &published_on) < 0) {
690 goto err;
693 /* Now that we know the signature is okay, and we have a
694 * publication time, cache the directory. */
695 if (directory_caches_v1_dir_info(get_options()) &&
696 !authdir_mode_v1(get_options()))
697 dirserv_set_cached_directory(str, published_on, 0);
699 r = 0;
700 goto done;
701 err:
702 r = -1;
703 done:
704 if (declared_key) crypto_free_pk_env(declared_key);
705 if (tokens) {
706 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
707 smartlist_free(tokens);
709 return r;
712 /** Read a signed router status statement from <b>str</b>. If it's
713 * well-formed, return 0. Otherwise, return -1. If we're a directory cache,
714 * cache it.*/
716 router_parse_runningrouters(const char *str)
718 char digest[DIGEST_LEN];
719 directory_token_t *tok;
720 time_t published_on;
721 int r = -1;
722 crypto_pk_env_t *declared_key = NULL;
723 smartlist_t *tokens = NULL;
724 const char *eos = str + strlen(str);
726 if (router_get_runningrouters_hash(str, digest)) {
727 log_warn(LD_DIR, "Unable to compute digest of running-routers");
728 goto err;
730 tokens = smartlist_create();
731 if (tokenize_string(str,eos,tokens,dir_token_table,0)) {
732 log_warn(LD_DIR, "Error tokenizing running-routers"); goto err;
734 tok = smartlist_get(tokens,0);
735 if (tok->tp != K_NETWORK_STATUS) {
736 log_warn(LD_DIR, "Network-status starts with wrong token");
737 goto err;
740 tok = find_first_by_keyword(tokens, K_PUBLISHED);
741 tor_assert(tok);
742 tor_assert(tok->n_args == 1);
743 if (parse_iso_time(tok->args[0], &published_on) < 0) {
744 goto err;
746 if (!(tok = find_first_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
747 log_warn(LD_DIR, "Missing signature on running-routers");
748 goto err;
750 declared_key = find_dir_signing_key(str, eos);
751 note_crypto_pk_op(VERIFY_DIR);
752 if (check_signature_token(digest, tok, declared_key, 1, "running-routers")
753 < 0)
754 goto err;
756 /* Now that we know the signature is okay, and we have a
757 * publication time, cache the list. */
758 if (get_options()->DirPort && !authdir_mode_v1(get_options()))
759 dirserv_set_cached_directory(str, published_on, 1);
761 r = 0;
762 err:
763 if (declared_key) crypto_free_pk_env(declared_key);
764 if (tokens) {
765 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
766 smartlist_free(tokens);
768 return r;
771 /** Given a directory or running-routers string in <b>str</b>, try to
772 * find the its dir-signing-key token (if any). If this token is
773 * present, extract and return the key. Return NULL on failure. */
774 static crypto_pk_env_t *
775 find_dir_signing_key(const char *str, const char *eos)
777 const char *cp;
778 directory_token_t *tok;
779 crypto_pk_env_t *key = NULL;
780 tor_assert(str);
781 tor_assert(eos);
783 /* Is there a dir-signing-key in the directory? */
784 cp = tor_memstr(str, eos-str, "\nopt dir-signing-key");
785 if (!cp)
786 cp = tor_memstr(str, eos-str, "\ndir-signing-key");
787 if (!cp)
788 return NULL;
789 ++cp; /* Now cp points to the start of the token. */
791 tok = get_next_token(&cp, eos, dir_token_table);
792 if (!tok) {
793 log_warn(LD_DIR, "Unparseable dir-signing-key token");
794 return NULL;
796 if (tok->tp != K_DIR_SIGNING_KEY) {
797 log_warn(LD_DIR, "Dir-signing-key token did not parse as expected");
798 goto done;
801 if (tok->key) {
802 key = tok->key;
803 tok->key = NULL; /* steal reference. */
804 } else {
805 log_warn(LD_DIR, "Dir-signing-key token contained no key");
808 done:
809 if (tok) token_free(tok);
810 return key;
813 /** Return true iff <b>key</b> is allowed to sign directories.
815 static int
816 dir_signing_key_is_trusted(crypto_pk_env_t *key)
818 char digest[DIGEST_LEN];
819 if (!key) return 0;
820 if (crypto_pk_get_digest(key, digest) < 0) {
821 log_warn(LD_DIR, "Error computing dir-signing-key digest");
822 return 0;
824 if (!router_digest_is_trusted_dir(digest)) {
825 log_warn(LD_DIR, "Listed dir-signing-key is not trusted");
826 return 0;
828 return 1;
831 /** Check whether the object body of the token in <b>tok</b> has a good
832 * signature for <b>digest</b> using key <b>pkey</b>. If
833 * <b>check_authority</b> is set, make sure that <b>pkey</b> is the key of a
834 * directory authority. Use <b>doctype</b> as the type of the document when
835 * generating log messages. Return 0 on success, negative on failure.
837 static int
838 check_signature_token(const char *digest,
839 directory_token_t *tok,
840 crypto_pk_env_t *pkey,
841 int check_authority,
842 const char *doctype)
844 char *signed_digest;
846 tor_assert(pkey);
847 tor_assert(tok);
848 tor_assert(digest);
849 tor_assert(doctype);
851 if (check_authority && !dir_signing_key_is_trusted(pkey)) {
852 log_warn(LD_DIR, "Key on %s did not come from an authority; rejecting",
853 doctype);
854 return -1;
857 if (strcmp(tok->object_type, "SIGNATURE")) {
858 log_warn(LD_DIR, "Bad object type on %s signature", doctype);
859 return -1;
862 signed_digest = tor_malloc(tok->object_size);
863 if (crypto_pk_public_checksig(pkey, signed_digest, tok->object_body,
864 tok->object_size)
865 != DIGEST_LEN) {
866 log_warn(LD_DIR, "Error reading %s: invalid signature.", doctype);
867 tor_free(signed_digest);
868 return -1;
870 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
871 // hex_str(signed_digest,4));
872 if (memcmp(digest, signed_digest, DIGEST_LEN)) {
873 log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype);
874 tor_free(signed_digest);
875 return -1;
877 tor_free(signed_digest);
878 return 0;
881 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
882 * or to the first of the annotations proceeding the next router or
883 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
884 * we found an extrainfo, or false if found a router. Do not scan beyond
885 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
886 static int
887 find_start_of_next_router_or_extrainfo(const char **s_ptr,
888 const char *eos,
889 int *is_extrainfo_out)
891 const char *annotations = NULL;
892 const char *s = *s_ptr;
894 s = eat_whitespace_eos(s, eos);
896 while (s < eos-32) { /* 32 gives enough room for a the first keyword. */
897 /* We're at the start of a line. */
898 tor_assert(*s != '\n');
900 if (*s == '@' && !annotations) {
901 annotations = s;
902 } else if (*s == 'r' && !strcmpstart(s, "router ")) {
903 *s_ptr = annotations ? annotations : s;
904 *is_extrainfo_out = 0;
905 return 0;
906 } else if (*s == 'e' && !strcmpstart(s, "extra-info ")) {
907 *s_ptr = annotations ? annotations : s;
908 *is_extrainfo_out = 1;
909 return 0;
912 if (!(s = memchr(s+1, '\n', eos-(s+1))))
913 break;
914 s = eat_whitespace_eos(s, eos);
916 return -1;
919 /** Given a string *<b>s</b> containing a concatenated sequence of router
920 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
921 * them and stores the result in <b>dest</b>. All routers are marked running
922 * and valid. Advances *s to a point immediately following the last router
923 * entry. Ignore any trailing router entries that are not complete.
925 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
926 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
927 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
929 * Returns 0 on success and -1 on failure.
932 router_parse_list_from_string(const char **s, const char *eos,
933 smartlist_t *dest,
934 saved_location_t saved_location,
935 int want_extrainfo,
936 int allow_annotations,
937 const char *prepend_annotations)
939 routerinfo_t *router;
940 extrainfo_t *extrainfo;
941 signed_descriptor_t *signed_desc;
942 void *elt;
943 const char *end, *start;
944 int have_extrainfo;
946 tor_assert(s);
947 tor_assert(*s);
948 tor_assert(dest);
950 start = *s;
951 if (!eos)
952 eos = *s + strlen(*s);
954 tor_assert(eos >= *s);
956 while (1) {
957 if (find_start_of_next_router_or_extrainfo(s, eos, &have_extrainfo) < 0)
958 break;
960 end = tor_memstr(*s, eos-*s, "\nrouter-signature");
961 if (end)
962 end = tor_memstr(end, eos-end, "\n-----END SIGNATURE-----\n");
963 if (end)
964 end += strlen("\n-----END SIGNATURE-----\n");
966 if (!end)
967 break;
969 elt = NULL;
971 if (have_extrainfo && want_extrainfo) {
972 routerlist_t *rl = router_get_routerlist();
973 extrainfo = extrainfo_parse_entry_from_string(*s, end,
974 saved_location != SAVED_IN_CACHE,
975 rl->identity_map);
976 if (extrainfo) {
977 signed_desc = &extrainfo->cache_info;
978 elt = extrainfo;
980 } else if (!have_extrainfo && !want_extrainfo) {
981 router = router_parse_entry_from_string(*s, end,
982 saved_location != SAVED_IN_CACHE,
983 allow_annotations,
984 prepend_annotations);
985 if (router) {
986 log_debug(LD_DIR, "Read router '%s', purpose '%s'",
987 router->nickname, router_purpose_to_string(router->purpose));
988 signed_desc = &router->cache_info;
989 elt = router;
992 if (!elt) {
993 *s = end;
994 continue;
996 if (saved_location != SAVED_NOWHERE) {
997 signed_desc->saved_location = saved_location;
998 signed_desc->saved_offset = *s - start;
1000 *s = end;
1001 smartlist_add(dest, elt);
1004 return 0;
1007 /* For debugging: define to count every descriptor digest we've seen so we
1008 * know if we need to try harder to avoid duplicate verifies. */
1009 #undef COUNT_DISTINCT_DIGESTS
1011 #ifdef COUNT_DISTINCT_DIGESTS
1012 static digestmap_t *verified_digests = NULL;
1013 #endif
1015 /** Log the total count of the number of distinct router digests we've ever
1016 * verified. When compared to the number of times we've verified routerdesc
1017 * signatures <i>in toto</i>, this will tell us if we're doing too much
1018 * multiple-verification. */
1019 void
1020 dump_distinct_digest_count(int severity)
1022 #ifdef COUNT_DISTINCT_DIGESTS
1023 if (!verified_digests)
1024 verified_digests = digestmap_new();
1025 log(severity, LD_GENERAL, "%d *distinct* router digests verified",
1026 digestmap_size(verified_digests));
1027 #else
1028 (void)severity; /* suppress "unused parameter" warning */
1029 #endif
1032 /** Helper function: reads a single router entry from *<b>s</b> ...
1033 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1034 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1035 * s through end into the signed_descriptor_body of the resulting
1036 * routerinfo_t.
1038 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1039 * before the router; if it's false, reject the router if it's annotated. If
1040 * <b>prepend_annotations</b> is set, it should contain some annotations:
1041 * append them to the front of the router before parsing it, and keep them
1042 * around when caching the router.
1044 * Only one of allow_annotations and prepend_annotations may be set.
1046 routerinfo_t *
1047 router_parse_entry_from_string(const char *s, const char *end,
1048 int cache_copy, int allow_annotations,
1049 const char *prepend_annotations)
1051 routerinfo_t *router = NULL;
1052 char digest[128];
1053 smartlist_t *tokens = NULL, *exit_policy_tokens = NULL;
1054 directory_token_t *tok;
1055 struct in_addr in;
1056 const char *start_of_annotations, *cp;
1057 size_t prepend_len = prepend_annotations ? strlen(prepend_annotations) : 0;
1058 int ok = 1;
1060 tor_assert(!allow_annotations || !prepend_annotations);
1062 if (!end) {
1063 end = s + strlen(s);
1066 /* point 'end' to a point immediately after the final newline. */
1067 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1068 --end;
1070 tokens = smartlist_create();
1071 if (prepend_annotations) {
1072 if (tokenize_string(prepend_annotations,NULL,tokens,
1073 routerdesc_token_table,TS_NOCHECK)) {
1074 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1075 goto err;
1079 start_of_annotations = s;
1080 cp = tor_memstr(s, end-s, "\nrouter ");
1081 if (!cp) {
1082 if (end-s < 7 || strcmpstart(s, "router ")) {
1083 log_warn(LD_DIR, "No router keyword found.");
1084 goto err;
1086 } else {
1087 s = cp+1;
1090 if (allow_annotations && start_of_annotations != s) {
1091 if (tokenize_string(start_of_annotations,s,tokens,
1092 routerdesc_token_table,TS_NOCHECK)) {
1093 log_warn(LD_DIR, "Error tokenizing router descriptor (annotations).");
1094 goto err;
1098 if (router_get_router_hash(s, digest) < 0) {
1099 log_warn(LD_DIR, "Couldn't compute router hash.");
1100 goto err;
1103 int flags = 0;
1104 if (allow_annotations)
1105 flags |= TS_ANNOTATIONS_OK;
1106 if (prepend_annotations)
1107 flags |= TS_ANNOTATIONS_OK|TS_NO_NEW_ANNOTATIONS;
1109 if (tokenize_string(s,end,tokens,routerdesc_token_table, flags)) {
1110 log_warn(LD_DIR, "Error tokenizing router descriptor.");
1111 goto err;
1115 if (smartlist_len(tokens) < 2) {
1116 log_warn(LD_DIR, "Impossibly short router descriptor.");
1117 goto err;
1120 tok = find_first_by_keyword(tokens, K_ROUTER);
1121 tor_assert(tok->n_args >= 5);
1123 router = tor_malloc_zero(sizeof(routerinfo_t));
1124 router->cache_info.routerlist_index = -1;
1125 router->cache_info.annotations_len = s-start_of_annotations + prepend_len;
1126 router->cache_info.signed_descriptor_len = end-s;
1127 if (cache_copy) {
1128 size_t len = router->cache_info.signed_descriptor_len +
1129 router->cache_info.annotations_len;
1130 char *cp =
1131 router->cache_info.signed_descriptor_body = tor_malloc(len+1);
1132 if (prepend_annotations) {
1133 memcpy(cp, prepend_annotations, prepend_len);
1134 cp += prepend_len;
1136 memcpy(cp, start_of_annotations, end-start_of_annotations);
1137 router->cache_info.signed_descriptor_body[len] = '\0';
1138 tor_assert(strlen(router->cache_info.signed_descriptor_body) == len);
1140 memcpy(router->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1142 router->nickname = tor_strdup(tok->args[0]);
1143 if (!is_legal_nickname(router->nickname)) {
1144 log_warn(LD_DIR,"Router nickname is invalid");
1145 goto err;
1147 router->address = tor_strdup(tok->args[1]);
1148 if (!tor_inet_aton(router->address, &in)) {
1149 log_warn(LD_DIR,"Router address is not an IP address.");
1150 goto err;
1152 router->addr = ntohl(in.s_addr);
1154 router->or_port =
1155 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,&ok,NULL);
1156 if (!ok) {
1157 log_warn(LD_DIR,"Invalid OR port %s", escaped(tok->args[2]));
1158 goto err;
1160 router->dir_port =
1161 (uint16_t) tor_parse_long(tok->args[4],10,0,65535,&ok,NULL);
1162 if (!ok) {
1163 log_warn(LD_DIR,"Invalid dir port %s", escaped(tok->args[4]));
1164 goto err;
1167 tok = find_first_by_keyword(tokens, K_BANDWIDTH);
1168 tor_assert(tok && tok->n_args >= 3);
1169 router->bandwidthrate =
1170 tor_parse_long(tok->args[0],10,1,INT_MAX,&ok,NULL);
1172 if (!ok) {
1173 log_warn(LD_DIR, "bandwidthrate %s unreadable or 0. Failing.",
1174 escaped(tok->args[0]));
1175 goto err;
1177 router->bandwidthburst = tor_parse_long(tok->args[1],10,0,INT_MAX,&ok,NULL);
1178 if (!ok) {
1179 log_warn(LD_DIR, "Invalid bandwidthburst %s", escaped(tok->args[1]));
1180 goto err;
1182 router->bandwidthcapacity =
1183 tor_parse_long(tok->args[2],10,0,INT_MAX,&ok,NULL);
1184 if (!ok) {
1185 log_warn(LD_DIR, "Invalid bandwidthcapacity %s", escaped(tok->args[1]));
1186 goto err;
1189 if ((tok = find_first_by_keyword(tokens, A_PURPOSE))) {
1190 tor_assert(tok->n_args);
1191 router->purpose = router_purpose_from_string(tok->args[0]);
1192 } else {
1193 router->purpose = ROUTER_PURPOSE_GENERAL;
1195 router->cache_info.send_unencrypted =
1196 (router->purpose == ROUTER_PURPOSE_GENERAL) ? 1 : 0;
1198 if ((tok = find_first_by_keyword(tokens, K_UPTIME))) {
1199 tor_assert(tok->n_args >= 1);
1200 router->uptime = tor_parse_long(tok->args[0],10,0,LONG_MAX,&ok,NULL);
1201 if (!ok) {
1202 log_warn(LD_DIR, "Invalid uptime %s", escaped(tok->args[0]));
1203 goto err;
1207 if ((tok = find_first_by_keyword(tokens, K_HIBERNATING))) {
1208 tor_assert(tok->n_args >= 1);
1209 router->is_hibernating
1210 = (tor_parse_long(tok->args[0],10,0,LONG_MAX,NULL,NULL) != 0);
1213 tok = find_first_by_keyword(tokens, K_PUBLISHED);
1214 tor_assert(tok);
1215 tor_assert(tok->n_args == 1);
1216 if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0)
1217 goto err;
1219 tok = find_first_by_keyword(tokens, K_ONION_KEY);
1220 tor_assert(tok);
1221 router->onion_pkey = tok->key;
1222 tok->key = NULL; /* Prevent free */
1224 tok = find_first_by_keyword(tokens, K_SIGNING_KEY);
1225 tor_assert(tok);
1226 router->identity_pkey = tok->key;
1227 tok->key = NULL; /* Prevent free */
1228 if (crypto_pk_get_digest(router->identity_pkey,
1229 router->cache_info.identity_digest)) {
1230 log_warn(LD_DIR, "Couldn't calculate key digest"); goto err;
1233 if ((tok = find_first_by_keyword(tokens, K_FINGERPRINT))) {
1234 /* If there's a fingerprint line, it must match the identity digest. */
1235 char d[DIGEST_LEN];
1236 tor_assert(tok->n_args == 1);
1237 tor_strstrip(tok->args[0], " ");
1238 if (base16_decode(d, DIGEST_LEN, tok->args[0], strlen(tok->args[0]))) {
1239 log_warn(LD_DIR, "Couldn't decode router fingerprint %s",
1240 escaped(tok->args[0]));
1241 goto err;
1243 if (memcmp(d,router->cache_info.identity_digest, DIGEST_LEN)!=0) {
1244 log_warn(LD_DIR, "Fingerprint '%s' does not match identity digest.",
1245 tok->args[0]);
1246 goto err;
1250 if ((tok = find_first_by_keyword(tokens, K_PLATFORM))) {
1251 router->platform = tor_strdup(tok->args[0]);
1254 if ((tok = find_first_by_keyword(tokens, K_CONTACT))) {
1255 router->contact_info = tor_strdup(tok->args[0]);
1258 if ((tok = find_first_by_keyword(tokens, K_EVENTDNS))) {
1259 router->has_old_dnsworkers = tok->n_args && !strcmp(tok->args[0], "0");
1260 } else if (router->platform) {
1261 if (! tor_version_as_new_as(router->platform, "0.1.2.2-alpha"))
1262 router->has_old_dnsworkers = 1;
1265 exit_policy_tokens = find_all_exitpolicy(tokens);
1266 SMARTLIST_FOREACH(exit_policy_tokens, directory_token_t *, t,
1267 if (router_add_exit_policy(router,t)<0) {
1268 log_warn(LD_DIR,"Error in exit policy");
1269 goto err;
1271 policy_expand_private(&router->exit_policy);
1273 if ((tok = find_first_by_keyword(tokens, K_FAMILY)) && tok->n_args) {
1274 int i;
1275 router->declared_family = smartlist_create();
1276 for (i=0;i<tok->n_args;++i) {
1277 if (!is_legal_nickname_or_hexdigest(tok->args[i])) {
1278 log_warn(LD_DIR, "Illegal nickname %s in family line",
1279 escaped(tok->args[i]));
1280 goto err;
1282 smartlist_add(router->declared_family, tor_strdup(tok->args[i]));
1286 if ((tok = find_first_by_keyword(tokens, K_CACHES_EXTRA_INFO)))
1287 router->caches_extra_info = 1;
1289 if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
1290 tor_assert(tok->n_args >= 1);
1291 if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
1292 base16_decode(router->cache_info.extra_info_digest,
1293 DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
1294 } else {
1295 log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
1299 if ((tok = find_first_by_keyword(tokens, K_HIDDEN_SERVICE_DIR))) {
1300 router->wants_to_be_hs_dir = 1;
1303 tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE);
1304 tor_assert(tok);
1305 note_crypto_pk_op(VERIFY_RTR);
1306 #ifdef COUNT_DISTINCT_DIGESTS
1307 if (!verified_digests)
1308 verified_digests = digestmap_new();
1309 digestmap_set(verified_digests, signed_digest, (void*)(uintptr_t)1);
1310 #endif
1311 if (check_signature_token(digest, tok, router->identity_pkey, 0,
1312 "router descriptor") < 0)
1313 goto err;
1315 if (!router->or_port) {
1316 log_warn(LD_DIR,"or_port unreadable or 0. Failing.");
1317 goto err;
1320 if (!router->platform) {
1321 router->platform = tor_strdup("<unknown>");
1324 goto done;
1326 err:
1327 routerinfo_free(router);
1328 router = NULL;
1329 done:
1330 if (tokens) {
1331 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1332 smartlist_free(tokens);
1334 if (exit_policy_tokens) {
1335 smartlist_free(exit_policy_tokens);
1337 return router;
1340 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
1341 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
1342 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
1343 * cache_info fields of the result. If <b>routermap</b> is provided, use it
1344 * as a map from router identity to routerinfo_t when looking up signing keys.
1346 extrainfo_t *
1347 extrainfo_parse_entry_from_string(const char *s, const char *end,
1348 int cache_copy, struct digest_ri_map_t *routermap)
1350 extrainfo_t *extrainfo = NULL;
1351 char digest[128];
1352 smartlist_t *tokens = NULL;
1353 directory_token_t *tok;
1354 crypto_pk_env_t *key = NULL;
1355 routerinfo_t *router = NULL;
1357 if (!end) {
1358 end = s + strlen(s);
1361 /* point 'end' to a point immediately after the final newline. */
1362 while (end > s+2 && *(end-1) == '\n' && *(end-2) == '\n')
1363 --end;
1365 if (router_get_extrainfo_hash(s, digest) < 0) {
1366 log_warn(LD_DIR, "Couldn't compute router hash.");
1367 return NULL;
1369 tokens = smartlist_create();
1370 if (tokenize_string(s,end,tokens,extrainfo_token_table,0)) {
1371 log_warn(LD_DIR, "Error tokenizing extra-info document.");
1372 goto err;
1375 if (smartlist_len(tokens) < 2) {
1376 log_warn(LD_DIR, "Impossibly short extra-info document.");
1377 goto err;
1380 tok = smartlist_get(tokens,0);
1381 if (tok->tp != K_EXTRA_INFO) {
1382 log_warn(LD_DIR,"Entry does not start with \"extra-info\"");
1383 goto err;
1386 extrainfo = tor_malloc_zero(sizeof(extrainfo_t));
1387 extrainfo->cache_info.is_extrainfo = 1;
1388 if (cache_copy)
1389 extrainfo->cache_info.signed_descriptor_body = tor_strndup(s, end-s);
1390 extrainfo->cache_info.signed_descriptor_len = end-s;
1391 memcpy(extrainfo->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1393 tor_assert(tok->n_args >= 2);
1394 if (!is_legal_nickname(tok->args[0])) {
1395 log_warn(LD_DIR,"Bad nickname %s on \"extra-info\"",escaped(tok->args[0]));
1396 goto err;
1398 strlcpy(extrainfo->nickname, tok->args[0], sizeof(extrainfo->nickname));
1399 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
1400 base16_decode(extrainfo->cache_info.identity_digest, DIGEST_LEN,
1401 tok->args[1], HEX_DIGEST_LEN)) {
1402 log_warn(LD_DIR,"Invalid fingerprint %s on \"extra-info\"",
1403 escaped(tok->args[1]));
1404 goto err;
1407 tok = find_first_by_keyword(tokens, K_PUBLISHED);
1408 tor_assert(tok);
1409 if (parse_iso_time(tok->args[0], &extrainfo->cache_info.published_on)) {
1410 log_warn(LD_DIR,"Invalid published time %s on \"extra-info\"",
1411 escaped(tok->args[0]));
1412 goto err;
1415 if (routermap &&
1416 (router = digestmap_get((digestmap_t*)routermap,
1417 extrainfo->cache_info.identity_digest))) {
1418 key = router->identity_pkey;
1421 tok = find_first_by_keyword(tokens, K_ROUTER_SIGNATURE);
1422 tor_assert(tok);
1423 if (strcmp(tok->object_type, "SIGNATURE") ||
1424 tok->object_size < 128 || tok->object_size > 512) {
1425 log_warn(LD_DIR, "Bad object type or length on extra-info signature");
1426 goto err;
1429 if (key) {
1430 note_crypto_pk_op(VERIFY_RTR);
1431 if (check_signature_token(digest, tok, key, 0, "extra-info") < 0)
1432 goto err;
1434 if (router)
1435 extrainfo->cache_info.send_unencrypted =
1436 router->cache_info.send_unencrypted;
1437 } else {
1438 extrainfo->pending_sig = tor_memdup(tok->object_body,
1439 tok->object_size);
1440 extrainfo->pending_sig_len = tok->object_size;
1443 goto done;
1444 err:
1445 if (extrainfo)
1446 extrainfo_free(extrainfo);
1447 extrainfo = NULL;
1448 done:
1449 if (tokens) {
1450 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1451 smartlist_free(tokens);
1453 return extrainfo;
1456 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
1457 * the first character after the certificate. */
1458 authority_cert_t *
1459 authority_cert_parse_from_string(const char *s, const char **end_of_string)
1461 authority_cert_t *cert = NULL, *old_cert;
1462 smartlist_t *tokens = NULL;
1463 char digest[DIGEST_LEN];
1464 directory_token_t *tok;
1465 char fp_declared[DIGEST_LEN];
1466 char *eos;
1467 size_t len;
1468 int found;
1470 s = eat_whitespace(s);
1471 eos = strstr(s, "\n-----END SIGNATURE-----\n");
1472 if (! eos) {
1473 log_warn(LD_DIR, "No end-of-signature found on key certificate");
1474 return NULL;
1476 eos = strchr(eos+2, '\n');
1477 tor_assert(eos);
1478 ++eos;
1479 len = eos - s;
1481 tokens = smartlist_create();
1482 if (tokenize_string(s, eos, tokens, dir_key_certificate_table, 0) < 0) {
1483 log_warn(LD_DIR, "Error tokenizing key certificate");
1484 goto err;
1486 if (router_get_hash_impl(s, digest, "dir-key-certificate-version",
1487 "\ndir-key-certification", '\n') < 0)
1488 goto err;
1489 tok = smartlist_get(tokens, 0);
1490 if (tok->tp != K_DIR_KEY_CERTIFICATE_VERSION || strcmp(tok->args[0], "3")) {
1491 log_warn(LD_DIR,
1492 "Key certificate does not begin with a recognized version (3).");
1493 goto err;
1496 cert = tor_malloc_zero(sizeof(authority_cert_t));
1497 memcpy(cert->cache_info.signed_descriptor_digest, digest, DIGEST_LEN);
1499 tok = find_first_by_keyword(tokens, K_DIR_SIGNING_KEY);
1500 tor_assert(tok && tok->key);
1501 cert->signing_key = tok->key;
1502 tok->key = NULL;
1503 if (crypto_pk_get_digest(cert->signing_key, cert->signing_key_digest))
1504 goto err;
1506 tok = find_first_by_keyword(tokens, K_DIR_IDENTITY_KEY);
1507 tor_assert(tok && tok->key);
1508 cert->identity_key = tok->key;
1509 tok->key = NULL;
1511 tok = find_first_by_keyword(tokens, K_FINGERPRINT);
1512 tor_assert(tok && tok->n_args);
1513 if (base16_decode(fp_declared, DIGEST_LEN, tok->args[0],
1514 strlen(tok->args[0]))) {
1515 log_warn(LD_DIR, "Couldn't decode key certificate fingerprint %s",
1516 escaped(tok->args[0]));
1517 goto err;
1520 if (crypto_pk_get_digest(cert->identity_key,
1521 cert->cache_info.identity_digest))
1522 goto err;
1524 if (memcmp(cert->cache_info.identity_digest, fp_declared, DIGEST_LEN)) {
1525 log_warn(LD_DIR, "Digest of certificate key didn't match declared "
1526 "fingerprint");
1527 goto err;
1530 tok = find_first_by_keyword(tokens, K_DIR_ADDRESS);
1531 if (tok) {
1532 tor_assert(tok->n_args);
1533 if (parse_addr_port(LOG_WARN, tok->args[0], NULL, &cert->addr,
1534 &cert->dir_port)<0) {
1535 log_warn(LD_DIR, "Couldn't parse dir-address in certificate");
1536 goto err;
1540 tok = find_first_by_keyword(tokens, K_DIR_KEY_PUBLISHED);
1541 tor_assert(tok);
1542 if (parse_iso_time(tok->args[0], &cert->cache_info.published_on) < 0) {
1543 goto err;
1545 tok = find_first_by_keyword(tokens, K_DIR_KEY_EXPIRES);
1546 tor_assert(tok);
1547 if (parse_iso_time(tok->args[0], &cert->expires) < 0) {
1548 goto err;
1551 tok = smartlist_get(tokens, smartlist_len(tokens)-1);
1552 if (tok->tp != K_DIR_KEY_CERTIFICATION) {
1553 log_warn(LD_DIR, "Certificate didn't end with dir-key-certification.");
1554 goto err;
1557 /* If we already have this cert, don't bother checking the signature. */
1558 old_cert = authority_cert_get_by_digests(
1559 cert->cache_info.identity_digest,
1560 cert->signing_key_digest);
1561 found = 0;
1562 if (old_cert) {
1563 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
1564 * buy us much. */
1565 if (old_cert->cache_info.signed_descriptor_len == len &&
1566 old_cert->cache_info.signed_descriptor_body &&
1567 !memcmp(s, old_cert->cache_info.signed_descriptor_body, len)) {
1568 log_debug(LD_DIR, "We already checked the signature on this "
1569 "certificate; no need to do so again.");
1570 found = 1;
1573 if (!found) {
1574 if (check_signature_token(digest, tok, cert->identity_key, 0,
1575 "key certificate")) {
1576 goto err;
1580 cert->cache_info.signed_descriptor_len = len;
1581 cert->cache_info.signed_descriptor_body = tor_malloc(len+1);
1582 memcpy(cert->cache_info.signed_descriptor_body, s, len);
1583 cert->cache_info.signed_descriptor_body[len] = 0;
1584 cert->cache_info.saved_location = SAVED_NOWHERE;
1586 if (end_of_string) {
1587 *end_of_string = eat_whitespace(eos);
1589 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1590 smartlist_free(tokens);
1591 return cert;
1592 err:
1593 authority_cert_free(cert);
1594 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1595 smartlist_free(tokens);
1596 return NULL;
1599 /** Helper: given a string <b>s</b>, return the start of the next router-status
1600 * object (starting with "r " at the start of a line). If none is found,
1601 * return the start of the next directory signature. If none is found, return
1602 * the end of the string. */
1603 static INLINE const char *
1604 find_start_of_next_routerstatus(const char *s)
1606 const char *eos = strstr(s, "\nr ");
1607 if (eos) {
1608 const char *eos2 = tor_memstr(s, eos-s, "\ndirectory-signature");
1609 if (eos2 && eos2 < eos)
1610 return eos2;
1611 else
1612 return eos+1;
1613 } else {
1614 if ((eos = strstr(s, "\ndirectory-signature")))
1615 return eos+1;
1616 return s + strlen(s);
1620 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
1621 * empty smartlist at <b>tokens</b>, parse and return the first router status
1622 * object in the string, and advance *<b>s</b> to just after the end of the
1623 * router status. Return NULL and advance *<b>s</b> on error.
1625 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
1626 * routerstatus but use <b>vote_rs</b> instead.
1628 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
1629 * consensus, and we should parse it according to the method used to
1630 * make that consensus.
1632 static routerstatus_t *
1633 routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens,
1634 networkstatus_t *vote,
1635 vote_routerstatus_t *vote_rs,
1636 int consensus_method)
1638 const char *eos;
1639 routerstatus_t *rs = NULL;
1640 directory_token_t *tok;
1641 char timebuf[ISO_TIME_LEN+1];
1642 struct in_addr in;
1643 tor_assert(tokens);
1644 tor_assert(bool_eq(vote, vote_rs));
1646 eos = find_start_of_next_routerstatus(*s);
1648 if (tokenize_string(*s, eos, tokens, rtrstatus_token_table,0)) {
1649 log_warn(LD_DIR, "Error tokenizing router status");
1650 goto err;
1652 if (smartlist_len(tokens) < 1) {
1653 log_warn(LD_DIR, "Impossibly short router status");
1654 goto err;
1656 tok = find_first_by_keyword(tokens, K_R);
1657 tor_assert(tok);
1658 tor_assert(tok->n_args >= 8);
1659 if (vote_rs) {
1660 rs = &vote_rs->status;
1661 } else {
1662 rs = tor_malloc_zero(sizeof(routerstatus_t));
1665 if (!is_legal_nickname(tok->args[0])) {
1666 log_warn(LD_DIR,
1667 "Invalid nickname %s in router status; skipping.",
1668 escaped(tok->args[0]));
1669 goto err;
1671 strlcpy(rs->nickname, tok->args[0], sizeof(rs->nickname));
1673 if (digest_from_base64(rs->identity_digest, tok->args[1])) {
1674 log_warn(LD_DIR, "Error decoding identity digest %s",
1675 escaped(tok->args[1]));
1676 goto err;
1679 if (digest_from_base64(rs->descriptor_digest, tok->args[2])) {
1680 log_warn(LD_DIR, "Error decoding descriptor digest %s",
1681 escaped(tok->args[2]));
1682 goto err;
1685 if (tor_snprintf(timebuf, sizeof(timebuf), "%s %s",
1686 tok->args[3], tok->args[4]) < 0 ||
1687 parse_iso_time(timebuf, &rs->published_on)<0) {
1688 log_warn(LD_DIR, "Error parsing time '%s %s'",
1689 tok->args[3], tok->args[4]);
1690 goto err;
1693 if (tor_inet_aton(tok->args[5], &in) == 0) {
1694 log_warn(LD_DIR, "Error parsing router address in network-status %s",
1695 escaped(tok->args[5]));
1696 goto err;
1698 rs->addr = ntohl(in.s_addr);
1700 rs->or_port =(uint16_t) tor_parse_long(tok->args[6],10,0,65535,NULL,NULL);
1701 rs->dir_port = (uint16_t) tor_parse_long(tok->args[7],10,0,65535,NULL,NULL);
1703 tok = find_first_by_keyword(tokens, K_S);
1704 if (tok && vote) {
1705 int i;
1706 vote_rs->flags = 0;
1707 for (i=0; i < tok->n_args; ++i) {
1708 int p = smartlist_string_pos(vote->known_flags, tok->args[i]);
1709 if (p >= 0) {
1710 vote_rs->flags |= (1<<p);
1711 } else {
1712 log_warn(LD_DIR, "Flags line had a flag %s not listed in known_flags.",
1713 escaped(tok->args[i]));
1714 goto err;
1717 } else if (tok) {
1718 int i;
1719 for (i=0; i < tok->n_args; ++i) {
1720 if (!strcmp(tok->args[i], "Exit"))
1721 rs->is_exit = 1;
1722 else if (!strcmp(tok->args[i], "Stable"))
1723 rs->is_stable = 1;
1724 else if (!strcmp(tok->args[i], "Fast"))
1725 rs->is_fast = 1;
1726 else if (!strcmp(tok->args[i], "Running"))
1727 rs->is_running = 1;
1728 else if (!strcmp(tok->args[i], "Named"))
1729 rs->is_named = 1;
1730 else if (!strcmp(tok->args[i], "Valid"))
1731 rs->is_valid = 1;
1732 else if (!strcmp(tok->args[i], "V2Dir"))
1733 rs->is_v2_dir = 1;
1734 else if (!strcmp(tok->args[i], "Guard"))
1735 rs->is_possible_guard = 1;
1736 else if (!strcmp(tok->args[i], "BadExit"))
1737 rs->is_bad_exit = 1;
1738 else if (!strcmp(tok->args[i], "BadDirectory"))
1739 rs->is_bad_directory = 1;
1740 else if (!strcmp(tok->args[i], "Authority"))
1741 rs->is_authority = 1;
1742 else if (!strcmp(tok->args[i], "Unnamed") &&
1743 consensus_method >= 2) {
1744 /* Unnamed is computed right by consensus method 2 and later. */
1745 rs->is_unnamed = 1;
1746 } else if (!strcmp(tok->args[i], "HSDir")) {
1747 rs->is_hs_dir = 1;
1751 if ((tok = find_first_by_keyword(tokens, K_V))) {
1752 tor_assert(tok->n_args == 1);
1753 rs->version_known = 1;
1754 if (strcmpstart(tok->args[0], "Tor ")) {
1755 rs->version_supports_begindir = 1;
1756 rs->version_supports_extrainfo_upload = 1;
1757 } else {
1758 rs->version_supports_begindir =
1759 tor_version_as_new_as(tok->args[0], "0.2.0.1-alpha");
1760 rs->version_supports_extrainfo_upload =
1761 tor_version_as_new_as(tok->args[0], "0.2.0.0-alpha-dev (r10070)");
1762 rs->version_supports_v3_dir =
1763 tor_version_as_new_as(tok->args[0], "0.2.0.8-alpha");
1765 if (vote_rs) {
1766 vote_rs->version = tok->args[0];
1767 tok->args[0] = NULL; /* suppress free() */
1771 if (!strcasecmp(rs->nickname, UNNAMED_ROUTER_NICKNAME))
1772 rs->is_named = 0;
1774 goto done;
1775 err:
1776 if (rs && !vote_rs)
1777 routerstatus_free(rs);
1778 rs = NULL;
1779 done:
1780 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1781 smartlist_clear(tokens);
1782 *s = eos;
1784 return rs;
1787 /** Helper to sort a smartlist of pointers to routerstatus_t */
1788 static int
1789 _compare_routerstatus_entries(const void **_a, const void **_b)
1791 const routerstatus_t *a = *_a, *b = *_b;
1792 return memcmp(a->identity_digest, b->identity_digest, DIGEST_LEN);
1795 /** Helper: used in call to _smartlist_uniq to clear out duplicate entries. */
1796 static void
1797 _free_duplicate_routerstatus_entry(void *e)
1799 log_warn(LD_DIR,
1800 "Network-status has two entries for the same router. "
1801 "Dropping one.");
1802 routerstatus_free(e);
1805 /** Given a v2 network-status object in <b>s</b>, try to
1806 * parse it and return the result. Return NULL on failure. Check the
1807 * signature of the network status, but do not (yet) check the signing key for
1808 * authority.
1810 networkstatus_v2_t *
1811 networkstatus_v2_parse_from_string(const char *s)
1813 const char *eos;
1814 smartlist_t *tokens = smartlist_create();
1815 smartlist_t *footer_tokens = smartlist_create();
1816 networkstatus_v2_t *ns = NULL;
1817 char ns_digest[DIGEST_LEN];
1818 char tmp_digest[DIGEST_LEN];
1819 struct in_addr in;
1820 directory_token_t *tok;
1821 int i;
1823 if (router_get_networkstatus_v2_hash(s, ns_digest)) {
1824 log_warn(LD_DIR, "Unable to compute digest of network-status");
1825 goto err;
1828 eos = find_start_of_next_routerstatus(s);
1829 if (tokenize_string(s, eos, tokens, netstatus_token_table,0)) {
1830 log_warn(LD_DIR, "Error tokenizing network-status header.");
1831 goto err;
1833 ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
1834 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
1836 tok = find_first_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
1837 tor_assert(tok && tok->n_args >= 1);
1838 if (strcmp(tok->args[0], "2")) {
1839 log_warn(LD_BUG, "Got a non-v2 networkstatus. Version was "
1840 "%s", escaped(tok->args[0]));
1841 goto err;
1844 tok = find_first_by_keyword(tokens, K_DIR_SOURCE);
1845 tor_assert(tok);
1846 tor_assert(tok->n_args >= 3);
1847 ns->source_address = tok->args[0]; tok->args[0] = NULL;
1848 if (tor_inet_aton(tok->args[1], &in) == 0) {
1849 log_warn(LD_DIR, "Error parsing network-status source address %s",
1850 escaped(tok->args[1]));
1851 goto err;
1853 ns->source_addr = ntohl(in.s_addr);
1854 ns->source_dirport =
1855 (uint16_t) tor_parse_long(tok->args[2],10,0,65535,NULL,NULL);
1856 if (ns->source_dirport == 0) {
1857 log_warn(LD_DIR, "Directory source without dirport; skipping.");
1858 goto err;
1861 tok = find_first_by_keyword(tokens, K_FINGERPRINT);
1862 tor_assert(tok);
1863 tor_assert(tok->n_args);
1864 if (base16_decode(ns->identity_digest, DIGEST_LEN, tok->args[0],
1865 strlen(tok->args[0]))) {
1866 log_warn(LD_DIR, "Couldn't decode networkstatus fingerprint %s",
1867 escaped(tok->args[0]));
1868 goto err;
1871 if ((tok = find_first_by_keyword(tokens, K_CONTACT))) {
1872 tor_assert(tok->n_args);
1873 ns->contact = tok->args[0];
1874 tok->args[0] = NULL;
1877 tok = find_first_by_keyword(tokens, K_DIR_SIGNING_KEY);
1878 tor_assert(tok && tok->key);
1879 ns->signing_key = tok->key;
1880 tok->key = NULL;
1882 if (crypto_pk_get_digest(ns->signing_key, tmp_digest)<0) {
1883 log_warn(LD_DIR, "Couldn't compute signing key digest");
1884 goto err;
1886 if (memcmp(tmp_digest, ns->identity_digest, DIGEST_LEN)) {
1887 log_warn(LD_DIR,
1888 "network-status fingerprint did not match dir-signing-key");
1889 goto err;
1892 if ((tok = find_first_by_keyword(tokens, K_DIR_OPTIONS))) {
1893 for (i=0; i < tok->n_args; ++i) {
1894 if (!strcmp(tok->args[i], "Names"))
1895 ns->binds_names = 1;
1896 if (!strcmp(tok->args[i], "Versions"))
1897 ns->recommends_versions = 1;
1898 if (!strcmp(tok->args[i], "BadExits"))
1899 ns->lists_bad_exits = 1;
1900 if (!strcmp(tok->args[i], "BadDirectories"))
1901 ns->lists_bad_directories = 1;
1905 if (ns->recommends_versions) {
1906 if (!(tok = find_first_by_keyword(tokens, K_CLIENT_VERSIONS))) {
1907 log_warn(LD_DIR, "Missing client-versions on versioning directory");
1908 goto err;
1910 ns->client_versions = tok->args[0];
1911 tok->args[0] = NULL;
1913 if (!(tok = find_first_by_keyword(tokens, K_SERVER_VERSIONS)) ||
1914 tok->n_args<1) {
1915 log_warn(LD_DIR, "Missing server-versions on versioning directory");
1916 goto err;
1918 ns->server_versions = tok->args[0];
1919 tok->args[0] = NULL;
1922 tok = find_first_by_keyword(tokens, K_PUBLISHED);
1923 tor_assert(tok);
1924 tor_assert(tok->n_args == 1);
1925 if (parse_iso_time(tok->args[0], &ns->published_on) < 0) {
1926 goto err;
1929 ns->entries = smartlist_create();
1930 s = eos;
1931 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1932 smartlist_clear(tokens);
1933 while (!strcmpstart(s, "r ")) {
1934 routerstatus_t *rs;
1935 if ((rs = routerstatus_parse_entry_from_string(&s, tokens, NULL, NULL, 0)))
1936 smartlist_add(ns->entries, rs);
1938 smartlist_sort(ns->entries, _compare_routerstatus_entries);
1939 smartlist_uniq(ns->entries, _compare_routerstatus_entries,
1940 _free_duplicate_routerstatus_entry);
1942 if (tokenize_string(s, NULL, footer_tokens, dir_footer_token_table,0)) {
1943 log_warn(LD_DIR, "Error tokenizing network-status footer.");
1944 goto err;
1946 if (smartlist_len(footer_tokens) < 1) {
1947 log_warn(LD_DIR, "Too few items in network-status footer.");
1948 goto err;
1950 tok = smartlist_get(footer_tokens, smartlist_len(footer_tokens)-1);
1951 if (tok->tp != K_DIRECTORY_SIGNATURE) {
1952 log_warn(LD_DIR,
1953 "Expected network-status footer to end with a signature.");
1954 goto err;
1957 note_crypto_pk_op(VERIFY_DIR);
1958 if (check_signature_token(ns_digest, tok, ns->signing_key, 0,
1959 "network-status") < 0)
1960 goto err;
1962 goto done;
1963 err:
1964 if (ns)
1965 networkstatus_v2_free(ns);
1966 ns = NULL;
1967 done:
1968 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
1969 smartlist_free(tokens);
1970 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
1971 smartlist_free(footer_tokens);
1973 return ns;
1976 /** Parse a v3 networkstatus vote (if <b>is_vote</b> is true) or a v3
1977 * networkstatus consensus (if <b>is_vote</b> is false) from <b>s</b>, and
1978 * return the result. Return NULL on failure. */
1979 networkstatus_t *
1980 networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
1981 int is_vote)
1983 smartlist_t *tokens = smartlist_create();
1984 smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
1985 networkstatus_voter_info_t *voter = NULL;
1986 networkstatus_t *ns = NULL;
1987 char ns_digest[DIGEST_LEN];
1988 const char *cert, *end_of_header, *end_of_footer;
1989 directory_token_t *tok;
1990 int ok;
1991 struct in_addr in;
1992 int i, inorder, n_signatures = 0;
1994 if (router_get_networkstatus_v3_hash(s, ns_digest)) {
1995 log_warn(LD_DIR, "Unable to compute digest of network-status");
1996 goto err;
1999 end_of_header = find_start_of_next_routerstatus(s);
2000 if (tokenize_string(s, end_of_header, tokens,
2001 is_vote ? networkstatus_token_table :
2002 networkstatus_consensus_token_table, 0)) {
2003 log_warn(LD_DIR, "Error tokenizing network-status vote header.");
2004 goto err;
2007 ns = tor_malloc_zero(sizeof(networkstatus_t));
2008 memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
2010 if (is_vote) {
2011 const char *end_of_cert = NULL;
2012 if (!(cert = strstr(s, "\ndir-key-certificate-version")))
2013 goto err;
2014 ++cert;
2015 ns->cert = authority_cert_parse_from_string(cert, &end_of_cert);
2016 if (!ns->cert || !end_of_cert || end_of_cert > end_of_header)
2017 goto err;
2020 tok = find_first_by_keyword(tokens, K_VOTE_STATUS);
2021 tor_assert(tok);
2022 tor_assert(tok->n_args);
2023 if (!strcmp(tok->args[0], "vote")) {
2024 ns->is_vote = 1;
2025 } else if (!strcmp(tok->args[0], "consensus")) {
2026 ns->is_vote = 0;
2027 } else {
2028 log_warn(LD_DIR, "Unrecognized vote status %s in network-status",
2029 escaped(tok->args[0]));
2030 goto err;
2032 if (!bool_eq(ns->is_vote, is_vote)) {
2033 log_warn(LD_DIR, "Got the wrong kind of v3 networkstatus.");
2034 goto err;
2037 if (ns->is_vote) {
2038 tok = find_first_by_keyword(tokens, K_PUBLISHED);
2039 if (parse_iso_time(tok->args[0], &ns->published))
2040 goto err;
2042 ns->supported_methods = smartlist_create();
2043 tok = find_first_by_keyword(tokens, K_CONSENSUS_METHODS);
2044 if (tok) {
2045 for (i=0; i < tok->n_args; ++i)
2046 smartlist_add(ns->supported_methods, tok->args[i]);
2047 tok->n_args = 0; /* Prevent double free. */
2048 } else {
2049 smartlist_add(ns->supported_methods, tor_strdup("1"));
2051 } else {
2052 tok = find_first_by_keyword(tokens, K_CONSENSUS_METHOD);
2053 if (tok) {
2054 ns->consensus_method = (int)tor_parse_long(tok->args[0], 10, 1, INT_MAX,
2055 &ok, NULL);
2056 if (!ok)
2057 goto err;
2058 } else {
2059 ns->consensus_method = 1;
2063 tok = find_first_by_keyword(tokens, K_VALID_AFTER);
2064 if (parse_iso_time(tok->args[0], &ns->valid_after))
2065 goto err;
2067 tok = find_first_by_keyword(tokens, K_FRESH_UNTIL);
2068 if (parse_iso_time(tok->args[0], &ns->fresh_until))
2069 goto err;
2071 tok = find_first_by_keyword(tokens, K_VALID_UNTIL);
2072 if (parse_iso_time(tok->args[0], &ns->valid_until))
2073 goto err;
2075 tok = find_first_by_keyword(tokens, K_VOTING_DELAY);
2076 tor_assert(tok->n_args >= 2);
2077 ns->vote_seconds =
2078 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &ok, NULL);
2079 if (!ok)
2080 goto err;
2081 ns->dist_seconds =
2082 (int) tor_parse_long(tok->args[1], 10, 0, INT_MAX, &ok, NULL);
2083 if (!ok)
2084 goto err;
2085 if (ns->valid_after + MIN_VOTE_INTERVAL > ns->fresh_until) {
2086 log_warn(LD_DIR, "Vote/consensus freshness interval is too short");
2087 goto err;
2089 if (ns->valid_after + MIN_VOTE_INTERVAL*2 > ns->valid_until) {
2090 log_warn(LD_DIR, "Vote/consensus liveness interval is too short");
2091 goto err;
2093 if (ns->vote_seconds < MIN_VOTE_SECONDS) {
2094 log_warn(LD_DIR, "Vote seconds is too short");
2095 goto err;
2097 if (ns->dist_seconds < MIN_DIST_SECONDS) {
2098 log_warn(LD_DIR, "Dist seconds is too short");
2099 goto err;
2102 if ((tok = find_first_by_keyword(tokens, K_CLIENT_VERSIONS))) {
2103 ns->client_versions = tok->args[0];
2104 tok->args[0] = NULL;
2106 if ((tok = find_first_by_keyword(tokens, K_SERVER_VERSIONS))) {
2107 ns->server_versions = tok->args[0];
2108 tok->args[0] = NULL;
2111 tok = find_first_by_keyword(tokens, K_KNOWN_FLAGS);
2112 ns->known_flags = smartlist_create();
2113 inorder = 1;
2114 for (i = 0; i < tok->n_args; ++i) {
2115 smartlist_add(ns->known_flags, tok->args[i]);
2116 if (i>0 && strcmp(tok->args[i-1], tok->args[i])>= 0) {
2117 log_warn(LD_DIR, "%s >= %s", tok->args[i-1], tok->args[i]);
2118 inorder = 0;
2121 tok->n_args = 0; /* suppress free of args members, but not of args itself. */
2122 if (!inorder) {
2123 log_warn(LD_DIR, "known-flags not in order");
2124 goto err;
2127 ns->voters = smartlist_create();
2129 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2131 tok = _tok;
2132 if (tok->tp == K_DIR_SOURCE) {
2133 tor_assert(tok->n_args >= 6);
2135 if (voter)
2136 smartlist_add(ns->voters, voter);
2137 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2138 if (is_vote)
2139 memcpy(voter->vote_digest, ns_digest, DIGEST_LEN);
2141 voter->nickname = tor_strdup(tok->args[0]);
2142 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2143 base16_decode(voter->identity_digest, sizeof(voter->identity_digest),
2144 tok->args[1], HEX_DIGEST_LEN) < 0) {
2145 log_warn(LD_DIR, "Error decoding identity digest %s in "
2146 "network-status vote.", escaped(tok->args[1]));
2147 goto err;
2149 if (is_vote && memcmp(ns->cert->cache_info.identity_digest,
2150 voter->identity_digest, DIGEST_LEN)) {
2151 log_warn(LD_DIR,"Mismatch between identities in certificate and vote");
2152 goto err;
2154 voter->address = tor_strdup(tok->args[2]);
2155 if (!tor_inet_aton(tok->args[3], &in)) {
2156 log_warn(LD_DIR, "Error decoding IP address %s in network-status.",
2157 escaped(tok->args[3]));
2158 goto err;
2160 voter->addr = ntohl(in.s_addr);
2161 voter->dir_port = (uint64_t)
2162 (int) tor_parse_long(tok->args[4], 10, 0, 65535, &ok, NULL);
2163 if (!ok)
2164 goto err;
2165 voter->or_port = (uint64_t)
2166 (int) tor_parse_long(tok->args[5], 10, 0, 65535, &ok, NULL);
2167 if (!ok)
2168 goto err;
2169 } else if (tok->tp == K_CONTACT) {
2170 if (!voter || voter->contact) {
2171 log_warn(LD_DIR, "contact element is out of place.");
2172 goto err;
2174 voter->contact = tor_strdup(tok->args[0]);
2175 } else if (tok->tp == K_VOTE_DIGEST) {
2176 tor_assert(!is_vote);
2177 tor_assert(tok->n_args >= 1);
2178 if (!voter || ! tor_digest_is_zero(voter->vote_digest)) {
2179 log_warn(LD_DIR, "vote-digest element is out of place.");
2180 goto err;
2182 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2183 base16_decode(voter->vote_digest, sizeof(voter->vote_digest),
2184 tok->args[0], HEX_DIGEST_LEN) < 0) {
2185 log_warn(LD_DIR, "Error decoding vote digest %s in "
2186 "network-status consensus.", escaped(tok->args[1]));
2187 goto err;
2191 if (voter) {
2192 smartlist_add(ns->voters, voter);
2193 voter = NULL;
2195 if (smartlist_len(ns->voters) == 0) {
2196 log_warn(LD_DIR, "Missing dir-source elements in a vote networkstatus.");
2197 goto err;
2198 } else if (is_vote && smartlist_len(ns->voters) != 1) {
2199 log_warn(LD_DIR, "Too many dir-source elements in a vote networkstatus.");
2200 goto err;
2203 /* Parse routerstatus lines. */
2204 rs_tokens = smartlist_create();
2205 s = end_of_header;
2206 ns->routerstatus_list = smartlist_create();
2208 while (!strcmpstart(s, "r ")) {
2209 if (is_vote) {
2210 vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t));
2211 if (routerstatus_parse_entry_from_string(&s, tokens, ns, rs, 0))
2212 smartlist_add(ns->routerstatus_list, rs);
2213 else {
2214 tor_free(rs->version);
2215 tor_free(rs);
2217 } else {
2218 routerstatus_t *rs;
2219 if ((rs = routerstatus_parse_entry_from_string(&s, tokens, NULL, NULL,
2220 ns->consensus_method)))
2221 smartlist_add(ns->routerstatus_list, rs);
2224 for (i = 1; i < smartlist_len(ns->routerstatus_list); ++i) {
2225 routerstatus_t *rs1, *rs2;
2226 if (is_vote) {
2227 vote_routerstatus_t *a = smartlist_get(ns->routerstatus_list, i-1);
2228 vote_routerstatus_t *b = smartlist_get(ns->routerstatus_list, i);
2229 rs1 = &a->status; rs2 = &b->status;
2230 } else {
2231 rs1 = smartlist_get(ns->routerstatus_list, i-1);
2232 rs2 = smartlist_get(ns->routerstatus_list, i);
2234 if (memcmp(rs1->identity_digest, rs2->identity_digest, DIGEST_LEN) >= 0) {
2235 log_warn(LD_DIR, "Vote networkstatus entries not sorted by identity "
2236 "digest");
2237 goto err;
2241 /* Parse footer; check signature. */
2242 footer_tokens = smartlist_create();
2243 if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
2244 ++end_of_footer;
2245 else
2246 end_of_footer = s + strlen(s);
2247 if (tokenize_string(s, end_of_footer, footer_tokens,
2248 networkstatus_vote_footer_token_table, 0)) {
2249 log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
2250 goto err;
2253 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, _tok,
2255 char declared_identity[DIGEST_LEN];
2256 networkstatus_voter_info_t *v;
2257 tok = _tok;
2258 if (tok->tp != K_DIRECTORY_SIGNATURE)
2259 continue;
2260 tor_assert(tok->n_args >= 2);
2262 if (!tok->object_type ||
2263 strcmp(tok->object_type, "SIGNATURE") ||
2264 tok->object_size < 128 || tok->object_size > 512) {
2265 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2266 goto err;
2269 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2270 base16_decode(declared_identity, sizeof(declared_identity),
2271 tok->args[0], HEX_DIGEST_LEN) < 0) {
2272 log_warn(LD_DIR, "Error decoding declared identity %s in "
2273 "network-status vote.", escaped(tok->args[0]));
2274 goto err;
2276 if (!(v = networkstatus_get_voter_by_id(ns, declared_identity))) {
2277 log_warn(LD_DIR, "ID on signature on network-status vote does not match "
2278 "any declared directory source.");
2279 goto err;
2281 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2282 base16_decode(v->signing_key_digest, sizeof(v->signing_key_digest),
2283 tok->args[1], HEX_DIGEST_LEN) < 0) {
2284 log_warn(LD_DIR, "Error decoding declared digest %s in "
2285 "network-status vote.", escaped(tok->args[1]));
2286 goto err;
2289 if (is_vote) {
2290 if (memcmp(declared_identity, ns->cert->cache_info.identity_digest,
2291 DIGEST_LEN)) {
2292 log_warn(LD_DIR, "Digest mismatch between declared and actual on "
2293 "network-status vote.");
2294 goto err;
2298 if (is_vote) {
2299 if (check_signature_token(ns_digest, tok, ns->cert->signing_key, 0,
2300 "network-status vote"))
2301 goto err;
2302 v->good_signature = 1;
2303 } else {
2304 v->signature = tor_memdup(tok->object_body, tok->object_size);
2305 v->signature_len = tok->object_size;
2307 ++n_signatures;
2310 if (! n_signatures) {
2311 log_warn(LD_DIR, "No signatures on networkstatus vote.");
2312 goto err;
2315 if (eos_out)
2316 *eos_out = end_of_footer;
2318 goto done;
2319 err:
2320 if (ns)
2321 networkstatus_vote_free(ns);
2322 ns = NULL;
2323 done:
2324 if (tokens) {
2325 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2326 smartlist_free(tokens);
2328 if (voter) {
2329 tor_free(voter->nickname);
2330 tor_free(voter->address);
2331 tor_free(voter->contact);
2332 tor_free(voter->signature);
2333 tor_free(voter);
2335 if (rs_tokens) {
2336 SMARTLIST_FOREACH(rs_tokens, directory_token_t *, t, token_free(t));
2337 smartlist_free(rs_tokens);
2339 if (footer_tokens) {
2340 SMARTLIST_FOREACH(footer_tokens, directory_token_t *, t, token_free(t));
2341 smartlist_free(footer_tokens);
2344 return ns;
2347 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
2348 * <b>eos</b> and return the result. Return -1 on failure. */
2349 ns_detached_signatures_t *
2350 networkstatus_parse_detached_signatures(const char *s, const char *eos)
2352 /* XXXX there is too much duplicate code here. */
2353 directory_token_t *tok;
2355 smartlist_t *tokens = smartlist_create();
2356 ns_detached_signatures_t *sigs =
2357 tor_malloc_zero(sizeof(ns_detached_signatures_t));
2359 if (!eos)
2360 eos = s + strlen(s);
2362 if (tokenize_string(s, eos, tokens,
2363 networkstatus_detached_signature_token_table, 0)) {
2364 log_warn(LD_DIR, "Error tokenizing detached networkstatus signatures");
2365 goto err;
2368 tok = find_first_by_keyword(tokens, K_CONSENSUS_DIGEST);
2369 if (strlen(tok->args[0]) != HEX_DIGEST_LEN) {
2370 log_warn(LD_DIR, "Wrong length on consensus-digest in detached "
2371 "networkstatus signatures");
2372 goto err;
2374 if (base16_decode(sigs->networkstatus_digest, DIGEST_LEN,
2375 tok->args[0], strlen(tok->args[0])) < 0) {
2376 log_warn(LD_DIR, "Bad encoding on on consensus-digest in detached "
2377 "networkstatus signatures");
2378 goto err;
2381 tok = find_first_by_keyword(tokens, K_VALID_AFTER);
2382 if (parse_iso_time(tok->args[0], &sigs->valid_after)) {
2383 log_warn(LD_DIR, "Bad valid-after in detached networkstatus signatures");
2384 goto err;
2387 tok = find_first_by_keyword(tokens, K_FRESH_UNTIL);
2388 if (parse_iso_time(tok->args[0], &sigs->fresh_until)) {
2389 log_warn(LD_DIR, "Bad fresh-until in detached networkstatus signatures");
2390 goto err;
2393 tok = find_first_by_keyword(tokens, K_VALID_UNTIL);
2394 if (parse_iso_time(tok->args[0], &sigs->valid_until)) {
2395 log_warn(LD_DIR, "Bad valid-until in detached networkstatus signatures");
2396 goto err;
2399 sigs->signatures = smartlist_create();
2400 SMARTLIST_FOREACH(tokens, directory_token_t *, _tok,
2402 char id_digest[DIGEST_LEN];
2403 char sk_digest[DIGEST_LEN];
2404 networkstatus_voter_info_t *voter;
2406 tok = _tok;
2407 if (tok->tp != K_DIRECTORY_SIGNATURE)
2408 continue;
2409 tor_assert(tok->n_args >= 2);
2411 if (!tok->object_type ||
2412 strcmp(tok->object_type, "SIGNATURE") ||
2413 tok->object_size < 128 || tok->object_size > 512) {
2414 log_warn(LD_DIR, "Bad object type or length on directory-signature");
2415 goto err;
2418 if (strlen(tok->args[0]) != HEX_DIGEST_LEN ||
2419 base16_decode(id_digest, sizeof(id_digest),
2420 tok->args[0], HEX_DIGEST_LEN) < 0) {
2421 log_warn(LD_DIR, "Error decoding declared identity %s in "
2422 "network-status vote.", escaped(tok->args[0]));
2423 goto err;
2425 if (strlen(tok->args[1]) != HEX_DIGEST_LEN ||
2426 base16_decode(sk_digest, sizeof(sk_digest),
2427 tok->args[1], HEX_DIGEST_LEN) < 0) {
2428 log_warn(LD_DIR, "Error decoding declared digest %s in "
2429 "network-status vote.", escaped(tok->args[1]));
2430 goto err;
2433 voter = tor_malloc_zero(sizeof(networkstatus_voter_info_t));
2434 memcpy(voter->identity_digest, id_digest, DIGEST_LEN);
2435 memcpy(voter->signing_key_digest, sk_digest, DIGEST_LEN);
2436 voter->signature = tor_memdup(tok->object_body, tok->object_size);
2437 voter->signature_len = tok->object_size;
2439 smartlist_add(sigs->signatures, voter);
2442 goto done;
2443 err:
2444 ns_detached_signatures_free(sigs);
2445 sigs = NULL;
2446 done:
2447 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
2448 smartlist_free(tokens);
2449 return sigs;
2452 /** Parse the addr policy in the string <b>s</b> and return it. If
2453 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
2454 * ADDR_POLICY_REJECT) for items that specify no action.
2456 addr_policy_t *
2457 router_parse_addr_policy_item_from_string(const char *s, int assume_action)
2459 directory_token_t *tok = NULL;
2460 const char *cp, *eos;
2461 /* Longest possible policy is "accept ffff:ffff:..255/ffff:...255:0-65535".
2462 * But note that there can be an arbitrary amount of space between the
2463 * accept and the address:mask/port element. */
2464 char line[TOR_ADDR_BUF_LEN*2 + 32];
2465 addr_policy_t *r;
2467 s = eat_whitespace(s);
2468 if ((*s == '*' || TOR_ISDIGIT(*s)) && assume_action >= 0) {
2469 if (tor_snprintf(line, sizeof(line), "%s %s",
2470 assume_action == ADDR_POLICY_ACCEPT?"accept":"reject", s)<0) {
2471 log_warn(LD_DIR, "Policy %s is too long.", escaped(s));
2472 return NULL;
2474 cp = line;
2475 tor_strlower(line);
2476 } else { /* assume an already well-formed address policy line */
2477 cp = s;
2480 eos = cp + strlen(cp);
2481 tok = get_next_token(&cp, eos, routerdesc_token_table);
2482 if (tok->tp == _ERR) {
2483 log_warn(LD_DIR, "Error reading address policy: %s", tok->error);
2484 goto err;
2486 if (tok->tp != K_ACCEPT && tok->tp != K_REJECT) {
2487 log_warn(LD_DIR, "Expected 'accept' or 'reject'.");
2488 goto err;
2491 /* Now that we've gotten an addr policy, add it to the router. */
2492 r = router_parse_addr_policy(tok);
2493 goto done;
2494 err:
2495 r = NULL;
2496 done:
2497 token_free(tok);
2498 return r;
2501 /** Add an exit policy stored in the token <b>tok</b> to the router info in
2502 * <b>router</b>. Return 0 on success, -1 on failure. */
2503 static int
2504 router_add_exit_policy(routerinfo_t *router, directory_token_t *tok)
2506 addr_policy_t *newe;
2507 newe = router_parse_addr_policy(tok);
2508 if (!newe)
2509 return -1;
2510 if (! router->exit_policy)
2511 router->exit_policy = smartlist_create();
2513 smartlist_add(router->exit_policy, newe);
2515 return 0;
2518 /** Given a K_ACCEPT or K_REJECT token and a router, create and return
2519 * a new exit_policy_t corresponding to the token. */
2520 static addr_policy_t *
2521 router_parse_addr_policy(directory_token_t *tok)
2523 addr_policy_t newe;
2524 char *arg;
2526 tor_assert(tok->tp == K_REJECT || tok->tp == K_ACCEPT);
2528 if (tok->n_args != 1)
2529 return NULL;
2530 arg = tok->args[0];
2532 if (!strcmpstart(arg,"private"))
2533 return router_parse_addr_policy_private(tok);
2535 memset(&newe, 0, sizeof(newe));
2537 newe.policy_type = (tok->tp == K_REJECT) ? ADDR_POLICY_REJECT
2538 : ADDR_POLICY_ACCEPT;
2540 if (parse_addr_and_port_range(arg, &newe.addr, &newe.maskbits,
2541 &newe.prt_min, &newe.prt_max))
2542 goto policy_read_failed;
2544 return addr_policy_get_canonical_entry(&newe);
2546 policy_read_failed:
2547 log_warn(LD_DIR,"Couldn't parse line %s. Dropping", escaped(arg));
2548 return NULL;
2551 /** Parse an exit policy line of the format "accept/reject private:...".
2552 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
2553 * router descriptors until earlier versions are obsolete.
2555 static addr_policy_t *
2556 router_parse_addr_policy_private(directory_token_t *tok)
2558 const char *arg;
2559 uint16_t port_min, port_max;
2560 addr_policy_t result;
2562 arg = tok->args[0];
2563 if (strcmpstart(arg, "private"))
2564 return NULL;
2566 arg += strlen("private");
2567 arg = (char*) eat_whitespace(arg);
2568 if (!arg || *arg != ':')
2569 return NULL;
2571 if (parse_port_range(arg+1, &port_min, &port_max)<0)
2572 return NULL;
2574 memset(&result, 0, sizeof(result));
2575 result.policy_type = (tok->tp == K_REJECT) ? ADDR_POLICY_REJECT
2576 : ADDR_POLICY_ACCEPT;
2577 result.is_private = 1;
2578 result.prt_min = port_min;
2579 result.prt_max = port_max;
2581 return addr_policy_get_canonical_entry(&result);
2584 /** Log and exit if <b>t</b> is malformed */
2585 void
2586 assert_addr_policy_ok(smartlist_t *lst)
2588 if (!lst) return;
2589 SMARTLIST_FOREACH(lst, addr_policy_t *, t, {
2590 tor_assert(t->policy_type == ADDR_POLICY_REJECT ||
2591 t->policy_type == ADDR_POLICY_ACCEPT);
2592 tor_assert(t->prt_min <= t->prt_max);
2597 * Low-level tokenizer for router descriptors and directories.
2600 /** Free all resources allocated for <b>tok</b> */
2601 static void
2602 token_free(directory_token_t *tok)
2604 int i;
2605 tor_assert(tok);
2606 if (tok->args) {
2607 for (i = 0; i < tok->n_args; ++i) {
2608 tor_free(tok->args[i]);
2610 tor_free(tok->args);
2612 tor_free(tok->object_type);
2613 tor_free(tok->object_body);
2614 tor_free(tok->error);
2615 if (tok->key)
2616 crypto_free_pk_env(tok->key);
2617 tor_free(tok);
2620 #define RET_ERR(msg) \
2621 STMT_BEGIN \
2622 if (tok) token_free(tok); \
2623 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2624 tok->tp = _ERR; \
2625 tok->error = tor_strdup(msg); \
2626 goto done_tokenizing; \
2627 STMT_END
2629 static INLINE directory_token_t *
2630 token_check_object(const char *kwd,
2631 directory_token_t *tok, obj_syntax o_syn)
2633 char ebuf[128];
2634 switch (o_syn) {
2635 case NO_OBJ:
2636 if (tok->object_body) {
2637 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd);
2638 RET_ERR(ebuf);
2640 if (tok->key) {
2641 tor_snprintf(ebuf, sizeof(ebuf), "Unexpected public key for %s", kwd);
2642 RET_ERR(ebuf);
2644 break;
2645 case NEED_OBJ:
2646 if (!tok->object_body) {
2647 tor_snprintf(ebuf, sizeof(ebuf), "Missing object for %s", kwd);
2648 RET_ERR(ebuf);
2650 break;
2651 case NEED_KEY_1024:
2652 if (tok->key && crypto_pk_keysize(tok->key) != PK_BYTES) {
2653 tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits",
2654 kwd, (int)crypto_pk_keysize(tok->key));
2655 RET_ERR(ebuf);
2657 /* fall through */
2658 case NEED_KEY:
2659 if (!tok->key) {
2660 tor_snprintf(ebuf, sizeof(ebuf), "Missing public key for %s", kwd);
2662 break;
2663 case OBJ_OK:
2664 break;
2667 done_tokenizing:
2668 return tok;
2671 /** Helper function: read the next token from *s, advance *s to the end of the
2672 * token, and return the parsed token. Parse *<b>s</b> according to the list
2673 * of tokens in <b>table</b>.
2675 static directory_token_t *
2676 get_next_token(const char **s, const char *eos, token_rule_t *table)
2678 const char *next, *eol, *obstart;
2679 int i, j, allocated, obname_len;
2680 directory_token_t *tok;
2681 obj_syntax o_syn = NO_OBJ;
2682 char ebuf[128];
2683 const char *kwd = "";
2685 #define RET_ERR(msg) \
2686 STMT_BEGIN \
2687 if (tok) token_free(tok); \
2688 tok = tor_malloc_zero(sizeof(directory_token_t)); \
2689 tok->tp = _ERR; \
2690 tok->error = tor_strdup(msg); \
2691 goto done_tokenizing; \
2692 STMT_END
2694 tok = tor_malloc_zero(sizeof(directory_token_t));
2695 tok->tp = _ERR;
2697 /* Set *s to first token, eol to end-of-line, next to after first token */
2698 *s = eat_whitespace_eos(*s, eos); /* eat multi-line whitespace */
2699 eol = memchr(*s, '\n', eos-*s);
2700 if (!eol)
2701 eol = eos;
2702 next = find_whitespace_eos(*s, eol);
2704 if (!strcmp_len(*s, "opt", next-*s)) {
2705 /* Skip past an "opt" at the start of the line. */
2706 *s = eat_whitespace_eos_no_nl(next, eol);
2707 next = find_whitespace_eos(*s, eol);
2708 } else if (*s == eos) { /* If no "opt", and end-of-line, line is invalid */
2709 RET_ERR("Unexpected EOF");
2712 /* Search the table for the appropriate entry. (I tried a binary search
2713 * instead, but it wasn't any faster.) */
2714 for (i = 0; table[i].t ; ++i) {
2715 if (!strcmp_len(*s, table[i].t, next-*s)) {
2716 /* We've found the keyword. */
2717 kwd = table[i].t;
2718 tok->tp = table[i].v;
2719 o_syn = table[i].os;
2720 *s = eat_whitespace_eos_no_nl(next, eol);
2721 next = find_whitespace_eos(*s, eol);
2722 /* We go ahead whether there are arguments or not, so that tok->args is
2723 * always set if we want arguments. */
2724 if (table[i].concat_args) {
2725 /* The keyword takes the line as a single argument */
2726 tok->args = tor_malloc(sizeof(char*));
2727 tok->args[0] = tor_strndup(*s,eol-*s); /* Grab everything on line */
2728 tok->n_args = 1;
2729 } else {
2730 /* This keyword takes multiple arguments. */
2731 j = 0;
2732 allocated = 16;
2733 tok->args = tor_malloc(sizeof(char*)*allocated);
2734 while (*s < eol) { /* While not at eol, store the next token */
2735 if (j == allocated) {
2736 allocated *= 2;
2737 tok->args = tor_realloc(tok->args,sizeof(char*)*allocated);
2739 tok->args[j++] = tor_strndup(*s, next-*s);
2740 *s = eat_whitespace_eos_no_nl(next, eol); /* eat intra-line ws */
2741 next = find_whitespace_eos(*s, eol); /* find end of token at *s */
2743 tok->n_args = j;
2745 if (tok->n_args < table[i].min_args) {
2746 tor_snprintf(ebuf, sizeof(ebuf), "Too few arguments to %s", kwd);
2747 RET_ERR(ebuf);
2748 } else if (tok->n_args > table[i].max_args) {
2749 tor_snprintf(ebuf, sizeof(ebuf), "Too many arguments to %s", kwd);
2750 RET_ERR(ebuf);
2752 break;
2756 if (tok->tp == _ERR) {
2757 /* No keyword matched; call it an "K_opt" or "A_unrecognized" */
2758 if (**s == '@')
2759 tok->tp = _A_UNKNOWN;
2760 else
2761 tok->tp = K_OPT;
2762 tok->args = tor_malloc(sizeof(char*));
2763 tok->args[0] = tor_strndup(*s, eol-*s);
2764 tok->n_args = 1;
2765 o_syn = OBJ_OK;
2768 /* Check whether there's an object present */
2769 *s = eat_whitespace_eos(eol, eos); /* Scan from end of first line */
2770 eol = memchr(*s, '\n', eos-*s);
2771 if (!eol || eol-*s<11 || strcmpstart(*s, "-----BEGIN ")) /* No object. */
2772 goto check_object;
2774 obstart = *s; /* Set obstart to start of object spec */
2775 if (*s+11 >= eol-5 || memchr(*s+11,'\0',eol-*s-16) || /* no short lines, */
2776 strcmp_len(eol-5, "-----", 5)) { /* nuls or invalid endings */
2777 RET_ERR("Malformed object: bad begin line");
2779 tok->object_type = tor_strndup(*s+11, eol-*s-16);
2780 obname_len = eol-*s-16; /* store objname length here to avoid a strlen() */
2781 *s = eol+1; /* Set *s to possible start of object data (could be eos) */
2783 /* Go to the end of the object */
2784 next = tor_memstr(*s, eos-*s, "-----END ");
2785 if (!next) {
2786 RET_ERR("Malformed object: missing object end line");
2788 eol = memchr(next, '\n', eos-next);
2789 if (!eol) /* end-of-line marker, or eos if there's no '\n' */
2790 eol = eos;
2791 /* Validate the ending tag, which should be 9 + NAME + 5 + eol */
2792 if (eol-next != 9+obname_len+5 ||
2793 strcmp_len(next+9, tok->object_type, obname_len) ||
2794 strcmp_len(eol-5, "-----", 5)) {
2795 snprintf(ebuf, sizeof(ebuf), "Malformed object: mismatched end tag %s",
2796 tok->object_type);
2797 ebuf[sizeof(ebuf)-1] = '\0';
2798 RET_ERR(ebuf);
2800 if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a key... */
2801 tok->key = crypto_new_pk_env();
2802 if (crypto_pk_read_public_key_from_string(tok->key, obstart, eol-obstart))
2803 RET_ERR("Couldn't parse public key.");
2804 } else { /* If it's something else, try to base64-decode it */
2805 int r;
2806 tok->object_body = tor_malloc(next-*s); /* really, this is too much RAM. */
2807 r = base64_decode(tok->object_body, next-*s, *s, next-*s);
2808 if (r<0)
2809 RET_ERR("Malformed object: bad base64-encoded data");
2810 tok->object_size = r;
2812 *s = eol;
2814 check_object:
2815 tok = token_check_object(kwd, tok, o_syn);
2817 done_tokenizing:
2818 return tok;
2820 #undef RET_ERR
2823 /** Read all tokens from a string between <b>start</b> and <b>end</b>, and add
2824 * them to <b>out</b>. Parse according to the token rules in <b>table</b>.
2825 * Caller must free tokens in <b>out</b>. If <b>end</b> is NULL, use the
2826 * entire string.
2828 static int
2829 tokenize_string(const char *start, const char *end, smartlist_t *out,
2830 token_rule_t *table, int flags)
2832 const char **s;
2833 directory_token_t *tok = NULL;
2834 int counts[_NIL];
2835 int i;
2836 int first_nonannotation;
2837 int prev_len = smartlist_len(out);
2839 s = &start;
2840 if (!end)
2841 end = start+strlen(start);
2842 for (i = 0; i < _NIL; ++i)
2843 counts[i] = 0;
2844 while (*s < end && (!tok || tok->tp != _EOF)) {
2845 tok = get_next_token(s, end, table);
2846 if (tok->tp == _ERR) {
2847 log_warn(LD_DIR, "parse error: %s", tok->error);
2848 token_free(tok);
2849 return -1;
2851 ++counts[tok->tp];
2852 smartlist_add(out, tok);
2853 *s = eat_whitespace_eos(*s, end);
2856 if (flags & TS_NOCHECK)
2857 return 0;
2859 if ((flags & TS_ANNOTATIONS_OK)) {
2860 first_nonannotation = -1;
2861 for (i = 0; i < smartlist_len(out); ++i) {
2862 tok = smartlist_get(out, i);
2863 if (tok->tp < MIN_ANNOTATION || tok->tp > MAX_ANNOTATION) {
2864 first_nonannotation = i;
2865 break;
2868 if (first_nonannotation < 0) {
2869 log_warn(LD_DIR, "parse error: item contains only annotations");
2870 return -1;
2872 for (i=first_nonannotation; i < smartlist_len(out); ++i) {
2873 tok = smartlist_get(out, i);
2874 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
2875 log_warn(LD_DIR, "parse error: Annotations mixed with keywords");
2876 return -1;
2879 if ((flags & TS_NO_NEW_ANNOTATIONS)) {
2880 if (first_nonannotation != prev_len) {
2881 log_warn(LD_DIR, "parse error: Unexpectd annotations.");
2882 return -1;
2885 } else {
2886 for (i=0; i < smartlist_len(out); ++i) {
2887 tok = smartlist_get(out, i);
2888 if (tok->tp >= MIN_ANNOTATION && tok->tp <= MAX_ANNOTATION) {
2889 log_warn(LD_DIR, "parse error: no annotations allowed.");
2890 return -1;
2893 first_nonannotation = 0;
2895 for (i = 0; table[i].t; ++i) {
2896 if (counts[table[i].v] < table[i].min_cnt) {
2897 log_warn(LD_DIR, "Parse error: missing %s element.", table[i].t);
2898 return -1;
2900 if (counts[table[i].v] > table[i].max_cnt) {
2901 log_warn(LD_DIR, "Parse error: too many %s elements.", table[i].t);
2902 return -1;
2904 if (table[i].pos & AT_START) {
2905 if (smartlist_len(out) < 1 ||
2906 (tok = smartlist_get(out, first_nonannotation))->tp != table[i].v) {
2907 log_warn(LD_DIR, "Parse error: first item is not %s.", table[i].t);
2908 return -1;
2911 if (table[i].pos & AT_END) {
2912 if (smartlist_len(out) < 1 ||
2913 (tok = smartlist_get(out, smartlist_len(out)-1))->tp != table[i].v) {
2914 log_warn(LD_DIR, "Parse error: last item is not %s.", table[i].t);
2915 return -1;
2919 return 0;
2922 /** Find the first token in <b>s</b> whose keyword is <b>keyword</b>; return
2923 * NULL if no such keyword is found.
2925 static directory_token_t *
2926 find_first_by_keyword(smartlist_t *s, directory_keyword keyword)
2928 SMARTLIST_FOREACH(s, directory_token_t *, t, if (t->tp == keyword) return t);
2929 return NULL;
2932 /** Return a newly allocated smartlist of all accept or reject tokens in
2933 * <b>s</b>.
2935 static smartlist_t *
2936 find_all_exitpolicy(smartlist_t *s)
2938 smartlist_t *out = smartlist_create();
2939 SMARTLIST_FOREACH(s, directory_token_t *, t,
2940 if (t->tp == K_ACCEPT || t->tp == K_REJECT)
2941 smartlist_add(out,t));
2942 return out;
2945 /** Compute the SHA-1 digest of the substring of <b>s</b> taken from the first
2946 * occurrence of <b>start_str</b> through the first instance of c after the
2947 * first subsequent occurrence of <b>end_str</b>; store the 20-byte result in
2948 * <b>digest</b>; return 0 on success.
2950 * If no such substring exists, return -1.
2952 static int
2953 router_get_hash_impl(const char *s, char *digest,
2954 const char *start_str,
2955 const char *end_str, char end_c)
2957 char *start, *end;
2958 start = strstr(s, start_str);
2959 if (!start) {
2960 log_warn(LD_DIR,"couldn't find start of hashed material \"%s\"",start_str);
2961 return -1;
2963 if (start != s && *(start-1) != '\n') {
2964 log_warn(LD_DIR,
2965 "first occurrence of \"%s\" is not at the start of a line",
2966 start_str);
2967 return -1;
2969 end = strstr(start+strlen(start_str), end_str);
2970 if (!end) {
2971 log_warn(LD_DIR,"couldn't find end of hashed material \"%s\"",end_str);
2972 return -1;
2974 end = strchr(end+strlen(end_str), end_c);
2975 if (!end) {
2976 log_warn(LD_DIR,"couldn't find EOL");
2977 return -1;
2979 ++end;
2981 if (crypto_digest(digest, start, end-start)) {
2982 log_warn(LD_BUG,"couldn't compute digest");
2983 return -1;
2986 return 0;
2989 /** Parse the Tor version of the platform string <b>platform</b>,
2990 * and compare it to the version in <b>cutoff</b>. Return 1 if
2991 * the router is at least as new as the cutoff, else return 0.
2994 tor_version_as_new_as(const char *platform, const char *cutoff)
2996 tor_version_t cutoff_version, router_version;
2997 char *s, *s2, *start;
2998 char tmp[128];
3000 tor_assert(platform);
3002 if (tor_version_parse(cutoff, &cutoff_version)<0) {
3003 log_warn(LD_BUG,"cutoff version '%s' unparseable.",cutoff);
3004 return 0;
3006 if (strcmpstart(platform,"Tor ")) /* nonstandard Tor; be safe and say yes */
3007 return 1;
3009 start = (char *)eat_whitespace(platform+3);
3010 if (!*start) return 0;
3011 s = (char *)find_whitespace(start); /* also finds '\0', which is fine */
3012 s2 = (char*)eat_whitespace(s);
3013 if (!strcmpstart(s2, "(r"))
3014 s = (char*)find_whitespace(s2);
3016 if ((size_t)(s-start+1) >= sizeof(tmp)) /* too big, no */
3017 return 0;
3018 strlcpy(tmp, start, s-start+1);
3020 if (tor_version_parse(tmp, &router_version)<0) {
3021 log_info(LD_DIR,"Router version '%s' unparseable.",tmp);
3022 return 1; /* be safe and say yes */
3025 /* Here's why we don't need to do any special handling for svn revisions:
3026 * - If neither has an svn revision, we're fine.
3027 * - If the router doesn't have an svn revision, we can't assume that it
3028 * is "at least" any svn revision, so we need to return 0.
3029 * - If the target version doesn't have an svn revision, any svn revision
3030 * (or none at all) is good enough, so return 1.
3031 * - If both target and router have an svn revision, we compare them.
3034 return tor_version_compare(&router_version, &cutoff_version) >= 0;
3037 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
3038 * Return 0 on success, -1 on failure. */
3040 tor_version_parse(const char *s, tor_version_t *out)
3042 char *eos=NULL;
3043 const char *cp=NULL;
3044 /* Format is:
3045 * "Tor " ? NUM dot NUM dot NUM [ ( pre | rc | dot ) NUM [ - tag ] ]
3047 tor_assert(s);
3048 tor_assert(out);
3050 memset(out, 0, sizeof(tor_version_t));
3052 if (!strcasecmpstart(s, "Tor "))
3053 s += 4;
3055 /* Get major. */
3056 out->major = strtol(s,&eos,10);
3057 if (!eos || eos==s || *eos != '.') return -1;
3058 cp = eos+1;
3060 /* Get minor */
3061 out->minor = strtol(cp,&eos,10);
3062 if (!eos || eos==cp || *eos != '.') return -1;
3063 cp = eos+1;
3065 /* Get micro */
3066 out->micro = strtol(cp,&eos,10);
3067 if (!eos || eos==cp) return -1;
3068 if (!*eos) {
3069 out->status = VER_RELEASE;
3070 out->patchlevel = 0;
3071 return 0;
3073 cp = eos;
3075 /* Get status */
3076 if (*cp == '.') {
3077 out->status = VER_RELEASE;
3078 ++cp;
3079 } else if (0==strncmp(cp, "pre", 3)) {
3080 out->status = VER_PRE;
3081 cp += 3;
3082 } else if (0==strncmp(cp, "rc", 2)) {
3083 out->status = VER_RC;
3084 cp += 2;
3085 } else {
3086 return -1;
3089 /* Get patchlevel */
3090 out->patchlevel = strtol(cp,&eos,10);
3091 if (!eos || eos==cp) return -1;
3092 cp = eos;
3094 /* Get status tag. */
3095 if (*cp == '-' || *cp == '.')
3096 ++cp;
3097 eos = (char*) find_whitespace(cp);
3098 if (eos-cp >= (int)sizeof(out->status_tag))
3099 strlcpy(out->status_tag, cp, sizeof(out->status_tag));
3100 else {
3101 memcpy(out->status_tag, cp, eos-cp);
3102 out->status_tag[eos-cp] = 0;
3104 cp = eat_whitespace(eos);
3106 if (!strcmpstart(cp, "(r")) {
3107 cp += 2;
3108 out->svn_revision = strtol(cp,&eos,10);
3111 return 0;
3114 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
3115 * b. */
3117 tor_version_compare(tor_version_t *a, tor_version_t *b)
3119 int i;
3120 tor_assert(a);
3121 tor_assert(b);
3122 if ((i = a->major - b->major))
3123 return i;
3124 else if ((i = a->minor - b->minor))
3125 return i;
3126 else if ((i = a->micro - b->micro))
3127 return i;
3128 else if ((i = a->status - b->status))
3129 return i;
3130 else if ((i = a->patchlevel - b->patchlevel))
3131 return i;
3132 else if ((i = strcmp(a->status_tag, b->status_tag)))
3133 return i;
3134 else
3135 return a->svn_revision - b->svn_revision;
3138 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
3140 static int
3141 tor_version_same_series(tor_version_t *a, tor_version_t *b)
3143 tor_assert(a);
3144 tor_assert(b);
3145 return ((a->major == b->major) &&
3146 (a->minor == b->minor) &&
3147 (a->micro == b->micro));
3150 /** Helper: Given pointers to two strings describing tor versions, return -1
3151 * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
3152 * Used to sort a list of versions. */
3153 static int
3154 _compare_tor_version_str_ptr(const void **_a, const void **_b)
3156 const char *a = *_a, *b = *_b;
3157 int ca, cb;
3158 tor_version_t va, vb;
3159 ca = tor_version_parse(a, &va);
3160 cb = tor_version_parse(b, &vb);
3161 /* If they both parse, compare them. */
3162 if (!ca && !cb)
3163 return tor_version_compare(&va,&vb);
3164 /* If one parses, it comes first. */
3165 if (!ca && cb)
3166 return -1;
3167 if (ca && !cb)
3168 return 1;
3169 /* If neither parses, compare strings. Also, the directory server admin
3170 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
3171 return strcmp(a,b);
3174 /** Sort a list of string-representations of versions in ascending order. */
3175 void
3176 sort_version_list(smartlist_t *versions, int remove_duplicates)
3178 smartlist_sort(versions, _compare_tor_version_str_ptr);
3180 if (remove_duplicates)
3181 smartlist_uniq(versions, _compare_tor_version_str_ptr, _tor_free);
3184 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
3185 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
3186 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
3187 * encrypted introduction points to the newly allocated
3188 * *<b>intro_points_encrypted_out</b>, their encrypted size to
3189 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
3190 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
3191 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
3192 * and -1 for failure.
3195 rend_parse_v2_service_descriptor(rend_service_descriptor_t **parsed_out,
3196 char *desc_id_out,
3197 char **intro_points_encrypted_out,
3198 size_t *intro_points_encrypted_size_out,
3199 size_t *encoded_size_out,
3200 const char **next_out, const char *desc)
3202 rend_service_descriptor_t *result =
3203 tor_malloc_zero(sizeof(rend_service_descriptor_t));
3204 char desc_hash[DIGEST_LEN];
3205 const char *eos;
3206 smartlist_t *tokens = smartlist_create();
3207 directory_token_t *tok;
3208 char secret_id_part[DIGEST_LEN];
3209 int i, version, num_ok=1;
3210 smartlist_t *versions;
3211 char public_key_hash[DIGEST_LEN];
3212 char test_desc_id[DIGEST_LEN];
3213 tor_assert(desc);
3214 /* Check if desc starts correctly. */
3215 if (strncmp(desc, "rendezvous-service-descriptor ",
3216 strlen("rendezvous-service-descriptor "))) {
3217 log_info(LD_REND, "Descriptor does not start correctly.");
3218 goto err;
3220 /* Compute descriptor hash for later validation. */
3221 if (router_get_hash_impl(desc, desc_hash,
3222 "rendezvous-service-descriptor ",
3223 "\nsignature", '\n') < 0) {
3224 log_warn(LD_REND, "Couldn't compute descriptor hash.");
3225 goto err;
3227 /* Determine end of string. */
3228 eos = strstr(desc, "\nrendezvous-service-descriptor ");
3229 if (!eos)
3230 eos = desc + strlen(desc);
3231 else
3232 eos = eos + 1;
3233 /* Tokenize descriptor. */
3234 if (tokenize_string(desc, eos, tokens, desc_token_table, 0)) {
3235 log_warn(LD_REND, "Error tokenizing descriptor.");
3236 goto err;
3238 /* Set next to next descriptor, if available. */
3239 *next_out = eos;
3240 /* Set length of encoded descriptor. */
3241 *encoded_size_out = eos - desc;
3242 /* Check min allowed length of token list. */
3243 if (smartlist_len(tokens) < 7) {
3244 log_warn(LD_REND, "Impossibly short descriptor.");
3245 goto err;
3247 /* Parse base32-encoded descriptor ID. */
3248 tok = find_first_by_keyword(tokens, R_RENDEZVOUS_SERVICE_DESCRIPTOR);
3249 tor_assert(tok);
3250 tor_assert(tok == smartlist_get(tokens, 0));
3251 tor_assert(tok->n_args == 1);
3252 if (strlen(tok->args[0]) != REND_DESC_ID_V2_LEN_BASE32 ||
3253 strspn(tok->args[0], BASE32_CHARS) != REND_DESC_ID_V2_LEN_BASE32) {
3254 log_warn(LD_REND, "Invalid descriptor ID: '%s'", tok->args[0]);
3255 goto err;
3257 if (base32_decode(desc_id_out, DIGEST_LEN,
3258 tok->args[0], REND_DESC_ID_V2_LEN_BASE32) < 0) {
3259 log_warn(LD_REND, "Descriptor ID contains illegal characters: %s",
3260 tok->args[0]);
3261 goto err;
3263 /* Parse descriptor version. */
3264 tok = find_first_by_keyword(tokens, R_VERSION);
3265 tor_assert(tok);
3266 tor_assert(tok->n_args == 1);
3267 result->version =
3268 (int) tor_parse_long(tok->args[0], 10, 0, INT_MAX, &num_ok, NULL);
3269 if (result->version != 2 || !num_ok) {
3270 /* If it's <2, it shouldn't be under this format. If the number
3271 * is greater than 2, we bumped it because we broke backward
3272 * compatibility. See how version numbers in our other formats
3273 * work. */
3274 log_warn(LD_REND, "Unrecognized descriptor version: %s",
3275 escaped(tok->args[0]));
3276 goto err;
3278 /* Parse public key. */
3279 tok = find_first_by_keyword(tokens, R_PERMANENT_KEY);
3280 tor_assert(tok);
3281 result->pk = tok->key;
3282 tok->key = NULL; /* Prevent free */
3283 /* Parse secret ID part. */
3284 tok = find_first_by_keyword(tokens, R_SECRET_ID_PART);
3285 tor_assert(tok);
3286 tor_assert(tok->n_args == 1);
3287 if (strlen(tok->args[0]) != REND_SECRET_ID_PART_LEN_BASE32 ||
3288 strspn(tok->args[0], BASE32_CHARS) != REND_SECRET_ID_PART_LEN_BASE32) {
3289 log_warn(LD_REND, "Invalid secret ID part: '%s'", tok->args[0]);
3290 goto err;
3292 if (base32_decode(secret_id_part, DIGEST_LEN, tok->args[0], 32) < 0) {
3293 log_warn(LD_REND, "Secret ID part contains illegal characters: %s",
3294 tok->args[0]);
3295 goto err;
3297 /* Parse publication time -- up-to-date check is done when storing the
3298 * descriptor. */
3299 tok = find_first_by_keyword(tokens, R_PUBLICATION_TIME);
3300 tor_assert(tok);
3301 tor_assert(tok->n_args == 1);
3302 if (parse_iso_time(tok->args[0], &result->timestamp) < 0) {
3303 log_warn(LD_REND, "Invalid publication time: '%s'", tok->args[0]);
3304 goto err;
3306 /* Parse protocol versions. */
3307 tok = find_first_by_keyword(tokens, R_PROTOCOL_VERSIONS);
3308 tor_assert(tok);
3309 tor_assert(tok->n_args == 1);
3310 versions = smartlist_create();
3311 smartlist_split_string(versions, tok->args[0], ",",
3312 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
3313 for (i = 0; i < smartlist_len(versions); i++) {
3314 version = (int) tor_parse_long(smartlist_get(versions, i),
3315 10, 0, INT_MAX, &num_ok, NULL);
3316 if (!num_ok) /* It's a string; let's ignore it. */
3317 continue;
3318 result->protocols |= 1 << version;
3320 SMARTLIST_FOREACH(versions, char *, cp, tor_free(cp));
3321 smartlist_free(versions);
3322 /* Parse encrypted introduction points. Don't verify. */
3323 tok = find_first_by_keyword(tokens, R_INTRODUCTION_POINTS);
3324 if (tok) {
3325 if (strcmp(tok->object_type, "MESSAGE")) {
3326 log_warn(LD_DIR, "Bad object type: introduction points should be of "
3327 "type MESSAGE");
3328 goto err;
3330 *intro_points_encrypted_out = tok->object_body;
3331 *intro_points_encrypted_size_out = tok->object_size;
3332 tok->object_body = NULL; /* Prevent free. */
3333 } else {
3334 *intro_points_encrypted_out = NULL;
3335 *intro_points_encrypted_size_out = 0;
3337 /* Parse and verify signature. */
3338 tok = find_first_by_keyword(tokens, R_SIGNATURE);
3339 tor_assert(tok);
3340 note_crypto_pk_op(VERIFY_RTR);
3341 if (check_signature_token(desc_hash, tok, result->pk, 0,
3342 "v2 rendezvous service descriptor") < 0)
3343 goto err;
3344 /* Verify that descriptor ID belongs to public key and secret ID part. */
3345 crypto_pk_get_digest(result->pk, public_key_hash);
3346 rend_get_descriptor_id_bytes(test_desc_id, public_key_hash,
3347 secret_id_part);
3348 if (memcmp(desc_id_out, test_desc_id, DIGEST_LEN)) {
3349 log_warn(LD_REND, "Parsed descriptor ID does not match "
3350 "computed descriptor ID.");
3351 goto err;
3353 goto done;
3354 err:
3355 if (result)
3356 rend_service_descriptor_free(result);
3357 result = NULL;
3358 done:
3359 if (tokens) {
3360 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3361 smartlist_free(tokens);
3363 *parsed_out = result;
3364 if (result)
3365 return 0;
3366 return -1;
3369 /** Decrypt and decode the introduction points in
3370 * <b>intro_points_encrypted</b> of length
3371 * <b>intro_points_encrypted_size</b> using <b>descriptor_cookie</b>
3372 * (which may also be <b>NULL</b> if no decryption, but only parsing is
3373 * required), parse the introduction points, and write the result to
3374 * <b>parsed</b>; return the number of successfully parsed introduction
3375 * points or -1 in case of a failure.
3378 rend_decrypt_introduction_points(rend_service_descriptor_t *parsed,
3379 const char *descriptor_cookie,
3380 const char *intro_points_encrypted,
3381 size_t intro_points_encrypted_size)
3383 char *ipos_decrypted = NULL;
3384 const char **current_ipo;
3385 smartlist_t *tokens;
3386 directory_token_t *tok;
3387 rend_intro_point_t *intro;
3388 extend_info_t *info;
3389 struct in_addr ip;
3390 int result, num_ok=1;
3391 tor_assert(parsed);
3392 /** Function may only be invoked once. */
3393 tor_assert(!parsed->intro_nodes);
3394 tor_assert(intro_points_encrypted);
3395 tor_assert(intro_points_encrypted_size > 0);
3396 /* Decrypt introduction points, if required. */
3397 if (descriptor_cookie) {
3398 crypto_cipher_env_t *cipher;
3399 int unenclen;
3400 ipos_decrypted = tor_malloc_zero(intro_points_encrypted_size - 16);
3401 cipher = crypto_create_init_cipher(descriptor_cookie, 0);
3402 unenclen = crypto_cipher_decrypt_with_iv(cipher, ipos_decrypted,
3403 intro_points_encrypted_size - 16,
3404 intro_points_encrypted,
3405 intro_points_encrypted_size);
3406 crypto_free_cipher_env(cipher);
3407 if (unenclen < 0) {
3408 tor_free(ipos_decrypted);
3409 return -1;
3411 intro_points_encrypted = ipos_decrypted;
3412 intro_points_encrypted_size = unenclen;
3414 /* Consider one intro point after the other. */
3415 current_ipo = &intro_points_encrypted;
3416 tokens = smartlist_create();
3417 parsed->intro_nodes = smartlist_create();
3418 while (!strcmpstart(*current_ipo, "introduction-point ")) {
3419 /* Determine end of string. */
3420 const char *eos = strstr(*current_ipo, "\nintroduction-point ");
3421 if (!eos)
3422 eos = *current_ipo+strlen(*current_ipo);
3423 else
3424 eos = eos+1;
3425 /* Free tokens and clear token list. */
3426 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3427 smartlist_clear(tokens);
3428 /* Tokenize string. */
3429 if (tokenize_string(*current_ipo, eos, tokens, ipo_token_table, 0)) {
3430 log_warn(LD_REND, "Error tokenizing introduction point.");
3431 goto err;
3433 /* Advance to next introduction point, if available. */
3434 *current_ipo = eos;
3435 /* Check minimum allowed length of introduction point. */
3436 if (smartlist_len(tokens) < 5) {
3437 log_warn(LD_REND, "Impossibly short introduction point.");
3438 goto err;
3440 /* Allocate new intro point and extend info. */
3441 intro = tor_malloc_zero(sizeof(rend_intro_point_t));
3442 info = intro->extend_info = tor_malloc_zero(sizeof(extend_info_t));
3443 /* Parse identifier. */
3444 tok = find_first_by_keyword(tokens, R_IPO_IDENTIFIER);
3445 tor_assert(tok);
3446 if (base32_decode(info->identity_digest, DIGEST_LEN,
3447 tok->args[0], REND_INTRO_POINT_ID_LEN_BASE32) < 0) {
3448 log_warn(LD_REND, "Identity digest contains illegal characters: %s",
3449 tok->args[0]);
3450 rend_intro_point_free(intro);
3451 goto err;
3453 /* Write identifier to nickname. */
3454 info->nickname[0] = '$';
3455 base16_encode(info->nickname + 1, sizeof(info->nickname) - 1,
3456 info->identity_digest, DIGEST_LEN);
3457 /* Parse IP address. */
3458 tok = find_first_by_keyword(tokens, R_IPO_IP_ADDRESS);
3459 if (tor_inet_aton(tok->args[0], &ip) == 0) {
3460 log_warn(LD_REND, "Could not parse IP address.");
3461 rend_intro_point_free(intro);
3462 goto err;
3464 info->addr = ntohl(ip.s_addr);
3465 /* Parse onion port. */
3466 tok = find_first_by_keyword(tokens, R_IPO_ONION_PORT);
3467 info->port = (uint16_t) tor_parse_long(tok->args[0],10,1,65535,
3468 &num_ok,NULL);
3469 if (!info->port || !num_ok) {
3470 log_warn(LD_REND, "Introduction point onion port %s is invalid",
3471 escaped(tok->args[0]));
3472 rend_intro_point_free(intro);
3473 goto err;
3475 /* Parse onion key. */
3476 tok = find_first_by_keyword(tokens, R_IPO_ONION_KEY);
3477 info->onion_key = tok->key;
3478 tok->key = NULL; /* Prevent free */
3479 /* Parse service key. */
3480 tok = find_first_by_keyword(tokens, R_IPO_SERVICE_KEY);
3481 intro->intro_key = tok->key;
3482 tok->key = NULL; /* Prevent free */
3483 /* Add extend info to list of introduction points. */
3484 smartlist_add(parsed->intro_nodes, intro);
3486 result = smartlist_len(parsed->intro_nodes);
3487 goto done;
3489 err:
3490 result = -1;
3492 done:
3493 /* Free tokens and clear token list. */
3494 SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
3495 smartlist_free(tokens);
3497 return result;