Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: dns_sec.c,v 1.3 2025/02/25 19:15:44 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 
     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