Line data Source code
1 : /* Copyright (c) 2003-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 : /**
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 59 : MOCK_IMPL(int,
46 : tor_lookup_hostname,(const char *name, uint32_t *addr))
47 : {
48 59 : tor_addr_t myaddr;
49 59 : int ret;
50 :
51 59 : if (BUG(!addr))
52 0 : return -1;
53 :
54 59 : *addr = 0;
55 :
56 59 : if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
57 : return ret;
58 :
59 4 : if (tor_addr_family(&myaddr) == AF_INET) {
60 4 : *addr = tor_addr_to_ipv4h(&myaddr);
61 4 : 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 3 : MOCK_IMPL(STATIC int,
75 : tor_addr_lookup_host_impl,(const char *name,
76 : uint16_t family,
77 : tor_addr_t *addr))
78 : {
79 3 : int err;
80 3 : struct addrinfo *res=NULL, *res_p;
81 3 : struct addrinfo *best=NULL;
82 3 : struct addrinfo hints;
83 3 : int result = -1;
84 3 : memset(&hints, 0, sizeof(hints));
85 3 : hints.ai_family = family;
86 3 : hints.ai_socktype = SOCK_STREAM;
87 3 : 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 3 : if (!err && res) {
91 : best = NULL;
92 0 : for (res_p = res; res_p; res_p = res_p->ai_next) {
93 0 : if (family == AF_UNSPEC) {
94 0 : if (res_p->ai_family == AF_INET) {
95 : best = res_p;
96 : break;
97 0 : } else if (res_p->ai_family == AF_INET6 && !best) {
98 0 : best = res_p;
99 : }
100 0 : } else if (family == res_p->ai_family) {
101 : best = res_p;
102 : break;
103 : }
104 : }
105 0 : if (!best)
106 0 : best = res;
107 0 : if (best->ai_family == AF_INET) {
108 0 : tor_addr_from_in(addr,
109 0 : &((struct sockaddr_in*)best->ai_addr)->sin_addr);
110 0 : result = 0;
111 0 : } else if (best->ai_family == AF_INET6) {
112 0 : tor_addr_from_in6(addr,
113 0 : &((struct sockaddr_in6*)best->ai_addr)->sin6_addr);
114 0 : result = 0;
115 : }
116 0 : tor_freeaddrinfo(res);
117 0 : return result;
118 : }
119 3 : 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 2527 : 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 2527 : int parsed_family = 0;
196 2527 : int result = -1;
197 :
198 2527 : tor_assert(name);
199 2527 : tor_assert(addr);
200 2527 : tor_assert(family == AF_INET || family == AF_INET6 || family == AF_UNSPEC);
201 :
202 2527 : if (!*name) {
203 : /* Empty address is an error. */
204 5 : goto permfail;
205 : }
206 :
207 : /* Is it an IP address? */
208 2522 : parsed_family = tor_addr_parse(addr, name);
209 :
210 2522 : if (parsed_family >= 0) {
211 : /* If the IP address family matches, or was unspecified */
212 2333 : if (parsed_family == family || family == AF_UNSPEC) {
213 2303 : goto success;
214 : } else {
215 30 : goto permfail;
216 : }
217 : } else {
218 : /* Clear the address after a failed tor_addr_parse(). */
219 189 : memset(addr, 0, sizeof(tor_addr_t));
220 189 : result = tor_addr_lookup_host_impl(name, family, addr);
221 189 : 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 35 : permfail:
227 35 : result = -1;
228 35 : goto done;
229 2303 : success:
230 2303 : result = 0;
231 :
232 : /* We have set the result, now it's time to clean up */
233 189 : done:
234 2527 : if (result) {
235 : /* Clear the address on error */
236 211 : memset(addr, 0, sizeof(tor_addr_t));
237 : }
238 2527 : 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 275 : tor_addr_port_lookup(const char *s, tor_addr_t *addr_out, uint16_t *port_out)
253 : {
254 275 : tor_addr_t addr;
255 275 : uint16_t portval = 0;
256 275 : char *tmp = NULL;
257 275 : int rv = 0;
258 275 : int result;
259 :
260 275 : tor_assert(s);
261 275 : tor_assert(addr_out);
262 :
263 275 : 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 275 : rv = tor_addr_port_parse(LOG_WARN, s, &addr, &portval, 0);
268 : /* That was easy, no DNS required. */
269 275 : if (rv == 0)
270 220 : 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 55 : 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 55 : if (family >= 0) {
281 : /* Double-check it's an IPv6 address. If not, we have a parsing bug.
282 : */
283 0 : 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 0 : goto err;
289 : }
290 :
291 : /* Now we have a hostname. Let's split off the port, if any. */
292 55 : rv = tor_addr_port_split(LOG_WARN, s, &tmp, &portval);
293 55 : if (rv < 0)
294 22 : goto err;
295 :
296 : /* And feed the hostname to the lookup function. */
297 33 : if (tor_addr_lookup(tmp, AF_UNSPEC, &addr) != 0)
298 24 : goto err;
299 :
300 9 : success:
301 229 : if (port_out)
302 229 : *port_out = portval;
303 229 : tor_addr_copy(addr_out, &addr);
304 229 : result = 0;
305 229 : goto done;
306 :
307 46 : err:
308 : /* Clear the address and port on error */
309 46 : memset(addr_out, 0, sizeof(tor_addr_t));
310 46 : if (port_out)
311 46 : *port_out = 0;
312 : result = -1;
313 :
314 : /* We have set the result, now it's time to clean up */
315 275 : done:
316 275 : tor_free(tmp);
317 275 : 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 6 : cached_getaddrinfo_item_hash(const cached_getaddrinfo_item_t *item)
343 : {
344 6 : return (unsigned)siphash24g(item->name, strlen(item->name)) + item->family;
345 : }
346 :
347 : static unsigned
348 0 : cached_getaddrinfo_items_eq(const cached_getaddrinfo_item_t *a,
349 : const cached_getaddrinfo_item_t *b)
350 : {
351 0 : 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 2 : cached_getaddrinfo_item_free_(cached_getaddrinfo_item_t *item)
360 : {
361 2 : if (item == NULL)
362 : return;
363 :
364 2 : tor_free(item->name);
365 2 : if (item->res)
366 0 : freeaddrinfo(item->res);
367 2 : tor_free(item);
368 : }
369 :
370 : static HT_HEAD(getaddrinfo_cache, cached_getaddrinfo_item_t)
371 : getaddrinfo_cache = HT_INITIALIZER();
372 :
373 585 : HT_PROTOTYPE(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
374 : cached_getaddrinfo_item_hash,
375 : cached_getaddrinfo_items_eq);
376 238 : HT_GENERATE2(getaddrinfo_cache, cached_getaddrinfo_item_t, node,
377 : cached_getaddrinfo_item_hash,
378 : cached_getaddrinfo_items_eq,
379 : 0.6, tor_reallocarray_, tor_free_);
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 22 : sandbox_disable_getaddrinfo_cache(void)
389 : {
390 22 : sandbox_getaddrinfo_cache_disabled = 1;
391 22 : }
392 :
393 : void
394 0 : tor_freeaddrinfo(struct addrinfo *ai)
395 : {
396 0 : if (sandbox_getaddrinfo_cache_disabled)
397 0 : freeaddrinfo(ai);
398 0 : }
399 :
400 : int
401 3 : tor_getaddrinfo(const char *name, const char *servname,
402 : const struct addrinfo *hints,
403 : struct addrinfo **res)
404 : {
405 3 : int err;
406 3 : struct cached_getaddrinfo_item_t search, *item;
407 :
408 3 : if (sandbox_getaddrinfo_cache_disabled) {
409 0 : return getaddrinfo(name, NULL, hints, res);
410 : }
411 :
412 3 : if (servname != NULL) {
413 0 : log_warn(LD_BUG, "called with non-NULL servname");
414 0 : return EAI_NONAME;
415 : }
416 3 : if (name == NULL) {
417 0 : log_warn(LD_BUG, "called with NULL name");
418 0 : return EAI_NONAME;
419 : }
420 :
421 3 : *res = NULL;
422 :
423 3 : memset(&search, 0, sizeof(search));
424 3 : search.name = (char *) name;
425 3 : search.family = hints ? hints->ai_family : AF_UNSPEC;
426 3 : item = HT_FIND(getaddrinfo_cache, &getaddrinfo_cache, &search);
427 :
428 3 : if (! sandbox_getaddrinfo_is_active) {
429 : /* If the sandbox is not turned on yet, then getaddrinfo and store the
430 : result. */
431 :
432 3 : err = getaddrinfo(name, NULL, hints, res);
433 3 : log_info(LD_NET,"(Sandbox) getaddrinfo %s.", err ? "failed" : "succeeded");
434 :
435 3 : if (! item) {
436 3 : item = tor_malloc_zero(sizeof(*item));
437 3 : item->name = tor_strdup(name);
438 3 : item->family = hints ? hints->ai_family : AF_UNSPEC;
439 3 : HT_INSERT(getaddrinfo_cache, &getaddrinfo_cache, item);
440 : }
441 :
442 3 : if (item->res) {
443 0 : freeaddrinfo(item->res);
444 0 : item->res = NULL;
445 : }
446 3 : item->res = *res;
447 3 : item->err = err;
448 3 : return err;
449 : }
450 :
451 : /* Otherwise, the sandbox is on. If we have an item, yield its cached
452 : result. */
453 0 : if (item) {
454 0 : *res = item->res;
455 0 : return item->err;
456 : }
457 :
458 : /* getting here means something went wrong */
459 0 : log_err(LD_BUG,"(Sandbox) failed to get address %s!", name);
460 0 : return EAI_NONAME;
461 : }
462 :
463 : int
464 0 : tor_add_addrinfo(const char *name)
465 : {
466 0 : struct addrinfo *res;
467 0 : struct addrinfo hints;
468 0 : int i;
469 0 : static const int families[] = { AF_INET, AF_INET6, AF_UNSPEC };
470 :
471 0 : memset(&hints, 0, sizeof(hints));
472 0 : hints.ai_socktype = SOCK_STREAM;
473 0 : for (i = 0; i < 3; ++i) {
474 0 : hints.ai_family = families[i];
475 :
476 0 : res = NULL;
477 0 : (void) tor_getaddrinfo(name, NULL, &hints, &res);
478 0 : if (res)
479 0 : tor_freeaddrinfo(res);
480 : }
481 :
482 0 : return 0;
483 : }
484 :
485 : void
486 235 : tor_free_getaddrinfo_cache(void)
487 : {
488 235 : cached_getaddrinfo_item_t **next, **item, *this;
489 :
490 235 : for (item = HT_START(getaddrinfo_cache, &getaddrinfo_cache);
491 237 : item;
492 2 : item = next) {
493 2 : this = *item;
494 2 : next = HT_NEXT_RMV(getaddrinfo_cache, &getaddrinfo_cache, item);
495 2 : cached_getaddrinfo_item_free(this);
496 : }
497 :
498 235 : HT_CLEAR(getaddrinfo_cache, &getaddrinfo_cache);
499 235 : }
500 :
501 : void
502 0 : tor_make_getaddrinfo_cache_active(void)
503 : {
504 0 : sandbox_getaddrinfo_is_active = 1;
505 0 : }
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) */
|