Tor 0.4.9.8
Loading...
Searching...
No Matches
directory.c
Go to the documentation of this file.
1/* Copyright (c) 2001-2004, Roger Dingledine.
2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3 * Copyright (c) 2007-2021, The Tor Project, Inc. */
4/* See LICENSE for licensing information */
5
6#include "core/or/or.h"
7
8#include "app/config/config.h"
10#include "core/or/circuitlist.h"
13#include "core/or/channeltls.h"
19#include "feature/hs/hs_cache.h"
22
23#include "core/or/circuit_st.h"
24#include "core/or/or_circuit_st.h"
29
30/**
31 * \file directory.c
32 * \brief Code to send and fetch information from directory authorities and
33 * caches via HTTP.
34 *
35 * Directory caches and authorities use dirserv.c to generate the results of a
36 * query and stream them to the connection; clients use routerparse.c to parse
37 * them.
38 *
39 * Every directory request has a dir_connection_t on the client side and on
40 * the server side. In most cases, the dir_connection_t object is a linked
41 * connection, tunneled through an edge_connection_t so that it can be a
42 * stream on the Tor network. The only non-tunneled connections are those
43 * that are used to upload material (descriptors and votes) to authorities.
44 * Among tunneled connections, some use one-hop circuits, and others use
45 * multi-hop circuits for anonymity.
46 *
47 * Directory requests are launched by calling
48 * directory_initiate_request(). This
49 * launch the connection, will construct an HTTP request with
50 * directory_send_command(), send the and wait for a response. The client
51 * later handles the response with connection_dir_client_reached_eof(),
52 * which passes the information received to another part of Tor.
53 *
54 * On the server side, requests are read in directory_handle_command(),
55 * which dispatches first on the request type (GET or POST), and then on
56 * the URL requested. GET requests are processed with a table-based
57 * dispatcher in url_table[]. The process of handling larger GET requests
58 * is complicated because we need to avoid allocating a copy of all the
59 * data to be sent to the client in one huge buffer. Instead, we spool the
60 * data into the buffer using logic in connection_dirserv_flushed_some() in
61 * dirserv.c. (TODO: If we extended buf.c to have a zero-copy
62 * reference-based buffer type, we could remove most of that code, at the
63 * cost of a bit more reference counting.)
64 **/
65
66/* In-points to directory.c:
67 *
68 * - directory_post_to_dirservers(), called from
69 * router_upload_dir_desc_to_dirservers() in router.c
70 * upload_service_descriptor() in rendservice.c
71 * - directory_get_from_dirserver(), called from
72 * run_scheduled_events() in main.c
73 * do_hup() in main.c
74 * - connection_dir_process_inbuf(), called from
75 * connection_process_inbuf() in connection.c
76 * - connection_dir_finished_flushing(), called from
77 * connection_finished_flushing() in connection.c
78 * - connection_dir_finished_connecting(), called from
79 * connection_finished_connecting() in connection.c
80 */
81
82/**
83 * Cast a `connection_t *` to a `dir_connection_t *`.
84 *
85 * Exit with an assertion failure if the input is not a
86 * `dir_connection_t`.
87 **/
90{
91 tor_assert(c->magic == DIR_CONNECTION_MAGIC);
92 return DOWNCAST(dir_connection_t, c);
93}
94
95/**
96 * Cast a `const connection_t *` to a `const dir_connection_t *`.
97 *
98 * Exit with an assertion failure if the input is not a
99 * `dir_connection_t`.
100 **/
101const dir_connection_t *
103{
104 return TO_DIR_CONN((connection_t *)c);
105}
106
107/** Return false if the directory purpose <b>dir_purpose</b>
108 * does not require an anonymous (three-hop) connection.
109 *
110 * Return true 1) by default, 2) if all directory actions have
111 * specifically been configured to be over an anonymous connection,
112 * or 3) if the router is a bridge */
113int
114purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
115 const char *resource)
116{
117 if (get_options()->AllDirActionsPrivate)
118 return 1;
119
120 if (router_purpose == ROUTER_PURPOSE_BRIDGE) {
121 if (dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC
122 && resource && !strcmp(resource, "authority.z")) {
123 /* We are asking a bridge for its own descriptor. That doesn't need
124 anonymity. */
125 return 0;
126 }
127 /* Assume all other bridge stuff needs anonymity. */
128 return 1; /* if no circuits yet, this might break bootstrapping, but it's
129 * needed to be safe. */
130 }
131
132 switch (dir_purpose)
133 {
144 return 0;
148 return 1;
150 default:
151 log_warn(LD_BUG, "Called with dir_purpose=%d, router_purpose=%d",
152 dir_purpose, router_purpose);
154 return 1; /* Assume it needs anonymity; better safe than sorry. */
155 }
156}
157
158/** Return a newly allocated string describing <b>auth</b>. Only describes
159 * authority features. */
160char *
162{
163 char *result;
164 smartlist_t *lst = smartlist_new();
165 if (auth & V3_DIRINFO)
166 smartlist_add(lst, (void*)"V3");
167 if (auth & BRIDGE_DIRINFO)
168 smartlist_add(lst, (void*)"Bridge");
169 if (smartlist_len(lst)) {
170 result = smartlist_join_strings(lst, ", ", 0, NULL);
171 } else {
172 result = tor_strdup("[Not an authority]");
173 }
174 smartlist_free(lst);
175 return result;
176}
177
178/** Return true iff anything we say on <b>conn</b> is being encrypted before
179 * we send it to the client/server. */
180int
182{
183 /* Right now it's sufficient to see if conn is or has been linked, since
184 * the only thing it could be linked to is an edge connection on a
185 * circuit, and the only way it could have been unlinked is at the edge
186 * connection getting closed.
187 */
188 return TO_CONN(conn)->linked;
189}
190
191/** Return true iff the given directory connection <b>dir_conn</b> is
192 * anonymous, that is, it is on a circuit via a public relay and not directly
193 * from a client or bridge.
194 *
195 * For client circuits via relays: true for 2-hop+ paths.
196 * For client circuits via bridges: true for 3-hop+ paths.
197 *
198 * This first test if the connection is encrypted since it is a strong
199 * requirement for anonymity. */
200bool
202{
203 const connection_t *conn, *linked_conn;
204 const edge_connection_t *edge_conn;
205 const circuit_t *circ;
206
207 tor_assert(dir_conn);
208
209 if (!connection_dir_is_encrypted(dir_conn)) {
210 return false;
211 }
212
213 /*
214 * Buckle up, we'll do a deep dive into the connection in order to get the
215 * final connection channel of that connection in order to figure out if
216 * this is a client or relay link.
217 *
218 * We go: dir_conn -> linked_conn -> edge_conn -> on_circuit -> p_chan.
219 */
220
221 conn = TO_CONN(dir_conn);
222 linked_conn = conn->linked_conn;
223
224 /* The dir connection should be connected to an edge connection. It can not
225 * be closed or marked for close. */
226 if (linked_conn == NULL || linked_conn->magic != EDGE_CONNECTION_MAGIC ||
228 log_debug(LD_DIR, "Directory connection is not anonymous: "
229 "not linked to edge");
230 return false;
231 }
232
233 edge_conn = CONST_TO_EDGE_CONN(linked_conn);
234 circ = edge_conn->on_circuit;
235
236 /* Can't be a circuit we initiated and without a circuit, no channel. */
237 if (circ == NULL || CIRCUIT_IS_ORIGIN(circ)) {
238 log_debug(LD_DIR, "Directory connection is not anonymous: "
239 "not on OR circuit");
240 return false;
241 }
242
243 /* It is possible that the circuit was closed because one of the channel was
244 * closed or a DESTROY cell was received. Either way, this connection can
245 * not continue so return that it is not anonymous since we can not know for
246 * sure if it is. */
247 if (circ->marked_for_close) {
248 log_debug(LD_DIR, "Directory connection is not anonymous: "
249 "circuit marked for close");
250 return false;
251 }
252
253 /* Get the previous channel to learn if it is a client or relay link. We
254 * BUG() because if the circuit is not mark for close, we ought to have a
255 * p_chan else we have a code flow issue. */
256 if (BUG(CONST_TO_OR_CIRCUIT(circ)->p_chan == NULL)) {
257 log_debug(LD_DIR, "Directory connection is not anonymous: "
258 "no p_chan on circuit");
259 return false;
260 }
261
262 /* Will be true if the channel is an unauthenticated peer which is only true
263 * for clients and bridges. */
264 return !channel_is_client(CONST_TO_OR_CIRCUIT(circ)->p_chan);
265}
266
267/** Did <b>conn</b> ever send us a version 0 sendme cell and we allowed
268 * it? Used to decide whether to count consensus fetches from it in our
269 * geoip stats.
270 *
271 * Note that this function might have false negatives in some cases, i.e.
272 * it could tell us that the conn never sent a v0 sendme when actually it
273 * did but its linked edge connection or OR connection got broken before
274 * we called this function. For our geoip stats these false negatives
275 * would mean overcounting users by including some of the v0-using
276 * clients.
277 *
278 * We think these false positives should be unlikely or maybe even
279 * impossible when called from connection_dirserv_flushed_some(), but
280 * be careful calling it from elsewhere.
281 * */
282bool
284{
285 const edge_connection_t *edge_conn = NULL;
286 const circuit_t *circ = NULL;
287 bool used_obsolete_sendme = 0;
288 const connection_t *linked_conn = TO_CONN(conn)->linked_conn;
289 if (linked_conn)
290 edge_conn = CONST_TO_EDGE_CONN(linked_conn);
291 if (edge_conn)
292 circ = edge_conn->on_circuit;
293 if (circ && CIRCUIT_IS_ORCIRC(circ))
294 used_obsolete_sendme = CONST_TO_OR_CIRCUIT(circ)->used_obsolete_sendme;
295
296 return used_obsolete_sendme;
297}
298
299/** Parse an HTTP request line at the start of a headers string. On failure,
300 * return -1. On success, set *<b>command_out</b> to a copy of the HTTP
301 * command ("get", "post", etc), set *<b>url_out</b> to a copy of the URL, and
302 * return 0. */
303int
304parse_http_command(const char *headers, char **command_out, char **url_out)
305{
306 const char *command, *end_of_command;
307 char *s, *start, *tmp;
308
309 s = (char *)eat_whitespace_no_nl(headers);
310 if (!*s) return -1;
311 command = s;
312 s = (char *)find_whitespace(s); /* get past GET/POST */
313 if (!*s) return -1;
314 end_of_command = s;
315 s = (char *)eat_whitespace_no_nl(s);
316 if (!*s) return -1;
317 start = s; /* this is the URL, assuming it's valid */
318 s = (char *)find_whitespace(start);
319 if (!*s) return -1;
320
321 /* tolerate the http[s] proxy style of putting the hostname in the url */
322 if (s-start >= 4 && !strcmpstart(start,"http")) {
323 tmp = start + 4;
324 if (*tmp == 's')
325 tmp++;
326 if (s-tmp >= 3 && !strcmpstart(tmp,"://")) {
327 tmp = strchr(tmp+3, '/');
328 if (tmp && tmp < s) {
329 log_debug(LD_DIR,"Skipping over 'http[s]://hostname/' string");
330 start = tmp;
331 }
332 }
333 }
334
335 /* Check if the header is well formed (next sequence
336 * should be HTTP/1.X\r\n). Assumes we're supporting 1.0? */
337 {
338 unsigned minor_ver;
339 char ch;
340 char *e = (char *)eat_whitespace_no_nl(s);
341 if (2 != tor_sscanf(e, "HTTP/1.%u%c", &minor_ver, &ch)) {
342 return -1;
343 }
344 if (ch != '\r')
345 return -1;
346 }
347
348 *url_out = tor_memdup_nulterm(start, s-start);
349 *command_out = tor_memdup_nulterm(command, end_of_command - command);
350 return 0;
351}
352
353/** Return a copy of the first HTTP header in <b>headers</b> whose key is
354 * <b>which</b>. The key should be given with a terminating colon and space;
355 * this function copies everything after, up to but not including the
356 * following \\r\\n. */
357char *
358http_get_header(const char *headers, const char *which)
359{
360 const char *cp = headers;
361 while (cp) {
362 if (!strcasecmpstart(cp, which)) {
363 const char *eos;
364 cp += strlen(which);
365 if ((eos = strchr(cp,'\r')))
366 return tor_strndup(cp, eos-cp);
367 else
368 return tor_strdup(cp);
369 }
370 cp = strchr(cp, '\n');
371 if (cp)
372 ++cp;
373 }
374 return NULL;
375}
376/** Parse an HTTP response string <b>headers</b> of the form
377 * \verbatim
378 * "HTTP/1.\%d \%d\%s\r\n...".
379 * \endverbatim
380 *
381 * If it's well-formed, assign the status code to *<b>code</b> and
382 * return 0. Otherwise, return -1.
383 *
384 * On success: If <b>date</b> is provided, set *date to the Date
385 * header in the http headers, or 0 if no such header is found. If
386 * <b>compression</b> is provided, set *<b>compression</b> to the
387 * compression method given in the Content-Encoding header, or 0 if no
388 * such header is found, or -1 if the value of the header is not
389 * recognized. If <b>reason</b> is provided, strdup the reason string
390 * into it.
391 */
392int
393parse_http_response(const char *headers, int *code, time_t *date,
394 compress_method_t *compression, char **reason)
395{
396 unsigned n1, n2;
397 char datestr[RFC1123_TIME_LEN+1];
398 smartlist_t *parsed_headers;
399 tor_assert(headers);
400 tor_assert(code);
401
402 while (TOR_ISSPACE(*headers)) headers++; /* tolerate leading whitespace */
403
404 if (tor_sscanf(headers, "HTTP/1.%u %u", &n1, &n2) < 2 ||
405 (n1 != 0 && n1 != 1) ||
406 (n2 < 100 || n2 >= 600)) {
407 log_warn(LD_HTTP,"Failed to parse header %s",escaped(headers));
408 return -1;
409 }
410 *code = n2;
411
412 parsed_headers = smartlist_new();
413 smartlist_split_string(parsed_headers, headers, "\n",
414 SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, -1);
415 if (reason) {
416 smartlist_t *status_line_elements = smartlist_new();
417 tor_assert(smartlist_len(parsed_headers));
418 smartlist_split_string(status_line_elements,
419 smartlist_get(parsed_headers, 0),
420 " ", SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 3);
421 tor_assert(smartlist_len(status_line_elements) <= 3);
422 if (smartlist_len(status_line_elements) == 3) {
423 *reason = smartlist_get(status_line_elements, 2);
424 smartlist_set(status_line_elements, 2, NULL); /* Prevent free */
425 }
426 SMARTLIST_FOREACH(status_line_elements, char *, cp, tor_free(cp));
427 smartlist_free(status_line_elements);
428 }
429 if (date) {
430 *date = 0;
431 SMARTLIST_FOREACH(parsed_headers, const char *, s,
432 if (!strcmpstart(s, "Date: ")) {
433 strlcpy(datestr, s+6, sizeof(datestr));
434 /* This will do nothing on failure, so we don't need to check
435 the result. We shouldn't warn, since there are many other valid
436 date formats besides the one we use. */
437 parse_rfc1123_time(datestr, date);
438 break;
439 });
440 }
441 if (compression) {
442 const char *enc = NULL;
443 SMARTLIST_FOREACH(parsed_headers, const char *, s,
444 if (!strcmpstart(s, "Content-Encoding: ")) {
445 enc = s+18; break;
446 });
447
448 if (enc == NULL)
449 *compression = NO_METHOD;
450 else {
451 *compression = compression_method_get_by_name(enc);
452
453 if (*compression == UNKNOWN_METHOD)
454 log_info(LD_HTTP, "Unrecognized content encoding: %s. Trying to deal.",
455 escaped(enc));
456 }
457 }
458 SMARTLIST_FOREACH(parsed_headers, char *, s, tor_free(s));
459 smartlist_free(parsed_headers);
460
461 return 0;
462}
463
464/** If any directory object is arriving, and it's over 10MB large, we're
465 * getting DoS'd. (As of 0.1.2.x, raw directories are about 1MB, and we never
466 * ask for more than 96 router descriptors at a time.)
467 */
468#define MAX_DIRECTORY_OBJECT_SIZE (10*(1<<20))
469
470#define MAX_VOTE_DL_SIZE (MAX_DIRECTORY_OBJECT_SIZE * 5)
471
472/** Read handler for directory connections. (That's connections <em>to</em>
473 * directory servers and connections <em>at</em> directory servers.)
474 */
475int
477{
478 size_t max_size;
479 tor_assert(conn);
480 tor_assert(conn->base_.type == CONN_TYPE_DIR);
481
482 /* Directory clients write, then read data until they receive EOF;
483 * directory servers read data until they get an HTTP command, then
484 * write their response (when it's finished flushing, they mark for
485 * close).
486 */
487
488 /* If we're on the dirserver side, look for a command. */
489 if (conn->base_.state == DIR_CONN_STATE_SERVER_COMMAND_WAIT) {
490 if (directory_handle_command(conn) < 0) {
491 connection_mark_for_close(TO_CONN(conn));
492 return -1;
493 }
494 return 0;
495 }
496
497 max_size =
498 (TO_CONN(conn)->purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) ?
499 MAX_VOTE_DL_SIZE : MAX_DIRECTORY_OBJECT_SIZE;
500
501 if (connection_get_inbuf_len(TO_CONN(conn)) > max_size) {
502 log_warn(LD_HTTP,
503 "Too much data received from %s: "
504 "denial of service attempt, or you need to upgrade?",
506 connection_mark_for_close(TO_CONN(conn));
507 return -1;
508 }
509
510 if (!conn->base_.inbuf_reached_eof)
511 log_debug(LD_HTTP,"Got data, not eof. Leaving on inbuf.");
512 return 0;
513}
514
515/** Called when we're about to finally unlink and free a directory connection:
516 * perform necessary accounting and cleanup */
517void
519{
520 connection_t *conn = TO_CONN(dir_conn);
521
523 /* It's a directory connection and connecting or fetching
524 * failed: forget about this router, and maybe try again. */
526 }
527
528 /* If we are an HSDir, mark the corresponding descriptor as downloaded. This
529 * is needed for the OOM cache cleanup.
530 *
531 * This is done when the direction connection is closed in order to raise the
532 * attack cost of filling the cache with bogus descriptors. That attacker
533 * would need to increase that downloaded counter for the attack to be
534 * successful which is expensive. */
535 if (conn->purpose == DIR_PURPOSE_SERVER && dir_conn->hs_ident) {
536 hs_cache_mark_dowloaded_as_dir(dir_conn->hs_ident);
537 }
538
540}
541
542/** Write handler for directory connections; called when all data has
543 * been flushed. Close the connection or wait for a response as
544 * appropriate.
545 */
546int
548{
549 tor_assert(conn);
550 tor_assert(conn->base_.type == CONN_TYPE_DIR);
551
552 if (conn->base_.marked_for_close)
553 return 0;
554
555 /* Note that we have finished writing the directory response. For direct
556 * connections this means we're done; for tunneled connections it's only
557 * an intermediate step. */
558 if (conn->dirreq_id)
559 geoip_change_dirreq_state(conn->dirreq_id, DIRREQ_TUNNELED,
561 else
562 geoip_change_dirreq_state(TO_CONN(conn)->global_identifier,
563 DIRREQ_DIRECT,
565 switch (conn->base_.state) {
568 log_debug(LD_DIR,"client finished sending command.");
570 return 0;
572 if (conn->spool) {
573 log_warn(LD_BUG, "Emptied a dirserv buffer, but it's still spooling!");
574 connection_mark_for_close(TO_CONN(conn));
575 } else {
576 log_debug(LD_DIRSERV, "Finished writing server response. Closing.");
577 connection_mark_for_close(TO_CONN(conn));
578 }
579 return 0;
580 default:
581 log_warn(LD_BUG,"called in unexpected state %d.",
582 conn->base_.state);
584 return -1;
585 }
586 return 0;
587}
588
589/** Connected handler for directory connections: begin sending data to the
590 * server, and return 0.
591 * Only used when connections don't immediately connect. */
592int
594{
595 tor_assert(conn);
596 tor_assert(conn->base_.type == CONN_TYPE_DIR);
598
599 log_debug(LD_HTTP,"Dir connection to %s established.",
601
602 /* start flushing conn */
604 return 0;
605}
606
607/** Helper. Compare two fp_pair_t objects, and return negative, 0, or
608 * positive as appropriate. */
609static int
610compare_pairs_(const void **a, const void **b)
611{
612 const fp_pair_t *fp1 = *a, *fp2 = *b;
613 int r;
614 if ((r = fast_memcmp(fp1->first, fp2->first, DIGEST_LEN)))
615 return r;
616 else
617 return fast_memcmp(fp1->second, fp2->second, DIGEST_LEN);
618}
619
620/** Divide a string <b>res</b> of the form FP1-FP2+FP3-FP4...[.z], where each
621 * FP is a hex-encoded fingerprint, into a sequence of distinct sorted
622 * fp_pair_t. Skip malformed pairs. On success, return 0 and add those
623 * fp_pair_t into <b>pairs_out</b>. On failure, return -1. */
624int
626 smartlist_t *pairs_out)
627{
628 smartlist_t *pairs_tmp = smartlist_new();
629 smartlist_t *pairs_result = smartlist_new();
630
631 smartlist_split_string(pairs_tmp, res, "+", 0, 0);
632 if (smartlist_len(pairs_tmp)) {
633 char *last = smartlist_get(pairs_tmp,smartlist_len(pairs_tmp)-1);
634 size_t last_len = strlen(last);
635 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
636 last[last_len-2] = '\0';
637 }
638 }
639 SMARTLIST_FOREACH_BEGIN(pairs_tmp, char *, cp) {
640 if (strlen(cp) != HEX_DIGEST_LEN*2+1) {
641 log_info(LD_DIR,
642 "Skipping digest pair %s with non-standard length.", escaped(cp));
643 } else if (cp[HEX_DIGEST_LEN] != '-') {
644 log_info(LD_DIR,
645 "Skipping digest pair %s with missing dash.", escaped(cp));
646 } else {
647 fp_pair_t pair;
648 if (base16_decode(pair.first, DIGEST_LEN,
649 cp, HEX_DIGEST_LEN) != DIGEST_LEN ||
650 base16_decode(pair.second,DIGEST_LEN,
652 log_info(LD_DIR, "Skipping non-decodable digest pair %s", escaped(cp));
653 } else {
654 smartlist_add(pairs_result, tor_memdup(&pair, sizeof(pair)));
655 }
656 }
657 tor_free(cp);
658 } SMARTLIST_FOREACH_END(cp);
659 smartlist_free(pairs_tmp);
660
661 /* Uniq-and-sort */
662 smartlist_sort(pairs_result, compare_pairs_);
664
665 smartlist_add_all(pairs_out, pairs_result);
666 smartlist_free(pairs_result);
667 return 0;
668}
669
670/** Given a directory <b>resource</b> request, containing zero
671 * or more strings separated by plus signs, followed optionally by ".z", store
672 * the strings, in order, into <b>fp_out</b>. If <b>compressed_out</b> is
673 * non-NULL, set it to 1 if the resource ends in ".z", else set it to 0.
674 *
675 * If (flags & DSR_HEX), then delete all elements that aren't hex digests, and
676 * decode the rest. If (flags & DSR_BASE64), then use "-" rather than "+" as
677 * a separator, delete all the elements that aren't base64-encoded digests,
678 * and decode the rest. If (flags & DSR_DIGEST256), these digests should be
679 * 256 bits long; else they should be 160.
680 *
681 * If (flags & DSR_SORT_UNIQ), then sort the list and remove all duplicates.
682 */
683int
685 smartlist_t *fp_out, int *compressed_out,
686 int flags)
687{
688 const int decode_hex = flags & DSR_HEX;
689 const int decode_base64 = flags & DSR_BASE64;
690 const int digests_are_256 = flags & DSR_DIGEST256;
691 const int sort_uniq = flags & DSR_SORT_UNIQ;
692
693 const int digest_len = digests_are_256 ? DIGEST256_LEN : DIGEST_LEN;
694 const int hex_digest_len = digests_are_256 ?
696 const int base64_digest_len = digests_are_256 ?
698 smartlist_t *fp_tmp = smartlist_new();
699
700 tor_assert(!(decode_hex && decode_base64));
701 tor_assert(fp_out);
702
703 smartlist_split_string(fp_tmp, resource, decode_base64?"-":"+", 0, 0);
704 if (compressed_out)
705 *compressed_out = 0;
706 if (smartlist_len(fp_tmp)) {
707 char *last = smartlist_get(fp_tmp,smartlist_len(fp_tmp)-1);
708 size_t last_len = strlen(last);
709 if (last_len > 2 && !strcmp(last+last_len-2, ".z")) {
710 last[last_len-2] = '\0';
711 if (compressed_out)
712 *compressed_out = 1;
713 }
714 }
715 if (decode_hex || decode_base64) {
716 const size_t encoded_len = decode_hex ? hex_digest_len : base64_digest_len;
717 int i;
718 char *cp, *d = NULL;
719 for (i = 0; i < smartlist_len(fp_tmp); ++i) {
720 cp = smartlist_get(fp_tmp, i);
721 if (strlen(cp) != encoded_len) {
722 log_info(LD_DIR,
723 "Skipping digest %s with non-standard length.", escaped(cp));
724 smartlist_del_keeporder(fp_tmp, i--);
725 goto again;
726 }
727 d = tor_malloc_zero(digest_len);
728 if (decode_hex ?
729 (base16_decode(d, digest_len, cp, hex_digest_len) != digest_len) :
730 (base64_decode(d, digest_len, cp, base64_digest_len)
731 != digest_len)) {
732 log_info(LD_DIR, "Skipping non-decodable digest %s", escaped(cp));
733 smartlist_del_keeporder(fp_tmp, i--);
734 goto again;
735 }
736 smartlist_set(fp_tmp, i, d);
737 d = NULL;
738 again:
739 tor_free(cp);
740 tor_free(d);
741 }
742 }
743 if (sort_uniq) {
744 if (decode_hex || decode_base64) {
745 if (digests_are_256) {
748 } else {
751 }
752 } else {
755 }
756 }
757 smartlist_add_all(fp_out, fp_tmp);
758 smartlist_free(fp_tmp);
759 return 0;
760}
int base64_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition binascii.c:396
int base16_decode(char *dest, size_t destlen, const char *src, size_t srclen)
Definition binascii.c:506
int channel_is_client(const channel_t *chan)
Definition channel.c:2917
Header file for channeltls.c.
Base circuit structure.
Header file for circuitlist.c.
#define CIRCUIT_IS_ORCIRC(c)
#define CIRCUIT_IS_ORIGIN(c)
compress_method_t compression_method_get_by_name(const char *name)
Definition compress.c:416
Headers for compress.c.
compress_method_t
Definition compress.h:21
const or_options_t * get_options(void)
Definition config.c:948
tor_cmdline_mode_t command
Definition config.c:2478
Header file for config.c.
const char * connection_describe_peer(const connection_t *conn)
Definition connection.c:526
const char * connection_describe(const connection_t *conn)
Definition connection.c:541
Header file for connection.c.
#define CONN_TYPE_DIR
Definition connection.h:55
const edge_connection_t * CONST_TO_EDGE_CONN(const connection_t *c)
Header file for connection_edge.c.
Header file for connection_or.c.
#define BASE64_DIGEST256_LEN
#define HEX_DIGEST256_LEN
#define HEX_DIGEST_LEN
#define BASE64_DIGEST_LEN
#define fast_memcmp(a, b, c)
Definition di_ops.h:28
#define DIGEST_LEN
#define DIGEST256_LEN
Client/server directory connection structure.
int directory_handle_command(dir_connection_t *conn)
Definition dircache.c:1739
Header file for dircache.c.
void connection_dir_client_request_failed(dir_connection_t *conn)
Definition dirclient.c:711
void connection_dir_client_refetch_hsdesc_if_needed(dir_connection_t *dir_conn)
Definition dirclient.c:2860
Header file for dirclient.c.
int connection_dir_finished_flushing(dir_connection_t *conn)
Definition directory.c:547
int connection_dir_finished_connecting(dir_connection_t *conn)
Definition directory.c:593
int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose, const char *resource)
Definition directory.c:114
int dir_split_resource_into_fingerprint_pairs(const char *res, smartlist_t *pairs_out)
Definition directory.c:625
int parse_http_response(const char *headers, int *code, time_t *date, compress_method_t *compression, char **reason)
Definition directory.c:393
static int compare_pairs_(const void **a, const void **b)
Definition directory.c:610
char * authdir_type_to_string(dirinfo_type_t auth)
Definition directory.c:161
int connection_dir_is_encrypted(const dir_connection_t *conn)
Definition directory.c:181
const dir_connection_t * CONST_TO_DIR_CONN(const connection_t *c)
Definition directory.c:102
dir_connection_t * TO_DIR_CONN(connection_t *c)
Definition directory.c:89
int dir_split_resource_into_fingerprints(const char *resource, smartlist_t *fp_out, int *compressed_out, int flags)
Definition directory.c:684
bool connection_dir_is_anonymous(const dir_connection_t *dir_conn)
Definition directory.c:201
char * http_get_header(const char *headers, const char *which)
Definition directory.c:358
bool connection_dir_used_obsolete_sendme(const dir_connection_t *conn)
Definition directory.c:283
int parse_http_command(const char *headers, char **command_out, char **url_out)
Definition directory.c:304
void connection_dir_about_to_close(dir_connection_t *dir_conn)
Definition directory.c:518
#define MAX_DIRECTORY_OBJECT_SIZE
Definition directory.c:468
int connection_dir_process_inbuf(dir_connection_t *conn)
Definition directory.c:476
Header file for directory.c.
#define DIR_PURPOSE_FETCH_EXTRAINFO
Definition directory.h:39
#define DIR_PURPOSE_FETCH_CERTIFICATE
Definition directory.h:57
#define DIR_PURPOSE_UPLOAD_HSDESC
Definition directory.h:67
#define DIR_PURPOSE_FETCH_MICRODESC
Definition directory.h:65
#define DIR_CONN_STATE_CONNECTING
Definition directory.h:20
#define DIR_CONN_STATE_CLIENT_FINISHED
Definition directory.h:26
#define DIR_CONN_STATE_CLIENT_READING
Definition directory.h:24
#define DIR_CONN_STATE_SERVER_WRITING
Definition directory.h:30
#define DIR_PURPOSE_UPLOAD_VOTE
Definition directory.h:43
#define DIR_CONN_STATE_SERVER_COMMAND_WAIT
Definition directory.h:28
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES
Definition directory.h:51
#define DIR_PURPOSE_FETCH_CONSENSUS
Definition directory.h:54
#define DIR_PURPOSE_SERVER
Definition directory.h:60
#define DIR_PURPOSE_FETCH_SERVERDESC
Definition directory.h:36
#define DIR_PURPOSE_UPLOAD_SIGNATURES
Definition directory.h:45
#define DIR_CONN_STATE_CLIENT_SENDING
Definition directory.h:22
#define DIR_PURPOSE_FETCH_STATUS_VOTE
Definition directory.h:48
#define DIR_PURPOSE_HAS_FETCHED_HSDESC
Definition directory.h:72
#define DIR_PURPOSE_UPLOAD_DIR
Definition directory.h:41
#define DIR_PURPOSE_FETCH_HSDESC
Definition directory.h:69
Header file for dirserv.c.
Edge-connection structure.
const char * escaped(const char *s)
Definition escape.c:126
Header file for fp_pair.c.
Header file for geoip_stats.c.
@ DIRREQ_FLUSHING_DIR_CONN_FINISHED
Definition geoip_stats.h:67
void hs_cache_mark_dowloaded_as_dir(const hs_ident_dir_conn_t *ident)
Definition hs_cache.c:442
Header file for hs_cache.c.
#define LD_HTTP
Definition log.h:76
#define LD_DIRSERV
Definition log.h:90
#define LD_BUG
Definition log.h:86
#define LD_DIR
Definition log.h:88
void tor_free_(void *mem)
Definition malloc.c:227
#define tor_free(p)
Definition malloc.h:56
Master header file for Tor-specific functionality.
#define TO_CONN(c)
Definition or.h:709
#define DOWNCAST(to, ptr)
Definition or.h:109
dirinfo_type_t
Definition or.h:890
@ V3_DIRINFO
Definition or.h:893
@ BRIDGE_DIRINFO
Definition or.h:895
OR connection structure.
Router descriptor structure.
#define ROUTER_PURPOSE_BRIDGE
int tor_sscanf(const char *buf, const char *pattern,...)
Definition scanf.c:309
void smartlist_sort_digests(smartlist_t *sl)
Definition smartlist.c:824
void smartlist_sort_digests256(smartlist_t *sl)
Definition smartlist.c:846
void smartlist_uniq_digests(smartlist_t *sl)
Definition smartlist.c:832
void smartlist_uniq_digests256(smartlist_t *sl)
Definition smartlist.c:863
void smartlist_uniq_strings(smartlist_t *sl)
Definition smartlist.c:574
void smartlist_sort_strings(smartlist_t *sl)
Definition smartlist.c:549
char * smartlist_join_strings(smartlist_t *sl, const char *join, int terminate, size_t *len_out)
Definition smartlist.c:279
void smartlist_sort(smartlist_t *sl, int(*compare)(const void **a, const void **b))
Definition smartlist.c:334
void smartlist_uniq(smartlist_t *sl, int(*compare)(const void **a, const void **b), void(*free_fn)(void *a))
Definition smartlist.c:390
void smartlist_add_all(smartlist_t *s1, const smartlist_t *s2)
smartlist_t * smartlist_new(void)
void smartlist_add(smartlist_t *sl, void *element)
void smartlist_del_keeporder(smartlist_t *sl, int idx)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
int smartlist_split_string(smartlist_t *sl, const char *str, const char *sep, int flags, int max)
uint16_t marked_for_close
Definition circuit_st.h:200
unsigned int inbuf_reached_eof
struct connection_t * linked_conn
unsigned int type
uint32_t magic
uint16_t marked_for_close
unsigned int linked_conn_is_closed
unsigned int purpose
smartlist_t * spool
struct circuit_t * on_circuit
bool used_obsolete_sendme
int parse_rfc1123_time(const char *buf, time_t *t)
Definition time_fmt.c:237
#define tor_assert_nonfatal_unreached()
Definition util_bug.h:177
#define tor_assert(expr)
Definition util_bug.h:103
#define tor_fragile_assert()
Definition util_bug.h:278
int strcasecmpstart(const char *s1, const char *s2)
int strcmpstart(const char *s1, const char *s2)
const char * find_whitespace(const char *s)
const char * eat_whitespace_no_nl(const char *s)