From: Wietse Venema Date: Sun, 8 Dec 2013 05:00:00 +0000 (-0500) Subject: postfix-2.11-20131208-nonprod X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1489cd448e3746ba88d13e71cfbff3826979953;p=thirdparty%2Fpostfix.git postfix-2.11-20131208-nonprod --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 441e160c2..982975fd0 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -155,6 +155,7 @@ -TLMTP_STATE -TLOCAL_EXP -TLOCAL_STATE +-TLONG_NAME_MASK -TMAC_EXP -TMAC_HEAD -TMAC_PARSE @@ -372,6 +373,7 @@ -Tsfsistat -Tsigset_t -Tsize_t +-Tsockaddr -Tssize_t -Tssl_cipher_stack_t -Tssl_comp_stack_t diff --git a/postfix/HISTORY b/postfix/HISTORY index 4883ede54..396760acb 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -19303,3 +19303,16 @@ Apologies for any names omitted. Bugfix (introduced: 20090106): the postconf '-#' option erased prior options. File: postconf/postconf.c. + +20131129 + + Bugfix: Makefile example in MULTI_INSTANCE_README. Viktor + Dukhovni. File: proto/MULTI_INSTANCE_README.html. + +20131130 + + Cleanup: simplify fingerprint security level implementation + in new DANE code. Viktor Dukhovni. Files: src/tls/tls.h + src/smtp/smtp_tls_policy.c src/tls/tls_dane.c + src/posttls-finger/posttls-finger.c. + diff --git a/postfix/README_FILES/MULTI_INSTANCE_README b/postfix/README_FILES/MULTI_INSTANCE_README index 6e2fb48c5..7e930f25c 100644 --- a/postfix/README_FILES/MULTI_INSTANCE_README +++ b/postfix/README_FILES/MULTI_INSTANCE_README @@ -177,7 +177,7 @@ database when none exists. generic: Makefile @echo Creating $@ @rm -f $@.tmp - @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp + @printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` > $@.tmp @mv $@.tmp generic %.cdb: % diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 2c8619a89..cbe1a17fc 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -74,7 +74,7 @@ all Postfix daemons, use this: $ postconf -F '*/*/chroot=n' For a second example, let's look at the submission service. This -service typically has multple "-o parameter=value" overrides. First +service typically has multiple "-o parameter=value" overrides. First the traditional view: $ postconf -Mf submission diff --git a/postfix/html/MULTI_INSTANCE_README.html b/postfix/html/MULTI_INSTANCE_README.html index 6aca5f53d..39fc87da1 100644 --- a/postfix/html/MULTI_INSTANCE_README.html +++ b/postfix/html/MULTI_INSTANCE_README.html @@ -233,7 +233,7 @@ creates a "generic" database when none exists.

generic: Makefile @echo Creating $@ @rm -f $@.tmp - @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp + @printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` > $@.tmp @mv $@.tmp generic %.cdb: % diff --git a/postfix/html/lmdb_table.5.html b/postfix/html/lmdb_table.5.html index d8dd19faf..6cba132a5 100644 --- a/postfix/html/lmdb_table.5.html +++ b/postfix/html/lmdb_table.5.html @@ -56,10 +56,12 @@ LMDB_TABLE(5) LMDB_TABLE(5) The Postfix LMDB adapter implements locking with fcntl(2) locks at whole-file granularity. LMDB's native locking scheme would require world-writable lockfiles and would - therefore violate the Postfix security model. Unlike some - other Postfix flat-file databases, LMDB databases can - safely be updated without serializing requests through the - proxymap(8) service. + therefore violate the Postfix security model. + + Multiple processes can safely update an LMDB database + without serializing requests through the proxymap(8) ser- + vice. This makes LMDB suitable as a shared cache for ver- + ify(8) or postscreen(8) services. CONFIGURATION PARAMETERS Short-lived programs automatically pick up changes to diff --git a/postfix/html/posttls-finger.1.html b/postfix/html/posttls-finger.1.html index 1848d6d24..a9a4943c5 100644 --- a/postfix/html/posttls-finger.1.html +++ b/postfix/html/posttls-finger.1.html @@ -12,14 +12,14 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) SYNOPSIS posttls-finger [options] [inet:]domain[:port] [match ...] - posttls-finger -S [options] unix:pathname [match ...] + posttls-finger -S [options] unix:pathname [match ...] DESCRIPTION posttls-finger(1) connects to the specified destination and reports TLS-related information about the server. With SMTP, the destination is a domainname; with LMTP it is either a domainname prefixed with inet: or a pathname pre- - fixed with unix:. If Postfix is built without TLS sup- + fixed with unix:. If Postfix is built without TLS sup- port, the resulting posttls-finger program has very lim- ited functionality, and only the -a, -c, -h, -o, -S, -t, -T and -v options are available. @@ -83,7 +83,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) taken from the smtp/tcp entry in /etc/services, defaulting to 25 if the entry is not found. - With LMTP, specify unix:pathname to connect to a local + With LMTP, specify unix:pathname to connect to a local server listening on a unix-domain socket bound to the specified pathname; otherwise, specify an optional inet: prefix followed by a domain and an optional port, with the @@ -314,7 +314,7 @@ POSTTLS-FINGER(1) POSTTLS-FINGER(1) validation information is available via native lookups). - unix:pathname + unix:pathname Connect to the UNIX-domain socket at pathname. LMTP only. diff --git a/postfix/man/man5/lmdb_table.5 b/postfix/man/man5/lmdb_table.5 index a45d9de9b..d6315bd71 100644 --- a/postfix/man/man5/lmdb_table.5 +++ b/postfix/man/man5/lmdb_table.5 @@ -63,10 +63,12 @@ curruption due stray pointer bugs. The Postfix LMDB adapter implements locking with fcntl(2) locks at whole-file granularity. LMDB's native locking scheme would require world-writable lockfiles and would -therefore violate the Postfix security model. Unlike some -other Postfix flat-file databases, LMDB databases can safely -be updated without serializing requests through the proxymap(8) -service. +therefore violate the Postfix security model. + +Multiple processes can safely update an LMDB database without +serializing requests through the proxymap(8) service. This +makes LMDB suitable as a shared cache for verify(8) or +postscreen(8) services. .SH "CONFIGURATION PARAMETERS" .na .nf diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index a44eaf15c..c68d90bc2 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -12,10 +12,10 @@ Postfix configuration parameters .SH DESCRIPTION .ad .fi -The Postfix main.cf configuration file specifies a small subset -of all the parameters that control the operation of the Postfix -mail system. Parameters not specified in main.cf are left at their -default values. +The Postfix main.cf configuration file specifies parameters that +control the operation of the Postfix mail system. Typically the +file contains only a small subset of all parameters; parameters +not specified are left at their default values. .PP The general format of the main.cf file is as follows: .IP \(bu diff --git a/postfix/proto/MULTI_INSTANCE_README.html b/postfix/proto/MULTI_INSTANCE_README.html index 59bb4fbd9..a2574df89 100644 --- a/postfix/proto/MULTI_INSTANCE_README.html +++ b/postfix/proto/MULTI_INSTANCE_README.html @@ -233,7 +233,7 @@ creates a "generic" database when none exists.

generic: Makefile @echo Creating $@ @rm -f $@.tmp - @printf '%s\t%s+root=%s\n' root $MTAADMIN `uname -n` > $@.tmp + @printf '%s\t%s+root=%s\n' root ${MTAADMIN} `uname -n` > $@.tmp @mv $@.tmp generic %.cdb: % diff --git a/postfix/proto/lmdb_table b/postfix/proto/lmdb_table index b1cc8169a..aa59635aa 100644 --- a/postfix/proto/lmdb_table +++ b/postfix/proto/lmdb_table @@ -53,10 +53,12 @@ # The Postfix LMDB adapter implements locking with fcntl(2) # locks at whole-file granularity. LMDB's native locking # scheme would require world-writable lockfiles and would -# therefore violate the Postfix security model. Unlike some -# other Postfix flat-file databases, LMDB databases can safely -# be updated without serializing requests through the proxymap(8) -# service. +# therefore violate the Postfix security model. +# +# Multiple processes can safely update an LMDB database without +# serializing requests through the proxymap(8) service. This +# makes LMDB suitable as a shared cache for verify(8) or +# postscreen(8) services. # CONFIGURATION PARAMETERS # .ad # .fi diff --git a/postfix/proto/postconf.man.prolog b/postfix/proto/postconf.man.prolog index 37afa4e88..170838fe6 100644 --- a/postfix/proto/postconf.man.prolog +++ b/postfix/proto/postconf.man.prolog @@ -12,10 +12,10 @@ Postfix configuration parameters .SH DESCRIPTION .ad .fi -The Postfix main.cf configuration file specifies a small subset -of all the parameters that control the operation of the Postfix -mail system. Parameters not specified in main.cf are left at their -default values. +The Postfix main.cf configuration file specifies parameters that +control the operation of the Postfix mail system. Typically the +file contains only a small subset of all parameters; parameters +not specified are left at their default values. .PP The general format of the main.cf file is as follows: .IP \(bu diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 00973bb01..f5154456c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20131126" +#define MAIL_RELEASE_DATE "20131208" #define MAIL_VERSION_NUMBER "2.11" #ifdef SNAPSHOT diff --git a/postfix/src/postconf/postconf_edit.c b/postfix/src/postconf/postconf_edit.c index 7607c5687..05fdc1f40 100644 --- a/postfix/src/postconf/postconf_edit.c +++ b/postfix/src/postconf/postconf_edit.c @@ -2,7 +2,7 @@ /* NAME /* postconf_edit 3 /* SUMMARY -/* edit main.cf +/* edit main.cf or master.cf /* SYNOPSIS /* #include /* @@ -25,19 +25,27 @@ /* /* edit_master() edits the \fBmaster.cf\fR configuration file. /* The file is copied to a temporary file then renamed into -/* place. Depending on the value of \fBmode\fR: +/* place. Depending on the flags in \fBmode\fR: /* .IP MASTER_ENTRY -/* edit_master() replaces or adds entire master.cf entries, -/* specified on the command line as "\fIname/type = name type -/* private unprivileged chroot wakeup process_limit command...\fR". -/* ,IP MASTER_FIELD -/* edit_master() replaces the value of specific service -/* attributes, specified on the command line as +/* With EDIT_CONF, edit_master() replaces or adds entire +/* master.cf entries, specified on the command line as +/* "\fIname/type = name type private unprivileged chroot wakeup +/* process_limit command...\fR". +/* +/* With EDIT_EXCL or COMMENT_OUT, edit_master() removes or +/* comments out entries specified on the command line as +/* "\fIname/type\fR. +/* .IP MASTER_FIELD +/* With EDIT_CONF, edit_master() replaces the value of specific +/* service attributes, specified on the command line as /* "\fIname/type/attribute = value\fR". /* .IP MASTER_PARAM -/* edit_master() replaces the value of specific service -/* parameters, specified on the command line as +/* With EDIT_CONF, edit_master() replaces or adds the value +/* of service parameters, specified on the command line as /* "\fIname/type/parameter = value\fR". +/* +/* With EDIT_EXCL, edit_master() removes service parameters +/* specified on the command line as "\fIparametername\fR". /* DIAGNOSTICS /* Problems are reported to the standard error stream. /* FILES @@ -346,7 +354,7 @@ void edit_master(int mode, int argc, char **argv) #define PC_MASTER_MASK (MASTER_ENTRY | MASTER_FIELD | MASTER_PARAM) /* - * Split name/type or name/type/field pattern into components. + * Split name/type or name/type/whatever pattern into components. */ switch (mode & PC_MASTER_MASK) { case MASTER_ENTRY: diff --git a/postfix/src/posttls-finger/posttls-finger.c b/postfix/src/posttls-finger/posttls-finger.c index 82d3aeb7d..2779ea075 100644 --- a/postfix/src/posttls-finger/posttls-finger.c +++ b/postfix/src/posttls-finger/posttls-finger.c @@ -798,7 +798,7 @@ static int doproto(STATE *state) /* connect_sock - connect a socket over some transport */ -static VSTREAM *connect_sock(int sock, struct sockaddr * sa, int salen, +static VSTREAM *connect_sock(int sock, struct sockaddr *sa, int salen, const char *name, const char *addr, STATE *state) { DSN_BUF *why = state->why; @@ -895,7 +895,7 @@ static VSTREAM *connect_unix(STATE *state, const char *path) if (msg_verbose) msg_info("%s: trying: %s...", myname, path); - return (connect_sock(sock, (struct sockaddr *) & sock_un, sizeof(sock_un), + return (connect_sock(sock, (struct sockaddr *) &sock_un, sizeof(sock_un), var_myhostname, path, state)); } @@ -906,7 +906,7 @@ static VSTREAM *connect_addr(STATE *state, DNS_RR *addr) static const char *myname = "connect_addr"; DSN_BUF *why = state->why; struct sockaddr_storage ss; /* remote */ - struct sockaddr *sa = (struct sockaddr *) & ss; + struct sockaddr *sa = (struct sockaddr *) &ss; SOCKADDR_SIZE salen = sizeof(ss); MAI_HOSTADDR_STR hostaddr; int sock; @@ -1392,7 +1392,7 @@ static int finger(STATE *state) state->why = dsb_create(); if (!(err = connect_dest(state))) { - if (state->pass == 1) + if (state->pass == 1 && !state->nochat) msg_info("Connected to %s", state->namaddrport); err = doproto(state); } @@ -1745,10 +1745,10 @@ static void parse_match(STATE *state, int argc, char *argv[]) argv_add(state->match, "hostname", ARGV_END); break; case TLS_LEV_FPRINT: - state->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); + state->dane = tls_dane_alloc(); while (*argv) - tls_dane_split((TLS_DANE *) state->dane, TLS_DANE_EE, TLS_DANE_PKEY, - state->mdalg, *argv++, ""); + tls_dane_add_ee_digests((TLS_DANE *) state->dane, + state->mdalg, *argv++, ""); break; case TLS_LEV_DANE: state->match = argv_alloc(2); @@ -1773,7 +1773,7 @@ static void parse_tas(STATE *state) return; case TLS_LEV_SECURE: case TLS_LEV_VERIFY: - state->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); + state->dane = tls_dane_alloc(); for (file = state->options.tas->argv; *file; ++file) { if (!tls_dane_load_trustfile((TLS_DANE *) state->dane, *file)) break; diff --git a/postfix/src/smtp/smtp_tls_policy.c b/postfix/src/smtp/smtp_tls_policy.c index 4f3fae10b..7c93e464d 100644 --- a/postfix/src/smtp/smtp_tls_policy.c +++ b/postfix/src/smtp/smtp_tls_policy.c @@ -308,9 +308,9 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, break; case TLS_LEV_FPRINT: if (!tls->dane) - tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); - tls_dane_split(tls->dane, TLS_DANE_EE, TLS_DANE_PKEY, - var_smtp_tls_fpt_dgst, val, "|"); + tls->dane = tls_dane_alloc(); + tls_dane_add_ee_digests(tls->dane, + var_smtp_tls_fpt_dgst, val, "|"); break; case TLS_LEV_VERIFY: case TLS_LEV_SECURE: @@ -345,7 +345,7 @@ static void tls_policy_lookup_one(SMTP_TLS_POLICY *tls, int *site_level, INVALID_RETURN(tls->why, site_level); } if (!tls->dane) - tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); + tls->dane = tls_dane_alloc(); if (!tls_dane_load_trustfile(tls->dane, val)) { INVALID_RETURN(tls->why, site_level); } @@ -559,11 +559,10 @@ static void *policy_create(const char *unused_key, void *context) break; case TLS_LEV_FPRINT: if (tls->dane == 0) - tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); + tls->dane = tls_dane_alloc(); if (!TLS_DANE_HASEE(tls->dane)) { - tls_dane_split(tls->dane, TLS_DANE_EE, TLS_DANE_PKEY, - var_smtp_tls_fpt_dgst, var_smtp_tls_fpt_cmatch, - "\t\n\r, "); + tls_dane_add_ee_digests(tls->dane, var_smtp_tls_fpt_dgst, + var_smtp_tls_fpt_cmatch, "\t\n\r, "); if (!TLS_DANE_HASEE(tls->dane)) { msg_warn("nexthop domain %s: configured at fingerprint " "security level, but with no fingerprints to match.", @@ -582,7 +581,7 @@ static void *policy_create(const char *unused_key, void *context) "\t\n\r, :"); if (*var_smtp_tls_tafile) { if (tls->dane == 0) - tls->dane = tls_dane_alloc(TLS_DANE_FLAG_MIXED); + tls->dane = tls_dane_alloc(); if (!TLS_DANE_HASTA(tls->dane) && !load_tas(tls->dane, var_smtp_tls_tafile)) { MARK_INVALID(tls->why, &tls->level); diff --git a/postfix/src/tls/tls.h b/postfix/src/tls/tls.h index cd4c2fcd2..cf2976667 100644 --- a/postfix/src/tls/tls.h +++ b/postfix/src/tls/tls.h @@ -108,10 +108,9 @@ extern const NAME_CODE tls_level_table[]; #define TLS_DANE_CERT 0 /* Match the certificate digest */ #define TLS_DANE_PKEY 1 /* Match the public key digest */ -#define TLS_DANE_FLAG_MIXED (1<<0) /* Combined pkeys and certs */ -#define TLS_DANE_FLAG_NORRS (1<<1) /* Nothing found in DNS */ -#define TLS_DANE_FLAG_EMPTY (1<<2) /* Nothing usable found in DNS */ -#define TLS_DANE_FLAG_ERROR (1<<3) /* TLSA record lookup error */ +#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_unusable(dane) ((dane)->flags & TLS_DANE_FLAG_EMPTY) #define tls_dane_notfound(dane) ((dane)->flags & TLS_DANE_FLAG_NORRS) @@ -146,10 +145,6 @@ typedef struct TLS_PKEYS { struct TLS_PKEYS *next; } TLS_PKEYS; - /* - * When TLS_DANE_FLAG_MIXED is set, the pkeys digest list is not allocated - * separately, and aliases the certs digest list for each algorithm. - */ typedef struct TLS_DANE { TLS_TLSA *ta; /* Trust-anchor cert/pubkey digests */ TLS_TLSA *ee; /* End-entity cert/pubkey digests */ @@ -170,9 +165,9 @@ typedef struct TLS_DANE { extern int tls_dane_avail(void); extern void tls_dane_flush(void); extern void tls_dane_verbose(int); -extern TLS_DANE *tls_dane_alloc(int); -extern void tls_dane_split(TLS_DANE *, int, int, const char *, const char *, - const char *); +extern TLS_DANE *tls_dane_alloc(void); +extern void tls_dane_add_ee_digests(TLS_DANE *, const char *, const char *, + const char *); extern void tls_dane_free(TLS_DANE *); extern TLS_DANE *tls_dane_resolve(unsigned, const char *, DNS_RR *, int); extern int tls_dane_load_trustfile(TLS_DANE *, const char *); diff --git a/postfix/src/tls/tls_dane.c b/postfix/src/tls/tls_dane.c index 92f2b6fa0..3efb2eb6f 100644 --- a/postfix/src/tls/tls_dane.c +++ b/postfix/src/tls/tls_dane.c @@ -13,16 +13,13 @@ /* void tls_dane_verbose(on) /* int on; /* -/* TLS_DANE *tls_dane_alloc(flags) -/* int flags; +/* TLS_DANE *tls_dane_alloc() /* /* void tls_dane_free(dane) /* TLS_DANE *dane; /* -/* void tls_dane_split(dane, certusage, selector, mdalg, digest, delim) +/* void tls_dane_add_ee_digests(dane, mdalg, digest, delim) /* TLS_DANE *dane; -/* int certusage; -/* int selector; /* const char *mdalg; /* const char *digest; /* const char *delim; @@ -65,17 +62,15 @@ /* tls_dane_verbose() turns on verbose logging of TLSA record lookups. /* /* tls_dane_alloc() returns a pointer to a newly allocated TLS_DANE -/* structure with null ta and ee digest sublists. If "flags" includes -/* TLS_DANE_FLAG_MIXED, the cert and pkey digests are stored together on -/* the pkeys list with the certs list empty, otherwise they are stored -/* separately. +/* structure with null ta and ee digest sublists. /* /* tls_dane_free() frees the structure allocated by tls_dane_alloc(). /* -/* tls_dane_split() splits "digest" using the characters in "delim" as -/* delimiters and stores the results with the requested "certusage" -/* and "selector". This is an incremental interface, that builds a -/* TLS_DANE structure outside the cache by manually adding entries. +/* tls_dane_add_ee_digests() splits "digest" using the characters in +/* "delim" as delimiters and stores the results on the EE match list +/* to match either a certificate or a public key. This is an incremental +/* interface, that builds a TLS_DANE structure outside the cache by +/* manually adding entries. /* /* tls_dane_load_trustfile() imports trust-anchor certificates and /* public keys from a file (rather than DNS TLSA records). @@ -128,8 +123,6 @@ /* When true, TLSA lookups are performed even when the qname and rname /* are insecure. This is only useful in the unlikely case that DLV is /* used to secure the TLSA RRset in an otherwise insecure zone. -/* .IP flags -/* Only one flag is part of the public interface at this time: /* .IP TLScontext /* Client context with TA/EE matching data and related state. /* .IP usage @@ -141,17 +134,6 @@ /* .IP ssl_ctx /* The global SSL_CTX structure used to initialize child SSL /* conenctions. -/* .RS -/* .IP TLS_DANE_FLAG_MIXED -/* Don't distinguish between certificate and public-key digests. -/* A single digest list for both certificates and keys with be -/* stored for each algorithm in the "pkeys" field, the "certs" -/* field will be null. -/* .RE -/* .IP certusage -/* Trust anchor (TLS_DANE_TA) or end-entity (TLS_DANE_EE) digests? -/* .IP selector -/* Full certificate (TLS_DANE_CERT) or pubkey (TLS_DANE_PKEY) digests? /* .IP mdalg /* Name of a message digest algorithm suitable for computing secure /* (1st pre-image resistant) message digests of certificates. For now, @@ -527,7 +509,7 @@ void tls_dane_flush(void) /* tls_dane_alloc - allocate a TLS_DANE structure */ -TLS_DANE *tls_dane_alloc(int flags) +TLS_DANE *tls_dane_alloc(void) { TLS_DANE *dane = (TLS_DANE *) mymalloc(sizeof(*dane)); @@ -536,7 +518,7 @@ TLS_DANE *tls_dane_alloc(int flags) dane->certs = 0; dane->pkeys = 0; dane->base_domain = 0; - dane->flags = flags; + dane->flags = 0; dane->expires = 0; dane->refs = 1; return (dane); @@ -663,36 +645,49 @@ static TLS_TLSA **dane_locate(TLS_TLSA **tlsap, const char *mdalg) return (tlsap); } -/* tls_dane_split - split and append digests */ +/* tls_dane_add_ee_digests - split and append digests */ -void tls_dane_split(TLS_DANE *dane, int certusage, int selector, - const char *mdalg, const char *digest, const char *delim) +void tls_dane_add_ee_digests(TLS_DANE *dane, const char *mdalg, + const char *digest, const char *delim) { - TLS_TLSA **tlsap; - TLS_TLSA *tlsa; - ARGV **argvp; - - tlsap = (certusage == TLS_DANE_EE) ? &dane->ee : &dane->ta; - tlsa = *(tlsap = dane_locate(tlsap, mdalg)); - argvp = ((dane->flags & TLS_DANE_FLAG_MIXED) || selector == TLS_DANE_PKEY) ? - &tlsa->pkeys : &tlsa->certs; + TLS_TLSA **tlsap = dane_locate(&dane->ee, mdalg); + TLS_TLSA *tlsa = *tlsap; /* Delimited append, may append nothing */ - if (*argvp == 0) - *argvp = argv_split(digest, delim); + if (tlsa->pkeys == 0) + tlsa->pkeys = argv_split(digest, delim); else - argv_split_append(*argvp, digest, delim); + argv_split_append(tlsa->pkeys, digest, delim); - if ((*argvp)->argc == 0) { - argv_free(*argvp); - *argvp = 0; + /* Remove empty elements from the list */ + if (tlsa->pkeys->argc == 0) { + argv_free(tlsa->pkeys); + tlsa->pkeys = 0; - /* Remove empty elements from the list */ - if (tlsa->pkeys == 0 && tlsa->certs == 0) { + if (tlsa->certs == 0) { *tlsap = tlsa->next; tlsa_free(tlsa); } + return; } + + /* + * At the "fingerprint" security level certificate digests and public key + * digests are interchangeable. Each leaf certificate is matched via + * either the public key digest or full certificate digest. The DER + * encoding of a certificate is not a valid public key, and conversely, + * the DER encoding of a public key is not a valid certificate. An + * attacker would need a 2nd-preimage that is feasible across types + * (given cert digest == some pkey digest) and yet presumably difficult + * within a type (e.g. given cert digest == some other cert digest). No + * such attacks are known at this time, and it is expected that if any + * are found they would work within as well as across the cert/pkey data + * types. + */ + if (tlsa->certs == 0) + tlsa->certs = argv_split(digest, delim); + else + argv_split_append(tlsa->certs, digest, delim); } /* dane_add - add a digest entry */ @@ -729,8 +724,7 @@ static void dane_add(TLS_DANE *dane, int certusage, int selector, tlsap = (certusage == TLS_DANE_EE) ? &dane->ee : &dane->ta; tlsa = *(tlsap = dane_locate(tlsap, mdalg)); - argvp = ((dane->flags & TLS_DANE_FLAG_MIXED) || selector == TLS_DANE_PKEY) ? - &tlsa->pkeys : &tlsa->certs; + argvp = (selector == TLS_DANE_PKEY) ? &tlsa->pkeys : &tlsa->certs; if (*argvp == 0) *argvp = argv_alloc(1); @@ -877,7 +871,7 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) if (ctx->target && ctx->target != ctx->count) ctx->flags &= ~FILTER_CTX_AGILITY_OK; else - ctx->target = (change & ~0xff) ? 0 : ctx->count; + ctx->target = (change & 0xffff00) ? 0 : ctx->count; ctx->count = 0; } } @@ -969,8 +963,8 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) k = X509_get_pubkey(x); EVP_PKEY_free(k); if (k == 0) { - msg_warn("%s public key malformed in RR: " - "%s%s%s IN TLSA %u %u %u ...", "certificate", + msg_warn("malformed %s in RR: %s%s%s IN TLSA %u %u %u ...", + "or unsupported certificate public key", q, a, r, usage, selector, mtype); X509_free(x); return (FILTER_RR_DROP); @@ -989,14 +983,18 @@ static int parse_tlsa_rr(DNS_RR *rr, filter_ctx *ctx) case DNS_TLSA_SELECTOR_SUBJECTPUBLICKEYINFO: if (!d2i_PUBKEY(&k, &p, dlen) || dlen != p - data) { - msg_warn("malformed %s in RR: " - "%s%s%s IN TLSA %u %u %u ...", "public key", - q, a, r, usage, selector, mtype); + msg_warn("malformed %s in RR: %s%s%s IN TLSA %u %u %u ...", + "public key", q, a, r, usage, selector, mtype); if (k) EVP_PKEY_free(k); return (FILTER_RR_DROP); } - /* See full cert case above */ + + /* + * When a full trust-anchor public key is published via DNS, we + * may need to use it to validate the server trust chain. Store + * it away for later use. + */ if (usage == DNS_TLSA_USAGE_TRUST_ANCHOR_ASSERTION && (ctx->flags & FILTER_CTX_PARSE_DATA)) ta_pkey_insert(ctx->dane, k); @@ -1073,7 +1071,7 @@ static void *dane_lookup(const char *tlsa_fqdn, void *unused_ctx) if (why == 0) why = vstring_alloc(10); - dane = tls_dane_alloc(0); + dane = tls_dane_alloc(); ret = dns_lookup(tlsa_fqdn, T_TLSA, RES_USE_DNSSEC, &rrs, 0, why); switch (ret) { @@ -1163,7 +1161,7 @@ TLS_DANE *tls_dane_resolve(unsigned port, const char *proto, DNS_RR *hostrr, */ iscname = strcasecmp(hostrr->rname, hostrr->qname); if (!forcetlsa && !hostrr->dnssec_valid && !iscname) { - dane = tls_dane_alloc(0); + dane = tls_dane_alloc(); dane->flags = TLS_DANE_FLAG_NORRS; } else { @@ -1301,12 +1299,10 @@ int tls_dane_match(TLS_SESS_STATE *TLScontext, int usage, TLS_TLSA *tlsa = (usage == TLS_DANE_EE) ? dane->ee : dane->ta; const char *namaddr = TLScontext->namaddr; const char *ustr = (usage == TLS_DANE_EE) ? "end entity" : "trust anchor"; - int mixed = (dane->flags & TLS_DANE_FLAG_MIXED); int matched; for (matched = 0; tlsa && !matched; tlsa = tlsa->next) { char **dgst; - ARGV *certs; /* * Note, set_trust() needs to know whether the match was for a pkey @@ -1328,26 +1324,10 @@ int tls_dane_match(TLS_SESS_STATE *TLScontext, int usage, namaddr, depth, ustr, tlsa->mdalg, pkey_dgst); myfree(pkey_dgst); } - - /* - * Backwards compatible "fingerprint" security level interface: - * - * Certificate digests and public key digests are interchangeable, each - * leaf certificate is matched via either the public key digest or - * full certificate digest when "mixed" is true. The combined set of - * digests is stored on the pkeys digest list and the certs list is - * empty. An attacker would need a 2nd-preimage (not just a - * collision) that is feasible across types (given cert digest == - * some key digest) while difficult within a type (e.g. given cert - * some other cert digest). No such attacks are know at this time, - * and it is expected that if any are found they would work within as - * well as across the cert/key data types. - */ - certs = mixed ? tlsa->pkeys : tlsa->certs; - if (certs != 0 && !matched) { + if (tlsa->certs != 0 && !matched) { char *cert_dgst = tls_cert_fprint(cert, tlsa->mdalg); - for (dgst = certs->argv; !matched && *dgst; ++dgst) + for (dgst = tlsa->certs->argv; !matched && *dgst; ++dgst) if (strcasecmp(cert_dgst, *dgst) == 0) matched = MATCHED_CERT; if (TLScontext->log_mask & (TLS_LOG_VERBOSE | TLS_LOG_CERTMATCH) diff --git a/postfix/src/tls/tls_fprint.c b/postfix/src/tls/tls_fprint.c index 40746ea55..abd5ff7d4 100644 --- a/postfix/src/tls/tls_fprint.c +++ b/postfix/src/tls/tls_fprint.c @@ -223,9 +223,6 @@ char *tls_serverid_digest(const TLS_CLIENT_START_PROPS *props, long protomask, * we must include the SNI name in the session id. */ if (props->dane) { - int mixed = (props->dane->flags & TLS_DANE_FLAG_MIXED); - - digest_object(&mixed); digest_dane(props->dane, ta); #if 0 digest_dane(props->dane, ee); /* See above */