From: Wietse Venema
The Postfix memcache client requires additional configuration when used as postscreen(8) or verify(8) cache. For details see the diff --git a/postfix/html/memcache_table.5.html b/postfix/html/memcache_table.5.html index 11ab0ff7e..c10aab16a 100644 --- a/postfix/html/memcache_table.5.html +++ b/postfix/html/memcache_table.5.html @@ -75,12 +75,12 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5) in all Postfix instances except for one instance that will be responsible for cache cleanup. - NOTE 2: In the case of a proxied database, the full - database name (including the "proxy:" prefix) must - be specified in the proxymap server's - proxy_read_maps or proxy_write_maps setting - (depending on whether the access is read-only or - read-write). + NOTE 2: In the case of a proxied backup database, + the full backup database name (including the + "proxy:" prefix) must be specified in the proxymap + server's proxy_read_maps or proxy_write_maps set- + ting (depending on whether the access is read-only + or read-write). flags (default: 0) Optional flags that should be stored along with a @@ -200,7 +200,7 @@ MEMCACHE_TABLE(5) MEMCACHE_TABLE(5) destinations). In a typical deployment a memcache data- base is writable by any process that can talk to the mem- cache server; in contrast, security-sensitive tables must - not be writable by the unprivileged Postfix user. + never be writable by the unprivileged Postfix user. The Postfix memcache client requires additional configura- tion when used as postscreen(8) or verify(8) cache. For diff --git a/postfix/man/man5/memcache_table.5 b/postfix/man/man5/memcache_table.5 index 002766859..f8f286e28 100644 --- a/postfix/man/man5/memcache_table.5 +++ b/postfix/man/man5/memcache_table.5 @@ -80,7 +80,8 @@ automatic cache cleanup (*_cache_cleanup_interval = 0) in all Postfix instances except for one instance that will be responsible for cache cleanup. -NOTE 2: In the case of a proxied database, the full database +NOTE 2: In the case of a proxied backup database, the full +backup database name (including the "proxy:" prefix) must be specified in the proxymap server's proxy_read_maps or proxy_write_maps setting (depending on whether the access is read-only or @@ -198,7 +199,7 @@ tables such as \fBalias_maps\fR (these may contain privileges or "\fI/file/name\fR" destinations). In a typical deployment a memcache database is writable by any process that can talk to the memcache server; in contrast, -security-sensitive tables must not be writable by the +security-sensitive tables must never be writable by the unprivileged Postfix user. The Postfix memcache client requires additional configuration diff --git a/postfix/proto/MEMCACHE_README.html b/postfix/proto/MEMCACHE_README.html index 3f2c3e09b..ad445892f 100644 --- a/postfix/proto/MEMCACHE_README.html +++ b/postfix/proto/MEMCACHE_README.html @@ -44,7 +44,7 @@ and "/file/name" destinations), or virtual_uid_maps, specify UNIX process privileges or "/file/name" destinations). Typically, a memcache database is writable by any process that can talk to the memcache server; in contrast, security-sensitive tables -must not be writable by the unprivileged Postfix user.
+must never be writable by the unprivileged Postfix user. The Postfix memcache client requires additional configuration
when used as postscreen(8) or verify(8) cache. For details see the
diff --git a/postfix/proto/memcache_table b/postfix/proto/memcache_table
index fc5827c13..d4a3658c3 100644
--- a/postfix/proto/memcache_table
+++ b/postfix/proto/memcache_table
@@ -72,7 +72,8 @@
# all Postfix instances except for one instance that will be
# responsible for cache cleanup.
#
-# NOTE 2: In the case of a proxied database, the full database
+# NOTE 2: In the case of a proxied backup database, the full
+# backup database
# name (including the "proxy:" prefix) must be specified in
# the proxymap server's proxy_read_maps or proxy_write_maps
# setting (depending on whether the access is read-only or
@@ -184,7 +185,7 @@
# privileges or "\fI/file/name\fR" destinations). In a typical
# deployment a memcache database is writable by any process
# that can talk to the memcache server; in contrast,
-# security-sensitive tables must not be writable by the
+# security-sensitive tables must never be writable by the
# unprivileged Postfix user.
#
# The Postfix memcache client requires additional configuration
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index 0a5d596ef..a1644a32a 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -422,6 +422,20 @@ maps_test: maps maps.in maps.ref
diff maps.ref maps.tmp
rm -f maps.tmp
+surrogate_test: mail_dict surrogate.ref
+ cp /dev/null surrogate.tmp
+ echo get foo|./mail_dict ldap:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict ldap:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict mysql:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict mysql:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict pgsql:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict pgsql:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict sqlite:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict sqlite:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./mail_dict memcache:/xx read >>surrogate.tmp 2>&1
+ diff surrogate.ref surrogate.tmp
+ rm -f surrogate.tmp
+
# Requires: Postfix running, root privileges
rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index cbb946c71..870efbe8c 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 "20120114"
+#define MAIL_RELEASE_DATE "20120115"
#define MAIL_VERSION_NUMBER "2.9"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/namadr_list.ref b/postfix/src/global/namadr_list.ref
index 1f62aa216..1aa895a6c 100644
--- a/postfix/src/global/namadr_list.ref
+++ b/postfix/src/global/namadr_list.ref
@@ -7,7 +7,10 @@ dummy/168.100.189.16: ERROR
./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28"
dummy/168.100.189.16: ERROR
dummy/168.100.989.16: NO
-./namadr_list: fatal: unsupported dictionary type: 2001
+./namadr_list: error: unsupported dictionary type: 2001
+./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 is unavailable. unsupported dictionary type: 2001
+./namadr_list: warning: 2001:240:5c7:0:2d0:b7ff:fe88:2ca7: table lookup problem
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: ERROR
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES
dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO
./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
diff --git a/postfix/src/global/surrogate.ref b/postfix/src/global/surrogate.ref
new file mode 100644
index 000000000..cd12a5490
--- /dev/null
+++ b/postfix/src/global/surrogate.ref
@@ -0,0 +1,36 @@
+./mail_dict: error: ldap:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: ldap:/xx is unavailable. ldap:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: ldap:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: mysql:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: mysql:/xx is unavailable. mysql:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: mysql:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: pgsql:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: pgsql:/xx is unavailable. pgsql:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: pgsql:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: sqlite:/xx map requires O_RDONLY access mode
+> get foo
+./mail_dict: warning: sqlite:/xx is unavailable. sqlite:/xx map requires O_RDONLY access mode
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: sqlite:/xx is unavailable. open /xx: No such file or directory
+foo: error
+./mail_dict: error: open /xx: No such file or directory
+> get foo
+./mail_dict: warning: memcache:/xx is unavailable. open /xx: No such file or directory
+foo: error
diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
index b2bfd231d..a95f08a97 100644
--- a/postfix/src/smtpd/smtpd.c
+++ b/postfix/src/smtpd/smtpd.c
@@ -1559,7 +1559,7 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
static NORETURN cant_announce_feature(SMTPD_STATE *state, const char *feature)
{
- msg_warn("don't know if feature %s should be announced to %s",
+ msg_warn("don't know if EHLO feature %s should be announced to %s",
feature, state->namaddr);
vstream_longjmp(state->client, SMTP_ERR_DATA);
}
@@ -1677,7 +1677,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
if (discard_mask && !(discard_mask & EHLO_MASK_SILENT))
msg_info("discarding EHLO keywords: %s", str_ehlo_mask(discard_mask));
if (ehlo_discard_maps && ehlo_discard_maps->error) {
- msg_warn("don't know what features to announce in EHLO");
+ msg_warn("don't know what EHLO features to announce to %s",
+ state->namaddr);
vstream_longjmp(state->client, SMTP_ERR_DATA);
}
@@ -4491,12 +4492,12 @@ static void smtpd_proto(SMTPD_STATE *state)
case SMTP_ERR_DATA:
msg_info("%s: reject: %s from %s: "
- "421 4.3.0 %s Server configuration error",
+ "421 4.3.0 %s Server local data error",
(state->queue_id ? state->queue_id : "NOQUEUE"),
state->where, state->namaddr, var_myhostname);
state->error_mask |= MAIL_ERROR_DATA;
if (vstream_setjmp(state->client) == 0)
- smtpd_chat_reply(state, "421 4.3.0 %s Server configuration error",
+ smtpd_chat_reply(state, "421 4.3.0 %s Server local data error",
var_myhostname);
break;
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index cff7d8a05..c73642c98 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -444,7 +444,7 @@ tests: valid_hostname_test mac_expand_test dict_test unescape_test \
attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
myaddrinfo_test format_tv_test ip_match_test name_mask_tests \
- base32_code_test dict_thash_test
+ base32_code_test dict_thash_test surrogate_test
root_tests:
@@ -633,6 +633,22 @@ dict_thash_test: ../postmap/postmap dict_thash.map
sort dict_thash.tmp | diff -b dict_thash.map -
rm -f dict_thash.tmp
+surrogate_test: dict_open surrogate.ref
+ cp /dev/null surrogate.tmp
+ echo get foo|./dict_open cidr:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./dict_open cidr:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./dict_open pcre:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./dict_open pcre:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./dict_open regexp:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./dict_open regexp:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./dict_open unix:xx write >>surrogate.tmp 2>&1
+ echo get foo|./dict_open unix:xx read >>surrogate.tmp 2>&1
+ echo get foo|./dict_open texthash:/xx write >>surrogate.tmp 2>&1
+ echo get foo|./dict_open texthash:/xx read >>surrogate.tmp 2>&1
+ echo get foo|./dict_open hash:/xx read >>surrogate.tmp 2>&1
+ diff surrogate.ref surrogate.tmp
+ rm -f surrogate.tmp
+
depend: $(MAKES)
(sed '1,/^# do not edit/!d' Makefile.in; \
set -e; for i in [a-z][a-z0-9]*.c; do \
diff --git a/postfix/src/util/dict_cidr.c b/postfix/src/util/dict_cidr.c
index 5731e58d4..2ea7ab1fd 100644
--- a/postfix/src/util/dict_cidr.c
+++ b/postfix/src/util/dict_cidr.c
@@ -166,8 +166,8 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
DICT_CIDR *dict_cidr;
VSTREAM *map_fp;
struct stat st;
- VSTRING *line_buffer = vstring_alloc(100);
- VSTRING *why = vstring_alloc(100);
+ VSTRING *line_buffer;
+ VSTRING *why;
DICT_CIDR_ENTRY *rule;
DICT_CIDR_ENTRY *last_rule = 0;
int lineno = 0;
@@ -189,6 +189,12 @@ DICT *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
if (fstat(vstream_fileno(map_fp), &st) < 0)
msg_fatal("fstat %s: %m", mapname);
+ /*
+ * No early returns without memory leaks.
+ */
+ line_buffer = vstring_alloc(100);
+ why = vstring_alloc(100);
+
/*
* XXX Eliminate unnecessary queries by setting a flag that says "this
* map matches network addresses only".
diff --git a/postfix/src/util/dict_db.c b/postfix/src/util/dict_db.c
index 29e4cda09..5a4287c86 100644
--- a/postfix/src/util/dict_db.c
+++ b/postfix/src/util/dict_db.c
@@ -573,8 +573,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
{
DICT_DB *dict_db;
struct stat st;
- DB *db;
- char *db_path;
+ DB *db = 0;
+ char *db_path = 0;
int lock_fd = -1;
int dbfd;
@@ -624,12 +624,16 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
* db_open() create a non-existent file for us.
*/
#define LOCK_OPEN_FLAGS(f) ((f) & ~(O_CREAT|O_TRUNC))
+#define FREE_RETURN(e) do { \
+ DICT *_dict = (e); if (db) DICT_DB_CLOSE(db); \
+ if (db_path) myfree(db_path); return (_dict); \
+ } while (0)
if (dict_flags & DICT_FLAG_LOCK) {
if ((lock_fd = open(db_path, LOCK_OPEN_FLAGS(open_flags), 0644)) < 0) {
if (errno != ENOENT)
- return (dict_surrogate(class, path, open_flags, dict_flags,
- "open database %s: %m", db_path));
+ FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+ "open database %s: %m", db_path));
} else {
if (myflock(lock_fd, INTERNAL_LOCK, MYFLOCK_OP_SHARED) < 0)
msg_fatal("shared-lock database %s for open: %m", db_path);
@@ -644,8 +648,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
*/
#if DB_VERSION_MAJOR < 2
if ((db = dbopen(db_path, open_flags, 0644, type, tweak)) == 0)
- return (dict_surrogate(class, path, open_flags, dict_flags,
- "open database %s: %m", db_path));
+ FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+ "open database %s: %m", db_path));
dbfd = db->fd(db);
#endif
@@ -661,8 +665,8 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
if (open_flags & O_TRUNC)
db_flags |= DB_TRUNCATE;
if ((errno = db_open(db_path, type, db_flags, 0644, 0, tweak, &db)) != 0)
- return (dict_surrogate(class, path, open_flags, dict_flags,
- "open database %s: %m", db_path));
+ FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+ "open database %s: %m", db_path));
if (db == 0)
msg_panic("db_open null result");
if ((errno = db->fd(db, &dbfd)) != 0)
@@ -690,12 +694,12 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
#if DB_VERSION_MAJOR == 5 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR > 0)
if ((errno = db->open(db, 0, db_path, 0, type, db_flags, 0644)) != 0)
- return (dict_surrogate(class, path, open_flags, dict_flags,
- "open database %s: %m", db_path));
+ FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+ "open database %s: %m", db_path));
#elif (DB_VERSION_MAJOR == 3 || DB_VERSION_MAJOR == 4)
if ((errno = db->open(db, db_path, 0, type, db_flags, 0644)) != 0)
- return (dict_surrogate(class, path, open_flags, dict_flags,
- "open database %s: %m", db_path));
+ FREE_RETURN(dict_surrogate(class, path, open_flags, dict_flags,
+ "open database %s: %m", db_path));
#else
#error "Unsupported Berkeley DB version"
#endif
diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c
index 49e2b2c3c..7b7c0c56c 100644
--- a/postfix/src/util/dict_open.c
+++ b/postfix/src/util/dict_open.c
@@ -339,9 +339,11 @@ DICT *dict_open3(const char *dict_type, const char *dict_name,
if (dict_open_hash == 0)
dict_open_init();
if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0)
- msg_fatal("unsupported dictionary type: %s", dict_type);
+ return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
+ "unsupported dictionary type: %s", dict_type));
if ((dict = dp->open(dict_name, open_flags, dict_flags)) == 0)
- msg_fatal("opening %s:%s %m", dict_type, dict_name);
+ return (dict_surrogate(dict_type, dict_name, open_flags, dict_flags,
+ "cannot open %s:%s: %m", dict_type, dict_name));
if (msg_verbose)
msg_info("%s: %s:%s", myname, dict_type, dict_name);
/* XXX the choice between wait-for-lock or no-wait is hard-coded. */
diff --git a/postfix/src/util/dict_surrogate.c b/postfix/src/util/dict_surrogate.c
index 42dbe8fad..4183d9259 100644
--- a/postfix/src/util/dict_surrogate.c
+++ b/postfix/src/util/dict_surrogate.c
@@ -6,7 +6,7 @@
/* SYNOPSIS
/* #include