1 /*
2 * Copyright (c) 2000-2004, 2010, 2015, 2020 Proofpoint, Inc. and its suppliers.
3 * All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11 /*
12 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H�gskolan
13 * (Royal Institute of Technology, Stockholm, Sweden).
14 * All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 *
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 *
23 * 2. Redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution.
26 *
27 * 3. Neither the name of the Institute nor the names of its contributors
28 * may be used to endorse or promote products derived from this software
29 * without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * SUCH DAMAGE.
42 */
43
44 #include <sendmail.h>
45 #include <sm/sendmail.h>
46
47 #if NAMED_BIND
48 # if NETINET
49 # include <netinet/in_systm.h>
50 # include <netinet/ip.h>
51 # endif
52 # if DNSSEC_TEST || _FFR_NAMESERVER
53 # define _DEFINE_SMR_GLOBALS 1
54 # endif
55 # include "sm_resolve.h"
56 # if DNSMAP || DANE
57
58 #include <arpa/inet.h>
59
60 SM_RCSID("$Id: sm_resolve.c,v 8.40 2013-11-22 20:51:56 ca Exp $")
61
62 static struct stot
63 {
64 const char *st_name;
65 int st_type;
66 } stot[] =
67 {
68 # if NETINET
69 { "A", T_A },
70 # endif
71 # if NETINET6
72 { "AAAA", T_AAAA },
73 # endif
74 { "NS", T_NS },
75 { "CNAME", T_CNAME },
76 { "PTR", T_PTR },
77 { "MX", T_MX },
78 { "TXT", T_TXT },
79 { "AFSDB", T_AFSDB },
80 { "SRV", T_SRV },
81 # ifdef T_DS
82 { "DS", T_DS },
83 # endif
84 { "RRSIG", T_RRSIG },
85 # ifdef T_NSEC
86 { "NSEC", T_NSEC },
87 # endif
88 # ifdef T_DNSKEY
89 { "DNSKEY", T_DNSKEY },
90 # endif
91 { "TLSA", T_TLSA },
92 { NULL, 0 }
93 };
94
95 static DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int, unsigned int));
96 # if DNSSEC_TEST && defined(T_TLSA)
97 static char *hex2bin __P((const char *, int));
98 # endif
99
100 /*
101 ** DNS_STRING_TO_TYPE -- convert resource record name into type
102 **
103 ** Parameters:
104 ** name -- name of resource record type
105 **
106 ** Returns:
107 ** type if succeeded.
108 ** -1 otherwise.
109 */
110
111 int
dns_string_to_type(name)112 dns_string_to_type(name)
113 const char *name;
114 {
115 struct stot *p = stot;
116
117 for (p = stot; p->st_name != NULL; p++)
118 if (SM_STRCASEEQ(name, p->st_name))
119 return p->st_type;
120 return -1;
121 }
122
123 /*
124 ** DNS_TYPE_TO_STRING -- convert resource record type into name
125 **
126 ** Parameters:
127 ** type -- resource record type
128 **
129 ** Returns:
130 ** name if succeeded.
131 ** NULL otherwise.
132 */
133
134 const char *
dns_type_to_string(type)135 dns_type_to_string(type)
136 int type;
137 {
138 struct stot *p = stot;
139
140 for (p = stot; p->st_name != NULL; p++)
141 if (type == p->st_type)
142 return p->st_name;
143 return NULL;
144 }
145
146 /*
147 ** DNS_FREE_DATA -- free all components of a DNS_REPLY_T
148 **
149 ** Parameters:
150 ** dr -- pointer to DNS_REPLY_T
151 **
152 ** Returns:
153 ** none.
154 */
155
156 void
dns_free_data(dr)157 dns_free_data(dr)
158 DNS_REPLY_T *dr;
159 {
160 RESOURCE_RECORD_T *rr;
161
162 if (dr == NULL)
163 return;
164 if (dr->dns_r_q.dns_q_domain != NULL)
165 sm_free(dr->dns_r_q.dns_q_domain);
166 for (rr = dr->dns_r_head; rr != NULL; )
167 {
168 RESOURCE_RECORD_T *tmp = rr;
169
170 if (rr->rr_domain != NULL)
171 sm_free(rr->rr_domain);
172 if (rr->rr_u.rr_data != NULL)
173 sm_free(rr->rr_u.rr_data);
174 rr = rr->rr_next;
175 sm_free(tmp);
176 }
177 sm_free(dr);
178 }
179
180 /*
181 ** BIN2HEX -- convert binary TLSA RR to hex string
182 **
183 ** Parameters:
184 ** tlsa -- pointer to result (allocated here)
185 ** p -- binary data (TLSA RR)
186 ** size -- length of p
187 ** min_size -- minimum expected size
188 **
189 ** Returns:
190 ** >0: length of string (*tlsa)
191 ** -1: error
192 */
193
194 static int bin2hex __P((char **, unsigned char *, int, int));
195
196 static int
bin2hex(tlsa,p,size,min_size)197 bin2hex(tlsa, p, size, min_size)
198 char **tlsa;
199 unsigned char *p;
200 int size;
201 int min_size;
202 {
203 int i, pos, txtlen;
204
205 txtlen = size * 3;
206 if (txtlen <= size || size < min_size)
207 {
208 if (LogLevel > 5)
209 sm_syslog(LOG_WARNING, NOQID,
210 "ERROR: bin2hex: size %d wrong", size);
211 return -1;
212 }
213 *tlsa = (char *) sm_malloc(txtlen);
214 if (*tlsa == NULL)
215 {
216 if (tTd(8, 17))
217 sm_dprintf("len=%d, rr_data=NULL\n", txtlen);
218 return -1;
219 }
220 snprintf(*tlsa, txtlen,
221 "%02X %02X %02X", p[0], p[1], p[2]);
222 pos = strlen(*tlsa);
223
224 /* why isn't there a print function like strlcat? */
225 for (i = 3; i < size && pos < txtlen; i++, pos += 3)
226 snprintf(*tlsa + pos, txtlen - pos, "%c%02X",
227 (i == 3) ? ' ' : ':', p[i]);
228
229 return i;
230 }
231
232 /*
233 ** PARSE_DNS_REPLY -- parse DNS reply data.
234 **
235 ** Parameters:
236 ** data -- pointer to dns data
237 ** len -- len of data
238 ** flags -- flags (RR_*)
239 **
240 ** Returns:
241 ** pointer to DNS_REPLY_T if succeeded.
242 ** NULL otherwise.
243 **
244 ** Note:
245 ** use dns_free_data() to free() the result when no longer needed.
246 */
247
248 static DNS_REPLY_T *
parse_dns_reply(data,len,flags)249 parse_dns_reply(data, len, flags)
250 unsigned char *data;
251 int len;
252 unsigned int flags;
253 {
254 unsigned char *p;
255 unsigned short ans_cnt, ui;
256 int status;
257 size_t l;
258 char host[MAXHOSTNAMELEN];
259 DNS_REPLY_T *dr;
260 RESOURCE_RECORD_T **rr;
261
262 if (tTd(8, 90))
263 {
264 FILE *fp;
265
266 fp = fopen("dns.buffer", "w");
267 if (fp != NULL)
268 {
269 fwrite(data, 1, len, fp);
270 fclose(fp);
271 fp = NULL;
272 }
273 else
274 sm_dprintf("parse_dns_reply: fp=%p, e=%d\n",
275 (void *)fp, errno);
276 }
277
278 dr = (DNS_REPLY_T *) sm_malloc(sizeof(*dr));
279 if (dr == NULL)
280 return NULL;
281 memset(dr, 0, sizeof(*dr));
282
283 p = data;
284
285 /* doesn't work on Crays? */
286 memcpy(&dr->dns_r_h, p, sizeof(dr->dns_r_h));
287 p += sizeof(dr->dns_r_h);
288 status = dn_expand(data, data + len, p, host, sizeof(host));
289 if (status < 0)
290 goto error;
291 dr->dns_r_q.dns_q_domain = sm_strdup(host);
292 if (dr->dns_r_q.dns_q_domain == NULL)
293 goto error;
294
295 ans_cnt = ntohs((unsigned short) dr->dns_r_h.ancount);
296 if (tTd(8, 17))
297 sm_dprintf("parse_dns_reply: ac=%d, ad=%d\n", ans_cnt,
298 dr->dns_r_h.ad);
299
300 p += status;
301 GETSHORT(dr->dns_r_q.dns_q_type, p);
302 GETSHORT(dr->dns_r_q.dns_q_class, p);
303 rr = &dr->dns_r_head;
304 ui = 0;
305 while (p < data + len && ui < ans_cnt)
306 {
307 int type, class, ttl, size, txtlen;
308
309 status = dn_expand(data, data + len, p, host, sizeof(host));
310 if (status < 0)
311 goto error;
312 ++ui;
313 p += status;
314 GETSHORT(type, p);
315 GETSHORT(class, p);
316 GETLONG(ttl, p);
317 GETSHORT(size, p);
318 if (p + size > data + len)
319 {
320 /*
321 ** announced size of data exceeds length of
322 ** data paket: someone is cheating.
323 */
324
325 if (LogLevel > 5)
326 sm_syslog(LOG_WARNING, NOQID,
327 "ERROR: DNS RDLENGTH=%d > data len=%d",
328 size, len - (int)(p - data));
329 goto error;
330 }
331 *rr = (RESOURCE_RECORD_T *) sm_malloc(sizeof(**rr));
332 if (*rr == NULL)
333 goto error;
334 memset(*rr, 0, sizeof(**rr));
335 (*rr)->rr_domain = sm_strdup(host);
336 if ((*rr)->rr_domain == NULL)
337 goto error;
338 (*rr)->rr_type = type;
339 (*rr)->rr_class = class;
340 (*rr)->rr_ttl = ttl;
341 (*rr)->rr_size = size;
342 switch (type)
343 {
344 case T_NS:
345 case T_CNAME:
346 case T_PTR:
347 status = dn_expand(data, data + len, p, host,
348 sizeof(host));
349 if (status < 0)
350 goto error;
351 if (tTd(8, 50))
352 sm_dprintf("parse_dns_reply: type=%s, host=%s\n",
353 dns_type_to_string(type), host);
354 (*rr)->rr_u.rr_txt = sm_strdup(host);
355 if ((*rr)->rr_u.rr_txt == NULL)
356 goto error;
357 break;
358
359 case T_MX:
360 case T_AFSDB:
361 status = dn_expand(data, data + len, p + 2, host,
362 sizeof(host));
363 if (status < 0)
364 goto error;
365 l = strlen(host) + 1;
366 (*rr)->rr_u.rr_mx = (MX_RECORD_T *)
367 sm_malloc(sizeof(*((*rr)->rr_u.rr_mx)) + l);
368 if ((*rr)->rr_u.rr_mx == NULL)
369 goto error;
370 (*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1];
371 (void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain,
372 host, l);
373 if (tTd(8, 50))
374 sm_dprintf("mx=%s, pref=%d\n", host,
375 (*rr)->rr_u.rr_mx->mx_r_preference);
376 break;
377
378 case T_SRV:
379 status = dn_expand(data, data + len, p + 6, host,
380 sizeof(host));
381 if (status < 0)
382 goto error;
383 l = strlen(host) + 1;
384 (*rr)->rr_u.rr_srv = (SRV_RECORDT_T*)
385 sm_malloc(sizeof(*((*rr)->rr_u.rr_srv)) + l);
386 if ((*rr)->rr_u.rr_srv == NULL)
387 goto error;
388 (*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1];
389 (*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3];
390 (*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5];
391 (void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target,
392 host, l);
393 break;
394
395 case T_TXT:
396
397 /*
398 ** The TXT record contains the length as
399 ** leading byte, hence the value is restricted
400 ** to 255, which is less than the maximum value
401 ** of RDLENGTH (size). Nevertheless, txtlen
402 ** must be less than size because the latter
403 ** specifies the length of the entire TXT
404 ** record.
405 */
406
407 txtlen = *p;
408 if (txtlen >= size)
409 {
410 if (LogLevel > 5)
411 sm_syslog(LOG_WARNING, NOQID,
412 "ERROR: DNS TXT record size=%d <= text len=%d",
413 size, txtlen);
414 goto error;
415 }
416 (*rr)->rr_u.rr_txt = (char *) sm_malloc(txtlen + 1);
417 if ((*rr)->rr_u.rr_txt == NULL)
418 goto error;
419 (void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1,
420 txtlen + 1);
421 break;
422
423 # ifdef T_TLSA
424 case T_TLSA:
425 if (tTd(8, 61))
426 sm_dprintf("parse_dns_reply: TLSA, size=%d, flags=%X\n",
427 size, flags);
428 if ((flags & RR_AS_TEXT) != 0)
429 {
430 txtlen = bin2hex((char **)&((*rr)->rr_u.rr_data),
431 p, size, 4);
432 if (txtlen <= 0)
433 goto error;
434 break;
435 }
436 /* FALLTHROUGH */
437 /* return "raw" data for caller to use as it pleases */
438 # endif /* T_TLSA */
439
440 default:
441 (*rr)->rr_u.rr_data = (unsigned char*) sm_malloc(size);
442 if ((*rr)->rr_u.rr_data == NULL)
443 goto error;
444 (void) memcpy((*rr)->rr_u.rr_data, p, size);
445 if (tTd(8, 61) && type == T_A)
446 {
447 SOCKADDR addr;
448
449 (void) memcpy((void *)&addr.sin.sin_addr.s_addr, p, size);
450 sm_dprintf("parse_dns_reply: IPv4=%s\n",
451 inet_ntoa(addr.sin.sin_addr));
452 }
453 break;
454 }
455 p += size;
456 rr = &(*rr)->rr_next;
457 }
458 *rr = NULL;
459 return dr;
460
461 error:
462 dns_free_data(dr);
463 return NULL;
464 }
465
466 # if DNSSEC_TEST
467
468 # include <arpa/nameser.h>
469 # if _FFR_8BITENVADDR
470 # include <sm/sendmail.h>
471 # endif
472
473 static int gen_dns_reply __P((unsigned char *, int, unsigned char *,
474 const char *, int, const char *, int, int, int, int,
475 const char *, int, int, int));
476 static int dnscrtrr __P((const char *, const char *, int, char *, int,
477 unsigned int, int *, int *, unsigned char *, int, unsigned char *));
478
479 /*
480 ** HERRNO2TXT -- return error text for h_errno
481 **
482 ** Parameters:
483 ** e -- h_errno
484 **
485 ** Returns:
486 ** DNS error text if available
487 */
488
489 const char *
herrno2txt(e)490 herrno2txt(e)
491 int e;
492 {
493 switch (e)
494 {
495 case NETDB_INTERNAL:
496 return "see errno";
497 case NETDB_SUCCESS:
498 return "OK";
499 case HOST_NOT_FOUND:
500 return "HOST_NOT_FOUND";
501 case TRY_AGAIN:
502 return "TRY_AGAIN";
503 case NO_RECOVERY:
504 return "NO_RECOVERY";
505 case NO_DATA:
506 return "NO_DATA";
507 }
508 return "bogus h_errno";
509 }
510
511 /*
512 ** GEN_DNS_REPLY -- generate DNS reply data.
513 **
514 ** Parameters:
515 ** buf -- buffer to which DNS data is written
516 ** buflen -- length of buffer
517 ** bufpos -- position in buffer where DNS RRs are appended
518 ** query -- name of query
519 ** qtype -- resource record type of query
520 ** domain -- name of domain which has been "found"
521 ** class -- resource record class
522 ** type -- resource record type
523 ** ttl -- TTL
524 ** size -- size of data
525 ** data -- data
526 ** txtlen -- length of text
527 ** pref -- MX preference
528 ** ad -- ad flag
529 **
530 ** Returns:
531 ** >0 length of buffer that has been used.
532 ** <0 error
533 */
534
535 static int
gen_dns_reply(buf,buflen,bufpos,query,qtype,domain,class,type,ttl,size,data,txtlen,pref,ad)536 gen_dns_reply(buf, buflen, bufpos, query, qtype, domain, class, type, ttl, size, data, txtlen, pref, ad)
537 unsigned char *buf;
538 int buflen;
539 unsigned char *bufpos;
540 const char *query;
541 int qtype;
542 const char *domain;
543 int class;
544 int type;
545 int ttl;
546 int size;
547 const char *data;
548 int txtlen;
549 int pref;
550 int ad;
551 {
552 unsigned short ans_cnt;
553 HEADER *hp;
554 unsigned char *cp, *ep;
555 int n;
556 static unsigned char *dnptrs[20], **dpp, **lastdnptr;
557
558 #define DN_COMP_CHK do \
559 { \
560 if (n < 0) \
561 { \
562 if (tTd(8, 91)) \
563 sm_dprintf("gen_dns_reply: dn_comp=%d\n", n); \
564 return n; \
565 } \
566 } while (0)
567
568 SM_REQUIRE(NULL != buf);
569 SM_REQUIRE(buflen >= HFIXEDSZ);
570 SM_REQUIRE(query != NULL);
571 hp = (HEADER *) buf;
572 ep = buf + buflen;
573 cp = buf + HFIXEDSZ;
574
575 if (bufpos != NULL)
576 cp = bufpos;
577 else
578 {
579 sm_dprintf("gen_dns_reply: query=%s, domain=%s, type=%s, size=%d, ad=%d\n",
580 query, domain, dns_type_to_string(type), size, ad);
581 dpp = dnptrs;
582 *dpp++ = buf;
583 *dpp++ = NULL;
584 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
585
586 memset(buf, 0, HFIXEDSZ);
587 hp->id = 0xdead; /* HACK */
588 hp->qr = 1;
589 hp->opcode = QUERY;
590 hp->rd = 0; /* recursion desired? */
591 hp->rcode = 0; /* !!! */
592 /* hp->aa = ?; * !!! */
593 /* hp->tc = ?; * !!! */
594 /* hp->ra = ?; * !!! */
595 hp->qdcount = htons(1);
596 hp->ancount = 0;
597
598 n = dn_comp(query, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
599 DN_COMP_CHK;
600 cp += n;
601 PUTSHORT(qtype, cp);
602 PUTSHORT(class, cp);
603 }
604 hp->ad = ad;
605
606 if (ep - cp < QFIXEDSZ)
607 {
608 if (tTd(8, 91))
609 sm_dprintf("gen_dns_reply: ep-cp=%ld\n",
610 (long) (ep - cp));
611 return (-1);
612 }
613 n = dn_comp(domain, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
614 DN_COMP_CHK;
615 cp += n;
616 PUTSHORT(type, cp);
617 PUTSHORT(class, cp);
618 PUTLONG(ttl, cp);
619
620 ans_cnt = ntohs((unsigned short) hp->ancount);
621 ++ans_cnt;
622 hp->ancount = htons((unsigned short) ans_cnt);
623
624 switch (type)
625 {
626 case T_MX:
627 n = dn_comp(data, cp + 4, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
628 DN_COMP_CHK;
629 PUTSHORT(n + 2, cp);
630 PUTSHORT(pref, cp);
631 cp += n;
632 break;
633
634 case T_TXT:
635 if (txtlen >= size)
636 return -1;
637 PUTSHORT(txtlen, cp);
638 (void) sm_strlcpy((char *)cp, data, txtlen + 1);
639 cp += txtlen;
640 break;
641
642 case T_CNAME:
643 n = dn_comp(data, cp + 2, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
644 DN_COMP_CHK;
645 PUTSHORT(n, cp);
646 cp += n;
647 break;
648
649 # if defined(T_TLSA)
650 case T_TLSA:
651 {
652 char *tlsa;
653
654 tlsa = hex2bin(data, size);
655 if (tlsa == NULL)
656 return (-1);
657 n = size / 2;
658 PUTSHORT(n, cp);
659 (void) memcpy(cp, tlsa, n);
660 cp += n;
661 }
662 break;
663 # endif /* T_TLSA */
664
665 default:
666 PUTSHORT(size, cp);
667 (void) memcpy(cp, data, size);
668 cp += size;
669 break;
670 }
671
672 return (cp - buf);
673 }
674
675 /*
676 ** SETHERRNOFROMSTRING -- set h_errno based on text
677 **
678 ** Parameters:
679 ** str -- string which might contain h_errno text
680 ** prc -- pointer to rcode (EX_*)
681 **
682 ** Returns:
683 ** h_errno if found
684 ** 0 otherwise
685 */
686
687 int
setherrnofromstring(str,prc)688 setherrnofromstring(str, prc)
689 const char *str;
690 int *prc;
691 {
692 SM_SET_H_ERRNO(0);
693 if (SM_IS_EMPTY(str))
694 return 0;
695 if (strstr(str, "herrno:") == NULL)
696 return 0;
697 if (prc != NULL)
698 *prc = EX_NOHOST;
699 if (strstr(str, "host_not_found"))
700 SM_SET_H_ERRNO(HOST_NOT_FOUND);
701 else if (strstr(str, "try_again"))
702 {
703 SM_SET_H_ERRNO(TRY_AGAIN);
704 if (prc != NULL)
705 *prc = EX_TEMPFAIL;
706 }
707 else if (strstr(str, "no_recovery"))
708 SM_SET_H_ERRNO(NO_RECOVERY);
709 else if (strstr(str, "no_data"))
710 SM_SET_H_ERRNO(NO_DATA);
711 else
712 SM_SET_H_ERRNO(NETDB_INTERNAL);
713 return h_errno;
714 }
715
716 /*
717 ** GETTTLFROMSTRING -- extract ttl from a string
718 **
719 ** Parameters:
720 ** str -- string which might contain ttl
721 **
722 ** Returns:
723 ** ttl if found
724 ** 0 otherwise
725 */
726
727 int
getttlfromstring(str)728 getttlfromstring(str)
729 const char *str;
730 {
731 if (SM_IS_EMPTY(str))
732 return 0;
733 #define TTL_PRE "ttl="
734 if (strstr(str, TTL_PRE) == NULL)
735 return 0;
736 return strtoul(str + strlen(TTL_PRE), NULL, 10);
737 }
738
739
740 # if defined(T_TLSA)
741 /*
742 ** HEX2BIN -- convert hex string to binary TLSA RR
743 **
744 ** Parameters:
745 ** p -- hex representation of TLSA RR
746 ** size -- length of p
747 **
748 ** Returns:
749 ** pointer to binary TLSA RR
750 ** NULL: error
751 */
752
753 static char *
hex2bin(p,size)754 hex2bin(p, size)
755 const char *p;
756 int size;
757 {
758 int i, pos, txtlen;
759 char *tlsa;
760
761 txtlen = size / 2;
762 if (txtlen * 2 == size)
763 {
764 if (LogLevel > 5)
765 sm_syslog(LOG_WARNING, NOQID,
766 "ERROR: hex2bin: size %d wrong", size);
767 return NULL;
768 }
769 tlsa = sm_malloc(txtlen + 1);
770 if (tlsa == NULL)
771 {
772 if (tTd(8, 17))
773 sm_dprintf("len=%d, tlsa=NULL\n", txtlen);
774 return NULL;
775 }
776
777 #define CHAR2INT(c) (((c) <= '9') ? ((c) - '0') : (toupper(c) - 'A' + 10))
778 for (i = 0, pos = 0; i + 1 < size && pos < txtlen; i += 2, pos++)
779 tlsa[pos] = CHAR2INT(p[i]) * 16 + CHAR2INT(p[i+1]);
780
781 return tlsa;
782 }
783 # endif /* T_TLSA */
784
785 const char *
rr_type2tag(rr_type)786 rr_type2tag(rr_type)
787 int rr_type;
788 {
789 switch (rr_type)
790 {
791 case T_A:
792 return "ipv4";
793 # if NETINET6
794 case T_AAAA:
795 return "ipv6";
796 # endif
797 case T_CNAME:
798 return "cname";
799 case T_MX:
800 return "mx";
801 # ifdef T_TLSA
802 case T_TLSA:
803 return "tlsa";
804 # endif
805 }
806 return NULL;
807 }
808
809 /*
810 ** DNSCRTRR -- create DNS RR
811 **
812 ** Parameters:
813 ** domain -- original query domain
814 ** query -- name of query
815 ** qtype -- resource record type of query
816 ** value -- (list of) data to set
817 ** rr_type -- resource record type
818 ** flags -- flags how to handle various lookups
819 ** herr -- (pointer to) h_errno (output if non-NULL)
820 ** adp -- (pointer to) ad flag
821 ** answer -- buffer for RRs
822 ** anslen -- size of answer
823 ** anspos -- current position in answer
824 **
825 ** Returns:
826 ** >0: length of data in answer
827 ** <0: error, check *herr
828 */
829
830 static int
dnscrtrr(domain,query,qtype,value,rr_type,flags,herr,adp,answer,anslen,anspos)831 dnscrtrr(domain, query, qtype, value, rr_type, flags, herr, adp, answer, anslen, anspos)
832 const char *domain;
833 const char *query;
834 int qtype;
835 char *value;
836 int rr_type;
837 unsigned int flags;
838 int *herr;
839 int *adp;
840 unsigned char *answer;
841 int anslen;
842 unsigned char *anspos;
843 {
844 SOCKADDR addr;
845 int ttl, ad, rlen;
846 char *p, *token;
847 char data[IN6ADDRSZ];
848 char rhs[MAXLINE];
849
850 rlen = -1;
851 if (SM_IS_EMPTY(value))
852 return rlen;
853 SM_REQUIRE(adp != NULL);
854 (void) sm_strlcpy(rhs, value, sizeof(rhs));
855 p = rhs;
856 if (setherrnofromstring(p, NULL) != 0)
857 {
858 if (herr != NULL)
859 *herr = h_errno;
860 if (tTd(8, 16))
861 sm_dprintf("dnscrtrr rhs=%s h_errno=%d (%s)\n",
862 p, h_errno, herrno2txt(h_errno));
863 return rlen;
864 }
865
866 ttl = 0;
867 ad = 0;
868 for (token = p; token != NULL && *token != '\0'; token = p)
869 {
870 rlen = 0;
871 while (p != NULL && *p != '\0' && !SM_ISSPACE(*p))
872 ++p;
873 if (SM_ISSPACE(*p))
874 *p++ = '\0';
875 sm_dprintf("dnscrtrr: token=%s\n", token);
876 if (strcmp(token, "ad") == 0)
877 {
878 bool adflag;
879
880 adflag = (_res.options & RES_USE_DNSSEC) != 0;
881
882 /* maybe print this only for the final RR? */
883 if (tTd(8, 61))
884 sm_dprintf("dnscrtrr: ad=1, adp=%d, adflag=%d\n",
885 *adp, adflag);
886 if (*adp != 0 && adflag)
887 {
888 *adp = 1;
889 ad = 1;
890 }
891 continue;
892 }
893 if (ttl == 0 && (ttl = getttlfromstring(token)) > 0)
894 {
895 if (tTd(8, 61))
896 sm_dprintf("dnscrtrr: ttl=%d\n", ttl);
897 continue;
898 }
899
900 if (rr_type == T_A)
901 {
902 addr.sin.sin_addr.s_addr = inet_addr(token);
903 (void) memmove(data, (void *)&addr.sin.sin_addr.s_addr,
904 INADDRSZ);
905 rlen = gen_dns_reply(answer, anslen, anspos,
906 query, qtype, domain, C_IN, rr_type, ttl,
907 INADDRSZ, data, 0, 0, ad);
908 }
909
910 # if NETINET6
911 if (rr_type == T_AAAA)
912 {
913 anynet_pton(AF_INET6, token, &addr.sin6.sin6_addr);
914 memmove(data, (void *)&addr.sin6.sin6_addr, IN6ADDRSZ);
915 rlen = gen_dns_reply(answer, anslen, anspos,
916 query, qtype, domain, C_IN, rr_type, ttl,
917 IN6ADDRSZ, data, 0, 0, ad);
918 }
919 # endif /* NETINET6 */
920
921 if (rr_type == T_MX)
922 {
923 char *endptr;
924 int pref;
925
926 pref = (int) strtoul(token, &endptr, 10);
927 if (endptr == NULL || *endptr != ':')
928 goto error;
929 token = endptr + 1;
930 rlen = gen_dns_reply(answer, anslen, anspos,
931 query, qtype, domain, C_IN, rr_type, ttl,
932 strlen(token) + 1, token, 0, pref, ad);
933 if (tTd(8, 50))
934 sm_dprintf("dnscrtrr: mx=%s, pref=%d, rlen=%d\n",
935 token, pref, rlen);
936 }
937
938 # ifdef T_TLSA
939 if (rr_type == T_TLSA)
940 rlen = gen_dns_reply(answer, anslen, anspos,
941 query, qtype, domain, C_IN, rr_type, ttl,
942 strlen(token) + 1, token, 0, 0, ad);
943 # endif
944
945 if (rr_type == T_CNAME)
946 rlen = gen_dns_reply(answer, anslen, anspos,
947 query, qtype, domain, C_IN, rr_type, ttl,
948 strlen(token), token, 0, 0, ad);
949 if (rlen < 0)
950 goto error;
951 if (rlen > 0)
952 anspos = answer + rlen;
953 }
954
955 if (ad != 1)
956 *adp = 0;
957
958 return rlen;
959
960 error:
961 if (herr != NULL && 0 == *herr)
962 *herr = NO_RECOVERY;
963 return -1;
964 }
965
966 /*
967 ** TSTDNS_SEARCH -- replacement for res_search() for testing
968 **
969 ** Parameters:
970 ** domain -- query domain
971 ** class -- class
972 ** type -- resource record type
973 ** answer -- buffer for RRs
974 ** anslen -- size of answer
975 **
976 ** Returns:
977 ** >0: length of data in answer
978 ** <0: error, check h_errno
979 */
980
981 int
tstdns_search(domain,class,type,answer,anslen)982 tstdns_search(domain, class, type, answer, anslen)
983 const char *domain;
984 int class;
985 int type;
986 unsigned char *answer;
987 int anslen;
988 {
989 int rlen, ad, maprcode, cnt, flags, herr;
990 bool found_cname;
991 const char *query;
992 char *p;
993 const char *tag;
994 char *av[2];
995 STAB *map;
996 # if _FFR_8BITENVADDR
997 char qbuf[MAXNAME_I];
998 char *qdomain;
999 # else
1000 # define qdomain domain
1001 # endif
1002 char key[MAXNAME_I + 16];
1003 char rhs[MAXLINE];
1004 unsigned char *anspos;
1005
1006 rlen = -1;
1007 herr = 0;
1008 if (class != C_IN)
1009 goto error;
1010 if (SM_IS_EMPTY(domain))
1011 goto error;
1012 tag = rr_type2tag(type);
1013 if (tag == NULL)
1014 goto error;
1015 maprcode = EX_OK;
1016 ad = -1;
1017 flags = 0;
1018 # if _FFR_8BITENVADDR
1019 if (tTd(8, 62))
1020 sm_dprintf("domain=%s\n", domain);
1021 (void) dequote_internal_chars((char *)domain, qbuf, sizeof(qbuf));
1022 query = qbuf;
1023 qdomain = qbuf;
1024 if (tTd(8, 63))
1025 sm_dprintf("qdomain=%s\n", qdomain);
1026 # else
1027 query = domain;
1028 # endif /* _FFR_8BITENVADDR */
1029 anspos = NULL;
1030
1031 map = stab("access", ST_MAP, ST_FIND);
1032 if (NULL == map)
1033 {
1034 sm_dprintf("access map not found\n");
1035 goto error;
1036 }
1037 if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
1038 !openmap(&(map->s_map)))
1039 {
1040 sm_dprintf("access map open failed\n");
1041 goto error;
1042 }
1043
1044 /*
1045 ** Look up tag:domain, if not found and domain does not end with a dot
1046 ** (and the proper debug level is selected), also try with trailing dot.
1047 */
1048
1049 #define SM_LOOKUP2(tag) \
1050 do { \
1051 int len; \
1052 \
1053 len = strlen(qdomain); \
1054 av[0] = key; \
1055 av[1] = NULL; \
1056 snprintf(key, sizeof(key), "%s:%s", tag, qdomain); \
1057 p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
1058 &maprcode); \
1059 if (p != NULL) \
1060 break; \
1061 if (!tTd(8, 112) || (len > 0 && '.' == qdomain[len - 1])) \
1062 break; \
1063 snprintf(key, sizeof(key), "%s:%s.", tag, qdomain); \
1064 p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
1065 &maprcode); \
1066 } while (0)
1067
1068 cnt = 0;
1069 found_cname = false;
1070 while (cnt < 6)
1071 {
1072 char *last;
1073
1074 /* Should this try with/without trailing dot? */
1075 SM_LOOKUP2(tag);
1076 if (p != NULL)
1077 {
1078 sm_dprintf("access map lookup key=%s, value=%s\n", key,
1079 p);
1080 break;
1081 }
1082 if (NULL == p && (flags & RR_NO_CNAME) == 0)
1083 {
1084 sm_dprintf("access map lookup failed key=%s, try cname\n",
1085 key);
1086 SM_LOOKUP2("cname");
1087 if (p != NULL)
1088 {
1089 sm_dprintf("cname lookup key=%s, value=%s, ad=%d\n",
1090 key, p, ad);
1091 rlen = dnscrtrr(qdomain, query, type, p, T_CNAME,
1092 flags, &herr, &ad, answer,
1093 anslen, anspos);
1094 if (rlen < 0)
1095 goto error;
1096 if (rlen > 0)
1097 anspos = answer + rlen;
1098 found_cname = true;
1099 }
1100 }
1101 if (NULL == p)
1102 break;
1103
1104 (void) sm_strlcpy(rhs, p, sizeof(rhs));
1105 p = rhs;
1106
1107 /* skip (leading) ad/ttl: look for last ' ' */
1108 if ((last = strrchr(p, ' ')) != NULL && last[1] != '\0')
1109 qdomain = last + 1;
1110 else
1111 qdomain = p;
1112 ++cnt;
1113 }
1114 if (NULL == p)
1115 {
1116 int t;
1117 char *tags[] = { "ipv4", "mx", "tlsa",
1118 # if NETINET6
1119 "ipv6",
1120 # endif
1121 NULL
1122 };
1123
1124 for (t = 0; tags[t] != NULL; t++)
1125 {
1126 if (strcmp(tag, tags[t]) == 0)
1127 continue;
1128 SM_LOOKUP2(tags[t]);
1129 if (p != NULL)
1130 {
1131 sm_dprintf("access map lookup failed key=%s:%s, but found key=%s\n",
1132 tag, qdomain, key);
1133 herr = NO_DATA;
1134 goto error;
1135 }
1136 }
1137 sm_dprintf("access map lookup failed key=%s\n", key);
1138 herr = HOST_NOT_FOUND;
1139 goto error;
1140 }
1141 if (found_cname && (flags & RR_ONLY_CNAME) != 0)
1142 return rlen;
1143 rlen = dnscrtrr(qdomain, query, type, p, type, flags, &herr, &ad,
1144 answer, anslen, anspos);
1145 if (rlen < 0)
1146 goto error;
1147 return rlen;
1148
1149 error:
1150 if (0 == herr)
1151 herr = NO_RECOVERY;
1152 SM_SET_H_ERRNO(herr);
1153 sm_dprintf("rlen=%d, herr=%d\n", rlen, herr);
1154 return -1;
1155 }
1156
1157 /*
1158 ** TSTDNS_QUERYDOMAIN -- replacement for res_querydomain() for testing
1159 **
1160 ** Parameters:
1161 ** name -- query name
1162 ** domain -- query domain
1163 ** class -- class
1164 ** type -- resource record type
1165 ** answer -- buffer for RRs
1166 ** anslen -- size of answer
1167 **
1168 ** Returns:
1169 ** >0: length of data in answer
1170 ** <0: error, check h_errno
1171 */
1172
1173 int
tstdns_querydomain(name,domain,class,type,answer,anslen)1174 tstdns_querydomain(name, domain, class, type, answer, anslen)
1175 const char *name;
1176 const char *domain;
1177 int class;
1178 int type;
1179 unsigned char *answer;
1180 int anslen;
1181 {
1182 char query[MAXNAME_I];
1183 int len;
1184
1185 if (NULL == name)
1186 goto error;
1187 if (SM_IS_EMPTY(domain))
1188 return tstdns_search(name, class, type, answer, anslen);
1189
1190 len = snprintf(query, sizeof(query), "%s.%s", name, domain);
1191 if (len >= (int)sizeof(query))
1192 goto error;
1193 return tstdns_search(query, class, type, answer, anslen);
1194
1195 error:
1196 SM_SET_H_ERRNO(NO_RECOVERY);
1197 return -1;
1198 }
1199
1200 # endif /* DNSSEC_TEST */
1201
1202 /*
1203 ** DNS_LOOKUP_INT -- perform DNS lookup
1204 **
1205 ** Parameters:
1206 ** domain -- name to look up
1207 ** rr_class -- resource record class
1208 ** rr_type -- resource record type
1209 ** retrans -- retransmission timeout
1210 ** retry -- number of retries
1211 ** options -- DNS resolver options
1212 ** flags -- currently only passed to parse_dns_reply()
1213 ** err -- (pointer to) errno (output if non-NULL)
1214 ** herr -- (pointer to) h_errno (output if non-NULL)
1215 **
1216 ** Returns:
1217 ** result of lookup if succeeded.
1218 ** NULL otherwise.
1219 */
1220
1221 DNS_REPLY_T *
dns_lookup_int(domain,rr_class,rr_type,retrans,retry,options,flags,err,herr)1222 dns_lookup_int(domain, rr_class, rr_type, retrans, retry, options, flags, err, herr)
1223 const char *domain;
1224 int rr_class;
1225 int rr_type;
1226 time_t retrans;
1227 int retry;
1228 unsigned int options;
1229 unsigned int flags;
1230 int *err;
1231 int *herr;
1232 {
1233 int len;
1234 unsigned long old_options = 0;
1235 time_t save_retrans = 0;
1236 int save_retry = 0;
1237 DNS_REPLY_T *dr = NULL;
1238 querybuf reply_buf;
1239 unsigned char *reply;
1240 int (*resfunc) __P((const char *, int, int, u_char *, int));
1241
1242 # define SMRBSIZE ((int) sizeof(reply_buf))
1243 # ifndef IP_MAXPACKET
1244 # define IP_MAXPACKET 65535
1245 # endif
1246
1247 resfunc = res_search;
1248 # if DNSSEC_TEST
1249 if (tTd(8, 110))
1250 resfunc = tstdns_search;
1251 # endif
1252
1253 old_options = _res.options;
1254 _res.options |= options;
1255 if (err != NULL)
1256 *err = 0;
1257 if (herr != NULL)
1258 *herr = 0;
1259 if (tTd(8, 16))
1260 {
1261 _res.options |= RES_DEBUG;
1262 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)\n", domain,
1263 rr_class, dns_type_to_string(rr_type), options);
1264 }
1265 # if DNSSEC_TEST
1266 if (tTd(8, 15))
1267 sm_dprintf("NS=%s, port=%d\n",
1268 inet_ntoa(_res.nsaddr_list[0].sin_addr),
1269 ntohs(_res.nsaddr_list[0].sin_port));
1270 # endif
1271 if (retrans > 0)
1272 {
1273 save_retrans = _res.retrans;
1274 _res.retrans = retrans;
1275 }
1276 if (retry > 0)
1277 {
1278 save_retry = _res.retry;
1279 _res.retry = retry;
1280 }
1281 errno = 0;
1282 SM_SET_H_ERRNO(0);
1283 reply = (unsigned char *)&reply_buf;
1284 len = (*resfunc)(domain, rr_class, rr_type, reply, SMRBSIZE);
1285 if (len >= SMRBSIZE)
1286 {
1287 if (len >= IP_MAXPACKET)
1288 {
1289 if (tTd(8, 4))
1290 sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n",
1291 domain, len, SMRBSIZE, IP_MAXPACKET);
1292 }
1293 else
1294 {
1295 if (tTd(8, 6))
1296 sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n",
1297 domain, len, SMRBSIZE, IP_MAXPACKET);
1298 reply = (unsigned char *)sm_malloc(IP_MAXPACKET);
1299 if (reply == NULL)
1300 SM_SET_H_ERRNO(TRY_AGAIN);
1301 else
1302 {
1303 SM_SET_H_ERRNO(0);
1304 len = (*resfunc)(domain, rr_class, rr_type,
1305 reply, IP_MAXPACKET);
1306 }
1307 }
1308 }
1309 _res.options = old_options;
1310 if (len < 0)
1311 {
1312 if (err != NULL)
1313 *err = errno;
1314 if (herr != NULL)
1315 *herr = h_errno;
1316 if (tTd(8, 16))
1317 {
1318 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d, errno=%d, h_errno=%d"
1319 # if DNSSEC_TEST
1320 " (%s)"
1321 # endif
1322 "\n",
1323 domain, rr_class, dns_type_to_string(rr_type),
1324 options, len, errno, h_errno
1325 # if DNSSEC_TEST
1326 , herrno2txt(h_errno)
1327 # endif
1328 );
1329 }
1330 }
1331 else if (tTd(8, 16))
1332 {
1333 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d\n",
1334 domain, rr_class, dns_type_to_string(rr_type),
1335 options, len);
1336 }
1337 if (len >= 0 && len < IP_MAXPACKET && reply != NULL)
1338 dr = parse_dns_reply(reply, len, flags);
1339 if (reply != (unsigned char *)&reply_buf && reply != NULL)
1340 {
1341 sm_free(reply);
1342 reply = NULL;
1343 }
1344 if (retrans > 0)
1345 _res.retrans = save_retrans;
1346 if (retry > 0)
1347 _res.retry = save_retry;
1348 return dr;
1349 }
1350
1351 /*
1352 ** DNS_LOOKUP_MAP -- perform DNS map lookup
1353 **
1354 ** Parameters:
1355 ** domain -- name to look up
1356 ** rr_class -- resource record class
1357 ** rr_type -- resource record type
1358 ** retrans -- retransmission timeout
1359 ** retry -- number of retries
1360 ** options -- DNS resolver options
1361 **
1362 ** Returns:
1363 ** result of lookup if succeeded.
1364 ** NULL otherwise.
1365 */
1366
1367 DNS_REPLY_T *
dns_lookup_map(domain,rr_class,rr_type,retrans,retry,options)1368 dns_lookup_map(domain, rr_class, rr_type, retrans, retry, options)
1369 const char *domain;
1370 int rr_class;
1371 int rr_type;
1372 time_t retrans;
1373 int retry;
1374 unsigned int options;
1375 {
1376 return dns_lookup_int(domain, rr_class, rr_type, retrans, retry,
1377 options, RR_AS_TEXT, NULL, NULL);
1378 }
1379
1380 # if DANE
1381 /*
1382 ** DNS2HE -- convert DNS_REPLY_T list to hostent struct
1383 **
1384 ** Parameters:
1385 ** dr -- DNS lookup result
1386 ** family -- address family
1387 **
1388 ** Returns:
1389 ** hostent struct if succeeded.
1390 ** NULL otherwise.
1391 **
1392 ** Note:
1393 ** this returns a pointer to a static struct!
1394 */
1395
1396 struct hostent *
dns2he(dr,family)1397 dns2he(dr, family)
1398 DNS_REPLY_T *dr;
1399 int family;
1400 {
1401 # define SM_MAX_ADDRS 256
1402 static struct hostent he;
1403 static char *he_aliases[1];
1404 static char *he_addr_list[SM_MAX_ADDRS];
1405 # ifdef IN6ADDRSZ
1406 # define IN_ADDRSZ IN6ADDRSZ
1407 # else
1408 # define IN_ADDRSZ INADDRSZ
1409 # endif
1410 static char he_addrs[SM_MAX_ADDRS * IN_ADDRSZ];
1411 static char he_name[MAXNAME_I];
1412 static bool he_init = false;
1413 struct hostent *h;
1414 int i;
1415 size_t sz;
1416 # if NETINET6 && DNSSEC_TEST
1417 struct in6_addr ia6;
1418 char buf6[INET6_ADDRSTRLEN];
1419 # endif
1420 RESOURCE_RECORD_T *rr;
1421
1422 if (dr == NULL)
1423 return NULL;
1424
1425 h = &he;
1426 if (!he_init)
1427 {
1428 he_aliases[0] = NULL;
1429 he.h_aliases = he_aliases;
1430 he.h_addr_list = he_addr_list;
1431 he.h_name = he_name;
1432 he_init = true;
1433 }
1434 h->h_addrtype = family;
1435
1436 if (tTd(8, 17))
1437 sm_dprintf("dns2he: ad=%d\n", dr->dns_r_h.ad);
1438
1439 /* do we want/need to copy the name? */
1440 rr = dr->dns_r_head;
1441 if (rr != NULL && rr->rr_domain != NULL)
1442 sm_strlcpy(h->h_name, rr->rr_domain, sizeof(he_name));
1443 else
1444 h->h_name[0] = '\0';
1445
1446 sz = 0;
1447 # if NETINET
1448 if (family == AF_INET)
1449 sz = INADDRSZ;
1450 # endif
1451 # if NETINET6
1452 if (family == AF_INET6)
1453 sz = IN6ADDRSZ;
1454 # endif
1455 if (sz == 0)
1456 return NULL;
1457 h->h_length = sz;
1458
1459 for (rr = dr->dns_r_head, i = 0; rr != NULL && i < SM_MAX_ADDRS - 1;
1460 rr = rr->rr_next)
1461 {
1462 h->h_addr_list[i] = he_addrs + i * h->h_length;
1463 switch (rr->rr_type)
1464 {
1465 # if NETINET
1466 case T_A:
1467 if (family != AF_INET)
1468 continue;
1469 memmove(h->h_addr_list[i], rr->rr_u.rr_a, INADDRSZ);
1470 ++i;
1471 break;
1472 # endif /* NETINET */
1473 # if NETINET6
1474 case T_AAAA:
1475 if (family != AF_INET6)
1476 continue;
1477 memmove(h->h_addr_list[i], rr->rr_u.rr_aaaa, IN6ADDRSZ);
1478 ++i;
1479 break;
1480 # endif /* NETINET6 */
1481 case T_CNAME:
1482 # if DNSSEC_TEST
1483 if (tTd(8, 16))
1484 sm_dprintf("dns2he: cname: %s ttl=%d\n",
1485 rr->rr_u.rr_txt, rr->rr_ttl);
1486 # endif
1487 break;
1488 case T_MX:
1489 # if DNSSEC_TEST
1490 if (tTd(8, 16))
1491 sm_dprintf("dns2he: mx: %d %s ttl=%d\n",
1492 rr->rr_u.rr_mx->mx_r_preference,
1493 rr->rr_u.rr_mx->mx_r_domain,
1494 rr->rr_ttl);
1495 # endif
1496 break;
1497
1498 # if defined(T_TLSA)
1499 case T_TLSA:
1500 # if DNSSEC_TEST
1501 if (tTd(8, 16))
1502 {
1503 char *tlsa;
1504 int len;
1505
1506 len = bin2hex(&tlsa, rr->rr_u.rr_data,
1507 rr->rr_size, 4);
1508 if (len > 0)
1509 sm_dprintf("dns2he: tlsa: %s ttl=%d\n",
1510 tlsa, rr->rr_ttl);
1511 }
1512 # endif
1513 break;
1514 # endif /* T_TLSA */
1515 }
1516 }
1517
1518 /* complain if list is too long! */
1519 SM_ASSERT(i < SM_MAX_ADDRS);
1520 h->h_addr_list[i] = NULL;
1521
1522 # if DNSSEC_TEST
1523 if (tTd(8, 16))
1524 {
1525 struct in_addr ia;
1526
1527 for (i = 0; h->h_addr_list[i] != NULL && i < SM_MAX_ADDRS; i++)
1528 {
1529 char *addr;
1530
1531 addr = NULL;
1532 # if NETINET6
1533 if (h->h_addrtype == AF_INET6)
1534 {
1535 memmove(&ia6, h->h_addr_list[i], IN6ADDRSZ);
1536 addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
1537 }
1538 else
1539 # endif /* NETINET6 */
1540 /* "else" in #if code above */
1541 {
1542 memmove(&ia, h->h_addr_list[i], INADDRSZ);
1543 addr = (char *) inet_ntoa(ia);
1544 }
1545 if (addr != NULL)
1546 sm_dprintf("dns2he: addr[%d]: %s\n", i, addr);
1547 }
1548 }
1549 # endif /* DNSSEC_TEST */
1550 return h;
1551 }
1552 # endif /* DANE */
1553 # endif /* DNSMAP || DANE */
1554
1555 # if DNSSEC_TEST || _FFR_NAMESERVER
1556 /*
1557 ** DNS_ADDNS -- add one NS in resolver context
1558 **
1559 ** Parameters:
1560 ** ns -- (IPv4 address of) nameserver
1561 ** port -- nameserver port (host order)
1562 **
1563 ** Returns:
1564 ** None.
1565 */
1566
1567 static void dns_addns __P((struct in_addr *, unsigned int));
1568 static int nsidx = 0;
1569 #ifndef MAXNS
1570 # define MAXNS 3
1571 #endif
1572 static void
dns_addns(ns,port)1573 dns_addns(ns, port)
1574 struct in_addr *ns;
1575 unsigned int port;
1576 {
1577 if (nsidx >= MAXNS)
1578 syserr("too many NameServers defined (%d max)", MAXNS);
1579 _res.nsaddr_list[nsidx].sin_family = AF_INET;
1580 _res.nsaddr_list[nsidx].sin_addr = *ns;
1581 if (port != 0)
1582 _res.nsaddr_list[nsidx].sin_port = htons(port);
1583 _res.nscount = ++nsidx;
1584 if (tTd(8, 61))
1585 sm_dprintf("dns_addns: nsidx=%d, ns=%s:%u\n",
1586 nsidx - 1, inet_ntoa(*ns), port);
1587 }
1588
1589 /*
1590 ** NSPORTIP -- parse port@IPv4 and set NS accordingly
1591 **
1592 ** Parameters:
1593 ** p -- port@IPv4
1594 **
1595 ** Returns:
1596 ** <0: error
1597 ** >=0: ok
1598 **
1599 ** Side Effects:
1600 ** sets NS for DNS lookups
1601 */
1602
1603 /*
1604 ** There should be a generic function for this...
1605 ** milter_open(), socket_map_open(), others?
1606 */
1607
1608 int
nsportip(p)1609 nsportip(p)
1610 char *p;
1611 {
1612 char *h;
1613 int r;
1614 unsigned short port;
1615 struct in_addr nsip;
1616
1617 if (SM_IS_EMPTY(p))
1618 return -1;
1619
1620 port = 0;
1621 while (SM_ISSPACE(*p))
1622 p++;
1623 if (*p == '\0')
1624 return -1;
1625 h = strchr(p, '@');
1626 if (h != NULL)
1627 {
1628 *h = '\0';
1629 if (isascii(*p) && isdigit(*p))
1630 port = atoi(p);
1631 *h = '@';
1632 p = h + 1;
1633 }
1634 h = strchr(p, ' ');
1635 if (h != NULL)
1636 *h = '\0';
1637 r = inet_pton(AF_INET, p, &nsip);
1638 if (r > 0)
1639 {
1640 if ((_res.options & RES_INIT) == 0)
1641 (void) res_init();
1642 dns_addns(&nsip, port);
1643 }
1644 if (h != NULL)
1645 *h = ' ';
1646 return r > 0 ? 0 : -1;
1647 }
1648 # endif /* DNSSEC_TEST || _FFR_NAMESERVER */
1649 #endif /* NAMED_BIND */
1650