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