2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-31 06:05:37 +00:00

postfix-3.1-20160104

This commit is contained in:
Wietse Venema
2016-01-04 00:00:00 -05:00
committed by Viktor Dukhovni
parent bbddef305d
commit adbd9510a1
9 changed files with 268 additions and 38 deletions

View File

@@ -22096,3 +22096,10 @@ Apologies for any names omitted.
src/smtp/smtp-only, src/smtp/smtp.c, src/smtp/smtp.h,
src/smtp/smtp_addr.c, src/smtp/smtp_params.c,
src/smtp/smtp_tls_policy.c, src/tls/tls.h, src/tls/tls_client.c.
20160104
Cleanup: distinct TLS levels for "full" DANE and for DANE
with insecure MX records. Viktor Dukhovni. Files:
posttls-finger/posttls-finger.c, smtp/smtp_tls_policy.c,
tls/tls.h, tls/tls_client.c, tls/tls_level.c.

View File

@@ -2,12 +2,6 @@ Wish list:
Things to do before the stable release:
Viktor's bitrot patches.
Not: SMTPUTF8 auto-conversion of lookups/matches.
---------------------end of Postfix 3.1.0 todo list
Spell-check, double-word check, and HTML validator check.
Disable -DSNAPSHOT and -DNONPROD in makedefs.

View File

@@ -1333,3 +1333,201 @@ unversioned
versioned
DNSWL
cbc
ADDRCPT
Ae
AES
Arnt
ASLR
authz
authzTo
autodetect
autodetection
backend
backends
backscatter
BACKSCATTER
balancer
byname
cakey
casefold
casefolding
caseless
Centos
CFLAGS
changetype
characterset
CHGFROM
cmusaslsecretMECHNAME
CNNIC
concurrencies
cryptanalytic
cryptographic
cryptographically
customizations
cyrus
DB's
de
decrypts
deinstall
dev
DMARC
EAI
EDH
encodings
ENHANCEDSTATUSCODES
environ
esac
etcetera
exchanger
executables
Executables
filename
filenames
fPIC
fred
genrsa
GSSAPI
Gulbrandsen
Gulbrandsen's
helpdesk
icu
icuuc
imap
infeasible
interoperability
interoperable
invasiveness
jetmore
Jetmore
KERBEROS
kern
launchd
ldapadd
ldapdb
ldapmodify
libc
libicu
liblogin
libplain
libsasl
libsasl's
login
Login
LOGIN
logins
lookup
Lookup
lookups
Makefile
makefiles
Makefiles
mary
matcher
maxprocperuid
mdash
MECHNAME
Memcache
Mf
milter
Milter
misconfigured
multi
mux
namen
nameserver
nameserver's
ndash
ne
newkey
nicke's
NOOP
nroff
ntlm
NTLM
Ok
opendkim
OpenDKIM
OpenDMARC
optimizations
ou
outform
pam
param
pathname
pathnames
performant
pipelined
pipelining
PIPELINING
pipemap
Plaintext
postfix
Postfix
POSTSCREEN
Pre
prepend
PREPEND
PROTO
proxyuser
randmap
rc
REJ
REPLBODY
resultn
Rhein
RHEL
rimap
rpath
RPATH
runpath
runtime
SASLv
scalable
scanf
sha
SHA
SMFIC
SMFIP
SMFIR
SMTP
smtputf
SMTPUTF
socketdir
socketmap
startup
subdirectory
subnet
subnetworks
substring
sys
SYS
sysconfig
TCP
testsaslauthd
Timo
tradeoff
typechecks
typen
ulimit
undeliverable
Unencrypted
unionmap
uniqueIdentifier
unpatched
untrusted
Untrusted
unvailable
uri
userPassword
UTF
uucp
UUCP
wakeup
Westchester
whitespace
Wl
xFFFFFFFF
xn
xyy
xzz
ymd

View File

@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
#define MAIL_RELEASE_DATE "20160103"
#define MAIL_RELEASE_DATE "20160104"
#define MAIL_VERSION_NUMBER "3.1"
#ifdef SNAPSHOT

View File

@@ -1262,9 +1262,8 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
HNAME(addr), ntohs(state->port));
level = TLS_LEV_INVALID;
} else if (tls_dane_notfound(state->ddane)
|| tls_dane_unusable(state->ddane)
|| level == TLS_LEV_DANE_ONLY) {
if (msg_verbose)
|| tls_dane_unusable(state->ddane)) {
if (msg_verbose || level == TLS_LEV_DANE_ONLY)
msg_info("no %sTLSA records found, "
"resorting to \"secure\"",
tls_dane_unusable(state->ddane) ?
@@ -1287,7 +1286,7 @@ static int dane_host_level(STATE *state, DNS_RR *addr)
if (state->mx) {
if (!state->mx->dnssec_valid) {
msg_info("MX RRset insecure: log verified as trusted");
state->ddane->flags |= TLS_DANE_FLAG_MXINSEC;
level = TLS_LEV_HALF_DANE;
}
if (strcmp(state->mx->qname, state->mx->rname) == 0)
argv_add(state->match, state->mx->qname, ARGV_END);

View File

@@ -436,6 +436,7 @@ static void set_cipher_grade(SMTP_TLS_POLICY *tls)
also_exclude = "eNULL";
break;
case TLS_LEV_HALF_DANE:
case TLS_LEV_DANE:
case TLS_LEV_DANE_ONLY:
case TLS_LEV_FPRINT:
@@ -563,6 +564,7 @@ static void *policy_create(const char *unused_key, void *context)
case TLS_LEV_NONE:
case TLS_LEV_MAY:
case TLS_LEV_ENCRYPT:
case TLS_LEV_HALF_DANE:
case TLS_LEV_DANE:
case TLS_LEV_DANE_ONLY:
break;
@@ -792,9 +794,15 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
STR(iter->dest), policy_name(tls->level));
return;
}
/* When the MX name is present and insecure, DANE may not apply. */
/*
* When the MX name is present and insecure, DANE may not apply, we then
* either fail if DANE is mandatory or use regular opportunistic TLS if
* the insecure MX level is "may".
*/
if (iter->mx && !iter->mx->dnssec_valid
&& smtp_tls_insecure_mx_policy <= TLS_LEV_MAY) {
&& (tls->level == TLS_LEV_DANE_ONLY ||
smtp_tls_insecure_mx_policy <= TLS_LEV_MAY)) {
dane_incompat(tls, iter, NONDANE_DEST, "non DNSSEC destination");
return;
}
@@ -841,8 +849,12 @@ static void dane_init(SMTP_TLS_POLICY *tls, SMTP_ITERATOR *iter)
tls_dane_free(dane);
return;
}
if (tls->level != TLS_LEV_DANE
|| smtp_tls_insecure_mx_policy != TLS_LEV_DANE)
msg_panic("wrong state for insecure MX host DANE policy");
/* For correct logging in tls_client_start() */
dane->flags |= TLS_DANE_FLAG_MXINSEC;
tls->level = TLS_LEV_HALF_DANE;
}
/*

View File

@@ -44,22 +44,23 @@
#define TLS_LEV_MAY 1 /* wildcard */
#define TLS_LEV_ENCRYPT 2 /* encrypted connection */
#define TLS_LEV_FPRINT 3 /* "peer" CA-less verification */
#define TLS_LEV_DANE 4 /* Opportunistic TLSA policy */
#define TLS_LEV_DANE_ONLY 5 /* Required TLSA policy */
#define TLS_LEV_VERIFY 6 /* certificate verified */
#define TLS_LEV_SECURE 7 /* "secure" verification */
#define TLS_LEV_HALF_DANE 4 /* DANE TLSA MX host, insecure MX RR */
#define TLS_LEV_DANE 5 /* Opportunistic TLSA policy */
#define TLS_LEV_DANE_ONLY 6 /* Required TLSA policy */
#define TLS_LEV_VERIFY 7 /* certificate verified */
#define TLS_LEV_SECURE 8 /* "secure" verification */
#define TLS_REQUIRED(l) ((l) > TLS_LEV_MAY)
#define TLS_MUST_MATCH(l) ((l) > TLS_LEV_ENCRYPT)
#define TLS_MUST_TRUST(l) ((l) >= TLS_LEV_DANE)
#define TLS_MUST_TRUST(l) ((l) >= TLS_LEV_HALF_DANE)
#define TLS_MUST_PKIX(l) ((l) >= TLS_LEV_VERIFY)
#define TLS_OPPORTUNISTIC(l) ((l) == TLS_LEV_MAY || (l) == TLS_LEV_DANE)
#define TLS_DANE_BASED(l) ((l) == TLS_LEV_DANE || (l) == TLS_LEV_DANE_ONLY)
#define TLS_DANE_BASED(l) \
((l) >= TLS_LEV_HALF_DANE && (l) <= TLS_LEV_DANE_ONLY)
#define TLS_NEVER_SECURED(l) ((l) == TLS_LEV_HALF_DANE)
extern const NAME_CODE tls_level_table[];
#define tls_level_lookup(s) name_code(tls_level_table, NAME_CODE_FLAG_NONE, (s))
#define str_tls_level(l) str_name_code(tls_level_table, (l))
extern int tls_level_lookup(const char *);
extern const char *str_tls_level(int);
#ifdef USE_TLS
@@ -141,7 +142,6 @@ extern const NAME_CODE tls_level_table[];
#define TLS_DANE_FLAG_NORRS (1<<0) /* Nothing found in DNS */
#define TLS_DANE_FLAG_EMPTY (1<<1) /* Nothing usable found in DNS */
#define TLS_DANE_FLAG_ERROR (1<<2) /* TLSA record lookup error */
#define TLS_DANE_FLAG_MXINSEC (1<<3) /* Insecure MX record */
#define tls_dane_unusable(dane) ((dane)->flags & TLS_DANE_FLAG_EMPTY)
#define tls_dane_notfound(dane) ((dane)->flags & TLS_DANE_FLAG_NORRS)
@@ -252,11 +252,13 @@ typedef struct {
#define TLS_CERT_FLAG_ALTNAME (1<<1)
#define TLS_CERT_FLAG_TRUSTED (1<<2)
#define TLS_CERT_FLAG_MATCHED (1<<3)
#define TLS_CERT_FLAG_SECURED (1<<4)
#define TLS_CERT_IS_PRESENT(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_PRESENT))
#define TLS_CERT_IS_ALTNAME(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_ALTNAME))
#define TLS_CERT_IS_TRUSTED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_TRUSTED))
#define TLS_CERT_IS_MATCHED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_MATCHED))
#define TLS_CERT_IS_SECURED(c) ((c) && ((c)->peer_status&TLS_CERT_FLAG_SECURED))
/*
* Opaque client context handle.

View File

@@ -83,8 +83,8 @@
/* .IP TLScontext->peer_status
/* A bitmask field that records the status of the peer certificate
/* verification. This consists of one or more of
/* TLS_CERT_FLAG_PRESENT, TLS_CERT_FLAG_ALTNAME, TLS_CERT_FLAG_TRUSTED
/* and TLS_CERT_FLAG_MATCHED.
/* TLS_CERT_FLAG_PRESENT, TLS_CERT_FLAG_ALTNAME, TLS_CERT_FLAG_TRUSTED,
/* TLS_CERT_FLAG_MATCHED and TLS_CERT_FLAG_SECURED.
/* .IP TLScontext->peer_CN
/* Extracted CommonName of the peer, or zero-length string if the
/* information could not be extracted.
@@ -1116,12 +1116,16 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
tls_stream_start(props->stream, TLScontext);
/*
* Can't really be DANE verified if the MX RRset was insecure
* Fully secured only if trusted, matched and not insecure like halfdane.
* Should perhaps also exclude "verify" (as opposed to "secure") here,
* because that can be subject to insecure MX indirection, but that's
* rather incompatible. Users have been warned.
*/
if (TLS_DANE_BASED(props->tls_level)
&& (props->dane->flags & TLS_DANE_FLAG_MXINSEC) != 0) {
TLScontext->peer_status &= ~TLS_CERT_FLAG_MATCHED;
}
if (TLS_CERT_IS_PRESENT(TLScontext)
&& TLS_CERT_IS_TRUSTED(TLScontext)
&& TLS_CERT_IS_MATCHED(TLScontext)
&& !TLS_NEVER_SECURED(props->tls_level))
TLScontext->peer_status |= TLS_CERT_FLAG_SECURED;
/*
* All the key facts in a single log entry.
@@ -1130,7 +1134,7 @@ TLS_SESS_STATE *tls_client_start(const TLS_CLIENT_START_PROPS *props)
msg_info("%s TLS connection established to %s: %s with cipher %s "
"(%d/%d bits)",
!TLS_CERT_IS_PRESENT(TLScontext) ? "Anonymous" :
TLS_CERT_IS_MATCHED(TLScontext) ? "Verified" :
TLS_CERT_IS_SECURED(TLScontext) ? "Verified" :
TLS_CERT_IS_TRUSTED(TLScontext) ? "Trusted" : "Untrusted",
props->namaddr, TLScontext->protocol, TLScontext->cipher_name,
TLScontext->cipher_usebits, TLScontext->cipher_algbits);

View File

@@ -12,9 +12,8 @@
/* const char *str_tls_level(level)
/* int level;
/* DESCRIPTION
/* The macros in this module convert TLS levels from symbolic
/* name to internal form and vice versa. The macros are safe
/* because they evaluate their arguments only once.
/* The functions in this module convert TLS levels from symbolic
/* name to internal form and vice versa.
/*
/* tls_level_lookup() converts a TLS level from symbolic name
/* to internal form. When an unknown level is specified,
@@ -22,7 +21,9 @@
/*
/* str_tls_level() converts a TLS level from internal form to
/* symbolic name. The result is a null pointer for an unknown
/* level.
/* level. The "halfdane" level is not a valid user-selected TLS level,
/* it is generated internally and is only valid output for the
/* str_tls_level() function.
/* SEE ALSO
/* name_code(3) name to number mapping
/* LICENSE
@@ -68,14 +69,27 @@
* The smtp(8) client will report trust failure in preference to reporting
* failure to match, so we make "dane" larger than "fingerprint".
*/
const NAME_CODE tls_level_table[] = {
static const NAME_CODE tls_level_table[] = {
"none", TLS_LEV_NONE,
"may", TLS_LEV_MAY,
"encrypt", TLS_LEV_ENCRYPT,
"fingerprint", TLS_LEV_FPRINT,
"halfdane", TLS_LEV_HALF_DANE, /* output only */
"dane", TLS_LEV_DANE,
"dane-only", TLS_LEV_DANE_ONLY,
"verify", TLS_LEV_VERIFY,
"secure", TLS_LEV_SECURE,
0, TLS_LEV_INVALID,
};
int tls_level_lookup(const char *name)
{
int level = name_code(tls_level_table, NAME_CODE_FLAG_NONE, name);
return ((level != TLS_LEV_HALF_DANE) ? level : TLS_LEV_INVALID);
}
const char *str_tls_level(int level)
{
return (str_name_code(tls_level_table, level));
}