2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 05:07:58 +00:00

postfix-3.3-20170716

This commit is contained in:
Wietse Venema 2017-07-16 00:00:00 -05:00 committed by Viktor Dukhovni
parent e0d44feb73
commit f06d554014
12 changed files with 179 additions and 19 deletions

View File

@ -23023,10 +23023,40 @@ Apologies for any names omitted.
Security: Berkeley DB 2 and later try to read settings from
a file DB_CONFIG in the current directory. This undocumented
feature may introduce undisclosed vulnerabilities resulting in
privilege escalation with Postfix set-gid programs (postdrop,
postqueue) before they chdir to the Postfix queue directory,
and with the postmap and postalias commands depending on whether
the user's current directory is writable by other users. This
fix does not change Postfix behavior for Berkeley DB < 3.
File: util/dict_db.c.
feature may introduce undisclosed vulnerabilities resulting
in privilege escalation with Postfix set-gid programs
(postdrop, postqueue) before they chdir to the Postfix queue
directory, and with the postmap and postalias commands
depending on whether the user's current directory is writable
by other users. This fix does not change Postfix behavior
for Berkeley DB < 3, but reduces file create performance
for Berkeley DB 3 .. 4.6. File: util/dict_db.c.
20170617
Cleanup: the postconf command warns about unknown parameter
names in a database configuration file, specified as an
absolute pathname (for example, ldap:/path/to/file). This
code was mostly written in January 2017, and it still is a
partial implementation. Files: postconf/postconf_dbms.c,
postconf/Makefile.in, postconf/test66.ref.
20170618
Cleanup: added missing "defined(__GLIBC__)" guards for
GLIBC version tests. File: util/sys_defs.h.
20170620
Bugfix (introduced: Postfix 3.2) extension propagation was
broken with "recipient_delimiter = .", because of code that
was too clever by half. Files: global/mail_adr_crunch.c,
global/mail_addr_crunch.ref.
20170704
Typos (introduced: Postfix 2.10): in comments about
IPv4-in-IPv6 addresses, replace :ffff::1.2.3.4 with the
correct form :ffff::1.2.3.4. Incorrect or misleading comments
are worse than no comments. Files: smtpd/smtpd_haproxy.c,
postscreen/postscreen_haproxy.c.

View File

@ -6,6 +6,20 @@ Wish list:
Disable -DSNAPSHOT and -DNONPROD in makedefs.
Add postwhite as a postscreen-related project.
https://github.com/stevejenkins/postwhite/blob/master/README.md
Decide whether to deprecate database configuration pathnames
that start with ".", for example, ldap:./file/name. These forms
are documented for ldap:, memcache:, mysql:, pgsql:, and sqlite:
maps. Postfix daemon processes will look up files relative to the
queue directory, but with postmap command-line processes it would
be more natural to interpret relative pathnames relative to the
current directory of the calling process (it would be a surprise
if "postmap hash:./foo" would access "/var/spool/postfix/foo",
or if "postmap hash:foo" and or "postmap hash:./foo" would access
different files).
Convert postalias(1) to store external-form keys, and convert
aliases(5) to perform external-first lookup with fallback to
internal form, to make it consistent with the rest of Postfix.

View File

@ -120,7 +120,7 @@ ARGV *mail_addr_crunch_opt(const char *string, const char *extension,
tok822_externalize(extern_addr, tpp[0]->head, TOK822_STR_DEFL);
canon_addr_external(canon_addr, STR(extern_addr));
unquote_822_local(intern_addr, STR(canon_addr));
if (extension && strchr(STR(intern_addr), *extension) == 0) {
if (extension) {
VSTRING_SPACE(intern_addr, extlen + 1);
if ((ratsign = strrchr(STR(intern_addr), '@')) == 0) {
vstring_strcat(intern_addr, extension);

View File

@ -1,7 +1,7 @@
==== external to internal, with extension
|foo+extension@example.com|
|foo bar+extension@example.com|
|foo+ext@example.com|
|foo+ext+extension@example.com|
==== external to internal, without extension
|foo@example.com|
|foo bar@example.com|
@ -9,14 +9,14 @@
==== external to external, with extension
|foo+extension@example.com|
|"foo bar+extension"@example.com|
|foo+ext@example.com|
|foo+ext+extension@example.com|
==== external to external, without extension
|foo@example.com|
|"foo bar"@example.com|
|foo+ext@example.com|
==== internal to internal, with extension
|foo+extension@example.com|
|foo+ext@example.com|
|foo+ext+extension@example.com|
==== internal to internal, without extension
|foo@example.com|
|foo+ext@example.com|

View File

@ -256,6 +256,7 @@ typedef struct {
#define DO_PROPAGATE_UNMATCHED_EXTENSION 1
#define NO_RECIPIENT_DELIMITER ""
#define PLUS_RECIPIENT_DELIMITER "+"
#define DOT_RECIPIENT_DELIMITER "."
/*
* All these tests must pass, so that we know that mail_addr_map_opt() works
@ -352,6 +353,14 @@ static MAIL_ADDR_MAP_TEST pass_tests[] = {
"a@a@example.com",
{"\"a@a\"@example.net"}, 1,
},
{
"12 external -external-> external, extension, propagation",
"inline:{ aa@example.com=bb@example.com }",
DO_PROPAGATE_UNMATCHED_EXTENSION, DOT_RECIPIENT_DELIMITER,
MA_FORM_EXTERNAL, MA_FORM_EXTERNAL, MA_FORM_EXTERNAL,
"aa.ext@example.com",
{"bb.ext@example.com"}, 1,
},
0,
};

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 "20170612"
#define MAIL_RELEASE_DATE "20170716"
#define MAIL_VERSION_NUMBER "3.3"
#ifdef SNAPSHOT

View File

@ -52,7 +52,7 @@ tests: test1 test2 test3 test4 test5 test6 test7 test8 test9 test10 test11 \
test31 test32 test33 test34 test35 test36 test37 test39 test40 test41 \
test42 test43 test44 test45 test46 test47 test48 test49 test50 test51 \
test52 test53 test54 test55 test56 test57 test58 test59 test60 test61 \
test62 test63 test64 test65
test62 test63 test64 test65 test66
root_tests:
@ -870,6 +870,22 @@ test65: $(PROG) test65.ref
diff test65.ref test65.tmp
rm -f main.cf master.cf test65.tmp
# unknown parameters in database configuration file (absolute pathname).
test66: $(PROG) test66.ref
rm -f main.cf master.cf
touch master.cf
echo alias_maps = ldap:`pwd`/test66.cf >> main.cf
echo " " mysql:`pwd`/test66.cf >> main.cf
echo " " pgsql:`pwd`/test66.cf >> main.cf
echo " " sqlite:`pwd`/test66.cf >> main.cf
echo " " memcache:`pwd`/test66.cf >> main.cf
echo junk = junk >> test66.cf
touch -t 197101010000 main.cf
$(SHLIB_ENV) ./$(PROG) -c. 2>test66.tmp >/dev/null
sed "s;PWD;`pwd`;" test66.ref | diff - test66.tmp
rm -f main.cf master.cf test66.tmp test66.cf
printfck: $(OBJS) $(PROG)
rm -rf printfck
mkdir printfck
@ -971,6 +987,7 @@ postconf_builtin.o: time_vars.h
postconf_dbms.o: ../../include/argv.h
postconf_dbms.o: ../../include/check_arg.h
postconf_dbms.o: ../../include/dict.h
postconf_dbms.o: ../../include/dict_ht.h
postconf_dbms.o: ../../include/dict_ldap.h
postconf_dbms.o: ../../include/dict_memcache.h
postconf_dbms.o: ../../include/dict_mysql.h

View File

@ -22,7 +22,9 @@
/* When a database type is found that supports legacy-style
/* configuration, the table name is combined with each of the
/* database-defined suffixes to generate candidate parameter
/* names for that database type.
/* names for that database type; if the table name specifies
/* a client configuration file, that file is scanned for unused
/* parameter settings.
/* .IP flag_parameter
/* A function that takes as arguments a candidate parameter
/* name, parameter flags, and a PCF_MASTER_ENT pointer. The
@ -46,6 +48,7 @@
/* System library. */
#include <sys_defs.h>
#include <errno.h>
#include <string.h>
/* Utility library. */
@ -61,6 +64,7 @@
#include <mail_conf.h>
#include <mail_params.h>
#include <dict_ht.h>
#include <dict_proxy.h>
#include <dict_ldap.h>
#include <dict_mysql.h>
@ -145,6 +149,64 @@ static const PCF_DBMS_INFO pcf_dbms_info[] = {
0,
};
/* pcf_check_dbms_client - look for unused names in client configuration */
static void pcf_check_dbms_client(const PCF_DBMS_INFO *dp, const char *cf_file)
{
DICT *dict;
VSTREAM *fp;
const char **cpp;
const char *name;
const char *value;
char *dict_spec;
int dir;
/*
* We read each database client configuration file into its own
* dictionary, and nag only the first time that a file is visited.
*/
dict_spec = concatenate(dp->db_type, ":", cf_file, (char *) 0);
if ((dict = dict_handle(dict_spec)) == 0) {
/*
* Populate the dictionary with settings in this database client
* configuration file. Don't die if a file can't be opened - some
* files may contain passwords and should not be world-readable.
* Note: dict_load_fp() nags about duplicate pameter settings.
*/
dict = dict_ht_open(dict_spec, O_CREAT | O_RDWR, 0);
dict_register(dict_spec, dict);
if ((fp = vstream_fopen(cf_file, O_RDONLY, 0)) == 0
&& errno != EACCES) {
msg_warn("open \"%s\" configuration \"%s\": %m",
dp->db_type, cf_file);
myfree(dict_spec);
return;
}
dict_load_fp(dict_spec, fp);
if (vstream_fclose(fp)) {
msg_warn("read \"%s\" configuration \"%s\": %m",
dp->db_type, cf_file);
myfree(dict_spec);
return;
}
/*
* Remove all known database client parameters from this dictionary,
* then report the remaining ones as "unused". We use ad-hoc logging
* code, because a database client parameter namespace is unlike the
* parameter namespaces in main.cf or master.cf.
*/
for (cpp = dp->db_suffixes; *cpp; cpp++)
(void) dict_del(dict, *cpp);
for (dir = DICT_SEQ_FUN_FIRST;
dict->sequence(dict, dir, &name, &value) == DICT_STAT_SUCCESS;
dir = DICT_SEQ_FUN_NEXT)
msg_warn("%s: unused parameter: %s=%s", dict_spec, name, value);
}
myfree(dict_spec);
}
/* pcf_register_dbms_helper - parse one possible database type:name */
static void pcf_register_dbms_helper(char *str_value,
@ -172,6 +234,28 @@ static void pcf_register_dbms_helper(char *str_value,
&& strcmp(db_type, DICT_TYPE_PROXY) == 0)
db_type = prefix;
if (prefix == 0)
continue;
/*
* Look for database:prefix where the prefix is an absolute pathname.
* Then, report unknown database client configuration parameters.
*
* XXX What about a pathname beginning with '.'? This supposedly is
* relative to the queue directory, which is the default directory
* for all Postfix daemon processes. This would also have to handle
* the case that the queue is not yet created.
*/
if (*prefix == '/') {
for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
if (strcmp(db_type, dp->db_type) == 0) {
pcf_check_dbms_client(dp, prefix);
break;
}
}
continue;
}
/*
* Look for database:prefix where the prefix is not a pathname and
* the database is a known type. Synthesize candidate parameter names
@ -179,7 +263,7 @@ static void pcf_register_dbms_helper(char *str_value,
* list, and see if those parameters have a "name=value" entry in the
* local or global namespace.
*/
if (prefix != 0 && *prefix != '/' && *prefix != '.') {
if (*prefix != '.') {
if (*prefix == CHARS_BRACE[0]) {
if ((err = extpar(&prefix, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
/* XXX Encapsulate this in pcf_warn() function. */

View File

@ -0,0 +1,5 @@
./postconf: warning: ldap:PWD/test66.cf: unused parameter: junk=junk
./postconf: warning: mysql:PWD/test66.cf: unused parameter: junk=junk
./postconf: warning: pgsql:PWD/test66.cf: unused parameter: junk=junk
./postconf: warning: sqlite:PWD/test66.cf: unused parameter: junk=junk
./postconf: warning: memcache:PWD/test66.cf: unused parameter: junk=junk

View File

@ -133,7 +133,7 @@ static void psc_endpt_haproxy_event(int event, void *context)
/*
* Parse the haproxy line. Note: the haproxy_srvr_parse() routine
* performs address protocol checks, address and port syntax checks, and
* converts IPv4-in-IPv6 address string syntax (:ffff::1.2.3.4) to IPv4
* converts IPv4-in-IPv6 address string syntax (::ffff:1.2.3.4) to IPv4
* syntax where permitted by the main.cf:inet_protocols setting.
*/
if (status == 0 && last_char == '\n') {

View File

@ -111,7 +111,7 @@ int smtpd_peer_from_haproxy(SMTPD_STATE *state)
/*
* Note: the haproxy_srvr_parse() routine performs address protocol
* checks, address and port syntax checks, and converts IPv4-in-IPv6
* address string syntax (:ffff::1.2.3.4) to IPv4 syntax where permitted
* address string syntax (::ffff:1.2.3.4) to IPv4 syntax where permitted
* by the main.cf:inet_protocols setting, but logs no warnings.
*/
#define ENABLE_DEADLINE 1

View File

@ -782,7 +782,8 @@ extern int initgroups(const char *, int);
#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) __GLIBC_PREREQ(maj, min)
#else
#define HAVE_GLIBC_API_VERSION_SUPPORT(maj, min) \
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
(defined(__GLIBC__) && \
((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min)))
#endif
#if HAVE_GLIBC_API_VERSION_SUPPORT(2, 1)
#define SOCKADDR_SIZE socklen_t
@ -805,7 +806,7 @@ extern int initgroups(const char *, int);
#define KERNEL_VERSION(a,b,c) (LINUX_VERSION_CODE + 1)
#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) \
|| (__GLIBC__ < 2)
|| (defined(__GLIBC__) && __GLIBC__ < 2)
#define CANT_USE_SEND_RECV_MSG
#define DEF_SMTP_CACHE_DEMAND 0
#else