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:
committed by
Viktor Dukhovni
parent
bbddef305d
commit
adbd9510a1
@@ -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.
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -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.
|
||||
|
@@ -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);
|
||||
|
@@ -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));
|
||||
}
|
||||
|
Reference in New Issue
Block a user