Home | History | Annotate | Line # | Download | only in smtp
      1 /*	$NetBSD: smtp_tls_policy.c,v 1.6 2026/05/09 18:49:20 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	smtp_tls_policy 3
      6 /* SUMMARY
      7 /*	SMTP_TLS_POLICY structure management
      8 /* SYNOPSIS
      9 /*	#include "smtp.h"
     10 /*
     11 /*	void    smtp_tls_list_init()
     12 /*
     13 /*	int	smtp_tls_policy_cache_query(why, tls, iter)
     14 /*	DSN_BUF	*why;
     15 /*	SMTP_TLS_POLICY *tls;
     16 /*	SMTP_ITERATOR *iter;
     17 /*
     18 /*	void	smtp_tls_policy_dummy(tls)
     19 /*	SMTP_TLS_POLICY *tls;
     20 /*
     21 /*	void	smtp_tls_policy_cache_flush()
     22 /*
     23 /*	int	smtp_tls_authorize_mx_hostname(tls, qname)
     24 /*	SMTP_TLS_POLICY *tls;
     25 /*	const char *qname;
     26 /* DESCRIPTION
     27 /*	smtp_tls_list_init() initializes lookup tables used by the TLS
     28 /*	policy engine.
     29 /*
     30 /*	smtp_tls_policy_cache_query() returns a shallow copy of the
     31 /*	cached SMTP_TLS_POLICY structure for the iterator's
     32 /*	destination, host, port and DNSSEC validation status.
     33 /*	This copy is guaranteed to be valid until the next
     34 /*	smtp_tls_policy_cache_query() or smtp_tls_policy_cache_flush()
     35 /*	call.  The caller can override the TLS security level without
     36 /*	corrupting the policy cache.
     37 /*	When any required table or DNS lookups fail, the TLS level
     38 /*	is set to TLS_LEV_INVALID, the "why" argument is updated
     39 /*	with the error reason and the result value is zero (false).
     40 /*	When var_smtp_tls_enf_sts_mx_pat is not null, and a policy plugin
     41 /*	specifies a policy_type "sts" plus one or more mx_host_pattern
     42 /*	instances, transform the policy as follows: allow only MX hosts
     43 /*	that match an mx_host_pattern instance, and match a server
     44 /*	certificate against the server hostname.
     45 /*
     46 /*	smtp_tls_policy_dummy() initializes a trivial, non-cached,
     47 /*	policy with TLS disabled.
     48 /*
     49 /*	smtp_tls_policy_cache_flush() destroys the TLS policy cache
     50 /*	and contents.
     51 /*
     52 /*	smtp_tls_authorize_mx_hostname() authorizes an MX host if the
     53 /*	name used for host lookup satisfies a TLS policy MX name
     54 /*	constraint (for example, an STS policy MX pattern), or if the
     55 /*	TLS policy has no name constraint.
     56 /*
     57 /*	Arguments:
     58 /* .IP why
     59 /*	A pointer to a DSN_BUF which holds error status information when
     60 /*	the TLS policy lookup fails.
     61 /* .IP tls
     62 /*	Pointer to TLS policy storage.
     63 /* .IP iter
     64 /*	The literal next-hop or fall-back destination including
     65 /*	the optional [] and including the :port or :service;
     66 /*	the name of the remote host after MX and CNAME expansions
     67 /*	(see smtp_cname_overrides_servername for the handling
     68 /*	of hostnames that resolve to a CNAME record);
     69 /*	the printable address of the remote host;
     70 /*	the remote port in network byte order;
     71 /*	the DNSSEC validation status of the host name lookup after
     72 /*	MX and CNAME expansions.
     73 /* LICENSE
     74 /* .ad
     75 /* .fi
     76 /*	This software is free. You can do with it whatever you want.
     77 /*	The original author kindly requests that you acknowledge
     78 /*	the use of his software.
     79 /* AUTHOR(S)
     80 /*	TLS support originally by:
     81 /*	Lutz Jaenicke
     82 /*	BTU Cottbus
     83 /*	Allgemeine Elektrotechnik
     84 /*	Universitaetsplatz 3-4
     85 /*	D-03044 Cottbus, Germany
     86 /*
     87 /*	Updated by:
     88 /*	Wietse Venema
     89 /*	IBM T.J. Watson Research
     90 /*	P.O. Box 704
     91 /*	Yorktown Heights, NY 10598, USA
     92 /*
     93 /*	Wietse Venema
     94 /*	Google, Inc.
     95 /*	111 8th Avenue
     96 /*	New York, NY 10011, USA
     97 /*
     98 /*	Viktor Dukhovni
     99 /*--*/
    100 
    101 /* System library. */
    102 
    103 #include <sys_defs.h>
    104 
    105 #ifdef USE_TLS
    106 
    107 #include <netinet/in.h>			/* ntohs() for Solaris or BSD */
    108 #include <arpa/inet.h>			/* ntohs() for Linux or BSD */
    109 #include <stdlib.h>
    110 #include <string.h>
    111 
    112 #ifdef STRCASECMP_IN_STRINGS_H
    113 #include <strings.h>
    114 #endif
    115 
    116 /* Utility library. */
    117 
    118 #include <msg.h>
    119 #include <mymalloc.h>
    120 #include <vstring.h>
    121 #include <sane_strtol.h>
    122 #include <stringops.h>
    123 #include <valid_hostname.h>
    124 #include <valid_utf8_hostname.h>
    125 #include <ctable.h>
    126 #include <midna_domain.h>
    127 
    128 /* Global library. */
    129 
    130 #include <mail_params.h>
    131 #include <maps.h>
    132 #include <dsn_buf.h>
    133 
    134 /* TLS library. */
    135 
    136 #include <tlsrpt_wrapper.h>
    137 
    138 /* DNS library. */
    139 
    140 #include <dns.h>
    141 
    142 /* Application-specific. */
    143 
    144 #include "smtp.h"
    145 
    146 /* XXX Cache size should scale with [sl]mtp_mx_address_limit. */
    147 #define CACHE_SIZE 20
    148 static CTABLE *policy_cache;
    149 
    150 static int global_tls_level(void);
    151 static void dane_init(SMTP_TLS_POLICY *, SMTP_ITERATOR *);
    152 
    153 static MAPS *tls_policy;		/* lookup table(s) */
    154 static MAPS *tls_per_site;		/* lookup table(s) */
    155 
    156 /* match_sts_mx_host_pattern -  match hostname against STS policy MX pattern */
    157 
    158 static int match_sts_mx_host_pattern(const char *pattern, const char *qname)
    159 {
    160     const char *first_dot_in_qname;
    161 
    162     /* Caller guarantees that inputs are in ASCII form. */
    163     return (strcasecmp(qname, pattern) == 0
    164 	    || (pattern[0] == '*' && pattern[1] == '.' && pattern[2] != 0
    165 		&& (first_dot_in_qname = strchr(qname, '.')) != 0
    166 		&& first_dot_in_qname > qname
    167 		&& strcasecmp(first_dot_in_qname + 1, pattern + 2) == 0));
    168 }
    169 
    170 /* smtp_tls_authorize_mx_hostname - enforce applicable MX hostname policy */
    171 
    172 int     smtp_tls_authorize_mx_hostname(SMTP_TLS_POLICY *tls, const char *name)
    173 {
    174 
    175 #define SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls) (var_smtp_tls_enf_sts_mx_pat \
    176 	    && (tls)->ext_policy_type != 0 \
    177 	    && strcasecmp((tls)->ext_policy_type, "sts") == 0 \
    178 	    && (tls)->matchargv != 0 && (tls)->ext_mx_host_patterns != 0)
    179 
    180     /* Enforce STS policy MX patterns. */
    181     if (SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls)) {
    182 	const char *aname;
    183 	char  **pattp;
    184 
    185 #ifndef NO_EAI
    186 	if (!allascii(name) && (aname = midna_domain_to_ascii(name)) != 0) {
    187 	    if (msg_verbose)
    188 		msg_info("%s asciified to %s", name, aname);
    189 	} else
    190 #endif
    191 	    aname = name;
    192 	for (pattp = tls->ext_mx_host_patterns->argv; *pattp; pattp++) {
    193 	    if (match_sts_mx_host_pattern(*pattp, aname)) {
    194 		if (msg_verbose)
    195 		    msg_info("MX name '%s' matches STS MX pattern for '%s'",
    196 			     aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
    197 		return (1);
    198 	    }
    199 	}
    200 	msg_warn("MX name '%s' does not match STS MX pattern for '%s'",
    201 	       aname, tls->ext_policy_domain ? tls->ext_policy_domain : "");
    202 	return (0);
    203     }
    204     /* No applicable policy name patterns. */
    205     return (1);
    206 }
    207 
    208 /* smtp_tls_list_init - initialize per-site policy lists */
    209 
    210 void    smtp_tls_list_init(void)
    211 {
    212     if (*var_smtp_tls_policy) {
    213 	tls_policy = maps_create(VAR_LMTP_SMTP(TLS_POLICY),
    214 				 var_smtp_tls_policy,
    215 				 DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
    216 				 | DICT_FLAG_UTF8_REQUEST);
    217 	if (*var_smtp_tls_per_site)
    218 	    msg_warn("%s ignored when %s is not empty.",
    219 		     VAR_LMTP_SMTP(TLS_PER_SITE), VAR_LMTP_SMTP(TLS_POLICY));
    220 	return;
    221     }
    222     if (*var_smtp_tls_per_site) {
    223 	tls_per_site = maps_create(VAR_LMTP_SMTP(TLS_PER_SITE),
    224 				   var_smtp_tls_per_site,
    225 				   DICT_FLAG_LOCK | DICT_FLAG_FOLD_FIX
    226 				   | DICT_FLAG_UTF8_REQUEST);
    227     }
    228 }
    229 
    230 /* policy_name - printable tls policy level */
    231 
    232 static const char *policy_name(int tls_level)
    233 {
    234     const char *name = str_tls_level(tls_level);
    235 
    236     if (name == 0)
    237 	name = "unknown";
    238     return name;
    239 }
    240 
    241 #define MARK_INVALID(why, levelp) do { \
    242 	    dsb_simple((why), "4.7.5", "client TLS configuration problem"); \
    243 	    *(levelp) = TLS_LEV_INVALID; } while (0)
    244 
    245 /* tls_site_lookup - look up per-site TLS security level */
    246 
    247 static void tls_site_lookup(SMTP_TLS_POLICY *tls, int *site_level,
    248 		              const char *site_name, const char *site_class)
    249 {
    250     const char *lookup;
    251 
    252     /*
    253      * Look up a non-default policy. In case of multiple lookup results, the
    254      * precedence order is a permutation of the TLS enforcement level order:
    255      * VERIFY, ENCRYPT, NONE, MAY, NOTFOUND. I.e. we override MAY with a more
    256      * specific policy including NONE, otherwise we choose the stronger
    257      * enforcement level.
    258      */
    259     if ((lookup = maps_find(tls_per_site, site_name, 0)) != 0) {
    260 	if (!strcasecmp(lookup, "NONE")) {
    261 	    /* NONE overrides MAY or NOTFOUND. */
    262 	    if (*site_level <= TLS_LEV_MAY)
    263 		*site_level = TLS_LEV_NONE;
    264 	} else if (!strcasecmp(lookup, "MAY")) {
    265 	    /* MAY overrides NOTFOUND but not NONE. */
    266 	    if (*site_level < TLS_LEV_NONE)
    267 		*site_level = TLS_LEV_MAY;
    268 	} else if (!strcasecmp(lookup, "MUST_NOPEERMATCH")) {
    269 	    if (*site_level < TLS_LEV_ENCRYPT)
    270 		*site_level = TLS_LEV_ENCRYPT;
    271 	} else if (!strcasecmp(lookup, "MUST")) {
    272 	    if (*site_level < TLS_LEV_VERIFY)
    273 		*site_level = TLS_LEV_VERIFY;
    274 	} else {
    275 	    msg_warn("%s: unknown TLS policy '%s' for %s %s",
    276 		     tls_per_site->title, lookup, site_class, site_name);
    277 	    MARK_INVALID(tls->why, site_level);
    278 	    return;
    279 	}
    280     } else if (tls_per_site->error) {
    281 	msg_warn("%s: %s \"%s\": per-site table lookup error",
    282 		 tls_per_site->title, site_class, site_name);
    283 	dsb_simple(tls->why, "4.3.0", "Temporary lookup error");
    284 	*site_level = TLS_LEV_INVALID;
    285 	return;
    286     }
    287     return;
    288 }
    289 
    290 /* tls_policy_lookup_one - look up destination TLS policy */
    291 
    292 static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level,
    293 				          const char *site_name,
    294 				          const char *site_class)
    295 {
    296     const char *lookup;
    297     char   *policy;
    298     char   *saved_policy = 0;
    299     char   *tok;
    300     char   *name;
    301     char   *val;
    302     static VSTRING *cbuf;
    303     char   *free_me = 0;
    304 
    305 #undef FREE_RETURN
    306 #define FREE_RETURN do { \
    307 	if (saved_policy) \
    308 	    myfree(saved_policy); \
    309 	if (free_me) \
    310 	    myfree(free_me); \
    311 	return; \
    312     } while (0)
    313 
    314 #define INVALID_RETURN(why, levelp) do { \
    315 	    MARK_INVALID((why), (levelp)); FREE_RETURN; } while (0)
    316 
    317 #define WHERE \
    318     STR(vstring_sprintf(cbuf, "%s, %s \"%s\"", \
    319 		tls_policy->title, site_class, site_name))
    320 
    321     if (cbuf == 0)
    322 	cbuf = vstring_alloc(10);
    323 
    324     if ((lookup = maps_find(tls_policy, site_name, 0)) == 0) {
    325 	if (tls_policy->error) {
    326 	    msg_warn("%s: policy table lookup error", WHERE);
    327 	    MARK_INVALID(tls->why, site_level);
    328 	}
    329 	return;
    330     }
    331     saved_policy = policy = mystrdup(lookup);
    332 
    333     if ((tok = mystrtokq(&policy, CHARS_COMMA_SP, CHARS_BRACE)) == 0) {
    334 	msg_warn("%s: invalid empty policy", WHERE);
    335 	INVALID_RETURN(tls->why, site_level);
    336     }
    337     *site_level = tls_level_lookup(tok);
    338     if (*site_level == TLS_LEV_INVALID) {
    339 	/* tls_level_lookup() logs no warning. */
    340 	msg_warn("%s: invalid security level \"%s\"", WHERE, tok);
    341 	INVALID_RETURN(tls->why, site_level);
    342     }
    343 
    344     /*
    345      * Warn about ignored attributes when TLS is disabled.
    346      */
    347     if (*site_level < TLS_LEV_MAY) {
    348 	while ((tok = mystrtokq(&policy, CHARS_COMMA_SP, CHARS_BRACE)) != 0)
    349 	    msg_warn("%s: ignoring attribute \"%s\" with TLS disabled",
    350 		     WHERE, tok);
    351 	FREE_RETURN;
    352     }
    353 
    354     /*
    355      * Errors in attributes may have security consequences, don't ignore
    356      * errors that can degrade security.
    357      *
    358      * Caution: normalize whitespace, to neutralize line break etc. characters
    359      * inside the value portion of { name = value }.
    360      */
    361     while ((tok = mystrtokq(&policy, CHARS_COMMA_SP, CHARS_BRACE)) != 0) {
    362 	const char *err;
    363 
    364 #define EXTPAR_OPT	(EXTPAR_FLAG_STRIP | EXTPAR_FLAG_NORMAL_WS)
    365 
    366 	if ((tok[0] == CHARS_BRACE[0]
    367 	     && (err = free_me = extpar(&tok, CHARS_BRACE, EXTPAR_OPT)) != 0)
    368 	    || (err = split_nameval(tok, &name, &val)) != 0) {
    369 	    msg_warn("%s: malformed attribute/value pair \"%s\": %s",
    370 		     WHERE, tok, err);
    371 	    INVALID_RETURN(tls->why, site_level);
    372 	}
    373 	/* Only one instance per policy. */
    374 	if (!strcasecmp(name, "ciphers")) {
    375 	    if (*val == 0) {
    376 		msg_warn("%s: attribute \"%s\" has empty value", WHERE, name);
    377 		INVALID_RETURN(tls->why, site_level);
    378 	    }
    379 	    if (tls->grade) {
    380 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    381 			 WHERE, name);
    382 		INVALID_RETURN(tls->why, site_level);
    383 	    }
    384 	    tls->grade = mystrdup(val);
    385 	    continue;
    386 	}
    387 	/* Only one instance per policy. */
    388 	if (!strcasecmp(name, "protocols")) {
    389 	    if (tls->protocols) {
    390 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    391 			 WHERE, name);
    392 		INVALID_RETURN(tls->why, site_level);
    393 	    }
    394 	    tls->protocols = mystrdup(val);
    395 	    continue;
    396 	}
    397 	/* Only one instance per policy. */
    398 	if (!strcasecmp(name, "servername")) {
    399 	    if (tls->sni) {
    400 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    401 			 WHERE, name);
    402 		INVALID_RETURN(tls->why, site_level);
    403 	    }
    404 	    if (valid_hostname(val, DONT_GRIPE))
    405 		tls->sni = mystrdup(val);
    406 	    else {
    407 		msg_warn("%s: \"%s=%s\" specifies an invalid hostname",
    408 			 WHERE, name, val);
    409 		INVALID_RETURN(tls->why, site_level);
    410 	    }
    411 	    continue;
    412 	}
    413 	/* Multiple instances per policy. */
    414 	if (!strcasecmp(name, "match")) {
    415 	    if (*val == 0) {
    416 		msg_warn("%s: attribute \"%s\" has empty value", WHERE, name);
    417 		INVALID_RETURN(tls->why, site_level);
    418 	    }
    419 	    switch (*site_level) {
    420 	    default:
    421 		msg_warn("%s: attribute \"%s\" invalid at security level "
    422 			 "\"%s\"", WHERE, name, policy_name(*site_level));
    423 		INVALID_RETURN(tls->why, site_level);
    424 		break;
    425 	    case TLS_LEV_FPRINT:
    426 		if (tls->matchargv == 0)
    427 		    tls->matchargv = argv_split(val, "|");
    428 		else
    429 		    argv_split_append(tls->matchargv, val, "|");
    430 		break;
    431 	    case TLS_LEV_VERIFY:
    432 	    case TLS_LEV_SECURE:
    433 		if (tls->matchargv == 0)
    434 		    tls->matchargv = argv_split(val, ":");
    435 		else
    436 		    argv_split_append(tls->matchargv, val, ":");
    437 		break;
    438 	    }
    439 	    continue;
    440 	}
    441 	/* Only one instance per policy. */
    442 	if (!strcasecmp(name, "exclude")) {
    443 	    if (tls->exclusions) {
    444 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    445 			 WHERE, name);
    446 		INVALID_RETURN(tls->why, site_level);
    447 	    }
    448 	    tls->exclusions = vstring_strcpy(vstring_alloc(10), val);
    449 	    continue;
    450 	}
    451 	/* Multiple instances per policy. */
    452 	if (!strcasecmp(name, "tafile")) {
    453 	    /* Only makes sense if we're using CA-based trust */
    454 	    if (!TLS_MUST_PKIX(*site_level)) {
    455 		msg_warn("%s: attribute \"%s\" invalid at security level"
    456 			 " \"%s\"", WHERE, name, policy_name(*site_level));
    457 		INVALID_RETURN(tls->why, site_level);
    458 	    }
    459 	    if (*val == 0) {
    460 		msg_warn("%s: attribute \"%s\" has empty value", WHERE, name);
    461 		INVALID_RETURN(tls->why, site_level);
    462 	    }
    463 	    if (!tls->dane)
    464 		tls->dane = tls_dane_alloc();
    465 	    if (!tls_dane_load_trustfile(tls->dane, val)) {
    466 		INVALID_RETURN(tls->why, site_level);
    467 	    }
    468 	    continue;
    469 	}
    470 	/* Last one wins. */
    471 	if (!strcasecmp(name, "connection_reuse")) {
    472 	    if (strcasecmp(val, "yes") == 0) {
    473 		tls->conn_reuse = 1;
    474 	    } else if (strcasecmp(val, "no") == 0) {
    475 		tls->conn_reuse = 0;
    476 	    } else {
    477 		msg_warn("%s: attribute \"%s\" has bad value: \"%s\"",
    478 			 WHERE, name, val);
    479 		INVALID_RETURN(tls->why, site_level);
    480 	    }
    481 	    continue;
    482 	}
    483 	/* Last one wins. */
    484 	if (!strcasecmp(name, "enable_rpk")) {
    485 	    /* Ultimately ignored at some security levels */
    486 	    if (strcasecmp(val, "yes") == 0) {
    487 		tls->enable_rpk = 1;
    488 	    } else if (strcasecmp(val, "no") == 0) {
    489 		tls->enable_rpk = 0;
    490 	    } else {
    491 		msg_warn("%s: attribute \"%s\" has bad value: \"%s\"",
    492 			 WHERE, name, val);
    493 		INVALID_RETURN(tls->why, site_level);
    494 	    }
    495 	    continue;
    496 	}
    497 	/* Only one instance per policy. */
    498 	if (!strcasecmp(name, EXT_POLICY_TTL)) {
    499 	    char   *end;
    500 	    long    lval;
    501 
    502 	    if (tls->ext_policy_ttl != EXT_POLICY_TTL_UNSET) {
    503 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    504 			 WHERE, name);
    505 		INVALID_RETURN(tls->why, site_level);
    506 	    }
    507 	    if (!alldig(val) || ((lval = sane_strtol(val, &end, 10)),
    508 				 ((tls->ext_policy_ttl = lval) != lval))
    509 		|| *end != 0) {
    510 		msg_warn("%s: attribute \"%s\" has a malformed value: \"%s\"",
    511 			 WHERE, name, val);
    512 		INVALID_RETURN(tls->why, site_level);
    513 	    }
    514 	    continue;
    515 	}
    516 	/* Only one instance per policy. */
    517 	if (!strcasecmp(name, EXT_POLICY_TYPE)) {
    518 	    if (tls->ext_policy_type) {
    519 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    520 			 WHERE, name);
    521 		INVALID_RETURN(tls->why, site_level);
    522 	    }
    523 	    if (!valid_tlsrpt_policy_type(val)) {
    524 		msg_warn("%s: attribute \"%s\" has an unexpected value: \"%s\"",
    525 			 WHERE, name, val);
    526 		INVALID_RETURN(tls->why, site_level);
    527 	    }
    528 	    tls->ext_policy_type = mystrdup(val);
    529 	    continue;
    530 	}
    531 	/* Only one instance per policy. */
    532 	if (!strcasecmp(name, EXT_POLICY_DOMAIN)) {
    533 	    if (tls->ext_policy_domain) {
    534 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    535 			 WHERE, name);
    536 		INVALID_RETURN(tls->why, site_level);
    537 	    }
    538 	    if (!valid_hostname(val, DO_GRIPE)) {
    539 		msg_warn("%s: attribute \"%s\" has a malformed value: \"%s\"",
    540 			 WHERE, name, val);
    541 		INVALID_RETURN(tls->why, site_level);
    542 	    }
    543 	    tls->ext_policy_domain = mystrdup(val);
    544 	    continue;
    545 	}
    546 	/* Multiple instances per policy are allowed. */
    547 	if (!strcasecmp(name, EXT_POLICY_STRING)) {
    548 	    if (tls->ext_policy_strings == 0)
    549 		tls->ext_policy_strings = argv_alloc(1);
    550 	    argv_add(tls->ext_policy_strings, val, (char *) 0);
    551 	    continue;
    552 	}
    553 	/* Multiple instances per policy are allowed. */
    554 	if (!strcasecmp(name, EXT_MX_HOST_PATTERN)) {
    555 	    if (tls->ext_mx_host_patterns == 0)
    556 		tls->ext_mx_host_patterns = argv_alloc(1);
    557 	    argv_add(tls->ext_mx_host_patterns, val, (char *) 0);
    558 	    continue;
    559 	}
    560 	/* Only one instance per policy. */
    561 	if (!strcasecmp(name, EXT_POLICY_FAILURE)) {
    562 	    if (tls->ext_policy_failure != 0) {
    563 		msg_warn("%s: attribute \"%s\" is specified multiple times",
    564 			 WHERE, name);
    565 		INVALID_RETURN(tls->why, site_level);
    566 	    }
    567 	    if (!valid_tlsrpt_policy_failure(val)) {
    568 		msg_warn("%s: attribute \"%s\" has an unexpected value: \"%s\"",
    569 			 WHERE, name, val);
    570 		INVALID_RETURN(tls->why, site_level);
    571 	    }
    572 	    tls->ext_policy_failure = mystrdup(val);
    573 	    continue;
    574 	}
    575 	msg_warn("%s: invalid attribute name: \"%s\"", WHERE, name);
    576 	INVALID_RETURN(tls->why, site_level);
    577     }
    578     if (tls->ext_policy_type == 0) {
    579 	if (tls->ext_policy_ttl != EXT_POLICY_TTL_UNSET
    580 	    || tls->ext_policy_strings
    581 	    || tls->ext_policy_domain || tls->ext_mx_host_patterns
    582 	    || tls->ext_policy_failure) {
    583 	    msg_warn("%s: built-in policy has unexpected attribute "
    584 		     "policy_ttl, policy_domain, policy_string, "
    585 		     "mx_host_pattern or policy_failure", WHERE);
    586 	    INVALID_RETURN(tls->why, site_level);
    587 	}
    588     }
    589     if (SAFE_FOR_SMTP_TLS_ENF_STS_MX_PAT(tls)) {
    590 	argv_truncate(tls->matchargv, 0);
    591 	argv_add(tls->matchargv, "hostname", (char *) 0);
    592     }
    593     FREE_RETURN;
    594 }
    595 
    596 /* tls_policy_lookup - look up destination TLS policy */
    597 
    598 static void tls_policy_lookup(SMTP_TLS_POLICY *tls, int *site_level,
    599 			              const char *site_name,
    600 			              const char *site_class)
    601 {
    602 
    603     /*
    604      * Only one lookup with [nexthop]:port, [nexthop] or nexthop:port These
    605      * are never the domain part of localpart@domain, rather they are
    606      * explicit nexthops from transport:nexthop, and match only the
    607      * corresponding policy. Parent domain matching (below) applies only to
    608      * sub-domains of the recipient domain.
    609      *
    610      * XXX UNIX-domain connections query with the pathname as destination.
    611      */
    612     if (!valid_utf8_hostname(var_smtputf8_enable, site_name, DONT_GRIPE)) {
    613 	tls_policy_lookup_one(tls, site_level, site_name, site_class);
    614 	return;
    615     }
    616     do {
    617 	tls_policy_lookup_one(tls, site_level, site_name, site_class);
    618     } while (*site_level == TLS_LEV_NOTFOUND
    619 	     && (site_name = strchr(site_name + 1, '.')) != 0);
    620 }
    621 
    622 /* load_tas - load one or more ta files */
    623 
    624 static int load_tas(TLS_DANE *dane, const char *files)
    625 {
    626     int     ret = 0;
    627     char   *save = mystrdup(files);
    628     char   *buf = save;
    629     char   *file;
    630 
    631     do {
    632 	if ((file = mystrtok(&buf, CHARS_COMMA_SP)) != 0)
    633 	    ret = tls_dane_load_trustfile(dane, file);
    634     } while (file && ret);
    635 
    636     myfree(save);
    637     return (ret);
    638 }
    639 
    640 /* set_cipher_grade - Set cipher grade and exclusions */
    641 
    642 static void set_cipher_grade(SMTP_TLS_POLICY *tls)
    643 {
    644     const char *mand_exclude = "";
    645     const char *also_exclude = "";
    646 
    647     /*
    648      * Use main.cf cipher level if no per-destination value specified. With
    649      * mandatory encryption at least encrypt, and with mandatory verification
    650      * at least authenticate!
    651      */
    652     switch (tls->level) {
    653     case TLS_LEV_INVALID:
    654     case TLS_LEV_NONE:
    655 	return;
    656 
    657     case TLS_LEV_MAY:
    658 	if (tls->grade == 0)
    659 	    tls->grade = mystrdup(var_smtp_tls_ciph);
    660 	break;
    661 
    662     case TLS_LEV_ENCRYPT:
    663 	if (tls->grade == 0)
    664 	    tls->grade = mystrdup(var_smtp_tls_mand_ciph);
    665 	mand_exclude = var_smtp_tls_mand_excl;
    666 	also_exclude = "eNULL";
    667 	break;
    668 
    669     case TLS_LEV_HALF_DANE:
    670     case TLS_LEV_DANE:
    671     case TLS_LEV_DANE_ONLY:
    672     case TLS_LEV_FPRINT:
    673     case TLS_LEV_VERIFY:
    674     case TLS_LEV_SECURE:
    675 	if (tls->grade == 0)
    676 	    tls->grade = mystrdup(var_smtp_tls_mand_ciph);
    677 	mand_exclude = var_smtp_tls_mand_excl;
    678 	also_exclude = "aNULL";
    679 	break;
    680     }
    681 
    682 #define ADD_EXCLUDE(vstr, str) \
    683     do { \
    684 	if (*(str)) \
    685 	    vstring_sprintf_append((vstr), "%s%s", \
    686 				   VSTRING_LEN(vstr) ? " " : "", (str)); \
    687     } while (0)
    688 
    689     /*
    690      * The "exclude" policy table attribute overrides main.cf exclusion
    691      * lists.
    692      */
    693     if (tls->exclusions == 0) {
    694 	tls->exclusions = vstring_alloc(10);
    695 	ADD_EXCLUDE(tls->exclusions, var_smtp_tls_excl_ciph);
    696 	ADD_EXCLUDE(tls->exclusions, mand_exclude);
    697     }
    698     ADD_EXCLUDE(tls->exclusions, also_exclude);
    699 }
    700 
    701 /* policy_create - create SMTP TLS policy cache object (ctable call-back) */
    702 
    703 static void *policy_create(const char *unused_key, void *context)
    704 {
    705     SMTP_ITERATOR *iter = (SMTP_ITERATOR *) context;
    706     int     site_level;
    707     const char *dest = STR(iter->dest);
    708     const char *host = STR(iter->host);
    709 
    710     /*
    711      * Prepare a pristine policy object.
    712      */
    713     SMTP_TLS_POLICY *tls = (SMTP_TLS_POLICY *) mymalloc(sizeof(*tls));
    714 
    715     smtp_tls_policy_init(tls, dsb_create());
    716     tls->conn_reuse = var_smtp_tls_conn_reuse;
    717     tls->enable_rpk = var_smtp_tls_enable_rpk;
    718 
    719     /*
    720      * Compute the per-site TLS enforcement level. For compatibility with the
    721      * original TLS patch, this algorithm is gives equal precedence to host
    722      * and next-hop policies.
    723      *
    724      * When "TLS-Required: no" is in effect, skip TLS policy lookup and limit
    725      * the security level to "may". Do not reset the security level after
    726      * policy lookup, as that would result in errors. For example, when TLSA
    727      * records are looked up for security level "dane", and then the security
    728      * level is reset to "may", the activation of those TLSA records will
    729      * fail.
    730      */
    731     tls->level = global_tls_level();
    732     site_level = TLS_LEV_NOTFOUND;
    733 
    734     if (STATE_TLS_NOT_REQUIRED(iter->parent)) {
    735 	if (msg_verbose)
    736 	    msg_info("%s: no tls policy lookup", __func__);
    737 	if (var_smtp_tls_wrappermode) {
    738 	    if (tls->level > TLS_LEV_ENCRYPT)
    739 		tls->level = TLS_LEV_ENCRYPT;
    740 	} else {
    741 	    if (tls->level > TLS_LEV_MAY)
    742 		tls->level = TLS_LEV_MAY;
    743 	}
    744     } else if (tls_policy) {
    745 	tls_policy_lookup(tls, &site_level, dest, "next-hop destination");
    746     } else if (tls_per_site) {
    747 	tls_site_lookup(tls, &site_level, dest, "next-hop destination");
    748 	if (site_level != TLS_LEV_INVALID
    749 	    && strcasecmp_utf8(dest, host) != 0)
    750 	    tls_site_lookup(tls, &site_level, host, "server hostname");
    751 
    752 	/*
    753 	 * Override a wild-card per-site policy with a more specific global
    754 	 * policy.
    755 	 *
    756 	 * With the original TLS patch, 1) a per-site ENCRYPT could not override
    757 	 * a global VERIFY, and 2) a combined per-site (NONE+MAY) policy
    758 	 * produced inconsistent results: it changed a global VERIFY into
    759 	 * NONE, while producing MAY with all weaker global policy settings.
    760 	 *
    761 	 * With the current implementation, a combined per-site (NONE+MAY)
    762 	 * consistently overrides global policy with NONE, and global policy
    763 	 * can override only a per-site MAY wildcard. That is, specific
    764 	 * policies consistently override wildcard policies, and
    765 	 * (non-wildcard) per-site policies consistently override global
    766 	 * policies.
    767 	 */
    768 	if (site_level == TLS_LEV_MAY && tls->level > TLS_LEV_MAY)
    769 	    site_level = tls->level;
    770     }
    771     switch (site_level) {
    772     default:
    773 	tls->level = site_level;
    774 	/* FALLTHROUGH */
    775     case TLS_LEV_NOTFOUND:
    776 	break;
    777     case TLS_LEV_INVALID:
    778 	tls->level = site_level;
    779 	return ((void *) tls);
    780     }
    781 
    782     /*
    783      * DANE initialization may change the security level to something else,
    784      * so do this early, so that we use the right level below.  Note that
    785      * "dane-only" changes to "dane" once we obtain the requisite TLSA
    786      * records.
    787      */
    788     if (TLS_DANE_BASED(tls->level))
    789 	dane_init(tls, iter);
    790     if (tls->level == TLS_LEV_INVALID)
    791 	return ((void *) tls);
    792 
    793     /*
    794      * Use main.cf protocols and SNI settings if not set in per-destination
    795      * table.
    796      */
    797     if (tls->level > TLS_LEV_NONE && tls->protocols == 0)
    798 	tls->protocols =
    799 	    mystrdup((tls->level == TLS_LEV_MAY) ?
    800 		     var_smtp_tls_proto : var_smtp_tls_mand_proto);
    801     if (tls->level > TLS_LEV_NONE && tls->sni == 0) {
    802 	if (!*var_smtp_tls_sni || valid_hostname(var_smtp_tls_sni, DONT_GRIPE))
    803 	    tls->sni = mystrdup(var_smtp_tls_sni);
    804 	else {
    805 	    msg_warn("\"%s = %s\" specifies an invalid hostname",
    806 		     VAR_LMTP_SMTP(TLS_SNI), var_smtp_tls_sni);
    807 	    MARK_INVALID(tls->why, &tls->level);
    808 	    return ((void *) tls);
    809 	}
    810     }
    811 
    812     /*
    813      * Compute cipher grade (if set in per-destination table, else
    814      * set_cipher() uses main.cf settings) and security level dependent
    815      * cipher exclusion list.
    816      */
    817     set_cipher_grade(tls);
    818 
    819 /*
    820  * Even when soliciting raw public keys, synthesize TLSA RRs that also match
    821  * certificates.  Though this is fragile, it maintains compatibility with
    822  * servers that never return RPKs.
    823  */
    824 #define DONT_SUPPRESS_CERT_MATCH	0
    825 
    826     /*
    827      * Use main.cf cert_match setting if not set in per-destination table.
    828      */
    829     switch (tls->level) {
    830     case TLS_LEV_INVALID:
    831     case TLS_LEV_NONE:
    832     case TLS_LEV_MAY:
    833     case TLS_LEV_ENCRYPT:
    834     case TLS_LEV_HALF_DANE:
    835     case TLS_LEV_DANE:
    836     case TLS_LEV_DANE_ONLY:
    837 	break;
    838     case TLS_LEV_FPRINT:
    839 	if (tls->dane == 0)
    840 	    tls->dane = tls_dane_alloc();
    841 	/* Process the specified fingerprint match patterns */
    842 	if (tls->matchargv) {
    843 	    int     i;
    844 
    845 	    for (i = 0; i < tls->matchargv->argc; ++i) {
    846 		tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH,
    847 					 tls->matchargv->argv[i], "",
    848 					 smtp_mode);
    849 	    }
    850 	} else {
    851 	    tls_dane_add_fpt_digests(tls->dane, DONT_SUPPRESS_CERT_MATCH,
    852 				     var_smtp_tls_fpt_cmatch, CHARS_COMMA_SP,
    853 				     smtp_mode);
    854 	}
    855 	if (tls->dane->tlsa == 0) {
    856 	    msg_warn("nexthop domain %s: configured at fingerprint "
    857 		     "security level, but with no fingerprints to match.",
    858 		     dest);
    859 	    MARK_INVALID(tls->why, &tls->level);
    860 	    return ((void *) tls);
    861 	}
    862 	break;
    863     case TLS_LEV_VERIFY:
    864     case TLS_LEV_SECURE:
    865 	if (tls->matchargv == 0)
    866 	    tls->matchargv =
    867 		argv_split(tls->level == TLS_LEV_VERIFY ?
    868 			   var_smtp_tls_vfy_cmatch : var_smtp_tls_sec_cmatch,
    869 			   CHARS_COMMA_SP ":");
    870 	if (*var_smtp_tls_tafile) {
    871 	    if (tls->dane == 0)
    872 		tls->dane = tls_dane_alloc();
    873 	    if (tls->dane->tlsa == 0
    874 		&& !load_tas(tls->dane, var_smtp_tls_tafile)) {
    875 		MARK_INVALID(tls->why, &tls->level);
    876 		return ((void *) tls);
    877 	    }
    878 	}
    879 	break;
    880     default:
    881 	msg_panic("unexpected TLS security level: %d", tls->level);
    882     }
    883 
    884     if (msg_verbose && tls->level != global_tls_level())
    885 	msg_info("%s TLS level: %s", "effective", policy_name(tls->level));
    886 
    887     return ((void *) tls);
    888 }
    889 
    890 /* policy_delete - free no longer cached policy (ctable call-back) */
    891 
    892 static void policy_delete(void *item, void *unused_context)
    893 {
    894     SMTP_TLS_POLICY *tls = (SMTP_TLS_POLICY *) item;
    895 
    896     if (tls->protocols)
    897 	myfree(tls->protocols);
    898     if (tls->sni)
    899 	myfree(tls->sni);
    900     if (tls->grade)
    901 	myfree(tls->grade);
    902     if (tls->exclusions)
    903 	vstring_free(tls->exclusions);
    904     if (tls->matchargv)
    905 	argv_free(tls->matchargv);
    906     if (tls->dane)
    907 	tls_dane_free(tls->dane);
    908     dsb_free(tls->why);
    909     if (tls->ext_policy_type)
    910 	myfree(tls->ext_policy_type);
    911     if (tls->ext_policy_domain)
    912 	myfree(tls->ext_policy_domain);
    913     if (tls->ext_policy_strings)
    914 	argv_free(tls->ext_policy_strings);
    915     if (tls->ext_mx_host_patterns)
    916 	argv_free(tls->ext_mx_host_patterns);
    917     if (tls->ext_policy_failure)
    918 	myfree(tls->ext_policy_failure);
    919 
    920     myfree((void *) tls);
    921 }
    922 
    923 /* smtp_tls_policy_cache_query - cached lookup of TLS policy */
    924 
    925 int     smtp_tls_policy_cache_query(DSN_BUF *why, SMTP_TLS_POLICY *tls,
    926 				            SMTP_ITERATOR *iter)
    927 {
    928     VSTRING *key;
    929 
    930     /*
    931      * Create an empty TLS Policy cache on the fly.
    932      */
    933     if (policy_cache == 0)
    934 	policy_cache =
    935 	    ctable_create(CACHE_SIZE, policy_create, policy_delete, (void *) 0);
    936 
    937     /*
    938      * Query the TLS Policy cache, with a search key that reflects our shared
    939      * values that also appear in other cache and table search keys.
    940      */
    941     key = vstring_alloc(100);
    942     smtp_key_prefix(key, ":", iter, SMTP_KEY_FLAG_CUR_NEXTHOP
    943 		    | SMTP_KEY_FLAG_HOSTNAME
    944 		    | SMTP_KEY_FLAG_PORT);
    945     ctable_newcontext(policy_cache, (void *) iter);
    946     *tls = *(SMTP_TLS_POLICY *) ctable_locate(policy_cache, STR(key));
    947     vstring_free(key);
    948 
    949     /*
    950      * Report errors. Both error and non-error results are cached. We must
    951      * therefore copy the cached DSN buffer content to the caller's buffer.
    952      */
    953     if (tls->level == TLS_LEV_INVALID) {
    954 	/* XXX Simplify this by implementing a "copy" primitive. */
    955 	dsb_update(why,
    956 		   STR(tls->why->status), STR(tls->why->action),
    957 		   STR(tls->why->mtype), STR(tls->why->mname),
    958 		   STR(tls->why->dtype), STR(tls->why->dtext),
    959 		   "%s", STR(tls->why->reason));
    960 	return (0);
    961     } else {
    962 	return (1);
    963     }
    964 }
    965 
    966 /* smtp_tls_policy_cache_flush - flush TLS policy cache */
    967 
    968 void    smtp_tls_policy_cache_flush(void)
    969 {
    970     if (policy_cache != 0) {
    971 	ctable_free(policy_cache);
    972 	policy_cache = 0;
    973     }
    974 }
    975 
    976 /* global_tls_level - parse and cache var_smtp_tls_level */
    977 
    978 static int global_tls_level(void)
    979 {
    980     static int l = TLS_LEV_NOTFOUND;
    981 
    982     if (l != TLS_LEV_NOTFOUND)
    983 	return l;
    984 
    985     /*
    986      * Compute the global TLS policy. This is the default policy level when
    987      * no per-site policy exists. It also is used to override a wild-card
    988      * per-site policy.
    989      *
    990      * We require that the global level is valid on startup.
    991      */
    992     if (*var_smtp_tls_level) {
    993 	if ((l = tls_level_lookup(var_smtp_tls_level)) == TLS_LEV_INVALID)
    994 	    msg_fatal("invalid tls security level: \"%s\"", var_smtp_tls_level);
    995     } else if (var_smtp_enforce_tls)
    996 	l = var_smtp_tls_enforce_peername ? TLS_LEV_VERIFY : TLS_LEV_ENCRYPT;
    997     else
    998 	l = var_smtp_use_tls ? TLS_LEV_MAY : TLS_LEV_NONE;
    999 
   1000     if (msg_verbose)
   1001 	msg_info("%s TLS level: %s", "global", policy_name(l));
   1002 
   1003     return l;
   1004 }
   1005 
   1006 #define NONDANE_CONFIG	0		/* Administrator's fault */
   1007 #define NONDANE_DEST	1		/* Remote server's fault */
   1008 #define DANE_CANTAUTH	2		/* Remote server's fault */
   1009 
   1010 static void PRINTFLIKE(4, 5) dane_incompat(SMTP_TLS_POLICY *tls,
   1011 					           SMTP_ITERATOR *iter,
   1012 					           int errtype,
   1013 					           const char *fmt,...)
   1014 {
   1015     va_list ap;
   1016 
   1017     va_start(ap, fmt);
   1018     if (tls->level == TLS_LEV_DANE) {
   1019 	tls->level = (errtype == DANE_CANTAUTH) ? TLS_LEV_ENCRYPT : TLS_LEV_MAY;
   1020 	if (errtype == NONDANE_CONFIG)
   1021 	    vmsg_warn(fmt, ap);
   1022 	else if (msg_verbose)
   1023 	    vmsg_info(fmt, ap);
   1024     } else {					/* dane-only */
   1025 	if (errtype == NONDANE_CONFIG) {
   1026 	    vmsg_warn(fmt, ap);
   1027 	    MARK_INVALID(tls->why, &tls->level);
   1028 	} else {
   1029 	    tls->level = TLS_LEV_INVALID;
   1030 	    vdsb_simple(tls->why, "4.7.5", fmt, ap);
   1031 	}
   1032     }
   1033     va_end(ap);
   1034 }
   1035 
   1036 /* dane_init - special initialization for "dane" security level */
   1037 
   1038 static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
   1039 {
   1040     TLS_DANE *dane;
   1041 
   1042     if (!iter->port) {
   1043 	msg_warn("%s: the \"dane\" security level is invalid for delivery via"
   1044 		 " unix-domain sockets", STR(iter->dest));
   1045 	MARK_INVALID(tls->why, &tls->level);
   1046 	return;
   1047     }
   1048     if (!tls_dane_avail()) {
   1049 	dane_incompat(tls, iter, NONDANE_CONFIG,
   1050 		      "%s: %s configured, but no requisite library support",
   1051 		      STR(iter->dest), policy_name(tls->level));
   1052 	return;
   1053     }
   1054     if (!(smtp_host_lookup_mask & SMTP_HOST_FLAG_DNS)
   1055 	|| smtp_dns_support != SMTP_DNS_DNSSEC) {
   1056 	dane_incompat(tls, iter, NONDANE_CONFIG,
   1057 		      "%s: %s configured with dnssec lookups disabled",
   1058 		      STR(iter->dest), policy_name(tls->level));
   1059 	return;
   1060     }
   1061 
   1062     /*
   1063      * If we ignore MX lookup errors, we also ignore DNSSEC security problems
   1064      * and thus avoid any reasonable expectation that we get the right DANE
   1065      * key material.
   1066      */
   1067     if (smtp_mode && var_ign_mx_lookup_err) {
   1068 	dane_incompat(tls, iter, NONDANE_CONFIG,
   1069 		      "%s: %s configured with MX lookup errors ignored",
   1070 		      STR(iter->dest), policy_name(tls->level));
   1071 	return;
   1072     }
   1073 
   1074     /*
   1075      * This is not optional, code in tls_dane.c assumes that the nexthop
   1076      * qname is already an fqdn.  If we're using these flags to go from qname
   1077      * to rname, the assumption is invalid.  Likewise we cannot add the qname
   1078      * to certificate name checks, ...
   1079      */
   1080     if (smtp_dns_res_opt & (RES_DEFNAMES | RES_DNSRCH)) {
   1081 	dane_incompat(tls, iter, NONDANE_CONFIG,
   1082 		      "%s: dns resolver options incompatible with %s TLS",
   1083 		      STR(iter->dest), policy_name(tls->level));
   1084 	return;
   1085     }
   1086 
   1087     /*
   1088      * When the MX name is present and insecure, DANE may not apply, we then
   1089      * either fail if DANE is mandatory or use regular opportunistic TLS if
   1090      * the insecure MX level is "may".
   1091      */
   1092     if (iter->mx && !iter->mx->dnssec_valid
   1093 	&& (tls->level == TLS_LEV_DANE_ONLY ||
   1094 	    smtp_tls_insecure_mx_policy <= TLS_LEV_MAY)) {
   1095 	dane_incompat(tls, iter, NONDANE_DEST, "non DNSSEC destination");
   1096 	return;
   1097     }
   1098     /* When TLSA lookups fail, we defer the message */
   1099     if ((dane = tls_dane_resolve(iter->port, "tcp", iter->rr,
   1100 				 var_smtp_tls_force_tlsa)) == 0) {
   1101 	tls->level = TLS_LEV_INVALID;
   1102 	dsb_simple(tls->why, "4.7.5", "TLSA lookup error for %s:%u",
   1103 		   STR(iter->host), ntohs(iter->port));
   1104 	return;
   1105     }
   1106     if (tls_dane_notfound(dane)) {
   1107 	dane_incompat(tls, iter, NONDANE_DEST, "no TLSA records found");
   1108 	tls_dane_free(dane);
   1109 	return;
   1110     }
   1111 
   1112     /*
   1113      * Some TLSA records found, but none usable, per
   1114      *
   1115      * https://tools.ietf.org/html/draft-ietf-dane-srv-02#section-4
   1116      *
   1117      * we MUST use TLS, and SHALL use full PKIX certificate checks.  The latter
   1118      * would be unwise for SMTP: no human present to "click ok" and risk of
   1119      * non-delivery in most cases exceeds risk of interception.
   1120      *
   1121      * We also have a form of Goedel's incompleteness theorem in play: any list
   1122      * of public root CA certs is either incomplete or inconsistent (for any
   1123      * given verifier some of the CAs are surely not trustworthy).
   1124      */
   1125     if (tls_dane_unusable(dane)) {
   1126 	dane_incompat(tls, iter, DANE_CANTAUTH, "TLSA records unusable");
   1127 	tls_dane_free(dane);
   1128 	return;
   1129     }
   1130 
   1131     /*
   1132      * Perhaps downgrade to "encrypt" if MX is insecure.
   1133      */
   1134     if (iter->mx && !iter->mx->dnssec_valid) {
   1135 	if (smtp_tls_insecure_mx_policy == TLS_LEV_ENCRYPT) {
   1136 	    dane_incompat(tls, iter, DANE_CANTAUTH,
   1137 			  "Verification not possible, MX RRset is insecure");
   1138 	    tls_dane_free(dane);
   1139 	    return;
   1140 	}
   1141 	if (tls->level != TLS_LEV_DANE
   1142 	    || smtp_tls_insecure_mx_policy != TLS_LEV_DANE)
   1143 	    msg_panic("wrong state for insecure MX host DANE policy");
   1144 
   1145 	/* For correct logging in tls_client_start() */
   1146 	tls->level = TLS_LEV_HALF_DANE;
   1147     }
   1148 
   1149     /*
   1150      * With DANE trust anchors, peername matching is not configurable.
   1151      */
   1152     if (dane->tlsa != 0) {
   1153 	tls->matchargv = argv_alloc(2);
   1154 	argv_add(tls->matchargv, dane->base_domain, ARGV_END);
   1155 	if (iter->mx) {
   1156 	    if (strcmp(iter->mx->qname, iter->mx->rname) == 0)
   1157 		argv_add(tls->matchargv, iter->mx->qname, ARGV_END);
   1158 	    else
   1159 		argv_add(tls->matchargv, iter->mx->rname,
   1160 			 iter->mx->qname, ARGV_END);
   1161 	}
   1162     } else
   1163 	msg_panic("empty DANE match list");
   1164     tls->dane = dane;
   1165     return;
   1166 }
   1167 
   1168 #endif
   1169