1 /* 2 * Copyright (c) 1998-2004, 2006, 2010 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved. 5 * Copyright (c) 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * By using this file, you agree to the terms and conditions set 9 * forth in the LICENSE file which can be found at the top level of 10 * the sendmail distribution. 11 * 12 */ 13 14 #include <sendmail.h> 15 #include "map.h" 16 #if _FFR_EAI 17 #include <unicode/uidna.h> 18 #endif 19 20 #if NAMED_BIND 21 SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (with name server)") 22 #else 23 SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (without name server)") 24 #endif 25 26 #if NAMED_BIND 27 28 # include <arpa/inet.h> 29 # include <sm_resolve.h> 30 # if DANE 31 # include <tls.h> 32 # ifndef SM_NEG_TTL 33 # define SM_NEG_TTL 60 /* "negative" TTL */ 34 # endif 35 # endif 36 37 38 # ifndef MXHOSTBUFSIZE 39 # define MXHOSTBUFSIZE (128 * MAXMXHOSTS) 40 # endif 41 42 static char MXHostBuf[MXHOSTBUFSIZE]; 43 # if (MXHOSTBUFSIZE < 2) || (MXHOSTBUFSIZE >= INT_MAX/2) 44 ERROR: _MXHOSTBUFSIZE is out of range 45 # endif 46 47 # ifndef MAXDNSRCH 48 # define MAXDNSRCH 6 /* number of possible domains to search */ 49 # endif 50 51 # ifndef RES_DNSRCH_VARIABLE 52 # define RES_DNSRCH_VARIABLE _res.dnsrch 53 # endif 54 55 # ifndef NO_DATA 56 # define NO_DATA NO_ADDRESS 57 # endif 58 59 # ifndef HFIXEDSZ 60 # define HFIXEDSZ 12 /* sizeof(HEADER) */ 61 # endif 62 63 # define MAXCNAMEDEPTH 10 /* maximum depth of CNAME recursion */ 64 65 # if defined(__RES) && (__RES >= 19940415) 66 # define RES_UNC_T char * 67 # else 68 # define RES_UNC_T unsigned char * 69 # endif 70 71 static int mxrand __P((char *)); 72 static int fallbackmxrr __P((int, unsigned short *, char **)); 73 74 # if DANE 75 76 /* 77 ** TLSAADD -- add TLSA records to dane_tlsa entry 78 ** 79 ** Parameters: 80 ** name -- key for stab entry (for debugging output) 81 ** dr -- DNS reply 82 ** dane_tlsa -- dane_tlsa entry 83 ** dnsrc -- DNS lookup return code (h_errno) 84 ** n -- current number of TLSA records in dane_tlsa entry 85 ** pttl -- (pointer to) TTL (in/out) 86 ** level -- recursion level (CNAMEs) 87 ** 88 ** Returns: 89 ** new number of TLSA records 90 */ 91 92 static int tlsaadd __P((const char *, DNS_REPLY_T *, dane_tlsa_P, int, int, 93 unsigned int *, int)); 94 95 static int 96 tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level) 97 const char *name; 98 DNS_REPLY_T *dr; 99 dane_tlsa_P dane_tlsa; 100 int dnsrc; 101 int n; 102 unsigned int *pttl; 103 int level; 104 { 105 RESOURCE_RECORD_T *rr; 106 unsigned int ttl; 107 int nprev; 108 109 if (dnsrc != 0) 110 { 111 if (tTd(8, 2)) 112 sm_dprintf("tlsaadd(%s), prev=%d, dnsrc=%d\n", 113 name, dane_tlsa->dane_tlsa_dnsrc, dnsrc); 114 115 /* check previous error and keep the "most important" one? */ 116 dane_tlsa->dane_tlsa_dnsrc = dnsrc; 117 # if DNSSEC_TEST 118 if (tTd(8, 110)) 119 *pttl = tTdlevel(8)-110; /* how to make this an option? */ 120 else 121 # else 122 *pttl = SM_NEG_TTL; 123 # endif 124 125 return n; 126 } 127 if (dr == NULL) 128 return n; 129 if (dr->dns_r_h.ad != 1 && Dane == DANE_SECURE) /* not secure? */ 130 return n; 131 ttl = *pttl; 132 133 /* first: try to find TLSA records */ 134 nprev = n; 135 for (rr = dr->dns_r_head; rr != NULL && n < MAX_TLSA_RR; 136 rr = rr->rr_next) 137 { 138 int tlsa_chk; 139 140 if (rr->rr_type != T_TLSA) 141 { 142 if (rr->rr_type != T_CNAME && tTd(8, 8)) 143 sm_dprintf("tlsaadd(%s), type=%s\n", name, 144 dns_type_to_string(rr->rr_type)); 145 continue; 146 } 147 tlsa_chk = dane_tlsa_chk(rr->rr_u.rr_data, rr->rr_size, name, 148 true); 149 if (!TLSA_IS_VALID(tlsa_chk)) 150 continue; 151 152 /* 153 ** To do: the RRs should be sorted (by "complexity") -- 154 ** when more than one type is supported. 155 */ 156 157 dane_tlsa->dane_tlsa_rr[n] = rr->rr_u.rr_data; 158 dane_tlsa->dane_tlsa_len[n] = rr->rr_size; 159 if (tTd(8, 2)) 160 { 161 unsigned char *p; 162 163 p = rr->rr_u.rr_data; 164 sm_dprintf("tlsaadd(%s), n=%d, %d-%d-%d:%02x\n", name, 165 n, (int)p[0], (int)p[1], (int)p[2], (int)p[3]); 166 } 167 168 /* require some minimum TTL? */ 169 if (ttl > rr->rr_ttl && rr->rr_ttl > 0) 170 ttl = rr->rr_ttl; 171 172 /* hack: instead of copying the data, just "take it over" */ 173 rr->rr_u.rr_data = NULL; 174 ++n; 175 } 176 177 /* second: check for CNAME records, but only if no TLSA RR was added */ 178 for (rr = dr->dns_r_head; rr != NULL && n < MAX_TLSA_RR && nprev == n; 179 rr = rr->rr_next) 180 { 181 DNS_REPLY_T *drc; 182 int err, herr; 183 184 if (rr->rr_type != T_CNAME) 185 continue; 186 if (level > 1) 187 { 188 if (tTd(8, 2)) 189 sm_dprintf("tlsaadd(%s), CNAME=%s, level=%d\n", 190 name, rr->rr_u.rr_txt, level); 191 continue; 192 } 193 194 drc = dns_lookup_int(rr->rr_u.rr_txt, C_IN, T_TLSA, 0, 0, 195 (Dane == DANE_SECURE && 196 !TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX)) 197 ? SM_RES_DNSSEC : 0, 198 RR_RAW, &err, &herr); 199 200 if (tTd(8, 2)) 201 sm_dprintf("tlsaadd(%s), CNAME=%s, level=%d, dr=%p, ad=%d, err=%d, herr=%d\n", 202 name, rr->rr_u.rr_txt, level, 203 (void *)drc, drc != NULL ? drc->dns_r_h.ad : -1, 204 err, herr); 205 nprev = n = tlsaadd(name, drc, dane_tlsa, herr, n, pttl, 206 level + 1); 207 dns_free_data(drc); 208 drc = NULL; 209 } 210 211 *pttl = ttl; 212 return n; 213 } 214 215 /* 216 ** GETTLSA -- get TLSA records for named host using DNS 217 ** 218 ** Parameters: 219 ** host -- host 220 ** name -- name for stab entry key (if NULL: host) 221 ** pste -- (pointer to) stab entry (output) 222 ** flags -- TLSAFL* 223 ** mxttl -- TTL of MX (or host) 224 ** port -- port 225 ** 226 ** Returns: 227 ** The number of TLSA records found. 228 ** <0 if there is an internal failure. 229 ** 230 ** Side effects: 231 ** Enters TLSA RRs into stab(). 232 ** If the DNS lookup fails temporarily, an "empty" entry is 233 ** created with that DNS error code. 234 */ 235 236 int 237 gettlsa(host, name, pste, flags, mxttl, port) 238 char *host; 239 char *name; 240 STAB **pste; 241 unsigned long flags; 242 unsigned int mxttl; 243 unsigned int port; 244 { 245 DNS_REPLY_T *dr; 246 dane_tlsa_P dane_tlsa; 247 STAB *ste; 248 time_t now; 249 unsigned int ttl; 250 int n_rrs, len, err, herr; 251 bool isrname; 252 char nbuf[MAXDNAME]; 253 char key[MAXDNAME]; 254 255 SM_REQUIRE(host != NULL); 256 if (pste != NULL) 257 *pste = NULL; 258 if ('\0' == *host) 259 return 0; 260 261 isrname = NULL == name; 262 if (isrname) 263 name = host; 264 now = 0; 265 n_rrs = 0; 266 dr = NULL; 267 dane_tlsa = NULL; 268 len = strlen(name); 269 if (len > 1 && name[len - 1] == '.') 270 { 271 len--; 272 name[len] = '\0'; 273 } 274 else 275 len = -1; 276 if (0 == port || tTd(66, 10)) 277 port = 25; 278 (void) sm_snprintf(key, sizeof(key), "_%u..%s", port, name); 279 ste = stab(key, ST_TLSA_RR, ST_FIND); 280 if (tTd(8, 2)) 281 sm_dprintf("gettlsa(%s, %s, ste=%p, pste=%p, flags=%lX, port=%d)\n", 282 host, isrname ? "" : name, (void *)ste, (void *)pste, 283 flags, port); 284 285 if (ste != NULL) 286 { 287 dane_tlsa = ste->s_tlsa; 288 if ((TLSAFLADMX & flags) != 0) 289 TLSA_CLR_FL(ste->s_tlsa, TLSAFLNOADMX); 290 } 291 292 /* Do not reload TLSA RRs if the MX RRs were not securely retrieved. */ 293 if (pste != NULL 294 && dane_tlsa != NULL && TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX) 295 && DANE_SECURE == Dane) 296 goto end; 297 298 if (ste != NULL) 299 { 300 SM_ASSERT(dane_tlsa != NULL); 301 now = curtime(); 302 if (dane_tlsa->dane_tlsa_exp <= now 303 && 0 == (TLSAFLNOEXP & flags)) 304 dane_tlsa_clr(dane_tlsa); 305 else 306 { 307 n_rrs = dane_tlsa->dane_tlsa_n; 308 goto end; 309 } 310 } 311 312 if (dane_tlsa == NULL) 313 { 314 dane_tlsa = (dane_tlsa_P) sm_malloc(sizeof(*dane_tlsa)); 315 if (dane_tlsa == NULL) 316 { 317 n_rrs = -ENOMEM; 318 goto end; 319 } 320 memset(dane_tlsa, '\0', sizeof(*dane_tlsa)); 321 } 322 323 /* There are flags to store -- just set those, do nothing else. */ 324 if (TLSA_STORE_FL(flags)) 325 { 326 dane_tlsa->dane_tlsa_flags = flags; 327 ttl = mxttl > 0 ? mxttl: SM_DEFAULT_TTL; 328 goto done; 329 } 330 331 (void) sm_snprintf(nbuf, sizeof(nbuf), "_%u._tcp.%s", port, host); 332 dr = dns_lookup_int(nbuf, C_IN, T_TLSA, 0, 0, 333 TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX) ? 0 : SM_RES_DNSSEC, 334 RR_RAW, &err, &herr); 335 if (tTd(8, 2)) 336 sm_dprintf("gettlsa(%s), dr=%p, ad=%d, err=%d, herr=%d\n", host, 337 (void *)dr, dr != NULL ? dr->dns_r_h.ad : -1, err, herr); 338 ttl = UINT_MAX; 339 n_rrs = tlsaadd(key, dr, dane_tlsa, herr, n_rrs, &ttl, 0); 340 341 /* no valid entries found? */ 342 if (n_rrs == 0 && !TLSA_RR_TEMPFAIL(dane_tlsa)) 343 { 344 if (tTd(8, 2)) 345 sm_dprintf("gettlsa(%s), n_rrs=%d, herr=%d, status=NOT_ADDED\n", 346 host, n_rrs, dane_tlsa->dane_tlsa_dnsrc); 347 goto cleanup; 348 } 349 350 done: 351 dane_tlsa->dane_tlsa_n = n_rrs; 352 if (!isrname) 353 { 354 SM_FREE(dane_tlsa->dane_tlsa_sni); 355 dane_tlsa->dane_tlsa_sni = sm_strdup(host); 356 } 357 if (NULL == ste) 358 { 359 ste = stab(key, ST_TLSA_RR, ST_ENTER); 360 if (NULL == ste) 361 goto error; 362 } 363 ste->s_tlsa = dane_tlsa; 364 if (now == 0) 365 now = curtime(); 366 dane_tlsa->dane_tlsa_exp = now + SM_MIN(ttl, SM_DEFAULT_TTL); 367 dns_free_data(dr); 368 dr = NULL; 369 goto end; 370 371 error: 372 if (tTd(8, 2)) 373 sm_dprintf("gettlsa(%s, %s), status=error\n", host, key); 374 n_rrs = -1; 375 cleanup: 376 if (NULL == ste) 377 dane_tlsa_free(dane_tlsa); 378 dns_free_data(dr); 379 dr = NULL; 380 381 end: 382 if (pste != NULL && ste != NULL) 383 *pste = ste; 384 if (len > 0) 385 host[len] = '.'; 386 return n_rrs; 387 } 388 # endif /* DANE */ 389 390 /* 391 ** GETFALLBACKMXRR -- get MX resource records for fallback MX host. 392 ** 393 ** We have to initialize this once before doing anything else. 394 ** Moreover, we have to repeat this from time to time to avoid 395 ** stale data, e.g., in persistent queue runners. 396 ** This should be done in a parent process so the child 397 ** processes have the right data. 398 ** 399 ** Parameters: 400 ** host -- the name of the fallback MX host. 401 ** 402 ** Returns: 403 ** number of MX records. 404 ** 405 ** Side Effects: 406 ** Populates NumFallbackMXHosts and fbhosts. 407 ** Sets renewal time (based on TTL). 408 */ 409 410 int NumFallbackMXHosts = 0; /* Number of fallback MX hosts (after MX expansion) */ 411 static char *fbhosts[MAXMXHOSTS + 1]; 412 413 int 414 getfallbackmxrr(host) 415 char *host; 416 { 417 int i, rcode; 418 int ttl; 419 static time_t renew = 0; 420 421 #if 0 422 /* This is currently done before this function is called. */ 423 if (host == NULL || *host == '\0') 424 return 0; 425 #endif /* 0 */ 426 if (NumFallbackMXHosts > 0 && renew > curtime()) 427 return NumFallbackMXHosts; 428 429 /* for DANE we need to invoke getmxrr() to get the TLSA RRs. */ 430 #if !DANE 431 if (host[0] == '[') 432 { 433 fbhosts[0] = host; 434 NumFallbackMXHosts = 1; 435 } 436 else 437 #endif 438 { 439 /* free old data */ 440 for (i = 0; i < NumFallbackMXHosts; i++) 441 sm_free(fbhosts[i]); 442 443 /* 444 ** Get new data. 445 ** Note: passing 0 as port is not correct but we cannot 446 ** determine the port number as there is no mailer. 447 */ 448 449 NumFallbackMXHosts = getmxrr(host, fbhosts, NULL, 450 #if DANE 451 (DANE_SECURE == Dane) ? ISAD : 452 #endif 453 0, 454 &rcode, &ttl, 0); 455 renew = curtime() + ttl; 456 for (i = 0; i < NumFallbackMXHosts; i++) 457 fbhosts[i] = newstr(fbhosts[i]); 458 } 459 if (NumFallbackMXHosts == NULLMX) 460 NumFallbackMXHosts = 0; 461 return NumFallbackMXHosts; 462 } 463 464 /* 465 ** FALLBACKMXRR -- add MX resource records for fallback MX host to list. 466 ** 467 ** Parameters: 468 ** nmx -- current number of MX records. 469 ** prefs -- array of preferences. 470 ** mxhosts -- array of MX hosts (maximum size: MAXMXHOSTS) 471 ** 472 ** Returns: 473 ** new number of MX records. 474 ** 475 ** Side Effects: 476 ** If FallbackMX was set, it appends the MX records for 477 ** that host to mxhosts (and modifies prefs accordingly). 478 */ 479 480 static int 481 fallbackmxrr(nmx, prefs, mxhosts) 482 int nmx; 483 unsigned short *prefs; 484 char **mxhosts; 485 { 486 int i; 487 488 for (i = 0; i < NumFallbackMXHosts && nmx < MAXMXHOSTS; i++) 489 { 490 if (nmx > 0) 491 prefs[nmx] = prefs[nmx - 1] + 1; 492 else 493 prefs[nmx] = 0; 494 mxhosts[nmx++] = fbhosts[i]; 495 } 496 return nmx; 497 } 498 499 /* 500 ** GETMXRR -- get MX resource records for a domain 501 ** 502 ** Parameters: 503 ** host -- the name of the host to MX. 504 ** mxhosts -- a pointer to a return buffer of MX records. 505 ** mxprefs -- a pointer to a return buffer of MX preferences. 506 ** If NULL, don't try to populate. 507 ** flags -- flags: 508 ** DROPLOCALHOSt -- If true, all MX records less preferred 509 ** than the local host (as determined by $=w) will 510 ** be discarded. 511 ** TRYFALLBACK -- add also fallback MX host? 512 ** ISAD -- host lookup was secure? 513 ** rcode -- a pointer to an EX_ status code. 514 ** pttl -- pointer to return TTL (can be NULL). 515 ** 516 ** Returns: 517 ** The number of MX records found. 518 ** -1 if there is an internal failure. 519 ** If no MX records are found, mxhosts[0] is set to host 520 ** and 1 is returned. 521 ** 522 ** Side Effects: 523 ** The entries made for mxhosts point to a static array 524 ** MXHostBuf[MXHOSTBUFSIZE], so the data needs to be copied, 525 ** if it must be preserved across calls to this function. 526 */ 527 528 int 529 getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port) 530 char *host; 531 char **mxhosts; 532 unsigned short *mxprefs; 533 unsigned int flags; 534 int *rcode; 535 int *pttl; 536 int port; 537 { 538 register unsigned char *eom, *cp; 539 register int i, j, n; 540 int nmx = 0; 541 register char *bp; 542 HEADER *hp; 543 querybuf answer; 544 int ancount, qdcount, buflen; 545 bool seenlocal = false; 546 unsigned short pref, type; 547 unsigned short localpref = 256; 548 char *fallbackMX = FallbackMX; 549 bool trycanon = false; 550 unsigned short *prefs; 551 int (*resfunc) __P((const char *, int, int, u_char *, int)); 552 unsigned short prefer[MAXMXHOSTS]; 553 int weight[MAXMXHOSTS]; 554 int ttl = 0; 555 bool ad; 556 bool seennullmx = false; 557 extern int res_query(), res_search(); 558 # if DANE 559 bool cname2mx; 560 char qname[MAXNAME]; 561 unsigned long old_options = 0; 562 # endif 563 564 if (tTd(8, 2)) 565 sm_dprintf("getmxrr(%s, droplocalhost=%d, flags=%X, port=%d)\n", 566 host, (flags & DROPLOCALHOST) != 0, flags, port); 567 ad = (flags & ISAD) != 0; 568 *rcode = EX_OK; 569 if (pttl != NULL) 570 *pttl = SM_DEFAULT_TTL; 571 if (*host == '\0') 572 return 0; 573 # if DANE 574 cname2mx = false; 575 qname[0] = '\0'; 576 old_options = _res.options; 577 if (ad) 578 _res.options |= SM_RES_DNSSEC; 579 # endif 580 581 if ((fallbackMX != NULL && (flags & DROPLOCALHOST) != 0 && 582 wordinclass(fallbackMX, 'w')) || (flags & TRYFALLBACK) == 0) 583 { 584 /* don't use fallback for this pass */ 585 fallbackMX = NULL; 586 } 587 588 if (mxprefs != NULL) 589 prefs = mxprefs; 590 else 591 prefs = prefer; 592 593 /* efficiency hack -- numeric or non-MX lookups */ 594 if (host[0] == '[') 595 goto punt; 596 597 # if DANE 598 /* 599 ** NOTE: This only works if nocanonify is used, 600 ** otherwise the name is already rewritten. 601 */ 602 603 /* always or only when "needed"? */ 604 if (DANE_ALWAYS == Dane || (ad && DANE_SECURE == Dane)) 605 (void) sm_strlcpy(qname, host, sizeof(qname)); 606 # endif /* DANE */ 607 608 # if _FFR_EAI 609 if (!addr_is_ascii(host)) 610 { 611 char buf[1024]; 612 UErrorCode error = U_ZERO_ERROR; 613 UIDNAInfo info = UIDNA_INFO_INITIALIZER; 614 UIDNA *idna; 615 616 idna = uidna_openUTS46(UIDNA_NONTRANSITIONAL_TO_ASCII, &error); 617 (void) uidna_nameToASCII_UTF8(idna, host, strlen(host), 618 buf, sizeof(buf) - 1, 619 &info, &error); 620 uidna_close(idna); 621 host = sm_rpool_strdup_x(CurEnv->e_rpool, buf); 622 } 623 # endif /* _FFR_EAI */ 624 625 /* 626 ** If we don't have MX records in our host switch, don't 627 ** try for MX records. Note that this really isn't "right", 628 ** since we might be set up to try NIS first and then DNS; 629 ** if the host is found in NIS we really shouldn't be doing 630 ** MX lookups. However, that should be a degenerate case. 631 */ 632 633 if (!UseNameServer) 634 goto punt; 635 if (HasWildcardMX && ConfigLevel >= 6) 636 resfunc = res_query; 637 else 638 resfunc = res_search; 639 # if DNSSEC_TEST 640 if (tTd(8, 110)) 641 resfunc = tstdns_search; 642 # endif 643 644 errno = 0; 645 hp = (HEADER *)&answer; 646 n = (*resfunc)(host, C_IN, T_MX, (unsigned char *) &answer, 647 sizeof(answer)); 648 if (n < 0) 649 { 650 if (tTd(8, 1)) 651 # if DNSSEC_TEST 652 sm_dprintf("getmxrr: res_search(%s) failed (errno=%d (%s), h_errno=%d (%s))\n", 653 host, errno, strerror(errno), 654 h_errno, herrno2txt(h_errno)); 655 # else 656 sm_dprintf("getmxrr: res_search(%s) failed, h_errno=%d\n", 657 host, h_errno); 658 # endif 659 switch (h_errno) 660 { 661 case NO_DATA: 662 trycanon = true; 663 /* FALLTHROUGH */ 664 665 case NO_RECOVERY: 666 /* no MX data on this host */ 667 goto punt; 668 669 case HOST_NOT_FOUND: 670 # if BROKEN_RES_SEARCH 671 case 0: /* Ultrix resolver returns failure w/ h_errno=0 */ 672 # endif 673 /* host doesn't exist in DNS; might be in /etc/hosts */ 674 trycanon = true; 675 *rcode = EX_NOHOST; 676 goto punt; 677 678 case TRY_AGAIN: 679 case -1: 680 /* couldn't connect to the name server */ 681 if (fallbackMX != NULL) 682 { 683 /* name server is hosed -- push to fallback */ 684 nmx = fallbackmxrr(nmx, prefs, mxhosts); 685 goto done; 686 } 687 /* it might come up later; better queue it up */ 688 *rcode = EX_TEMPFAIL; 689 break; 690 691 default: 692 syserr("getmxrr: res_search (%s) failed with impossible h_errno (%d)", 693 host, h_errno); 694 *rcode = EX_OSERR; 695 break; 696 } 697 698 /* irreconcilable differences */ 699 goto error; 700 } 701 702 ad = ad && hp->ad; 703 if (tTd(8, 2)) 704 sm_dprintf("getmxrr(%s), hp=%p, ad=%d\n", host, (void*)hp, ad); 705 706 /* avoid problems after truncation in tcp packets */ 707 if (n > sizeof(answer)) 708 n = sizeof(answer); 709 710 /* find first satisfactory answer */ 711 cp = (unsigned char *)&answer + HFIXEDSZ; 712 eom = (unsigned char *)&answer + n; 713 714 for (qdcount = ntohs((unsigned short) hp->qdcount); 715 qdcount--; 716 cp += n + QFIXEDSZ) 717 { 718 if ((n = dn_skipname(cp, eom)) < 0) 719 goto punt; 720 } 721 722 /* NOTE: see definition of MXHostBuf! */ 723 buflen = sizeof(MXHostBuf) - 1; 724 SM_ASSERT(buflen > 0); 725 bp = MXHostBuf; 726 ancount = ntohs((unsigned short) hp->ancount); 727 728 /* See RFC 1035 for layout of RRs. */ 729 /* XXX leave room for FallbackMX ? */ 730 while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1) 731 { 732 if ((n = dn_expand((unsigned char *)&answer, eom, cp, 733 (RES_UNC_T) bp, buflen)) < 0) 734 break; 735 cp += n; 736 GETSHORT(type, cp); 737 cp += INT16SZ; /* skip over class */ 738 GETLONG(ttl, cp); 739 GETSHORT(n, cp); /* rdlength */ 740 # if DANE 741 if (type == T_CNAME) 742 cname2mx = true; 743 # endif 744 if (type != T_MX) 745 { 746 if ((tTd(8, 8) || _res.options & RES_DEBUG) 747 # if DANE 748 && type != T_RRSIG 749 # endif 750 ) 751 sm_dprintf("unexpected answer type %s, size %d\n", 752 dns_type_to_string(type), n); 753 cp += n; 754 continue; 755 } 756 GETSHORT(pref, cp); 757 if ((n = dn_expand((unsigned char *)&answer, eom, cp, 758 (RES_UNC_T) bp, buflen)) < 0) 759 break; 760 cp += n; 761 n = strlen(bp); 762 763 /* Support for RFC7505 "MX 0 ." */ 764 if (pref == 0 && *bp == '\0') 765 seennullmx = true; 766 767 if (wordinclass(bp, 'w')) 768 { 769 if (tTd(8, 3)) 770 sm_dprintf("found localhost (%s) in MX list, pref=%d\n", 771 bp, pref); 772 if ((flags & DROPLOCALHOST) != 0) 773 { 774 if (!seenlocal || pref < localpref) 775 localpref = pref; 776 seenlocal = true; 777 continue; 778 } 779 weight[nmx] = 0; 780 } 781 else 782 weight[nmx] = mxrand(bp); 783 prefs[nmx] = pref; 784 mxhosts[nmx++] = bp; 785 # if DANE 786 if (CHK_DANE(Dane) && port >= 0) 787 { 788 int nrr; 789 unsigned long flags; 790 791 flags = ad ? TLSAFLADMX : TLSAFLNOADMX; 792 nrr = gettlsa(bp, NULL, NULL, flags, ttl, port); 793 794 /* Only check qname if no TLSA RRs were found */ 795 if (0 == nrr && cname2mx && '\0' != qname[0] && 796 strcmp(qname, bp)) 797 gettlsa(qname, bp, NULL, flags, ttl, port); 798 /* XXX is this the right ad flag? */ 799 } 800 # endif 801 802 /* 803 ** Note: n can be 0 for something like: 804 ** host MX 0 . 805 ** See RFC 7505 806 */ 807 808 bp += n; 809 if (0 == n || bp[-1] != '.') 810 { 811 *bp++ = '.'; 812 n++; 813 } 814 *bp++ = '\0'; 815 if (buflen < n + 1) 816 { 817 /* don't want to wrap buflen */ 818 break; 819 } 820 buflen -= n + 1; 821 } 822 823 /* Support for RFC7505 "MX 0 ." */ 824 if (seennullmx && nmx == 1) 825 { 826 if (tTd(8, 4)) 827 sm_dprintf("getmxrr: Null MX record found, domain doesn't accept mail (RFC7505)\n"); 828 *rcode = EX_UNAVAILABLE; 829 return NULLMX; 830 } 831 832 /* return only one TTL entry, that should be sufficient */ 833 if (ttl > 0 && pttl != NULL) 834 *pttl = ttl; 835 836 /* sort the records */ 837 for (i = 0; i < nmx; i++) 838 { 839 for (j = i + 1; j < nmx; j++) 840 { 841 if (prefs[i] > prefs[j] || 842 (prefs[i] == prefs[j] && weight[i] > weight[j])) 843 { 844 register int temp; 845 register char *temp1; 846 847 temp = prefs[i]; 848 prefs[i] = prefs[j]; 849 prefs[j] = temp; 850 temp1 = mxhosts[i]; 851 mxhosts[i] = mxhosts[j]; 852 mxhosts[j] = temp1; 853 temp = weight[i]; 854 weight[i] = weight[j]; 855 weight[j] = temp; 856 } 857 } 858 if (seenlocal && prefs[i] >= localpref) 859 { 860 /* truncate higher preference part of list */ 861 nmx = i; 862 } 863 } 864 865 /* delete duplicates from list (yes, some bozos have duplicates) */ 866 for (i = 0; i < nmx - 1; ) 867 { 868 if (sm_strcasecmp(mxhosts[i], mxhosts[i + 1]) != 0) 869 i++; 870 else 871 { 872 /* compress out duplicate */ 873 for (j = i + 1; j < nmx; j++) 874 { 875 mxhosts[j] = mxhosts[j + 1]; 876 prefs[j] = prefs[j + 1]; 877 } 878 nmx--; 879 } 880 } 881 882 if (nmx == 0) 883 { 884 punt: 885 if (seenlocal) 886 { 887 struct hostent *h = NULL; 888 889 /* 890 ** If we have deleted all MX entries, this is 891 ** an error -- we should NEVER send to a host that 892 ** has an MX, and this should have been caught 893 ** earlier in the config file. 894 ** 895 ** Some sites prefer to go ahead and try the 896 ** A record anyway; that case is handled by 897 ** setting TryNullMXList. I believe this is a 898 ** bad idea, but it's up to you.... 899 */ 900 901 if (TryNullMXList) 902 { 903 SM_SET_H_ERRNO(0); 904 errno = 0; 905 h = sm_gethostbyname(host, AF_INET); 906 if (h == NULL) 907 { 908 if (errno == ETIMEDOUT || 909 h_errno == TRY_AGAIN || 910 (errno == ECONNREFUSED && 911 UseNameServer)) 912 { 913 *rcode = EX_TEMPFAIL; 914 goto error; 915 } 916 # if NETINET6 917 SM_SET_H_ERRNO(0); 918 errno = 0; 919 h = sm_gethostbyname(host, AF_INET6); 920 if (h == NULL && 921 (errno == ETIMEDOUT || 922 h_errno == TRY_AGAIN || 923 (errno == ECONNREFUSED && 924 UseNameServer))) 925 { 926 *rcode = EX_TEMPFAIL; 927 goto error; 928 } 929 # endif /* NETINET6 */ 930 } 931 } 932 933 if (h == NULL) 934 { 935 *rcode = EX_CONFIG; 936 syserr("MX list for %s points back to %s", 937 host, MyHostName); 938 goto error; 939 } 940 # if NETINET6 941 freehostent(h); 942 h = NULL; 943 # endif 944 } 945 if (strlen(host) >= sizeof(MXHostBuf)) 946 { 947 *rcode = EX_CONFIG; 948 syserr("Host name %s too long", 949 shortenstring(host, MAXSHORTSTR)); 950 goto error; 951 } 952 (void) sm_strlcpy(MXHostBuf, host, sizeof(MXHostBuf)); 953 mxhosts[0] = MXHostBuf; 954 prefs[0] = 0; 955 if (host[0] == '[') 956 { 957 register char *p; 958 # if NETINET6 959 struct sockaddr_in6 tmp6; 960 # endif 961 962 /* this may be an MX suppression-style address */ 963 p = strchr(MXHostBuf, ']'); 964 if (p != NULL) 965 { 966 *p = '\0'; 967 968 if (inet_addr(&MXHostBuf[1]) != INADDR_NONE) 969 { 970 nmx++; 971 *p = ']'; 972 } 973 # if NETINET6 974 else if (anynet_pton(AF_INET6, &MXHostBuf[1], 975 &tmp6.sin6_addr) == 1) 976 { 977 nmx++; 978 *p = ']'; 979 } 980 # endif /* NETINET6 */ 981 else 982 { 983 trycanon = true; 984 mxhosts[0]++; 985 } 986 } 987 } 988 if (trycanon && 989 (n = getcanonname(mxhosts[0], sizeof(MXHostBuf) - 2, false, 990 pttl)) != HOST_NOTFOUND) 991 { 992 /* XXX MXHostBuf == "" ? is that possible? */ 993 bp = &MXHostBuf[strlen(MXHostBuf)]; 994 if (bp[-1] != '.') 995 { 996 *bp++ = '.'; 997 *bp = '\0'; 998 } 999 nmx = 1; 1000 # if DANE 1001 if (tTd(8, 3)) 1002 sm_dprintf("getmxrr=%s, getcanonname=%d\n", 1003 mxhosts[0], n); 1004 if (CHK_DANE(Dane) && port >= 0) 1005 { 1006 int nrr; 1007 unsigned long flags; 1008 unsigned int cttl; 1009 1010 if (pttl != NULL) 1011 cttl = *pttl; 1012 else if (ttl > 0) 1013 cttl = ttl; 1014 else 1015 cttl = SM_DEFAULT_TTL; 1016 1017 flags = (ad && n == HOST_SECURE) 1018 ? TLSAFLADMX : TLSAFLNOADMX; 1019 nrr = gettlsa(mxhosts[0], NULL, NULL, flags, 1020 cttl, port); 1021 1022 /* 1023 ** Only check qname if no TLSA RRs were found 1024 ** XXX: what about (temp) DNS errors? 1025 */ 1026 1027 if (0 == nrr && '\0' != qname[0] && 1028 strcmp(qname, mxhosts[0])) 1029 gettlsa(qname, mxhosts[0], NULL, flags, 1030 cttl, port); 1031 /* XXX is this the right ad flag? */ 1032 } 1033 # endif 1034 } 1035 } 1036 1037 /* if we have a default lowest preference, include that */ 1038 if (fallbackMX != NULL && !seenlocal) 1039 { 1040 /* TODO: DNSsec status of fallbacks */ 1041 nmx = fallbackmxrr(nmx, prefs, mxhosts); 1042 } 1043 done: 1044 # if DANE 1045 _res.options = old_options; 1046 # endif 1047 return nmx; 1048 1049 error: 1050 # if DANE 1051 _res.options = old_options; 1052 # endif 1053 return -1; 1054 } 1055 1056 /* 1057 ** MXRAND -- create a randomizer for equal MX preferences 1058 ** 1059 ** If two MX hosts have equal preferences we want to randomize 1060 ** the selection. But in order for signatures to be the same, 1061 ** we need to randomize the same way each time. This function 1062 ** computes a pseudo-random hash function from the host name. 1063 ** 1064 ** Parameters: 1065 ** host -- the name of the host. 1066 ** 1067 ** Returns: 1068 ** A random but repeatable value based on the host name. 1069 */ 1070 1071 static int 1072 mxrand(host) 1073 register char *host; 1074 { 1075 int hfunc; 1076 static unsigned int seed; 1077 1078 if (seed == 0) 1079 { 1080 seed = (int) curtime() & 0xffff; 1081 if (seed == 0) 1082 seed++; 1083 } 1084 1085 if (tTd(17, 9)) 1086 sm_dprintf("mxrand(%s)", host); 1087 1088 hfunc = seed; 1089 while (*host != '\0') 1090 { 1091 int c = *host++; 1092 1093 if (isascii(c) && isupper(c)) 1094 c = tolower(c); 1095 hfunc = ((hfunc << 1) ^ c) % 2003; 1096 } 1097 1098 hfunc &= 0xff; 1099 hfunc++; 1100 1101 if (tTd(17, 9)) 1102 sm_dprintf(" = %d\n", hfunc); 1103 return hfunc; 1104 } 1105 /* 1106 ** BESTMX -- find the best MX for a name 1107 ** 1108 ** This is really a hack, but I don't see any obvious way 1109 ** to generalize it at the moment. 1110 */ 1111 1112 /* ARGSUSED3 */ 1113 char * 1114 bestmx_map_lookup(map, name, av, statp) 1115 MAP *map; 1116 char *name; 1117 char **av; 1118 int *statp; 1119 { 1120 int nmx; 1121 int saveopts = _res.options; 1122 int i; 1123 ssize_t len = 0; 1124 char *result; 1125 char *mxhosts[MAXMXHOSTS + 1]; 1126 # if _FFR_BESTMX_BETTER_TRUNCATION 1127 char *buf; 1128 # else 1129 char *p; 1130 char buf[PSBUFSIZE / 2]; 1131 # endif 1132 1133 _res.options &= ~(RES_DNSRCH|RES_DEFNAMES); 1134 nmx = getmxrr(name, mxhosts, NULL, 0, statp, NULL, -1); 1135 _res.options = saveopts; 1136 if (nmx <= 0) 1137 return NULL; 1138 if (bitset(MF_MATCHONLY, map->map_mflags)) 1139 return map_rewrite(map, name, strlen(name), NULL); 1140 if ((map->map_coldelim == '\0') || (nmx == 1)) 1141 return map_rewrite(map, mxhosts[0], strlen(mxhosts[0]), av); 1142 1143 /* 1144 ** We were given a -z flag (return all MXs) and there are multiple 1145 ** ones. We need to build them all into a list. 1146 */ 1147 1148 # if _FFR_BESTMX_BETTER_TRUNCATION 1149 for (i = 0; i < nmx; i++) 1150 { 1151 if (strchr(mxhosts[i], map->map_coldelim) != NULL) 1152 { 1153 syserr("bestmx_map_lookup: MX host %.64s includes map delimiter character 0x%02X", 1154 mxhosts[i], map->map_coldelim); 1155 return NULL; 1156 } 1157 len += strlen(mxhosts[i]) + 1; 1158 if (len < 0) 1159 { 1160 len -= strlen(mxhosts[i]) + 1; 1161 break; 1162 } 1163 } 1164 buf = (char *) sm_malloc(len); 1165 if (buf == NULL) 1166 { 1167 *statp = EX_UNAVAILABLE; 1168 return NULL; 1169 } 1170 *buf = '\0'; 1171 for (i = 0; i < nmx; i++) 1172 { 1173 int end; 1174 1175 end = sm_strlcat(buf, mxhosts[i], len); 1176 if (i != nmx && end + 1 < len) 1177 { 1178 buf[end] = map->map_coldelim; 1179 buf[end + 1] = '\0'; 1180 } 1181 } 1182 1183 /* Cleanly truncate for rulesets */ 1184 truncate_at_delim(buf, PSBUFSIZE / 2, map->map_coldelim); 1185 # else /* _FFR_BESTMX_BETTER_TRUNCATION */ 1186 p = buf; 1187 for (i = 0; i < nmx; i++) 1188 { 1189 size_t slen; 1190 1191 if (strchr(mxhosts[i], map->map_coldelim) != NULL) 1192 { 1193 syserr("bestmx_map_lookup: MX host %.64s includes map delimiter character 0x%02X", 1194 mxhosts[i], map->map_coldelim); 1195 return NULL; 1196 } 1197 slen = strlen(mxhosts[i]); 1198 if (len + slen + 2 > sizeof(buf)) 1199 break; 1200 if (i > 0) 1201 { 1202 *p++ = map->map_coldelim; 1203 len++; 1204 } 1205 (void) sm_strlcpy(p, mxhosts[i], sizeof(buf) - len); 1206 p += slen; 1207 len += slen; 1208 } 1209 # endif /* _FFR_BESTMX_BETTER_TRUNCATION */ 1210 1211 result = map_rewrite(map, buf, len, av); 1212 # if _FFR_BESTMX_BETTER_TRUNCATION 1213 sm_free(buf); 1214 # endif 1215 return result; 1216 } 1217 /* 1218 ** DNS_GETCANONNAME -- get the canonical name for named host using DNS 1219 ** 1220 ** This algorithm tries to be smart about wildcard MX records. 1221 ** This is hard to do because DNS doesn't tell is if we matched 1222 ** against a wildcard or a specific MX. 1223 ** 1224 ** We always prefer A & CNAME records, since these are presumed 1225 ** to be specific. 1226 ** 1227 ** If we match an MX in one pass and lose it in the next, we use 1228 ** the old one. For example, consider an MX matching *.FOO.BAR.COM. 1229 ** A hostname bletch.foo.bar.com will match against this MX, but 1230 ** will stop matching when we try bletch.bar.com -- so we know 1231 ** that bletch.foo.bar.com must have been right. This fails if 1232 ** there was also an MX record matching *.BAR.COM, but there are 1233 ** some things that just can't be fixed. 1234 ** 1235 ** Parameters: 1236 ** host -- a buffer containing the name of the host. 1237 ** This is a value-result parameter. 1238 ** hbsize -- the size of the host buffer. 1239 ** trymx -- if set, try MX records as well as A and CNAME. 1240 ** statp -- pointer to place to store status. 1241 ** pttl -- pointer to return TTL (can be NULL). 1242 ** 1243 ** Returns: 1244 ** >0 -- if the host was found. 1245 ** 0 -- otherwise. 1246 */ 1247 1248 int 1249 dns_getcanonname(host, hbsize, trymx, statp, pttl) 1250 char *host; 1251 int hbsize; 1252 bool trymx; 1253 int *statp; 1254 int *pttl; 1255 { 1256 register unsigned char *eom, *ap; 1257 register char *cp; 1258 register int n; 1259 HEADER *hp; 1260 querybuf answer; 1261 int ancount, qdcount, ret, type, qtype, initial, loopcnt, ttl, sli; 1262 char **domain; 1263 char *dp; 1264 char *mxmatch; 1265 bool amatch, gotmx, ad; 1266 char nbuf[SM_MAX(MAXPACKET, MAXDNAME*2+2)]; 1267 # if DNSSEC_TEST 1268 # define ADDSL 1 /* NameSearchList may add another entry to searchlist! */ 1269 # else 1270 # define ADDSL 0 1271 # endif 1272 char *searchlist[MAXDNSRCH + 2 + ADDSL]; 1273 # define SLSIZE SM_ARRAY_SIZE(searchlist) 1274 int (*resqdomain) __P((const char *, const char *, int, int, unsigned char *, int)); 1275 # if DANE 1276 unsigned long old_options = 0; 1277 # endif 1278 1279 ttl = 0; 1280 gotmx = false; 1281 ad = true; 1282 if (tTd(8, 2)) 1283 sm_dprintf("dns_getcanonname(%s, trymx=%d)\n", host, trymx); 1284 1285 if ((_res.options & RES_INIT) == 0 && res_init() == -1) 1286 { 1287 *statp = EX_UNAVAILABLE; 1288 return HOST_NOTFOUND; 1289 } 1290 1291 # if DANE 1292 old_options = _res.options; 1293 if (DANE_SECURE == Dane) 1294 _res.options |= SM_RES_DNSSEC; 1295 # endif 1296 1297 *statp = EX_OK; 1298 resqdomain = res_querydomain; 1299 # if DNSSEC_TEST 1300 if (tTd(8, 110)) 1301 resqdomain = tstdns_querydomain; 1302 # endif 1303 1304 /* 1305 ** Initialize domain search list. If there is at least one 1306 ** dot in the name, search the unmodified name first so we 1307 ** find "vse.CS" in Czechoslovakia instead of in the local 1308 ** domain (e.g., vse.CS.Berkeley.EDU). Note that there is no 1309 ** longer a country named Czechoslovakia but this type of problem 1310 ** is still present. 1311 ** 1312 ** Older versions of the resolver could create this 1313 ** list by tearing apart the host name. 1314 */ 1315 1316 loopcnt = 0; 1317 cnameloop: 1318 /* Check for dots in the name */ 1319 for (cp = host, n = 0; *cp != '\0'; cp++) 1320 if (*cp == '.') 1321 n++; 1322 1323 /* 1324 ** Build the search list. 1325 ** If there is at least one dot in name, start with a null 1326 ** domain to search the unmodified name first. 1327 ** If name does not end with a dot and search up local domain 1328 ** tree desired, append each local domain component to the 1329 ** search list; if name contains no dots and default domain 1330 ** name is desired, append default domain name to search list; 1331 ** else if name ends in a dot, remove that dot. 1332 */ 1333 1334 sli = 0; 1335 if (n > 0) 1336 searchlist[sli++] = ""; 1337 # if DNSSEC_TEST 1338 if (NameSearchList != NULL) 1339 { 1340 SM_ASSERT(sli < SLSIZE); 1341 searchlist[sli++] = NameSearchList; 1342 } 1343 # endif 1344 if (n >= 0 && *--cp != '.' && bitset(RES_DNSRCH, _res.options)) 1345 { 1346 /* make sure there are less than MAXDNSRCH domains */ 1347 for (domain = RES_DNSRCH_VARIABLE, ret = 0; 1348 *domain != NULL && ret < MAXDNSRCH && sli < SLSIZE; 1349 ret++) 1350 searchlist[sli++] = *domain++; 1351 } 1352 else if (n == 0 && bitset(RES_DEFNAMES, _res.options)) 1353 { 1354 SM_ASSERT(sli < SLSIZE); 1355 searchlist[sli++] = _res.defdname; 1356 } 1357 else if (*cp == '.') 1358 { 1359 *cp = '\0'; 1360 } 1361 SM_ASSERT(sli < SLSIZE); 1362 searchlist[sli] = NULL; 1363 1364 /* 1365 ** Now loop through the search list, appending each domain in turn 1366 ** name and searching for a match. 1367 */ 1368 1369 mxmatch = NULL; 1370 initial = T_A; 1371 # if NETINET6 1372 if (InetMode == AF_INET6) 1373 initial = T_AAAA; 1374 # endif 1375 qtype = initial; 1376 1377 for (sli = 0; sli < SLSIZE; ) 1378 { 1379 dp = searchlist[sli]; 1380 if (NULL == dp) 1381 break; 1382 if (qtype == initial) 1383 gotmx = false; 1384 if (tTd(8, 5)) 1385 sm_dprintf("dns_getcanonname: trying %s.%s (%s)\n", 1386 host, dp, 1387 # if NETINET6 1388 qtype == T_AAAA ? "AAAA" : 1389 # endif 1390 qtype == T_A ? "A" : 1391 qtype == T_MX ? "MX" : 1392 "???"); 1393 errno = 0; 1394 hp = (HEADER *) &answer; 1395 ret = (*resqdomain)(host, dp, C_IN, qtype, 1396 answer.qb2, sizeof(answer.qb2)); 1397 if (ret <= 0) 1398 { 1399 int save_errno = errno; 1400 1401 if (tTd(8, 7)) 1402 sm_dprintf("\tNO: errno=%d, h_errno=%d\n", 1403 save_errno, h_errno); 1404 1405 if (save_errno == ECONNREFUSED || h_errno == TRY_AGAIN) 1406 { 1407 /* 1408 ** the name server seems to be down or broken. 1409 */ 1410 1411 SM_SET_H_ERRNO(TRY_AGAIN); 1412 if (*dp == '\0') 1413 { 1414 if (*statp == EX_OK) 1415 *statp = EX_TEMPFAIL; 1416 goto nexttype; 1417 } 1418 *statp = EX_TEMPFAIL; 1419 1420 if (WorkAroundBrokenAAAA) 1421 { 1422 /* 1423 ** Only return if not TRY_AGAIN as an 1424 ** attempt with a different qtype may 1425 ** succeed (res_querydomain() calls 1426 ** res_query() calls res_send() which 1427 ** sets errno to ETIMEDOUT if the 1428 ** nameservers could be contacted but 1429 ** didn't give an answer). 1430 */ 1431 1432 if (save_errno != ETIMEDOUT) 1433 goto error; 1434 } 1435 else 1436 goto error; 1437 } 1438 1439 nexttype: 1440 if (h_errno != HOST_NOT_FOUND) 1441 { 1442 /* might have another type of interest */ 1443 # if NETINET6 1444 if (qtype == T_AAAA) 1445 { 1446 qtype = T_A; 1447 continue; 1448 } 1449 else 1450 # endif /* NETINET6 */ 1451 if (qtype == T_A && !gotmx && 1452 (trymx || *dp == '\0')) 1453 { 1454 qtype = T_MX; 1455 continue; 1456 } 1457 } 1458 1459 /* definite no -- try the next domain */ 1460 sli++; 1461 qtype = initial; 1462 continue; 1463 } 1464 else if (tTd(8, 7)) 1465 sm_dprintf("\tYES\n"); 1466 1467 /* avoid problems after truncation in tcp packets */ 1468 if (ret > sizeof(answer)) 1469 ret = sizeof(answer); 1470 SM_ASSERT(ret >= 0); 1471 1472 /* 1473 ** Appear to have a match. Confirm it by searching for A or 1474 ** CNAME records. If we don't have a local domain 1475 ** wild card MX record, we will accept MX as well. 1476 */ 1477 1478 ap = (unsigned char *) &answer + HFIXEDSZ; 1479 eom = (unsigned char *) &answer + ret; 1480 1481 if (0 == hp->ad) 1482 ad = false; 1483 1484 /* skip question part of response -- we know what we asked */ 1485 for (qdcount = ntohs((unsigned short) hp->qdcount); 1486 qdcount--; 1487 ap += ret + QFIXEDSZ) 1488 { 1489 if ((ret = dn_skipname(ap, eom)) < 0) 1490 { 1491 if (tTd(8, 20)) 1492 sm_dprintf("qdcount failure (%d)\n", 1493 ntohs((unsigned short) hp->qdcount)); 1494 *statp = EX_SOFTWARE; 1495 goto error; 1496 } 1497 } 1498 1499 amatch = false; 1500 for (ancount = ntohs((unsigned short) hp->ancount); 1501 --ancount >= 0 && ap < eom; 1502 ap += n) 1503 { 1504 n = dn_expand((unsigned char *) &answer, eom, ap, 1505 (RES_UNC_T) nbuf, sizeof(nbuf)); 1506 if (n < 0) 1507 break; 1508 ap += n; 1509 GETSHORT(type, ap); 1510 ap += INT16SZ; /* skip over class */ 1511 GETLONG(ttl, ap); 1512 GETSHORT(n, ap); /* rdlength */ 1513 switch (type) 1514 { 1515 case T_MX: 1516 gotmx = true; 1517 if (*dp != '\0' && HasWildcardMX) 1518 { 1519 /* 1520 ** If we are using MX matches and have 1521 ** not yet gotten one, save this one 1522 ** but keep searching for an A or 1523 ** CNAME match. 1524 */ 1525 1526 if (trymx && mxmatch == NULL) 1527 mxmatch = dp; 1528 continue; 1529 } 1530 1531 /* 1532 ** If we did not append a domain name, this 1533 ** must have been a canonical name to start 1534 ** with. Even if we did append a domain name, 1535 ** in the absence of a wildcard MX this must 1536 ** still be a real MX match. 1537 ** Such MX matches are as good as an A match, 1538 ** fall through. 1539 */ 1540 /* FALLTHROUGH */ 1541 1542 # if NETINET6 1543 case T_AAAA: 1544 # endif 1545 case T_A: 1546 /* Flag that a good match was found */ 1547 amatch = true; 1548 1549 /* continue in case a CNAME also exists */ 1550 continue; 1551 1552 case T_CNAME: 1553 if (DontExpandCnames) 1554 { 1555 /* got CNAME -- guaranteed canonical */ 1556 amatch = true; 1557 break; 1558 } 1559 1560 if (loopcnt++ > MAXCNAMEDEPTH) 1561 { 1562 /*XXX should notify postmaster XXX*/ 1563 message("DNS failure: CNAME loop for %s", 1564 host); 1565 if (CurEnv->e_message == NULL) 1566 { 1567 char ebuf[MAXLINE]; 1568 1569 (void) sm_snprintf(ebuf, 1570 sizeof(ebuf), 1571 "Deferred: DNS failure: CNAME loop for %.100s", 1572 host); 1573 CurEnv->e_message = 1574 sm_rpool_strdup_x( 1575 CurEnv->e_rpool, ebuf); 1576 } 1577 SM_SET_H_ERRNO(NO_RECOVERY); 1578 *statp = EX_CONFIG; 1579 goto error; 1580 } 1581 1582 /* value points at name */ 1583 if ((ret = dn_expand((unsigned char *)&answer, 1584 eom, ap, (RES_UNC_T) nbuf, 1585 sizeof(nbuf))) < 0) 1586 break; 1587 (void) sm_strlcpy(host, nbuf, hbsize); 1588 1589 /* 1590 ** RFC 1034 section 3.6 specifies that CNAME 1591 ** should point at the canonical name -- but 1592 ** urges software to try again anyway. 1593 */ 1594 1595 goto cnameloop; 1596 1597 default: 1598 /* not a record of interest */ 1599 continue; 1600 } 1601 } 1602 1603 if (amatch) 1604 { 1605 /* 1606 ** Got a good match -- either an A, CNAME, or an 1607 ** exact MX record. Save it and get out of here. 1608 */ 1609 1610 mxmatch = dp; 1611 break; 1612 } 1613 1614 /* 1615 ** Nothing definitive yet. 1616 ** If this was a T_A query and we haven't yet found a MX 1617 ** match, try T_MX if allowed to do so. 1618 ** Otherwise, try the next domain. 1619 */ 1620 1621 # if NETINET6 1622 if (qtype == T_AAAA) 1623 qtype = T_A; 1624 else 1625 # endif 1626 if (qtype == T_A && !gotmx && (trymx || *dp == '\0')) 1627 qtype = T_MX; 1628 else 1629 { 1630 qtype = initial; 1631 sli++; 1632 } 1633 } 1634 1635 /* if nothing was found, we are done */ 1636 if (mxmatch == NULL) 1637 { 1638 if (*statp == EX_OK) 1639 *statp = EX_NOHOST; 1640 goto error; 1641 } 1642 1643 /* 1644 ** Create canonical name and return. 1645 ** If saved domain name is null, name was already canonical. 1646 ** Otherwise append the saved domain name. 1647 */ 1648 1649 (void) sm_snprintf(nbuf, sizeof(nbuf), "%.*s%s%.*s", MAXDNAME, host, 1650 *mxmatch == '\0' ? "" : ".", 1651 MAXDNAME, mxmatch); 1652 (void) sm_strlcpy(host, nbuf, hbsize); 1653 if (tTd(8, 5)) 1654 sm_dprintf("dns_getcanonname: %s\n", host); 1655 *statp = EX_OK; 1656 1657 /* return only one TTL entry, that should be sufficient */ 1658 if (ttl > 0 && pttl != NULL) 1659 *pttl = ttl; 1660 # if DANE 1661 _res.options = old_options; 1662 # endif 1663 return ad ? HOST_SECURE : HOST_OK; 1664 1665 error: 1666 # if DANE 1667 _res.options = old_options; 1668 # endif 1669 return HOST_NOTFOUND; 1670 } 1671 1672 #endif /* NAMED_BIND */ 1673