xref: /freebsd/contrib/sendmail/src/domain.c (revision d39bd2c1388b520fcba9abed1932acacead60fba)
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