It's supposed to be 7bit, therefore quoted-printable encoding
is not expected. Problem reported by Griff. File:
bounce/bounce_notify_util.c.
+
+20170611
+
+ 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, but reduces file create performance
+ for Berkeley DB 3 .. 4.6. File: util/dict_db.c.
typedef struct {
DICT dict; /* generic members */
DB *db; /* open db file */
+#if DB_VERSION_MAJOR > 2
+ DB_ENV *dbenv;
+#endif
#if DB_VERSION_MAJOR > 1
DBC *cursor; /* dict_db_sequence() */
#endif
if (DICT_DB_CLOSE(dict_db->db) < 0)
msg_info("close database %s: %m (possible Berkeley DB bug)",
dict_db->dict.name);
+#if DB_VERSION_MAJOR > 2
+ dict_db->dbenv->close(dict_db->dbenv, 0);
+#endif
if (dict_db->key_buf)
vstring_free(dict_db->key_buf);
if (dict_db->val_buf)
dict_free(dict);
}
+#if DB_VERSION_MAJOR > 2
+
+/* dict_db_new_env - workaround for undocumented ./DB_CONFIG read */
+
+static DB_ENV *dict_db_new_env(const char *db_path)
+{
+ VSTRING *db_home_buf;
+ DB_ENV *dbenv;
+ u_int32_t cache_size_gbytes;
+ u_int32_t cache_size_bytes;
+ int ncache;
+
+ if ((errno = db_env_create(&dbenv, 0)) != 0)
+ msg_fatal("create DB environment: %m");
+#if DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 7)
+ if ((errno = dbenv->get_cachesize(dbenv, &cache_size_gbytes,
+ &cache_size_bytes, &ncache)) != 0)
+ msg_fatal("get DB cache size: %m");
+ if (cache_size_gbytes == 0 && cache_size_bytes < dict_db_cache_size) {
+ if ((errno = dbenv->set_cache_max(dbenv, cache_size_gbytes,
+ dict_db_cache_size)) != 0)
+ msg_fatal("set DB max cache size %d: %m", dict_db_cache_size);
+ if ((errno = dbenv->set_cachesize(dbenv, cache_size_gbytes,
+ dict_db_cache_size, ncache)) != 0)
+ msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
+ }
+#endif
+ /* XXX db_home is also the default directory for the .db file. */
+ db_home_buf = vstring_alloc(100);
+ if ((errno = dbenv->open(dbenv, sane_dirname(db_home_buf, db_path),
+ DB_INIT_MPOOL | DB_CREATE | DB_PRIVATE, 0)) != 0)
+ msg_fatal("open DB environment: %m");
+ vstring_free(db_home_buf);
+ return (dbenv);
+}
+
+#endif
+
/* dict_db_open - open data base */
static DICT *dict_db_open(const char *class, const char *path, int open_flags,
#if DB_VERSION_MAJOR > 1
int db_flags;
+#endif
+#if DB_VERSION_MAJOR > 2
+ DB_ENV *dbenv;
+
#endif
/*
db_flags |= DB_CREATE;
if (open_flags & O_TRUNC)
db_flags |= DB_TRUNCATE;
- if ((errno = db_create(&db, 0, 0)) != 0)
+ if ((errno = db_create(&db, dbenv = dict_db_new_env(db_path), 0)) != 0)
msg_fatal("create DB database: %m");
if (db == 0)
msg_panic("db_create null result");
- if ((errno = db->set_cachesize(db, 0, dict_db_cache_size, 0)) != 0)
- msg_fatal("set DB cache size %d: %m", dict_db_cache_size);
if (type == DB_HASH && db->set_h_nelem(db, DICT_DB_NELM) != 0)
msg_fatal("set DB hash element count %d: %m", DICT_DB_NELM);
#if DB_VERSION_MAJOR == 6 || DB_VERSION_MAJOR == 5 || \
if (dict_flags & DICT_FLAG_FOLD_FIX)
dict_db->dict.fold_buf = vstring_alloc(10);
dict_db->db = db;
+#if DB_VERSION_MAJOR > 2
+ dict_db->dbenv = dbenv;
+#endif
#if DB_VERSION_MAJOR > 1
dict_db->cursor = 0;
#endif