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
tlsa_rr_print(rr,len)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
tlsa_rr_cmp(rr1,l1,rr2,l2)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
tlsainsert(dane_tlsa,rr,pn)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
tlsaadd(name,dr,dane_tlsa,dnsrc,nr,pttl,level)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
gettlsa(host,name,pste,flags,mxttl,port)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
getfallbackmxrr(host)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
fallbackmxrr(nmx,prefs,mxhosts)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 *
hn2alabel(hostname)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
getmxrr(host,mxhosts,mxprefs,flags,rcode,pttl,port,pad)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
mxrand(host)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 *
bestmx_map_lookup(map,name,av,statp)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
dns_getcanonname(host,hbsize,trymx,statp,pttl)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