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-2017, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Code to parse and validate router descriptors, consenus directories,
10 * and similar objects.
12 * The objects parsed by this module use a common text-based metaformat,
13 * documented in dir-spec.txt in torspec.git. This module is itself divided
14 * into two major kinds of function: code to handle the metaformat, and code
15 * to convert from particular instances of the metaformat into the
16 * objects that Tor uses.
18 * The generic parsing code works by calling a table-based tokenizer on the
19 * input string. Each token corresponds to a single line with a token, plus
20 * optional arguments on that line, plus an optional base-64 encoded object
21 * after that line. Each token has a definition in a table of token_rule_t
22 * entries that describes how many arguments it can take, whether it takes an
23 * object, how many times it may appear, whether it must appear first, and so
26 * The tokenizer function tokenize_string() converts its string input into a
27 * smartlist full of instances of directory_token_t, according to a provided
28 * table of token_rule_t.
30 * The generic parts of this module additionally include functions for
31 * finding the start and end of signed information inside a signed object, and
32 * computing the digest that will be signed.
34 * There are also functions for saving objects to disk that have caused
37 * The specific parts of this module describe conversions between
38 * particular lists of directory_token_t and particular objects. The
39 * kinds of objects that can be parsed here are:
41 * <li>router descriptors (managed from routerlist.c)
42 * <li>extra-info documents (managed from routerlist.c)
43 * <li>microdescriptors (managed from microdesc.c)
44 * <li>vote and consensus networkstatus documents, and the routerstatus_t
45 * objects that they comprise (managed from networkstatus.c)
46 * <li>detached-signature objects used by authorities for gathering
47 * signatures on the networkstatus consensus (managed from dirvote.c)
48 * <li>authority key certificates (managed from routerlist.c)
49 * <li>hidden service descriptors (managed from rendcommon.c and rendcache.c)
52 * For no terribly good reason, the functions to <i>generate</i> signatures on
53 * the above directory objects are also in this module.
56 #define ROUTERPARSE_PRIVATE
60 #include "circuitstats.h"
63 #include "parsecommon.h"
66 #include "rendcommon.h"
68 #include "routerlist.h"
70 #include "microdesc.h"
71 #include "networkstatus.h"
73 #include "routerkeys.h"
74 #include "routerparse.h"
75 #include "entrynodes.h"
78 #include "shared_random.h"
83 /****************************************************************************/
85 /** List of tokens recognized in router descriptors */
86 static token_rule_t routerdesc_token_table
[] = {
87 T0N("reject", K_REJECT
, ARGS
, NO_OBJ
),
88 T0N("accept", K_ACCEPT
, ARGS
, NO_OBJ
),
89 T0N("reject6", K_REJECT6
, ARGS
, NO_OBJ
),
90 T0N("accept6", K_ACCEPT6
, ARGS
, NO_OBJ
),
91 T1_START( "router", K_ROUTER
, GE(5), NO_OBJ
),
92 T01("ipv6-policy", K_IPV6_POLICY
, CONCAT_ARGS
, NO_OBJ
),
93 T1( "signing-key", K_SIGNING_KEY
, NO_ARGS
, NEED_KEY_1024
),
94 T1( "onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
95 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
96 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
97 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
98 T01("uptime", K_UPTIME
, GE(1), NO_OBJ
),
99 T01("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
100 T01("hibernating", K_HIBERNATING
, GE(1), NO_OBJ
),
101 T01("platform", K_PLATFORM
, CONCAT_ARGS
, NO_OBJ
),
102 T01("proto", K_PROTO
, CONCAT_ARGS
, NO_OBJ
),
103 T01("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
104 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
105 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
106 T01("extra-info-digest", K_EXTRA_INFO_DIGEST
, GE(1), NO_OBJ
),
107 T01("hidden-service-dir", K_HIDDEN_SERVICE_DIR
, NO_ARGS
, NO_OBJ
),
108 T01("identity-ed25519", K_IDENTITY_ED25519
, NO_ARGS
, NEED_OBJ
),
109 T01("master-key-ed25519", K_MASTER_KEY_ED25519
, GE(1), NO_OBJ
),
110 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519
, GE(1), NO_OBJ
),
111 T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT
, NO_ARGS
, NEED_OBJ
),
112 T01("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT
,
115 T01("allow-single-hop-exits",K_ALLOW_SINGLE_HOP_EXITS
, NO_ARGS
, NO_OBJ
),
117 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
118 T01("caches-extra-info", K_CACHES_EXTRA_INFO
, NO_ARGS
, NO_OBJ
),
119 T0N("or-address", K_OR_ADDRESS
, GE(1), NO_OBJ
),
121 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
122 T1( "bandwidth", K_BANDWIDTH
, GE(3), NO_OBJ
),
123 A01("@purpose", A_PURPOSE
, GE(1), NO_OBJ
),
124 T01("tunnelled-dir-server",K_DIR_TUNNELLED
, NO_ARGS
, NO_OBJ
),
129 /** List of tokens recognized in extra-info documents. */
130 static token_rule_t extrainfo_token_table
[] = {
131 T1_END( "router-signature", K_ROUTER_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
132 T1( "published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
133 T01("identity-ed25519", K_IDENTITY_ED25519
, NO_ARGS
, NEED_OBJ
),
134 T01("router-sig-ed25519", K_ROUTER_SIG_ED25519
, GE(1), NO_OBJ
),
135 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
136 T01("read-history", K_READ_HISTORY
, ARGS
, NO_OBJ
),
137 T01("write-history", K_WRITE_HISTORY
, ARGS
, NO_OBJ
),
138 T01("dirreq-stats-end", K_DIRREQ_END
, ARGS
, NO_OBJ
),
139 T01("dirreq-v2-ips", K_DIRREQ_V2_IPS
, ARGS
, NO_OBJ
),
140 T01("dirreq-v3-ips", K_DIRREQ_V3_IPS
, ARGS
, NO_OBJ
),
141 T01("dirreq-v2-reqs", K_DIRREQ_V2_REQS
, ARGS
, NO_OBJ
),
142 T01("dirreq-v3-reqs", K_DIRREQ_V3_REQS
, ARGS
, NO_OBJ
),
143 T01("dirreq-v2-share", K_DIRREQ_V2_SHARE
, ARGS
, NO_OBJ
),
144 T01("dirreq-v3-share", K_DIRREQ_V3_SHARE
, ARGS
, NO_OBJ
),
145 T01("dirreq-v2-resp", K_DIRREQ_V2_RESP
, ARGS
, NO_OBJ
),
146 T01("dirreq-v3-resp", K_DIRREQ_V3_RESP
, ARGS
, NO_OBJ
),
147 T01("dirreq-v2-direct-dl", K_DIRREQ_V2_DIR
, ARGS
, NO_OBJ
),
148 T01("dirreq-v3-direct-dl", K_DIRREQ_V3_DIR
, ARGS
, NO_OBJ
),
149 T01("dirreq-v2-tunneled-dl", K_DIRREQ_V2_TUN
, ARGS
, NO_OBJ
),
150 T01("dirreq-v3-tunneled-dl", K_DIRREQ_V3_TUN
, ARGS
, NO_OBJ
),
151 T01("entry-stats-end", K_ENTRY_END
, ARGS
, NO_OBJ
),
152 T01("entry-ips", K_ENTRY_IPS
, ARGS
, NO_OBJ
),
153 T01("cell-stats-end", K_CELL_END
, ARGS
, NO_OBJ
),
154 T01("cell-processed-cells", K_CELL_PROCESSED
, ARGS
, NO_OBJ
),
155 T01("cell-queued-cells", K_CELL_QUEUED
, ARGS
, NO_OBJ
),
156 T01("cell-time-in-queue", K_CELL_TIME
, ARGS
, NO_OBJ
),
157 T01("cell-circuits-per-decile", K_CELL_CIRCS
, ARGS
, NO_OBJ
),
158 T01("exit-stats-end", K_EXIT_END
, ARGS
, NO_OBJ
),
159 T01("exit-kibibytes-written", K_EXIT_WRITTEN
, ARGS
, NO_OBJ
),
160 T01("exit-kibibytes-read", K_EXIT_READ
, ARGS
, NO_OBJ
),
161 T01("exit-streams-opened", K_EXIT_OPENED
, ARGS
, NO_OBJ
),
163 T1_START( "extra-info", K_EXTRA_INFO
, GE(2), NO_OBJ
),
168 /** List of tokens recognized in the body part of v3 networkstatus
170 static token_rule_t rtrstatus_token_table
[] = {
171 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
172 T1( "r", K_R
, GE(7), NO_OBJ
),
173 T0N("a", K_A
, GE(1), NO_OBJ
),
174 T1( "s", K_S
, ARGS
, NO_OBJ
),
175 T01("v", K_V
, CONCAT_ARGS
, NO_OBJ
),
176 T01("w", K_W
, ARGS
, NO_OBJ
),
177 T0N("m", K_M
, CONCAT_ARGS
, NO_OBJ
),
178 T0N("id", K_ID
, GE(2), NO_OBJ
),
179 T01("pr", K_PROTO
, CONCAT_ARGS
, NO_OBJ
),
180 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
184 /** List of tokens common to V3 authority certificates and V3 consensuses. */
185 #define CERTIFICATE_MEMBERS \
186 T1("dir-key-certificate-version", K_DIR_KEY_CERTIFICATE_VERSION, \
188 T1("dir-identity-key", K_DIR_IDENTITY_KEY, NO_ARGS, NEED_KEY ),\
189 T1("dir-key-published",K_DIR_KEY_PUBLISHED, CONCAT_ARGS, NO_OBJ), \
190 T1("dir-key-expires", K_DIR_KEY_EXPIRES, CONCAT_ARGS, NO_OBJ), \
191 T1("dir-signing-key", K_DIR_SIGNING_KEY, NO_ARGS, NEED_KEY ),\
192 T1("dir-key-crosscert", K_DIR_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ),\
193 T1("dir-key-certification", K_DIR_KEY_CERTIFICATION, \
194 NO_ARGS, NEED_OBJ), \
195 T01("dir-address", K_DIR_ADDRESS, GE(1), NO_OBJ),
197 /** List of tokens recognized in V3 authority certificates. */
198 static token_rule_t dir_key_certificate_table
[] = {
200 T1("fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
204 /** List of tokens recognized in rendezvous service descriptors */
205 static token_rule_t desc_token_table
[] = {
206 T1_START("rendezvous-service-descriptor", R_RENDEZVOUS_SERVICE_DESCRIPTOR
,
208 T1("version", R_VERSION
, EQ(1), NO_OBJ
),
209 T1("permanent-key", R_PERMANENT_KEY
, NO_ARGS
, NEED_KEY_1024
),
210 T1("secret-id-part", R_SECRET_ID_PART
, EQ(1), NO_OBJ
),
211 T1("publication-time", R_PUBLICATION_TIME
, CONCAT_ARGS
, NO_OBJ
),
212 T1("protocol-versions", R_PROTOCOL_VERSIONS
, EQ(1), NO_OBJ
),
213 T01("introduction-points", R_INTRODUCTION_POINTS
, NO_ARGS
, NEED_OBJ
),
214 T1_END("signature", R_SIGNATURE
, NO_ARGS
, NEED_OBJ
),
218 /** List of tokens recognized in the (encrypted) list of introduction points of
219 * rendezvous service descriptors */
220 static token_rule_t ipo_token_table
[] = {
221 T1_START("introduction-point", R_IPO_IDENTIFIER
, EQ(1), NO_OBJ
),
222 T1("ip-address", R_IPO_IP_ADDRESS
, EQ(1), NO_OBJ
),
223 T1("onion-port", R_IPO_ONION_PORT
, EQ(1), NO_OBJ
),
224 T1("onion-key", R_IPO_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
225 T1("service-key", R_IPO_SERVICE_KEY
, NO_ARGS
, NEED_KEY_1024
),
229 /** List of tokens recognized in the (possibly encrypted) list of introduction
230 * points of rendezvous service descriptors */
231 static token_rule_t client_keys_token_table
[] = {
232 T1_START("client-name", C_CLIENT_NAME
, CONCAT_ARGS
, NO_OBJ
),
233 T1("descriptor-cookie", C_DESCRIPTOR_COOKIE
, EQ(1), NO_OBJ
),
234 T01("client-key", C_CLIENT_KEY
, NO_ARGS
, NEED_SKEY_1024
),
238 /** List of tokens recognized in V3 networkstatus votes. */
239 static token_rule_t networkstatus_token_table
[] = {
240 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
242 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
243 T1("published", K_PUBLISHED
, CONCAT_ARGS
, NO_OBJ
),
244 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
245 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
246 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
247 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
248 T1("known-flags", K_KNOWN_FLAGS
, ARGS
, NO_OBJ
),
249 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
250 T( "fingerprint", K_FINGERPRINT
, CONCAT_ARGS
, NO_OBJ
),
251 T01("signing-ed25519", K_SIGNING_CERT_ED
, NO_ARGS
, NEED_OBJ
),
252 T01("shared-rand-participate",K_SR_FLAG
, NO_ARGS
, NO_OBJ
),
253 T0N("shared-rand-commit", K_COMMIT
, GE(3), NO_OBJ
),
254 T01("shared-rand-previous-value", K_PREVIOUS_SRV
,EQ(2), NO_OBJ
),
255 T01("shared-rand-current-value", K_CURRENT_SRV
, EQ(2), NO_OBJ
),
256 T0N("package", K_PACKAGE
, CONCAT_ARGS
, NO_OBJ
),
257 T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS
,
258 CONCAT_ARGS
, NO_OBJ
),
259 T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS
,
260 CONCAT_ARGS
, NO_OBJ
),
261 T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS
,
262 CONCAT_ARGS
, NO_OBJ
),
263 T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS
,
264 CONCAT_ARGS
, NO_OBJ
),
268 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
269 T1( "contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
270 T1( "dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
271 T01("legacy-dir-key", K_LEGACY_DIR_KEY
, GE(1), NO_OBJ
),
272 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
273 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
274 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
275 T1( "consensus-methods", K_CONSENSUS_METHODS
, GE(1), NO_OBJ
),
280 /** List of tokens recognized in V3 networkstatus consensuses. */
281 static token_rule_t networkstatus_consensus_token_table
[] = {
282 T1_START("network-status-version", K_NETWORK_STATUS_VERSION
,
284 T1("vote-status", K_VOTE_STATUS
, GE(1), NO_OBJ
),
285 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
286 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
287 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
288 T1("voting-delay", K_VOTING_DELAY
, GE(2), NO_OBJ
),
290 T0N("opt", K_OPT
, CONCAT_ARGS
, OBJ_OK
),
292 T1N("dir-source", K_DIR_SOURCE
, GE(6), NO_OBJ
),
293 T1N("contact", K_CONTACT
, CONCAT_ARGS
, NO_OBJ
),
294 T1N("vote-digest", K_VOTE_DIGEST
, GE(1), NO_OBJ
),
296 T1( "known-flags", K_KNOWN_FLAGS
, CONCAT_ARGS
, NO_OBJ
),
298 T01("client-versions", K_CLIENT_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
299 T01("server-versions", K_SERVER_VERSIONS
, CONCAT_ARGS
, NO_OBJ
),
300 T01("consensus-method", K_CONSENSUS_METHOD
, EQ(1), NO_OBJ
),
301 T01("params", K_PARAMS
, ARGS
, NO_OBJ
),
303 T01("shared-rand-previous-value", K_PREVIOUS_SRV
, EQ(2), NO_OBJ
),
304 T01("shared-rand-current-value", K_CURRENT_SRV
, EQ(2), NO_OBJ
),
306 T01("recommended-client-protocols", K_RECOMMENDED_CLIENT_PROTOCOLS
,
307 CONCAT_ARGS
, NO_OBJ
),
308 T01("recommended-relay-protocols", K_RECOMMENDED_RELAY_PROTOCOLS
,
309 CONCAT_ARGS
, NO_OBJ
),
310 T01("required-client-protocols", K_REQUIRED_CLIENT_PROTOCOLS
,
311 CONCAT_ARGS
, NO_OBJ
),
312 T01("required-relay-protocols", K_REQUIRED_RELAY_PROTOCOLS
,
313 CONCAT_ARGS
, NO_OBJ
),
318 /** List of tokens recognized in the footer of v1 directory footers. */
319 static token_rule_t networkstatus_vote_footer_token_table
[] = {
320 T01("directory-footer", K_DIRECTORY_FOOTER
, NO_ARGS
, NO_OBJ
),
321 T01("bandwidth-weights", K_BW_WEIGHTS
, ARGS
, NO_OBJ
),
322 T( "directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
326 /** List of tokens recognized in detached networkstatus signature documents. */
327 static token_rule_t networkstatus_detached_signature_token_table
[] = {
328 T1_START("consensus-digest", K_CONSENSUS_DIGEST
, GE(1), NO_OBJ
),
329 T("additional-digest", K_ADDITIONAL_DIGEST
,GE(3), NO_OBJ
),
330 T1("valid-after", K_VALID_AFTER
, CONCAT_ARGS
, NO_OBJ
),
331 T1("fresh-until", K_FRESH_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
332 T1("valid-until", K_VALID_UNTIL
, CONCAT_ARGS
, NO_OBJ
),
333 T("additional-signature", K_ADDITIONAL_SIGNATURE
, GE(4), NEED_OBJ
),
334 T1N("directory-signature", K_DIRECTORY_SIGNATURE
, GE(2), NEED_OBJ
),
338 /** List of tokens recognized in microdescriptors */
339 static token_rule_t microdesc_token_table
[] = {
340 T1_START("onion-key", K_ONION_KEY
, NO_ARGS
, NEED_KEY_1024
),
341 T01("ntor-onion-key", K_ONION_KEY_NTOR
, GE(1), NO_OBJ
),
342 T0N("id", K_ID
, GE(2), NO_OBJ
),
343 T0N("a", K_A
, GE(1), NO_OBJ
),
344 T01("family", K_FAMILY
, ARGS
, NO_OBJ
),
345 T01("p", K_P
, CONCAT_ARGS
, NO_OBJ
),
346 T01("p6", K_P6
, CONCAT_ARGS
, NO_OBJ
),
347 A01("@last-listed", A_LAST_LISTED
, CONCAT_ARGS
, NO_OBJ
),
353 /* static function prototypes */
354 static int router_add_exit_policy(routerinfo_t
*router
,directory_token_t
*tok
);
355 static addr_policy_t
*router_parse_addr_policy(directory_token_t
*tok
,
357 static addr_policy_t
*router_parse_addr_policy_private(directory_token_t
*tok
);
359 static int router_get_hash_impl_helper(const char *s
, size_t s_len
,
360 const char *start_str
,
361 const char *end_str
, char end_c
,
363 const char **start_out
, const char **end_out
);
364 static int router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
365 const char *start_str
, const char *end_str
,
367 digest_algorithm_t alg
);
368 static int router_get_hashes_impl(const char *s
, size_t s_len
,
369 common_digests_t
*digests
,
370 const char *start_str
, const char *end_str
,
372 static smartlist_t
*find_all_exitpolicy(smartlist_t
*s
);
374 #define CST_NO_CHECK_OBJTYPE (1<<0)
375 static int check_signature_token(const char *digest
,
377 directory_token_t
*tok
,
380 const char *doctype
);
382 #undef DEBUG_AREA_ALLOC
384 #ifdef DEBUG_AREA_ALLOC
385 #define DUMP_AREA(a,name) STMT_BEGIN \
386 size_t alloc=0, used=0; \
387 memarea_get_stats((a),&alloc,&used); \
388 log_debug(LD_MM, "Area for %s has %lu allocated; using %lu.", \
389 name, (unsigned long)alloc, (unsigned long)used); \
391 #else /* !(defined(DEBUG_AREA_ALLOC)) */
392 #define DUMP_AREA(a,name) STMT_NIL
393 #endif /* defined(DEBUG_AREA_ALLOC) */
395 /* Dump mechanism for unparseable descriptors */
397 /** List of dumped descriptors for FIFO cleanup purposes */
398 STATIC smartlist_t
*descs_dumped
= NULL
;
399 /** Total size of dumped descriptors for FIFO cleanup */
400 STATIC
uint64_t len_descs_dumped
= 0;
401 /** Directory to stash dumps in */
402 static int have_dump_desc_dir
= 0;
403 static int problem_with_dump_desc_dir
= 0;
405 #define DESC_DUMP_DATADIR_SUBDIR "unparseable-descs"
406 #define DESC_DUMP_BASE_FILENAME "unparseable-desc"
408 /** Find the dump directory and check if we'll be able to create it */
414 dump_desc_dir
= get_datadir_fname(DESC_DUMP_DATADIR_SUBDIR
);
417 * We just check for it, don't create it at this point; we'll
418 * create it when we need it if it isn't already there.
420 if (check_private_dir(dump_desc_dir
, CPD_CHECK
, get_options()->User
) < 0) {
421 /* Error, log and flag it as having a problem */
423 "Doesn't look like we'll be able to create descriptor dump "
424 "directory %s; dumps will be disabled.",
426 problem_with_dump_desc_dir
= 1;
427 tor_free(dump_desc_dir
);
431 /* Check if it exists */
432 switch (file_status(dump_desc_dir
)) {
434 /* We already have a directory */
435 have_dump_desc_dir
= 1;
438 /* Nothing, we'll need to create it later */
439 have_dump_desc_dir
= 0;
442 /* Log and flag having a problem */
444 "Couldn't check whether descriptor dump directory %s already"
446 dump_desc_dir
, strerror(errno
));
447 problem_with_dump_desc_dir
= 1;
452 /* Something else was here! */
454 "Descriptor dump directory %s already exists and isn't a "
457 problem_with_dump_desc_dir
= 1;
460 if (have_dump_desc_dir
&& !problem_with_dump_desc_dir
) {
461 dump_desc_populate_fifo_from_directory(dump_desc_dir
);
464 tor_free(dump_desc_dir
);
467 /** Create the dump directory if needed and possible */
469 dump_desc_create_dir(void)
473 /* If the problem flag is set, skip it */
474 if (problem_with_dump_desc_dir
) return;
477 if (!have_dump_desc_dir
) {
478 dump_desc_dir
= get_datadir_fname(DESC_DUMP_DATADIR_SUBDIR
);
480 if (check_private_dir(dump_desc_dir
, CPD_CREATE
,
481 get_options()->User
) < 0) {
483 "Failed to create descriptor dump directory %s",
485 problem_with_dump_desc_dir
= 1;
488 /* Okay, we created it */
489 have_dump_desc_dir
= 1;
491 tor_free(dump_desc_dir
);
495 /** Dump desc FIFO/cleanup; take ownership of the given filename, add it to
496 * the FIFO, and clean up the oldest entries to the extent they exceed the
497 * configured cap. If any old entries with a matching hash existed, they
498 * just got overwritten right before this was called and we should adjust
499 * the total size counter without deleting them.
502 dump_desc_fifo_add_and_clean(char *filename
, const uint8_t *digest_sha256
,
505 dumped_desc_t
*ent
= NULL
, *tmp
;
508 tor_assert(filename
!= NULL
);
509 tor_assert(digest_sha256
!= NULL
);
511 if (descs_dumped
== NULL
) {
512 /* We better have no length, then */
513 tor_assert(len_descs_dumped
== 0);
514 /* Make a smartlist */
515 descs_dumped
= smartlist_new();
518 /* Make a new entry to put this one in */
519 ent
= tor_malloc_zero(sizeof(*ent
));
520 ent
->filename
= filename
;
522 ent
->when
= time(NULL
);
523 memcpy(ent
->digest_sha256
, digest_sha256
, DIGEST256_LEN
);
525 /* Do we need to do some cleanup? */
526 max_len
= get_options()->MaxUnparseableDescSizeToLog
;
527 /* Iterate over the list until we've freed enough space */
528 while (len
> max_len
- len_descs_dumped
&&
529 smartlist_len(descs_dumped
) > 0) {
530 /* Get the oldest thing on the list */
531 tmp
= (dumped_desc_t
*)(smartlist_get(descs_dumped
, 0));
534 * Check if it matches the filename we just added, so we don't delete
535 * something we just emitted if we get repeated identical descriptors.
537 if (strcmp(tmp
->filename
, filename
) != 0) {
538 /* Delete it and adjust the length counter */
539 tor_unlink(tmp
->filename
);
540 tor_assert(len_descs_dumped
>= tmp
->len
);
541 len_descs_dumped
-= tmp
->len
;
543 "Deleting old unparseable descriptor dump %s due to "
548 * Don't delete, but do adjust the counter since we will bump it
551 tor_assert(len_descs_dumped
>= tmp
->len
);
552 len_descs_dumped
-= tmp
->len
;
554 "Replacing old descriptor dump %s with new identical one",
558 /* Free it and remove it from the list */
559 smartlist_del_keeporder(descs_dumped
, 0);
560 tor_free(tmp
->filename
);
564 /* Append our entry to the end of the list and bump the counter */
565 smartlist_add(descs_dumped
, ent
);
566 len_descs_dumped
+= len
;
569 /** Check if we already have a descriptor for this hash and move it to the
570 * head of the queue if so. Return 1 if one existed and 0 otherwise.
573 dump_desc_fifo_bump_hash(const uint8_t *digest_sha256
)
575 dumped_desc_t
*match
= NULL
;
577 tor_assert(digest_sha256
);
580 /* Find a match if one exists */
581 SMARTLIST_FOREACH_BEGIN(descs_dumped
, dumped_desc_t
*, ent
) {
583 tor_memeq(ent
->digest_sha256
, digest_sha256
, DIGEST256_LEN
)) {
585 * Save a pointer to the match and remove it from its current
589 SMARTLIST_DEL_CURRENT_KEEPORDER(descs_dumped
, ent
);
592 } SMARTLIST_FOREACH_END(ent
);
595 /* Update the timestamp */
596 match
->when
= time(NULL
);
597 /* Add it back at the end of the list */
598 smartlist_add(descs_dumped
, match
);
600 /* Indicate we found one */
608 /** Clean up on exit; just memory, leave the dumps behind
611 dump_desc_fifo_cleanup(void)
614 /* Free each descriptor */
615 SMARTLIST_FOREACH_BEGIN(descs_dumped
, dumped_desc_t
*, ent
) {
617 tor_free(ent
->filename
);
619 } SMARTLIST_FOREACH_END(ent
);
621 smartlist_free(descs_dumped
);
623 len_descs_dumped
= 0;
627 /** Handle one file for dump_desc_populate_fifo_from_directory(); make sure
628 * the filename is sensibly formed and matches the file content, and either
629 * return a dumped_desc_t for it or remove the file and return NULL.
631 MOCK_IMPL(STATIC dumped_desc_t
*,
632 dump_desc_populate_one_file
, (const char *dirname
, const char *f
))
634 dumped_desc_t
*ent
= NULL
;
635 char *path
= NULL
, *desc
= NULL
;
636 const char *digest_str
;
637 char digest
[DIGEST256_LEN
], content_digest
[DIGEST256_LEN
];
638 /* Expected prefix before digest in filenames */
639 const char *f_pfx
= DESC_DUMP_BASE_FILENAME
".";
641 * Stat while reading; this is important in case the file
642 * contains a NUL character.
646 /* Sanity-check args */
647 tor_assert(dirname
!= NULL
);
648 tor_assert(f
!= NULL
);
650 /* Form the full path */
651 tor_asprintf(&path
, "%s" PATH_SEPARATOR
"%s", dirname
, f
);
653 /* Check that f has the form DESC_DUMP_BASE_FILENAME.<digest256> */
655 if (!strcmpstart(f
, f_pfx
)) {
656 /* It matches the form, but is the digest parseable as such? */
657 digest_str
= f
+ strlen(f_pfx
);
658 if (base16_decode(digest
, DIGEST256_LEN
,
659 digest_str
, strlen(digest_str
)) != DIGEST256_LEN
) {
660 /* We failed to decode it */
669 /* We couldn't get a sensible digest */
671 "Removing unrecognized filename %s from unparseable "
672 "descriptors directory", f
);
679 * The filename has the form DESC_DUMP_BASE_FILENAME "." <digest256> and
680 * we've decoded the digest. Next, check that we can read it and the
681 * content matches this digest. We are relying on the fact that if the
682 * file contains a '\0', read_file_to_str() will allocate space for and
683 * read the entire file and return the correct size in st.
685 desc
= read_file_to_str(path
, RFTS_IGNORE_MISSING
|RFTS_BIN
, &st
);
687 /* We couldn't read it */
689 "Failed to read %s from unparseable descriptors directory; "
690 "attempting to remove it.", f
);
696 #if SIZE_MAX > UINT64_MAX
697 if (BUG((uint64_t)st
.st_size
> (uint64_t)SIZE_MAX
)) {
699 * Should be impossible since RFTS above should have failed to read the
700 * huge file into RAM. */
704 #endif /* SIZE_MAX > UINT64_MAX */
705 if (BUG(st
.st_size
< 0)) {
707 * Should be impossible, since the OS isn't supposed to be b0rken. */
711 /* (Now we can be sure that st.st_size is safe to cast to a size_t.) */
714 * We got one; now compute its digest and check that it matches the
717 if (crypto_digest256((char *)content_digest
, desc
, (size_t) st
.st_size
,
718 DIGEST_SHA256
) < 0) {
719 /* Weird, but okay */
721 "Unable to hash content of %s from unparseable descriptors "
728 /* Compare the digests */
729 if (tor_memneq(digest
, content_digest
, DIGEST256_LEN
)) {
732 "Hash of %s from unparseable descriptors directory didn't "
733 "match its filename; removing it", f
);
739 /* Okay, it's a match, we should prepare ent */
740 ent
= tor_malloc_zero(sizeof(dumped_desc_t
));
741 ent
->filename
= path
;
742 memcpy(ent
->digest_sha256
, digest
, DIGEST256_LEN
);
743 ent
->len
= (size_t) st
.st_size
;
744 ent
->when
= st
.st_mtime
;
745 /* Null out path so we don't free it out from under ent */
749 /* Free allocations if we had them */
756 /** Sort helper for dump_desc_populate_fifo_from_directory(); compares
757 * the when field of dumped_desc_ts in a smartlist to put the FIFO in
758 * the correct order after reconstructing it from the directory.
761 dump_desc_compare_fifo_entries(const void **a_v
, const void **b_v
)
763 const dumped_desc_t
**a
= (const dumped_desc_t
**)a_v
;
764 const dumped_desc_t
**b
= (const dumped_desc_t
**)b_v
;
766 if ((a
!= NULL
) && (*a
!= NULL
)) {
767 if ((b
!= NULL
) && (*b
!= NULL
)) {
768 /* We have sensible dumped_desc_ts to compare */
769 if ((*a
)->when
< (*b
)->when
) {
771 } else if ((*a
)->when
== (*b
)->when
) {
778 * We shouldn't see this, but what the hell, NULLs precede everythin
788 /** Scan the contents of the directory, and update FIFO/counters; this will
789 * consistency-check descriptor dump filenames against hashes of descriptor
790 * dump file content, and remove any inconsistent/unreadable dumps, and then
791 * reconstruct the dump FIFO as closely as possible for the last time the
792 * tor process shut down. If a previous dump was repeated more than once and
793 * moved ahead in the FIFO, the mtime will not have been updated and the
794 * reconstructed order will be wrong, but will always be a permutation of
798 dump_desc_populate_fifo_from_directory(const char *dirname
)
800 smartlist_t
*files
= NULL
;
801 dumped_desc_t
*ent
= NULL
;
803 tor_assert(dirname
!= NULL
);
805 /* Get a list of files */
806 files
= tor_listdir(dirname
);
809 "Unable to get contents of unparseable descriptor dump "
816 * Iterate through the list and decide which files should go in the
817 * FIFO and which should be purged.
820 SMARTLIST_FOREACH_BEGIN(files
, char *, f
) {
821 /* Try to get a FIFO entry */
822 ent
= dump_desc_populate_one_file(dirname
, f
);
825 * We got one; add it to the FIFO. No need for duplicate checking
826 * here since we just verified the name and digest match.
829 /* Make sure we have a list to add it to */
831 descs_dumped
= smartlist_new();
832 len_descs_dumped
= 0;
835 /* Add it and adjust the counter */
836 smartlist_add(descs_dumped
, ent
);
837 len_descs_dumped
+= ent
->len
;
840 * If we didn't, we will have unlinked the file if necessary and
841 * possible, and emitted a log message about it, so just go on to
844 } SMARTLIST_FOREACH_END(f
);
846 /* Did we get anything? */
847 if (descs_dumped
!= NULL
) {
848 /* Sort the FIFO in order of increasing timestamp */
849 smartlist_sort(descs_dumped
, dump_desc_compare_fifo_entries
);
853 "Reloaded unparseable descriptor dump FIFO with %d dump(s) "
854 "totaling " U64_FORMAT
" bytes",
855 smartlist_len(descs_dumped
), U64_PRINTF_ARG(len_descs_dumped
));
858 /* Free the original list */
859 SMARTLIST_FOREACH(files
, char *, f
, tor_free(f
));
860 smartlist_free(files
);
863 /** For debugging purposes, dump unparseable descriptor *<b>desc</b> of
864 * type *<b>type</b> to file $DATADIR/unparseable-desc. Do not write more
865 * than one descriptor to disk per minute. If there is already such a
866 * file in the data directory, overwrite it. */
867 MOCK_IMPL(STATIC
void,
868 dump_desc
,(const char *desc
, const char *type
))
873 /* The SHA256 of the string */
874 uint8_t digest_sha256
[DIGEST256_LEN
];
875 char digest_sha256_hex
[HEX_DIGEST256_LEN
+1];
876 /* Filename to log it to */
877 char *debugfile
, *debugfile_base
;
879 /* Get the hash for logging purposes anyway */
881 if (crypto_digest256((char *)digest_sha256
, desc
, len
,
882 DIGEST_SHA256
) < 0) {
884 "Unable to parse descriptor of type %s, and unable to even hash"
889 base16_encode(digest_sha256_hex
, sizeof(digest_sha256_hex
),
890 (const char *)digest_sha256
, sizeof(digest_sha256
));
893 * We mention type and hash in the main log; don't clutter up the files
894 * with anything but the exact dump.
896 tor_asprintf(&debugfile_base
,
897 DESC_DUMP_BASE_FILENAME
".%s", digest_sha256_hex
);
898 debugfile
= get_datadir_fname2(DESC_DUMP_DATADIR_SUBDIR
, debugfile_base
);
901 * Check if the sandbox is active or will become active; see comment
902 * below at the log message for why.
904 if (!(sandbox_is_active() || get_options()->Sandbox
)) {
905 if (len
<= get_options()->MaxUnparseableDescSizeToLog
) {
906 if (!dump_desc_fifo_bump_hash(digest_sha256
)) {
907 /* Create the directory if needed */
908 dump_desc_create_dir();
909 /* Make sure we've got it */
910 if (have_dump_desc_dir
&& !problem_with_dump_desc_dir
) {
911 /* Write it, and tell the main log about it */
912 write_str_to_file(debugfile
, desc
, 1);
914 "Unable to parse descriptor of type %s with hash %s and "
915 "length %lu. See file %s in data directory for details.",
916 type
, digest_sha256_hex
, (unsigned long)len
,
918 dump_desc_fifo_add_and_clean(debugfile
, digest_sha256
, len
);
919 /* Since we handed ownership over, don't free debugfile later */
922 /* Problem with the subdirectory */
924 "Unable to parse descriptor of type %s with hash %s and "
925 "length %lu. Descriptor not dumped because we had a "
926 "problem creating the " DESC_DUMP_DATADIR_SUBDIR
928 type
, digest_sha256_hex
, (unsigned long)len
);
929 /* We do have to free debugfile in this case */
932 /* We already had one with this hash dumped */
934 "Unable to parse descriptor of type %s with hash %s and "
935 "length %lu. Descriptor not dumped because one with that "
936 "hash has already been dumped.",
937 type
, digest_sha256_hex
, (unsigned long)len
);
938 /* We do have to free debugfile in this case */
941 /* Just log that it happened without dumping */
943 "Unable to parse descriptor of type %s with hash %s and "
944 "length %lu. Descriptor not dumped because it exceeds maximum"
945 " log size all by itself.",
946 type
, digest_sha256_hex
, (unsigned long)len
);
947 /* We do have to free debugfile in this case */
951 * Not logging because the sandbox is active and seccomp2 apparently
952 * doesn't have a sensible way to allow filenames according to a pattern
953 * match. (If we ever figure out how to say "allow writes to /regex/",
954 * remove this checK).
957 "Unable to parse descriptor of type %s with hash %s and "
958 "length %lu. Descriptor not dumped because the sandbox is "
960 type
, digest_sha256_hex
, (unsigned long)len
);
963 tor_free(debugfile_base
);
970 /** Set <b>digest</b> to the SHA-1 digest of the hash of the directory in
971 * <b>s</b>. Return 0 on success, -1 on failure.
974 router_get_dir_hash(const char *s
, char *digest
)
976 return router_get_hash_impl(s
, strlen(s
), digest
,
977 "signed-directory","\ndirectory-signature",'\n',
981 /** Set <b>digest</b> to the SHA-1 digest of the hash of the first router in
982 * <b>s</b>. Return 0 on success, -1 on failure.
985 router_get_router_hash(const char *s
, size_t s_len
, char *digest
)
987 return router_get_hash_impl(s
, s_len
, digest
,
988 "router ","\nrouter-signature", '\n',
992 /** Try to find the start and end of the signed portion of a networkstatus
993 * document in <b>s</b>. On success, set <b>start_out</b> to the first
994 * character of the document, and <b>end_out</b> to a position one after the
995 * final character of the signed document, and return 0. On failure, return
998 router_get_networkstatus_v3_signed_boundaries(const char *s
,
999 const char **start_out
,
1000 const char **end_out
)
1002 return router_get_hash_impl_helper(s
, strlen(s
),
1003 "network-status-version",
1004 "\ndirectory-signature",
1006 start_out
, end_out
);
1009 /** Set <b>digest_out</b> to the SHA3-256 digest of the signed portion of the
1010 * networkstatus vote in <b>s</b> -- or of the entirety of <b>s</b> if no
1011 * signed portion can be identified. Return 0 on success, -1 on failure. */
1013 router_get_networkstatus_v3_sha3_as_signed(uint8_t *digest_out
,
1016 const char *start
, *end
;
1017 if (router_get_networkstatus_v3_signed_boundaries(s
, &start
, &end
) < 0) {
1019 end
= s
+ strlen(s
);
1023 return crypto_digest256((char*)digest_out
, start
, end
-start
,
1027 /** Set <b>digests</b> to all the digests of the consensus document in
1030 router_get_networkstatus_v3_hashes(const char *s
, common_digests_t
*digests
)
1032 return router_get_hashes_impl(s
,strlen(s
),digests
,
1033 "network-status-version",
1034 "\ndirectory-signature",
1038 /** Set <b>digest</b> to the SHA-1 digest of the hash of the <b>s_len</b>-byte
1039 * extrainfo string at <b>s</b>. Return 0 on success, -1 on failure. */
1041 router_get_extrainfo_hash(const char *s
, size_t s_len
, char *digest
)
1043 return router_get_hash_impl(s
, s_len
, digest
, "extra-info",
1044 "\nrouter-signature",'\n', DIGEST_SHA1
);
1047 /** Helper: used to generate signatures for routers, directories and
1048 * network-status objects. Given a <b>digest_len</b>-byte digest in
1049 * <b>digest</b> and a secret <b>private_key</b>, generate an PKCS1-padded
1050 * signature, BASE64-encode it, surround it with -----BEGIN/END----- pairs,
1051 * and return the new signature on success or NULL on failure.
1054 router_get_dirobj_signature(const char *digest
,
1056 const crypto_pk_t
*private_key
)
1063 /* overestimate of BEGIN/END lines total len. */
1064 #define BEGIN_END_OVERHEAD_LEN 64
1066 keysize
= crypto_pk_keysize(private_key
);
1067 signature
= tor_malloc(keysize
);
1068 siglen
= crypto_pk_private_sign(private_key
, signature
, keysize
,
1069 digest
, digest_len
);
1071 log_warn(LD_BUG
,"Couldn't sign digest.");
1075 /* The *2 here is a ridiculous overestimate of base-64 overhead. */
1076 buf_len
= (siglen
* 2) + BEGIN_END_OVERHEAD_LEN
;
1077 buf
= tor_malloc(buf_len
);
1079 if (strlcpy(buf
, "-----BEGIN SIGNATURE-----\n", buf_len
) >= buf_len
)
1083 if (base64_encode(buf
+i
, buf_len
-i
, signature
, siglen
,
1084 BASE64_ENCODE_MULTILINE
) < 0) {
1085 log_warn(LD_BUG
,"couldn't base64-encode signature");
1089 if (strlcat(buf
, "-----END SIGNATURE-----\n", buf_len
) >= buf_len
)
1092 tor_free(signature
);
1096 log_warn(LD_BUG
,"tried to exceed string length.");
1098 tor_free(signature
);
1103 /** Helper: used to generate signatures for routers, directories and
1104 * network-status objects. Given a digest in <b>digest</b> and a secret
1105 * <b>private_key</b>, generate a PKCS1-padded signature, BASE64-encode it,
1106 * surround it with -----BEGIN/END----- pairs, and write it to the
1107 * <b>buf_len</b>-byte buffer at <b>buf</b>. Return 0 on success, -1 on
1111 router_append_dirobj_signature(char *buf
, size_t buf_len
, const char *digest
,
1112 size_t digest_len
, crypto_pk_t
*private_key
)
1114 size_t sig_len
, s_len
;
1115 char *sig
= router_get_dirobj_signature(digest
, digest_len
, private_key
);
1117 log_warn(LD_BUG
, "No signature generated");
1120 sig_len
= strlen(sig
);
1121 s_len
= strlen(buf
);
1122 if (sig_len
+ s_len
+ 1 > buf_len
) {
1123 log_warn(LD_BUG
, "Not enough room for signature");
1127 memcpy(buf
+s_len
, sig
, sig_len
+1);
1132 /** Return VS_RECOMMENDED if <b>myversion</b> is contained in
1133 * <b>versionlist</b>. Else, return VS_EMPTY if versionlist has no
1134 * entries. Else, return VS_OLD if every member of
1135 * <b>versionlist</b> is newer than <b>myversion</b>. Else, return
1136 * VS_NEW_IN_SERIES if there is at least one member of <b>versionlist</b> in
1137 * the same series (major.minor.micro) as <b>myversion</b>, but no such member
1138 * is newer than <b>myversion.</b>. Else, return VS_NEW if every member of
1139 * <b>versionlist</b> is older than <b>myversion</b>. Else, return
1142 * (versionlist is a comma-separated list of version strings,
1143 * optionally prefixed with "Tor". Versions that can't be parsed are
1147 tor_version_is_obsolete(const char *myversion
, const char *versionlist
)
1149 tor_version_t mine
, other
;
1150 int found_newer
= 0, found_older
= 0, found_newer_in_series
= 0,
1151 found_any_in_series
= 0, r
, same
;
1152 version_status_t ret
= VS_UNRECOMMENDED
;
1153 smartlist_t
*version_sl
;
1155 log_debug(LD_CONFIG
,"Checking whether version '%s' is in '%s'",
1156 myversion
, versionlist
);
1158 if (tor_version_parse(myversion
, &mine
)) {
1159 log_err(LD_BUG
,"I couldn't parse my own version (%s)", myversion
);
1162 version_sl
= smartlist_new();
1163 smartlist_split_string(version_sl
, versionlist
, ",", SPLIT_SKIP_SPACE
, 0);
1165 if (!strlen(versionlist
)) { /* no authorities cared or agreed */
1170 SMARTLIST_FOREACH_BEGIN(version_sl
, const char *, cp
) {
1171 if (!strcmpstart(cp
, "Tor "))
1174 if (tor_version_parse(cp
, &other
)) {
1175 /* Couldn't parse other; it can't be a match. */
1177 same
= tor_version_same_series(&mine
, &other
);
1179 found_any_in_series
= 1;
1180 r
= tor_version_compare(&mine
, &other
);
1182 ret
= VS_RECOMMENDED
;
1187 found_newer_in_series
= 1;
1192 } SMARTLIST_FOREACH_END(cp
);
1194 /* We didn't find the listed version. Is it new or old? */
1195 if (found_any_in_series
&& !found_newer_in_series
&& found_newer
) {
1196 ret
= VS_NEW_IN_SERIES
;
1197 } else if (found_newer
&& !found_older
) {
1199 } else if (found_older
&& !found_newer
) {
1202 ret
= VS_UNRECOMMENDED
;
1206 SMARTLIST_FOREACH(version_sl
, char *, version
, tor_free(version
));
1207 smartlist_free(version_sl
);
1211 MOCK_IMPL(STATIC
int,
1212 signed_digest_equals
, (const uint8_t *d1
, const uint8_t *d2
, size_t len
))
1214 return tor_memeq(d1
, d2
, len
);
1217 /** Check whether the object body of the token in <b>tok</b> has a good
1218 * signature for <b>digest</b> using key <b>pkey</b>.
1219 * If <b>CST_NO_CHECK_OBJTYPE</b> is set, do not check
1220 * the object type of the signature object. Use <b>doctype</b> as the type of
1221 * the document when generating log messages. Return 0 on success, negative
1225 check_signature_token(const char *digest
,
1227 directory_token_t
*tok
,
1230 const char *doctype
)
1232 char *signed_digest
;
1234 const int check_objtype
= ! (flags
& CST_NO_CHECK_OBJTYPE
);
1239 tor_assert(doctype
);
1241 if (check_objtype
) {
1242 if (strcmp(tok
->object_type
, "SIGNATURE")) {
1243 log_warn(LD_DIR
, "Bad object type on %s signature", doctype
);
1248 keysize
= crypto_pk_keysize(pkey
);
1249 signed_digest
= tor_malloc(keysize
);
1250 if (crypto_pk_public_checksig(pkey
, signed_digest
, keysize
,
1251 tok
->object_body
, tok
->object_size
)
1253 log_warn(LD_DIR
, "Error reading %s: invalid signature.", doctype
);
1254 tor_free(signed_digest
);
1257 // log_debug(LD_DIR,"Signed %s hash starts %s", doctype,
1258 // hex_str(signed_digest,4));
1259 if (! signed_digest_equals((const uint8_t *)digest
,
1260 (const uint8_t *)signed_digest
, digest_len
)) {
1261 log_warn(LD_DIR
, "Error reading %s: signature does not match.", doctype
);
1262 tor_free(signed_digest
);
1265 tor_free(signed_digest
);
1269 /** Helper: move *<b>s_ptr</b> ahead to the next router, the next extra-info,
1270 * or to the first of the annotations proceeding the next router or
1271 * extra-info---whichever comes first. Set <b>is_extrainfo_out</b> to true if
1272 * we found an extrainfo, or false if found a router. Do not scan beyond
1273 * <b>eos</b>. Return -1 if we found nothing; 0 if we found something. */
1275 find_start_of_next_router_or_extrainfo(const char **s_ptr
,
1277 int *is_extrainfo_out
)
1279 const char *annotations
= NULL
;
1280 const char *s
= *s_ptr
;
1282 s
= eat_whitespace_eos(s
, eos
);
1284 while (s
< eos
-32) { /* 32 gives enough room for a the first keyword. */
1285 /* We're at the start of a line. */
1286 tor_assert(*s
!= '\n');
1288 if (*s
== '@' && !annotations
) {
1290 } else if (*s
== 'r' && !strcmpstart(s
, "router ")) {
1291 *s_ptr
= annotations
? annotations
: s
;
1292 *is_extrainfo_out
= 0;
1294 } else if (*s
== 'e' && !strcmpstart(s
, "extra-info ")) {
1295 *s_ptr
= annotations
? annotations
: s
;
1296 *is_extrainfo_out
= 1;
1300 if (!(s
= memchr(s
+1, '\n', eos
-(s
+1))))
1302 s
= eat_whitespace_eos(s
, eos
);
1307 /** Given a string *<b>s</b> containing a concatenated sequence of router
1308 * descriptors (or extra-info documents if <b>is_extrainfo</b> is set), parses
1309 * them and stores the result in <b>dest</b>. All routers are marked running
1310 * and valid. Advances *s to a point immediately following the last router
1311 * entry. Ignore any trailing router entries that are not complete.
1313 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
1314 * descriptor in the signed_descriptor_body field of each routerinfo_t. If it
1315 * isn't SAVED_NOWHERE, remember the offset of each descriptor.
1317 * Returns 0 on success and -1 on failure. Adds a digest to
1318 * <b>invalid_digests_out</b> for every entry that was unparseable or
1319 * invalid. (This may cause duplicate entries.)
1322 router_parse_list_from_string(const char **s
, const char *eos
,
1324 saved_location_t saved_location
,
1326 int allow_annotations
,
1327 const char *prepend_annotations
,
1328 smartlist_t
*invalid_digests_out
)
1330 routerinfo_t
*router
;
1331 extrainfo_t
*extrainfo
;
1332 signed_descriptor_t
*signed_desc
= NULL
;
1334 const char *end
, *start
;
1343 eos
= *s
+ strlen(*s
);
1345 tor_assert(eos
>= *s
);
1348 char raw_digest
[DIGEST_LEN
];
1349 int have_raw_digest
= 0;
1351 if (find_start_of_next_router_or_extrainfo(s
, eos
, &have_extrainfo
) < 0)
1354 end
= tor_memstr(*s
, eos
-*s
, "\nrouter-signature");
1356 end
= tor_memstr(end
, eos
-end
, "\n-----END SIGNATURE-----\n");
1358 end
+= strlen("\n-----END SIGNATURE-----\n");
1365 if (have_extrainfo
&& want_extrainfo
) {
1366 routerlist_t
*rl
= router_get_routerlist();
1367 have_raw_digest
= router_get_extrainfo_hash(*s
, end
-*s
, raw_digest
) == 0;
1368 extrainfo
= extrainfo_parse_entry_from_string(*s
, end
,
1369 saved_location
!= SAVED_IN_CACHE
,
1370 rl
->identity_map
, &dl_again
);
1372 signed_desc
= &extrainfo
->cache_info
;
1375 } else if (!have_extrainfo
&& !want_extrainfo
) {
1376 have_raw_digest
= router_get_router_hash(*s
, end
-*s
, raw_digest
) == 0;
1377 router
= router_parse_entry_from_string(*s
, end
,
1378 saved_location
!= SAVED_IN_CACHE
,
1380 prepend_annotations
, &dl_again
);
1382 log_debug(LD_DIR
, "Read router '%s', purpose '%s'",
1383 router_describe(router
),
1384 router_purpose_to_string(router
->purpose
));
1385 signed_desc
= &router
->cache_info
;
1389 if (! elt
&& ! dl_again
&& have_raw_digest
&& invalid_digests_out
) {
1390 smartlist_add(invalid_digests_out
, tor_memdup(raw_digest
, DIGEST_LEN
));
1396 if (saved_location
!= SAVED_NOWHERE
) {
1397 tor_assert(signed_desc
);
1398 signed_desc
->saved_location
= saved_location
;
1399 signed_desc
->saved_offset
= *s
- start
;
1402 smartlist_add(dest
, elt
);
1408 /* For debugging: define to count every descriptor digest we've seen so we
1409 * know if we need to try harder to avoid duplicate verifies. */
1410 #undef COUNT_DISTINCT_DIGESTS
1412 #ifdef COUNT_DISTINCT_DIGESTS
1413 static digestmap_t
*verified_digests
= NULL
;
1416 /** Log the total count of the number of distinct router digests we've ever
1417 * verified. When compared to the number of times we've verified routerdesc
1418 * signatures <i>in toto</i>, this will tell us if we're doing too much
1419 * multiple-verification. */
1421 dump_distinct_digest_count(int severity
)
1423 #ifdef COUNT_DISTINCT_DIGESTS
1424 if (!verified_digests
)
1425 verified_digests
= digestmap_new();
1426 tor_log(severity
, LD_GENERAL
, "%d *distinct* router digests verified",
1427 digestmap_size(verified_digests
));
1428 #else /* !(defined(COUNT_DISTINCT_DIGESTS)) */
1429 (void)severity
; /* suppress "unused parameter" warning */
1430 #endif /* defined(COUNT_DISTINCT_DIGESTS) */
1433 /** Try to find an IPv6 OR port in <b>list</b> of directory_token_t's
1434 * with at least one argument (use GE(1) in setup). If found, store
1435 * address and port number to <b>addr_out</b> and
1436 * <b>port_out</b>. Return number of OR ports found. */
1438 find_single_ipv6_orport(const smartlist_t
*list
,
1439 tor_addr_t
*addr_out
,
1443 tor_assert(list
!= NULL
);
1444 tor_assert(addr_out
!= NULL
);
1445 tor_assert(port_out
!= NULL
);
1447 SMARTLIST_FOREACH_BEGIN(list
, directory_token_t
*, t
) {
1450 uint16_t port_min
, port_max
;
1451 tor_assert(t
->n_args
>= 1);
1452 /* XXXX Prop186 the full spec allows much more than this. */
1453 if (tor_addr_parse_mask_ports(t
->args
[0], 0,
1454 &a
, &bits
, &port_min
,
1455 &port_max
) == AF_INET6
&&
1457 port_min
== port_max
) {
1458 /* Okay, this is one we can understand. Use it and ignore
1459 any potential more addresses in list. */
1460 tor_addr_copy(addr_out
, &a
);
1461 *port_out
= port_min
;
1465 } SMARTLIST_FOREACH_END(t
);
1470 /** Helper function: reads a single router entry from *<b>s</b> ...
1471 * *<b>end</b>. Mallocs a new router and returns it if all goes well, else
1472 * returns NULL. If <b>cache_copy</b> is true, duplicate the contents of
1473 * s through end into the signed_descriptor_body of the resulting
1476 * If <b>end</b> is NULL, <b>s</b> must be properly NUL-terminated.
1478 * If <b>allow_annotations</b>, it's okay to encounter annotations in <b>s</b>
1479 * before the router; if it's false, reject the router if it's annotated. If
1480 * <b>prepend_annotations</b> is set, it should contain some annotations:
1481 * append them to the front of the router before parsing it, and keep them
1482 * around when caching the router.
1484 * Only one of allow_annotations and prepend_annotations may be set.
1486 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
1487 * if it's okay to try to download a descriptor with this same digest again,
1488 * and 0 if it isn't. (It might not be okay to download it again if part of
1489 * the part covered by the digest is invalid.)
1492 router_parse_entry_from_string(const char *s
, const char *end
,
1493 int cache_copy
, int allow_annotations
,
1494 const char *prepend_annotations
,
1495 int *can_dl_again_out
)
1497 routerinfo_t
*router
= NULL
;
1499 smartlist_t
*tokens
= NULL
, *exit_policy_tokens
= NULL
;
1500 directory_token_t
*tok
;
1502 const char *start_of_annotations
, *cp
, *s_dup
= s
;
1503 size_t prepend_len
= prepend_annotations
? strlen(prepend_annotations
) : 0;
1505 memarea_t
*area
= NULL
;
1506 tor_cert_t
*ntor_cc_cert
= NULL
;
1507 /* Do not set this to '1' until we have parsed everything that we intend to
1508 * parse that's covered by the hash. */
1509 int can_dl_again
= 0;
1511 tor_assert(!allow_annotations
|| !prepend_annotations
);
1514 end
= s
+ strlen(s
);
1517 /* point 'end' to a point immediately after the final newline. */
1518 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
1521 area
= memarea_new();
1522 tokens
= smartlist_new();
1523 if (prepend_annotations
) {
1524 if (tokenize_string(area
,prepend_annotations
,NULL
,tokens
,
1525 routerdesc_token_table
,TS_NOCHECK
)) {
1526 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1531 start_of_annotations
= s
;
1532 cp
= tor_memstr(s
, end
-s
, "\nrouter ");
1534 if (end
-s
< 7 || strcmpstart(s
, "router ")) {
1535 log_warn(LD_DIR
, "No router keyword found.");
1542 if (start_of_annotations
!= s
) { /* We have annotations */
1543 if (allow_annotations
) {
1544 if (tokenize_string(area
,start_of_annotations
,s
,tokens
,
1545 routerdesc_token_table
,TS_NOCHECK
)) {
1546 log_warn(LD_DIR
, "Error tokenizing router descriptor (annotations).");
1550 log_warn(LD_DIR
, "Found unexpected annotations on router descriptor not "
1551 "loaded from disk. Dropping it.");
1556 if (router_get_router_hash(s
, end
- s
, digest
) < 0) {
1557 log_warn(LD_DIR
, "Couldn't compute router hash.");
1562 if (allow_annotations
)
1563 flags
|= TS_ANNOTATIONS_OK
;
1564 if (prepend_annotations
)
1565 flags
|= TS_ANNOTATIONS_OK
|TS_NO_NEW_ANNOTATIONS
;
1567 if (tokenize_string(area
,s
,end
,tokens
,routerdesc_token_table
, flags
)) {
1568 log_warn(LD_DIR
, "Error tokenizing router descriptor.");
1573 if (smartlist_len(tokens
) < 2) {
1574 log_warn(LD_DIR
, "Impossibly short router descriptor.");
1578 tok
= find_by_keyword(tokens
, K_ROUTER
);
1579 const int router_token_pos
= smartlist_pos(tokens
, tok
);
1580 tor_assert(tok
->n_args
>= 5);
1582 router
= tor_malloc_zero(sizeof(routerinfo_t
));
1583 router
->cert_expiration_time
= TIME_MAX
;
1584 router
->cache_info
.routerlist_index
= -1;
1585 router
->cache_info
.annotations_len
= s
-start_of_annotations
+ prepend_len
;
1586 router
->cache_info
.signed_descriptor_len
= end
-s
;
1588 size_t len
= router
->cache_info
.signed_descriptor_len
+
1589 router
->cache_info
.annotations_len
;
1591 router
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
1592 if (prepend_annotations
) {
1593 memcpy(signed_body
, prepend_annotations
, prepend_len
);
1594 signed_body
+= prepend_len
;
1596 /* This assertion will always succeed.
1597 * len == signed_desc_len + annotations_len
1598 * == end-s + s-start_of_annotations + prepend_len
1599 * == end-start_of_annotations + prepend_len
1600 * We already wrote prepend_len bytes into the buffer; now we're
1601 * writing end-start_of_annotations -NM. */
1602 tor_assert(signed_body
+(end
-start_of_annotations
) ==
1603 router
->cache_info
.signed_descriptor_body
+len
);
1604 memcpy(signed_body
, start_of_annotations
, end
-start_of_annotations
);
1605 router
->cache_info
.signed_descriptor_body
[len
] = '\0';
1606 tor_assert(strlen(router
->cache_info
.signed_descriptor_body
) == len
);
1608 memcpy(router
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
1610 router
->nickname
= tor_strdup(tok
->args
[0]);
1611 if (!is_legal_nickname(router
->nickname
)) {
1612 log_warn(LD_DIR
,"Router nickname is invalid");
1615 if (!tor_inet_aton(tok
->args
[1], &in
)) {
1616 log_warn(LD_DIR
,"Router address is not an IP address.");
1619 router
->addr
= ntohl(in
.s_addr
);
1622 (uint16_t) tor_parse_long(tok
->args
[2],10,0,65535,&ok
,NULL
);
1624 log_warn(LD_DIR
,"Invalid OR port %s", escaped(tok
->args
[2]));
1628 (uint16_t) tor_parse_long(tok
->args
[4],10,0,65535,&ok
,NULL
);
1630 log_warn(LD_DIR
,"Invalid dir port %s", escaped(tok
->args
[4]));
1634 tok
= find_by_keyword(tokens
, K_BANDWIDTH
);
1635 tor_assert(tok
->n_args
>= 3);
1636 router
->bandwidthrate
= (int)
1637 tor_parse_long(tok
->args
[0],10,1,INT_MAX
,&ok
,NULL
);
1640 log_warn(LD_DIR
, "bandwidthrate %s unreadable or 0. Failing.",
1641 escaped(tok
->args
[0]));
1644 router
->bandwidthburst
=
1645 (int) tor_parse_long(tok
->args
[1],10,0,INT_MAX
,&ok
,NULL
);
1647 log_warn(LD_DIR
, "Invalid bandwidthburst %s", escaped(tok
->args
[1]));
1650 router
->bandwidthcapacity
= (int)
1651 tor_parse_long(tok
->args
[2],10,0,INT_MAX
,&ok
,NULL
);
1653 log_warn(LD_DIR
, "Invalid bandwidthcapacity %s", escaped(tok
->args
[1]));
1657 if ((tok
= find_opt_by_keyword(tokens
, A_PURPOSE
))) {
1658 tor_assert(tok
->n_args
);
1659 router
->purpose
= router_purpose_from_string(tok
->args
[0]);
1661 router
->purpose
= ROUTER_PURPOSE_GENERAL
;
1663 router
->cache_info
.send_unencrypted
=
1664 (router
->purpose
== ROUTER_PURPOSE_GENERAL
) ? 1 : 0;
1666 if ((tok
= find_opt_by_keyword(tokens
, K_UPTIME
))) {
1667 tor_assert(tok
->n_args
>= 1);
1668 router
->uptime
= tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,&ok
,NULL
);
1670 log_warn(LD_DIR
, "Invalid uptime %s", escaped(tok
->args
[0]));
1675 if ((tok
= find_opt_by_keyword(tokens
, K_HIBERNATING
))) {
1676 tor_assert(tok
->n_args
>= 1);
1677 router
->is_hibernating
1678 = (tor_parse_long(tok
->args
[0],10,0,LONG_MAX
,NULL
,NULL
) != 0);
1681 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
1682 tor_assert(tok
->n_args
== 1);
1683 if (parse_iso_time(tok
->args
[0], &router
->cache_info
.published_on
) < 0)
1686 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
1687 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
1689 "Relay's onion key had invalid exponent.");
1692 router
->onion_pkey
= tok
->key
;
1693 tok
->key
= NULL
; /* Prevent free */
1695 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
1696 curve25519_public_key_t k
;
1697 tor_assert(tok
->n_args
>= 1);
1698 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
1699 log_warn(LD_DIR
, "Bogus ntor-onion-key in routerinfo");
1702 router
->onion_curve25519_pkey
=
1703 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
1706 tok
= find_by_keyword(tokens
, K_SIGNING_KEY
);
1707 router
->identity_pkey
= tok
->key
;
1708 tok
->key
= NULL
; /* Prevent free */
1709 if (crypto_pk_get_digest(router
->identity_pkey
,
1710 router
->cache_info
.identity_digest
)) {
1711 log_warn(LD_DIR
, "Couldn't calculate key digest"); goto err
;
1715 directory_token_t
*ed_sig_tok
, *ed_cert_tok
, *cc_tap_tok
, *cc_ntor_tok
,
1717 ed_sig_tok
= find_opt_by_keyword(tokens
, K_ROUTER_SIG_ED25519
);
1718 ed_cert_tok
= find_opt_by_keyword(tokens
, K_IDENTITY_ED25519
);
1719 master_key_tok
= find_opt_by_keyword(tokens
, K_MASTER_KEY_ED25519
);
1720 cc_tap_tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_CROSSCERT
);
1721 cc_ntor_tok
= find_opt_by_keyword(tokens
, K_NTOR_ONION_KEY_CROSSCERT
);
1722 int n_ed_toks
= !!ed_sig_tok
+ !!ed_cert_tok
+
1723 !!cc_tap_tok
+ !!cc_ntor_tok
;
1724 if ((n_ed_toks
!= 0 && n_ed_toks
!= 4) ||
1725 (n_ed_toks
== 4 && !router
->onion_curve25519_pkey
)) {
1726 log_warn(LD_DIR
, "Router descriptor with only partial ed25519/"
1727 "cross-certification support");
1730 if (master_key_tok
&& !ed_sig_tok
) {
1731 log_warn(LD_DIR
, "Router descriptor has ed25519 master key but no "
1736 tor_assert(ed_cert_tok
&& cc_tap_tok
&& cc_ntor_tok
);
1737 const int ed_cert_token_pos
= smartlist_pos(tokens
, ed_cert_tok
);
1738 if (ed_cert_token_pos
== -1 || router_token_pos
== -1 ||
1739 (ed_cert_token_pos
!= router_token_pos
+ 1 &&
1740 ed_cert_token_pos
!= router_token_pos
- 1)) {
1741 log_warn(LD_DIR
, "Ed25519 certificate in wrong position");
1744 if (ed_sig_tok
!= smartlist_get(tokens
, smartlist_len(tokens
)-2)) {
1745 log_warn(LD_DIR
, "Ed25519 signature in wrong position");
1748 if (strcmp(ed_cert_tok
->object_type
, "ED25519 CERT")) {
1749 log_warn(LD_DIR
, "Wrong object type on identity-ed25519 in decriptor");
1752 if (strcmp(cc_ntor_tok
->object_type
, "ED25519 CERT")) {
1753 log_warn(LD_DIR
, "Wrong object type on ntor-onion-key-crosscert "
1757 if (strcmp(cc_tap_tok
->object_type
, "CROSSCERT")) {
1758 log_warn(LD_DIR
, "Wrong object type on onion-key-crosscert "
1762 if (strcmp(cc_ntor_tok
->args
[0], "0") &&
1763 strcmp(cc_ntor_tok
->args
[0], "1")) {
1764 log_warn(LD_DIR
, "Bad sign bit on ntor-onion-key-crosscert");
1767 int ntor_cc_sign_bit
= !strcmp(cc_ntor_tok
->args
[0], "1");
1769 uint8_t d256
[DIGEST256_LEN
];
1770 const char *signed_start
, *signed_end
;
1771 tor_cert_t
*cert
= tor_cert_parse(
1772 (const uint8_t*)ed_cert_tok
->object_body
,
1773 ed_cert_tok
->object_size
);
1775 log_warn(LD_DIR
, "Couldn't parse ed25519 cert");
1778 /* makes sure it gets freed. */
1779 router
->cache_info
.signing_key_cert
= cert
;
1781 if (cert
->cert_type
!= CERT_TYPE_ID_SIGNING
||
1782 ! cert
->signing_key_included
) {
1783 log_warn(LD_DIR
, "Invalid form for ed25519 cert");
1787 if (master_key_tok
) {
1788 /* This token is optional, but if it's present, it must match
1789 * the signature in the signing cert, or supplant it. */
1790 tor_assert(master_key_tok
->n_args
>= 1);
1791 ed25519_public_key_t pkey
;
1792 if (ed25519_public_from_base64(&pkey
, master_key_tok
->args
[0])<0) {
1793 log_warn(LD_DIR
, "Can't parse ed25519 master key");
1797 if (fast_memneq(&cert
->signing_key
.pubkey
,
1798 pkey
.pubkey
, ED25519_PUBKEY_LEN
)) {
1799 log_warn(LD_DIR
, "Ed25519 master key does not match "
1800 "key in certificate");
1804 ntor_cc_cert
= tor_cert_parse((const uint8_t*)cc_ntor_tok
->object_body
,
1805 cc_ntor_tok
->object_size
);
1806 if (!ntor_cc_cert
) {
1807 log_warn(LD_DIR
, "Couldn't parse ntor-onion-key-crosscert cert");
1810 if (ntor_cc_cert
->cert_type
!= CERT_TYPE_ONION_ID
||
1811 ! ed25519_pubkey_eq(&ntor_cc_cert
->signed_key
, &cert
->signing_key
)) {
1812 log_warn(LD_DIR
, "Invalid contents for ntor-onion-key-crosscert cert");
1816 ed25519_public_key_t ntor_cc_pk
;
1817 if (ed25519_public_key_from_curve25519_public_key(&ntor_cc_pk
,
1818 router
->onion_curve25519_pkey
,
1819 ntor_cc_sign_bit
)<0) {
1820 log_warn(LD_DIR
, "Error converting onion key to ed25519");
1824 if (router_get_hash_impl_helper(s
, end
-s
, "router ",
1825 "\nrouter-sig-ed25519",
1827 &signed_start
, &signed_end
) < 0) {
1828 log_warn(LD_DIR
, "Can't find ed25519-signed portion of descriptor");
1831 crypto_digest_t
*d
= crypto_digest256_new(DIGEST_SHA256
);
1832 crypto_digest_add_bytes(d
, ED_DESC_SIGNATURE_PREFIX
,
1833 strlen(ED_DESC_SIGNATURE_PREFIX
));
1834 crypto_digest_add_bytes(d
, signed_start
, signed_end
-signed_start
);
1835 crypto_digest_get_digest(d
, (char*)d256
, sizeof(d256
));
1836 crypto_digest_free(d
);
1838 ed25519_checkable_t check
[3];
1840 time_t expires
= TIME_MAX
;
1841 if (tor_cert_get_checkable_sig(&check
[0], cert
, NULL
, &expires
) < 0) {
1842 log_err(LD_BUG
, "Couldn't create 'checkable' for cert.");
1845 if (tor_cert_get_checkable_sig(&check
[1],
1846 ntor_cc_cert
, &ntor_cc_pk
, &expires
) < 0) {
1847 log_err(LD_BUG
, "Couldn't create 'checkable' for ntor_cc_cert.");
1851 if (ed25519_signature_from_base64(&check
[2].signature
,
1852 ed_sig_tok
->args
[0])<0) {
1853 log_warn(LD_DIR
, "Couldn't decode ed25519 signature");
1856 check
[2].pubkey
= &cert
->signed_key
;
1857 check
[2].msg
= d256
;
1858 check
[2].len
= DIGEST256_LEN
;
1860 if (ed25519_checksig_batch(check_ok
, check
, 3) < 0) {
1861 log_warn(LD_DIR
, "Incorrect ed25519 signature(s)");
1865 if (check_tap_onion_key_crosscert(
1866 (const uint8_t*)cc_tap_tok
->object_body
,
1867 (int)cc_tap_tok
->object_size
,
1870 (const uint8_t*)router
->cache_info
.identity_digest
)<0) {
1871 log_warn(LD_DIR
, "Incorrect TAP cross-verification");
1875 /* We check this before adding it to the routerlist. */
1876 router
->cert_expiration_time
= expires
;
1880 if ((tok
= find_opt_by_keyword(tokens
, K_FINGERPRINT
))) {
1881 /* If there's a fingerprint line, it must match the identity digest. */
1883 tor_assert(tok
->n_args
== 1);
1884 tor_strstrip(tok
->args
[0], " ");
1885 if (base16_decode(d
, DIGEST_LEN
,
1886 tok
->args
[0], strlen(tok
->args
[0])) != DIGEST_LEN
) {
1887 log_warn(LD_DIR
, "Couldn't decode router fingerprint %s",
1888 escaped(tok
->args
[0]));
1891 if (tor_memneq(d
,router
->cache_info
.identity_digest
, DIGEST_LEN
)) {
1892 log_warn(LD_DIR
, "Fingerprint '%s' does not match identity digest.",
1899 const char *version
= NULL
, *protocols
= NULL
;
1900 if ((tok
= find_opt_by_keyword(tokens
, K_PLATFORM
))) {
1901 router
->platform
= tor_strdup(tok
->args
[0]);
1902 version
= tok
->args
[0];
1905 if ((tok
= find_opt_by_keyword(tokens
, K_PROTO
))) {
1906 router
->protocol_list
= tor_strdup(tok
->args
[0]);
1907 protocols
= tok
->args
[0];
1910 summarize_protover_flags(&router
->pv
, protocols
, version
);
1913 if ((tok
= find_opt_by_keyword(tokens
, K_CONTACT
))) {
1914 router
->contact_info
= tor_strdup(tok
->args
[0]);
1917 if (find_opt_by_keyword(tokens
, K_REJECT6
) ||
1918 find_opt_by_keyword(tokens
, K_ACCEPT6
)) {
1919 log_warn(LD_DIR
, "Rejecting router with reject6/accept6 line: they crash "
1924 smartlist_t
*or_addresses
= find_all_by_keyword(tokens
, K_OR_ADDRESS
);
1926 find_single_ipv6_orport(or_addresses
, &router
->ipv6_addr
,
1927 &router
->ipv6_orport
);
1928 smartlist_free(or_addresses
);
1931 exit_policy_tokens
= find_all_exitpolicy(tokens
);
1932 if (!smartlist_len(exit_policy_tokens
)) {
1933 log_warn(LD_DIR
, "No exit policy tokens in descriptor.");
1936 SMARTLIST_FOREACH(exit_policy_tokens
, directory_token_t
*, t
,
1937 if (router_add_exit_policy(router
,t
)<0) {
1938 log_warn(LD_DIR
,"Error in exit policy");
1941 policy_expand_private(&router
->exit_policy
);
1943 if ((tok
= find_opt_by_keyword(tokens
, K_IPV6_POLICY
)) && tok
->n_args
) {
1944 router
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
1945 if (! router
->ipv6_exit_policy
) {
1946 log_warn(LD_DIR
, "Error in ipv6-policy %s", escaped(tok
->args
[0]));
1951 if (policy_is_reject_star(router
->exit_policy
, AF_INET
, 1) &&
1952 (!router
->ipv6_exit_policy
||
1953 short_policy_is_reject_star(router
->ipv6_exit_policy
)))
1954 router
->policy_is_reject_star
= 1;
1956 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
)) && tok
->n_args
) {
1958 router
->declared_family
= smartlist_new();
1959 for (i
=0;i
<tok
->n_args
;++i
) {
1960 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
1961 log_warn(LD_DIR
, "Illegal nickname %s in family line",
1962 escaped(tok
->args
[i
]));
1965 smartlist_add_strdup(router
->declared_family
, tok
->args
[i
]);
1969 if (find_opt_by_keyword(tokens
, K_CACHES_EXTRA_INFO
))
1970 router
->caches_extra_info
= 1;
1972 if (find_opt_by_keyword(tokens
, K_ALLOW_SINGLE_HOP_EXITS
))
1973 router
->allow_single_hop_exits
= 1;
1975 if ((tok
= find_opt_by_keyword(tokens
, K_EXTRA_INFO_DIGEST
))) {
1976 tor_assert(tok
->n_args
>= 1);
1977 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
1978 if (base16_decode(router
->cache_info
.extra_info_digest
, DIGEST_LEN
,
1979 tok
->args
[0], HEX_DIGEST_LEN
) != DIGEST_LEN
) {
1980 log_warn(LD_DIR
,"Invalid extra info digest");
1983 log_warn(LD_DIR
, "Invalid extra info digest %s", escaped(tok
->args
[0]));
1986 if (tok
->n_args
>= 2) {
1987 if (digest256_from_base64(router
->cache_info
.extra_info_digest256
,
1988 tok
->args
[1]) < 0) {
1989 log_warn(LD_DIR
, "Invalid extra info digest256 %s",
1990 escaped(tok
->args
[1]));
1995 if (find_opt_by_keyword(tokens
, K_HIDDEN_SERVICE_DIR
)) {
1996 router
->wants_to_be_hs_dir
= 1;
1999 /* This router accepts tunnelled directory requests via begindir if it has
2000 * an open dirport or it included "tunnelled-dir-server". */
2001 if (find_opt_by_keyword(tokens
, K_DIR_TUNNELLED
) || router
->dir_port
> 0) {
2002 router
->supports_tunnelled_dir_requests
= 1;
2005 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
2006 #ifdef COUNT_DISTINCT_DIGESTS
2007 if (!verified_digests
)
2008 verified_digests
= digestmap_new();
2009 digestmap_set(verified_digests
, signed_digest
, (void*)(uintptr_t)1);
2012 if (!router
->or_port
) {
2013 log_warn(LD_DIR
,"or_port unreadable or 0. Failing.");
2017 /* We've checked everything that's covered by the hash. */
2019 if (check_signature_token(digest
, DIGEST_LEN
, tok
, router
->identity_pkey
, 0,
2020 "router descriptor") < 0)
2023 if (!router
->platform
) {
2024 router
->platform
= tor_strdup("<unknown>");
2029 dump_desc(s_dup
, "router descriptor");
2030 routerinfo_free(router
);
2033 tor_cert_free(ntor_cc_cert
);
2035 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2036 smartlist_free(tokens
);
2038 smartlist_free(exit_policy_tokens
);
2040 DUMP_AREA(area
, "routerinfo");
2041 memarea_drop_all(area
);
2043 if (can_dl_again_out
)
2044 *can_dl_again_out
= can_dl_again
;
2048 /** Parse a single extrainfo entry from the string <b>s</b>, ending at
2049 * <b>end</b>. (If <b>end</b> is NULL, parse up to the end of <b>s</b>.) If
2050 * <b>cache_copy</b> is true, make a copy of the extra-info document in the
2051 * cache_info fields of the result. If <b>routermap</b> is provided, use it
2052 * as a map from router identity to routerinfo_t when looking up signing keys.
2054 * If <b>can_dl_again_out</b> is provided, set *<b>can_dl_again_out</b> to 1
2055 * if it's okay to try to download an extrainfo with this same digest again,
2056 * and 0 if it isn't. (It might not be okay to download it again if part of
2057 * the part covered by the digest is invalid.)
2060 extrainfo_parse_entry_from_string(const char *s
, const char *end
,
2061 int cache_copy
, struct digest_ri_map_t
*routermap
,
2062 int *can_dl_again_out
)
2064 extrainfo_t
*extrainfo
= NULL
;
2066 smartlist_t
*tokens
= NULL
;
2067 directory_token_t
*tok
;
2068 crypto_pk_t
*key
= NULL
;
2069 routerinfo_t
*router
= NULL
;
2070 memarea_t
*area
= NULL
;
2071 const char *s_dup
= s
;
2072 /* Do not set this to '1' until we have parsed everything that we intend to
2073 * parse that's covered by the hash. */
2074 int can_dl_again
= 0;
2080 end
= s
+ strlen(s
);
2083 /* point 'end' to a point immediately after the final newline. */
2084 while (end
> s
+2 && *(end
-1) == '\n' && *(end
-2) == '\n')
2087 if (router_get_extrainfo_hash(s
, end
-s
, digest
) < 0) {
2088 log_warn(LD_DIR
, "Couldn't compute router hash.");
2091 tokens
= smartlist_new();
2092 area
= memarea_new();
2093 if (tokenize_string(area
,s
,end
,tokens
,extrainfo_token_table
,0)) {
2094 log_warn(LD_DIR
, "Error tokenizing extra-info document.");
2098 if (smartlist_len(tokens
) < 2) {
2099 log_warn(LD_DIR
, "Impossibly short extra-info document.");
2103 /* XXXX Accept this in position 1 too, and ed identity in position 0. */
2104 tok
= smartlist_get(tokens
,0);
2105 if (tok
->tp
!= K_EXTRA_INFO
) {
2106 log_warn(LD_DIR
,"Entry does not start with \"extra-info\"");
2110 extrainfo
= tor_malloc_zero(sizeof(extrainfo_t
));
2111 extrainfo
->cache_info
.is_extrainfo
= 1;
2113 extrainfo
->cache_info
.signed_descriptor_body
= tor_memdup_nulterm(s
,end
-s
);
2114 extrainfo
->cache_info
.signed_descriptor_len
= end
-s
;
2115 memcpy(extrainfo
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
2116 crypto_digest256((char*)extrainfo
->digest256
, s
, end
-s
, DIGEST_SHA256
);
2118 tor_assert(tok
->n_args
>= 2);
2119 if (!is_legal_nickname(tok
->args
[0])) {
2120 log_warn(LD_DIR
,"Bad nickname %s on \"extra-info\"",escaped(tok
->args
[0]));
2123 strlcpy(extrainfo
->nickname
, tok
->args
[0], sizeof(extrainfo
->nickname
));
2124 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
2125 base16_decode(extrainfo
->cache_info
.identity_digest
, DIGEST_LEN
,
2126 tok
->args
[1], HEX_DIGEST_LEN
) != DIGEST_LEN
) {
2127 log_warn(LD_DIR
,"Invalid fingerprint %s on \"extra-info\"",
2128 escaped(tok
->args
[1]));
2132 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
2133 if (parse_iso_time(tok
->args
[0], &extrainfo
->cache_info
.published_on
)) {
2134 log_warn(LD_DIR
,"Invalid published time %s on \"extra-info\"",
2135 escaped(tok
->args
[0]));
2140 directory_token_t
*ed_sig_tok
, *ed_cert_tok
;
2141 ed_sig_tok
= find_opt_by_keyword(tokens
, K_ROUTER_SIG_ED25519
);
2142 ed_cert_tok
= find_opt_by_keyword(tokens
, K_IDENTITY_ED25519
);
2143 int n_ed_toks
= !!ed_sig_tok
+ !!ed_cert_tok
;
2144 if (n_ed_toks
!= 0 && n_ed_toks
!= 2) {
2145 log_warn(LD_DIR
, "Router descriptor with only partial ed25519/"
2146 "cross-certification support");
2150 tor_assert(ed_cert_tok
);
2151 const int ed_cert_token_pos
= smartlist_pos(tokens
, ed_cert_tok
);
2152 if (ed_cert_token_pos
!= 1) {
2153 /* Accept this in position 0 XXXX */
2154 log_warn(LD_DIR
, "Ed25519 certificate in wrong position");
2157 if (ed_sig_tok
!= smartlist_get(tokens
, smartlist_len(tokens
)-2)) {
2158 log_warn(LD_DIR
, "Ed25519 signature in wrong position");
2161 if (strcmp(ed_cert_tok
->object_type
, "ED25519 CERT")) {
2162 log_warn(LD_DIR
, "Wrong object type on identity-ed25519 in decriptor");
2166 uint8_t d256
[DIGEST256_LEN
];
2167 const char *signed_start
, *signed_end
;
2168 tor_cert_t
*cert
= tor_cert_parse(
2169 (const uint8_t*)ed_cert_tok
->object_body
,
2170 ed_cert_tok
->object_size
);
2172 log_warn(LD_DIR
, "Couldn't parse ed25519 cert");
2175 /* makes sure it gets freed. */
2176 extrainfo
->cache_info
.signing_key_cert
= cert
;
2178 if (cert
->cert_type
!= CERT_TYPE_ID_SIGNING
||
2179 ! cert
->signing_key_included
) {
2180 log_warn(LD_DIR
, "Invalid form for ed25519 cert");
2184 if (router_get_hash_impl_helper(s
, end
-s
, "extra-info ",
2185 "\nrouter-sig-ed25519",
2187 &signed_start
, &signed_end
) < 0) {
2188 log_warn(LD_DIR
, "Can't find ed25519-signed portion of extrainfo");
2191 crypto_digest_t
*d
= crypto_digest256_new(DIGEST_SHA256
);
2192 crypto_digest_add_bytes(d
, ED_DESC_SIGNATURE_PREFIX
,
2193 strlen(ED_DESC_SIGNATURE_PREFIX
));
2194 crypto_digest_add_bytes(d
, signed_start
, signed_end
-signed_start
);
2195 crypto_digest_get_digest(d
, (char*)d256
, sizeof(d256
));
2196 crypto_digest_free(d
);
2198 ed25519_checkable_t check
[2];
2200 if (tor_cert_get_checkable_sig(&check
[0], cert
, NULL
, NULL
) < 0) {
2201 log_err(LD_BUG
, "Couldn't create 'checkable' for cert.");
2205 if (ed25519_signature_from_base64(&check
[1].signature
,
2206 ed_sig_tok
->args
[0])<0) {
2207 log_warn(LD_DIR
, "Couldn't decode ed25519 signature");
2210 check
[1].pubkey
= &cert
->signed_key
;
2211 check
[1].msg
= d256
;
2212 check
[1].len
= DIGEST256_LEN
;
2214 if (ed25519_checksig_batch(check_ok
, check
, 2) < 0) {
2215 log_warn(LD_DIR
, "Incorrect ed25519 signature(s)");
2218 /* We don't check the certificate expiration time: checking that it
2219 * matches the cert in the router descriptor is adequate. */
2223 /* We've checked everything that's covered by the hash. */
2227 (router
= digestmap_get((digestmap_t
*)routermap
,
2228 extrainfo
->cache_info
.identity_digest
))) {
2229 key
= router
->identity_pkey
;
2232 tok
= find_by_keyword(tokens
, K_ROUTER_SIGNATURE
);
2233 if (strcmp(tok
->object_type
, "SIGNATURE") ||
2234 tok
->object_size
< 128 || tok
->object_size
> 512) {
2235 log_warn(LD_DIR
, "Bad object type or length on extra-info signature");
2240 if (check_signature_token(digest
, DIGEST_LEN
, tok
, key
, 0,
2245 extrainfo
->cache_info
.send_unencrypted
=
2246 router
->cache_info
.send_unencrypted
;
2248 extrainfo
->pending_sig
= tor_memdup(tok
->object_body
,
2250 extrainfo
->pending_sig_len
= tok
->object_size
;
2255 dump_desc(s_dup
, "extra-info descriptor");
2256 extrainfo_free(extrainfo
);
2260 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2261 smartlist_free(tokens
);
2264 DUMP_AREA(area
, "extrainfo");
2265 memarea_drop_all(area
);
2267 if (can_dl_again_out
)
2268 *can_dl_again_out
= can_dl_again
;
2272 /** Parse a key certificate from <b>s</b>; point <b>end-of-string</b> to
2273 * the first character after the certificate. */
2275 authority_cert_parse_from_string(const char *s
, const char **end_of_string
)
2277 /** Reject any certificate at least this big; it is probably an overflow, an
2278 * attack, a bug, or some other nonsense. */
2279 #define MAX_CERT_SIZE (128*1024)
2281 authority_cert_t
*cert
= NULL
, *old_cert
;
2282 smartlist_t
*tokens
= NULL
;
2283 char digest
[DIGEST_LEN
];
2284 directory_token_t
*tok
;
2285 char fp_declared
[DIGEST_LEN
];
2289 memarea_t
*area
= NULL
;
2290 const char *s_dup
= s
;
2292 s
= eat_whitespace(s
);
2293 eos
= strstr(s
, "\ndir-key-certification");
2295 log_warn(LD_DIR
, "No signature found on key certificate");
2298 eos
= strstr(eos
, "\n-----END SIGNATURE-----\n");
2300 log_warn(LD_DIR
, "No end-of-signature found on key certificate");
2303 eos
= strchr(eos
+2, '\n');
2308 if (len
> MAX_CERT_SIZE
) {
2309 log_warn(LD_DIR
, "Certificate is far too big (at %lu bytes long); "
2310 "rejecting", (unsigned long)len
);
2314 tokens
= smartlist_new();
2315 area
= memarea_new();
2316 if (tokenize_string(area
,s
, eos
, tokens
, dir_key_certificate_table
, 0) < 0) {
2317 log_warn(LD_DIR
, "Error tokenizing key certificate");
2320 if (router_get_hash_impl(s
, strlen(s
), digest
, "dir-key-certificate-version",
2321 "\ndir-key-certification", '\n', DIGEST_SHA1
) < 0)
2323 tok
= smartlist_get(tokens
, 0);
2324 if (tok
->tp
!= K_DIR_KEY_CERTIFICATE_VERSION
|| strcmp(tok
->args
[0], "3")) {
2326 "Key certificate does not begin with a recognized version (3).");
2330 cert
= tor_malloc_zero(sizeof(authority_cert_t
));
2331 memcpy(cert
->cache_info
.signed_descriptor_digest
, digest
, DIGEST_LEN
);
2333 tok
= find_by_keyword(tokens
, K_DIR_SIGNING_KEY
);
2334 tor_assert(tok
->key
);
2335 cert
->signing_key
= tok
->key
;
2337 if (crypto_pk_get_digest(cert
->signing_key
, cert
->signing_key_digest
))
2340 tok
= find_by_keyword(tokens
, K_DIR_IDENTITY_KEY
);
2341 tor_assert(tok
->key
);
2342 cert
->identity_key
= tok
->key
;
2345 tok
= find_by_keyword(tokens
, K_FINGERPRINT
);
2346 tor_assert(tok
->n_args
);
2347 if (base16_decode(fp_declared
, DIGEST_LEN
, tok
->args
[0],
2348 strlen(tok
->args
[0])) != DIGEST_LEN
) {
2349 log_warn(LD_DIR
, "Couldn't decode key certificate fingerprint %s",
2350 escaped(tok
->args
[0]));
2354 if (crypto_pk_get_digest(cert
->identity_key
,
2355 cert
->cache_info
.identity_digest
))
2358 if (tor_memneq(cert
->cache_info
.identity_digest
, fp_declared
, DIGEST_LEN
)) {
2359 log_warn(LD_DIR
, "Digest of certificate key didn't match declared "
2364 tok
= find_opt_by_keyword(tokens
, K_DIR_ADDRESS
);
2367 char *address
= NULL
;
2368 tor_assert(tok
->n_args
);
2369 /* XXX++ use some tor_addr parse function below instead. -RD */
2370 if (tor_addr_port_split(LOG_WARN
, tok
->args
[0], &address
,
2371 &cert
->dir_port
) < 0 ||
2372 tor_inet_aton(address
, &in
) == 0) {
2373 log_warn(LD_DIR
, "Couldn't parse dir-address in certificate");
2377 cert
->addr
= ntohl(in
.s_addr
);
2381 tok
= find_by_keyword(tokens
, K_DIR_KEY_PUBLISHED
);
2382 if (parse_iso_time(tok
->args
[0], &cert
->cache_info
.published_on
) < 0) {
2385 tok
= find_by_keyword(tokens
, K_DIR_KEY_EXPIRES
);
2386 if (parse_iso_time(tok
->args
[0], &cert
->expires
) < 0) {
2390 tok
= smartlist_get(tokens
, smartlist_len(tokens
)-1);
2391 if (tok
->tp
!= K_DIR_KEY_CERTIFICATION
) {
2392 log_warn(LD_DIR
, "Certificate didn't end with dir-key-certification.");
2396 /* If we already have this cert, don't bother checking the signature. */
2397 old_cert
= authority_cert_get_by_digests(
2398 cert
->cache_info
.identity_digest
,
2399 cert
->signing_key_digest
);
2402 /* XXXX We could just compare signed_descriptor_digest, but that wouldn't
2404 if (old_cert
->cache_info
.signed_descriptor_len
== len
&&
2405 old_cert
->cache_info
.signed_descriptor_body
&&
2406 tor_memeq(s
, old_cert
->cache_info
.signed_descriptor_body
, len
)) {
2407 log_debug(LD_DIR
, "We already checked the signature on this "
2408 "certificate; no need to do so again.");
2413 if (check_signature_token(digest
, DIGEST_LEN
, tok
, cert
->identity_key
, 0,
2414 "key certificate")) {
2418 tok
= find_by_keyword(tokens
, K_DIR_KEY_CROSSCERT
);
2419 if (check_signature_token(cert
->cache_info
.identity_digest
,
2423 CST_NO_CHECK_OBJTYPE
,
2424 "key cross-certification")) {
2429 cert
->cache_info
.signed_descriptor_len
= len
;
2430 cert
->cache_info
.signed_descriptor_body
= tor_malloc(len
+1);
2431 memcpy(cert
->cache_info
.signed_descriptor_body
, s
, len
);
2432 cert
->cache_info
.signed_descriptor_body
[len
] = 0;
2433 cert
->cache_info
.saved_location
= SAVED_NOWHERE
;
2435 if (end_of_string
) {
2436 *end_of_string
= eat_whitespace(eos
);
2438 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2439 smartlist_free(tokens
);
2441 DUMP_AREA(area
, "authority cert");
2442 memarea_drop_all(area
);
2446 dump_desc(s_dup
, "authority cert");
2447 authority_cert_free(cert
);
2448 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2449 smartlist_free(tokens
);
2451 DUMP_AREA(area
, "authority cert");
2452 memarea_drop_all(area
);
2457 /** Helper: given a string <b>s</b>, return the start of the next router-status
2458 * object (starting with "r " at the start of a line). If none is found,
2459 * return the start of the directory footer, or the next directory signature.
2460 * If none is found, return the end of the string. */
2461 static inline const char *
2462 find_start_of_next_routerstatus(const char *s
)
2464 const char *eos
, *footer
, *sig
;
2465 if ((eos
= strstr(s
, "\nr ")))
2468 eos
= s
+ strlen(s
);
2470 footer
= tor_memstr(s
, eos
-s
, "\ndirectory-footer");
2471 sig
= tor_memstr(s
, eos
-s
, "\ndirectory-signature");
2474 return MIN(footer
, sig
) + 1;
2483 /** Parse the GuardFraction string from a consensus or vote.
2485 * If <b>vote</b> or <b>vote_rs</b> are set the document getting
2486 * parsed is a vote routerstatus. Otherwise it's a consensus. This is
2487 * the same semantic as in routerstatus_parse_entry_from_string(). */
2489 routerstatus_parse_guardfraction(const char *guardfraction_str
,
2490 networkstatus_t
*vote
,
2491 vote_routerstatus_t
*vote_rs
,
2495 const char *end_of_header
= NULL
;
2496 int is_consensus
= !vote_rs
;
2497 uint32_t guardfraction
;
2499 tor_assert(bool_eq(vote
, vote_rs
));
2501 /* If this info comes from a consensus, but we should't apply
2502 guardfraction, just exit. */
2503 if (is_consensus
&& !should_apply_guardfraction(NULL
)) {
2507 end_of_header
= strchr(guardfraction_str
, '=');
2508 if (!end_of_header
) {
2512 guardfraction
= (uint32_t)tor_parse_ulong(end_of_header
+1,
2513 10, 0, 100, &ok
, NULL
);
2515 log_warn(LD_DIR
, "Invalid GuardFraction %s", escaped(guardfraction_str
));
2519 log_debug(LD_GENERAL
, "[*] Parsed %s guardfraction '%s' for '%s'.",
2520 is_consensus
? "consensus" : "vote",
2521 guardfraction_str
, rs
->nickname
);
2523 if (!is_consensus
) { /* We are parsing a vote */
2524 vote_rs
->status
.guardfraction_percentage
= guardfraction
;
2525 vote_rs
->status
.has_guardfraction
= 1;
2527 /* We are parsing a consensus. Only apply guardfraction to guards. */
2528 if (rs
->is_possible_guard
) {
2529 rs
->guardfraction_percentage
= guardfraction
;
2530 rs
->has_guardfraction
= 1;
2532 log_warn(LD_BUG
, "Got GuardFraction for non-guard %s. "
2533 "This is not supposed to happen. Not applying. ", rs
->nickname
);
2540 /** Summarize the protocols listed in <b>protocols</b> into <b>out</b>,
2541 * falling back or correcting them based on <b>version</b> as appropriate.
2544 summarize_protover_flags(protover_summary_flags_t
*out
,
2545 const char *protocols
,
2546 const char *version
)
2549 memset(out
, 0, sizeof(*out
));
2551 out
->protocols_known
= 1;
2552 out
->supports_extend2_cells
=
2553 protocol_list_supports_protocol(protocols
, PRT_RELAY
, 2);
2554 out
->supports_ed25519_link_handshake_compat
=
2555 protocol_list_supports_protocol(protocols
, PRT_LINKAUTH
, 3);
2556 out
->supports_ed25519_link_handshake_any
=
2557 protocol_list_supports_protocol_or_later(protocols
, PRT_LINKAUTH
, 3);
2558 out
->supports_ed25519_hs_intro
=
2559 protocol_list_supports_protocol(protocols
, PRT_HSINTRO
, 4);
2560 out
->supports_v3_hsdir
=
2561 protocol_list_supports_protocol(protocols
, PRT_HSDIR
,
2563 out
->supports_v3_rendezvous_point
=
2564 protocol_list_supports_protocol(protocols
, PRT_HSREND
,
2565 PROTOVER_HS_RENDEZVOUS_POINT_V3
);
2567 if (version
&& !strcmpstart(version
, "Tor ")) {
2568 if (!out
->protocols_known
) {
2569 /* The version is a "Tor" version, and where there is no
2570 * list of protocol versions that we should be looking at instead. */
2572 out
->supports_extend2_cells
=
2573 tor_version_as_new_as(version
, "0.2.4.8-alpha");
2574 out
->protocols_known
= 1;
2576 /* Bug #22447 forces us to filter on this version. */
2577 if (!tor_version_as_new_as(version
, "0.3.0.8")) {
2578 out
->supports_v3_hsdir
= 0;
2584 /** Given a string at *<b>s</b>, containing a routerstatus object, and an
2585 * empty smartlist at <b>tokens</b>, parse and return the first router status
2586 * object in the string, and advance *<b>s</b> to just after the end of the
2587 * router status. Return NULL and advance *<b>s</b> on error.
2589 * If <b>vote</b> and <b>vote_rs</b> are provided, don't allocate a fresh
2590 * routerstatus but use <b>vote_rs</b> instead.
2592 * If <b>consensus_method</b> is nonzero, this routerstatus is part of a
2593 * consensus, and we should parse it according to the method used to
2594 * make that consensus.
2596 * Parse according to the syntax used by the consensus flavor <b>flav</b>.
2598 STATIC routerstatus_t
*
2599 routerstatus_parse_entry_from_string(memarea_t
*area
,
2600 const char **s
, smartlist_t
*tokens
,
2601 networkstatus_t
*vote
,
2602 vote_routerstatus_t
*vote_rs
,
2603 int consensus_method
,
2604 consensus_flavor_t flav
)
2606 const char *eos
, *s_dup
= *s
;
2607 routerstatus_t
*rs
= NULL
;
2608 directory_token_t
*tok
;
2609 char timebuf
[ISO_TIME_LEN
+1];
2613 tor_assert(bool_eq(vote
, vote_rs
));
2615 if (!consensus_method
)
2617 tor_assert(flav
== FLAV_NS
|| flav
== FLAV_MICRODESC
);
2619 eos
= find_start_of_next_routerstatus(*s
);
2621 if (tokenize_string(area
,*s
, eos
, tokens
, rtrstatus_token_table
,0)) {
2622 log_warn(LD_DIR
, "Error tokenizing router status");
2625 if (smartlist_len(tokens
) < 1) {
2626 log_warn(LD_DIR
, "Impossibly short router status");
2629 tok
= find_by_keyword(tokens
, K_R
);
2630 tor_assert(tok
->n_args
>= 7); /* guaranteed by GE(7) in K_R setup */
2631 if (flav
== FLAV_NS
) {
2632 if (tok
->n_args
< 8) {
2633 log_warn(LD_DIR
, "Too few arguments to r");
2636 } else if (flav
== FLAV_MICRODESC
) {
2637 offset
= -1; /* There is no descriptor digest in an md consensus r line */
2641 rs
= &vote_rs
->status
;
2643 rs
= tor_malloc_zero(sizeof(routerstatus_t
));
2646 if (!is_legal_nickname(tok
->args
[0])) {
2648 "Invalid nickname %s in router status; skipping.",
2649 escaped(tok
->args
[0]));
2652 strlcpy(rs
->nickname
, tok
->args
[0], sizeof(rs
->nickname
));
2654 if (digest_from_base64(rs
->identity_digest
, tok
->args
[1])) {
2655 log_warn(LD_DIR
, "Error decoding identity digest %s",
2656 escaped(tok
->args
[1]));
2660 if (flav
== FLAV_NS
) {
2661 if (digest_from_base64(rs
->descriptor_digest
, tok
->args
[2])) {
2662 log_warn(LD_DIR
, "Error decoding descriptor digest %s",
2663 escaped(tok
->args
[2]));
2668 if (tor_snprintf(timebuf
, sizeof(timebuf
), "%s %s",
2669 tok
->args
[3+offset
], tok
->args
[4+offset
]) < 0 ||
2670 parse_iso_time(timebuf
, &rs
->published_on
)<0) {
2671 log_warn(LD_DIR
, "Error parsing time '%s %s' [%d %d]",
2672 tok
->args
[3+offset
], tok
->args
[4+offset
],
2677 if (tor_inet_aton(tok
->args
[5+offset
], &in
) == 0) {
2678 log_warn(LD_DIR
, "Error parsing router address in network-status %s",
2679 escaped(tok
->args
[5+offset
]));
2682 rs
->addr
= ntohl(in
.s_addr
);
2684 rs
->or_port
= (uint16_t) tor_parse_long(tok
->args
[6+offset
],
2685 10,0,65535,NULL
,NULL
);
2686 rs
->dir_port
= (uint16_t) tor_parse_long(tok
->args
[7+offset
],
2687 10,0,65535,NULL
,NULL
);
2690 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
2692 find_single_ipv6_orport(a_lines
, &rs
->ipv6_addr
, &rs
->ipv6_orport
);
2693 smartlist_free(a_lines
);
2697 tok
= find_opt_by_keyword(tokens
, K_S
);
2701 for (i
=0; i
< tok
->n_args
; ++i
) {
2702 int p
= smartlist_string_pos(vote
->known_flags
, tok
->args
[i
]);
2704 vote_rs
->flags
|= (U64_LITERAL(1)<<p
);
2706 log_warn(LD_DIR
, "Flags line had a flag %s not listed in known_flags.",
2707 escaped(tok
->args
[i
]));
2712 /* This is a consensus, not a vote. */
2714 for (i
=0; i
< tok
->n_args
; ++i
) {
2715 if (!strcmp(tok
->args
[i
], "Exit"))
2717 else if (!strcmp(tok
->args
[i
], "Stable"))
2719 else if (!strcmp(tok
->args
[i
], "Fast"))
2721 else if (!strcmp(tok
->args
[i
], "Running"))
2722 rs
->is_flagged_running
= 1;
2723 else if (!strcmp(tok
->args
[i
], "Named"))
2725 else if (!strcmp(tok
->args
[i
], "Valid"))
2727 else if (!strcmp(tok
->args
[i
], "Guard"))
2728 rs
->is_possible_guard
= 1;
2729 else if (!strcmp(tok
->args
[i
], "BadExit"))
2730 rs
->is_bad_exit
= 1;
2731 else if (!strcmp(tok
->args
[i
], "Authority"))
2732 rs
->is_authority
= 1;
2733 else if (!strcmp(tok
->args
[i
], "Unnamed") &&
2734 consensus_method
>= 2) {
2735 /* Unnamed is computed right by consensus method 2 and later. */
2737 } else if (!strcmp(tok
->args
[i
], "HSDir")) {
2739 } else if (!strcmp(tok
->args
[i
], "V2Dir")) {
2743 /* These are implied true by having been included in a consensus made
2744 * with a given method */
2745 rs
->is_flagged_running
= 1; /* Starting with consensus method 4. */
2746 if (consensus_method
>= MIN_METHOD_FOR_EXCLUDING_INVALID_NODES
)
2750 const char *protocols
= NULL
, *version
= NULL
;
2751 if ((tok
= find_opt_by_keyword(tokens
, K_PROTO
))) {
2752 tor_assert(tok
->n_args
== 1);
2753 protocols
= tok
->args
[0];
2755 if ((tok
= find_opt_by_keyword(tokens
, K_V
))) {
2756 tor_assert(tok
->n_args
== 1);
2757 version
= tok
->args
[0];
2759 vote_rs
->version
= tor_strdup(tok
->args
[0]);
2763 summarize_protover_flags(&rs
->pv
, protocols
, version
);
2766 /* handle weighting/bandwidth info */
2767 if ((tok
= find_opt_by_keyword(tokens
, K_W
))) {
2769 for (i
=0; i
< tok
->n_args
; ++i
) {
2770 if (!strcmpstart(tok
->args
[i
], "Bandwidth=")) {
2773 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
2777 log_warn(LD_DIR
, "Invalid Bandwidth %s", escaped(tok
->args
[i
]));
2780 rs
->has_bandwidth
= 1;
2781 } else if (!strcmpstart(tok
->args
[i
], "Measured=") && vote_rs
) {
2783 vote_rs
->measured_bw_kb
=
2784 (uint32_t)tor_parse_ulong(strchr(tok
->args
[i
], '=')+1,
2785 10, 0, UINT32_MAX
, &ok
, NULL
);
2787 log_warn(LD_DIR
, "Invalid Measured Bandwidth %s",
2788 escaped(tok
->args
[i
]));
2791 vote_rs
->has_measured_bw
= 1;
2792 vote
->has_measured_bws
= 1;
2793 } else if (!strcmpstart(tok
->args
[i
], "Unmeasured=1")) {
2794 rs
->bw_is_unmeasured
= 1;
2795 } else if (!strcmpstart(tok
->args
[i
], "GuardFraction=")) {
2796 if (routerstatus_parse_guardfraction(tok
->args
[i
],
2797 vote
, vote_rs
, rs
) < 0) {
2804 /* parse exit policy summaries */
2805 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
2806 tor_assert(tok
->n_args
== 1);
2807 if (strcmpstart(tok
->args
[0], "accept ") &&
2808 strcmpstart(tok
->args
[0], "reject ")) {
2809 log_warn(LD_DIR
, "Unknown exit policy summary type %s.",
2810 escaped(tok
->args
[0]));
2813 /* XXX weasel: parse this into ports and represent them somehow smart,
2814 * maybe not here but somewhere on if we need it for the client.
2815 * we should still parse it here to check it's valid tho.
2817 rs
->exitsummary
= tor_strdup(tok
->args
[0]);
2818 rs
->has_exitsummary
= 1;
2822 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, t
) {
2823 if (t
->tp
== K_M
&& t
->n_args
) {
2824 vote_microdesc_hash_t
*line
=
2825 tor_malloc(sizeof(vote_microdesc_hash_t
));
2826 line
->next
= vote_rs
->microdesc
;
2827 line
->microdesc_hash_line
= tor_strdup(t
->args
[0]);
2828 vote_rs
->microdesc
= line
;
2830 if (t
->tp
== K_ID
) {
2831 tor_assert(t
->n_args
>= 2);
2832 if (!strcmp(t
->args
[0], "ed25519")) {
2833 vote_rs
->has_ed25519_listing
= 1;
2834 if (strcmp(t
->args
[1], "none") &&
2835 digest256_from_base64((char*)vote_rs
->ed25519_id
,
2837 log_warn(LD_DIR
, "Bogus ed25519 key in networkstatus vote");
2842 if (t
->tp
== K_PROTO
) {
2843 tor_assert(t
->n_args
== 1);
2844 vote_rs
->protocols
= tor_strdup(t
->args
[0]);
2846 } SMARTLIST_FOREACH_END(t
);
2847 } else if (flav
== FLAV_MICRODESC
) {
2848 tok
= find_opt_by_keyword(tokens
, K_M
);
2850 tor_assert(tok
->n_args
);
2851 if (digest256_from_base64(rs
->descriptor_digest
, tok
->args
[0])) {
2852 log_warn(LD_DIR
, "Error decoding microdescriptor digest %s",
2853 escaped(tok
->args
[0]));
2857 log_info(LD_BUG
, "Found an entry in networkstatus with no "
2858 "microdescriptor digest. (Router %s ($%s) at %s:%d.)",
2859 rs
->nickname
, hex_str(rs
->identity_digest
, DIGEST_LEN
),
2860 fmt_addr32(rs
->addr
), rs
->or_port
);
2864 if (!strcasecmp(rs
->nickname
, UNNAMED_ROUTER_NICKNAME
))
2869 dump_desc(s_dup
, "routerstatus entry");
2871 routerstatus_free(rs
);
2874 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
2875 smartlist_clear(tokens
);
2877 DUMP_AREA(area
, "routerstatus entry");
2878 memarea_clear(area
);
2886 compare_vote_routerstatus_entries(const void **_a
, const void **_b
)
2888 const vote_routerstatus_t
*a
= *_a
, *b
= *_b
;
2889 return fast_memcmp(a
->status
.identity_digest
, b
->status
.identity_digest
,
2893 /** Verify the bandwidth weights of a network status document */
2895 networkstatus_verify_bw_weights(networkstatus_t
*ns
, int consensus_method
)
2897 int64_t G
=0, M
=0, E
=0, D
=0, T
=0;
2898 double Wgg
, Wgm
, Wgd
, Wmg
, Wmm
, Wme
, Wmd
, Weg
, Wem
, Wee
, Wed
;
2899 double Gtotal
=0, Mtotal
=0, Etotal
=0;
2900 const char *casename
= NULL
;
2902 (void) consensus_method
;
2904 const int64_t weight_scale
= networkstatus_get_weight_scale_param(ns
);
2905 tor_assert(weight_scale
>= 1);
2906 Wgg
= networkstatus_get_bw_weight(ns
, "Wgg", -1);
2907 Wgm
= networkstatus_get_bw_weight(ns
, "Wgm", -1);
2908 Wgd
= networkstatus_get_bw_weight(ns
, "Wgd", -1);
2909 Wmg
= networkstatus_get_bw_weight(ns
, "Wmg", -1);
2910 Wmm
= networkstatus_get_bw_weight(ns
, "Wmm", -1);
2911 Wme
= networkstatus_get_bw_weight(ns
, "Wme", -1);
2912 Wmd
= networkstatus_get_bw_weight(ns
, "Wmd", -1);
2913 Weg
= networkstatus_get_bw_weight(ns
, "Weg", -1);
2914 Wem
= networkstatus_get_bw_weight(ns
, "Wem", -1);
2915 Wee
= networkstatus_get_bw_weight(ns
, "Wee", -1);
2916 Wed
= networkstatus_get_bw_weight(ns
, "Wed", -1);
2918 if (Wgg
<0 || Wgm
<0 || Wgd
<0 || Wmg
<0 || Wmm
<0 || Wme
<0 || Wmd
<0 || Weg
<0
2919 || Wem
<0 || Wee
<0 || Wed
<0) {
2920 log_warn(LD_BUG
, "No bandwidth weights produced in consensus!");
2924 // First, sanity check basic summing properties that hold for all cases
2925 // We use > 1 as the check for these because they are computed as integers.
2926 // Sometimes there are rounding errors.
2927 if (fabs(Wmm
- weight_scale
) > 1) {
2928 log_warn(LD_BUG
, "Wmm=%f != "I64_FORMAT
,
2929 Wmm
, I64_PRINTF_ARG(weight_scale
));
2933 if (fabs(Wem
- Wee
) > 1) {
2934 log_warn(LD_BUG
, "Wem=%f != Wee=%f", Wem
, Wee
);
2938 if (fabs(Wgm
- Wgg
) > 1) {
2939 log_warn(LD_BUG
, "Wgm=%f != Wgg=%f", Wgm
, Wgg
);
2943 if (fabs(Weg
- Wed
) > 1) {
2944 log_warn(LD_BUG
, "Wed=%f != Weg=%f", Wed
, Weg
);
2948 if (fabs(Wgg
+ Wmg
- weight_scale
) > 0.001*weight_scale
) {
2949 log_warn(LD_BUG
, "Wgg=%f != "I64_FORMAT
" - Wmg=%f", Wgg
,
2950 I64_PRINTF_ARG(weight_scale
), Wmg
);
2954 if (fabs(Wee
+ Wme
- weight_scale
) > 0.001*weight_scale
) {
2955 log_warn(LD_BUG
, "Wee=%f != "I64_FORMAT
" - Wme=%f", Wee
,
2956 I64_PRINTF_ARG(weight_scale
), Wme
);
2960 if (fabs(Wgd
+ Wmd
+ Wed
- weight_scale
) > 0.001*weight_scale
) {
2961 log_warn(LD_BUG
, "Wgd=%f + Wmd=%f + Wed=%f != "I64_FORMAT
,
2962 Wgd
, Wmd
, Wed
, I64_PRINTF_ARG(weight_scale
));
2966 Wgg
/= weight_scale
;
2967 Wgm
/= weight_scale
; (void) Wgm
; // unused from here on.
2968 Wgd
/= weight_scale
;
2970 Wmg
/= weight_scale
;
2971 Wmm
/= weight_scale
;
2972 Wme
/= weight_scale
;
2973 Wmd
/= weight_scale
;
2975 Weg
/= weight_scale
; (void) Weg
; // unused from here on.
2976 Wem
/= weight_scale
; (void) Wem
; // unused from here on.
2977 Wee
/= weight_scale
;
2978 Wed
/= weight_scale
;
2980 // Then, gather G, M, E, D, T to determine case
2981 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, routerstatus_t
*, rs
) {
2983 /* Bug #2203: Don't count bad exits as exits for balancing */
2984 is_exit
= rs
->is_exit
&& !rs
->is_bad_exit
;
2985 if (rs
->has_bandwidth
) {
2986 T
+= rs
->bandwidth_kb
;
2987 if (is_exit
&& rs
->is_possible_guard
) {
2988 D
+= rs
->bandwidth_kb
;
2989 Gtotal
+= Wgd
*rs
->bandwidth_kb
;
2990 Mtotal
+= Wmd
*rs
->bandwidth_kb
;
2991 Etotal
+= Wed
*rs
->bandwidth_kb
;
2992 } else if (is_exit
) {
2993 E
+= rs
->bandwidth_kb
;
2994 Mtotal
+= Wme
*rs
->bandwidth_kb
;
2995 Etotal
+= Wee
*rs
->bandwidth_kb
;
2996 } else if (rs
->is_possible_guard
) {
2997 G
+= rs
->bandwidth_kb
;
2998 Gtotal
+= Wgg
*rs
->bandwidth_kb
;
2999 Mtotal
+= Wmg
*rs
->bandwidth_kb
;
3001 M
+= rs
->bandwidth_kb
;
3002 Mtotal
+= Wmm
*rs
->bandwidth_kb
;
3005 log_warn(LD_BUG
, "Missing consensus bandwidth for router %s",
3006 routerstatus_describe(rs
));
3008 } SMARTLIST_FOREACH_END(rs
);
3010 // Finally, check equality conditions depending upon case 1, 2 or 3
3011 // Full equality cases: 1, 3b
3012 // Partial equality cases: 2b (E=G), 3a (M=E)
3013 // Fully unknown: 2a
3014 if (3*E
>= T
&& 3*G
>= T
) {
3015 // Case 1: Neither are scarce
3016 casename
= "Case 1";
3017 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
3019 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3020 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3022 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3023 casename
, Etotal
, Mtotal
,
3024 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3025 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3026 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3029 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
3031 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3032 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3034 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3035 casename
, Etotal
, Gtotal
,
3036 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3037 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3038 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3041 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
3043 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3044 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3046 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3047 casename
, Mtotal
, Gtotal
,
3048 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3049 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3050 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3053 } else if (3*E
< T
&& 3*G
< T
) {
3054 int64_t R
= MIN(E
, G
);
3055 int64_t S
= MAX(E
, G
);
3057 * Case 2: Both Guards and Exits are scarce
3058 * Balance D between E and G, depending upon
3059 * D capacity and scarcity. Devote no extra
3060 * bandwidth to middle nodes.
3062 if (R
+D
< S
) { // Subcase a
3063 double Rtotal
, Stotal
;
3071 casename
= "Case 2a";
3073 if (Rtotal
> Stotal
) {
3075 "Bw Weight Failure for %s: Rtotal %f > Stotal %f. "
3076 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3078 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3079 casename
, Rtotal
, Stotal
,
3080 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3081 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3082 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3088 "Bw Weight Failure for %s: 3*Rtotal %f > T "
3089 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
3090 " D="I64_FORMAT
" T="I64_FORMAT
". "
3091 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3092 casename
, Rtotal
*3, I64_PRINTF_ARG(T
),
3093 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3094 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3095 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3101 "Bw Weight Failure for %s: 3*Stotal %f > T "
3102 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
3103 " D="I64_FORMAT
" T="I64_FORMAT
". "
3104 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3105 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
3106 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3107 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3108 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3114 "Bw Weight Failure for %s: 3*Mtotal %f < T "
3116 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3118 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3119 casename
, Mtotal
*3, I64_PRINTF_ARG(T
),
3120 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3121 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3122 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3125 } else { // Subcase b: R+D > S
3126 casename
= "Case 2b";
3128 /* Check the rare-M redirect case. */
3129 if (D
!= 0 && 3*M
< T
) {
3130 casename
= "Case 2b (balanced)";
3131 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
3133 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3134 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3136 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3137 casename
, Etotal
, Mtotal
,
3138 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3139 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3140 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3143 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
3145 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3146 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3148 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3149 casename
, Etotal
, Gtotal
,
3150 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3151 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3152 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3155 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
3157 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3158 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3160 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3161 casename
, Mtotal
, Gtotal
,
3162 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3163 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3164 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3168 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
3170 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3171 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3173 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3174 casename
, Etotal
, Gtotal
,
3175 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3176 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3177 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3182 } else { // if (E < T/3 || G < T/3) {
3183 int64_t S
= MIN(E
, G
);
3184 int64_t NS
= MAX(E
, G
);
3185 if (3*(S
+D
) < T
) { // Subcase a:
3189 casename
= "Case 3a (G scarce)";
3192 } else { // if (G >= E) {
3193 casename
= "Case 3a (E scarce)";
3200 "Bw Weight Failure for %s: 3*Stotal %f > T "
3201 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
3202 " D="I64_FORMAT
" T="I64_FORMAT
". "
3203 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3204 casename
, Stotal
*3, I64_PRINTF_ARG(T
),
3205 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3206 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3207 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3211 if (fabs(NStotal
-Mtotal
) > 0.01*MAX(NStotal
,Mtotal
)) {
3213 "Bw Weight Failure for %s: NStotal %f != Mtotal %f. "
3214 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3216 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3217 casename
, NStotal
, Mtotal
,
3218 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3219 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3220 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3224 // if NS < M, NStotal > T/3 because only one of G or E is scarce
3225 if (3*NStotal
< T
) {
3227 "Bw Weight Failure for %s: 3*NStotal %f < T "
3228 I64_FORMAT
". G="I64_FORMAT
" M="I64_FORMAT
3229 " E="I64_FORMAT
" D="I64_FORMAT
" T="I64_FORMAT
". "
3230 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3231 casename
, NStotal
*3, I64_PRINTF_ARG(T
),
3232 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3233 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3234 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3238 } else { // Subcase b: S+D >= T/3
3239 casename
= "Case 3b";
3240 if (fabs(Etotal
-Mtotal
) > 0.01*MAX(Etotal
,Mtotal
)) {
3242 "Bw Weight Failure for %s: Etotal %f != Mtotal %f. "
3243 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3245 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3246 casename
, Etotal
, Mtotal
,
3247 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3248 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3249 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3252 if (fabs(Etotal
-Gtotal
) > 0.01*MAX(Etotal
,Gtotal
)) {
3254 "Bw Weight Failure for %s: Etotal %f != Gtotal %f. "
3255 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3257 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3258 casename
, Etotal
, Gtotal
,
3259 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3260 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3261 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3264 if (fabs(Gtotal
-Mtotal
) > 0.01*MAX(Gtotal
,Mtotal
)) {
3266 "Bw Weight Failure for %s: Mtotal %f != Gtotal %f. "
3267 "G="I64_FORMAT
" M="I64_FORMAT
" E="I64_FORMAT
" D="I64_FORMAT
3269 "Wgg=%f Wgd=%f Wmg=%f Wme=%f Wmd=%f Wee=%f Wed=%f",
3270 casename
, Mtotal
, Gtotal
,
3271 I64_PRINTF_ARG(G
), I64_PRINTF_ARG(M
), I64_PRINTF_ARG(E
),
3272 I64_PRINTF_ARG(D
), I64_PRINTF_ARG(T
),
3273 Wgg
, Wgd
, Wmg
, Wme
, Wmd
, Wee
, Wed
);
3280 log_notice(LD_DIR
, "Bandwidth-weight %s is verified and valid.",
3286 /** Parse and extract all SR commits from <b>tokens</b> and place them in
3289 extract_shared_random_commits(networkstatus_t
*ns
, smartlist_t
*tokens
)
3291 smartlist_t
*chunks
= NULL
;
3295 /* Commits are only present in a vote. */
3296 tor_assert(ns
->type
== NS_TYPE_VOTE
);
3298 ns
->sr_info
.commits
= smartlist_new();
3300 smartlist_t
*commits
= find_all_by_keyword(tokens
, K_COMMIT
);
3301 /* It's normal that a vote might contain no commits even if it participates
3302 * in the SR protocol. Don't treat it as an error. */
3303 if (commits
== NULL
) {
3307 /* Parse the commit. We do NO validation of number of arguments or ordering
3308 * for forward compatibility, it's the parse commit job to inform us if it's
3309 * supported or not. */
3310 chunks
= smartlist_new();
3311 SMARTLIST_FOREACH_BEGIN(commits
, directory_token_t
*, tok
) {
3312 /* Extract all arguments and put them in the chunks list. */
3313 for (int i
= 0; i
< tok
->n_args
; i
++) {
3314 smartlist_add(chunks
, tok
->args
[i
]);
3316 sr_commit_t
*commit
= sr_parse_commit(chunks
);
3317 smartlist_clear(chunks
);
3318 if (commit
== NULL
) {
3319 /* Get voter identity so we can warn that this dirauth vote contains
3320 * commit we can't parse. */
3321 networkstatus_voter_info_t
*voter
= smartlist_get(ns
->voters
, 0);
3323 log_warn(LD_DIR
, "SR: Unable to parse commit %s from vote of voter %s.",
3324 escaped(tok
->object_body
),
3325 hex_str(voter
->identity_digest
,
3326 sizeof(voter
->identity_digest
)));
3327 /* Commitment couldn't be parsed. Continue onto the next commit because
3328 * this one could be unsupported for instance. */
3331 /* Add newly created commit object to the vote. */
3332 smartlist_add(ns
->sr_info
.commits
, commit
);
3333 } SMARTLIST_FOREACH_END(tok
);
3336 smartlist_free(chunks
);
3337 smartlist_free(commits
);
3340 /** Check if a shared random value of type <b>srv_type</b> is in
3341 * <b>tokens</b>. If there is, parse it and set it to <b>srv_out</b>. Return
3342 * -1 on failure, 0 on success. The resulting srv is allocated on the heap and
3343 * it's the responsibility of the caller to free it. */
3345 extract_one_srv(smartlist_t
*tokens
, directory_keyword srv_type
,
3349 directory_token_t
*tok
;
3350 sr_srv_t
*srv
= NULL
;
3351 smartlist_t
*chunks
;
3355 chunks
= smartlist_new();
3356 tok
= find_opt_by_keyword(tokens
, srv_type
);
3358 /* That's fine, no SRV is allowed. */
3362 for (int i
= 0; i
< tok
->n_args
; i
++) {
3363 smartlist_add(chunks
, tok
->args
[i
]);
3365 srv
= sr_parse_srv(chunks
);
3367 log_warn(LD_DIR
, "SR: Unparseable SRV %s", escaped(tok
->object_body
));
3374 smartlist_free(chunks
);
3378 /** Extract any shared random values found in <b>tokens</b> and place them in
3379 * the networkstatus <b>ns</b>. */
3381 extract_shared_random_srvs(networkstatus_t
*ns
, smartlist_t
*tokens
)
3383 const char *voter_identity
;
3384 networkstatus_voter_info_t
*voter
;
3388 /* Can be only one of them else code flow. */
3389 tor_assert(ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_CONSENSUS
);
3391 if (ns
->type
== NS_TYPE_VOTE
) {
3392 voter
= smartlist_get(ns
->voters
, 0);
3394 voter_identity
= hex_str(voter
->identity_digest
,
3395 sizeof(voter
->identity_digest
));
3397 /* Consensus has multiple voters so no specific voter. */
3398 voter_identity
= "consensus";
3401 /* We extract both, and on error everything is stopped because it means
3402 * the vote is malformed for the shared random value(s). */
3403 if (extract_one_srv(tokens
, K_PREVIOUS_SRV
, &ns
->sr_info
.previous_srv
) < 0) {
3404 log_warn(LD_DIR
, "SR: Unable to parse previous SRV from %s",
3406 /* Maybe we have a chance with the current SRV so let's try it anyway. */
3408 if (extract_one_srv(tokens
, K_CURRENT_SRV
, &ns
->sr_info
.current_srv
) < 0) {
3409 log_warn(LD_DIR
, "SR: Unable to parse current SRV from %s",
3414 /** Parse a v3 networkstatus vote, opinion, or consensus (depending on
3415 * ns_type), from <b>s</b>, and return the result. Return NULL on failure. */
3417 networkstatus_parse_vote_from_string(const char *s
, const char **eos_out
,
3418 networkstatus_type_t ns_type
)
3420 smartlist_t
*tokens
= smartlist_new();
3421 smartlist_t
*rs_tokens
= NULL
, *footer_tokens
= NULL
;
3422 networkstatus_voter_info_t
*voter
= NULL
;
3423 networkstatus_t
*ns
= NULL
;
3424 common_digests_t ns_digests
;
3425 uint8_t sha3_as_signed
[DIGEST256_LEN
];
3426 const char *cert
, *end_of_header
, *end_of_footer
, *s_dup
= s
;
3427 directory_token_t
*tok
;
3429 int i
, inorder
, n_signatures
= 0;
3430 memarea_t
*area
= NULL
, *rs_area
= NULL
;
3431 consensus_flavor_t flav
= FLAV_NS
;
3432 char *last_kwd
=NULL
;
3439 if (router_get_networkstatus_v3_hashes(s
, &ns_digests
) ||
3440 router_get_networkstatus_v3_sha3_as_signed(sha3_as_signed
, s
)<0) {
3441 log_warn(LD_DIR
, "Unable to compute digest of network-status");
3445 area
= memarea_new();
3446 end_of_header
= find_start_of_next_routerstatus(s
);
3447 if (tokenize_string(area
, s
, end_of_header
, tokens
,
3448 (ns_type
== NS_TYPE_CONSENSUS
) ?
3449 networkstatus_consensus_token_table
:
3450 networkstatus_token_table
, 0)) {
3451 log_warn(LD_DIR
, "Error tokenizing network-status header");
3455 ns
= tor_malloc_zero(sizeof(networkstatus_t
));
3456 memcpy(&ns
->digests
, &ns_digests
, sizeof(ns_digests
));
3457 memcpy(&ns
->digest_sha3_as_signed
, sha3_as_signed
, sizeof(sha3_as_signed
));
3459 tok
= find_by_keyword(tokens
, K_NETWORK_STATUS_VERSION
);
3461 if (tok
->n_args
> 1) {
3462 int flavor
= networkstatus_parse_flavor_name(tok
->args
[1]);
3464 log_warn(LD_DIR
, "Can't parse document with unknown flavor %s",
3465 escaped(tok
->args
[1]));
3468 ns
->flavor
= flav
= flavor
;
3470 if (flav
!= FLAV_NS
&& ns_type
!= NS_TYPE_CONSENSUS
) {
3471 log_warn(LD_DIR
, "Flavor found on non-consensus networkstatus.");
3475 if (ns_type
!= NS_TYPE_CONSENSUS
) {
3476 const char *end_of_cert
= NULL
;
3477 if (!(cert
= strstr(s
, "\ndir-key-certificate-version")))
3480 ns
->cert
= authority_cert_parse_from_string(cert
, &end_of_cert
);
3481 if (!ns
->cert
|| !end_of_cert
|| end_of_cert
> end_of_header
)
3485 tok
= find_by_keyword(tokens
, K_VOTE_STATUS
);
3486 tor_assert(tok
->n_args
);
3487 if (!strcmp(tok
->args
[0], "vote")) {
3488 ns
->type
= NS_TYPE_VOTE
;
3489 } else if (!strcmp(tok
->args
[0], "consensus")) {
3490 ns
->type
= NS_TYPE_CONSENSUS
;
3491 } else if (!strcmp(tok
->args
[0], "opinion")) {
3492 ns
->type
= NS_TYPE_OPINION
;
3494 log_warn(LD_DIR
, "Unrecognized vote status %s in network-status",
3495 escaped(tok
->args
[0]));
3498 if (ns_type
!= ns
->type
) {
3499 log_warn(LD_DIR
, "Got the wrong kind of v3 networkstatus.");
3503 if (ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_OPINION
) {
3504 tok
= find_by_keyword(tokens
, K_PUBLISHED
);
3505 if (parse_iso_time(tok
->args
[0], &ns
->published
))
3508 ns
->supported_methods
= smartlist_new();
3509 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHODS
);
3511 for (i
=0; i
< tok
->n_args
; ++i
)
3512 smartlist_add_strdup(ns
->supported_methods
, tok
->args
[i
]);
3514 smartlist_add_strdup(ns
->supported_methods
, "1");
3517 tok
= find_opt_by_keyword(tokens
, K_CONSENSUS_METHOD
);
3520 ns
->consensus_method
= (int)tor_parse_long(tok
->args
[0], 10, 1, INT_MAX
,
3525 ns
->consensus_method
= 1;
3529 if ((tok
= find_opt_by_keyword(tokens
, K_RECOMMENDED_CLIENT_PROTOCOLS
)))
3530 ns
->recommended_client_protocols
= tor_strdup(tok
->args
[0]);
3531 if ((tok
= find_opt_by_keyword(tokens
, K_RECOMMENDED_RELAY_PROTOCOLS
)))
3532 ns
->recommended_relay_protocols
= tor_strdup(tok
->args
[0]);
3533 if ((tok
= find_opt_by_keyword(tokens
, K_REQUIRED_CLIENT_PROTOCOLS
)))
3534 ns
->required_client_protocols
= tor_strdup(tok
->args
[0]);
3535 if ((tok
= find_opt_by_keyword(tokens
, K_REQUIRED_RELAY_PROTOCOLS
)))
3536 ns
->required_relay_protocols
= tor_strdup(tok
->args
[0]);
3538 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
3539 if (parse_iso_time(tok
->args
[0], &ns
->valid_after
))
3542 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
3543 if (parse_iso_time(tok
->args
[0], &ns
->fresh_until
))
3546 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
3547 if (parse_iso_time(tok
->args
[0], &ns
->valid_until
))
3550 tok
= find_by_keyword(tokens
, K_VOTING_DELAY
);
3551 tor_assert(tok
->n_args
>= 2);
3555 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &ok
, NULL
);
3559 (int) tor_parse_long(tok
->args
[1], 10, 0, INT_MAX
, &ok
, NULL
);
3563 if (ns
->valid_after
+
3564 (get_options()->TestingTorNetwork
?
3565 MIN_VOTE_INTERVAL_TESTING
: MIN_VOTE_INTERVAL
) > ns
->fresh_until
) {
3566 log_warn(LD_DIR
, "Vote/consensus freshness interval is too short");
3569 if (ns
->valid_after
+
3570 (get_options()->TestingTorNetwork
?
3571 MIN_VOTE_INTERVAL_TESTING
: MIN_VOTE_INTERVAL
)*2 > ns
->valid_until
) {
3572 log_warn(LD_DIR
, "Vote/consensus liveness interval is too short");
3575 if (ns
->vote_seconds
< MIN_VOTE_SECONDS
) {
3576 log_warn(LD_DIR
, "Vote seconds is too short");
3579 if (ns
->dist_seconds
< MIN_DIST_SECONDS
) {
3580 log_warn(LD_DIR
, "Dist seconds is too short");
3584 if ((tok
= find_opt_by_keyword(tokens
, K_CLIENT_VERSIONS
))) {
3585 ns
->client_versions
= tor_strdup(tok
->args
[0]);
3587 if ((tok
= find_opt_by_keyword(tokens
, K_SERVER_VERSIONS
))) {
3588 ns
->server_versions
= tor_strdup(tok
->args
[0]);
3592 smartlist_t
*package_lst
= find_all_by_keyword(tokens
, K_PACKAGE
);
3593 ns
->package_lines
= smartlist_new();
3595 SMARTLIST_FOREACH(package_lst
, directory_token_t
*, t
,
3596 smartlist_add_strdup(ns
->package_lines
, t
->args
[0]));
3598 smartlist_free(package_lst
);
3601 tok
= find_by_keyword(tokens
, K_KNOWN_FLAGS
);
3602 ns
->known_flags
= smartlist_new();
3604 for (i
= 0; i
< tok
->n_args
; ++i
) {
3605 smartlist_add_strdup(ns
->known_flags
, tok
->args
[i
]);
3606 if (i
>0 && strcmp(tok
->args
[i
-1], tok
->args
[i
])>= 0) {
3607 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
3612 log_warn(LD_DIR
, "known-flags not in order");
3615 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3616 smartlist_len(ns
->known_flags
) > MAX_KNOWN_FLAGS_IN_VOTE
) {
3617 /* If we allowed more than 64 flags in votes, then parsing them would make
3618 * us invoke undefined behavior whenever we used 1<<flagnum to do a
3619 * bit-shift. This is only for votes and opinions: consensus users don't
3620 * care about flags they don't recognize, and so don't build a bitfield
3622 log_warn(LD_DIR
, "Too many known-flags in consensus vote or opinion");
3626 tok
= find_opt_by_keyword(tokens
, K_PARAMS
);
3630 ns
->net_params
= smartlist_new();
3631 for (i
= 0; i
< tok
->n_args
; ++i
) {
3633 char *eq
= strchr(tok
->args
[i
], '=');
3636 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3639 eq_pos
= eq
-tok
->args
[i
];
3640 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
3642 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3645 if (i
> 0 && strcmp(tok
->args
[i
-1], tok
->args
[i
]) >= 0) {
3646 log_warn(LD_DIR
, "%s >= %s", tok
->args
[i
-1], tok
->args
[i
]);
3649 if (last_kwd
&& eq_pos
== strlen(last_kwd
) &&
3650 fast_memeq(last_kwd
, tok
->args
[i
], eq_pos
)) {
3651 log_warn(LD_DIR
, "Duplicate value for %s parameter",
3652 escaped(tok
->args
[i
]));
3656 last_kwd
= tor_strndup(tok
->args
[i
], eq_pos
);
3657 smartlist_add_strdup(ns
->net_params
, tok
->args
[i
]);
3660 log_warn(LD_DIR
, "params not in order");
3664 log_warn(LD_DIR
, "Duplicate in parameters");
3669 ns
->voters
= smartlist_new();
3671 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
3673 if (tok
->tp
== K_DIR_SOURCE
) {
3674 tor_assert(tok
->n_args
>= 6);
3677 smartlist_add(ns
->voters
, voter
);
3678 voter
= tor_malloc_zero(sizeof(networkstatus_voter_info_t
));
3679 voter
->sigs
= smartlist_new();
3680 if (ns
->type
!= NS_TYPE_CONSENSUS
)
3681 memcpy(voter
->vote_digest
, ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
);
3683 voter
->nickname
= tor_strdup(tok
->args
[0]);
3684 if (strlen(tok
->args
[1]) != HEX_DIGEST_LEN
||
3685 base16_decode(voter
->identity_digest
, sizeof(voter
->identity_digest
),
3686 tok
->args
[1], HEX_DIGEST_LEN
)
3687 != sizeof(voter
->identity_digest
)) {
3688 log_warn(LD_DIR
, "Error decoding identity digest %s in "
3689 "network-status document.", escaped(tok
->args
[1]));
3692 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3693 tor_memneq(ns
->cert
->cache_info
.identity_digest
,
3694 voter
->identity_digest
, DIGEST_LEN
)) {
3695 log_warn(LD_DIR
,"Mismatch between identities in certificate and vote");
3698 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3699 if (authority_cert_is_blacklisted(ns
->cert
)) {
3700 log_warn(LD_DIR
, "Rejecting vote signature made with blacklisted "
3702 hex_str(ns
->cert
->signing_key_digest
, DIGEST_LEN
));
3706 voter
->address
= tor_strdup(tok
->args
[2]);
3707 if (!tor_inet_aton(tok
->args
[3], &in
)) {
3708 log_warn(LD_DIR
, "Error decoding IP address %s in network-status.",
3709 escaped(tok
->args
[3]));
3712 voter
->addr
= ntohl(in
.s_addr
);
3714 voter
->dir_port
= (uint16_t)
3715 tor_parse_long(tok
->args
[4], 10, 0, 65535, &ok
, NULL
);
3718 voter
->or_port
= (uint16_t)
3719 tor_parse_long(tok
->args
[5], 10, 0, 65535, &ok
, NULL
);
3722 } else if (tok
->tp
== K_CONTACT
) {
3723 if (!voter
|| voter
->contact
) {
3724 log_warn(LD_DIR
, "contact element is out of place.");
3727 voter
->contact
= tor_strdup(tok
->args
[0]);
3728 } else if (tok
->tp
== K_VOTE_DIGEST
) {
3729 tor_assert(ns
->type
== NS_TYPE_CONSENSUS
);
3730 tor_assert(tok
->n_args
>= 1);
3731 if (!voter
|| ! tor_digest_is_zero(voter
->vote_digest
)) {
3732 log_warn(LD_DIR
, "vote-digest element is out of place.");
3735 if (strlen(tok
->args
[0]) != HEX_DIGEST_LEN
||
3736 base16_decode(voter
->vote_digest
, sizeof(voter
->vote_digest
),
3737 tok
->args
[0], HEX_DIGEST_LEN
)
3738 != sizeof(voter
->vote_digest
)) {
3739 log_warn(LD_DIR
, "Error decoding vote digest %s in "
3740 "network-status consensus.", escaped(tok
->args
[0]));
3744 } SMARTLIST_FOREACH_END(_tok
);
3746 smartlist_add(ns
->voters
, voter
);
3749 if (smartlist_len(ns
->voters
) == 0) {
3750 log_warn(LD_DIR
, "Missing dir-source elements in a networkstatus.");
3752 } else if (ns
->type
!= NS_TYPE_CONSENSUS
&& smartlist_len(ns
->voters
) != 1) {
3753 log_warn(LD_DIR
, "Too many dir-source elements in a vote networkstatus.");
3757 if (ns
->type
!= NS_TYPE_CONSENSUS
&&
3758 (tok
= find_opt_by_keyword(tokens
, K_LEGACY_DIR_KEY
))) {
3760 if (strlen(tok
->args
[0]) == HEX_DIGEST_LEN
) {
3761 networkstatus_voter_info_t
*voter_0
= smartlist_get(ns
->voters
, 0);
3762 if (base16_decode(voter_0
->legacy_id_digest
, DIGEST_LEN
,
3763 tok
->args
[0], HEX_DIGEST_LEN
) != DIGEST_LEN
)
3769 log_warn(LD_DIR
, "Invalid legacy key digest %s on vote.",
3770 escaped(tok
->args
[0]));
3774 /* If this is a vote document, check if information about the shared
3775 randomness protocol is included, and extract it. */
3776 if (ns
->type
== NS_TYPE_VOTE
) {
3777 /* Does this authority participates in the SR protocol? */
3778 tok
= find_opt_by_keyword(tokens
, K_SR_FLAG
);
3780 ns
->sr_info
.participate
= 1;
3781 /* Get the SR commitments and reveals from the vote. */
3782 extract_shared_random_commits(ns
, tokens
);
3785 /* For both a vote and consensus, extract the shared random values. */
3786 if (ns
->type
== NS_TYPE_VOTE
|| ns
->type
== NS_TYPE_CONSENSUS
) {
3787 extract_shared_random_srvs(ns
, tokens
);
3790 /* Parse routerstatus lines. */
3791 rs_tokens
= smartlist_new();
3792 rs_area
= memarea_new();
3794 ns
->routerstatus_list
= smartlist_new();
3796 while (!strcmpstart(s
, "r ")) {
3797 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3798 vote_routerstatus_t
*rs
= tor_malloc_zero(sizeof(vote_routerstatus_t
));
3799 if (routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
, ns
,
3801 smartlist_add(ns
->routerstatus_list
, rs
);
3803 vote_routerstatus_free(rs
);
3807 if ((rs
= routerstatus_parse_entry_from_string(rs_area
, &s
, rs_tokens
,
3809 ns
->consensus_method
,
3811 /* Use exponential-backoff scheduling when downloading microdescs */
3812 smartlist_add(ns
->routerstatus_list
, rs
);
3816 for (i
= 1; i
< smartlist_len(ns
->routerstatus_list
); ++i
) {
3817 routerstatus_t
*rs1
, *rs2
;
3818 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3819 vote_routerstatus_t
*a
= smartlist_get(ns
->routerstatus_list
, i
-1);
3820 vote_routerstatus_t
*b
= smartlist_get(ns
->routerstatus_list
, i
);
3821 rs1
= &a
->status
; rs2
= &b
->status
;
3823 rs1
= smartlist_get(ns
->routerstatus_list
, i
-1);
3824 rs2
= smartlist_get(ns
->routerstatus_list
, i
);
3826 if (fast_memcmp(rs1
->identity_digest
, rs2
->identity_digest
, DIGEST_LEN
)
3828 log_warn(LD_DIR
, "Networkstatus entries not sorted by identity digest");
3832 if (ns_type
!= NS_TYPE_CONSENSUS
) {
3833 digest256map_t
*ed_id_map
= digest256map_new();
3834 SMARTLIST_FOREACH_BEGIN(ns
->routerstatus_list
, vote_routerstatus_t
*,
3836 if (! vrs
->has_ed25519_listing
||
3837 tor_mem_is_zero((const char *)vrs
->ed25519_id
, DIGEST256_LEN
))
3839 if (digest256map_get(ed_id_map
, vrs
->ed25519_id
) != NULL
) {
3840 log_warn(LD_DIR
, "Vote networkstatus ed25519 identities were not "
3842 digest256map_free(ed_id_map
, NULL
);
3845 digest256map_set(ed_id_map
, vrs
->ed25519_id
, (void*)1);
3846 } SMARTLIST_FOREACH_END(vrs
);
3847 digest256map_free(ed_id_map
, NULL
);
3850 /* Parse footer; check signature. */
3851 footer_tokens
= smartlist_new();
3852 if ((end_of_footer
= strstr(s
, "\nnetwork-status-version ")))
3855 end_of_footer
= s
+ strlen(s
);
3856 if (tokenize_string(area
,s
, end_of_footer
, footer_tokens
,
3857 networkstatus_vote_footer_token_table
, 0)) {
3858 log_warn(LD_DIR
, "Error tokenizing network-status vote footer.");
3864 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
3866 if (tok
->tp
== K_DIRECTORY_SIGNATURE
)
3868 else if (found_sig
) {
3869 log_warn(LD_DIR
, "Extraneous token after first directory-signature");
3872 } SMARTLIST_FOREACH_END(_tok
);
3875 if ((tok
= find_opt_by_keyword(footer_tokens
, K_DIRECTORY_FOOTER
))) {
3876 if (tok
!= smartlist_get(footer_tokens
, 0)) {
3877 log_warn(LD_DIR
, "Misplaced directory-footer token");
3882 tok
= find_opt_by_keyword(footer_tokens
, K_BW_WEIGHTS
);
3884 ns
->weight_params
= smartlist_new();
3885 for (i
= 0; i
< tok
->n_args
; ++i
) {
3887 char *eq
= strchr(tok
->args
[i
], '=');
3889 log_warn(LD_DIR
, "Bad element '%s' in weight params",
3890 escaped(tok
->args
[i
]));
3893 tor_parse_long(eq
+1, 10, INT32_MIN
, INT32_MAX
, &ok
, NULL
);
3895 log_warn(LD_DIR
, "Bad element '%s' in params", escaped(tok
->args
[i
]));
3898 smartlist_add_strdup(ns
->weight_params
, tok
->args
[i
]);
3902 SMARTLIST_FOREACH_BEGIN(footer_tokens
, directory_token_t
*, _tok
) {
3903 char declared_identity
[DIGEST_LEN
];
3904 networkstatus_voter_info_t
*v
;
3905 document_signature_t
*sig
;
3906 const char *id_hexdigest
= NULL
;
3907 const char *sk_hexdigest
= NULL
;
3908 digest_algorithm_t alg
= DIGEST_SHA1
;
3910 if (tok
->tp
!= K_DIRECTORY_SIGNATURE
)
3912 tor_assert(tok
->n_args
>= 2);
3913 if (tok
->n_args
== 2) {
3914 id_hexdigest
= tok
->args
[0];
3915 sk_hexdigest
= tok
->args
[1];
3917 const char *algname
= tok
->args
[0];
3919 id_hexdigest
= tok
->args
[1];
3920 sk_hexdigest
= tok
->args
[2];
3921 a
= crypto_digest_algorithm_parse_name(algname
);
3923 log_warn(LD_DIR
, "Unknown digest algorithm %s; skipping",
3930 if (!tok
->object_type
||
3931 strcmp(tok
->object_type
, "SIGNATURE") ||
3932 tok
->object_size
< 128 || tok
->object_size
> 512) {
3933 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
3937 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
3938 base16_decode(declared_identity
, sizeof(declared_identity
),
3939 id_hexdigest
, HEX_DIGEST_LEN
)
3940 != sizeof(declared_identity
)) {
3941 log_warn(LD_DIR
, "Error decoding declared identity %s in "
3942 "network-status document.", escaped(id_hexdigest
));
3945 if (!(v
= networkstatus_get_voter_by_id(ns
, declared_identity
))) {
3946 log_warn(LD_DIR
, "ID on signature on network-status document does "
3947 "not match any declared directory source.");
3950 sig
= tor_malloc_zero(sizeof(document_signature_t
));
3951 memcpy(sig
->identity_digest
, v
->identity_digest
, DIGEST_LEN
);
3953 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
3954 base16_decode(sig
->signing_key_digest
, sizeof(sig
->signing_key_digest
),
3955 sk_hexdigest
, HEX_DIGEST_LEN
)
3956 != sizeof(sig
->signing_key_digest
)) {
3957 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
3958 "network-status document.", escaped(sk_hexdigest
));
3963 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3964 if (tor_memneq(declared_identity
, ns
->cert
->cache_info
.identity_digest
,
3966 log_warn(LD_DIR
, "Digest mismatch between declared and actual on "
3967 "network-status vote.");
3973 if (voter_get_sig_by_algorithm(v
, sig
->alg
)) {
3974 /* We already parsed a vote with this algorithm from this voter. Use the
3976 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "We received a networkstatus "
3977 "that contains two signatures from the same voter with the same "
3978 "algorithm. Ignoring the second signature.");
3983 if (ns
->type
!= NS_TYPE_CONSENSUS
) {
3984 if (check_signature_token(ns_digests
.d
[DIGEST_SHA1
], DIGEST_LEN
,
3985 tok
, ns
->cert
->signing_key
, 0,
3986 "network-status document")) {
3990 sig
->good_signature
= 1;
3992 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
3996 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
3997 sig
->signature_len
= (int) tok
->object_size
;
3999 smartlist_add(v
->sigs
, sig
);
4002 } SMARTLIST_FOREACH_END(_tok
);
4004 if (! n_signatures
) {
4005 log_warn(LD_DIR
, "No signatures on networkstatus document.");
4007 } else if (ns
->type
== NS_TYPE_VOTE
&& n_signatures
!= 1) {
4008 log_warn(LD_DIR
, "Received more than one signature on a "
4009 "network-status vote.");
4014 *eos_out
= end_of_footer
;
4018 dump_desc(s_dup
, "v3 networkstatus");
4019 networkstatus_vote_free(ns
);
4023 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4024 smartlist_free(tokens
);
4028 SMARTLIST_FOREACH(voter
->sigs
, document_signature_t
*, sig
,
4029 document_signature_free(sig
));
4030 smartlist_free(voter
->sigs
);
4032 tor_free(voter
->nickname
);
4033 tor_free(voter
->address
);
4034 tor_free(voter
->contact
);
4038 SMARTLIST_FOREACH(rs_tokens
, directory_token_t
*, t
, token_clear(t
));
4039 smartlist_free(rs_tokens
);
4041 if (footer_tokens
) {
4042 SMARTLIST_FOREACH(footer_tokens
, directory_token_t
*, t
, token_clear(t
));
4043 smartlist_free(footer_tokens
);
4046 DUMP_AREA(area
, "v3 networkstatus");
4047 memarea_drop_all(area
);
4050 memarea_drop_all(rs_area
);
4056 /** Return the common_digests_t that holds the digests of the
4057 * <b>flavor_name</b>-flavored networkstatus according to the detached
4058 * signatures document <b>sigs</b>, allocating a new common_digests_t as
4060 static common_digests_t
*
4061 detached_get_digests(ns_detached_signatures_t
*sigs
, const char *flavor_name
)
4063 common_digests_t
*d
= strmap_get(sigs
->digests
, flavor_name
);
4065 d
= tor_malloc_zero(sizeof(common_digests_t
));
4066 strmap_set(sigs
->digests
, flavor_name
, d
);
4071 /** Return the list of signatures of the <b>flavor_name</b>-flavored
4072 * networkstatus according to the detached signatures document <b>sigs</b>,
4073 * allocating a new common_digests_t as needed. */
4074 static smartlist_t
*
4075 detached_get_signatures(ns_detached_signatures_t
*sigs
,
4076 const char *flavor_name
)
4078 smartlist_t
*sl
= strmap_get(sigs
->signatures
, flavor_name
);
4080 sl
= smartlist_new();
4081 strmap_set(sigs
->signatures
, flavor_name
, sl
);
4086 /** Parse a detached v3 networkstatus signature document between <b>s</b> and
4087 * <b>eos</b> and return the result. Return -1 on failure. */
4088 ns_detached_signatures_t
*
4089 networkstatus_parse_detached_signatures(const char *s
, const char *eos
)
4091 /* XXXX there is too much duplicate shared between this function and
4092 * networkstatus_parse_vote_from_string(). */
4093 directory_token_t
*tok
;
4094 memarea_t
*area
= NULL
;
4095 common_digests_t
*digests
;
4097 smartlist_t
*tokens
= smartlist_new();
4098 ns_detached_signatures_t
*sigs
=
4099 tor_malloc_zero(sizeof(ns_detached_signatures_t
));
4100 sigs
->digests
= strmap_new();
4101 sigs
->signatures
= strmap_new();
4104 eos
= s
+ strlen(s
);
4106 area
= memarea_new();
4107 if (tokenize_string(area
,s
, eos
, tokens
,
4108 networkstatus_detached_signature_token_table
, 0)) {
4109 log_warn(LD_DIR
, "Error tokenizing detached networkstatus signatures");
4113 /* Grab all the digest-like tokens. */
4114 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
4115 const char *algname
;
4116 digest_algorithm_t alg
;
4118 const char *hexdigest
;
4119 size_t expected_length
, digest_length
;
4123 if (tok
->tp
== K_CONSENSUS_DIGEST
) {
4127 hexdigest
= tok
->args
[0];
4128 } else if (tok
->tp
== K_ADDITIONAL_DIGEST
) {
4129 int a
= crypto_digest_algorithm_parse_name(tok
->args
[1]);
4131 log_warn(LD_DIR
, "Unrecognized algorithm name %s", tok
->args
[0]);
4134 alg
= (digest_algorithm_t
) a
;
4135 flavor
= tok
->args
[0];
4136 algname
= tok
->args
[1];
4137 hexdigest
= tok
->args
[2];
4142 digest_length
= crypto_digest_algorithm_get_length(alg
);
4143 expected_length
= digest_length
* 2; /* hex encoding */
4145 if (strlen(hexdigest
) != expected_length
) {
4146 log_warn(LD_DIR
, "Wrong length on consensus-digest in detached "
4147 "networkstatus signatures");
4150 digests
= detached_get_digests(sigs
, flavor
);
4151 tor_assert(digests
);
4152 if (!tor_mem_is_zero(digests
->d
[alg
], digest_length
)) {
4153 log_warn(LD_DIR
, "Multiple digests for %s with %s on detached "
4154 "signatures document", flavor
, algname
);
4157 if (base16_decode(digests
->d
[alg
], digest_length
,
4158 hexdigest
, strlen(hexdigest
)) != (int) digest_length
) {
4159 log_warn(LD_DIR
, "Bad encoding on consensus-digest in detached "
4160 "networkstatus signatures");
4163 } SMARTLIST_FOREACH_END(_tok
);
4165 tok
= find_by_keyword(tokens
, K_VALID_AFTER
);
4166 if (parse_iso_time(tok
->args
[0], &sigs
->valid_after
)) {
4167 log_warn(LD_DIR
, "Bad valid-after in detached networkstatus signatures");
4171 tok
= find_by_keyword(tokens
, K_FRESH_UNTIL
);
4172 if (parse_iso_time(tok
->args
[0], &sigs
->fresh_until
)) {
4173 log_warn(LD_DIR
, "Bad fresh-until in detached networkstatus signatures");
4177 tok
= find_by_keyword(tokens
, K_VALID_UNTIL
);
4178 if (parse_iso_time(tok
->args
[0], &sigs
->valid_until
)) {
4179 log_warn(LD_DIR
, "Bad valid-until in detached networkstatus signatures");
4183 SMARTLIST_FOREACH_BEGIN(tokens
, directory_token_t
*, _tok
) {
4184 const char *id_hexdigest
;
4185 const char *sk_hexdigest
;
4186 const char *algname
;
4188 digest_algorithm_t alg
;
4190 char id_digest
[DIGEST_LEN
];
4191 char sk_digest
[DIGEST_LEN
];
4192 smartlist_t
*siglist
;
4193 document_signature_t
*sig
;
4197 if (tok
->tp
== K_DIRECTORY_SIGNATURE
) {
4198 tor_assert(tok
->n_args
>= 2);
4201 id_hexdigest
= tok
->args
[0];
4202 sk_hexdigest
= tok
->args
[1];
4203 } else if (tok
->tp
== K_ADDITIONAL_SIGNATURE
) {
4204 tor_assert(tok
->n_args
>= 4);
4205 flavor
= tok
->args
[0];
4206 algname
= tok
->args
[1];
4207 id_hexdigest
= tok
->args
[2];
4208 sk_hexdigest
= tok
->args
[3];
4214 int a
= crypto_digest_algorithm_parse_name(algname
);
4216 log_warn(LD_DIR
, "Unrecognized algorithm name %s", algname
);
4219 alg
= (digest_algorithm_t
) a
;
4222 if (!tok
->object_type
||
4223 strcmp(tok
->object_type
, "SIGNATURE") ||
4224 tok
->object_size
< 128 || tok
->object_size
> 512) {
4225 log_warn(LD_DIR
, "Bad object type or length on directory-signature");
4229 if (strlen(id_hexdigest
) != HEX_DIGEST_LEN
||
4230 base16_decode(id_digest
, sizeof(id_digest
),
4231 id_hexdigest
, HEX_DIGEST_LEN
) != sizeof(id_digest
)) {
4232 log_warn(LD_DIR
, "Error decoding declared identity %s in "
4233 "network-status vote.", escaped(id_hexdigest
));
4236 if (strlen(sk_hexdigest
) != HEX_DIGEST_LEN
||
4237 base16_decode(sk_digest
, sizeof(sk_digest
),
4238 sk_hexdigest
, HEX_DIGEST_LEN
) != sizeof(sk_digest
)) {
4239 log_warn(LD_DIR
, "Error decoding declared signing key digest %s in "
4240 "network-status vote.", escaped(sk_hexdigest
));
4244 siglist
= detached_get_signatures(sigs
, flavor
);
4246 SMARTLIST_FOREACH(siglist
, document_signature_t
*, dsig
, {
4247 if (dsig
->alg
== alg
&&
4248 tor_memeq(id_digest
, dsig
->identity_digest
, DIGEST_LEN
) &&
4249 tor_memeq(sk_digest
, dsig
->signing_key_digest
, DIGEST_LEN
)) {
4254 log_warn(LD_DIR
, "Two signatures with identical keys and algorithm "
4259 sig
= tor_malloc_zero(sizeof(document_signature_t
));
4261 memcpy(sig
->identity_digest
, id_digest
, DIGEST_LEN
);
4262 memcpy(sig
->signing_key_digest
, sk_digest
, DIGEST_LEN
);
4263 if (tok
->object_size
>= INT_MAX
|| tok
->object_size
>= SIZE_T_CEILING
) {
4267 sig
->signature
= tor_memdup(tok
->object_body
, tok
->object_size
);
4268 sig
->signature_len
= (int) tok
->object_size
;
4270 smartlist_add(siglist
, sig
);
4271 } SMARTLIST_FOREACH_END(_tok
);
4275 ns_detached_signatures_free(sigs
);
4278 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4279 smartlist_free(tokens
);
4281 DUMP_AREA(area
, "detached signatures");
4282 memarea_drop_all(area
);
4287 /** Parse the addr policy in the string <b>s</b> and return it. If
4288 * assume_action is nonnegative, then insert its action (ADDR_POLICY_ACCEPT or
4289 * ADDR_POLICY_REJECT) for items that specify no action.
4291 * Returns NULL on policy errors.
4293 * Set *<b>malformed_list</b> to true if the entire policy list should be
4294 * discarded. Otherwise, set it to false, and only this item should be ignored
4295 * on error - the rest of the policy list can continue to be processed and
4298 * The addr_policy_t returned by this function can have its address set to
4299 * AF_UNSPEC for '*'. Use policy_expand_unspec() to turn this into a pair
4300 * of AF_INET and AF_INET6 items.
4302 MOCK_IMPL(addr_policy_t
*,
4303 router_parse_addr_policy_item_from_string
,(const char *s
, int assume_action
,
4304 int *malformed_list
))
4306 directory_token_t
*tok
= NULL
;
4307 const char *cp
, *eos
;
4308 /* Longest possible policy is
4309 * "accept6 [ffff:ffff:..255]/128:10000-65535",
4310 * which contains a max-length IPv6 address, plus 26 characters.
4311 * But note that there can be an arbitrary amount of space between the
4312 * accept and the address:mask/port element.
4313 * We don't need to multiply TOR_ADDR_BUF_LEN by 2, as there is only one
4314 * IPv6 address. But making the buffer shorter might cause valid long lines,
4315 * which parsed in previous versions, to fail to parse in new versions.
4316 * (These lines would have to have excessive amounts of whitespace.) */
4317 char line
[TOR_ADDR_BUF_LEN
*2 + 32];
4319 memarea_t
*area
= NULL
;
4321 tor_assert(malformed_list
);
4322 *malformed_list
= 0;
4324 s
= eat_whitespace(s
);
4325 /* We can only do assume_action on []-quoted IPv6, as "a" (accept)
4326 * and ":" (port separator) are ambiguous */
4327 if ((*s
== '*' || *s
== '[' || TOR_ISDIGIT(*s
)) && assume_action
>= 0) {
4328 if (tor_snprintf(line
, sizeof(line
), "%s %s",
4329 assume_action
== ADDR_POLICY_ACCEPT
?"accept":"reject", s
)<0) {
4330 log_warn(LD_DIR
, "Policy %s is too long.", escaped(s
));
4335 } else { /* assume an already well-formed address policy line */
4339 eos
= cp
+ strlen(cp
);
4340 area
= memarea_new();
4341 tok
= get_next_token(area
, &cp
, eos
, routerdesc_token_table
);
4342 if (tok
->tp
== ERR_
) {
4343 log_warn(LD_DIR
, "Error reading address policy: %s", tok
->error
);
4346 if (tok
->tp
!= K_ACCEPT
&& tok
->tp
!= K_ACCEPT6
&&
4347 tok
->tp
!= K_REJECT
&& tok
->tp
!= K_REJECT6
) {
4348 log_warn(LD_DIR
, "Expected 'accept' or 'reject'.");
4352 /* Use the extended interpretation of accept/reject *,
4353 * expanding it into an IPv4 wildcard and an IPv6 wildcard.
4354 * Also permit *4 and *6 for IPv4 and IPv6 only wildcards. */
4355 r
= router_parse_addr_policy(tok
, TAPMP_EXTENDED_STAR
);
4360 /* Ensure that accept6/reject6 fields are followed by IPv6 addresses.
4361 * AF_UNSPEC addresses are only permitted on the accept/reject field type.
4362 * Unlike descriptors, torrcs exit policy accept/reject can be followed by
4363 * either an IPv4 or IPv6 address. */
4364 if ((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
4365 tor_addr_family(&r
->addr
) != AF_INET6
) {
4366 /* This is a non-fatal error, just ignore this one entry. */
4367 *malformed_list
= 0;
4368 log_warn(LD_DIR
, "IPv4 address '%s' with accept6/reject6 field type in "
4369 "exit policy. Ignoring, but continuing to parse rules. (Use "
4370 "accept/reject with IPv4 addresses.)",
4371 tok
->n_args
== 1 ? tok
->args
[0] : "");
4372 addr_policy_free(r
);
4379 *malformed_list
= 1;
4384 DUMP_AREA(area
, "policy item");
4385 memarea_drop_all(area
);
4390 /** Add an exit policy stored in the token <b>tok</b> to the router info in
4391 * <b>router</b>. Return 0 on success, -1 on failure. */
4393 router_add_exit_policy(routerinfo_t
*router
, directory_token_t
*tok
)
4395 addr_policy_t
*newe
;
4396 /* Use the standard interpretation of accept/reject *, an IPv4 wildcard. */
4397 newe
= router_parse_addr_policy(tok
, 0);
4400 if (! router
->exit_policy
)
4401 router
->exit_policy
= smartlist_new();
4403 /* Ensure that in descriptors, accept/reject fields are followed by
4404 * IPv4 addresses, and accept6/reject6 fields are followed by
4405 * IPv6 addresses. Unlike torrcs, descriptor exit policies do not permit
4406 * accept/reject followed by IPv6. */
4407 if (((tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) &&
4408 tor_addr_family(&newe
->addr
) == AF_INET
)
4410 ((tok
->tp
== K_ACCEPT
|| tok
->tp
== K_REJECT
) &&
4411 tor_addr_family(&newe
->addr
) == AF_INET6
)) {
4412 /* There's nothing the user can do about other relays' descriptors,
4413 * so we don't provide usage advice here. */
4414 log_warn(LD_DIR
, "Mismatch between field type and address type in exit "
4415 "policy '%s'. Discarding entire router descriptor.",
4416 tok
->n_args
== 1 ? tok
->args
[0] : "");
4417 addr_policy_free(newe
);
4421 smartlist_add(router
->exit_policy
, newe
);
4426 /** Given a K_ACCEPT[6] or K_REJECT[6] token and a router, create and return
4427 * a new exit_policy_t corresponding to the token. If TAPMP_EXTENDED_STAR
4428 * is set in fmt_flags, K_ACCEPT6 and K_REJECT6 tokens followed by *
4429 * expand to IPv6-only policies, otherwise they expand to IPv4 and IPv6
4431 static addr_policy_t
*
4432 router_parse_addr_policy(directory_token_t
*tok
, unsigned fmt_flags
)
4437 tor_assert(tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
||
4438 tok
->tp
== K_ACCEPT
|| tok
->tp
== K_ACCEPT6
);
4440 if (tok
->n_args
!= 1)
4444 if (!strcmpstart(arg
,"private"))
4445 return router_parse_addr_policy_private(tok
);
4447 memset(&newe
, 0, sizeof(newe
));
4449 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
4450 newe
.policy_type
= ADDR_POLICY_REJECT
;
4452 newe
.policy_type
= ADDR_POLICY_ACCEPT
;
4454 /* accept6/reject6 * produces an IPv6 wildcard address only.
4455 * (accept/reject * produces rules for IPv4 and IPv6 wildcard addresses.) */
4456 if ((fmt_flags
& TAPMP_EXTENDED_STAR
)
4457 && (tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
)) {
4458 fmt_flags
|= TAPMP_STAR_IPV6_ONLY
;
4461 if (tor_addr_parse_mask_ports(arg
, fmt_flags
, &newe
.addr
, &newe
.maskbits
,
4462 &newe
.prt_min
, &newe
.prt_max
) < 0) {
4463 log_warn(LD_DIR
,"Couldn't parse line %s. Dropping", escaped(arg
));
4467 return addr_policy_get_canonical_entry(&newe
);
4470 /** Parse an exit policy line of the format "accept[6]/reject[6] private:...".
4471 * This didn't exist until Tor 0.1.1.15, so nobody should generate it in
4472 * router descriptors until earlier versions are obsolete.
4474 * accept/reject and accept6/reject6 private all produce rules for both
4475 * IPv4 and IPv6 addresses.
4477 static addr_policy_t
*
4478 router_parse_addr_policy_private(directory_token_t
*tok
)
4481 uint16_t port_min
, port_max
;
4482 addr_policy_t result
;
4485 if (strcmpstart(arg
, "private"))
4488 arg
+= strlen("private");
4489 arg
= (char*) eat_whitespace(arg
);
4490 if (!arg
|| *arg
!= ':')
4493 if (parse_port_range(arg
+1, &port_min
, &port_max
)<0)
4496 memset(&result
, 0, sizeof(result
));
4497 if (tok
->tp
== K_REJECT
|| tok
->tp
== K_REJECT6
)
4498 result
.policy_type
= ADDR_POLICY_REJECT
;
4500 result
.policy_type
= ADDR_POLICY_ACCEPT
;
4501 result
.is_private
= 1;
4502 result
.prt_min
= port_min
;
4503 result
.prt_max
= port_max
;
4505 if (tok
->tp
== K_ACCEPT6
|| tok
->tp
== K_REJECT6
) {
4506 log_warn(LD_GENERAL
,
4507 "'%s' expands into rules which apply to all private IPv4 and "
4508 "IPv6 addresses. (Use accept/reject private:* for IPv4 and "
4509 "IPv6.)", tok
->n_args
== 1 ? tok
->args
[0] : "");
4512 return addr_policy_get_canonical_entry(&result
);
4515 /** Log and exit if <b>t</b> is malformed */
4517 assert_addr_policy_ok(smartlist_t
*lst
)
4520 SMARTLIST_FOREACH(lst
, addr_policy_t
*, t
, {
4521 tor_assert(t
->policy_type
== ADDR_POLICY_REJECT
||
4522 t
->policy_type
== ADDR_POLICY_ACCEPT
);
4523 tor_assert(t
->prt_min
<= t
->prt_max
);
4527 /** Return a newly allocated smartlist of all accept or reject tokens in
4530 static smartlist_t
*
4531 find_all_exitpolicy(smartlist_t
*s
)
4533 smartlist_t
*out
= smartlist_new();
4534 SMARTLIST_FOREACH(s
, directory_token_t
*, t
,
4535 if (t
->tp
== K_ACCEPT
|| t
->tp
== K_ACCEPT6
||
4536 t
->tp
== K_REJECT
|| t
->tp
== K_REJECT6
)
4537 smartlist_add(out
,t
));
4541 /** Helper function for <b>router_get_hash_impl</b>: given <b>s</b>,
4542 * <b>s_len</b>, <b>start_str</b>, <b>end_str</b>, and <b>end_c</b> with the
4543 * same semantics as in that function, set *<b>start_out</b> (inclusive) and
4544 * *<b>end_out</b> (exclusive) to the boundaries of the string to be hashed.
4546 * Return 0 on success and -1 on failure.
4549 router_get_hash_impl_helper(const char *s
, size_t s_len
,
4550 const char *start_str
,
4551 const char *end_str
, char end_c
,
4553 const char **start_out
, const char **end_out
)
4555 const char *start
, *end
;
4556 start
= tor_memstr(s
, s_len
, start_str
);
4558 log_fn(log_severity
,LD_DIR
,
4559 "couldn't find start of hashed material \"%s\"",start_str
);
4562 if (start
!= s
&& *(start
-1) != '\n') {
4563 log_fn(log_severity
,LD_DIR
,
4564 "first occurrence of \"%s\" is not at the start of a line",
4568 end
= tor_memstr(start
+strlen(start_str
),
4569 s_len
- (start
-s
) - strlen(start_str
), end_str
);
4571 log_fn(log_severity
,LD_DIR
,
4572 "couldn't find end of hashed material \"%s\"",end_str
);
4575 end
= memchr(end
+strlen(end_str
), end_c
, s_len
- (end
-s
) - strlen(end_str
));
4577 log_fn(log_severity
,LD_DIR
,
4578 "couldn't find EOL");
4588 /** Compute the digest of the substring of <b>s</b> taken from the first
4589 * occurrence of <b>start_str</b> through the first instance of c after the
4590 * first subsequent occurrence of <b>end_str</b>; store the 20-byte or 32-byte
4591 * result in <b>digest</b>; return 0 on success.
4593 * If no such substring exists, return -1.
4596 router_get_hash_impl(const char *s
, size_t s_len
, char *digest
,
4597 const char *start_str
,
4598 const char *end_str
, char end_c
,
4599 digest_algorithm_t alg
)
4601 const char *start
=NULL
, *end
=NULL
;
4602 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,LOG_WARN
,
4606 return router_compute_hash_final(digest
, start
, end
-start
, alg
);
4609 /** Compute the digest of the <b>len</b>-byte directory object at
4610 * <b>start</b>, using <b>alg</b>. Store the result in <b>digest</b>, which
4611 * must be long enough to hold it. */
4612 MOCK_IMPL(STATIC
int,
4613 router_compute_hash_final
,(char *digest
,
4614 const char *start
, size_t len
,
4615 digest_algorithm_t alg
))
4617 if (alg
== DIGEST_SHA1
) {
4618 if (crypto_digest(digest
, start
, len
) < 0) {
4619 log_warn(LD_BUG
,"couldn't compute digest");
4623 if (crypto_digest256(digest
, start
, len
, alg
) < 0) {
4624 log_warn(LD_BUG
,"couldn't compute digest");
4632 /** As router_get_hash_impl, but compute all hashes. */
4634 router_get_hashes_impl(const char *s
, size_t s_len
, common_digests_t
*digests
,
4635 const char *start_str
,
4636 const char *end_str
, char end_c
)
4638 const char *start
=NULL
, *end
=NULL
;
4639 if (router_get_hash_impl_helper(s
,s_len
,start_str
,end_str
,end_c
,LOG_WARN
,
4643 if (crypto_common_digests(digests
, start
, end
-start
)) {
4644 log_warn(LD_BUG
,"couldn't compute digests");
4651 /** Assuming that s starts with a microdesc, return the start of the
4652 * *NEXT* one. Return NULL on "not found." */
4654 find_start_of_next_microdesc(const char *s
, const char *eos
)
4656 int started_with_annotations
;
4657 s
= eat_whitespace_eos(s
, eos
);
4661 #define CHECK_LENGTH() STMT_BEGIN \
4666 #define NEXT_LINE() STMT_BEGIN \
4667 s = memchr(s, '\n', eos-s); \
4668 if (!s || s+1 >= eos) \
4675 started_with_annotations
= (*s
== '@');
4677 if (started_with_annotations
) {
4678 /* Start by advancing to the first non-annotation line. */
4684 /* Now we should be pointed at an onion-key line. If we are, then skip
4686 if (!strcmpstart(s
, "onion-key"))
4689 /* Okay, now we're pointed at the first line of the microdescriptor which is
4690 not an annotation or onion-key. The next line that _is_ an annotation or
4691 onion-key is the start of the next microdescriptor. */
4692 while (s
+32 < eos
) {
4693 if (*s
== '@' || !strcmpstart(s
, "onion-key"))
4703 /** Parse as many microdescriptors as are found from the string starting at
4704 * <b>s</b> and ending at <b>eos</b>. If allow_annotations is set, read any
4705 * annotations we recognize and ignore ones we don't.
4707 * If <b>saved_location</b> isn't SAVED_IN_CACHE, make a local copy of each
4708 * descriptor in the body field of each microdesc_t.
4710 * Return all newly parsed microdescriptors in a newly allocated
4711 * smartlist_t. If <b>invalid_disgests_out</b> is provided, add a SHA256
4712 * microdesc digest to it for every microdesc that we found to be badly
4713 * formed. (This may cause duplicates) */
4715 microdescs_parse_from_string(const char *s
, const char *eos
,
4716 int allow_annotations
,
4717 saved_location_t where
,
4718 smartlist_t
*invalid_digests_out
)
4720 smartlist_t
*tokens
;
4721 smartlist_t
*result
;
4722 microdesc_t
*md
= NULL
;
4724 const char *start
= s
;
4725 const char *start_of_next_microdesc
;
4726 int flags
= allow_annotations
? TS_ANNOTATIONS_OK
: 0;
4727 const int copy_body
= (where
!= SAVED_IN_CACHE
);
4729 directory_token_t
*tok
;
4732 eos
= s
+ strlen(s
);
4734 s
= eat_whitespace_eos(s
, eos
);
4735 area
= memarea_new();
4736 result
= smartlist_new();
4737 tokens
= smartlist_new();
4742 start_of_next_microdesc
= find_start_of_next_microdesc(s
, eos
);
4743 if (!start_of_next_microdesc
)
4744 start_of_next_microdesc
= eos
;
4746 md
= tor_malloc_zero(sizeof(microdesc_t
));
4748 const char *cp
= tor_memstr(s
, start_of_next_microdesc
-s
,
4750 const int no_onion_key
= (cp
== NULL
);
4752 cp
= s
; /* So that we have *some* junk to put in the body */
4755 md
->bodylen
= start_of_next_microdesc
- cp
;
4756 md
->saved_location
= where
;
4758 md
->body
= tor_memdup_nulterm(cp
, md
->bodylen
);
4760 md
->body
= (char*)cp
;
4761 md
->off
= cp
- start
;
4762 crypto_digest256(md
->digest
, md
->body
, md
->bodylen
, DIGEST_SHA256
);
4764 log_fn(LOG_PROTOCOL_WARN
, LD_DIR
, "Malformed or truncated descriptor");
4769 if (tokenize_string(area
, s
, start_of_next_microdesc
, tokens
,
4770 microdesc_token_table
, flags
)) {
4771 log_warn(LD_DIR
, "Unparseable microdescriptor");
4775 if ((tok
= find_opt_by_keyword(tokens
, A_LAST_LISTED
))) {
4776 if (parse_iso_time(tok
->args
[0], &md
->last_listed
)) {
4777 log_warn(LD_DIR
, "Bad last-listed time in microdescriptor");
4782 tok
= find_by_keyword(tokens
, K_ONION_KEY
);
4783 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
4785 "Relay's onion key had invalid exponent.");
4788 md
->onion_pkey
= tok
->key
;
4791 if ((tok
= find_opt_by_keyword(tokens
, K_ONION_KEY_NTOR
))) {
4792 curve25519_public_key_t k
;
4793 tor_assert(tok
->n_args
>= 1);
4794 if (curve25519_public_from_base64(&k
, tok
->args
[0]) < 0) {
4795 log_warn(LD_DIR
, "Bogus ntor-onion-key in microdesc");
4798 md
->onion_curve25519_pkey
=
4799 tor_memdup(&k
, sizeof(curve25519_public_key_t
));
4802 smartlist_t
*id_lines
= find_all_by_keyword(tokens
, K_ID
);
4804 SMARTLIST_FOREACH_BEGIN(id_lines
, directory_token_t
*, t
) {
4805 tor_assert(t
->n_args
>= 2);
4806 if (!strcmp(t
->args
[0], "ed25519")) {
4807 if (md
->ed25519_identity_pkey
) {
4808 log_warn(LD_DIR
, "Extra ed25519 key in microdesc");
4809 smartlist_free(id_lines
);
4812 ed25519_public_key_t k
;
4813 if (ed25519_public_from_base64(&k
, t
->args
[1])<0) {
4814 log_warn(LD_DIR
, "Bogus ed25519 key in microdesc");
4815 smartlist_free(id_lines
);
4818 md
->ed25519_identity_pkey
= tor_memdup(&k
, sizeof(k
));
4820 } SMARTLIST_FOREACH_END(t
);
4821 smartlist_free(id_lines
);
4825 smartlist_t
*a_lines
= find_all_by_keyword(tokens
, K_A
);
4827 find_single_ipv6_orport(a_lines
, &md
->ipv6_addr
, &md
->ipv6_orport
);
4828 smartlist_free(a_lines
);
4832 if ((tok
= find_opt_by_keyword(tokens
, K_FAMILY
))) {
4834 md
->family
= smartlist_new();
4835 for (i
=0;i
<tok
->n_args
;++i
) {
4836 if (!is_legal_nickname_or_hexdigest(tok
->args
[i
])) {
4837 log_warn(LD_DIR
, "Illegal nickname %s in family line",
4838 escaped(tok
->args
[i
]));
4841 smartlist_add_strdup(md
->family
, tok
->args
[i
]);
4845 if ((tok
= find_opt_by_keyword(tokens
, K_P
))) {
4846 md
->exit_policy
= parse_short_policy(tok
->args
[0]);
4848 if ((tok
= find_opt_by_keyword(tokens
, K_P6
))) {
4849 md
->ipv6_exit_policy
= parse_short_policy(tok
->args
[0]);
4852 smartlist_add(result
, md
);
4857 if (! okay
&& invalid_digests_out
) {
4858 smartlist_add(invalid_digests_out
,
4859 tor_memdup(md
->digest
, DIGEST256_LEN
));
4864 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4865 memarea_clear(area
);
4866 smartlist_clear(tokens
);
4867 s
= start_of_next_microdesc
;
4870 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
4871 memarea_drop_all(area
);
4872 smartlist_free(tokens
);
4877 /** Extract a Tor version from a <b>platform</b> line from a router
4878 * descriptor, and place the result in <b>router_version</b>.
4880 * Return 1 on success, -1 on parsing failure, and 0 if the
4881 * platform line does not indicate some version of Tor.
4883 * If <b>strict</b> is non-zero, finding any weird version components
4884 * (like negative numbers) counts as a parsing failure.
4887 tor_version_parse_platform(const char *platform
,
4888 tor_version_t
*router_version
,
4892 char *s
, *s2
, *start
;
4894 if (strcmpstart(platform
,"Tor ")) /* nonstandard Tor; say 0. */
4897 start
= (char *)eat_whitespace(platform
+3);
4898 if (!*start
) return -1;
4899 s
= (char *)find_whitespace(start
); /* also finds '\0', which is fine */
4900 s2
= (char*)eat_whitespace(s
);
4901 if (!strcmpstart(s2
, "(r") || !strcmpstart(s2
, "(git-"))
4902 s
= (char*)find_whitespace(s2
);
4904 if ((size_t)(s
-start
+1) >= sizeof(tmp
)) /* too big, no */
4906 strlcpy(tmp
, start
, s
-start
+1);
4908 if (tor_version_parse(tmp
, router_version
)<0) {
4909 log_info(LD_DIR
,"Router version '%s' unparseable.",tmp
);
4914 if (router_version
->major
< 0 ||
4915 router_version
->minor
< 0 ||
4916 router_version
->micro
< 0 ||
4917 router_version
->patchlevel
< 0 ||
4918 router_version
->svn_revision
< 0) {
4926 /** Parse the Tor version of the platform string <b>platform</b>,
4927 * and compare it to the version in <b>cutoff</b>. Return 1 if
4928 * the router is at least as new as the cutoff, else return 0.
4931 tor_version_as_new_as(const char *platform
, const char *cutoff
)
4933 tor_version_t cutoff_version
, router_version
;
4935 tor_assert(platform
);
4937 if (tor_version_parse(cutoff
, &cutoff_version
)<0) {
4938 log_warn(LD_BUG
,"cutoff version '%s' unparseable.",cutoff
);
4942 r
= tor_version_parse_platform(platform
, &router_version
, 0);
4944 /* nonstandard Tor; be safe and say yes */
4947 /* unparseable version; be safe and say yes. */
4951 /* Here's why we don't need to do any special handling for svn revisions:
4952 * - If neither has an svn revision, we're fine.
4953 * - If the router doesn't have an svn revision, we can't assume that it
4954 * is "at least" any svn revision, so we need to return 0.
4955 * - If the target version doesn't have an svn revision, any svn revision
4956 * (or none at all) is good enough, so return 1.
4957 * - If both target and router have an svn revision, we compare them.
4960 return tor_version_compare(&router_version
, &cutoff_version
) >= 0;
4963 /** Parse a tor version from <b>s</b>, and store the result in <b>out</b>.
4964 * Return 0 on success, -1 on failure. */
4966 tor_version_parse(const char *s
, tor_version_t
*out
)
4969 const char *cp
=NULL
;
4972 * "Tor " ? NUM dot NUM [ dot NUM [ ( pre | rc | dot ) NUM ] ] [ - tag ]
4977 memset(out
, 0, sizeof(tor_version_t
));
4978 out
->status
= VER_RELEASE
;
4979 if (!strcasecmpstart(s
, "Tor "))
4986 if (!cp || *cp < '0' || *cp > '9') \
4988 out->m = (int)tor_parse_uint64(cp, 10, 0, INT32_MAX, &ok, &eos); \
4991 if (!eos || eos == cp) \
5008 else if (*cp
== '-')
5016 } else if (*cp
== '.') {
5018 } else if (*cp
== '-') {
5020 } else if (0==strncmp(cp
, "pre", 3)) {
5021 out
->status
= VER_PRE
;
5023 } else if (0==strncmp(cp
, "rc", 2)) {
5024 out
->status
= VER_RC
;
5033 /* Get status tag. */
5034 if (*cp
== '-' || *cp
== '.')
5036 eos
= (char*) find_whitespace(cp
);
5037 if (eos
-cp
>= (int)sizeof(out
->status_tag
))
5038 strlcpy(out
->status_tag
, cp
, sizeof(out
->status_tag
));
5040 memcpy(out
->status_tag
, cp
, eos
-cp
);
5041 out
->status_tag
[eos
-cp
] = 0;
5043 cp
= eat_whitespace(eos
);
5045 if (!strcmpstart(cp
, "(r")) {
5047 out
->svn_revision
= (int) strtol(cp
,&eos
,10);
5048 } else if (!strcmpstart(cp
, "(git-")) {
5049 char *close_paren
= strchr(cp
, ')');
5051 char digest
[DIGEST_LEN
];
5055 if (close_paren
-cp
> HEX_DIGEST_LEN
)
5057 hexlen
= (int)(close_paren
-cp
);
5058 memwipe(digest
, 0, sizeof(digest
));
5059 if ( hexlen
== 0 || (hexlen
% 2) == 1)
5061 if (base16_decode(digest
, hexlen
/2, cp
, hexlen
) != hexlen
/2)
5063 memcpy(out
->git_tag
, digest
, hexlen
/2);
5064 out
->git_tag_len
= hexlen
/2;
5072 /** Compare two tor versions; Return <0 if a < b; 0 if a ==b, >0 if a >
5075 tor_version_compare(tor_version_t
*a
, tor_version_t
*b
)
5081 /* We take this approach to comparison to ensure the same (bogus!) behavior
5082 * on all inputs as we would have seen before bug #21278 was fixed. The
5083 * only important difference here is that this method doesn't cause
5084 * a signed integer underflow.
5086 #define CMP(field) do { \
5087 unsigned aval = (unsigned) a->field; \
5088 unsigned bval = (unsigned) b->field; \
5089 int result = (int) (aval - bval); \
5092 else if (result > 0) \
5101 if ((i
= strcmp(a
->status_tag
, b
->status_tag
)))
5106 return fast_memcmp(a
->git_tag
, b
->git_tag
, a
->git_tag_len
);
5113 /** Return true iff versions <b>a</b> and <b>b</b> belong to the same series.
5116 tor_version_same_series(tor_version_t
*a
, tor_version_t
*b
)
5120 return ((a
->major
== b
->major
) &&
5121 (a
->minor
== b
->minor
) &&
5122 (a
->micro
== b
->micro
));
5125 /** Helper: Given pointers to two strings describing tor versions, return -1
5126 * if _a precedes _b, 1 if _b precedes _a, and 0 if they are equivalent.
5127 * Used to sort a list of versions. */
5129 compare_tor_version_str_ptr_(const void **_a
, const void **_b
)
5131 const char *a
= *_a
, *b
= *_b
;
5133 tor_version_t va
, vb
;
5134 ca
= tor_version_parse(a
, &va
);
5135 cb
= tor_version_parse(b
, &vb
);
5136 /* If they both parse, compare them. */
5138 return tor_version_compare(&va
,&vb
);
5139 /* If one parses, it comes first. */
5144 /* If neither parses, compare strings. Also, the directory server admin
5145 ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
5149 /** Sort a list of string-representations of versions in ascending order. */
5151 sort_version_list(smartlist_t
*versions
, int remove_duplicates
)
5153 smartlist_sort(versions
, compare_tor_version_str_ptr_
);
5155 if (remove_duplicates
)
5156 smartlist_uniq(versions
, compare_tor_version_str_ptr_
, tor_free_
);
5159 /** Parse and validate the ASCII-encoded v2 descriptor in <b>desc</b>,
5160 * write the parsed descriptor to the newly allocated *<b>parsed_out</b>, the
5161 * binary descriptor ID of length DIGEST_LEN to <b>desc_id_out</b>, the
5162 * encrypted introduction points to the newly allocated
5163 * *<b>intro_points_encrypted_out</b>, their encrypted size to
5164 * *<b>intro_points_encrypted_size_out</b>, the size of the encoded descriptor
5165 * to *<b>encoded_size_out</b>, and a pointer to the possibly next
5166 * descriptor to *<b>next_out</b>; return 0 for success (including validation)
5167 * and -1 for failure.
5169 * If <b>as_hsdir</b> is 1, we're parsing this as an HSDir, and we should
5170 * be strict about time formats.
5173 rend_parse_v2_service_descriptor(rend_service_descriptor_t
**parsed_out
,
5175 char **intro_points_encrypted_out
,
5176 size_t *intro_points_encrypted_size_out
,
5177 size_t *encoded_size_out
,
5178 const char **next_out
, const char *desc
,
5181 rend_service_descriptor_t
*result
=
5182 tor_malloc_zero(sizeof(rend_service_descriptor_t
));
5183 char desc_hash
[DIGEST_LEN
];
5185 smartlist_t
*tokens
= smartlist_new();
5186 directory_token_t
*tok
;
5187 char secret_id_part
[DIGEST_LEN
];
5188 int i
, version
, num_ok
=1;
5189 smartlist_t
*versions
;
5190 char public_key_hash
[DIGEST_LEN
];
5191 char test_desc_id
[DIGEST_LEN
];
5192 memarea_t
*area
= NULL
;
5193 const int strict_time_fmt
= as_hsdir
;
5196 /* Check if desc starts correctly. */
5197 if (strncmp(desc
, "rendezvous-service-descriptor ",
5198 strlen("rendezvous-service-descriptor "))) {
5199 log_info(LD_REND
, "Descriptor does not start correctly.");
5202 /* Compute descriptor hash for later validation. */
5203 if (router_get_hash_impl(desc
, strlen(desc
), desc_hash
,
5204 "rendezvous-service-descriptor ",
5205 "\nsignature", '\n', DIGEST_SHA1
) < 0) {
5206 log_warn(LD_REND
, "Couldn't compute descriptor hash.");
5209 /* Determine end of string. */
5210 eos
= strstr(desc
, "\nrendezvous-service-descriptor ");
5212 eos
= desc
+ strlen(desc
);
5216 if (eos
-desc
> REND_DESC_MAX_SIZE
) {
5217 /* XXXX+ If we are parsing this descriptor as a server, this
5218 * should be a protocol warning. */
5219 log_warn(LD_REND
, "Descriptor length is %d which exceeds "
5220 "maximum rendezvous descriptor size of %d bytes.",
5221 (int)(eos
-desc
), REND_DESC_MAX_SIZE
);
5224 /* Tokenize descriptor. */
5225 area
= memarea_new();
5226 if (tokenize_string(area
, desc
, eos
, tokens
, desc_token_table
, 0)) {
5227 log_warn(LD_REND
, "Error tokenizing descriptor.");
5230 /* Set next to next descriptor, if available. */
5232 /* Set length of encoded descriptor. */
5233 *encoded_size_out
= eos
- desc
;
5234 /* Check min allowed length of token list. */
5235 if (smartlist_len(tokens
) < 7) {
5236 log_warn(LD_REND
, "Impossibly short descriptor.");
5239 /* Parse base32-encoded descriptor ID. */
5240 tok
= find_by_keyword(tokens
, R_RENDEZVOUS_SERVICE_DESCRIPTOR
);
5241 tor_assert(tok
== smartlist_get(tokens
, 0));
5242 tor_assert(tok
->n_args
== 1);
5243 if (!rend_valid_descriptor_id(tok
->args
[0])) {
5244 log_warn(LD_REND
, "Invalid descriptor ID: '%s'", tok
->args
[0]);
5247 if (base32_decode(desc_id_out
, DIGEST_LEN
,
5248 tok
->args
[0], REND_DESC_ID_V2_LEN_BASE32
) < 0) {
5249 log_warn(LD_REND
, "Descriptor ID contains illegal characters: %s",
5253 /* Parse descriptor version. */
5254 tok
= find_by_keyword(tokens
, R_VERSION
);
5255 tor_assert(tok
->n_args
== 1);
5257 (int) tor_parse_long(tok
->args
[0], 10, 0, INT_MAX
, &num_ok
, NULL
);
5258 if (result
->version
!= 2 || !num_ok
) {
5259 /* If it's <2, it shouldn't be under this format. If the number
5260 * is greater than 2, we bumped it because we broke backward
5261 * compatibility. See how version numbers in our other formats
5263 log_warn(LD_REND
, "Unrecognized descriptor version: %s",
5264 escaped(tok
->args
[0]));
5267 /* Parse public key. */
5268 tok
= find_by_keyword(tokens
, R_PERMANENT_KEY
);
5269 result
->pk
= tok
->key
;
5270 tok
->key
= NULL
; /* Prevent free */
5271 /* Parse secret ID part. */
5272 tok
= find_by_keyword(tokens
, R_SECRET_ID_PART
);
5273 tor_assert(tok
->n_args
== 1);
5274 if (strlen(tok
->args
[0]) != REND_SECRET_ID_PART_LEN_BASE32
||
5275 strspn(tok
->args
[0], BASE32_CHARS
) != REND_SECRET_ID_PART_LEN_BASE32
) {
5276 log_warn(LD_REND
, "Invalid secret ID part: '%s'", tok
->args
[0]);
5279 if (base32_decode(secret_id_part
, DIGEST_LEN
, tok
->args
[0], 32) < 0) {
5280 log_warn(LD_REND
, "Secret ID part contains illegal characters: %s",
5284 /* Parse publication time -- up-to-date check is done when storing the
5286 tok
= find_by_keyword(tokens
, R_PUBLICATION_TIME
);
5287 tor_assert(tok
->n_args
== 1);
5288 if (parse_iso_time_(tok
->args
[0], &result
->timestamp
,
5289 strict_time_fmt
, 0) < 0) {
5290 log_warn(LD_REND
, "Invalid publication time: '%s'", tok
->args
[0]);
5293 /* Parse protocol versions. */
5294 tok
= find_by_keyword(tokens
, R_PROTOCOL_VERSIONS
);
5295 tor_assert(tok
->n_args
== 1);
5296 versions
= smartlist_new();
5297 smartlist_split_string(versions
, tok
->args
[0], ",",
5298 SPLIT_SKIP_SPACE
|SPLIT_IGNORE_BLANK
, 0);
5299 for (i
= 0; i
< smartlist_len(versions
); i
++) {
5300 version
= (int) tor_parse_long(smartlist_get(versions
, i
),
5301 10, 0, INT_MAX
, &num_ok
, NULL
);
5302 if (!num_ok
) /* It's a string; let's ignore it. */
5304 if (version
>= REND_PROTOCOL_VERSION_BITMASK_WIDTH
)
5305 /* Avoid undefined left-shift behaviour. */
5307 result
->protocols
|= 1 << version
;
5309 SMARTLIST_FOREACH(versions
, char *, cp
, tor_free(cp
));
5310 smartlist_free(versions
);
5311 /* Parse encrypted introduction points. Don't verify. */
5312 tok
= find_opt_by_keyword(tokens
, R_INTRODUCTION_POINTS
);
5314 if (strcmp(tok
->object_type
, "MESSAGE")) {
5315 log_warn(LD_DIR
, "Bad object type: introduction points should be of "
5319 *intro_points_encrypted_out
= tor_memdup(tok
->object_body
,
5321 *intro_points_encrypted_size_out
= tok
->object_size
;
5323 *intro_points_encrypted_out
= NULL
;
5324 *intro_points_encrypted_size_out
= 0;
5326 /* Parse and verify signature. */
5327 tok
= find_by_keyword(tokens
, R_SIGNATURE
);
5328 if (check_signature_token(desc_hash
, DIGEST_LEN
, tok
, result
->pk
, 0,
5329 "v2 rendezvous service descriptor") < 0)
5331 /* Verify that descriptor ID belongs to public key and secret ID part. */
5332 if (crypto_pk_get_digest(result
->pk
, public_key_hash
) < 0) {
5333 log_warn(LD_REND
, "Unable to compute rend descriptor public key digest");
5336 rend_get_descriptor_id_bytes(test_desc_id
, public_key_hash
,
5338 if (tor_memneq(desc_id_out
, test_desc_id
, DIGEST_LEN
)) {
5339 log_warn(LD_REND
, "Parsed descriptor ID does not match "
5340 "computed descriptor ID.");
5345 rend_service_descriptor_free(result
);
5349 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5350 smartlist_free(tokens
);
5353 memarea_drop_all(area
);
5354 *parsed_out
= result
;
5360 /** Decrypt the encrypted introduction points in <b>ipos_encrypted</b> of
5361 * length <b>ipos_encrypted_size</b> using <b>descriptor_cookie</b> and
5362 * write the result to a newly allocated string that is pointed to by
5363 * <b>ipos_decrypted</b> and its length to <b>ipos_decrypted_size</b>.
5364 * Return 0 if decryption was successful and -1 otherwise. */
5366 rend_decrypt_introduction_points(char **ipos_decrypted
,
5367 size_t *ipos_decrypted_size
,
5368 const char *descriptor_cookie
,
5369 const char *ipos_encrypted
,
5370 size_t ipos_encrypted_size
)
5372 tor_assert(ipos_encrypted
);
5373 tor_assert(descriptor_cookie
);
5374 if (ipos_encrypted_size
< 2) {
5375 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5379 if (ipos_encrypted
[0] == (int)REND_BASIC_AUTH
) {
5380 char iv
[CIPHER_IV_LEN
], client_id
[REND_BASIC_AUTH_CLIENT_ID_LEN
],
5381 session_key
[CIPHER_KEY_LEN
], *dec
;
5382 int declen
, client_blocks
;
5383 size_t pos
= 0, len
, client_entries_len
;
5384 crypto_digest_t
*digest
;
5385 crypto_cipher_t
*cipher
;
5386 client_blocks
= (int) ipos_encrypted
[1];
5387 client_entries_len
= client_blocks
* REND_BASIC_AUTH_CLIENT_MULTIPLE
*
5388 REND_BASIC_AUTH_CLIENT_ENTRY_LEN
;
5389 if (ipos_encrypted_size
< 2 + client_entries_len
+ CIPHER_IV_LEN
+ 1) {
5390 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5394 memcpy(iv
, ipos_encrypted
+ 2 + client_entries_len
, CIPHER_IV_LEN
);
5395 digest
= crypto_digest_new();
5396 crypto_digest_add_bytes(digest
, descriptor_cookie
, REND_DESC_COOKIE_LEN
);
5397 crypto_digest_add_bytes(digest
, iv
, CIPHER_IV_LEN
);
5398 crypto_digest_get_digest(digest
, client_id
,
5399 REND_BASIC_AUTH_CLIENT_ID_LEN
);
5400 crypto_digest_free(digest
);
5401 for (pos
= 2; pos
< 2 + client_entries_len
;
5402 pos
+= REND_BASIC_AUTH_CLIENT_ENTRY_LEN
) {
5403 if (tor_memeq(ipos_encrypted
+ pos
, client_id
,
5404 REND_BASIC_AUTH_CLIENT_ID_LEN
)) {
5405 /* Attempt to decrypt introduction points. */
5406 cipher
= crypto_cipher_new(descriptor_cookie
);
5407 if (crypto_cipher_decrypt(cipher
, session_key
, ipos_encrypted
5408 + pos
+ REND_BASIC_AUTH_CLIENT_ID_LEN
,
5409 CIPHER_KEY_LEN
) < 0) {
5410 log_warn(LD_REND
, "Could not decrypt session key for client.");
5411 crypto_cipher_free(cipher
);
5414 crypto_cipher_free(cipher
);
5416 len
= ipos_encrypted_size
- 2 - client_entries_len
- CIPHER_IV_LEN
;
5417 dec
= tor_malloc_zero(len
+ 1);
5418 declen
= crypto_cipher_decrypt_with_iv(session_key
, dec
, len
,
5419 ipos_encrypted
+ 2 + client_entries_len
,
5420 ipos_encrypted_size
- 2 - client_entries_len
);
5423 log_warn(LD_REND
, "Could not decrypt introduction point string.");
5427 if (fast_memcmpstart(dec
, declen
, "introduction-point ")) {
5428 log_warn(LD_REND
, "Decrypted introduction points don't "
5429 "look like we could parse them.");
5433 *ipos_decrypted
= dec
;
5434 *ipos_decrypted_size
= declen
;
5438 log_warn(LD_REND
, "Could not decrypt introduction points. Please "
5439 "check your authorization for this service!");
5441 } else if (ipos_encrypted
[0] == (int)REND_STEALTH_AUTH
) {
5444 if (ipos_encrypted_size
< CIPHER_IV_LEN
+ 2) {
5445 log_warn(LD_REND
, "Size of encrypted introduction points is too "
5449 dec
= tor_malloc_zero(ipos_encrypted_size
- CIPHER_IV_LEN
- 1 + 1);
5451 declen
= crypto_cipher_decrypt_with_iv(descriptor_cookie
, dec
,
5452 ipos_encrypted_size
-
5455 ipos_encrypted_size
- 1);
5458 log_warn(LD_REND
, "Decrypting introduction points failed!");
5462 *ipos_decrypted
= dec
;
5463 *ipos_decrypted_size
= declen
;
5466 log_warn(LD_REND
, "Unknown authorization type number: %d",
5472 /** Parse the encoded introduction points in <b>intro_points_encoded</b> of
5473 * length <b>intro_points_encoded_size</b> and write the result to the
5474 * descriptor in <b>parsed</b>; return the number of successfully parsed
5475 * introduction points or -1 in case of a failure. */
5477 rend_parse_introduction_points(rend_service_descriptor_t
*parsed
,
5478 const char *intro_points_encoded
,
5479 size_t intro_points_encoded_size
)
5481 const char *current_ipo
, *end_of_intro_points
;
5482 smartlist_t
*tokens
= NULL
;
5483 directory_token_t
*tok
;
5484 rend_intro_point_t
*intro
;
5485 extend_info_t
*info
;
5486 int result
, num_ok
=1;
5487 memarea_t
*area
= NULL
;
5489 /** Function may only be invoked once. */
5490 tor_assert(!parsed
->intro_nodes
);
5491 if (!intro_points_encoded
|| intro_points_encoded_size
== 0) {
5492 log_warn(LD_REND
, "Empty or zero size introduction point list");
5495 /* Consider one intro point after the other. */
5496 current_ipo
= intro_points_encoded
;
5497 end_of_intro_points
= intro_points_encoded
+ intro_points_encoded_size
;
5498 tokens
= smartlist_new();
5499 parsed
->intro_nodes
= smartlist_new();
5500 area
= memarea_new();
5502 while (!fast_memcmpstart(current_ipo
, end_of_intro_points
-current_ipo
,
5503 "introduction-point ")) {
5504 /* Determine end of string. */
5505 const char *eos
= tor_memstr(current_ipo
, end_of_intro_points
-current_ipo
,
5506 "\nintroduction-point ");
5508 eos
= end_of_intro_points
;
5511 tor_assert(eos
<= intro_points_encoded
+intro_points_encoded_size
);
5512 /* Free tokens and clear token list. */
5513 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5514 smartlist_clear(tokens
);
5515 memarea_clear(area
);
5516 /* Tokenize string. */
5517 if (tokenize_string(area
, current_ipo
, eos
, tokens
, ipo_token_table
, 0)) {
5518 log_warn(LD_REND
, "Error tokenizing introduction point");
5521 /* Advance to next introduction point, if available. */
5523 /* Check minimum allowed length of introduction point. */
5524 if (smartlist_len(tokens
) < 5) {
5525 log_warn(LD_REND
, "Impossibly short introduction point.");
5528 /* Allocate new intro point and extend info. */
5529 intro
= tor_malloc_zero(sizeof(rend_intro_point_t
));
5530 info
= intro
->extend_info
= tor_malloc_zero(sizeof(extend_info_t
));
5531 /* Parse identifier. */
5532 tok
= find_by_keyword(tokens
, R_IPO_IDENTIFIER
);
5533 if (base32_decode(info
->identity_digest
, DIGEST_LEN
,
5534 tok
->args
[0], REND_INTRO_POINT_ID_LEN_BASE32
) < 0) {
5535 log_warn(LD_REND
, "Identity digest contains illegal characters: %s",
5537 rend_intro_point_free(intro
);
5540 /* Write identifier to nickname. */
5541 info
->nickname
[0] = '$';
5542 base16_encode(info
->nickname
+ 1, sizeof(info
->nickname
) - 1,
5543 info
->identity_digest
, DIGEST_LEN
);
5544 /* Parse IP address. */
5545 tok
= find_by_keyword(tokens
, R_IPO_IP_ADDRESS
);
5546 if (tor_addr_parse(&info
->addr
, tok
->args
[0])<0) {
5547 log_warn(LD_REND
, "Could not parse introduction point address.");
5548 rend_intro_point_free(intro
);
5551 if (tor_addr_family(&info
->addr
) != AF_INET
) {
5552 log_warn(LD_REND
, "Introduction point address was not ipv4.");
5553 rend_intro_point_free(intro
);
5557 /* Parse onion port. */
5558 tok
= find_by_keyword(tokens
, R_IPO_ONION_PORT
);
5559 info
->port
= (uint16_t) tor_parse_long(tok
->args
[0],10,1,65535,
5561 if (!info
->port
|| !num_ok
) {
5562 log_warn(LD_REND
, "Introduction point onion port %s is invalid",
5563 escaped(tok
->args
[0]));
5564 rend_intro_point_free(intro
);
5567 /* Parse onion key. */
5568 tok
= find_by_keyword(tokens
, R_IPO_ONION_KEY
);
5569 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
5571 "Introduction point's onion key had invalid exponent.");
5572 rend_intro_point_free(intro
);
5575 info
->onion_key
= tok
->key
;
5576 tok
->key
= NULL
; /* Prevent free */
5577 /* Parse service key. */
5578 tok
= find_by_keyword(tokens
, R_IPO_SERVICE_KEY
);
5579 if (!crypto_pk_public_exponent_ok(tok
->key
)) {
5581 "Introduction point key had invalid exponent.");
5582 rend_intro_point_free(intro
);
5585 intro
->intro_key
= tok
->key
;
5586 tok
->key
= NULL
; /* Prevent free */
5587 /* Add extend info to list of introduction points. */
5588 smartlist_add(parsed
->intro_nodes
, intro
);
5590 result
= smartlist_len(parsed
->intro_nodes
);
5597 /* Free tokens and clear token list. */
5599 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5600 smartlist_free(tokens
);
5603 memarea_drop_all(area
);
5608 /** Parse the content of a client_key file in <b>ckstr</b> and add
5609 * rend_authorized_client_t's for each parsed client to
5610 * <b>parsed_clients</b>. Return the number of parsed clients as result
5611 * or -1 for failure. */
5613 rend_parse_client_keys(strmap_t
*parsed_clients
, const char *ckstr
)
5616 smartlist_t
*tokens
;
5617 directory_token_t
*tok
;
5618 const char *current_entry
= NULL
;
5619 memarea_t
*area
= NULL
;
5620 char *err_msg
= NULL
;
5621 if (!ckstr
|| strlen(ckstr
) == 0)
5623 tokens
= smartlist_new();
5624 /* Begin parsing with first entry, skipping comments or whitespace at the
5626 area
= memarea_new();
5627 current_entry
= eat_whitespace(ckstr
);
5628 while (!strcmpstart(current_entry
, "client-name ")) {
5629 rend_authorized_client_t
*parsed_entry
;
5630 /* Determine end of string. */
5631 const char *eos
= strstr(current_entry
, "\nclient-name ");
5633 eos
= current_entry
+ strlen(current_entry
);
5636 /* Free tokens and clear token list. */
5637 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5638 smartlist_clear(tokens
);
5639 memarea_clear(area
);
5640 /* Tokenize string. */
5641 if (tokenize_string(area
, current_entry
, eos
, tokens
,
5642 client_keys_token_table
, 0)) {
5643 log_warn(LD_REND
, "Error tokenizing client keys file.");
5646 /* Advance to next entry, if available. */
5647 current_entry
= eos
;
5648 /* Check minimum allowed length of token list. */
5649 if (smartlist_len(tokens
) < 2) {
5650 log_warn(LD_REND
, "Impossibly short client key entry.");
5653 /* Parse client name. */
5654 tok
= find_by_keyword(tokens
, C_CLIENT_NAME
);
5655 tor_assert(tok
== smartlist_get(tokens
, 0));
5656 tor_assert(tok
->n_args
== 1);
5658 if (!rend_valid_client_name(tok
->args
[0])) {
5659 log_warn(LD_CONFIG
, "Illegal client name: %s. (Length must be "
5660 "between 1 and %d, and valid characters are "
5661 "[A-Za-z0-9+-_].)", tok
->args
[0], REND_CLIENTNAME_MAX_LEN
);
5664 /* Check if client name is duplicate. */
5665 if (strmap_get(parsed_clients
, tok
->args
[0])) {
5666 log_warn(LD_CONFIG
, "HiddenServiceAuthorizeClient contains a "
5667 "duplicate client name: '%s'. Ignoring.", tok
->args
[0]);
5670 parsed_entry
= tor_malloc_zero(sizeof(rend_authorized_client_t
));
5671 parsed_entry
->client_name
= tor_strdup(tok
->args
[0]);
5672 strmap_set(parsed_clients
, parsed_entry
->client_name
, parsed_entry
);
5673 /* Parse client key. */
5674 tok
= find_opt_by_keyword(tokens
, C_CLIENT_KEY
);
5676 parsed_entry
->client_key
= tok
->key
;
5677 tok
->key
= NULL
; /* Prevent free */
5680 /* Parse descriptor cookie. */
5681 tok
= find_by_keyword(tokens
, C_DESCRIPTOR_COOKIE
);
5682 tor_assert(tok
->n_args
== 1);
5683 if (rend_auth_decode_cookie(tok
->args
[0], parsed_entry
->descriptor_cookie
,
5684 NULL
, &err_msg
) < 0) {
5685 tor_assert(err_msg
);
5686 log_warn(LD_REND
, "%s", err_msg
);
5691 result
= strmap_size(parsed_clients
);
5696 /* Free tokens and clear token list. */
5697 SMARTLIST_FOREACH(tokens
, directory_token_t
*, t
, token_clear(t
));
5698 smartlist_free(tokens
);
5700 memarea_drop_all(area
);
5704 /** Called on startup; right now we just handle scanning the unparseable
5705 * descriptor dumps, but hang anything else we might need to do in the
5706 * future here as well.
5709 routerparse_init(void)
5712 * Check both if the sandbox is active and whether it's configured; no
5713 * point in loading all that if we won't be able to use it after the
5714 * sandbox becomes active.
5716 if (!(sandbox_is_active() || get_options()->Sandbox
)) {
5721 /** Clean up all data structures used by routerparse.c at exit */
5723 routerparse_free_all(void)
5725 dump_desc_fifo_cleanup();