resolve.c (14099B)
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 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, 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 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) */