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