Tor  0.4.3.0-alpha-dev
resolve.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-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 /**
7  * \file resolve.c
8  * \brief Use the libc DNS resolver to convert hostnames into addresses.
9  **/
10 
11 #define RESOLVE_PRIVATE
12 #include "lib/net/resolve.h"
13 
14 #include "lib/net/address.h"
15 #include "lib/net/inaddr.h"
16 #include "lib/malloc/malloc.h"
17 #include "lib/string/parse_int.h"
18 #include "lib/string/util_string.h"
19 
20 #include "ext/siphash.h"
21 #include "ext/ht.h"
22 
23 #ifdef HAVE_SYS_TYPES_H
24 #include <sys/types.h>
25 #endif
26 #ifdef HAVE_SYS_SOCKET_H
27 #include <sys/socket.h>
28 #endif
29 #ifdef HAVE_NETDB_H
30 #include <netdb.h>
31 #endif
32 
33 #include <string.h>
34 
35 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
36  * *<b>addr</b> to the proper IP address, in host byte order. Returns 0
37  * on success, -1 on failure; 1 on transient failure.
38  *
39  * This function only accepts IPv4 addresses.
40  *
41  * (This function exists because standard windows gethostbyname
42  * doesn't treat raw IP addresses properly.)
43  */
44 
45 MOCK_IMPL(int,
46 tor_lookup_hostname,(const char *name, uint32_t *addr))
47 {
48  tor_addr_t myaddr;
49  int ret;
50 
51  if (BUG(!addr))
52  return -1;
53 
54  *addr = 0;
55 
56  if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
57  return ret;
58 
59  if (tor_addr_family(&myaddr) == AF_INET) {
60  *addr = tor_addr_to_ipv4h(&myaddr);
61  return ret;
62  }
63 
64  return -1;
65 }
66 
67 #ifdef HAVE_GETADDRINFO
68 
69 /* Host lookup helper for tor_addr_lookup(), when getaddrinfo() is
70  * available on this system.
71  *
72  * See tor_addr_lookup() for details.
73  */
74 MOCK_IMPL(STATIC int,
75 tor_addr_lookup_host_impl,(const char *name,
76  uint16_t family,
77  tor_addr_t *addr))
78 {
79  int err;
80  struct addrinfo *res=NULL, *res_p;
81  struct addrinfo *best=NULL;
82  struct addrinfo hints;
83  int result = -1;
84  memset(&hints, 0, sizeof(hints));
85  hints.ai_family = family;
86  hints.ai_socktype = SOCK_STREAM;
87  err = tor_getaddrinfo(name, NULL, &hints, &res);
88  /* The check for 'res' here shouldn't be necessary, but it makes static
89  * analysis tools happy. */
90  if (!err && res) {
91  best = NULL;
92  for (res_p = res; res_p; res_p = res_p->ai_next) {
93  if (family == AF_UNSPEC) {
94  if (res_p->ai_family == AF_INET) {
95  best = res_p;
96  break;
97  } else if (res_p->ai_family == AF_INET6 && !best) {
98  best = res_p;
99  }
100  } else if (family == res_p->ai_family) {
101  best = res_p;
102  break;
103  }
104  }
105  if (!best)
106  best = res;
107  if (best->ai_family == AF_INET) {
108  tor_addr_from_in(addr,
109  &((struct sockaddr_in*)best->ai_addr)->sin_addr);
110  result = 0;
111  } else if (best->ai_family == AF_INET6) {
112  tor_addr_from_in6(addr,
113  &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
114  result = 0;
115  }
116  tor_freeaddrinfo(res);
117  return result;
118  }
119  return (err == EAI_AGAIN) ? 1 : -1;
120 }
121 
122 #else /* !defined(HAVE_GETADDRINFO) */
123 
124 /* Host lookup helper for tor_addr_lookup(), which calls gethostbyname().
125  * Used when getaddrinfo() is not available on this system.
126  *
127  * See tor_addr_lookup() for details.
128  */
129 MOCK_IMPL(STATIC int,
130 tor_addr_lookup_host_impl,(const char *name,
131  uint16_t family,
132  tor_addr_t *addr))
133 {
134  (void) family;
135  struct hostent *ent;
136  int err;
137 #ifdef HAVE_GETHOSTBYNAME_R_6_ARG
138  char buf[2048];
139  struct hostent hostent;
140  int r;
141  r = gethostbyname_r(name, &hostent, buf, sizeof(buf), &ent, &err);
142 #elif defined(HAVE_GETHOSTBYNAME_R_5_ARG)
143  char buf[2048];
144  struct hostent hostent;
145  ent = gethostbyname_r(name, &hostent, buf, sizeof(buf), &err);
146 #elif defined(HAVE_GETHOSTBYNAME_R_3_ARG)
147  struct hostent_data data;
148  struct hostent hent;
149  memset(&data, 0, sizeof(data));
150  err = gethostbyname_r(name, &hent, &data);
151  ent = err ? NULL : &hent;
152 #else
153  ent = gethostbyname(name);
154 #ifdef _WIN32
155  err = WSAGetLastError();
156 #else
157  err = h_errno;
158 #endif /* defined(_WIN32) */
159 #endif /* defined(HAVE_GETHOSTBYNAME_R_6_ARG) || ... */
160  if (ent) {
161  if (ent->h_addrtype == AF_INET) {
162  tor_addr_from_in(addr, (struct in_addr*) ent->h_addr);
163  } else if (ent->h_addrtype == AF_INET6) {
164  tor_addr_from_in6(addr, (struct in6_addr*) ent->h_addr);
165  } else {
166  tor_assert(0); // LCOV_EXCL_LINE: gethostbyname() returned bizarre type
167  }
168  return 0;
169  }
170 #ifdef _WIN32
171  return (err == WSATRY_AGAIN) ? 1 : -1;
172 #else
173  return (err == TRY_AGAIN) ? 1 : -1;
174 #endif
175 }
176 #endif /* defined(HAVE_GETADDRINFO) */
177 
178 /** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
179  * *<b>addr</b> to the proper IP address and family. The <b>family</b>
180  * argument (which must be AF_INET, AF_INET6, or AF_UNSPEC) declares a
181  * <i>preferred</i> family, though another one may be returned if only one
182  * family is implemented for this address.
183  *
184  * Like tor_addr_parse(), this function accepts IPv6 addresses with or without
185  * square brackets.
186  *
187  * Return 0 on success, -1 on failure; 1 on transient failure.
188  */
189 MOCK_IMPL(int,
190 tor_addr_lookup,(const char *name, uint16_t family, tor_addr_t *addr))
191 {
192  /* Perhaps eventually this should be replaced by a tor_getaddrinfo or
193  * something.
194  */
195  int parsed_family = 0;
196  int result = -1;
197 
198  tor_assert(name);
199  tor_assert(addr);
200  tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
201 
202  if (!*name) {
203  /* Empty address is an error. */
204  goto permfail;
205  }
206 
207  /* Is it an IP address? */
208  parsed_family = tor_addr_parse(addr, name);
209 
210  if (parsed_family >= 0) {
211  /* If the IP address family matches, or was unspecified */
212  if (parsed_family == family || family == AF_UNSPEC) {
213  goto success;
214  } else {
215  goto permfail;
216  }
217  } else {
218  /* Clear the address after a failed tor_addr_parse(). */
219  memset(addr, 0, sizeof(tor_addr_t));
220  result = tor_addr_lookup_host_impl(name, family, addr);
221  goto done;
222  }
223 
224  /* If we weren't successful, and haven't already set the result,
225  * assume it's a permanent failure */
226  permfail:
227  result = -1;
228  goto done;
229  success:
230  result = 0;
231 
232  /* We have set the result, now it's time to clean up */
233  done:
234  if (result) {
235  /* Clear the address on error */
236  memset(addr, 0, sizeof(tor_addr_t));
237  }
238  return result;
239 }
240 
241 /** Parse an address or address-port combination from <b>s</b>, resolve the
242  * address as needed, and put the result in <b>addr_out</b> and (optionally)
243  * <b>port_out</b>.
244  *
245  * Like tor_addr_port_parse(), this function accepts:
246  * - IPv6 address and port, when the IPv6 address is in square brackets,
247  * - IPv6 address with square brackets,
248  * - IPv6 address without square brackets.
249  *
250  * Return 0 on success, negative on failure. */
251 int
252 tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
253 {
254  tor_addr_t addr;
255  uint16_t portval = 0;
256  char *tmp = NULL;
257  int rv = 0;
258  int result;
259 
260  tor_assert(s);
261  tor_assert(addr_out);
262 
263  s = eat_whitespace(s);
264 
265  /* Try parsing s as an address:port first, so we don't have to duplicate
266  * the logic that rejects IPv6:Port with no square brackets. */
267  rv = tor_addr_port_parse(LOG_WARN, s, &addr, &portval, 0);
268  /* That was easy, no DNS required. */
269  if (rv == 0)
270  goto success;
271 
272  /* Now let's check for malformed IPv6 addresses and ports:
273  * tor_addr_port_parse() requires squared brackes if there is a port,
274  * and we want tor_addr_port_lookup() to have the same requirement.
275  * But we strip the port using tor_addr_port_split(), so tor_addr_lookup()
276  * only sees the address, and will accept it without square brackets. */
277  int family = tor_addr_parse(&addr, s);
278  /* If tor_addr_parse() succeeds where tor_addr_port_parse() failed, we need
279  * to reject this address as malformed. */
280  if (family >= 0) {
281  /* Double-check it's an IPv6 address. If not, we have a parsing bug.
282  */
283  tor_assertf_nonfatal(family == AF_INET6,
284  "Wrong family: %d (should be IPv6: %d) which "
285  "failed IP:port parsing, but passed IP parsing. "
286  "input string: '%s'; parsed address: '%s'.",
287  family, AF_INET6, s, fmt_addr(&addr));
288  goto err;
289  }
290 
291  /* Now we have a hostname. Let's split off the port, if any. */
292  rv = tor_addr_port_split(LOG_WARN, s, &tmp, &portval);
293  if (rv < 0)
294  goto err;
295 
296  /* And feed the hostname to the lookup function. */
297  if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
298  goto err;
299 
300  success:
301  if (port_out)
302  *port_out = portval;
303  tor_addr_copy(addr_out, &addr);
304  result = 0;
305  goto done;
306 
307  err:
308  /* Clear the address and port on error */
309  memset(addr_out, 0, sizeof(tor_addr_t));
310  if (port_out)
311  *port_out = 0;
312  result = -1;
313 
314  /* We have set the result, now it's time to clean up */
315  done:
316  tor_free(tmp);
317  return result;
318 }
319 
320 #ifdef USE_SANDBOX_GETADDRINFO
321 /** True if we should only return cached values */
322 static int sandbox_getaddrinfo_is_active = 0;
323 
324 /** Cache entry for getaddrinfo results; used when sandboxing is implemented
325  * so that we can consult the cache when the sandbox prevents us from doing
326  * getaddrinfo.
327  *
328  * We support only a limited range of getaddrinfo calls, where servname is null
329  * and hints contains only socktype=SOCK_STREAM, family in INET,INET6,UNSPEC.
330  */
331 typedef struct cached_getaddrinfo_item_t {
332  HT_ENTRY(cached_getaddrinfo_item_t) node;
333  char *name;
334  int family;
335  /** set if no error; otherwise NULL */
336  struct addrinfo *res;
337  /** 0 for no error; otherwise an EAI_* value */
338  int err;
339 } cached_getaddrinfo_item_t;
340 
341 static unsigned
342 cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
343 {
344  return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
345 }
346 
347 static unsigned
348 cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
349  const cached_getaddrinfo_item_t *b)
350 {
351  return (a->family == b->family) && 0 == strcmp(a->name, b->name);
352 }
353 
354 #define cached_getaddrinfo_item_free(item) \
355  FREE_AND_NULL(cached_getaddrinfo_item_t, \
356  cached_getaddrinfo_item_free_, (item))
357 
358 static void
359 cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
360 {
361  if (item == NULL)
362  return;
363 
364  tor_free(item->name);
365  if (item->res)
366  freeaddrinfo(item->res);
367  tor_free(item);
368 }
369 
370 static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
371  getaddrinfo_cache = HT_INITIALIZER();
372 
373 HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
374  cached_getaddrinfo_item_hash,
375  cached_getaddrinfo_items_eq)
376 HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
377  cached_getaddrinfo_item_hash,
378  cached_getaddrinfo_items_eq,
380 
381 /** If true, don't try to cache getaddrinfo results. */
382 static int sandbox_getaddrinfo_cache_disabled = 0;
383 
384 /** Tell the sandbox layer not to try to cache getaddrinfo results. Used as in
385  * tor-resolve, when we have no intention of initializing crypto or of
386  * installing the sandbox.*/
387 void
388 sandbox_disable_getaddrinfo_cache(void)
389 {
390  sandbox_getaddrinfo_cache_disabled = 1;
391 }
392 
393 void
394 tor_freeaddrinfo(struct addrinfo *ai)
395 {
396  if (sandbox_getaddrinfo_cache_disabled)
397  freeaddrinfo(ai);
398 }
399 
400 int
401 tor_getaddrinfo(const char *name, const char *servname,
402  const struct addrinfo *hints,
403  struct addrinfo **res)
404 {
405  int err;
406  struct cached_getaddrinfo_item_t search, *item;
407 
408  if (sandbox_getaddrinfo_cache_disabled) {
409  return getaddrinfo(name, NULL, hints, res);
410  }
411 
412  if (servname != NULL) {
413  log_warn(LD_BUG, "called with non-NULL servname");
414  return EAI_NONAME;
415  }
416  if (name == NULL) {
417  log_warn(LD_BUG, "called with NULL name");
418  return EAI_NONAME;
419  }
420 
421  *res = NULL;
422 
423  memset(&search, 0, sizeof(search));
424  search.name = (char *) name;
425  search.family = hints ? hints->ai_family : AF_UNSPEC;
426  item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
427 
428  if (! sandbox_getaddrinfo_is_active) {
429  /* If the sandbox is not turned on yet, then getaddrinfo and store the
430  result. */
431 
432  err = getaddrinfo(name, NULL, hints, res);
433  log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
434 
435  if (! item) {
436  item = tor_malloc_zero(sizeof(*item));
437  item->name = tor_strdup(name);
438  item->family = hints ? hints->ai_family : AF_UNSPEC;
439  HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
440  }
441 
442  if (item->res) {
443  freeaddrinfo(item->res);
444  item->res = NULL;
445  }
446  item->res = *res;
447  item->err = err;
448  return err;
449  }
450 
451  /* Otherwise, the sandbox is on. If we have an item, yield its cached
452  result. */
453  if (item) {
454  *res = item->res;
455  return item->err;
456  }
457 
458  /* getting here means something went wrong */
459  log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
460  return EAI_NONAME;
461 }
462 
463 int
464 tor_add_addrinfo(const char *name)
465 {
466  struct addrinfo *res;
467  struct addrinfo hints;
468  int i;
469  static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
470 
471  memset(&hints, 0, sizeof(hints));
472  hints.ai_socktype = SOCK_STREAM;
473  for (i = 0; i < 3; ++i) {
474  hints.ai_family = families[i];
475 
476  res = NULL;
477  (void) tor_getaddrinfo(name, NULL, &hints, &res);
478  if (res)
479  tor_freeaddrinfo(res);
480  }
481 
482  return 0;
483 }
484 
485 void
486 tor_free_getaddrinfo_cache(void)
487 {
488  cached_getaddrinfo_item_t **next, **item, *this;
489 
490  for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
491  item;
492  item = next) {
493  this = *item;
494  next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
495  cached_getaddrinfo_item_free(this);
496  }
497 
498  HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
499 }
500 
501 void
502 tor_make_getaddrinfo_cache_active(void)
503 {
504  sandbox_getaddrinfo_is_active = 1;
505 }
506 #else /* !defined(USE_SANDBOX_GETADDRINFO) */
507 void
508 sandbox_disable_getaddrinfo_cache(void)
509 {
510 }
511 void
512 tor_make_getaddrinfo_cache_active(void)
513 {
514 }
515 #endif /* defined(USE_SANDBOX_GETADDRINFO) */
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
int tor_addr_lookup(const char *name, uint16_t family, tor_addr_t *addr)
Definition: resolve.c:190
#define tor_assert(expr)
Definition: util_bug.h:102
static uint32_t tor_addr_to_ipv4h(const tor_addr_t *a)
Definition: address.h:152
#define tor_free(p)
Definition: malloc.h:52
Header for util_string.c.
Header for inaddr.c.
const char * name
Definition: config.c:2441
Headers for util_malloc.c.
int tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
Definition: resolve.c:252
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
Definition: malloc.c:146
#define tor_addr_from_in(dest, in)
Definition: address.h:291
#define STATIC
Definition: testsupport.h:32
int tor_addr_port_parse(int severity, const char *addrport, tor_addr_t *address_out, uint16_t *port_out, int default_port)
Definition: address.c:1759
Headers for address.h.
HT_GENERATE2(cdm_diff_ht, cdm_diff_t, node, cdm_diff_hash, cdm_diff_eq, 0.6, tor_reallocarray, tor_free_) static void cdm_diff_free_(cdm_diff_t *diff)
Definition: consdiffmgr.c:222
const char * eat_whitespace(const char *s)
Definition: util_string.c:268
int tor_addr_parse(tor_addr_t *addr, const char *src)
Definition: address.c:1255
#define LOG_WARN
Definition: log.h:53
void tor_free_(void *mem)
Definition: malloc.c:227
void tor_addr_from_in6(tor_addr_t *dest, const struct in6_addr *in6)
Definition: address.c:896
HT_PROTOTYPE(HT_GENERATE2(channel_gid_map, HT_GENERATE2(channel_t, HT_GENERATE2(gidmap_node, HT_GENERATE2(channel_id_hash, HT_GENERATE2(channel_id_eq)
Definition: channel.c:121
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht
#define fmt_addr(a)
Definition: address.h:211
Header for resolve.c.
#define LD_NET
Definition: log.h:66
void tor_addr_copy(tor_addr_t *dest, const tor_addr_t *src)
Definition: address.c:904
Header for parse_int.c.
#define LD_BUG
Definition: log.h:86
static sa_family_t tor_addr_family(const tor_addr_t *a)
Definition: address.h:179
int tor_addr_port_split(int severity, const char *addrport, char **address_out, uint16_t *port_out)
Definition: address.c:1818
int tor_lookup_hostname(const char *name, uint32_t *addr)
Definition: resolve.c:46