xref: /netbsd-src/external/ibm-public/postfix/dist/src/dns/dns_sec.c (revision 67b9b338a7386232ac596b5fd0cd5a9cc8a03c71)
1 /*	$NetBSD: dns_sec.c,v 1.2 2022/10/08 16:12:45 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dns_sec 3
6 /* SUMMARY
7 /*	DNSSEC validation availability
8 /* SYNOPSIS
9 /*	#include <dns.h>
10 /*
11 /*	DNS_SEC_STATS_SET(
12 /*	int	flags)
13 /*
14 /*	DNS_SEC_STATS_TEST(
15 /*	int	flags)
16 /*
17 /*	void	dns_sec_probe(
18 /*	int	rflags)
19 /* DESCRIPTION
20 /*	This module maintains information about the availability of
21 /*	DNSSEC validation, in global flags that summarize
22 /*	process-lifetime history.
23 /* .IP DNS_SEC_FLAG_AVAILABLE
24 /*	The process has received at least one DNSSEC validated
25 /*	response to a query that requested DNSSEC validation.
26 /* .IP DNS_SEC_FLAG_DONT_PROBE
27 /*	The process has sent a DNSSEC probe (see below), or DNSSEC
28 /*	probing is disabled by configuration.
29 /* .PP
30 /*	DNS_SEC_STATS_SET() sets one or more DNS_SEC_FLAG_* flags,
31 /*	and DNS_SEC_STATS_TEST() returns non-zero if any of the
32 /*	specified flags is set.
33 /*
34 /*	dns_sec_probe() generates a query to the target specified
35 /*	with the \fBdnssec_probe\fR configuration parameter. It
36 /*	sets the DNS_SEC_FLAG_DONT_PROBE flag, and it calls
37 /*	dns_lookup() which sets DNS_SEC_FLAG_AVAILABLE if it receives
38 /*	a DNSSEC validated response. Preconditions:
39 /* .IP \(bu
40 /*	The rflags argument must request DNSSEC validation (in the
41 /*	same manner as dns_lookup() rflags argument).
42 /* .IP \(bu
43 /*	The DNS_SEC_FLAG_AVAILABLE and DNS_SEC_FLAG_DONT_PROBE
44 /*	flags must be false.
45 /* LICENSE
46 /* .ad
47 /* .fi
48 /*	The Secure Mailer license must be distributed with this software.
49 /* AUTHOR(S)
50 /*	Wietse Venema
51 /*	Google, Inc.
52 /*	111 8th Avenue
53 /*	New York, NY 10011, USA
54 /*--*/
55 
56 #include <sys_defs.h>
57 
58  /*
59   * Utility library.
60   */
61 #include <msg.h>
62 #include <mymalloc.h>
63 #include <split_at.h>
64 #include <vstring.h>
65 
66  /*
67   * Global library.
68   */
69 #include <mail_params.h>
70 
71  /*
72   * DNS library.
73   */
74 #include <dns.h>
75 
76 int     dns_sec_stats;
77 
78 /* dns_sec_probe - send a probe to establish DNSSEC viability */
79 
dns_sec_probe(int rflags)80 void    dns_sec_probe(int rflags)
81 {
82     const char myname[] = "dns_sec_probe";
83     char   *saved_dnssec_probe;
84     char   *qname;
85     int     qtype;
86     DNS_RR *rrlist = 0;
87     int     dns_status;
88     VSTRING *why;
89 
90     /*
91      * Sanity checks.
92      */
93     if (!DNS_WANT_DNSSEC_VALIDATION(rflags))
94 	msg_panic("%s: DNSSEC is not requested", myname);
95     if (DNS_SEC_STATS_TEST(DNS_SEC_FLAG_DONT_PROBE))
96 	msg_panic("%s: DNSSEC probe was already sent, or probing is disabled",
97 		  myname);
98     if (DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
99 	msg_panic("%s: already have validated DNS response", myname);
100 
101     /*
102      * Don't recurse.
103      */
104     DNS_SEC_STATS_SET(DNS_SEC_FLAG_DONT_PROBE);
105 
106     /*
107      * Don't probe.
108      */
109     if (*var_dnssec_probe == 0)
110 	return;
111 
112     /*
113      * Parse the probe spec. Format is type:resource.
114      */
115     saved_dnssec_probe = mystrdup(var_dnssec_probe);
116     if ((qname = split_at(saved_dnssec_probe, ':')) == 0 || *qname == 0
117 	|| (qtype = dns_type(saved_dnssec_probe)) == 0)
118 	msg_fatal("malformed %s value: %s format is qtype:qname",
119 		  VAR_DNSSEC_PROBE, var_dnssec_probe);
120 
121     why = vstring_alloc(100);
122     dns_status = dns_lookup(qname, qtype, rflags, &rrlist, (VSTRING *) 0, why);
123     if (!DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
124 	msg_warn("DNSSEC validation may be unavailable");
125     else if (msg_verbose)
126 	msg_info(VAR_DNSSEC_PROBE
127 		 " '%s' received a response that is DNSSEC validated",
128 		 var_dnssec_probe);
129     switch (dns_status) {
130     default:
131 	if (!DNS_SEC_STATS_TEST(DNS_SEC_FLAG_AVAILABLE))
132 	    msg_warn("reason: " VAR_DNSSEC_PROBE
133 		     " '%s' received a response that is not DNSSEC validated",
134 		     var_dnssec_probe);
135 	if (rrlist)
136 	    dns_rr_free(rrlist);
137 	break;
138     case DNS_RETRY:
139     case DNS_FAIL:
140 	msg_warn("reason: " VAR_DNSSEC_PROBE " '%s' received no response: %s",
141 		 var_dnssec_probe, vstring_str(why));
142 	break;
143     }
144     myfree(saved_dnssec_probe);
145     vstring_free(why);
146 }
147