86 #include <netinet/in.h>
87 #include <arpa/inet.h>
91 #ifdef STRCASECMP_IN_STRINGS_H
119 #define CACHE_SIZE 20
120 static CTABLE *policy_cache;
122 static int global_tls_level(
void);
125 static MAPS *tls_policy;
126 static MAPS *tls_per_site;
130 void smtp_tls_list_init(
void)
138 msg_warn(
"%s ignored when %s is not empty.",
152 static const char *policy_name(
int tls_level)
161 #define MARK_INVALID(why, levelp) do { \
162 dsb_simple((why), "4.7.5", "client TLS configuration problem"); \
163 *(levelp) = TLS_LEV_INVALID; } while (0)
167 static void tls_site_lookup(SMTP_TLS_POLICY *tls,
int *site_level,
168 const char *site_name,
const char *site_class)
179 if ((lookup =
maps_find(tls_per_site, site_name, 0)) != 0) {
188 }
else if (!
strcasecmp(lookup,
"MUST_NOPEERMATCH")) {
195 msg_warn(
"%s: unknown TLS policy '%s' for %s %s",
196 tls_per_site->
title, lookup, site_class, site_name);
197 MARK_INVALID(tls->why, site_level);
200 }
else if (tls_per_site->
error) {
201 msg_warn(
"%s: %s \"%s\": per-site table lookup error",
202 tls_per_site->
title, site_class, site_name);
203 dsb_simple(tls->why,
"4.3.0",
"Temporary lookup error");
212 static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls,
int *site_level,
213 const char *site_name,
214 const char *site_class)
226 #define FREE_RETURN do { myfree(saved_policy); return; } while (0)
228 #define INVALID_RETURN(why, levelp) do { \
229 MARK_INVALID((why), (levelp)); FREE_RETURN; } while (0)
232 STR(vstring_sprintf(cbuf, "%s, %s \"%s\"", \
233 tls_policy->title, site_class, site_name))
238 if ((lookup =
maps_find(tls_policy, site_name, 0)) == 0) {
239 if (tls_policy->
error) {
240 msg_warn(
"%s: policy table lookup error", WHERE);
241 MARK_INVALID(tls->why, site_level);
245 saved_policy = policy =
mystrdup(lookup);
248 msg_warn(
"%s: invalid empty policy", WHERE);
249 INVALID_RETURN(tls->why, site_level);
254 msg_warn(
"%s: invalid security level \"%s\"", WHERE, tok);
255 INVALID_RETURN(tls->why, site_level);
263 msg_warn(
"%s: ignoring attribute \"%s\" with TLS disabled",
274 msg_warn(
"%s: malformed attribute/value pair \"%s\": %s",
276 INVALID_RETURN(tls->why, site_level);
281 msg_warn(
"%s: attribute \"%s\" has empty value", WHERE, name);
282 INVALID_RETURN(tls->why, site_level);
285 msg_warn(
"%s: attribute \"%s\" is specified multiple times",
287 INVALID_RETURN(tls->why, site_level);
294 if (tls->protocols) {
295 msg_warn(
"%s: attribute \"%s\" is specified multiple times",
297 INVALID_RETURN(tls->why, site_level);
305 msg_warn(
"%s: attribute \"%s\" has empty value", WHERE, name);
306 INVALID_RETURN(tls->why, site_level);
308 switch (*site_level) {
310 msg_warn(
"%s: attribute \"%s\" invalid at security level "
311 "\"%s\"", WHERE, name, policy_name(*site_level));
312 INVALID_RETURN(tls->why, site_level);
316 tls->dane = tls_dane_alloc();
317 tls_dane_add_ee_digests(tls->dane,
322 if (tls->matchargv == 0)
332 if (tls->exclusions) {
333 msg_warn(
"%s: attribute \"%s\" is specified multiple times",
335 INVALID_RETURN(tls->why, site_level);
344 msg_warn(
"%s: attribute \"%s\" invalid at security level"
345 " \"%s\"", WHERE, name, policy_name(*site_level));
346 INVALID_RETURN(tls->why, site_level);
349 msg_warn(
"%s: attribute \"%s\" has empty value", WHERE, name);
350 INVALID_RETURN(tls->why, site_level);
353 tls->dane = tls_dane_alloc();
354 if (!tls_dane_load_trustfile(tls->dane, val)) {
355 INVALID_RETURN(tls->why, site_level);
359 msg_warn(
"%s: invalid attribute name: \"%s\"", WHERE, name);
360 INVALID_RETURN(tls->why, site_level);
368 static void tls_policy_lookup(SMTP_TLS_POLICY *tls,
int *site_level,
369 const char *site_name,
370 const char *site_class)
383 tls_policy_lookup_one(tls, site_level, site_name, site_class);
387 tls_policy_lookup_one(tls, site_level, site_name, site_class);
389 && (site_name = strchr(site_name + 1,
'.')) != 0);
394 static int load_tas(TLS_DANE *dane,
const char *files)
403 ret = tls_dane_load_trustfile(dane, file);
404 }
while (file && ret);
412 static void set_cipher_grade(SMTP_TLS_POLICY *tls)
414 const char *mand_exclude =
"";
415 const char *also_exclude =
"";
422 switch (tls->level) {
436 also_exclude =
"eNULL";
448 also_exclude =
"aNULL";
452 #define ADD_EXCLUDE(vstr, str) \
455 vstring_sprintf_append((vstr), "%s%s", \
456 VSTRING_LEN(vstr) ? " " : "", (str)); \
463 if (tls->exclusions == 0) {
466 ADD_EXCLUDE(tls->exclusions, mand_exclude);
468 ADD_EXCLUDE(tls->exclusions, also_exclude);
473 static void *policy_create(
const char *unused_key,
void *context)
477 const char *dest =
STR(iter->
dest);
478 const char *host =
STR(iter->
host);
483 SMTP_TLS_POLICY *tls = (SMTP_TLS_POLICY *)
mymalloc(
sizeof(*tls));
492 tls->level = global_tls_level();
496 tls_policy_lookup(tls, &site_level, dest,
"next-hop destination");
497 }
else if (tls_per_site) {
498 tls_site_lookup(tls, &site_level, dest,
"next-hop destination");
501 tls_site_lookup(tls, &site_level, host,
"server hostname");
520 site_level = tls->level;
522 switch (site_level) {
524 tls->level = site_level;
529 tls->level = site_level;
530 return ((
void *) tls);
540 dane_init(tls, iter);
542 return ((
void *) tls);
557 set_cipher_grade(tls);
562 switch (tls->level) {
573 tls->dane = tls_dane_alloc();
574 if (!TLS_DANE_HASEE(tls->dane)) {
577 if (!TLS_DANE_HASEE(tls->dane)) {
578 msg_warn(
"nexthop domain %s: configured at fingerprint "
579 "security level, but with no fingerprints to match.",
581 MARK_INVALID(tls->why, &tls->level);
582 return ((
void *) tls);
588 if (tls->matchargv == 0)
595 tls->dane = tls_dane_alloc();
596 if (!TLS_DANE_HASTA(tls->dane)
598 MARK_INVALID(tls->why, &tls->level);
599 return ((
void *) tls);
604 msg_panic(
"unexpected TLS security level: %d", tls->level);
607 if (
msg_verbose && tls->level != global_tls_level())
608 msg_info(
"%s TLS level: %s",
"effective", policy_name(tls->level));
610 return ((
void *) tls);
615 static void policy_delete(
void *item,
void *unused_context)
617 SMTP_TLS_POLICY *tls = (SMTP_TLS_POLICY *) item;
628 tls_dane_free(tls->dane);
636 int smtp_tls_policy_cache_query(
DSN_BUF *why, SMTP_TLS_POLICY *tls,
644 if (policy_cache == 0)
646 ctable_create(CACHE_SIZE, policy_create, policy_delete, (
void *) 0);
667 STR(tls->why->status),
STR(tls->why->action),
668 STR(tls->why->mtype),
STR(tls->why->mname),
669 STR(tls->why->dtype),
STR(tls->why->dtext),
670 "%s",
STR(tls->why->reason));
679 void smtp_tls_policy_cache_flush(
void)
681 if (policy_cache != 0) {
689 static int global_tls_level(
void)
712 msg_info(
"%s TLS level: %s",
"global", policy_name(l));
717 #define NONDANE_CONFIG 0
718 #define NONDANE_DEST 1
719 #define DANE_CANTAUTH 2
721 static void PRINTFLIKE(4, 5) dane_incompat(SMTP_TLS_POLICY *tls,
731 if (errtype == NONDANE_CONFIG)
736 if (errtype == NONDANE_CONFIG) {
738 MARK_INVALID(tls->why, &tls->level);
749 static void dane_init(SMTP_TLS_POLICY *tls,
SMTP_ITERATOR *iter)
754 msg_warn(
"%s: the \"dane\" security level is invalid for delivery via"
755 " unix-domain sockets",
STR(iter->
dest));
756 MARK_INVALID(tls->why, &tls->level);
759 if (!tls_dane_avail()) {
760 dane_incompat(tls, iter, NONDANE_CONFIG,
761 "%s: %s configured, but no requisite library support",
762 STR(iter->
dest), policy_name(tls->level));
767 dane_incompat(tls, iter, NONDANE_CONFIG,
768 "%s: %s configured with dnssec lookups disabled",
769 STR(iter->
dest), policy_name(tls->level));
779 dane_incompat(tls, iter, NONDANE_CONFIG,
780 "%s: %s configured with MX lookup errors ignored",
781 STR(iter->
dest), policy_name(tls->level));
792 dane_incompat(tls, iter, NONDANE_CONFIG,
793 "%s: dns resolver options incompatible with %s TLS",
794 STR(iter->
dest), policy_name(tls->level));
806 dane_incompat(tls, iter, NONDANE_DEST,
"non DNSSEC destination");
810 if ((dane = tls_dane_resolve(iter->
port,
"tcp", iter->
rr,
813 dsb_simple(tls->why,
"4.7.5",
"TLSA lookup error for %s:%u",
817 if (tls_dane_notfound(dane)) {
818 dane_incompat(tls, iter, NONDANE_DEST,
"no TLSA records found");
836 if (tls_dane_unusable(dane)) {
837 dane_incompat(tls, iter, DANE_CANTAUTH,
"TLSA records unusable");
847 dane_incompat(tls, iter, DANE_CANTAUTH,
848 "Verification not possible, MX RRset is insecure");
854 msg_panic(
"wrong state for insecure MX host DANE policy");
863 if (TLS_DANE_HASTA(dane)) {
873 }
else if (!TLS_DANE_HASEE(dane))
#define SMTP_KEY_FLAG_HOSTNAME
#define TLS_LEV_DANE_ONLY
DSN_BUF * dsb_create(void)
char * mystrdup(const char *str)
#define TLS_LEV_HALF_DANE
char * var_smtp_tls_per_site
ARGV * argv_free(ARGV *argvp)
const char * str_tls_level(int)
NORETURN msg_panic(const char *fmt,...)
DSN_BUF * dsb_update(DSN_BUF *dsb, const char *status, const char *action, const char *mtype, const char *mname, const char *dtype, const char *dtext, const char *format,...)
char * var_smtp_tls_mand_excl
bool var_ign_mx_lookup_err
#define TLS_DANE_BASED(l)
char * var_smtp_tls_level
const void * ctable_locate(CTABLE *cache, const char *key)
void dsb_free(DSN_BUF *dsb)
DSN_BUF * vdsb_simple(DSN_BUF *dsb, const char *status, const char *format, va_list ap)
void argv_add(ARGV *argvp,...)
int smtp_host_lookup_mask
char * var_smtp_tls_policy
#define DICT_FLAG_UTF8_REQUEST
#define strcasecmp_utf8(s1, s2)
char * mystrtok(char **src, const char *sep)
ARGV * argv_alloc(ssize_t len)
const char * split_nameval(char *buf, char **name, char **value)
#define DICT_FLAG_FOLD_FIX
char * var_smtp_tls_vfy_cmatch
#define SMTP_HOST_FLAG_DNS
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
void ctable_newcontext(CTABLE *cache, void *context)
int valid_utf8_hostname(int enable_utf8, const char *name, int gripe)
char * var_smtp_tls_proto
bool var_smtp_tls_force_tlsa
MAPS * maps_create(const char *title, const char *map_names, int dict_flags)
#define SMTP_KEY_FLAG_PORT
char * var_smtp_tls_tafile
void msg_warn(const char *fmt,...)
CTABLE * ctable_create(ssize_t limit, CTABLE_CREATE_FN create, CTABLE_DELETE_FN delete, void *context)
VSTRING * vstring_alloc(ssize_t len)
unsigned smtp_dns_res_opt
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
char * var_smtp_tls_excl_ciph
void vmsg_warn(const char *fmt, va_list ap)
NORETURN msg_fatal(const char *fmt,...)
bool var_smtp_tls_enforce_peername
int tls_level_lookup(const char *)
ARGV * argv_split(const char *, const char *)
char * var_smtp_tls_fpt_cmatch
int strcasecmp(const char *s1, const char *s2)
#define SMTP_KEY_FLAG_NEXTHOP
void vmsg_info(const char *fmt, va_list ap)
VSTRING * vstring_free(VSTRING *vp)
char * var_smtp_tls_fpt_dgst
unsigned int dnssec_valid
ARGV * argv_split_append(ARGV *, const char *, const char *)
bool var_smtp_enforce_tls
char * var_smtp_tls_mand_proto
char * var_smtp_tls_sec_cmatch
void ctable_free(CTABLE *cache)
const char * maps_find(MAPS *maps, const char *name, int flags)
char * smtp_key_prefix(VSTRING *, const char *, SMTP_ITERATOR *, int)
char * var_smtp_tls_mand_ciph
void * mymalloc(ssize_t len)
void msg_info(const char *fmt,...)