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