-TADDR_MATCH_LIST
-TADDR_PATTERN
-TALIAS_TOKEN
+-TALLOWED_PARENT
-TANVIL_CLNT
-TANVIL_LOCAL
-TANVIL_MAX
-TMKMAP_OPEN_FN
-TMKMAP_OPEN_INFO
-TMKMAP_SDBM
+-TMOCK_OPEN_AS_REQ
+-TMOCK_SPAWN_CMD_REQ
+-TMOCK_STAT_REQ
+-TMSG_CAPTURE
-TMSG_STATS
-TMULTI_SERVER
-TMVECT
-TNAME_CODE
-TNAME_MASK
-TNBBIO
+-TNBDB_PATH_SUFFIX
-TNVTABLE_INFO
-TOPTIONS
-TOSSL_DGST
-Tsize_t
-Tsockaddr
-Tsockaddr_storage
+-Tspawn_args
-Tssize_t
-Tssl_cipher_stack_t
-Tssl_comp_stack_t
+-Tstat
-Ttime_t
-Ttlsa_filter
-Tuint16_t
reflects the current status of the software.
Added -d (don't disconnect) and -c (show running counter)
- option to te smtp-source test program. These tools are
+ option to the smtp-source test program. These tools are
great torture tests for the mail software, and for the
system that it runs on.
that an IPv6 address needs to be enclosed in [] for the
debug_peer_list and qmqpd_authorized_clients parameters.
File: proto/postconf.proto.
+
+20260219
+
+ Feature: support to migrate a working Postfix configuration
+ that uses hash: and btree: tables, to an OS that has deleted
+ Berkeley DB support. Files: Makefile.in, conf/postfix-files,
+ conf/postfix-non-bdb-script, conf/postfix-script,
+ global/Makefile.in, global/allowed_prefix.c,
+ global/allowed_prefix.h, global/allowed_prefix_test.c,
+ global/mail_params.c, global/mail_params.h, global/mail_proto.h,
+ global/nbdb_clnt.c, global/nbdb_clnt.h, global/nbdb_redirect.c,
+ global/nbdb_redirect.h, global/nbdb_redirect_test.c,
+ global/nbdb_surrogate.c, global/nbdb_surrogate.h,
+ global/nbdb_surrogate_test.c, global/nbdb_util.c,
+ global/nbdb_util.h, global/nbdb_util_test.c, html/Makefile.in,
+ man/Makefile.in, mantools/postlink, proto/Makefile.in,
+ proto/NON_BERKELEYDB_README.html, proto/postconf.proto,
+ proto/stop, proto/stop.double-cc,
+ proto/stop.double-install-proto-text, proto/stop.spell-cc,
+ proto/stop.spell-history, proto/stop.spell-proto-html,
+ smtp/smtp_connect.c, testing/Makefile.in, testing/mock_open_as.c,
+ testing/mock_open_as.h, testing/mock_spawn_command.c,
+ testing/mock_spawn_command.h, testing/mock_stat.c,
+ testing/mock_stat.h, testing/msg_capture.c, testing/msg_capture.h,
+ util/Makefile.in, util/dict.h, util/dict_open.c,
+ util/dict_surrogate.c, util/open_as.c, util/open_as.h,
+ util/spawn_command.c, util/spawn_command.h, util/vstream.h,
+ util/wrap_stat.c, util/wrap_stat.h.
+
+20260220
+
+ Documentation: TESTING, proto/NON_BERKELEYDB_README.html,
+ proto/stop.spell-proto-html, postfix/postfix.c, conf/postfix-files,
+ mantools/postlink, global/nbdb_clnt.c.
+
+ Portability: testing/msg_capture.c.
+
+ Migration to "No Berkeley DB": update default values
+ for alias_maps and alias_database, and replace the
+ platform-dependent database type with $default_database_type.
+ File: src/util/sys_defs.h.
+
+ Documentation: update obsolete references to "dbm or db"
+ in xxx_table(5) manpages and make text more consistent.
+ Files: proto/cidr_table, proto/ldap_table, proto/memcache_table,
+ proto/mongodb_table, proto/mysql_table, proto/nisplus_table,
+ proto/pcre_table, proto/pgsql_table, proto/regexp_table,
+ proto/socketmap_table, proto/sqlite_table, proto/tcp_table.
+
+ Documentation: made the postmap(1) and postmap(1) manpages
+ more consistent in the discussion of the default_data_base,
+ and moved that text to a more visible location. Files:
+ postalias/postalias.c, postmap/postmap.c.
+
+ Documentation: updated 'man5' manpages for changes in default
+ indexed file types. Files: proto/access, proto/canonical,
+ proto/generic, proto/relocated, proto/transport, proto/virtual.
+
+ Incompatibility: The alias_maps and alias_database parameter
+ default values have changed from hash:/path/to/aliases (or
+ dbm:/path/to/aliases) to $default_database_type:/path/to/aliases.
+ This simplifies the migration away from Berkeley DB. File:
+ util/sys_defs.h.
+
+20260221
+
+ Testing: factored out the mock cdb and lmdb code to make
+ more tests independent of whether the build includes support
+ for cdb and lmdb. Files: global/Makefile.in,
+ global/nbdb_redirect_test.c, global/nbdb_util_test.c,
+ nbdb_reindexd/Makefile.in, nbdb_reindexd/nbdb_index_as_test.c,
+ nbdb_reindexd/nbdb_process_test.c, testing/Makefile.in,
+ testing/mock_dict.c, testing/mock_dict.h.
+
+20260222
+
+ Cleanup: migration service name word-smithing. Files:
+ mantools/postlink, proto/postconf.proto, global/mail_params.h.
+
+ Documentation: missing DEF_SHLIB_DIR in INSTALL. File:
+ proto/install.html.
+
+20260225
+
+ Documentation: examples now use lmdb plus text about implicit
+ types with "postmap /path/to/file" and available explicit types.
+ Files: proto/INSTALL.html, proto/SASL_README.html,
+ proto/STANDARD_CONFIGURATION_README.html, proto/UUCP_README.html,
+ proto/VIRTUAL_README.html.
+
+ Workaround: as of Postfix 3.11, the default alias_maps value
+ contains $default_database_type:/path/to/aliases, instead
+ of a hard-coded type hash. If default_database_type was
+ changed from hash to lmdb (or cdb), then the indexed file
+ /path/to/aliases.lmdb (or /path/to/aliases.cdb) will likely
+ not exist.
+
+ Unfortunately, if $default_database_type has changed from
+ hash to lmdb (or cdb) Postfix will not try to use
+ hash:/path/to/aliases, and will not trigger compatibility
+ workarounds that are implemented with "enable-redirect" or
+ "enable-reindex". This would be a gap in migration coverage.
+
+ To avoid this, synthesize a stand-alone re-indexing request.
+ Files: conf/postfix-script, proto/NON_BERKELEYDB_README.html.
+ This is needed only for databases specified in alias_maps.
+
+ Postfix works on Linux 7.x kernels. Frank Scheiner. Files:
+ makedefs, util/sys_defs.h.
+
+20260226
+
+ Documentation: update postconf(5) examples: all examples
+ show "lmdb", and mention cdb, hash, etc. as alternatives.
+ File: proto/postconf.proto.
+
+ Cleanup: wordsmithing of recently-edited README files.
+ proto/SASL_README.html, proto/STANDARD_CONFIGURATION_README.html,
+ proto/UUCP_README.html.
+
+ Cleanup: fix HTML validator complaint. File:
+ proto/postconf.html.prolog
+
+ Cleanup: make only one attempt to generate an indexed file
+ for $alias_maps. This creates a status file
+ $config_directory/check-alias-maps-migration-done. File:
+ conf/postfix-script.
+
+20260227
+
+ Documentation: new Appendix with Mailman migration
+ instructions. File: proto/NON_BERKELEYDB_README.html.
+
+ Cleanup: missing #include <stdlib.h>, reported on Solaris 11.4.
+ File: nbdb_reindexd/nbdb_reindexd.c.
+
+ Cleanup: log a fatal error instead of dereferencing a null
+ pointer. Fedor Vorobev. File: util/dict_db.c.
+
+ Bitrot: patches in anticipation of OpenSSL 4. Viktor Dukhovni.
+ Files: posttls-finger/posttls-finger.c, tls/tls_client.c,
+ tls/tls.h, tls/tls_misc.c, tls/tls_verify.c.
|_____________________|____________________|
|config_directory |/etc/postfix |
|_____________________|____________________|
- |default_database_type|lmdb or hash |
+ |default_database_type|lmdb, cdb, or hash |
|_____________________|____________________|
|default_cache_db_type|lmdb or btree |
|_____________________|____________________|
|_________________|_____________________|____________________|
|DEF_CONFIG_DIR |config_directory |/etc/postfix |
|_________________|_____________________|____________________|
- |DEF_DB_TYPE |default_database_type|lmdb or hash |
+ |DEF_DB_TYPE |default_database_type|lmdb, cdb, or hash |
|_________________|_____________________|____________________|
|DEF_CACHE_DB_TYPE|default_cache_db_type|lmdb or btree |
|_________________|_____________________|____________________|
|_________________|_____________________|____________________|
|DEF_SENDMAIL_PATH|sendmail_path |/usr/sbin/sendmail |
|_________________|_____________________|____________________|
+ |DEF_SHLIB_DIR |shlib_directory |/usr/lib/postfix |
+ |_________________|_____________________|____________________|
Note: the data_directory parameter (for caches and pseudo-random numbers) was
-introduced with Postfix version 2.5.
+introduced with Postfix version 2.5; shlib_directory (for shared-library
+objects and database plugins) with Postfix version 3.0.
4.7 - Overriding other compile-time features
|_______________________________|_____________________________________________|
|| |Do not build with Berkeley DB support. By |
|| |default, Berkeley DB support is compiled in |
-|| |on platforms that are known to support this |
-||-DNO_DB |feature. If you override this, then you |
+|| |on platforms that have historically supported|
+||-DNO_DB |this feature. If you override this, then you |
|| |probably should also override |
|| |default_database_type or DEF_DB_TYPE as |
|| |described in section 4.6. |
First, be sure to update the text file with aliases for root, postmaster and
"postfix" that forward mail to a real person. Postfix has a sample aliases file
-/etc/postfix/aliases that you can adapt to local conditions.
+/etc/postfix/aliases that you can copy and adapt to local conditions. /p>
/etc/aliases:
root: you
# sendmail -bi
# postalias /etc/aliases (pathname is system dependent!)
+The form "postalias /etc/aliases" builds a default-type indexed file. Use
+"postalias type:/etc/aliases" to specify an explicit type (it should match the
+type in the output from "postconf -x alias_maps").
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "postconf -m".
+
11 - To chroot or not to chroot
Postfix daemon processes can be configured (via master.cf) to run in a chroot
src/postsuper src/qmqpd src/spawn src/flush src/verify \
src/virtual src/proxymap src/anvil src/scache src/discard src/tlsmgr \
src/postmulti src/postscreen src/dnsblog src/tlsproxy \
- src/posttls-finger src/postlogd src/testing
+ src/posttls-finger src/postlogd src/nbdb_reindexd src/testing
MANDIRS = proto man html
LIBEXEC = libexec/post-install libexec/postfix-script libexec/postfix-wrapper \
- libexec/postmulti-script libexec/postfix-tls-script
+ libexec/postmulti-script libexec/postfix-non-bdb-script \
+ libexec/postfix-tls-script
PLUGINS = meta/dynamicmaps.cf
META = meta/main.cf.proto meta/master.cf.proto meta/postfix-files \
meta/makedefs.out $(PLUGINS)
libexec/postfix-script: conf/postfix-script
rm -f $@ && ln -f $? $@
+libexec/postfix-non-bdb-script: conf/postfix-non-bdb-script
+ rm -f $@ && ln -f $? $@
+
libexec/postfix-tls-script: conf/postfix-tls-script
rm -f $@ && ln -f $? $@
L\bLo\boo\bok\bku\bup\bp t\bta\bab\bbl\ble\bes\bs (\b(d\bda\bat\bta\bab\bba\bas\bse\bes\bs)\b)
* DATABASE_README: Lookup table overview
+ * NON_BERKELEYDB_README: Non-Berkeley-DB migration
* DB_README: Berkeley DB Howto
* CDB_README: CDB Howto
* LDAP_README: LDAP Howto
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|config_directory |/etc/postfix |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |default_database_type|lmdb or hash |
+ |default_database_type|lmdb, cdb, or hash |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|default_cache_db_type|lmdb or btree |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|DEF_CONFIG_DIR |config_directory |/etc/postfix |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
- |DEF_DB_TYPE |default_database_type|lmdb or hash |
+ |DEF_DB_TYPE |default_database_type|lmdb, cdb, or hash |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|DEF_CACHE_DB_TYPE|default_cache_db_type|lmdb or btree |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|DEF_SENDMAIL_PATH|sendmail_path |/usr/sbin/sendmail |
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |DEF_SHLIB_DIR |shlib_directory |/usr/lib/postfix |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
Note: the data_directory parameter (for caches and pseudo-random numbers) was
-introduced with Postfix version 2.5.
+introduced with Postfix version 2.5; shlib_directory (for shared-library
+objects and database plugins) with Postfix version 3.0.
4\b4.\b.7\b7 -\b- O\bOv\bve\ber\brr\bri\bid\bdi\bin\bng\bg o\bot\bth\bhe\ber\br c\bco\bom\bmp\bpi\bil\ble\be-\b-t\bti\bim\bme\be f\bfe\bea\bat\btu\bur\bre\bes\bs
|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
|| |Do not build with Berkeley DB support. By |
|| |default, Berkeley DB support is compiled in |
-|| |on platforms that are known to support this |
-||-DNO_DB |feature. If you override this, then you |
+|| |on platforms that have historically supported|
+||-DNO_DB |this feature. If you override this, then you |
|| |probably should also override |
|| |default_database_type or DEF_DB_TYPE as |
|| |described in section 4.6. |
First, be sure to update the text file with aliases for root, postmaster and
"postfix" that forward mail to a real person. Postfix has a sample aliases file
-/etc/postfix/aliases that you can adapt to local conditions.
+/etc/postfix/aliases that you can copy and adapt to local conditions. /p>
/etc/aliases:
root: you
# sendmail -bi
# postalias /etc/aliases (pathname is system dependent!)
+The form "postalias /etc/aliases" builds a default-type indexed file. Use
+"postalias type:/etc/aliases" to specify an explicit type (it should match the
+type in the output from "postconf -x alias_maps").
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
1\b11\b1 -\b- T\bTo\bo c\bch\bhr\bro\boo\bot\bt o\bor\br n\bno\bot\bt t\bto\bo c\bch\bhr\bro\boo\bot\bt
Postfix daemon processes can be configured (via master.cf) to run in a chroot
--- /dev/null
+P\bPo\bos\bst\btf\bfi\bix\bx N\bNo\bon\bn-\b-B\bBe\ber\brk\bke\bel\ble\bey\by-\b-D\bDB\bB m\bmi\big\bgr\bra\bat\bti\bio\bon\bn
+
+-------------------------------------------------------------------------------
+
+T\bTa\bab\bbl\ble\be o\bof\bf c\bco\bon\bnt\bte\ben\bnt\bts\bs
+
+ * Introduction
+ * Background
+ * Skip this if not building Postfix from source, or if your system still
+ supports Berkeley DB
+ * Migration support level overview
+ * Level 'disable': manual migration
+ * Level 'enable-redirect': database aliasing
+ * Level 'enable-reindex': redirect and automatically generate non-Berkeley-DB
+ indexed files
+ * Addressing errors with automatic indexed file generation
+ * Appendix: Mailman integration
+
+I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
+
+(Please see the Appendix for Mailman integration tips.)
+
+After running the same Postfix configuration for a decade or more, there is a
+rude awakening when you update the OS to a newer version that has deleted its
+support for Berkeley DB. Postfix programs fail to open all hash: and btree:
+tables with messages like this:
+
+ Berkeley DB support for 'hash:/etc/postfix/virtual' is not available
+ for this build; see https://www.postfix.org/NON_BERKELEYDB_README.html
+ for alternatives
+
+This document comes to the rescue, with strategies to migrate an existing
+Postfix configuration that uses Berkeley DB hash: and btree: database files, to
+an OS distribution that has removed Berkeley DB support, with a Postfix
+configuration that uses lmdb: (or a combination of cdb: and lmdb:).
+
+By the way, you don't have to wait until Berkeley DB support is removed; your
+can proactively use the steps described here on a system that still has
+Berkeley DB, to migrate a Postfix configuration from Berkeley DB to lmdb: (or a
+combination of cdb: and lmdb:).
+
+B\bBa\bac\bck\bkg\bgr\bro\bou\bun\bnd\bd
+
+Historically, Postfix has used Berkeley DB hash: and btree: for key-value
+stores, as indicated in the "With Berkeley DB" table column below. In a world
+without Berkeley DB, good replacements are cdb: and lmdb: as indicated in the
+"No Berkeley DB" column.
+
+ _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b
+ |P\bPu\bur\brp\bpo\bos\bse\be |W\bWi\bit\bth\bh B\bBe\ber\brk\bke\bel\ble\bey\by D\bDB\bB |N\bNo\bo B\bBe\ber\brk\bke\bel\ble\bey\by D\bDB\bB |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |Mostly-static data| |default_database_type=lmdb|
+ |such as aliases, |default_database_type=hash |or |
+ |transport_maps, | |default_database_type=cdb |
+ |access tables | | |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+ |Dynamic caches | | |
+ |maintained by | | |
+ |postscreen(8), |default_cache_db_type=btree|default_cache_db_type=lmdb|
+ |verify(8), tlsmgr | | |
+ |(8) | | |
+ |_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b|_\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b _\b |
+
+The default values for default_database_type and default_cache_db_type may be
+specified at build time (see the section below, and they may be changed later
+by editing main.cf, for example with the postconf(1) command.)
+
+The sections that follow present three migration strategies with different
+levels of assistance by tooling that was developed for Postfix 3.11 and later.
+
+S\bSk\bki\bip\bp t\bth\bhi\bis\bs i\bif\bf n\bno\bot\bt b\bbu\bui\bil\bld\bdi\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx f\bfr\bro\bom\bm s\bso\bou\bur\brc\bce\be,\b, o\bor\br i\bif\bf y\byo\bou\bur\br s\bsy\bys\bst\bte\bem\bm s\bst\bti\bil\bll\bl s\bsu\bup\bpp\bpo\bor\brt\bts\bs
+B\bBe\ber\brk\bke\bel\ble\bey\by D\bDB\bB.\b.
+
+Click here to skip to the next section.
+
+On systems that have removed Berkeley DB support, run "make makefiles" with a
+CCARGS value that (also) contains "-DNO_DB", and specify appropriate values for
+default_database_type (lmdb or cdb) and default_cache_db_type (lmdb).
+
+In the examples below, the "..." are place holders any dependencies that you
+build Postfix with, such as CDB, LDAP, LMDB, MySQL/MariaDB, OpenSSL, SASL, and
+so on.
+
+Example 1: use lmdb: for both default_database_type (read-mostly lookup tables)
+and default_cache_db_type (read-write caches). Terminal input is b\bbo\bol\bld\bd, output
+is normal font.
+
+ $ m\bma\bak\bke\be m\bma\bak\bke\bef\bfi\bil\ble\bes\bs C\bCC\bCA\bAR\bRG\bGS\bS=\b="\b"-\b-D\bDN\bNO\bO_\b_D\bDB\bB .\b..\b..\b."\b" \\b\
+ d\bde\bef\bfa\bau\bul\blt\bt_\b_d\bda\bat\bta\bab\bba\bas\bse\be_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb \\b\
+ d\bde\bef\bfa\bau\bul\blt\bt_\b_c\bca\bac\bch\bhe\be_\b_d\bdb\bb_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb .\b..\b..\b. \\b\
+ A\bAU\bUX\bXL\bLI\bIB\bBS\bS.\b..\b..\b.
+
+Example 2: alternative form that produces the same result.
+
+ $ e\bex\bxp\bpo\bor\brt\bt C\bCC\bCA\bAR\bRG\bGS\bS=\b="\b"-\b-D\bDN\bNO\bO_\b_D\bDB\bB .\b..\b..\b."\b"
+ $ e\bex\bxp\bpo\bor\brt\bt d\bde\bef\bfa\bau\bul\blt\bt_\b_d\bda\bat\bta\bab\bba\bas\bse\be_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb
+ $ e\bex\bxp\bpo\bor\brt\bt d\bde\bef\bfa\bau\bul\blt\bt_\b_c\bca\bac\bch\bhe\be_\b_d\bdb\bb_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb
+ $ e\bex\bxp\bpo\bor\brt\bt A\bAU\bUX\bXL\bLI\bIB\bBS\bS.\b..\b..\b.
+ ...
+ $ m\bma\bak\bke\be m\bma\bak\bke\bef\bfi\bil\ble\bes\bs
+
+Another alternative is to use cdb for default_database_type (read-mostly lookup
+tables) and lmdb for default_cache_db_type (read-write caches).
+
+M\bMi\big\bgr\bra\bat\bti\bio\bon\bn s\bsu\bup\bpp\bpo\bor\brt\bt l\ble\bev\bve\bel\bl o\bov\bve\ber\brv\bvi\bie\bew\bw
+
+The goal of the migration is clear: stop using hash: and btree:, and use lmdb:
+or cdb: instead. If your configuration is simple or if you are familiar with
+Postfix configuration, a few "grep" commands will find all the problems, and a
+few edits will be easy to make.
+
+If, on the other hand, you are not familiar with the details of your Postfix
+configuration, then this document provides options where Postfix can help.
+
+Postfix 3.11 introduces multiple levels of migration support. You can use the
+command "postfix non-bdb status" to view the migration support level. This is
+what the default should look like (terminal input is b\bbo\bol\bld\bd, output is normal
+font):
+
+ # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb s\bst\bta\bat\btu\bus\bs
+ disable
+
+In increasing order, the support levels are:
+
+disable (manual migration)
+ You start up Postfix, watch the logging when Postfix programs fail to open
+ a hash: or btree: table, edit Postfix configuration files to use lmdb: or
+ cdb:, then run postmap(1) or postalias(1) commands to create lmdb: or cdb:
+ indexed database files. Use this option if you are familiar with Postfix
+ configuration.
+
+ This will not fix the integration with Mailman versions from before gitlab
+ commit 8fa56b72 (May 2025) and other software that are broken when they
+ want to use "postmap hash:/path/to/file". Mailman uses this to maintain a
+ table with mailing list contact addresses. For that, you need to use the
+ next-up level.
+
+enable-redirect (database aliasing)
+ This level implicitly redirects a request to access hash:/path/to/file to
+ $default_database_type:/path/to/file, and redirects a request to access a
+ btree:/path/to/file to $default_cache_db_type:/path/to/file.
+
+ This still requires manually running postmap(1) or postalias(1) commands,
+ but "fixes" the integration with Mailman versions from before gitlab commit
+ 8fa56b72 (May 2025) and other software when they want to use "postmap hash:
+ /path/to/file", and Berkeley DB support is not available. Such commands
+ will implicitly create a new lmdb: or cdb: indexed database file, depending
+ on the default_database_type value.
+
+enable-reindex (aliasing, plus running postmap(1) or postalias(1))
+ This level implements "enable-redirect (database aliasing)", and also runs
+ the postmap(1) or postalias(1) command to create a new lmdb or cdb indexed
+ database file. This uses the nbdb_reindexd(8) daemon.
+
+The levels enable-redirect and enable-reindex leave some technical debt:
+configurations that still say hash: or btree: (even if they use lmdb: or cdb:
+behind the scene).
+
+ * Using these levels gives you extra time to prepare for a long-term
+ configuration change that replaces hard-coded instances of hash: with the
+ value of default_database_type, and that replaces btree: with the value of
+ default_cache_db_type.
+
+ * Depending on your use of other software that wants to use postmap(1) or
+ postalias(1) commands, you may have to permanently the leave the enable-
+ redirect level active.
+
+After this overview, the sections that follow will go into more detail.
+
+L\bLe\bev\bve\bel\bl '\b'd\bdi\bis\bsa\bab\bbl\ble\be'\b':\b: m\bma\ban\bnu\bua\bal\bl m\bmi\big\bgr\bra\bat\bti\bio\bon\bn
+
+To disable all non-Berkeley-DB migration features use the "postfix non-bdb"
+command:
+
+ # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb d\bdi\bis\bsa\bab\bbl\ble\be
+ # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+
+This will edit main.cf to remove a non_bdb_migration_level setting and the
+level revert to its implicit default (disable), and will edit master.cf to
+remove an entry for the reindex service.
+
+This setting will cause problems with Mailman versions from before gitlab
+commit 8fa56b72 (May 2025) and other software that wants to use "postmap hash:/
+path/to/file" (or similar postalias commands), and Berkeley DB support is no
+longer available. In that case, you will need the "enable-redirect" migration
+support level.
+
+A manual migration process goes like this:
+
+ * Stop Postfix.
+
+ * Make lmdb: the default for both default_database_type (read-mostly lookup
+ tables) and default_cache_db_type (read-write caches):
+
+ # p\bpo\bos\bst\btc\bco\bon\bnf\bf d\bde\bef\bfa\bau\bul\blt\bt_\b_d\bda\bat\bta\bab\bba\bas\bse\be_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb d\bde\bef\bfa\bau\bul\blt\bt_\b_c\bca\bac\bch\bhe\be_\b_d\bdb\bb_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb
+
+ * Alternatively, make cdb: the default for default_database_type (read-mostly
+ lookup tables) and lmdb: the default for default_cache_db_type (read-write
+ caches):
+
+ # p\bpo\bos\bst\btc\bco\bon\bnf\bf d\bde\bef\bfa\bau\bul\blt\bt_\b_d\bda\bat\bta\bab\bba\bas\bse\be_\b_t\bty\byp\bpe\be=\b=c\bcd\bdb\bb d\bde\bef\bfa\bau\bul\blt\bt_\b_c\bca\bac\bch\bhe\be_\b_d\bdb\bb_\b_t\bty\byp\bpe\be=\b=l\blm\bmd\bdb\bb
+
+ * Look for hash: and btree: references in Postfix configuration files.
+ Instead of /etc/postfix use the pathname in the output from "postconf -
+ x config_directory".
+
+ # g\bgr\bre\bep\bp -\b-E\bE -\b-r\br '\b'(\b(h\bha\bas\bsh\bh|\b|b\bbt\btr\bre\bee\be)\b):\b:/\b/'\b' /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx
+
+ * For each instance in the "grep" output :
+
+ o Edit the configuration file and replace "hash" with "lmdb" or "cdb"
+ (use the same value as the output from "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-h\bhx\bx
+ d\bde\bef\bfa\bau\bul\blt\bt_\b_d\bda\bat\bta\bab\bba\bas\bse\be_\b_t\bty\byp\bpe\be") and replace "btree" with "lmdb".
+
+ o If this instance has no source file (only the ".db" file exists),
+ proceed with the next instance of "grep" output.
+
+ o If this instance appears in the output from "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-h\bhP\bPP\bPx\bx '\b'*\b*/\b/*\b*/\b/
+ a\bal\bli\bia\bas\bs_\b_m\bma\bap\bps\bs'\b' |\b| s\bso\bor\brt\bt -\b-u\bu", run the postalias(1) command. If this instance
+ is like "lmdb:/path/to/source":
+
+ # p\bpo\bos\bst\bta\bal\bli\bia\bas\bs l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/s\bso\bou\bur\brc\bce\be
+
+ Instead of "lmdb:" use "cdb:" if the instance is like "cdb:/path/to/
+ source".
+
+ o Otherwise, run the postmap(1) command. If this instance is like "lmdb:/
+ path/to/source":
+
+ # p\bpo\bos\bst\btm\bma\bap\bp l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/s\bso\bou\bur\brc\bce\be
+
+ Instead of "lmdb:" use "cdb:" if this instance is like "cdb:/path/to/
+ source".
+
+ * Start Postfix, watch the log for warnings about files that cannot be
+ opened, find the configuration file that still uses "hash" or "btree", and
+ repeat the steps above.
+
+ * It is now safe to delete the unused ".db" files.
+
+L\bLe\bev\bve\bel\bl '\b'e\ben\bna\bab\bbl\ble\be-\b-r\bre\bed\bdi\bir\bre\bec\bct\bt'\b':\b: d\bda\bat\bta\bab\bba\bas\bse\be a\bal\bli\bia\bas\bsi\bin\bng\bg
+
+To enable this migration support level, use:
+
+ # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb e\ben\bna\bab\bbl\ble\be-\b-r\bre\bed\bdi\bir\bre\bec\bct\bt
+ # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+
+This postfix non-bdb" command edits main.cf to enable redirection (aliasing)
+from Berkeley DB types "hash" and "btree" to the non-Berkeley-DB types
+specified with $default_database_type and $default_cache_db_type. Custom
+redirection may be configured with non_bdb_custom_mapping. This command also
+edits master.cf to remove an unused nbdb_reindex service entry.
+
+This migration support level will not automatically create non-Berkeley-DB
+indexed database files. Instead, Postfix programs will log an error as they
+fail to open an indexed database file, and will leave it to the system
+administrator to run postmap(1) or postalias(1) to create that file.
+
+For each instance of "hash:/path/to/source" or "btree:/path/to/source" that
+requires manually running postmap(1) or postalias(1):
+
+ * If this instance appears in the output from "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-h\bhP\bPP\bPx\bx '\b'*\b*/\b/*\b*/\b/
+ a\bal\bli\bia\bas\bs_\b_m\bma\bap\bps\bs'\b' |\b| s\bso\bor\brt\bt -\b-u\bu", run the postalias(1) command. If this instance is
+ like "lmdb:/path/to/source":
+
+ # p\bpo\bos\bst\bta\bal\bli\bia\bas\bs l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/s\bso\bou\bur\brc\bce\be
+
+ Instead of "lmdb:" use "cdb:" if the instance is like "cdb:/path/to/
+ source".
+
+ * Otherwise, run the postmap(1) command. If this instance is like "lmdb:/
+ path/to/source":
+
+ # p\bpo\bos\bst\btm\bma\bap\bp l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/s\bso\bou\bur\brc\bce\be
+
+ Instead of "lmdb:" use "cdb:" if this instance is like "cdb:/path/to/
+ source".
+
+This migration support level will fix problems with Mailman versions from
+before May 2025 and other software that wants to use "postmap hash:/path/to/
+file". With database redirection, such commands will implicitly create an
+indexed file for $default_database_type:/path/to/file (similar aliasing happens
+for postalias commands).
+
+The command "postfix non-bdb enable-redirect" will refuse to make any changes
+when default_database_type or default_cache_db_type specify a hash: or btree:
+type.
+
+L\bLe\bev\bve\bel\bl '\b'e\ben\bna\bab\bbl\ble\be-\b-r\bre\bei\bin\bnd\bde\bex\bx'\b':\b: r\bre\bed\bdi\bir\bre\bec\bct\bt a\ban\bnd\bd a\bau\but\bto\bom\bma\bat\bti\bic\bca\bal\bll\bly\by g\bge\ben\bne\ber\bra\bat\bte\be n\bno\bon\bn-\b-B\bBe\ber\brk\bke\bel\ble\bey\by-\b-D\bDB\bB
+i\bin\bnd\bde\bex\bxe\bed\bd f\bfi\bil\ble\bes\bs
+
+NOTE: this level should be used only temporarily to generate most of the non-
+Berkeley-DB indexed files that Postfix needs. Leaving this enabled may expose
+the system to privilege-escalation attacks. There are no security concerns for
+using enable-redirect.
+
+To enable this migration support level, use:
+
+ # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb e\ben\bna\bab\bbl\ble\be-\b-r\bre\bei\bin\bnd\bde\bex\bx
+ # p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd
+
+This postfix non-bdb command edits main.cf to set the non-Berkeley-DB migration
+support level, and master.cf to add or replace an nbdb-reindex service entry.
+
+The resulting configuration implements not only the functionality of enable-
+redirect, but also automatically creates a non-Berkeley-DB indexed database
+file when a daemon program wants to access a file that does not exist. This
+uses the nbdb_reindexd(8) daemon to run postmap(1) or postalias(1) commands for
+databases that satisfy basic requirements to block privilege-escalation
+attacks. The number of requirements is large, but mainly, database files and
+their parent directory must not allow write access for group or other users,
+and their pathnames must match a list of trusted directory prefixes. The
+complete list of requirements is documented in nbdb_reindexd(8).
+
+This command immediately generates non-Berkeley-DB indexed files for command-
+line programs that lack privileges to send requests to the nbdb_reindexd(8)
+indexing server. This applies to "hash:" and "btree:" tables that are used by
+postqueue(1) and sendmail(1) as configured with authorized_flush_users and
+authorized_mailq_users, and used by sendmail(1) and postdrop(1) as configured
+with authorized_submit_users and local_login_sender_maps.
+
+The command "postfix non-bdb enable-reindex" will refuse to make any changes
+when default_database_type or default_cache_db_type specify a hash: or btree:
+type.
+
+The nbdb_reindexd(8) daemon will log when it successfully runs a postmap(1) or
+postalias(1) command. Examples, for a system with "default_database_type =
+lmdb":
+
+ successfully executed 'postmap lmdb:/etc/postfix/transport' as uid 0
+ successfully executed 'postalias lmdb:/etc/aliases' as uid 0
+
+See the section "Addressing errors with automatic indexed file generation" for
+the most likely errors that Postfix programs may log.
+
+Once there are no more errors from Postfix programs for about 24 hours, turn
+off automatic index generation by reducing the support level to enable-redirect
+with:
+
+ # postfix non-bdb enable-redirect
+ # postfix reload
+
+A\bAd\bdd\bdr\bre\bes\bss\bsi\bin\bng\bg e\ber\brr\bro\bor\brs\bs w\bwi\bit\bth\bh a\bau\but\bto\bom\bma\bat\bti\bic\bc i\bin\bnd\bde\bex\bxe\bed\bd f\bfi\bil\ble\be g\bge\ben\bne\ber\bra\bat\bti\bio\bon\bn
+
+U\bUn\bne\bex\bxp\bpe\bec\bct\bte\bed\bd p\bpa\bat\bth\bhn\bna\bam\bme\be e\ber\brr\bro\bor\brs\bs
+
+Depending on the location of your Postfix lookup tables, Postfix programs may
+log a request to add a trusted directory to the directories listed with
+non_bdb_migration_allow_root_prefixes or non_bdb_migration_allow_user_prefixes.
+
+Example, with line breaks added for readability:
+
+ could not execute command 'postmap lmdb:/path/to/file': table
+ /path/to/file has an unexpected pathname;
+
+ to allow automatic indexing as root, append its parent directory
+ to the non_bdb_migration_allow_root_prefixes setting (current setting
+ is: "/etc /usr/local/etc");
+
+ alternatively, execute the failed command by hand
+
+You have two options:
+
+ 1. If you think that the suggested change is safe, update the setting as
+ proposed and execute "postfix reload".
+
+ 2. Alternatively, you can execute the failed postmap(1) or postalias(1)
+ command by hand, and Postfix will not log the same error again.
+
+A similar request may be logged when a file needs to be indexed as a non-root
+user.
+
+U\bUn\bne\bex\bxp\bpe\bec\bct\bte\bed\bd f\bfi\bil\ble\be o\bor\br d\bdi\bir\bre\bec\bct\bto\bor\bry\by o\bow\bwn\bne\ber\br o\bor\br p\bpe\ber\brm\bmi\bis\bss\bsi\bio\bon\bns\bs
+
+Other errors may be logged when a database file or directory has an unexpected
+owner, or when it is writable by group or by other users.
+
+Example with line breaks added for readability:
+
+ could not execute command 'postmap lmdb:/path/to/file': legacy
+ indexed file '/path/to/file.db' is owned by uid '0', but parent
+ directory '/path/to' is owned or writable by other user;
+
+ to allow automatic indexing, correct the ownership or permissions;
+
+ alternatively, execute the failed command by hand
+
+Again, you have two options:
+
+ 1. Fix the ownership or permission error.
+
+ 2. Execute the failed postmap(1) or postalias(1) command by hand, and Postfix
+ will not log the same error again.
+
+Once there are no more errors from Postfix programs for about 24 hours, turn
+off automatic index generation by reducing the support level to enable-redirect
+with:
+
+ # postfix non-bdb enable-redirect
+ # postfix reload
+
+A\bAp\bpp\bpe\ben\bnd\bdi\bix\bx:\b: M\bMa\bai\bil\blm\bma\ban\bn i\bin\bnt\bte\beg\bgr\bra\bat\bti\bio\bon\bn
+
+This section has instructions to migrate an existing Mailman configuration that
+wants to use commands like "postmap hash:/path/to/file". Mailman uses such
+commands to maintain tables with mailing list contact addresses and domain
+names. This will break on systems that no longer have Berkeley DB support.
+
+Solutions:
+
+ * (Not recommended) Upgrade to a Mailman version that contains gitlab commit
+ 8fa56b72 (May 2025). Unfortunately, this has not yet been widely adopted by
+ OS distributions.
+
+ * Avoid Mailman changes, and use Postfix migration support described below.
+ In a nutshell, the postmap command will execute the command "postmap hash:/
+ path/to/file" as if the command specifies lmdb:/path/to/file (or cdb:,
+ depending on Postfix configuration).
+
+With Mailman3 the integration with Postfix using LMTP may look like:
+
+ /var/lib/mailman3/data/postfix_domains (domain names)
+ /var/lib/mailman3/data/postfix_domains.db (Berkeley DB hash file)
+ /var/lib/mailman3/data/postfix_lmtp (transport map)
+ /var/lib/mailman3/data/postfix_lmtp.db (Berkeley DB hash file)
+
+ Caution: the data directory may contain other files with names ending in
+ ".db" that are not part of the Mailman-Postfix integration. Do not tamper
+ with the other files.
+
+The relevant Postfix migration levels are:
+
+enable-redirect (redirect hash: to lmdb: or cdb:)
+ Command: # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb e\ben\bna\bab\bbl\ble\be-\b-r\bre\bed\bdi\bir\bre\bec\bct\bt
+
+ This will fix the problem that Mailman wants to use commands like "postmap
+ hash:/path/to/postfix_domains" and "postmap hash:/path/to/postfix_lmtp".
+
+ Instead of complaining about an unsupported database type, these postmap
+ commands will implicitly create ".lmdb" indexed files like (lmdb:/path/to/
+ postfix_domains or lmdb:/path/to/postfix_lmtp, or their cdb: versions
+ depending on the Postfix default_database_type setting).
+
+ This will not fix the problem that Postfix wants to use databases like
+ hash:/path/to/postfix_domains and hash::/path/to/postfix_lmtp. With enable-
+ redirect, these will redirect to ".lmdb" indexed files (good) but those
+ files do not yet exist (bad). You will need to create them by hand with
+ commands like:
+
+ # p\bpo\bos\bst\btm\bma\bap\bp l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/p\bpo\bos\bst\btf\bfi\bix\bx_\b_d\bdo\bom\bma\bai\bin\bns\bs
+ # p\bpo\bos\bst\btm\bma\bap\bp l\blm\bmd\bdb\bb:\b:/\b/p\bpa\bat\bth\bh/\b/t\bto\bo/\b/p\bpo\bos\bst\btf\bfi\bix\bx_\b_l\blm\bmt\btp\bp
+
+ After this, no further human action will be needed. When Mailman needs to
+ update these files, it will invoke postmap commands that will work as
+ promised above. Leave the Postfix migration level at enable-reindex until
+ you can upgrade to a newer Mailman version that supports Postfix with non-
+ Berkeley databases.
+
+enable-reindex (also automatically run postmap commands)
+ Command: # p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb e\ben\bna\bab\bbl\ble\be-\b-r\bre\bed\bdi\bir\bre\bec\bct\bt
+
+ In addition to "enable-redirect", Postfix will also try to run commands
+ like "postmap lmdb:/path/to/postfix_domains" and "postmap lmdb:/path/to/
+ postfix_lmtp". There will be some delay depending on the amount of mailing
+ list traffic; you may want to post a test message to make the postmap
+ commands happen sooner.
+
+ Postfix will log the postmap commands (or will log a request to make some
+ configuration changes; see "Addressing errors with automatic indexed file
+ generation" above).
+
+ Note: once these "postmap" commands have completed, you should reduce the
+ migration support level with the command "p\bpo\bos\bst\btf\bfi\bix\bx n\bno\bon\bn-\b-b\bbd\bdb\bb e\ben\bna\bab\bbl\ble\be-\b-r\bre\bed\bdi\bir\bre\bec\bct\bt".
+ For security reasons the enable-reindex level should not be permanently
+ enabled.
+
authenticated client is allowed to use a particular envelope sender address:
/etc/postfix/main.cf:
- s\bsm\bmt\btp\bpd\bd_\b_s\bse\ben\bnd\bde\ber\br_\b_l\blo\bog\bgi\bin\bn_\b_m\bma\bap\bps\bs =\b= h\bha\bas\bsh\bh:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bco\bon\bnt\btr\bro\bol\bll\ble\bed\bd_\b_e\ben\bnv\bve\bel\blo\bop\bpe\be_\b_s\bse\ben\bnd\bde\ber\brs\bs
+ s\bsm\bmt\btp\bpd\bd_\b_s\bse\ben\bnd\bde\ber\br_\b_l\blo\bog\bgi\bin\bn_\b_m\bma\bap\bps\bs =\b=
+ l\blm\bmd\bdb\bb:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bco\bon\bnt\btr\bro\bol\bll\ble\bed\bd_\b_e\ben\bnv\bve\bel\blo\bop\bpe\be_\b_s\bse\ben\bnd\bde\ber\brs\bs
smtpd_recipient_restrictions =
...
@example.net barney, fred, john@example.com,
mary@example.com
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bco\bon\bnt\btr\bro\bol\bll\ble\bed\bd_\b_e\ben\bnv\bve\bel\blo\bop\bpe\be_\b_s\bse\ben\bnd\bde\ber\brs\bs" after
+you change the controlled_envelope_senders file, to (re)build a default-type
+indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bco\bon\bnt\btr\bro\bol\bll\ble\bed\bd_\b_e\ben\bnv\bve\bel\blo\bop\bpe\be_\b_s\bse\ben\bnd\bde\ber\brs\bs"
+to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
With this, the reject_sender_login_mismatch restriction above will reject the
sender address in the MAIL FROM command if smtpd_sender_login_maps does not
specify the SMTP client's login name as an owner of that address.
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
permit_mynetworks
- check_sasl_access hash:/etc/postfix/sasl_access
+ check_sasl_access lmdb:/etc/postfix/sasl_access
permit_sasl_authenticated
...
# Use this when smtpd_sasl_local_domain=example.com.
username@example.com HOLD
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_a\bac\bcc\bce\bes\bss\bs" after you change the
+sasl_access file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_a\bac\bcc\bce\bes\bss\bs" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
D\bDe\bef\bfa\bau\bul\blt\bt a\bau\but\bth\bhe\ben\bnt\bti\bic\bca\bat\bti\bio\bon\bn d\bdo\bom\bma\bai\bin\bn
Postfix can append a domain name (or any other string) to a SASL login name
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
* The smtp_sasl_auth_enable setting enables client-side authentication. We
will configure the client's username and password information in the second
SASL client passwords. It opens the file as user root before it drops
privileges, and before entering an optional chroot jail.
- * Use the postmap command whenever you change the /etc/postfix/sasl_passwd
- file.
+ Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" after changing the
+ sasl_passwd file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" to specify an explicit type.
+
+ The default indexed file type is configured with the default_database_type
+ parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf
+ -\b-m\bm".
* If you specify the "[" and "]" in the relayhost destination, then you must
use the same form in the smtp_sasl_password_maps file.
/etc/postfix/main.cf:
smtp_sender_dependent_authentication = yes
- sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
+ sender_dependent_relayhost_maps =
+ lmdb:/etc/postfix/sender_relay
smtp_sasl_auth_enable = yes
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
user1@example.com [mail.example.com]:submission
user2@example.net [mail.example.net]
+ Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
* If you are creative, then you can try to combine the two tables into one
single MySQL database, and configure different Postfix queries to extract
the appropriate information.
- * Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb
- files. To find out what lookup tables Postfix supports, use the command
- "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" after you change the
+ sasl_passwd file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" to specify an explicit type.
- * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" whenever you change
- the sasl_passwd table.
+ The default indexed file type is configured with the default_database_type
+ parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf
+ -\b-m\bm".
- * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" whenever you change
- the sender_relay table.
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" after you change
+ the sender_relay file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" to specify an explicit type.
P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP/\b/L\bLM\bMT\bTP\bP c\bcl\bli\bie\ben\bnt\bt p\bpo\bol\bli\bic\bcy\by -\b- S\bSA\bAS\bSL\bL m\bme\bec\bch\bha\ban\bni\bis\bsm\bm p\bpr\bro\bop\bpe\ber\brt\bti\bie\bes\bs
this document.
1 /etc/postfix/main.cf:
- 2 smtp_generic_maps = hash:/etc/postfix/generic
+ 2 smtp_generic_maps = lmdb:/etc/postfix/generic
3
4 /etc/postfix/generic:
5 his@localdomain.local hisaccount@hisisp.example
extension of +local (this example assumes that the ISP supports "+" style
address extensions).
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/g\bge\ben\bne\ber\bri\bic\bc" whenever you change the
-generic table.
+generic file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/
+e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/g\bge\ben\bne\ber\bri\bic\bc" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
S\bSo\bol\blu\but\bti\bio\bon\bn 2\b2:\b: P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.1\b1 a\ban\bnd\bd e\bea\bar\brl\bli\bie\ber\br
2 myhostname = hostname.localdomain
3 mydomain = localdomain
4
- 5 canonical_maps = hash:/etc/postfix/canonical
+ 5 canonical_maps = lmdb:/etc/postfix/canonical
6
- 7 virtual_alias_maps = hash:/etc/postfix/virtual
+ 7 virtual_alias_maps = lmdb:/etc/postfix/virtual
8
9 /etc/postfix/canonical:
10 your-login-name your-account@your-isp.com
instead of sending it to the ISP. This part is not required but is
convenient.
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bca\ban\bno\bon\bni\bic\bca\bal\bl" whenever you change the
-canonical table.
+canonical file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bca\ban\bno\bon\bni\bic\bca\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" whenever you change the
-virtual table.
+virtual file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/
+e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
E\bEn\bna\bab\bbl\bli\bin\bng\bg S\bSA\bAS\bSL\bL a\bau\but\bth\bhe\ben\bnt\bti\bic\bca\bat\bti\bio\bon\bn i\bin\bn t\bth\bhe\be P\bPo\bos\bst\btf\bfi\bix\bx S\bSM\bMT\bTP\bP/\b/L\bLM\bMT\bTP\bP c\bcl\bli\bie\ben\bnt\bt
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
* The smtp_sasl_auth_enable setting enables client-side authentication. We
will configure the client's username and password information in the second
SASL client passwords. It opens the file as user root before it drops
privileges, and before entering an optional chroot jail.
- * Use the postmap command whenever you change the /etc/postfix/sasl_passwd
- file.
+ Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" after changing the
+ sasl_passwd file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" to specify an explicit type.
+
+ The default indexed file type is configured with the default_database_type
+ parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf
+ -\b-m\bm".
* If you specify the "[" and "]" in the relayhost destination, then you must
use the same form in the smtp_sasl_password_maps file.
/etc/postfix/main.cf:
smtp_sender_dependent_authentication = yes
- sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
+ sender_dependent_relayhost_maps =
+ lmdb:/etc/postfix/sender_relay
smtp_sasl_auth_enable = yes
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
user1@example.com [mail.example.com]:submission
user2@example.net [mail.example.net]
+ Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
* If you are creative, then you can try to combine the two tables into one
single MySQL database, and configure different Postfix queries to extract
the appropriate information.
- * Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb
- files. To find out what lookup tables Postfix supports, use the command
- "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" after you change the
+ sasl_passwd file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" to specify an explicit type.
- * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bsa\bas\bsl\bl_\b_p\bpa\bas\bss\bsw\bwd\bd" whenever you change
- the sasl_passwd table.
+ The default indexed file type is configured with the default_database_type
+ parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf
+ -\b-m\bm".
- * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" whenever you change
- the sender_relay table.
+ * Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" after you change
+ the sender_relay file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/s\bse\ben\bnd\bde\ber\br_\b_r\bre\bel\bla\bay\by" to specify an explicit type.
address.
1 /etc/postfix/main.cf:
- 2 virtual_alias_maps = hash:/etc/postfix/virtual
+ 2 virtual_alias_maps = lmdb:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 postmaster postmaster@example.com
9b permit_mynetworks reject_unauth_destination
10b ...spam blocking rules....
- 11 relay_recipient_maps = hash:/etc/postfix/relay_recipients
- 12 transport_maps = hash:/etc/postfix/transport
+ 11 relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
+ 12 transport_maps = lmdb:/etc/postfix/transport
13
14 /etc/postfix/relay_recipients:
15 user1@example.com x
"relay" delivery transport, instead of competing with other SMTP deliveries
for SMTP clients from the default "smtp" delivery transport.
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" whenever you change the
+virtual file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/
+e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/r\bre\bel\bla\bay\by_\b_r\bre\bec\bci\bip\bpi\bie\ben\bnt\bts\bs" whenever you change
-the relay_recipients table.
+the relay_recipients file, to (re)build a default-type indexed file. Execute
+"p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/r\bre\bel\bla\bay\by_\b_r\bre\bec\bci\bip\bpi\bie\ben\bnt\bts\bs" to specify an explicit type.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" whenever you change the
-transport table.
+transport file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" to specify an explicit type.
In some installations, there may be separate instances of Postfix processing
inbound and outbound mail on a multi-homed firewall. The inbound Postfix
locally, you can set up virtual aliases as follows:
1 /etc/postfix/main.cf:
- 2 virtual_alias_maps = hash:/etc/postfix/virtual
+ 2 virtual_alias_maps = lmdb:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 root root@localhost
listed in $mydestination, or when it matches $inet_interfaces or
$proxy_interfaces.
-Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after editing the file.
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after editing the virtual
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
R\bRu\bun\bnn\bni\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx b\bbe\beh\bhi\bin\bnd\bd a\ba f\bfi\bir\bre\bew\bwa\bal\bll\bl
this document.
1 /etc/postfix/main.cf:
- 2 transport_maps = hash:/etc/postfix/transport
+ 2 transport_maps = lmdb:/etc/postfix/transport
3 relayhost =
4 # Optional for a machine that isn't "always on"
5 #fallback_relay = [gateway.example.com]
is turned off. Postfix tries to deliver mail directly, and gives
undeliverable mail to a gateway.
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" whenever you edit the
-transport table.
+transport file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
C\bCo\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx a\bas\bs p\bpr\bri\bim\bma\bar\bry\by o\bor\br b\bba\bac\bck\bku\bup\bp M\bMX\bX h\bho\bos\bst\bt f\bfo\bor\br a\ba r\bre\bem\bmo\bot\bte\be s\bsi\bit\bte\be
11 # You must specify your NAT/proxy external address.
12 #proxy_interfaces = 1.2.3.4
13
- 14 relay_recipient_maps = hash:/etc/postfix/relay_recipients
+ 14 relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
15
16 /etc/postfix/relay_recipients:
17 user1@the.backed-up.domain.tld x
When your system is PRIMARY MX host for a remote site you need the above, plus:
20 /etc/postfix/main.cf:
- 21 transport_maps = hash:/etc/postfix/transport
+ 21 transport_maps = lmdb:/etc/postfix/transport
22
23 /etc/postfix/transport:
24 the.backed-up.domain.tld relay:[their.mail.host.tld]
* Line 24: The [] forces Postfix to do no MX lookup.
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/r\bre\bel\bla\bay\by_\b_r\bre\bec\bci\bip\bpi\bie\ben\bnt\bts\bs" whenever you change
+the relay_recipients file, to (re)build a default-type indexed file. Execute
+"p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/r\bre\bel\bla\bay\by_\b_r\bre\bec\bci\bip\bpi\bie\ben\bnt\bts\bs" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" whenever you change the
-transport table.
+transport file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" to specify an explicit type.
NOTE for Postfix < 2.2: Do not use the fallback_relay feature when relaying
mail for a backup or primary MX domain. Mail would loop between the Postfix MX
this document.
1 /etc/postfix/main.cf:
- 2 smtp_generic_maps = hash:/etc/postfix/generic
+ 2 smtp_generic_maps = lmdb:/etc/postfix/generic
3
4 /etc/postfix/generic:
5 his@localdomain.local hisaccount@hisisp.example
extension of +local (this example assumes that the ISP supports "+" style
address extensions).
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/g\bge\ben\bne\ber\bri\bic\bc" whenever you change the
-generic table.
+generic file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/
+e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/g\bge\ben\bne\ber\bri\bic\bc" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
S\bSo\bol\blu\but\bti\bio\bon\bn 2\b2:\b: P\bPo\bos\bst\btf\bfi\bix\bx v\bve\ber\brs\bsi\bio\bon\bn 2\b2.\b.1\b1 a\ban\bnd\bd e\bea\bar\brl\bli\bie\ber\br
2 myhostname = hostname.localdomain
3 mydomain = localdomain
4
- 5 canonical_maps = hash:/etc/postfix/canonical
+ 5 canonical_maps = lmdb:/etc/postfix/canonical
6
- 7 virtual_alias_maps = hash:/etc/postfix/virtual
+ 7 virtual_alias_maps = lmdb:/etc/postfix/virtual
8
9 /etc/postfix/canonical:
10 your-login-name your-account@your-isp.com
instead of sending it to the ISP. This part is not required but is
convenient.
-Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb files.
-To find out what lookup tables Postfix supports, use the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bca\ban\bno\bon\bni\bic\bca\bal\bl" whenever you change the
-canonical table.
+canonical file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp
+t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/c\bca\ban\bno\bon\bni\bic\bca\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" whenever you change the
-virtual table.
+virtual file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/
+e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
executes the u\buu\bux\bx command without assistance from the shell, so there are no
problems with shell meta characters in command-line parameters.
+ * Enable t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt table lookups:
+
+ /etc/postfix/main.cf:
+ transport_maps = lmdb:/etc/postfix/transport
+
* Specify that mail for example.com, should be delivered via UUCP, to a host
named uucp-host:
example.com uucp:uucp-host
.example.com uucp:uucp-host
+ Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
See the transport(5) manual page for more details.
* Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" whenever you change
- the t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt file.
-
- * Enable t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt table lookups:
-
- /etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+ the t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt file, to (re)build a default-type indexed file. Execute
+ "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/t\btr\bra\ban\bns\bsp\bpo\bor\brt\bt" to specify an explicit type.
- Specify d\bdb\bbm\bm instead of h\bha\bas\bsh\bh if your system uses d\bdb\bbm\bm files instead of d\bdb\bb
- files. To find out what map types Postfix supports, use the command
- "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+ The default indexed file type is configured with the default_database_type
+ parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf
+ -\b-m\bm".
* Add example.com to the list of domains that your site is willing to relay
mail for.
* Postfix virtual MAILBOX example: separate domains, non-UNIX accounts
* Non-Postfix mailbox store: separate domains, non-UNIX accounts
* Mail forwarding domains
- * Mailing lists
- * Autoreplies
+ * Hosted mailing list domains
C\bCa\ban\bno\bon\bni\bic\bca\bal\bl v\bve\ber\brs\bsu\bus\bs h\bho\bos\bst\bte\bed\bd v\bve\ber\brs\bsu\bus\bs o\bot\bth\bhe\ber\br d\bdo\bom\bma\bai\bin\bns\bs
L\bLo\boc\bca\bal\bl f\bfi\bil\ble\bes\bs v\bve\ber\brs\bsu\bus\bs n\bne\bet\btw\bwo\bor\brk\bk d\bda\bat\bta\bab\bba\bas\bse\bes\bs
-The examples in this text use table lookups from local files such as DBM or
-Berkeley DB. These are easy to debug with the p\bpo\bos\bst\btm\bma\bap\bp command:
+The examples in this text use table lookups from local files such as lmdb:,
+cdb:, hash:, or dbm:. These are easy to debug with the p\bpo\bos\bst\btm\bma\bap\bp command:
- Example: postmap -q info@example.com hash:/etc/postfix/virtual
+ Example: postmap -q info@example.com /etc/postfix/virtual
-See the documentation in LDAP_README, MYSQL_README and PGSQL_README for how to
-replace local files by databases. The reader is strongly advised to make the
-system work with local files before migrating to network databases, and to use
-the p\bpo\bos\bst\btm\bma\bap\bp command to verify that network database lookups produce the exact
-same results as local file lookup.
+The above example assumes that the database is configured in main.cf as
+$default_database_type:/etc/postfix/virtual. Otherwise, use the command
+instead:
+
+ Example: postmap -q info@example.com type:/etc/postfix/virtual
+
+and specify the explicit type that this table uses in main.cf.
+
+You can replace local file lookups with networked (LDAP, SQL etc.) lookups. See
+the documentation in LDAP_README, MYSQL_README, PGSQL_README, etc., for
+examples. The reader is strongly advised to make Postfix work with local files
+before migrating to network databases, and to use the p\bpo\bos\bst\btm\bma\bap\bp command to verify
+that network database lookups produce the exact same results as local file
+lookup.
Example: postmap -q info@example.com ldap:/etc/postfix/virtual.cf
1 /etc/postfix/main.cf:
2 virtual_alias_domains = example.com ...other hosted domains...
- 3 virtual_alias_maps = hash:/etc/postfix/virtual
+ 3 virtual_alias_maps = lmdb:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
receive many spam messages, and many bounces for spam messages that were
sent in the name of anything@example.com.
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after changing the virtual
-file, and execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
+Execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
Note: virtual aliases can resolve to a local address or to a remote address, or
both. They don't have to resolve to UNIX system accounts on your machine.
1 /etc/postfix/main.cf:
2 virtual_mailbox_domains = example.com ...more domains...
3 virtual_mailbox_base = /var/mail/vhosts
- 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox
+ 4 virtual_mailbox_maps = lmdb:/etc/postfix/vmailbox
5 virtual_minimum_uid = 100
6 virtual_uid_maps = static:5000
7 virtual_gid_maps = static:5000
- 8 virtual_alias_maps = hash:/etc/postfix/virtual
+ 8 virtual_alias_maps = lmdb:/etc/postfix/virtual
9
10 /etc/postfix/vmailbox:
11 info@example.com example.com/info
explicit domain name on the right-hand side of the virtual alias table
entries or else mail will go to the wrong domain.
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after changing the virtual
-file, execute "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvm\bma\bai\bil\blb\bbo\box\bx" after changing the vmailbox file,
-and execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
+Execute "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvm\bma\bai\bil\blb\bbo\box\bx" after changing the vmailbox file, to
+(re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/
+v\bvm\bma\bai\bil\blb\bbo\box\bx" to specify an explicit type.
+
+Execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
Note: mail delivery happens with the recipient's UID/GID privileges specified
with virtual_uid_maps and virtual_gid_maps. Postfix 2.0 and earlier will not
1 /etc/postfix/main.cf:
2 virtual_transport = ...see below...
3 virtual_mailbox_domains = example.com ...more domains...
- 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox
- 5 virtual_alias_maps = hash:/etc/postfix/virtual
+ 4 virtual_mailbox_maps = lmdb:/etc/postfix/vmailbox
+ 5 virtual_alias_maps = lmdb:/etc/postfix/virtual
6
7 /etc/postfix/vmailbox:
8 info@example.com whatever
explicit domain name on the right-hand side of the virtual alias table
entries or else mail will go to the wrong domain.
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after changing the virtual
-file, execute "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvm\bma\bai\bil\blb\bbo\box\bx" after changing the vmailbox file,
-and execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvm\bma\bai\bil\blb\bbo\box\bx" after changing the vmailbox
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvm\bma\bai\bil\blb\bbo\box\bx" to specify an explicit type.
+
+Execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
M\bMa\bai\bil\bl f\bfo\bor\brw\bwa\bar\brd\bdi\bin\bng\bg d\bdo\bom\bma\bai\bin\bns\bs
1 /etc/postfix/main.cf:
2 virtual_alias_domains = example.com ...other hosted domains...
- 3 virtual_alias_maps = hash:/etc/postfix/virtual
+ 3 virtual_alias_maps = lmdb:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
receive many spam messages, and many bounces for spam messages that were
sent in the name of anything@example.com.
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after changing the virtual
-file, and execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
+Execute the command "p\bpo\bos\bst\btf\bfi\bix\bx r\bre\bel\blo\boa\bad\bd" after changing the main.cf file.
More details about the virtual alias file are given in the virtual(5) manual
page, including multiple addresses on the right-hand side.
-M\bMa\bai\bil\bli\bin\bng\bg l\bli\bis\bst\bts\bs
+H\bHo\bos\bst\bte\bed\bd m\bma\bai\bil\bli\bin\bng\bg l\bli\bis\bst\bt d\bdo\bom\bma\bai\bin\bns\bs
+
+Note: this section presents a historical approach to run a mailing list based
+on local aliases(5). This approach may still be useful for small mailing lists
+that are managed by hand or with the software like Majordomo. For a more
+contemporary and more scalable approach, see GNU Mailman.
The examples that were given above already show how to direct mail for virtual
postmaster addresses to a local postmaster. You can use the same method to
agent:
/etc/postfix/main.cf:
- virtual_alias_maps = hash:/etc/postfix/virtual
+ virtual_alias_maps = lmdb:/etc/postfix/virtual
+ virtual_mailbox_domains = example.com
/etc/postfix/virtual:
listname-request@example.com listname-request
listname@example.com listname
owner-listname@example.com owner-listname
+ postmaster@example.com postmaster
/etc/aliases:
listname: "|/some/where/majordomo/wrapper ..."
owner-listname: ...
listname-request: ...
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+
+Execute the command "p\bpo\bos\bst\btm\bma\bap\bp /\b/e\bet\btc\bc/\b/p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" after changing the virtual
+file, to (re)build a default-type indexed file. Execute "p\bpo\bos\bst\btm\bma\bap\bp t\bty\byp\bpe\be:\b:/\b/e\bet\btc\bc/\b/
+p\bpo\bos\bst\btf\bfi\bix\bx/\b/v\bvi\bir\brt\btu\bua\bal\bl" to specify an explicit type.
+
+The default indexed file type is configured with the default_database_type
+parameter. To list available explicit types, execute the command "p\bpo\bos\bst\btc\bco\bon\bnf\bf -\b-m\bm".
+
This example assumes that in main.cf, $myorigin is listed under the
mydestination parameter setting. If that is not the case, specify an explicit
domain name on the right-hand side of the virtual alias table entries or else
be rejected with "User unknown". In order to make the transport mapping work
one would still need a bunch of virtual alias or virtual mailbox table entries.
- * In case of a virtual alias domain, there would need to be one identity
- mapping from each mailing list address to itself.
- * In case of a virtual mailbox domain, there would need to be a dummy mailbox
- for each mailing list address.
-
-A\bAu\but\bto\bor\bre\bep\bpl\bli\bie\bes\bs
-
-In order to set up an autoreply for virtual recipients while still delivering
-mail as normal, set up a rule in a virtual alias table:
-
- /etc/postfix/main.cf:
- virtual_alias_maps = hash:/etc/postfix/virtual
-
- /etc/postfix/virtual:
- user@domain.tld user@domain.tld, user@domain.tld@autoreply.mydomain.tld
-
-This delivers mail to the recipient, and sends a copy of the mail to the
-address that produces automatic replies. The address can be serviced on a
-different machine, or it can be serviced locally by setting up a transport map
-entry that pipes all mail for autoreply.mydomain.tld into some script that
-sends an automatic reply back to the sender.
-
-DO NOT list autoreply.mydomain.tld in mydestination!
-
- /etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
-
- /etc/postfix/transport:
- autoreply.mydomain.tld autoreply:
-
- /etc/postfix/master.cf:
- # =============================================================
- # service type private unpriv chroot wakeup maxproc command
- # (yes) (yes) (yes) (never) (100)
- # =============================================================
- autoreply unix - n n - - pipe
- flags= user=nobody argv=/path/to/autoreply $sender $mailbox
-
-This invokes /path/to/autoreply with the sender address and the user@domain.tld
-recipient address on the command line.
-
-For more information, see the pipe(8) manual page, and the comments in the
-Postfix master.cf file.
+ * In the case of a virtual alias DOMAIN, there would need to be an identity
+ mapping from each mailing list address to an address in a different domain.
+ * In the case of a virtual mailbox DOMAIN, there would need to be a dummy
+ virtual_mailbox_maps for each mailing list address.
Major changes - database
------------------------
-[Infrastructure 20251226] Tooling to help with the migration away
-from Berkeley DB.
-
-The new parameter default_cache_db_type controls the default database
-type for address_verify_map and postscreen_cache_map, and can
-eliminate a few hard-coded database types in main.cf. This parameter
-defaults to 'lmdb' if the default_database_type value equals 'lmdb',
-otherwise it assumes the historical value 'btree'.
-
-Sites that build without Berkeley DB are suggested to use one of the
-following commands in their build process:
-
-1 - Make lmdb the default for both default_database_type
- and default_cache_db_type.
-
- make makefiles CCARGS="-DNO_DB ..." default_database_type=lmdb \
- default_cache_db_type=lmdb
+[Incompat 20260220] The alias_maps and alias_database parameter
+default values have changed from hash:/path/to/aliases (or
+dbm:/path/to/aliases) to $default_database_type:/path/to/aliases.
+This simplifies the migration away from Berkeley DB.
-2 - Make cdb the default for default_database_type, and make
- lmdb the default for default_cache_db_type.
+[Infrastructure 20260219] Support to migrate a Postfix configuration
+that uses Berkeley DB hash: or btree: tables, to a configuration
+that uses lmdb: or a combination of cdb: and lmdb:. This is needed
+for (Linux) OS distributions that have removed Berkeley DB support.
+See NON_BERKELEYDB_README for manual and atomatic migratom support.
- make makefiles CCARGS="-DNO_DB ..." default_database_type=cdb \
- default_cache_db_type=lmdb
+Postfix already supports CDB and LMDB for more than 10 years. It
+may be a good idea to do the migration before you need to upgrade
+to an OS distribution that no longer supports Berkeley DB.
-Postfix hash and btree files can easily be migrated when the source
-file (without the '.db name suffix) is available. Just run
-
- postmap lmdb:/path/to/file
-
-That does not work for address_verify_map, postscreen_cache_map,
-and the optional smtp_sasl_auth_cache_name. These have no source
-file because they are managed by Postfix daemon processes.
-
-You can either ignore these files (they will be populated again
-over time), or you can copy the existing entries from the existing
-'.db' file to a new '.lmdb' . file. But that is possible only if
-Berkeley DB support is still available. Execute as root:
+[Infrastructure 20251226] Tooling to help with the migration away
+from Berkeley DB.
- rm -f /path/to/file.lmdb
- postmap -s btree:/path/to/file | postmap -i lmdb:/path/to/file
- chown postfix /path/to/file.lmdb
+The new parameter default_cache_db_type controls the default database
+type for address_verify_map, postscreen_cache_map, and
+smtp_sasl_auth_cache_name, previously hard-coded as 'btree'.
[Feature 20250321] Safety: the SQLite client now logs a warning
when a query uses double quotes instead of the Postfix-recommended
--- /dev/null
+Testing is a work in progress.
+
+- As of Postfix 3.11 most new code is covered by tests.
+
+- Many Postfix tests require building with shared=yes and dynamicmaps=no.
+The shared=yes is needed so that test code can overrride internal
+dependencies with mocks; the dynamicmaps=no is needed until there
+is an easy way way to tell dynamicmaps support to not use the system
+dynamicmaps.cf file.
+
+- Historically, many tests in src/util, src/dns, and src/smtpd
+are non-hermetic: they have dependencies on DNS or on local system
+configuration.
+
+- The PTEST test framework needs to be integrated; this fixed many many
+non-hermetic tests in src/util and src/dns. That development stalled
+after postfix-3.8-20220816-nonprod.
# messages.
#
# Normally, the access(5) table is specified as a text file
-# that serves as input to the postmap(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/access" to rebuild an indexed file
-# after changing the corresponding text file.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# that serves as input to the postmap(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/access" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/access"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
# (including domain).
#
# Normally, the aliases(5) table is specified as a text file
-# that serves as input to the postalias(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast lookup by the mail system. Execute the command
-# newaliases in order to rebuild the indexed file after
-# changing the Postfix alias database.
+# that serves as input to the postalias(1) command to create
+# an indexed file for fast lookup. The location of this file
+# is system-dependent. This text will use /path/to/aliases.
+#
+# Execute the command "newaliases to rebuild the indexed
+# file after changing the text file. Execute "postalias -q
+# name /path/to/aliases" to query a default-type indexed
+# file, or execute "postalias -q name type:/path/to/aliases"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
#
# When the table is provided via other means such as NIS,
# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
-# Alternatively, the table can be provided as a regu-
-# lar-expression map where patterns are given as regular
-# expressions. In this case, the lookups are done in a
-# slightly different way as described below under "REGULAR
+# Alternatively, the table can be provided as a regu-
+# lar-expression map where patterns are given as regular
+# expressions. In this case, the lookups are done in a
+# slightly different way as described below under "REGULAR
# EXPRESSION TABLES".
#
# Users can control delivery of their own mail by setting up
#
# name: value1, value2, ...
#
-# o Empty lines and whitespace-only lines are ignored,
-# as are lines whose first non-whitespace character
+# o Empty lines and whitespace-only lines are ignored,
+# as are lines whose first non-whitespace character
# is a `#'.
#
-# o A logical line starts with non-whitespace text. A
-# line that starts with whitespace continues a logi-
+# o A logical line starts with non-whitespace text. A
+# line that starts with whitespace continues a logi-
# cal line.
#
-# The name is a local address (no domain part). Use double
-# quotes when the name contains any special characters such
-# as whitespace, `#', `:', or `@'. The name is folded to
+# The name is a local address (no domain part). Use double
+# quotes when the name contains any special characters such
+# as whitespace, `#', `:', or `@'. The name is folded to
# lowercase, in order to make database lookups case insensi-
# tive.
#
-# In addition, when an alias exists for owner-name, this
-# will override the envelope sender address, so that deliv-
+# In addition, when an alias exists for owner-name, this
+# will override the envelope sender address, so that deliv-
# ery diagnostics are directed to owner-name, instead of the
-# originator of the message (for details, see
-# owner_request_special, expand_owner_alias and
-# reset_owner_alias). This is typically used to direct
-# delivery errors to the maintainer of a mailing list, who
+# originator of the message (for details, see
+# owner_request_special, expand_owner_alias and
+# reset_owner_alias). This is typically used to direct
+# delivery errors to the maintainer of a mailing list, who
# is in a better position to deal with mailing list delivery
# problems than the originator of the undelivered mail.
#
# The value contains one or more of the following:
#
# address
-# Mail is forwarded to address, which is compatible
+# Mail is forwarded to address, which is compatible
# with the RFC 822 standard.
#
# /file/name
-# Mail is appended to /file/name. For details on how
-# a file is written see the sections "EXTERNAL FILE
-# DELIVERY" and "DELIVERY RIGHTS" in the local(8)
-# documentation. Delivery is not limited to regular
-# files. For example, to dispose of unwanted mail,
+# Mail is appended to /file/name. For details on how
+# a file is written see the sections "EXTERNAL FILE
+# DELIVERY" and "DELIVERY RIGHTS" in the local(8)
+# documentation. Delivery is not limited to regular
+# files. For example, to dispose of unwanted mail,
# deflect it to /dev/null.
#
# |command
-# Mail is piped into command. Commands that contain
-# special characters, such as whitespace, should be
-# enclosed between double quotes. For details on how
-# a command is executed see "EXTERNAL COMMAND DELIV-
+# Mail is piped into command. Commands that contain
+# special characters, such as whitespace, should be
+# enclosed between double quotes. For details on how
+# a command is executed see "EXTERNAL COMMAND DELIV-
# ERY" and "DELIVERY RIGHTS" in the local(8) documen-
# tation.
#
# When the command fails, a limited amount of command
-# output is mailed back to the sender. The file
-# /usr/include/sysexits.h defines the expected exit
-# status codes. For example, use "|exit 67" to simu-
-# late a "user unknown" error, and "|exit 0" to
+# output is mailed back to the sender. The file
+# /usr/include/sysexits.h defines the expected exit
+# status codes. For example, use "|exit 67" to simu-
+# late a "user unknown" error, and "|exit 0" to
# implement an expensive black hole.
#
# :include:/file/name
-# Mail is sent to the destinations listed in the
+# Mail is sent to the destinations listed in the
# named file. Lines in :include: files have the same
-# syntax as the right-hand side of aliases(5)
+# syntax as the right-hand side of aliases(5)
# entries.
#
# A destination can be any destination that is
#
# ADDRESS EXTENSION
# When alias database search fails, and the recipient local-
-# part contains the optional recipient delimiter (e.g.,
-# user+foo), the search is repeated for the unextended
+# part contains the optional recipient delimiter (e.g.,
+# user+foo), the search is repeated for the unextended
# address (e.g., user).
#
-# The propagate_unmatched_extensions parameter controls
-# whether an unmatched address extension (+foo) is propa-
+# The propagate_unmatched_extensions parameter controls
+# whether an unmatched address extension (+foo) is propa-
# gated to the result of table lookup.
#
# CASE FOLDING
# to lowercase before database lookup.
#
# REGULAR EXPRESSION TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
-# a description of regular expression lookup table syntax,
-# see regexp_table(5) or pcre_table(5). NOTE: these formats
+# a description of regular expression lookup table syntax,
+# see regexp_table(5) or pcre_table(5). NOTE: these formats
# do not use ":" at the end of a pattern.
#
-# Each regular expression is applied to the entire search
-# string. Thus, a search string user+foo is not broken up
+# Each regular expression is applied to the entire search
+# string. Thus, a search string user+foo is not broken up
# into user and foo.
#
-# Regular expressions are applied in the order as specified
-# in the table, until a regular expression is found that
+# Regular expressions are applied in the order as specified
+# in the table, until a regular expression is found that
# matches the search string.
#
-# Lookup results are the same as with indexed file lookups.
-# For security reasons there is no support for $1, $2 etc.
+# Lookup results are the same as with indexed file lookups.
+# For security reasons there is no support for $1, $2 etc.
# substring interpolation.
#
# SECURITY
-# The local(8) delivery agent disallows regular expression
-# substitution of $1 etc. in alias_maps, because that would
+# The local(8) delivery agent disallows regular expression
+# substitution of $1 etc. in alias_maps, because that would
# open a security hole.
#
-# The local(8) delivery agent will silently ignore requests
-# to use the proxymap(8) server within alias_maps. Instead
-# it will open the table directly. Before Postfix version
-# 2.2, the local(8) delivery agent will terminate with a
+# The local(8) delivery agent will silently ignore requests
+# to use the proxymap(8) server within alias_maps. Instead
+# it will open the table directly. Before Postfix version
+# 2.2, the local(8) delivery agent will terminate with a
# fatal error.
#
# CONFIGURATION PARAMETERS
-# The following main.cf parameters are especially relevant.
-# The text below provides only a parameter summary. See
+# The following main.cf parameters are especially relevant.
+# The text below provides only a parameter summary. See
# postconf(5) for more details including examples.
#
# alias_database (see 'postconf -d' output)
-# The alias databases for local(8) delivery that are
+# The alias databases for local(8) delivery that are
# updated with "newaliases" or with "sendmail -bi".
#
# alias_maps (see 'postconf -d' output)
-# Optional lookup tables that are searched only with
-# an email address localpart (no domain) and that
-# apply only to local(8) recipients; this is unlike
-# virtual_alias_maps that are often searched with a
-# full email address (including domain) and that
-# apply to all recipients: local(8), virtual, and
+# Optional lookup tables that are searched only with
+# an email address localpart (no domain) and that
+# apply only to local(8) recipients; this is unlike
+# virtual_alias_maps that are often searched with a
+# full email address (including domain) and that
+# apply to all recipients: local(8), virtual, and
# remote.
#
# allow_mail_to_commands (alias, forward)
-# Restrict local(8) mail delivery to external com-
+# Restrict local(8) mail delivery to external com-
# mands.
#
# allow_mail_to_files (alias, forward)
-# Restrict local(8) mail delivery to external files.
+# Restrict local(8) mail delivery to external files.
#
# expand_owner_alias (no)
# When delivering to an alias "aliasname" that has an
# "owner-aliasname" companion alias, set the envelope
-# sender address to the expansion of the
+# sender address to the expansion of the
# "owner-aliasname" alias.
#
# propagate_unmatched_extensions (canonical, virtual)
-# What address lookup tables copy an address exten-
+# What address lookup tables copy an address exten-
# sion from the lookup key to the lookup result.
#
# owner_request_special (yes)
# Enable special treatment for owner-listname entries
# in the aliases(5) file, and don't split owner-list-
-# name and listname-request address localparts when
+# name and listname-request address localparts when
# the recipient_delimiter is set to "-".
#
# recipient_delimiter (empty)
-# The set of characters that can separate an email
-# address localpart, user name, or a .forward file
+# The set of characters that can separate an email
+# address localpart, user name, or a .forward file
# name from its extension.
#
# Available in Postfix version 2.3 and later:
#
# frozen_delivered_to (yes)
-# Update the local(8) delivery agent's idea of the
-# Delivered-To: address (see prepend_deliv-
-# ered_header) only once, at the start of a delivery
-# attempt; do not update the Delivered-To: address
+# Update the local(8) delivery agent's idea of the
+# Delivered-To: address (see prepend_deliv-
+# ered_header) only once, at the start of a delivery
+# attempt; do not update the Delivered-To: address
# while expanding aliases or .forward files.
#
# STANDARDS
# postconf(5), configuration parameters
#
# README FILES
-# Use "postconf readme_directory" or "postconf html_direc-
+# Use "postconf readme_directory" or "postconf html_direc-
# tory" to locate this information.
# DATABASE_README, Postfix lookup table overview
#
# LICENSE
-# The Secure Mailer license must be distributed with this
+# The Secure Mailer license must be distributed with this
# software.
#
# AUTHOR(S)
# the queue. The address mapping is recursive.
#
# Normally, the canonical(5) table is specified as a text
-# file that serves as input to the postmap(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/canonical" to rebuild an indexed
-# file after changing the corresponding text file.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# file that serves as input to the postmap(1) command to
+# create an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/canonical" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/canoni-
+# cal" to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
# that are used in SMTP protocol commands).
#
# Normally, the generic(5) table is specified as a text file
-# that serves as input to the postmap(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/generic" to rebuild an indexed file
-# after changing the corresponding text file.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# that serves as input to the postmap(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/generic" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/generic"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
$daemon_directory/main.cf:f:root:-:644:o
$daemon_directory/master.cf:f:root:-:644:o
$daemon_directory/master:f:root:-:755
+$daemon_directory/nbdb_reindexd:f:root:-:755
$daemon_directory/oqmgr:f:root:-:755
$daemon_directory/pickup:f:root:-:755
$daemon_directory/pipe:f:root:-:755
#$daemon_directory/postfix-files:f:root:-:644:o
#$daemon_directory/postfix-files.d:d:root:-:755:o
$daemon_directory/postfix-script:f:root:-:755
+$daemon_directory/postfix-non-bdb-script:f:root:-:755
$daemon_directory/postfix-tls-script:f:root:-:755
$daemon_directory/postfix-wrapper:f:root:-:755
$daemon_directory/postmulti-script:f:root:-:755
$manpage_directory/man1/postcat.1:f:root:-:644
$manpage_directory/man1/postconf.1:f:root:-:644
$manpage_directory/man1/postdrop.1:f:root:-:644
+$manpage_directory/man1/postfix-non-bdb.1:f:root:-:644
$manpage_directory/man1/postfix-tls.1:f:root:-:644
$manpage_directory/man1/postfix.1:f:root:-:644
$manpage_directory/man1/postkick.1:f:root:-:644
$manpage_directory/man8/lmtp.8:f:root:-:644
$manpage_directory/man8/local.8:f:root:-:644
$manpage_directory/man8/master.8:f:root:-:644
+$manpage_directory/man8/nbdb_reindexd.8:f:root:-:644
$manpage_directory/man8/nqmgr.8:f:root:-:644:o
$manpage_directory/man8/oqmgr.8:f:root:-:644:
$manpage_directory/man8/pickup.8:f:root:-:644
$readme_directory/SMTPUTF8_README:f:root:-:644
$readme_directory/SQLITE_README:f:root:-:644
$readme_directory/NFS_README:f:root:-:644
+$readme_directory/NON_BERKELEYDB_README:f:root:-:644
$readme_directory/OVERVIEW:f:root:-:644
$readme_directory/PACKAGE_README:f:root:-:644
$readme_directory/PCRE_README:f:root:-:644
$html_directory/SMTPUTF8_README.html:f:root:-:644
$html_directory/SQLITE_README.html:f:root:-:644
$html_directory/NFS_README.html:f:root:-:644
+$html_directory/NON_BERKELEYDB_README.html:f:root:-:644
$html_directory/OVERVIEW.html:f:root:-:644
$html_directory/PACKAGE_README.html:f:root:-:644
$html_directory/PCRE_README.html:f:root:-:644
$html_directory/sqlite_table.5.html:f:root:-:644
$html_directory/nisplus_table.5.html:f:root:-:644
$html_directory/newaliases.1.html:h:$html_directory/mailq.1.html:-:644
+$html_directory/nbdb_reindexd.8.html:f:root:-:644
$html_directory/oqmgr.8.html:f:root:-:644
$html_directory/pcre_table.5.html:f:root:-:644
$html_directory/pgsql_table.5.html:f:root:-:644
$html_directory/postdrop.1.html:f:root:-:644
$html_directory/postfix-logo.jpg:f:root:-:644
$html_directory/postfix-manuals.html:f:root:-:644
+$html_directory/postfix-non-bdb.1.html:f:root:-:644
$html_directory/postfix-tls.1.html:f:root:-:644
$html_directory/postfix-wrapper.5.html:f:root:-:644
$html_directory/postfix.1.html:f:root:-:644
--- /dev/null
+#!/bin/sh
+
+#++
+# NAME
+# postfix-non-bdb 1
+# SUMMARY
+# Postfix non-Berkeley-DB migration
+# SYNOPSIS
+# \fBpostfix non-bdb\fR \fIsubcommand\fR
+# DESCRIPTION
+# The "\fBpostfix non-bdb \fIsubcommand\fR" feature edits main.cf
+# and master.cf, to manage the migration of an existing Postfix
+# configuration that uses Berkeley DB type "hash:" or "btree:"
+# tables (which are no longer supported on some OS distributions),
+# to supported types such as "cdb:" or "lmdb:".
+#
+# The following subcommands are available:
+# .IP \fBstatus\fR
+# Reports the non-Berkeley-DB migration status, without making
+# any changes.
+# .IP \fBdisable\fR
+# Edits main.cf and master.cf, to turn off the \fBenable-redirect\fR
+# and \fBenable-reindex\fR features.
+# .sp
+# This will break integration with other software such as
+# mailman versions from before May 2025 when they want to
+# use "postmap hash:/path/to/file", for example, to update a
+# mailman-maintained table.
+# .IP "\fBenable-redirect\fR (aliasing)"
+# Edits main.cf and master.cf, to enable redirection (aliasing)
+# from Berkeley DB types "hash" and "btree" to the non-Berkeley-DB
+# types specified with $default_database_type and
+# $default_cache_db_type. Custom redirection may be configured
+# with non_bdb_custom_mapping.
+# .sp
+# This configuration will not automatically create non-Berkeley-DB
+# indexed database files. Instead, Postfix programs will log an
+# error as they fail to open an indexed database file, and will
+# leave it to the system administrator to run postmap(1) or
+# postalias(1) to create that file.
+# .sp
+# This will fix integration with other software such as mailman
+# versions from before May 2025 when they want to use "postmap
+# hash:/path/to/file", for example, to update a mailman-maintained
+# table.
+# .sp
+# This subcommand will not make any changes when
+# default_database_type or default_cache_db_type specify a hash:
+# or btree: type.
+# .IP \fBenable-reindex\fR
+# Edits main.cf and master.cf, to implement \fBenable-redirect\fR,
+# and to automatically create a non-Berkeley-DB indexed database
+# file when a daemon program wants to access a file that does not
+# yet exist. This uses the nbdb_reindexd(8) daemon to run postmap(1)
+# or postalias(1) as described in "SECURITY" below.
+# .sp
+# This subcommand immediately generates non-Berkeley-DB indexed
+# files for unprivileged command-line programs that cannot send
+# requests to the nbdb_reindexd(8) daemon server. This involves
+# "hash:" and "btree:" tables that are used by postqueue(1) and
+# sendmail(1) as specified in authorized_flush_users and
+# authorized_mailq_users, and by sendmail(1) and postdrop(1)
+# as specified in authorized_submit_users and
+# local_login_sender_maps.
+# .sp
+# This subcommand will not make any changes when
+# default_database_type or default_cache_db_type specify a hash:
+# or btree: type.
+# .sp
+# \fINOTE: \fBenable-reindex\fI should be used only temporarily
+# to generate most of the non-Berkeley-DB indexed files that Postfix
+# needs. Leaving this enabled may expose the system to
+# privilege-escalation attacks. There are no security
+# concerns for using \fBenable-redirect\fR.
+# SECURITY
+# .ad
+# .fi
+# The nbdb_reindexd(8) daemon automatically generates a
+# non-Berkeley-DB indexed file only if the database pathname matches
+# the directory prefixes specified with
+# non_bdb_migration_allow_root_prefixes (for files that must be
+# owned by root), or with non_bdb_migration_allow_user_prefixes
+# (for files that must be owned by a non-root user). Additional
+# restrictions on file and directory ownership and permissions
+# are documented in nbdb_reindexd(8).
+# CONFIGURATION PARAMETERS
+# .ad
+# .fi
+# The "\fBpostfix non-bdb \fIsubcommand\fR" feature
+# updates the following configuration parameter:
+# .IP "\fBnon_bdb_migration_level (disable)\fR"
+# The non-Berkeley-DB migration service level.
+# .PP
+# Other relevant parameters:
+# .IP "\fBnon_bdb_custom_mapping (empty)\fR"
+# When non-Berkeley-DB migration is enabled, an optional mapping
+# from a hash: or btree: type to a non-Berkeley-DB type.
+# .IP "\fBnon_bdb_migration_allow_root_prefixes (see 'postconf -d non_bdb_migration_allow_root_prefixes' output)\fR"
+# A list of trusted pathname prefixes that must be matched when
+# the non-Berkeley-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+# run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with "root" privilege.
+# .IP "\fBnon_bdb_migration_allow_user_prefixes (see 'postconf -d non_bdb_migration_allow_user_prefixes' output)\fR"
+# A list of trusted pathname prefixes that must be matched when
+# the non-Berkeley-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+# run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with non-root privilege.
+# SEE ALSO
+# nbdb_reindexd(8) reindexing service
+# README FILES
+# .ad
+# .fi
+# Use "\fBpostconf readme_directory\fR" or
+# "\fBpostconf html_directory\fR" to locate this information.
+# .na
+# .nf
+# NON_BERKELEYDB_README, migration guide
+# LICENSE
+# .ad
+# .fi
+# The Secure Mailer license must be distributed with this software.
+# HISTORY
+# The "\fBpostfix non-bdb\fR" command was introduced with Postfix
+# version 3.11.
+# AUTHOR(S)
+# Wietse Venema
+# porcupine.org
+#--
+
+umask 022
+SHELL=/bin/sh
+
+case $command_directory in
+"") echo This script must be run by the postfix command. 1>&2
+ echo Do not run directly. 1>&2 exit 1;; esac
+
+cd $command_directory || {
+ # Let's hope there's a "postlog" somewhere on the PATH
+ FATAL="postlog -p fatal -t $MAIL_LOGTAG/postfix-tls-script"
+ msg="no Postfix command directory '${command_directory}'"
+ $FATAL "$msg" || { echo "$msg" >&2; sleep 1; }
+ exit 1
+}
+
+postconf=$command_directory/postconf
+LOGGER="$command_directory/postlog -t $MAIL_LOGTAG/postfix-non-bdb-script"
+INFO="$LOGGER -p info"
+WARN="$LOGGER -p warn"
+ERROR="$LOGGER -p error"
+FATAL="$LOGGER -p fatal"
+
+REINDEX_SVC=nbdb_reindex
+REINDEX_BIN=nbdb_reindexd
+
+# Helper functions.
+
+reindex_for_non_daemons() {
+ # The following tables are needed by unprivileged command-line
+ # tools that cannot send requests to the reindexing service unless
+ # they are run by root.
+ for type_name in `$postconf -h authorized_flush_users \
+ authorized_mailq_users authorized_submit_users \
+ local_login_sender_maps`; \
+ do
+ case $type_name in
+ hash:*|btree:*)
+ $INFO Proactively reindexing $type_name
+ postmap $type_name || exit 1;;
+ esac
+ done
+}
+
+validate_redirect_targets() {
+ # By default, the Berkeley DB type 'hash' will redirect to
+ # $default_database_type, and type 'btree' will redirect to
+ # $default_cache_db_type. Require that the targets are not
+ # Berkeley DB types.
+ for param in default_database_type default_cache_db_type
+ do
+ eval type="`$postconf -h $param`"
+ case $type in
+ hash|btree)
+ $FATAL "parameter $param specifies a Berkeley DB type: '$type'"
+ exit 1;;
+ esac
+ done
+}
+
+# Subcommand implementations.
+
+status() {
+ $postconf -h non_bdb_migration_level
+}
+
+disable_all() {
+ $postconf -X non_bdb_migration_level
+ $postconf -MX ${REINDEX_SVC}/unix
+}
+
+enable_redirect() {
+ validate_redirect_targets
+ $postconf -MX ${REINDEX_SVC}/unix
+ $postconf non_bdb_migration_level=enable-redirect || exit 1
+}
+
+enable_reindex() {
+ validate_redirect_targets
+ reindex_for_non_daemons
+ $postconf -M \
+ ${REINDEX_SVC}/unix="${REINDEX_SVC} unix y n n - 1 ${REINDEX_BIN}" || exit 1
+ $postconf non_bdb_migration_level=enable-reindex || exit 1
+}
+
+usage() {
+ $FATAL "usage: postfix non-bdb enable-redirect (or enable-reindex, or disable)"
+ exit 1
+}
+
+#
+# Parse JCL
+#
+case $# in
+ 1) ;;
+ *) usage;;
+esac
+
+case "$1" in
+enable-redirect)
+ enable_redirect;;
+enable-reindex)
+ enable_reindex;;
+disable)
+ disable_all;;
+status)
+ status;;
+*) usage
+esac
+
+exit 0
}
# Foreground this so it can be stopped. All inodes are cached.
$daemon_directory/postfix-script check-warn
+ $daemon_directory/postfix-script check-alias-maps-migration
fi
$INFO starting the Postfix mail system || exit 1
case $1 in
check)
$daemon_directory/postfix-script check-fatal || exit 1
+ $daemon_directory/postfix-script check-alias-maps-migration
$daemon_directory/postfix-script check-warn
exit 0
;;
exit 0
;;
+check-alias-maps-migration)
+ # This command is NOT part of the public interface.
+
+ # As of Postfix 3.11, the default alias_maps value
+ # contains $default_database_type:/path/to/aliases. When
+ # default_database_type is changed to lmdb or cdb, Postfix
+ # will not generate hash:/path/to/aliases requests that can
+ # be resolved dynamically with enable-redirect or enable-reindex.
+ #
+ # To avoid this, craft a one-time stand-alone re-indexing request.
+ test -f $config_directory/check-alias-maps-migration-done && exit 0
+ BACKUP_IFS="$IFS"
+ for map in `$command_directory/postconf -hx alias_maps`
+ do
+ echo "$map" | (
+ IFS=: read type path; IFS="$BACKUP_IFS"
+ case "$type" in
+ cdb|lmdb)
+ test ! -f "$path.$type" -a -f "$path" -a -f "$path.db" && {
+ $daemon_directory/nbdb_reindexd -S "hash:$path" ||
+ $WARN "See https://www.postfix.org/NON_BERKELEYDB_README.html for suggestions"
+ }
+ esac
+ )
+ done
+ touch $config_directory/check-alias-maps-migration-done
+ ;;
+
check-warn)
# This command is NOT part of the public interface.
$daemon_directory/post-install "$@"
;;
-tls)
- shift
- $daemon_directory/postfix-tls-script "$@"
+tls|non-bdb)
+ cmd=$1; shift
+ $daemon_directory/postfix-$cmd-script "$@"
;;
/*)
;;
*)
- $FATAL "unknown command: '$1'. Usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration, logrotate)"
+ $FATAL "unknown command: '$1'. Usage: postfix start (or stop, reload, abort, flush, check, status, set-permissions, upgrade-configuration, logrotate, tls, non-bdb)"
exit 1
;;
# messages.
#
# Normally, the relocated(5) table is specified as a text
-# file that serves as input to the postmap(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/relocated" to rebuild an indexed
-# file after changing the corresponding relocated table.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# file that serves as input to the postmap(1) command to
+# create an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/relocated" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/relo-
+# cated" to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
# relayhost, or from the recipient domain.
#
# Normally, the transport(5) table is specified as a text
-# file that serves as input to the postmap(1) command. The
-# result, an indexed file in dbm or db format, is used for
-# fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/transport" to rebuild an indexed
-# file after changing the corresponding transport table.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# file that serves as input to the postmap(1) command to
+# create an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/transport" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/trans-
+# port" to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
# addresses in general.
#
# Normally, the virtual(5) alias table is specified as a
-# text file that serves as input to the postmap(1) command.
-# The result, an indexed file in dbm or db format, is used
-# for fast searching by the mail system. Execute the command
-# "postmap /etc/postfix/virtual" to rebuild an indexed file
-# after changing the corresponding text file.
-#
-# When the table is provided via other means such as NIS,
-# LDAP or SQL, the same lookups are done as for ordinary
-# indexed files.
+# text file that serves as input to the postmap(1) command
+# to create an indexed file for fast lookup.
+#
+# Execute the command "postmap /etc/postfix/virtual" to
+# rebuild a default-type indexed file after changing the
+# text file, or execute "postmap type:/etc/postfix/virtual"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform
+# this may be one of lmdb:, cdb:, hash:, or dbm: (without
+# the trailing ':').
+#
+# When the table is provided via other means such as NIS,
+# LDAP or SQL, the same lookups are done as for ordinary
+# indexed files. Managing such databases is outside the
+# scope of Postfix.
#
# Alternatively, the table can be provided as a regu-
# lar-expression map where patterns are given as regular
<tr> <td><a href="postconf.5.html#config_directory">config_directory</a></td> <td>/etc/postfix</td> </tr>
-<tr> <td><a href="postconf.5.html#default_database_type">default_database_type</a></td> <td>lmdb or hash</td> </tr>
+<tr> <td><a href="postconf.5.html#default_database_type">default_database_type</a></td> <td>lmdb, cdb, or hash</td> </tr>
<tr> <td><a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a></td> <td>lmdb or btree</td> </tr>
<td>/etc/postfix</td> </tr>
<tr> <td>DEF_DB_TYPE</td> <td><a href="postconf.5.html#default_database_type">default_database_type</a></td>
-<td>lmdb or hash</td> </tr>
+<td>lmdb, cdb, or hash</td> </tr>
<tr> <td>DEF_CACHE_DB_TYPE</td> <td><a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a></td>
<td>lmdb or btree</td> </tr>
<tr> <td>DEF_SENDMAIL_PATH</td> <td><a href="postconf.5.html#sendmail_path">sendmail_path</a></td>
<td>/usr/sbin/sendmail</td> </tr>
+<tr> <td>DEF_SHLIB_DIR</td> <td><a href="postconf.5.html#shlib_directory">shlib_directory</a></td>
+<td>/usr/lib/postfix</td> </tr>
+
</table>
</blockquote>
<p> Note: the <a href="postconf.5.html#data_directory">data_directory</a> parameter (for caches and pseudo-random
-numbers) was introduced with Postfix version 2.5. </p>
+numbers) was introduced with Postfix version 2.5; <a href="postconf.5.html#shlib_directory">shlib_directory</a>
+(for shared-library objects and database plugins) with Postfix
+version 3.0. </p>
<h3><a name="build_other">4.7 - Overriding other compile-time
features</a></h3>
<tr> <td> </td> <td> -DNO_DB </td> <td> Do not build with Berkeley
DB support. By default, Berkeley DB support is compiled in on
-platforms that are known to support this feature. If you override
+platforms that have historically supported this feature. If you override
this, then you probably should also override <a href="postconf.5.html#default_database_type">default_database_type</a>
or DEF_DB_TYPE as described in section 4.6. </td> </tr>
<p> First, be sure to update the text file with aliases for root,
postmaster and "postfix" that forward mail to a real person. Postfix
-has a sample aliases file /etc/postfix/aliases that you can adapt
-to local conditions. </p>
+has a sample aliases file /etc/postfix/aliases that you can copy
+and adapt to local conditions. /p>
<blockquote>
<pre>
</pre>
</blockquote>
+<p> The form "postalias /etc/aliases" builds a default-type indexed
+file. Use "postalias <i>type</i>:/etc/aliases" to specify an explicit
+type (it should match the type in the output from "postconf -x
+<a href="postconf.5.html#alias_maps">alias_maps</a>"). </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<h2><a name="hamlet">11 - To chroot or not to chroot</a></h2>
<p> Postfix daemon processes can be configured (via <a href="master.5.html">master.cf</a>) to
oqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
trace.8.html verify.8.html proxymap.8.html anvil.8.html \
scache.8.html discard.8.html tlsmgr.8.html postscreen.8.html \
- dnsblog.8.html tlsproxy.8.html postlogd.8.html
+ dnsblog.8.html tlsproxy.8.html postlogd.8.html nbdb_reindexd.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html postmulti.1.html \
postqueue.1.html postsuper.1.html sendmail.1.html \
smtp-source.1.html smtp-sink.1.html posttls-finger.1.html \
qmqp-source.1.html qmqp-sink.1.html \
- qshape.1.html postfix-tls.1.html makedefs.1.html
+ qshape.1.html postfix-tls.1.html makedefs.1.html postfix-non-bdb.1.html
CONFIG = access.5.html aliases.5.html canonical.5.html relocated.5.html \
transport.5.html virtual.5.html pcre_table.5.html regexp_table.5.html \
cidr_table.5.html tcp_table.5.html header_checks.5.html \
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+nbdb_reindexd.8.html: ../src/nbdb_reindexd/nbdb_reindexd.c
+ PATH=../mantools:$$PATH; \
+ srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+
oqmgr.8.html: ../src/oqmgr/qmgr.c
PATH=../mantools:$$PATH; \
srctoman $? | sed -e 's/qmgr[^_]/o&/' \
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+postfix-non-bdb.1.html: ../conf/postfix-non-bdb-script
+ PATH=../mantools:$$PATH; \
+ srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
+
postfix-tls.1.html: ../conf/postfix-tls-script
PATH=../mantools:$$PATH; \
srctoman - $? | $(AWK) | $(NROFF) -man | uniq | $(MAN2HTML) | postlink >$@
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "https://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix Non-Berkeley-DB migration</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+Non-Berkeley-DB migration</h1>
+
+<hr>
+
+<h2> Table of contents </h2>
+
+<ul>
+
+<li> <a href="#intro">Introduction </a>
+
+<li> <a href="#background">Background </a>
+
+<li> <a href="#build-conf">Skip this if not building Postfix from
+source, or if your system still supports Berkeley DB </a>
+
+<li> <a href="#level-overview"> Migration support level overview </a>
+
+<li> <a href="#disable"> Level 'disable': manual migration </a>
+
+<li> <a href="#enable-redirect"> Level 'enable-redirect': database
+aliasing </a>
+
+<li> <a href="#enable-reindex"> Level 'enable-reindex': redirect
+and automatically generate non-Berkeley-DB indexed files </a>
+
+<li> <a href="#addr-errors">Addressing errors with automatic indexed
+file generation </a>
+
+<li> <a href="#mailman">Appendix: Mailman integration </a>
+
+</ul>
+
+<h2> <a name="intro">Introduction </a> </h2>
+
+<p> (Please see the <a href="#mailman">Appendix</a> for Mailman
+integration tips.) </p>
+
+<p> After running the same Postfix configuration for a decade or
+more, there is a rude awakening when you update the OS to a newer
+version that has deleted its support for Berkeley DB. Postfix
+programs fail to open all <a href="DATABASE_README.html#types">hash</a>: and <a href="DATABASE_README.html#types">btree</a>: tables with messages
+like this: </p>
+
+<blockquote>
+<pre>
+Berkeley DB support for '<a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual' is not available
+for this build; see https://www.postfix.org/<a href="NON_BERKELEYDB_README.html">NON_BERKELEYDB_README</a>.html
+for alternatives
+</pre>
+</blockquote>
+
+<p> This document comes to the rescue, with strategies to migrate
+an existing Postfix configuration that uses Berkeley DB <a href="DATABASE_README.html#types">hash</a>: and
+<a href="DATABASE_README.html#types">btree</a>: database files, to an OS distribution that has removed
+Berkeley DB support, with a Postfix configuration that uses <a href="lmdb_table.5.html">lmdb</a>: (or
+a combination of <a href="CDB_README.html">cdb</a>: and <a href="lmdb_table.5.html">lmdb</a>:). <p>
+
+<p> By the way, you don't have to wait until Berkeley DB support
+is removed; your can proactively use the steps described here on a
+system that still has Berkeley DB, to migrate a Postfix configuration
+from Berkeley DB to <a href="lmdb_table.5.html">lmdb</a>: (or a combination of <a href="CDB_README.html">cdb</a>: and <a href="lmdb_table.5.html">lmdb</a>:).
+
+<h2> <a name="background">Background </a> </h2>
+
+<p> Historically, Postfix has used Berkeley DB <a href="DATABASE_README.html#types">hash</a>: and <a href="DATABASE_README.html#types">btree</a>: for
+key-value stores, as indicated in the "With Berkeley DB" table
+column below. In a world without Berkeley DB, good replacements are
+<a href="CDB_README.html">cdb</a>: and <a href="lmdb_table.5.html">lmdb</a>: as indicated in the "No Berkeley DB" column. </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th> Purpose </th> <th> With Berkeley DB </th> <th> No Berkeley
+DB </th> </tr>
+
+<tr> <td> Mostly-static data such as aliases, <a href="postconf.5.html#transport_maps">transport_maps</a>,
+access tables </td> <td> <a href="postconf.5.html#default_database_type">default_database_type</a>=hash </td> <td>
+<a href="postconf.5.html#default_database_type">default_database_type</a>=lmdb or <a href="postconf.5.html#default_database_type">default_database_type</a>=cdb </td>
+</tr>
+
+<tr> <td> Dynamic caches maintained by <a href="postscreen.8.html">postscreen(8)</a>, <a href="verify.8.html">verify(8)</a>,
+<a href="tlsmgr.8.html">tlsmgr(8)</a> </td> <td> <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=btree </td> <td>
+<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=lmdb </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> The default values for <a href="postconf.5.html#default_database_type">default_database_type</a> and <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>
+may be specified at build time (see the <a href="#build-conf">section
+below</a>, and they may be changed later by editing main.cf, for
+example with the <a href="postconf.1.html">postconf(1)</a> command.) </p>
+
+<p> The sections that follow present three migration strategies
+with different levels of assistance by tooling that was developed
+for Postfix 3.11 and later. </p>
+
+<h2> <a name="build-conf"> Skip this if not building Postfix from
+source, or if your system still supports Berkeley DB. </a> </h2>
+
+<p> <a href="#level-overview">Click here to skip to the next section</a>.
+
+<p> On systems that have removed Berkeley DB support, run "<tt>make
+makefiles</tt>" with a CCARGS value that (also) contains "-DNO_DB",
+and specify appropriate values for <a href="postconf.5.html#default_database_type">default_database_type</a> (lmdb or cdb)
+and <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> (lmdb). </p>
+
+<p> In the examples below, the "<tt>...</tt>" are place holders any
+dependencies that you build Postfix with, such as CDB, LDAP, LMDB,
+MySQL/MariaDB, OpenSSL, SASL, and so on.
+
+<p> Example 1: use <a href="lmdb_table.5.html">lmdb</a>: for both <a href="postconf.5.html#default_database_type">default_database_type</a> (read-mostly
+lookup tables) and <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> (read-write caches). Terminal
+input is <b>bold</b>, output is <tt>normal</tt> font. </p>
+
+<blockquote> <pre>
+$ <b>make makefiles CCARGS="-DNO_DB ..." \
+ <a href="postconf.5.html#default_database_type">default_database_type</a>=lmdb \
+ <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=lmdb ... \
+ AUXLIBS...</b>
+</pre>
+</blockquote>
+
+<p> Example 2: alternative form that produces the same result.
+</p>
+
+<blockquote>
+<pre>
+$ <b>export CCARGS="-DNO_DB ..."</b>
+$ <b>export <a href="postconf.5.html#default_database_type">default_database_type</a>=lmdb</b>
+$ <b>export <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=lmdb</b>
+$ <b>export AUXLIBS...</b>
+...
+$ <b>make makefiles</b>
+</pre>
+</blockquote>
+
+<p> Another alternative is to use cdb for <a href="postconf.5.html#default_database_type">default_database_type</a>
+(read-mostly lookup tables) and lmdb for <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>
+(read-write caches). </p>
+
+<h2> <a name="level-overview"> Migration support level overview </a> </h2>
+
+<p> The goal of the migration is clear: stop using <a href="DATABASE_README.html#types">hash</a>: and <a href="DATABASE_README.html#types">btree</a>:,
+and use <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>: instead. If your configuration is simple or
+if you are familiar with Postfix configuration, a few "<tt>grep</tt>"
+commands will find all the problems, and a few edits will be easy
+to make. </p>
+
+<p> If, on the other hand, you are not familiar with the details of your
+Postfix configuration, then this document provides options where Postfix
+can help. </p>
+
+<p> Postfix 3.11 introduces multiple levels of migration support.
+You can use the command "<tt><a href="postfix-non-bdb.1.html">postfix non-bdb</a> status</tt>" to view
+the migration support level. This is what the default should look
+like (terminal input is <tt><b>bold</b></tt>, output is <tt>normal</tt>
+font): </p>
+
+<blockquote>
+<pre>
+# <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> status</b>
+disable
+</pre>
+</blockquote>
+
+<p> In increasing order, the support levels are: </p>
+
+<dl>
+
+<dt> <a href="#disable">disable</a> (manual migration) </dt>
+
+<dd> <p> You start up Postfix, watch the logging when Postfix
+programs fail to open a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: table, edit Postfix
+configuration files to use <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>:, then run <a href="postmap.1.html">postmap(1)</a> or
+<a href="postalias.1.html">postalias(1)</a> commands to create <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>: indexed database
+files. Use this option if you are familiar with Postfix configuration.
+</p>
+
+<p> This will not fix the integration with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software that are broken
+when they want to use "<tt>postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i></tt>".
+Mailman uses this to maintain a table with mailing list contact
+addresses. For that, you need to use the next-up level. </p> </dd>
+
+<dt> <a href="#enable-redirect">enable-redirect</a> (database
+aliasing) </dt>
+
+<dd> <p> This level implicitly redirects a request to access
+<a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i> to $<a href="postconf.5.html#default_database_type">default_database_type</a>:<i>/path/to/file</i>,
+and redirects a request to access a <a href="DATABASE_README.html#types">btree</a>:<i>/path/to/file</i> to
+$<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>:<i>/path/to/file</i>. </p>
+
+<p> This still requires manually running <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a>
+commands, but "fixes" the integration with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software when they want
+to use "<tt>postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i>"</tt>, and Berkeley
+DB support is not available. Such commands will implicitly create
+a new <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>: indexed database file, depending on the
+<a href="postconf.5.html#default_database_type">default_database_type</a> value. </p> </dd>
+
+<dt> <a href="#enable-reindex"> enable-reindex </a> (aliasing, plus
+running <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a>)</dt>
+
+<dd> <p> This level implements "<tt>enable-redirect</tt> (database
+aliasing)", and also runs the <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> command to create
+a new lmdb or cdb indexed database file. This uses the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>
+daemon. </p>
+
+</dl>
+
+<p> The levels <a href="#enable-redirect">enable-redirect</a> and
+<a href="#enable-reindex"> enable-reindex </a> leave some technical
+debt: configurations that still say <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: (even if
+they use <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>: behind the scene). </p>
+
+<ul>
+
+<li> <p> Using these levels gives you extra time to prepare for a
+long-term configuration change that replaces hard-coded instances of <a href="DATABASE_README.html#types">hash</a>:
+with the value of <a href="postconf.5.html#default_database_type">default_database_type</a>, and that replaces <a href="DATABASE_README.html#types">btree</a>: with
+the value of <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>. </p>
+
+<li> <p> Depending on your use of other software that wants to use
+<a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> commands, you may have to permanently
+the leave the <a href="#enable-redirect">enable-redirect</a> level
+active. </p>
+
+</ul>
+
+<p> After this overview, the sections that follow will go into more
+detail. </p>
+
+<h2> <a name="disable"> Level 'disable': manual migration </a> </h2>
+
+<p> To disable all non-Berkeley-DB migration features use
+the "<tt><a href="postfix-non-bdb.1.html">postfix non-bdb</a></tt>" command:
+
+<blockquote>
+<pre>
+# <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> disable</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> This will edit <a href="postconf.5.html">main.cf</a> to remove a <a href="postconf.5.html#non_bdb_migration_level">non_bdb_migration_level</a> setting
+and the level revert to its implicit default (disable), and will edit
+<a href="master.5.html">master.cf</a> to remove an entry for the <tt>reindex</tt> service. </p>
+
+<p> This setting will cause problems with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software that wants to use
+"<tt>postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i></tt>" (or similar postalias
+commands), and Berkeley DB support is no longer available. In that
+case, you will need the "<tt>enable-redirect</tt>" migration support
+level.
+
+<p> A manual migration process goes like this: </p>
+
+<ul>
+
+<li> <p> Stop Postfix. </p>
+
+<li> <p> Make <a href="lmdb_table.5.html">lmdb</a>: the default for both <a href="postconf.5.html#default_database_type">default_database_type</a>
+(read-mostly lookup tables) and <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> (read-write
+caches): </p>
+
+<pre>
+# <b>postconf <a href="postconf.5.html#default_database_type">default_database_type</a>=lmdb <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=lmdb</b>
+</pre>
+
+<li> <p> Alternatively, make <a href="CDB_README.html">cdb</a>: the default for <a href="postconf.5.html#default_database_type">default_database_type</a>
+(read-mostly lookup tables) and <a href="lmdb_table.5.html">lmdb</a>: the default for
+<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> (read-write caches): </p>
+
+<pre>
+# <b>postconf <a href="postconf.5.html#default_database_type">default_database_type</a>=cdb <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>=lmdb</b>
+</pre>
+
+<li> <p> Look for <a href="DATABASE_README.html#types">hash</a>: and <a href="DATABASE_README.html#types">btree</a>: references in Postfix
+configuration files. Instead of <tt>/etc/postfix</tt> use the pathname
+in the output from "<tt>postconf -x <a href="postconf.5.html#config_directory">config_directory</a></tt>". </p>
+
+<pre>
+# <b>grep -E -r '(hash|btree):/' /etc/postfix</b>
+</pre>
+
+<li> <p> For each instance in the "<tt>grep</tt>" output : </p>
+
+<ul>
+
+<li> <p> Edit the configuration file and replace "hash" with "lmdb"
+or "cdb" (use the same value as the output from "<tt><b>postconf
+-hx <a href="postconf.5.html#default_database_type">default_database_type</a></b></tt>") and replace "btree" with "lmdb".
+</p>
+
+<li> <p> If this instance has no source file (only the ".db" file
+exists), proceed with the next instance of "<tt>grep</tt>" output.
+</p>
+
+<li> <p> If this instance appears in the output from "<tt><b>postconf
+-hPPx '*/*/alias_maps' | sort -u</b></tt>", run the <a href="postalias.1.html">postalias(1)</a>
+command. If this instance is like "<tt><a href="lmdb_table.5.html">lmdb</a>:/path/to/source</tt>":
+</p>
+
+<pre>
+# <b>postalias <a href="lmdb_table.5.html">lmdb</a>:/path/to/source</b>
+</pre>
+
+<p> Instead of "<a href="lmdb_table.5.html">lmdb</a>:" use "<a href="CDB_README.html">cdb</a>:" if the instance is like
+"<tt><a href="CDB_README.html">cdb</a>:/path/to/source</tt>". </p>
+
+<li> <p> Otherwise, run the <a href="postmap.1.html">postmap(1)</a> command. If this instance
+is like "<tt><a href="lmdb_table.5.html">lmdb</a>:/path/to/source</tt>": </p>
+
+<pre>
+# <b>postmap <a href="lmdb_table.5.html">lmdb</a>:/path/to/source</b>
+</pre>
+
+<p> Instead of "<a href="lmdb_table.5.html">lmdb</a>:" use "<a href="CDB_README.html">cdb</a>:" if this instance is like
+"<tt><a href="CDB_README.html">cdb</a>:/path/to/source</tt>". </p>
+
+</ul>
+
+<li> <p> Start Postfix, watch the log for warnings about files that
+cannot be opened, find the configuration file that still uses "hash"
+or "btree", and repeat the steps above. </p>
+
+<li> <p> It is now safe to delete the unused ".db" files. </p>
+
+</ul>
+
+<h2> <a name="enable-redirect"> Level 'enable-redirect': database
+aliasing </a> </h2>
+
+<p> To enable this migration support level, use: </p>
+
+<blockquote>
+<pre>
+# <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> This <tt><a href="postfix-non-bdb.1.html">postfix non-bdb</a></tt>" command edits <a href="postconf.5.html">main.cf</a> to enable
+redirection (aliasing) from Berkeley DB types "hash" and "btree"
+to the non-Berkeley-DB types specified with $<a href="postconf.5.html#default_database_type">default_database_type</a>
+and $<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>. Custom redirection may be configured
+with <a href="postconf.5.html#non_bdb_custom_mapping">non_bdb_custom_mapping</a>. This command also edits <a href="master.5.html">master.cf</a> to
+remove an unused <tt>nbdb_reindex</tt> service entry. </p>
+
+<p> This migration support level will not automatically create
+non-Berkeley-DB indexed database files. Instead, Postfix programs
+will log an error as they fail to open an indexed database file,
+and will leave it to the system administrator to run <a href="postmap.1.html">postmap(1)</a> or
+<a href="postalias.1.html">postalias(1)</a> to create that file. </p>
+
+<p> For each instance of "<tt><a href="DATABASE_README.html#types">hash</a>:/path/to/source</tt>" or
+"<tt><a href="DATABASE_README.html#types">btree</a>:/path/to/source</tt>" that requires manually running
+<a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a>: </p>
+
+<ul>
+
+<li> <p> If this instance appears in the output from "<tt><b>postconf
+-hPPx '*/*/alias_maps' | sort -u</b></tt>", run the <a href="postalias.1.html">postalias(1)</a>
+command. If this instance is like "<tt><a href="lmdb_table.5.html">lmdb</a>:/path/to/source</tt>":
+</p>
+
+<pre>
+# <b>postalias <a href="lmdb_table.5.html">lmdb</a>:/path/to/source</b>
+</pre>
+
+<p> Instead of "<a href="lmdb_table.5.html">lmdb</a>:" use "<a href="CDB_README.html">cdb</a>:" if the instance is like
+"<tt><a href="CDB_README.html">cdb</a>:/path/to/source</tt>". </p>
+
+<li> <p> Otherwise, run the <a href="postmap.1.html">postmap(1)</a> command. If this instance
+is like "<tt><a href="lmdb_table.5.html">lmdb</a>:/path/to/source</tt>": </p>
+
+<pre>
+# <b>postmap <a href="lmdb_table.5.html">lmdb</a>:/path/to/source</b>
+</pre>
+
+<p> Instead of "<a href="lmdb_table.5.html">lmdb</a>:" use "<a href="CDB_README.html">cdb</a>:" if this instance is like
+"<tt><a href="CDB_README.html">cdb</a>:/path/to/source</tt>". </p>
+
+</ul>
+
+<p> This migration support level will fix problems with Mailman
+versions from before May 2025 and other software that wants to use
+"<tt>postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i></tt>". With database
+redirection, such commands will implicitly create an indexed file
+for $<a href="postconf.5.html#default_database_type">default_database_type</a>:<i>/path/to/file</i> (similar aliasing
+happens for postalias commands). </p>
+
+<p> The command "<tt><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect</tt>" will
+refuse to make any changes when <a href="postconf.5.html#default_database_type">default_database_type</a> or
+<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> specify a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: type.
+
+<h2> <a name="enable-reindex"> Level 'enable-reindex': redirect and
+automatically generate non-Berkeley-DB indexed files </a> </h2>
+
+<p> <i> NOTE: this level should be used only temporarily to generate
+most of the non-Berkeley-DB indexed files that Postfix needs.
+Leaving this enabled may expose the system to privilege-escalation
+attacks. There are no security concerns for using enable-redirect.
+</i> </p>
+
+<p> To enable this migration support level, use: </p>
+
+<blockquote>
+<pre>
+# <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-reindex</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p>This <a href="postfix-non-bdb.1.html">postfix non-bdb</a> command edits <a href="postconf.5.html">main.cf</a> to set the non-Berkeley-DB
+migration support level, and <a href="master.5.html">master.cf</a> to add or replace an
+<tt>nbdb-reindex</tt> service entry. </p>
+
+<p> The resulting configuration implements not only the functionality
+of <a href="#enable-redirect"> enable-redirect</a>, but also
+automatically creates a non-Berkeley-DB indexed database file when
+a daemon program wants to access a file that does not exist. This
+uses the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> daemon to run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a>
+commands for databases that satisfy basic requirements to block
+privilege-escalation attacks. The number of requirements is large,
+but mainly, database files and their parent directory must not allow
+write access for group or other users, and their pathnames must
+match a list of trusted directory prefixes. The complete list of
+requirements is documented in <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>. <p>
+
+This command immediately generates non-Berkeley-DB indexed files
+for command-line programs that lack privileges to send requests to
+the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> indexing server. This applies to "<a href="DATABASE_README.html#types">hash</a>:" and
+"<a href="DATABASE_README.html#types">btree</a>:" tables that are used by <a href="postqueue.1.html">postqueue(1)</a> and <a href="sendmail.1.html">sendmail(1)</a> as
+configured with <a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> and <a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a>,
+and used by <a href="sendmail.1.html">sendmail(1)</a> and <a href="postdrop.1.html">postdrop(1)</a> as configured with
+<a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> and <a href="postconf.5.html#local_login_sender_maps">local_login_sender_maps</a>. </p>
+
+<p> The command "<tt><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-reindex</tt>" will
+refuse to make any changes when <a href="postconf.5.html#default_database_type">default_database_type</a> or
+<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> specify a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: type.
+
+<p> The <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> daemon will log when it successfully runs
+a <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> command. Examples, for a system with
+"<tt><a href="postconf.5.html#default_database_type">default_database_type</a> = lmdb</tt>": </p>
+
+<blockquote>
+<pre>
+successfully executed 'postmap <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport' as uid 0
+successfully executed 'postalias <a href="lmdb_table.5.html">lmdb</a>:/etc/aliases' as uid 0
+</pre>
+</blockquote>
+
+<p> See the section "<a href="addr-errors">Addressing errors
+with automatic indexed file generation</a>" for the most likely
+errors that Postfix programs may log. </p>
+
+<p> Once there are no more errors from Postfix programs for about
+24 hours, turn off automatic index generation by reducing the support
+level to <tt>enable-redirect</tt> with: </p>
+
+<blockquote>
+<pre>
+# <a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect
+# postfix reload
+</pre>
+</blockquote>
+
+<h2> <a name="addr-errors">Addressing errors with automatic
+indexed file generation </a> </h2>
+
+<h3> Unexpected pathname errors </h3>
+
+<p> Depending on the location of your Postfix lookup tables, Postfix
+programs may log a request to add a trusted directory to the
+directories listed with <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a> or
+<a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a>. </p>
+
+<p> Example, with line breaks added for readability: </p>
+
+<blockquote>
+<pre>
+could not execute command 'postmap <a href="lmdb_table.5.html">lmdb</a>:/path/to/file': table
+/path/to/file has an unexpected pathname;
+
+to allow automatic indexing as root, append its parent directory
+to the <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a> setting (current setting
+is: "/etc /usr/local/etc");
+
+alternatively, execute the failed command by hand
+</pre>
+</blockquote>
+
+<p> You have two options: </p>
+
+<ol>
+
+<li> <p> If you think that the suggested change is safe, update the
+setting as proposed and execute "<tt>postfix reload</tt>". </p>
+
+<li> <p> Alternatively, you can execute the failed <a href="postmap.1.html">postmap(1)</a> or
+<a href="postalias.1.html">postalias(1)</a> command by hand, and Postfix will not log the same error
+again. </p>
+
+</ol>
+
+<p> A similar request may be logged when a file needs to be indexed as
+a non-root user. </p>
+
+<h3> Unexpected file or directory owner or permissions </h3>
+
+<p> Other errors may be logged when a database file or directory
+has an unexpected owner, or when it is writable by group or by other
+users. </p>
+
+<p> Example with line breaks added for readability: </p>
+
+<blockquote>
+<pre>
+could not execute command 'postmap <a href="lmdb_table.5.html">lmdb</a>:/path/to/file': legacy
+indexed file '/path/to/file.db' is owned by uid '0', but parent
+directory '/path/to' is owned or writable by other user;
+
+to allow automatic indexing, correct the ownership or permissions;
+
+alternatively, execute the failed command by hand
+</pre>
+</blockquote>
+
+<p> Again, you have two options: </p>
+
+<ol>
+
+<li> <p> Fix the ownership or permission error. </p>
+
+<li> <p> Execute the failed <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> command by
+hand, and Postfix will not log the same error again. </p>
+
+</ol>
+
+<p> Once there are no more errors from Postfix programs for about
+24 hours, turn off automatic index generation by reducing the
+support level to <tt>enable-redirect</tt> with: </p>
+
+<blockquote>
+<pre>
+# <a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect
+# postfix reload
+</pre>
+</blockquote>
+
+<h2> <a name="mailman">Appendix: Mailman integration </a> </h2>
+
+<p> This section has instructions to migrate an existing Mailman
+configuration that wants to use commands like "postmap
+<a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i>". Mailman uses such commands to maintain
+tables with mailing list contact addresses and domain names. This
+will break on systems that no longer have Berkeley DB support. </p>
+
+<p> Solutions: </p>
+
+<ul>
+
+<li> <p> (Not recommended) Upgrade to a Mailman version that contains
+<a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c1321
+4f43c7d32d">gitlab commit 8fa56b72</a> (May 2025). Unfortunately,
+this has not yet been widely adopted by OS distributions. </p>
+
+<li> <p> Avoid Mailman changes, and use Postfix migration support
+described below. In a nutshell, the postmap command will execute
+the command "postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/file</i>" as if the command
+specifies <a href="lmdb_table.5.html">lmdb</a>:<i>/path/to/file</i> (or <a href="CDB_README.html">cdb</a>:, depending on Postfix
+configuration). </p>
+
+</ul>
+
+<p> With Mailman3 the integration with Postfix using LMTP may look
+like: </p>
+
+<blockquote>
+<pre>
+/var/lib/mailman3/data/postfix_domains (domain names)
+/var/lib/mailman3/data/postfix_domains.db (Berkeley DB hash file)
+/var/lib/mailman3/data/postfix_lmtp (transport map)
+/var/lib/mailman3/data/postfix_lmtp.db (Berkeley DB hash file)
+</pre>
+</blockquote>
+
+<blockquote> <i> Caution: the data directory may contain other files
+with names ending in "<tt>.db</tt>" that are not part of the
+Mailman-Postfix integration. Do not tamper with the other files. </i>
+</blockquote>
+
+<p> The relevant Postfix migration levels are: </p>
+
+<dl> <dt> <a href="#enable-redirect">enable-redirect</a> (redirect hash:
+to <a href="lmdb_table.5.html">lmdb</a>: or <a href="CDB_README.html">cdb</a>:) </dt>
+
+<dd> <p> Command: <tt> # <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect</b></tt> </p>
+
+<p> This will fix the problem that Mailman wants to use commands like
+"<tt>postmap <a href="DATABASE_README.html#types">hash</a>:<i>/path/to/</i>postfix_domains</tt>" and "<tt>postmap
+<a href="DATABASE_README.html#types">hash</a>:<i>/path/to</i>/postfix_lmtp</tt>". </p>
+
+<p> Instead of complaining about an unsupported database type, these
+postmap commands will implicitly create "<tt>.lmdb</tt>" indexed
+files like (<a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_domains or
+<a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_lmtp, or their <a href="CDB_README.html">cdb</a>: versions depending
+on the Postfix <a href="postconf.5.html#default_database_type">default_database_type</a> setting). </p>
+
+<p> This will not fix the problem that Postfix wants to
+use databases like <a href="DATABASE_README.html#types">hash</a>:<i>/path/to</i>/postfix_domains
+and <a href="DATABASE_README.html#types">hash</a>::<i>/path/to</i>/postfix_lmtp. With <a
+href="#enable-redirect">enable-redirect</a>, these will redirect to
+"<tt>.lmdb</tt>" indexed files (good) but those files do not yet exist
+(bad). You will need to create them by hand with commands like: </p>
+
+<pre>
+# <b>postmap <a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_domains</b>
+# <b>postmap <a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_lmtp</b>
+</pre>
+
+<p> After this, no further human action will be needed. When Mailman
+needs to update these files, it will invoke postmap commands that
+will work as promised above. Leave the Postfix migration level at <a
+href="#enable-reindex">enable-reindex</a> until you can upgrade to a
+newer Mailman version that supports Postfix with non-Berkeley
+databases. </p>
+
+</dd>
+
+<dt><a href="#enable-reindex">enable-reindex</a> (also automatically
+run postmap commands)</dt>
+
+<dd> <p> Command: <tt> # <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect</b></tt> </p>
+
+<p> In addition to "<a href="#enable-redirect">enable-redirect</a>",
+Postfix will also try to run commands like "<tt>postmap
+<a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_domains</tt>" and "<tt>postmap
+<a href="lmdb_table.5.html">lmdb</a>:<i>/path/to</i>/postfix_lmtp</tt>". There will be some delay
+depending on the amount of mailing list traffic; you may want to post
+a test message to make the postmap commands happen sooner. </p>
+
+<p> Postfix will log the postmap commands (or will log a request to make
+some configuration changes; see "<a href="addr-errors">Addressing errors
+with automatic indexed file generation</a>" above). </p>
+
+<p> <i>Note: once these "postmap" commands have completed,
+you should reduce the migration support level with the command
+"<b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> enable-redirect</b>". For security reasons the <a
+href="#enable-reindex">enable-reindex</a> level should not be permanently
+enabled. </i> </p>
+
+</dl>
+
+</body>
+
+</html>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <strong><a href="postconf.5.html#smtpd_sender_login_maps">smtpd_sender_login_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/controlled_envelope_senders</strong>
+ <strong><a href="postconf.5.html#smtpd_sender_login_maps">smtpd_sender_login_maps</a> =
+ <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/controlled_envelope_senders</strong>
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
...
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "<b>postmap
+/etc/postfix/controlled_envelope_senders</b>" after you change the
+controlled_envelope_senders file, to (re)build a default-type indexed
+file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/controlled_envelope_senders</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<p> With this, the <code><a href="postconf.5.html#reject_sender_login_mismatch">reject_sender_login_mismatch</a></code>
restriction above will reject the sender address in the MAIL FROM
command if <code><a href="postconf.5.html#smtpd_sender_login_maps">smtpd_sender_login_maps</a></code> does not specify
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>
- <a href="postconf.5.html#check_sasl_access">check_sasl_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sasl_access
+ <a href="postconf.5.html#check_sasl_access">check_sasl_access</a> <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sasl_access
<a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>
...
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/sasl_access</b>"
+after you change the sasl_access file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_access</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<h4><a name="id397172">Default authentication domain</a></h4>
<p> Postfix can append a domain name (or any other string) to a
<a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]
# Alternative form:
# <a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]:submission
- <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sasl_passwd
+ <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sasl_passwd
</pre>
</blockquote>
<ul>
-<li> <p> Use the <code>postmap</code> command whenever you
-change the <code>/etc/postfix/sasl_passwd</code> file. </p> </li>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
+after changing the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p> </li>
<li> <p> If you specify the "<code>[</code>" and "<code>]</code>"
in the <code><a href="postconf.5.html#relayhost">relayhost</a></code> destination, then you must use the
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> = yes
- <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_relay
+ <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> =
+ <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sender_relay
<a href="postconf.5.html#smtp_sasl_auth_enable">smtp_sasl_auth_enable</a> = yes
- <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sasl_passwd
+ <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sasl_passwd
<a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]
# Alternative form:
# <a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]:submission
<ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<li> <p> If you are creative, then you can try to combine the two
tables into one single MySQL database, and configure different
Postfix queries to extract the appropriate information. </p>
-<li> <p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
-
<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
-whenever you change the sasl_passwd table. </p>
+after you change the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<li> <p> Execute the command "<b>postmap /etc/postfix/sender_relay</b>"
-whenever you change the sender_relay table. </p>
+after you change the sender_relay file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sender_relay</b>"
+to specify an explicit type.</p>
</ul>
<blockquote>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
-2 <a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/generic
+2 <a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/generic
3
4 /etc/postfix/generic:
5 his@localdomain.local hisaccount@hisisp.example
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
<p> Execute the command "<b>postmap /etc/postfix/generic</b>"
-whenever you change the generic table. </p>
+whenever you change the generic file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/generic</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<h3>Solution 2: Postfix version 2.1 and earlier </h3>
2 <a href="postconf.5.html#myhostname">myhostname</a> = hostname.localdomain
3 <a href="postconf.5.html#mydomain">mydomain</a> = localdomain
4
- 5 <a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/canonical
+ 5 <a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/canonical
6
- 7 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 7 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
8
9 /etc/postfix/canonical:
10 your-login-name your-account@your-isp.com
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
<p> Execute the command "<b>postmap /etc/postfix/canonical</b>"
-whenever you change the canonical table. </p>
+whenever you change the canonical file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/canonical</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>"
-whenever you change the virtual table. </p>
+whenever you change the virtual file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>"
+to specify an explicit type. </p>
<h2><a name="client_sasl_enable">Enabling SASL authentication in the
Postfix SMTP/LMTP client</a></h2>
<a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]
# Alternative form:
# <a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]:submission
- <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sasl_passwd
+ <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sasl_passwd
</pre>
</blockquote>
<ul>
-<li> <p> Use the <code>postmap</code> command whenever you
-change the <code>/etc/postfix/sasl_passwd</code> file. </p> </li>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
+after changing the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p> </li>
<li> <p> If you specify the "<code>[</code>" and "<code>]</code>"
in the <code><a href="postconf.5.html#relayhost">relayhost</a></code> destination, then you must use the
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtp_sender_dependent_authentication">smtp_sender_dependent_authentication</a> = yes
- <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_relay
+ <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> =
+ <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sender_relay
<a href="postconf.5.html#smtp_sasl_auth_enable">smtp_sasl_auth_enable</a> = yes
- <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sasl_passwd
+ <a href="postconf.5.html#smtp_sasl_password_maps">smtp_sasl_password_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sasl_passwd
<a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]
# Alternative form:
# <a href="postconf.5.html#relayhost">relayhost</a> = [mail.isp.example]:submission
<ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<li> <p> If you are creative, then you can try to combine the two
tables into one single MySQL database, and configure different
Postfix queries to extract the appropriate information. </p>
-<li> <p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
-
<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
-whenever you change the sasl_passwd table. </p>
+after you change the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<li> <p> Execute the command "<b>postmap /etc/postfix/sender_relay</b>"
-whenever you change the sender_relay table. </p>
+after you change the sender_relay file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sender_relay</b>"
+to specify an explicit type.</p>
</ul>
<blockquote>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
-2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 postmaster postmaster@example.com
9b <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>
10b ...spam blocking rules....
<br>
-11 <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relay_recipients
-12 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
+11 <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relay_recipients
+12 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
13
14 /etc/postfix/relay_recipients:
15 user1@example.com x
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/virtual</b>"
+whenever you change the virtual file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/relay_recipients</b>"
-whenever you change the relay_recipients table. </p>
+whenever you change the relay_recipients file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/relay_recipients</b>" to specify an explicit
+type.</p>
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the transport table. </p>
+whenever you change the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
<p> In some installations, there may be separate instances of Postfix
processing inbound and outbound mail on a multi-homed firewall. The
<blockquote>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
-2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+2 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 root root@localhost
</ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-editing the file. </p>
+editing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<h2><a name="intranet">Running Postfix behind a firewall</a></h2>
<blockquote>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
- 2 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
+ 2 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
3 <a href="postconf.5.html#relayhost">relayhost</a> =
4 # Optional for a machine that isn't "always on"
5 #<a href="postconf.5.html#fallback_relay">fallback_relay</a> = [gateway.example.com]
</ul>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
+whenever you edit the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
-<p> Execute the command "<b>postmap /etc/postfix/transport</b>" whenever
-you edit the transport table. </p>
<h2><a name="backup">Configuring Postfix as primary or backup MX host for a remote site</a></h2>
11 # You must specify your NAT/proxy external address.
12 #<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> = 1.2.3.4
13
-14 <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relay_recipients
+14 <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relay_recipients
15
16 /etc/postfix/relay_recipients:
17 user1@the.backed-up.domain.tld x
<blockquote>
<pre>
20 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
-21 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
+21 <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
22
23 /etc/postfix/transport:
24 the.backed-up.domain.tld relay:[their.mail.host.tld]
</ul>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/relay_recipients</b>"
+whenever you change the relay_recipients file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/relay_recipients</b>" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the transport table. </p>
+whenever you change the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
<p> NOTE for Postfix < 2.2: Do not use the <a href="postconf.5.html#fallback_relay">fallback_relay</a> feature
when relaying mail
<blockquote>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
-2 <a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/generic
+2 <a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/generic
3
4 /etc/postfix/generic:
5 his@localdomain.local hisaccount@hisisp.example
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
<p> Execute the command "<b>postmap /etc/postfix/generic</b>"
-whenever you change the generic table. </p>
+whenever you change the generic file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/generic</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<h3>Solution 2: Postfix version 2.1 and earlier </h3>
2 <a href="postconf.5.html#myhostname">myhostname</a> = hostname.localdomain
3 <a href="postconf.5.html#mydomain">mydomain</a> = localdomain
4
- 5 <a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/canonical
+ 5 <a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/canonical
6
- 7 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 7 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
8
9 /etc/postfix/canonical:
10 your-login-name your-account@your-isp.com
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
<p> Execute the command "<b>postmap /etc/postfix/canonical</b>"
-whenever you change the canonical table. </p>
+whenever you change the canonical file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/canonical</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>"
-whenever you change the virtual table. </p>
+whenever you change the virtual file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>"
+to specify an explicit type. </p>
</body>
command without assistance from the shell, so there are no problems
with shell meta characters in command-line parameters. </p>
+<li> <p> Enable <b>transport</b> table lookups: </p>
+
+<pre>
+/etc/postfix/<a href="postconf.5.html">main.cf</a>:
+ <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
+</pre>
+
<li> <p> Specify that mail for <i>example.com</i>, should be
delivered via UUCP, to a host named <i>uucp-host</i>: </p>
.example.com uucp:uucp-host
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> See the <a href="transport.5.html">transport(5)</a> manual page for more details. </p>
<li> <p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the <b>transport</b> file. </p>
-
-<li> <p> Enable <b>transport</b> table lookups: </p>
-
-<pre>
-/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
-</pre>
+whenever you change the <b>transport</b> file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/transport</b>" to specify an explicit type.
+</p>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what map
-types Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<li> <p> Add <i>example.com</i> to the list of domains that your site
is willing to relay mail for. </p>
<li> <a href="#forwarding">Mail forwarding domains</a>
-<li> <a href="#mailing_lists">Mailing lists</a>
-
-<li> <a href="#autoreplies">Autoreplies</a>
+<li> <a href="#mailing_lists">Hosted mailing list domains</a>
</ul>
<h2><a name="local_vs_database">Local files versus network databases</a></h2>
<p> The examples in this text use table lookups from local files
-such as DBM or Berkeley DB. These are easy to debug with the
+such as <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. These are easy to debug with the
<b>postmap</b> command: </p>
<blockquote>
-Example: <tt>postmap -q info@example.com <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual</tt>
+Example: <tt>postmap -q info@example.com /etc/postfix/virtual</tt>
</blockquote>
-<p> See the documentation in <a href="LDAP_README.html">LDAP_README</a>, <a href="MYSQL_README.html">MYSQL_README</a> and <a href="PGSQL_README.html">PGSQL_README</a>
-for how to replace local files by databases. The reader is strongly
-advised to make the system work with local files before migrating
-to network databases, and to use the <b>postmap</b> command to verify
-that network database lookups produce the exact same results as
-local file lookup. </p>
+<p> The above example assumes that the database is configured in
+<a href="postconf.5.html">main.cf</a> as $<a href="postconf.5.html#default_database_type">default_database_type</a>:/etc/postfix/virtual. Otherwise,
+use the command instead: </p>
+
+<blockquote>
+Example: <tt>postmap -q info@example.com
+<i>type</i>:/etc/postfix/virtual</tt>
+</blockquote>
+
+<p> and specify the explicit type that this table uses in <a href="postconf.5.html">main.cf</a>. </p>
+
+<p> You can replace local file lookups with networked (LDAP, SQL
+etc.) lookups. See the documentation in <a href="LDAP_README.html">LDAP_README</a>, <a href="MYSQL_README.html">MYSQL_README</a>,
+<a href="PGSQL_README.html">PGSQL_README</a>, etc., for examples. The reader is strongly advised
+to make Postfix work with local files before migrating to network
+databases, and to use the <b>postmap</b> command to verify that
+network database lookups produce the exact same results as local
+file lookup. </p>
<blockquote>
Example: <tt>postmap -q info@example.com <a href="ldap_table.5.html">ldap</a>:/etc/postfix/virtual.cf</tt>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
2 <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> = example.com ...other <a href="VIRTUAL_README.html#canonical">hosted domains</a>...
- 3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
</ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p>Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, and execute the command "<b>postfix
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p>Execute the command "<b>postfix
reload</b>" after changing the <a href="postconf.5.html">main.cf</a> file. </p>
<p> Note: virtual aliases can resolve to a local address or to a
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
2 <a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> = example.com ...more domains...
3 <a href="postconf.5.html#virtual_mailbox_base">virtual_mailbox_base</a> = /var/mail/vhosts
- 4 <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/vmailbox
+ 4 <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/vmailbox
5 <a href="postconf.5.html#virtual_minimum_uid">virtual_minimum_uid</a> = 100
6 <a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a> = <a href="DATABASE_README.html#types">static</a>:5000
7 <a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a> = <a href="DATABASE_README.html#types">static</a>:5000
- 8 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 8 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
9
10 /etc/postfix/vmailbox:
11 info@example.com example.com/info
</ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, execute "<b>postmap /etc/postfix/vmailbox</b>"
-after changing the vmailbox file, and execute the command "<b>postfix
-reload</b>" after changing the <a href="postconf.5.html">main.cf</a> file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute "<b>postmap /etc/postfix/vmailbox</b>" after changing
+the vmailbox file, to (re)build a default-type indexed file. Execute
+"<b>postmap <i>type</i>:/etc/postfix/vmailbox</b>" to specify an
+explicit type. </p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+<a href="postconf.5.html">main.cf</a> file. </p>
<p> Note: mail delivery happens with the recipient's UID/GID
privileges specified with <a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a> and <a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a>.
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
2 <a href="postconf.5.html#virtual_transport">virtual_transport</a> = ...see below...
3 <a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> = example.com ...more domains...
- 4 <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/vmailbox
- 5 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 4 <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/vmailbox
+ 5 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
6
7 /etc/postfix/vmailbox:
8 info@example.com whatever
</ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, execute "<b>postmap /etc/postfix/vmailbox</b>"
-after changing the vmailbox file, and execute the command "<b>postfix
-reload</b>" after changing the <a href="postconf.5.html">main.cf</a> file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute the command "<b>postmap /etc/postfix/vmailbox</b>" after
+changing the vmailbox file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/vmailbox</b>" to
+specify an explicit type.</p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+<a href="postconf.5.html">main.cf</a> file. </p>
<h2><a name="forwarding">Mail forwarding domains</a></h2>
<pre>
1 /etc/postfix/<a href="postconf.5.html">main.cf</a>:
2 <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> = example.com ...other <a href="VIRTUAL_README.html#canonical">hosted domains</a>...
- 3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ 3 <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
</ul>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, and execute the command "<b>postfix
-reload</b>" after changing the <a href="postconf.5.html">main.cf</a> file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+<a href="postconf.5.html">main.cf</a> file. </p>
<p> More details about the virtual alias file are given in the
<a href="virtual.5.html">virtual(5)</a> manual page, including multiple addresses on the right-hand
side. </p>
-<h2><a name="mailing_lists">Mailing lists</a></h2>
+<h2><a name="mailing_lists">Hosted mailing list domains</a></h2>
+
+<p> <i> Note: this section presents a historical approach to run a
+mailing list based on local <a href="aliases.5.html">aliases(5)</a>. This approach may still be
+useful for small mailing lists that are managed by hand or with the
+software like Majordomo. For a more contemporary and more scalable
+approach, see <a href="https://lists.org"> GNU Mailman</a>. </i>
+</p>
-<p> The examples that were given above already show how to direct
+<p>The examples that were given above already show how to direct
mail for virtual postmaster addresses to a local postmaster. You
can use the same method to direct mail for any address to a local
or remote address. </p>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+ <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
+ <a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> = example.com
/etc/postfix/virtual:
listname-request@example.com listname-request
listname@example.com listname
owner-listname@example.com owner-listname
+ postmaster@example.com postmaster
/etc/aliases:
listname: "|/some/where/majordomo/wrapper ..."
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p>Execute the command "<b>postmap /etc/postfix/virtual</b>" after
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<p> This example assumes that in <a href="postconf.5.html">main.cf</a>, $<a href="postconf.5.html#myorigin">myorigin</a> is listed under
the <a href="postconf.5.html#mydestination">mydestination</a> parameter setting. If that is not the case,
specify an explicit domain name on the right-hand side of the
<ul>
-<li> In case of a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, there would need to be one
-identity mapping from each mailing list address to itself.
+<li> In the case of a virtual alias DOMAIN, there would need to be
+an identity mapping from each mailing list address to an address in a
+different domain.
-<li> In case of a <a href="ADDRESS_CLASS_README.html#virtual_mailbox_class">virtual mailbox domain</a>, there would need to be
-a dummy mailbox for each mailing list address.
+<li> In the case of a virtual mailbox DOMAIN, there would need to
+be a dummy <a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> for each mailing list address.
</ul>
-<h2><a name="autoreplies">Autoreplies</a></h2>
-
-<p> In order to set up an autoreply for virtual recipients while
-still delivering mail as normal, set up a rule in a virtual alias
-table: </p>
-
-<blockquote>
-<pre>
-/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
-
-/etc/postfix/virtual:
- user@domain.tld user@domain.tld, user@domain.tld@autoreply.<a href="postconf.5.html#mydomain">mydomain</a>.tld
-</pre>
-</blockquote>
-
-<p> This delivers mail to the recipient, and sends a copy of the
-mail to the address that produces automatic replies. The address
-can be serviced on a different machine, or it can be serviced
-locally by setting up a transport map entry that pipes all mail
-for autoreply.<a href="postconf.5.html#mydomain">mydomain</a>.tld into some script that sends an automatic
-reply back to the sender. </p>
-
-<p> DO NOT list autoreply.<a href="postconf.5.html#mydomain">mydomain</a>.tld in <a href="postconf.5.html#mydestination">mydestination</a>! </p>
-
-<blockquote>
-<pre>
-/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
-
-/etc/postfix/transport:
- autoreply.<a href="postconf.5.html#mydomain">mydomain</a>.tld autoreply:
-
-/etc/postfix/<a href="master.5.html">master.cf</a>:
- # =============================================================
- # service type private unpriv chroot wakeup maxproc command
- # (yes) (yes) (yes) (never) (100)
- # =============================================================
- autoreply unix - n n - - pipe
- flags= user=nobody argv=/path/to/autoreply $sender $mailbox
-</pre>
-</blockquote>
-
-<p> This invokes /path/to/autoreply with the sender address and
-the user@domain.tld recipient address on the command line. </p>
-
-<p> For more information, see the <a href="pipe.8.html">pipe(8)</a> manual page, and the
-comments in the Postfix <a href="master.5.html">master.cf</a> file. </p>
-
</body>
</html>
email messages.
Normally, the <a href="access.5.html"><b>access</b>(5)</a> table is specified as a text file that serves
- as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file in <b>dbm</b>
- or <b>db</b> format, is used for fast searching by the mail system. Execute
- the command "<b>postmap /etc/postfix/access</b>" to rebuild an indexed file
- after changing the corresponding text file.
+ as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for fast
+ lookup.
+
+ Execute the command "<b>postmap /etc/postfix/access</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/access</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
directed to a TCP-based server. In those cases, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern action</i>
- When <i>pattern</i> matches a mail address, domain or host address,
+ When <i>pattern</i> matches a mail address, domain or host address,
perform the corresponding <i>action</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b><a name="email_address_patterns_in_indexed_tables">EMAIL ADDRESS PATTERNS IN INDEXED TABLES</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, patterns are tried in the order as
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
<i>user</i>@<i>domain</i>
<i>domain.tld</i>
Matches <i>domain.tld</i> as the domain part of an email address.
- The pattern <i>domain.tld</i> also matches subdomains, but only when
- the string <b>smtpd_access_maps</b> is listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
+ The pattern <i>domain.tld</i> also matches subdomains, but only when
+ the string <b>smtpd_access_maps</b> is listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
<b><a href="postconf.5.html#parent_domain_matches_subdomains">ent_domain_matches_subdomains</a></b> configuration setting.
<i>.domain.tld</i>
- Matches subdomains of <i>domain.tld</i>, but only when the string
- <b>smtpd_access_maps</b> is not listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
+ Matches subdomains of <i>domain.tld</i>, but only when the string
+ <b>smtpd_access_maps</b> is not listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
<b><a href="postconf.5.html#parent_domain_matches_subdomains">ent_domain_matches_subdomains</a></b> configuration setting.
<i>user</i>@ Matches all mail addresses with the specified user part.
<b><a name="email_address_extension">EMAIL ADDRESS EXTENSION</a></b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>domain</i>, <i>user+foo</i>@, and <i>user</i>@.
<b>HOST NAME/ADDRESS PATTERNS IN INDEXED TABLES</b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, the following lookup patterns are
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, the following lookup patterns are
examined in the order as listed:
<i>domain.tld</i>
Matches <i>domain.tld</i>.
- The pattern <i>domain.tld</i> also matches subdomains, but only when
- the string <b>smtpd_access_maps</b> is listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
+ The pattern <i>domain.tld</i> also matches subdomains, but only when
+ the string <b>smtpd_access_maps</b> is listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
<b><a href="postconf.5.html#parent_domain_matches_subdomains">ent_domain_matches_subdomains</a></b> configuration setting.
<i>.domain.tld</i>
- Matches subdomains of <i>domain.tld</i>, but only when the string
- <b>smtpd_access_maps</b> is not listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
+ Matches subdomains of <i>domain.tld</i>, but only when the string
+ <b>smtpd_access_maps</b> is not listed in the Postfix <b><a href="postconf.5.html#parent_domain_matches_subdomains">par</a>-</b>
<b><a href="postconf.5.html#parent_domain_matches_subdomains">ent_domain_matches_subdomains</a></b> configuration setting.
<i>net.work.addr.ess</i>
<i>net.work</i>
- <i>net</i> Matches a remote IPv4 host address or network address range.
- Specify one to four decimal octets separated by ".". Do not
+ <i>net</i> Matches a remote IPv4 host address or network address range.
+ Specify one to four decimal octets separated by ".". Do not
specify "[]" , "/", leading zeros, or hexadecimal forms.
- Network ranges are matched by repeatedly truncating the last
- ".octet" from a remote IPv4 host address string, until a match
+ Network ranges are matched by repeatedly truncating the last
+ ".octet" from a remote IPv4 host address string, until a match
is found in the access table, or until further truncation is not
possible.
- NOTE: use the <b>cidr</b> lookup table type to specify network/netmask
+ NOTE: use the <b>cidr</b> lookup table type to specify network/netmask
patterns. See <a href="cidr_table.5.html"><b>cidr_table</b>(5)</a> for details.
<i>net:work:addr:ess</i>
<i>net:work</i>
- <i>net</i> Matches a remote IPv6 host address or network address range.
+ <i>net</i> Matches a remote IPv6 host address or network address range.
Specify three to eight hexadecimal octet pairs separated by ":",
- using the compressed form "::" for a sequence of zero-valued
- octet pairs. Do not specify "[]", "/", leading zeros, or
+ using the compressed form "::" for a sequence of zero-valued
+ octet pairs. Do not specify "[]", "/", leading zeros, or
non-compressed forms.
- A network range is matched by repeatedly truncating the last
- ":octetpair" from the compressed-form remote IPv6 host address
- string, until a match is found in the access table, or until
+ A network range is matched by repeatedly truncating the last
+ ":octetpair" from the compressed-form remote IPv6 host address
+ string, until a match is found in the access table, or until
further truncation is not possible.
- NOTE: use the <b>cidr</b> lookup table type to specify network/netmask
+ NOTE: use the <b>cidr</b> lookup table type to specify network/netmask
patterns. See <a href="cidr_table.5.html"><b>cidr_table</b>(5)</a> for details.
IPv6 support is available in Postfix 2.2 and later.
<b>OK</b> Accept the address etc. that matches the pattern.
<i>all-numerical</i>
- An all-numerical result is treated as OK. This format is gener-
+ An all-numerical result is treated as OK. This format is gener-
ated by address-based relay authorization schemes such as
pop-before-smtp.
For other accept actions, see "OTHER ACTIONS" below.
<b><a name="reject_actions">REJECT ACTIONS</a></b>
- Postfix version 2.3 and later support enhanced status codes as defined
- in <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>. When no code is specified at the beginning of the <i>text</i>
+ Postfix version 2.3 and later support enhanced status codes as defined
+ in <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>. When no code is specified at the beginning of the <i>text</i>
below, Postfix inserts a default enhanced status code of "5.7.1" in the
- case of reject actions, and "4.7.1" in the case of defer actions. See
+ case of reject actions, and "4.7.1" in the case of defer actions. See
"ENHANCED STATUS CODES" below.
<b>4</b><i>NN text</i>
<b>5</b><i>NN text</i>
- Reject the address etc. that matches the pattern, and respond
- with the numerical three-digit code and text. <b>4</b><i>NN</i> means "try
+ Reject the address etc. that matches the pattern, and respond
+ with the numerical three-digit code and text. <b>4</b><i>NN</i> means "try
again later", while <b>5</b><i>NN</i> means "do not try again".
- The following responses have special meaning for the Postfix
+ The following responses have special meaning for the Postfix
SMTP server:
<b>421</b> <i>text</i> (Postfix 2.3 and later)
<b>521</b> <i>text</i> (Postfix 2.6 and later)
- After responding with the numerical three-digit code and
- text, disconnect immediately from the SMTP client. This
- frees up SMTP server resources so that they can be made
+ After responding with the numerical three-digit code and
+ text, disconnect immediately from the SMTP client. This
+ frees up SMTP server resources so that they can be made
available to another SMTP client.
Note: The "521" response should be used only with botnets
- and other malware where interoperability is of no con-
- cern. The "send 521 and disconnect" behavior is NOT
+ and other malware where interoperability is of no con-
+ cern. The "send 521 and disconnect" behavior is NOT
defined in the SMTP standard.
<b>REJECT</b> <i>optional text...</i>
- Reject the address etc. that matches the pattern. Reply with
- "<b>$<a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a></b> <i>optional text...</i>" when the optional
+ Reject the address etc. that matches the pattern. Reply with
+ "<b>$<a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a></b> <i>optional text...</i>" when the optional
text is specified, otherwise reply with a generic error response
message.
<b>DEFER</b> <i>optional text...</i>
- Reject the address etc. that matches the pattern. Reply with
+ Reject the address etc. that matches the pattern. Reply with
"<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a></b> <i>optional text...</i>" when the optional text
is specified, otherwise reply with a generic error response mes-
sage.
This feature is available in Postfix 2.6 and later.
<b>DEFER_IF_REJECT</b> <i>optional text...</i>
- Defer the request if some later restriction would result in a
+ Defer the request if some later restriction would result in a
REJECT action. Reply with "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional</i>
- <i>text...</i>" when the optional text is specified, otherwise reply
+ <i>text...</i>" when the optional text is specified, otherwise reply
with a generic error response message.
Prior to Postfix 2.6, the SMTP reply code is 450.
This feature is available in Postfix 2.1 and later.
<b>DEFER_IF_PERMIT</b> <i>optional text...</i>
- Defer the request if some later restriction would result in an
- explicit or implicit PERMIT action. Reply with
- "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional text...</i>" when the
+ Defer the request if some later restriction would result in an
+ explicit or implicit PERMIT action. Reply with
+ "<b>$<a href="postconf.5.html#access_map_defer_code">access_map_defer_code</a> 4.7.1</b> <i>optional text...</i>" when the
optional text is specified, otherwise reply with a generic error
response message.
<b><a name="other_actions">OTHER ACTIONS</a></b>
<i>restriction...</i>
- Apply the named UCE restriction(s) (<b>permit</b>, <b>reject</b>,
+ Apply the named UCE restriction(s) (<b>permit</b>, <b>reject</b>,
<b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a></b>, and so on).
<b>BCC</b> <i>user@domain</i>
Send one copy of the message to the specified recipient.
- If multiple BCC actions are specified within the same SMTP MAIL
+ If multiple BCC actions are specified within the same SMTP MAIL
transaction, with Postfix 3.0 only the last action will be used.
This feature is available in Postfix 3.0 and later.
Claim successful delivery and silently discard the message. Log
the optional text if specified, otherwise log a generic message.
- Note: this action currently affects all recipients of the mes-
- sage. To discard only one recipient without discarding the
+ Note: this action currently affects all recipients of the mes-
+ sage. To discard only one recipient without discarding the
entire message, use the <a href="transport.5.html">transport(5)</a> table to direct mail to the
<a href="discard.8.html">discard(8)</a> service.
This feature is available in Postfix 2.0 and later.
<b>DUNNO</b> Pretend that the lookup key was not found. This prevents Postfix
- from trying substrings of the lookup key (such as a subdomain
+ from trying substrings of the lookup key (such as a subdomain
name, or a network address subnetwork).
This feature is available in Postfix 2.0 and later.
<b>FILTER</b> <i>transport:destination</i>
After the message is queued, send the entire message through the
- specified external content filter. The <i>transport</i> name specifies
- the first field of a mail delivery agent definition in <a href="master.5.html">mas-
- ter.cf</a>; the syntax of the next-hop <i>destination</i> is described in
- the manual page of the corresponding delivery agent. More
- information about external content filters is in the Postfix
+ specified external content filter. The <i>transport</i> name specifies
+ the first field of a mail delivery agent definition in <a href="master.5.html">mas-
+ ter.cf</a>; the syntax of the next-hop <i>destination</i> is described in
+ the manual page of the corresponding delivery agent. More
+ information about external content filters is in the Postfix
<a href="FILTER_README.html">FILTER_README</a> file.
- Note 1: do not use $<i>number</i> regular expression substitutions for
- <i>transport</i> or <i>destination</i> unless you know that the information
+ Note 1: do not use $<i>number</i> regular expression substitutions for
+ <i>transport</i> or <i>destination</i> unless you know that the information
has a trusted origin.
- Note 2: this action overrides the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#content_filter">content_filter</a></b> set-
- ting, and affects all recipients of the message. In the case
- that multiple <b>FILTER</b> actions fire, only the last one is exe-
+ Note 2: this action overrides the <a href="postconf.5.html">main.cf</a> <b><a href="postconf.5.html#content_filter">content_filter</a></b> set-
+ ting, and affects all recipients of the message. In the case
+ that multiple <b>FILTER</b> actions fire, only the last one is exe-
cuted.
Note 3: the purpose of the FILTER command is to override message
- routing. To override the recipient's <i>transport</i> but not the
+ routing. To override the recipient's <i>transport</i> but not the
next-hop <i>destination</i>, specify an empty filter <i>destination</i> (Post-
- fix 2.7 and later), or specify a <i>transport:destination</i> that
- delivers through a different Postfix instance (Postfix 2.6 and
+ fix 2.7 and later), or specify a <i>transport:destination</i> that
+ delivers through a different Postfix instance (Postfix 2.6 and
earlier). Other options are using the recipient-dependent <b><a href="postconf.5.html#transport_maps">trans</a>-</b>
- <b><a href="postconf.5.html#transport_maps">port_maps</a></b> or the sender-dependent <b><a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default-</b>
+ <b><a href="postconf.5.html#transport_maps">port_maps</a></b> or the sender-dependent <b><a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default-</b>
<b>_transport_maps</a></b> features.
This feature is available in Postfix 2.0 and later.
<b>HOLD</b> <i>optional text...</i>
- Place the message on the <b>hold</b> queue, where it will sit until
- someone either deletes it or releases it for delivery. Log the
+ Place the message on the <b>hold</b> queue, where it will sit until
+ someone either deletes it or releases it for delivery. Log the
optional text if specified, otherwise log a generic message.
- Mail that is placed on hold can be examined with the <a href="postcat.1.html"><b>postcat</b>(1)</a>
- command, and can be destroyed or released with the <a href="postsuper.1.html"><b>postsuper</b>(1)</a>
+ Mail that is placed on hold can be examined with the <a href="postcat.1.html"><b>postcat</b>(1)</a>
+ command, and can be destroyed or released with the <a href="postsuper.1.html"><b>postsuper</b>(1)</a>
command.
- Note: use "<b>postsuper -r</b>" to release mail that was kept on hold
- for a significant fraction of <b>$<a href="postconf.5.html#maximal_queue_lifetime">maximal_queue_lifetime</a></b> or
- <b>$<a href="postconf.5.html#bounce_queue_lifetime">bounce_queue_lifetime</a></b>, or longer. Use "<b>postsuper -H</b>" only for
+ Note: use "<b>postsuper -r</b>" to release mail that was kept on hold
+ for a significant fraction of <b>$<a href="postconf.5.html#maximal_queue_lifetime">maximal_queue_lifetime</a></b> or
+ <b>$<a href="postconf.5.html#bounce_queue_lifetime">bounce_queue_lifetime</a></b>, or longer. Use "<b>postsuper -H</b>" only for
mail that will not expire within a few delivery attempts.
- Note: this action currently affects all recipients of the mes-
+ Note: this action currently affects all recipients of the mes-
sage.
This feature is available in Postfix 2.0 and later.
<b>PREPEND</b> <i>headername: headervalue</i>
- Prepend the specified message header to the message. When more
- than one PREPEND action executes, the first prepended header
+ Prepend the specified message header to the message. When more
+ than one PREPEND action executes, the first prepended header
appears before the second etc. prepended header.
- Note: this action must execute before the message content is
- received; it cannot execute in the context of
+ Note: this action must execute before the message content is
+ received; it cannot execute in the context of
<b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a></b>.
This feature is available in Postfix 2.1 and later.
<b>REDIRECT</b> <i>user@domain</i>
- After the message is queued, send the message to the specified
+ After the message is queued, send the message to the specified
address instead of the intended recipient(s). When multiple <b>RE-</b>
<b>DIRECT</b> actions fire, only the last one takes effect.
- Note 1: this action overrides the FILTER action, and currently
+ Note 1: this action overrides the FILTER action, and currently
overrides all recipients of the message.
- Note 2: a REDIRECT address is subject to canonicalization (add
- missing domain) but NOT subject to canonical, masquerade, bcc,
+ Note 2: a REDIRECT address is subject to canonicalization (add
+ missing domain) but NOT subject to canonical, masquerade, bcc,
or virtual alias mapping.
This feature is available in Postfix 2.1 and later.
<b>INFO</b> <i>optional text...</i>
- Log an informational record with the optional text, together
- with client information and if available, with helo, sender,
+ Log an informational record with the optional text, together
+ with client information and if available, with helo, sender,
recipient and protocol information.
This feature is available in Postfix 3.0 and later.
<b>WARN</b> <i>optional text...</i>
- Log a warning with the optional text, together with client
- information and if available, with helo, sender, recipient and
+ Log a warning with the optional text, together with client
+ information and if available, with helo, sender, recipient and
protocol information.
This feature is available in Postfix 2.1 and later.
<b><a name="enhanced_status_codes">ENHANCED STATUS CODES</a></b>
- Postfix version 2.3 and later support enhanced status codes as defined
- in <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>. When an enhanced status code is specified in an access
+ Postfix version 2.3 and later support enhanced status codes as defined
+ in <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>. When an enhanced status code is specified in an access
table, it is subject to modification. The following transformations are
- needed when the same access table is used for client, helo, sender, or
- recipient access restrictions; they happen regardless of whether Post-
+ needed when the same access table is used for client, helo, sender, or
+ recipient access restrictions; they happen regardless of whether Post-
fix replies to a MAIL FROM, RCPT TO or other SMTP command.
- <b>o</b> When a sender address matches a REJECT action, the Postfix SMTP
+ <b>o</b> When a sender address matches a REJECT action, the Postfix SMTP
server will transform a recipient DSN status (e.g., 4.1.1-4.1.6)
into the corresponding sender DSN status, and vice versa.
- <b>o</b> When non-address information matches a REJECT action (such as
- the HELO command argument or the client hostname/address), the
- Postfix SMTP server will transform a sender or recipient DSN
+ <b>o</b> When non-address information matches a REJECT action (such as
+ the HELO command argument or the client hostname/address), the
+ Postfix SMTP server will transform a sender or recipient DSN
status into a generic non-address DSN status (e.g., 4.0.0).
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
+ Each pattern is a regular expression that is applied to the entire
string being looked up. Depending on the application, that string is an
- entire client hostname, an entire client IP address, or an entire mail
- address. Thus, no parent domain or parent network search is done,
- <i>user@domain</i> mail addresses are not broken up into their <i>user@</i> and
- <i>domain</i> constituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
+ entire client hostname, an entire client IP address, or an entire mail
+ address. Thus, no parent domain or parent network search is done,
+ <i>user@domain</i> mail addresses are not broken up into their <i>user@</i> and
+ <i>domain</i> constituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Actions are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Actions are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
available up to and including Postfix version 2.4.
- Each lookup operation uses the entire query string once. Depending on
- the application, that string is an entire client hostname, an entire
- client IP address, or an entire mail address. Thus, no parent domain
- or parent network search is done, <i>user@domain</i> mail addresses are not
- broken up into their <i>user@</i> and <i>domain</i> constituent parts, nor is
+ Each lookup operation uses the entire query string once. Depending on
+ the application, that string is an entire client hostname, an entire
+ client IP address, or an entire mail address. Thus, no parent domain
+ or parent network search is done, <i>user@domain</i> mail addresses are not
+ broken up into their <i>user@</i> and <i>domain</i> constituent parts, nor is
<i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Actions are the same as with indexed file lookups.
<b><a name="example">EXAMPLE</a></b>
- The following example uses an indexed file, so that the order of table
- entries does not matter. The example permits access by the client at
+ The following example uses an indexed file, so that the order of table
+ entries does not matter. The example permits access by the client at
address 1.2.3.4 but rejects all other clients in 1.2.3.0/24. Instead of
- <b>hash</b> lookup tables, some systems use <b>dbm</b>. Use the command "<b>postconf</b>
+ <b>hash</b> lookup tables, some systems use <b>dbm</b>. Use the command "<b>postconf</b>
<b>-m</b>" to find out what lookup tables Postfix supports on your system.
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
1.2.3 REJECT
1.2.3.4 OK
- Execute the command "<b>postmap /etc/postfix/access</b>" after editing the
+ Execute the command "<b>postmap /etc/postfix/access</b>" after editing the
file.
<b><a name="bugs">BUGS</a></b>
full email address (including domain).
Normally, the <a href="aliases.5.html"><b>aliases</b>(5)</a> table is specified as a text file that serves
- as input to the <a href="postalias.1.html"><b>postalias</b>(1)</a> command. The result, an indexed file in
- <b>dbm</b> or <b>db</b> format, is used for fast lookup by the mail system. Execute
- the command <b>newaliases</b> in order to rebuild the indexed file after
- changing the Postfix alias database.
+ as input to the <a href="postalias.1.html"><b>postalias</b>(1)</a> command to create an indexed file for fast
+ lookup. The location of this file is system-dependent. This text will
+ use <b>/path/to/aliases</b>.
+
+ Execute the command "<b>newaliases</b> to rebuild the indexed file after
+ changing the text file. Execute "<b>postalias -q</b> <i>name</i> <b>/path/to/aliases</b>" to
+ query a default-type indexed file, or execute "<b>postalias -q</b> <i>name</i>
+ <i>type</i><b>:/path/to/aliases</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions. In this case, the
- lookups are done in a slightly different way as described below under
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions. In this case, the
+ lookups are done in a slightly different way as described below under
"REGULAR EXPRESSION TABLES".
- Users can control delivery of their own mail by setting up <b>.forward</b>
- files in their home directory. Lines in per-user <b>.forward</b> files have
+ Users can control delivery of their own mail by setting up <b>.forward</b>
+ files in their home directory. Lines in per-user <b>.forward</b> files have
the same syntax as the right-hand side of <a href="aliases.5.html"><b>aliases</b>(5)</a> entries.
The format of the alias database input file is as follows:
<i>name</i>: <i>value1</i>, <i>value2</i>, <i>...</i>
- <b>o</b> Empty lines and whitespace-only lines are ignored, as are lines
+ <b>o</b> Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
- <b>o</b> A logical line starts with non-whitespace text. A line that
+ <b>o</b> A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
- The <i>name</i> is a local address (no domain part). Use double quotes when
- the name contains any special characters such as whitespace, `#', `:',
- or `@'. The <i>name</i> is folded to lowercase, in order to make database
+ The <i>name</i> is a local address (no domain part). Use double quotes when
+ the name contains any special characters such as whitespace, `#', `:',
+ or `@'. The <i>name</i> is folded to lowercase, in order to make database
lookups case insensitive.
- In addition, when an alias exists for <b>owner-</b><i>name</i>, this will override
- the envelope sender address, so that delivery diagnostics are directed
- to <b>owner-</b><i>name</i>, instead of the originator of the message (for details,
- see <b><a href="postconf.5.html#owner_request_special">owner_request_special</a></b>, <b><a href="postconf.5.html#expand_owner_alias">expand_owner_alias</a></b> and <b><a href="postconf.5.html#reset_owner_alias">reset_owner_alias</a></b>).
+ In addition, when an alias exists for <b>owner-</b><i>name</i>, this will override
+ the envelope sender address, so that delivery diagnostics are directed
+ to <b>owner-</b><i>name</i>, instead of the originator of the message (for details,
+ see <b><a href="postconf.5.html#owner_request_special">owner_request_special</a></b>, <b><a href="postconf.5.html#expand_owner_alias">expand_owner_alias</a></b> and <b><a href="postconf.5.html#reset_owner_alias">reset_owner_alias</a></b>).
This is typically used to direct delivery errors to the maintainer of a
- mailing list, who is in a better position to deal with mailing list
+ mailing list, who is in a better position to deal with mailing list
delivery problems than the originator of the undelivered mail.
The <i>value</i> contains one or more of the following:
<i>address</i>
- Mail is forwarded to <i>address</i>, which is compatible with the <a href="https://tools.ietf.org/html/rfc822">RFC</a>
+ Mail is forwarded to <i>address</i>, which is compatible with the <a href="https://tools.ietf.org/html/rfc822">RFC</a>
<a href="https://tools.ietf.org/html/rfc822">822</a> standard.
<i>/file/name</i>
- Mail is appended to <i>/file/name</i>. For details on how a file is
- written see the sections "EXTERNAL FILE DELIVERY" and "DELIVERY
- RIGHTS" in the <a href="local.8.html"><b>local</b>(8)</a> documentation. Delivery is not limited
- to regular files. For example, to dispose of unwanted mail,
+ Mail is appended to <i>/file/name</i>. For details on how a file is
+ written see the sections "EXTERNAL FILE DELIVERY" and "DELIVERY
+ RIGHTS" in the <a href="local.8.html"><b>local</b>(8)</a> documentation. Delivery is not limited
+ to regular files. For example, to dispose of unwanted mail,
deflect it to <b>/dev/null</b>.
|<i>command</i>
- Mail is piped into <i>command</i>. Commands that contain special char-
- acters, such as whitespace, should be enclosed between double
- quotes. For details on how a command is executed see "EXTERNAL
+ Mail is piped into <i>command</i>. Commands that contain special char-
+ acters, such as whitespace, should be enclosed between double
+ quotes. For details on how a command is executed see "EXTERNAL
COMMAND DELIVERY" and "DELIVERY RIGHTS" in the <a href="local.8.html"><b>local</b>(8)</a> documen-
tation.
- When the command fails, a limited amount of command output is
- mailed back to the sender. The file <b>/usr/include/sysexits.h</b>
- defines the expected exit status codes. For example, use <b>"|exit</b>
- <b>67"</b> to simulate a "user unknown" error, and <b>"|exit 0"</b> to imple-
+ When the command fails, a limited amount of command output is
+ mailed back to the sender. The file <b>/usr/include/sysexits.h</b>
+ defines the expected exit status codes. For example, use <b>"|exit</b>
+ <b>67"</b> to simulate a "user unknown" error, and <b>"|exit 0"</b> to imple-
ment an expensive black hole.
<b>:include:</b><i>/file/name</i>
- Mail is sent to the destinations listed in the named file.
- Lines in <b>:include:</b> files have the same syntax as the right-hand
+ Mail is sent to the destinations listed in the named file.
+ Lines in <b>:include:</b> files have the same syntax as the right-hand
side of <a href="aliases.5.html"><b>aliases</b>(5)</a> entries.
- A destination can be any destination that is described in this
- manual page. However, delivery to "|<i>command</i>" and <i>/file/name</i> is
- disallowed by default. To enable, edit the <b><a href="postconf.5.html#allow_mail_to_commands">allow_mail_to_com</a>-</b>
+ A destination can be any destination that is described in this
+ manual page. However, delivery to "|<i>command</i>" and <i>/file/name</i> is
+ disallowed by default. To enable, edit the <b><a href="postconf.5.html#allow_mail_to_commands">allow_mail_to_com</a>-</b>
<b><a href="postconf.5.html#allow_mail_to_commands">mands</a></b> and <b><a href="postconf.5.html#allow_mail_to_files">allow_mail_to_files</a></b> configuration parameters.
<b><a name="address_extension">ADDRESS EXTENSION</a></b>
- When alias database search fails, and the recipient localpart contains
- the optional recipient delimiter (e.g., <i>user+foo</i>), the search is
+ When alias database search fails, and the recipient localpart contains
+ the optional recipient delimiter (e.g., <i>user+foo</i>), the search is
repeated for the unextended address (e.g., <i>user</i>).
- The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
+ The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
unmatched address extension (<i>+foo</i>) is propagated to the result of table
lookup.
before database lookup.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
- expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
+ expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
NOTE: these formats do not use ":" at the end of a pattern.
Each regular expression is applied to the entire search string. Thus, a
reasons there is no support for <b>$1</b>, <b>$2</b> etc. substring interpolation.
<b><a name="security">SECURITY</a></b>
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent disallows regular expression substitution
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent disallows regular expression substitution
of $1 etc. in <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>, because that would open a security hole.
- The <a href="local.8.html"><b>local</b>(8)</a> delivery agent will silently ignore requests to use the
- <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server within <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>. Instead it will open the table
+ The <a href="local.8.html"><b>local</b>(8)</a> delivery agent will silently ignore requests to use the
+ <a href="proxymap.8.html"><b>proxymap</b>(8)</a> server within <b><a href="postconf.5.html#alias_maps">alias_maps</a></b>. Instead it will open the table
directly. Before Postfix version 2.2, the <a href="local.8.html"><b>local</b>(8)</a> delivery agent will
terminate with a fatal error.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
- below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
+ below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
details including examples.
<b><a href="postconf.5.html#alias_database">alias_database</a> (see 'postconf -d' output)</b>
- The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are updated with
+ The alias databases for <a href="local.8.html"><b>local</b>(8)</a> delivery that are updated with
"<b>newaliases</b>" or with "<b>sendmail -bi</b>".
<b><a href="postconf.5.html#alias_maps">alias_maps</a> (see 'postconf -d' output)</b>
- Optional lookup tables that are searched only with an email
- address localpart (no domain) and that apply only to <a href="local.8.html"><b>local</b>(8)</a>
- recipients; this is unlike <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> that are often
- searched with a full email address (including domain) and that
+ Optional lookup tables that are searched only with an email
+ address localpart (no domain) and that apply only to <a href="local.8.html"><b>local</b>(8)</a>
+ recipients; this is unlike <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> that are often
+ searched with a full email address (including domain) and that
apply to all recipients: <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote.
<b><a href="postconf.5.html#allow_mail_to_commands">allow_mail_to_commands</a> (alias, forward)</b>
Restrict <a href="local.8.html"><b>local</b>(8)</a> mail delivery to external files.
<b><a href="postconf.5.html#expand_owner_alias">expand_owner_alias</a> (no)</b>
- When delivering to an alias "<i>aliasname</i>" that has an
+ When delivering to an alias "<i>aliasname</i>" that has an
"owner-<i>aliasname</i>" companion alias, set the envelope sender
address to the expansion of the "owner-<i>aliasname</i>" alias.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
- The set of characters that can separate an email address local-
+ The set of characters that can separate an email address local-
part, user name, or a .forward file name from its extension.
Available in Postfix version 2.3 and later:
<b><a href="postconf.5.html#frozen_delivered_to">frozen_delivered_to</a> (yes)</b>
- Update the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the Delivered-To:
- address (see <a href="postconf.5.html#prepend_delivered_header">prepend_delivered_header</a>) only once, at the start
- of a delivery attempt; do not update the Delivered-To: address
+ Update the <a href="local.8.html"><b>local</b>(8)</a> delivery agent's idea of the Delivered-To:
+ address (see <a href="postconf.5.html#prepend_delivered_header">prepend_delivered_header</a>) only once, at the start
+ of a delivery attempt; do not update the Delivered-To: address
while expanding aliases or .forward files.
<b><a name="standards">STANDARDS</a></b>
sive.
Normally, the <a href="canonical.5.html"><b>canonical</b>(5)</a> table is specified as a text file that
- serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file
- in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
- Execute the command "<b>postmap /etc/postfix/canonical</b>" to rebuild an
- indexed file after changing the corresponding text file.
+ serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for
+ fast lookup.
+
+ Execute the command "<b>postmap /etc/postfix/canonical</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/canonical</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
directed to a TCP-based server. In those cases, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
By default the <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping affects both message header
- addresses (i.e. addresses that appear inside messages) and message
- envelope addresses (for example, the addresses that are used in SMTP
- protocol commands). This is controlled with the <b><a href="postconf.5.html#canonical_classes">canonical_classes</a></b>
+ addresses (i.e. addresses that appear inside messages) and message
+ envelope addresses (for example, the addresses that are used in SMTP
+ protocol commands). This is controlled with the <b><a href="postconf.5.html#canonical_classes">canonical_classes</a></b>
parameter.
- NOTE: Postfix versions 2.2 and later rewrite message headers from
- remote SMTP clients only if the client matches the <a href="postconf.5.html#local_header_rewrite_clients">local_header_re</a>-
+ NOTE: Postfix versions 2.2 and later rewrite message headers from
+ remote SMTP clients only if the client matches the <a href="postconf.5.html#local_header_rewrite_clients">local_header_re</a>-
<a href="postconf.5.html#local_header_rewrite_clients">write_clients</a> parameter, or if the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> config-
- uration parameter specifies a non-empty value. To get the behavior
- before Postfix 2.2, specify "<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> =
+ uration parameter specifies a non-empty value. To get the behavior
+ before Postfix 2.2, specify "<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> =
<a href="DATABASE_README.html#types">static</a>:all".
- Typically, one would use the <a href="canonical.5.html"><b>canonical</b>(5)</a> table to replace login names
+ Typically, one would use the <a href="canonical.5.html"><b>canonical</b>(5)</a> table to replace login names
by <i>Firstname.Lastname</i>, or to clean up addresses produced by legacy mail
systems.
- The <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping is not to be confused with <i>virtual alias</i> sup-
- port or with <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>. To change the destination but not the
+ The <a href="canonical.5.html"><b>canonical</b>(5)</a> mapping is not to be confused with <i>virtual alias</i> sup-
+ port or with <a href="ADDRESS_REWRITING_README.html#aliases">local aliasing</a>. To change the destination but not the
headers, use the <a href="virtual.5.html"><b>virtual</b>(5)</a> or <a href="aliases.5.html"><b>aliases</b>(5)</a> map instead.
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern address</i>
- When <i>pattern</i> matches a mail address, replace it by the corre-
+ When <i>pattern</i> matches a mail address, replace it by the corre-
sponding <i>address</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b><a name="table_search_order">TABLE SEARCH ORDER</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
sequence of query patterns as described below.
Each query pattern is sent to each specified lookup table before trying
Replace <i>user</i>@<i>domain</i> by <i>address</i>. This form has the highest prece-
dence.
- This is useful to clean up addresses produced by legacy mail
- systems. It can also be used to produce <i>Firstname.Lastname</i>
+ This is useful to clean up addresses produced by legacy mail
+ systems. It can also be used to produce <i>Firstname.Lastname</i>
style addresses, but see below for a simpler solution.
<i>user address</i>
- Replace <i>user</i>@<i>site</i> by <i>address</i> when <i>site</i> is equal to $<b><a href="postconf.5.html#myorigin">myorigin</a></b>,
- when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is listed in
+ Replace <i>user</i>@<i>site</i> by <i>address</i> when <i>site</i> is equal to $<b><a href="postconf.5.html#myorigin">myorigin</a></b>,
+ when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is listed in
$<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or $<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a></b>.
This form is useful for replacing login names by <i>Firstname.Last-</i>
Replace other addresses in <i>domain</i> by <i>address</i>. This form has the
lowest precedence.
- Note: @<i>domain</i> is a wild-card. When this form is applied to
- recipient addresses, the Postfix SMTP server accepts mail for
- any recipient in <i>domain</i>, regardless of whether that recipient
- exists. This may turn your mail system into a backscatter
- source: Postfix first accepts mail for non-existent recipients
- and then tries to return that mail as "undeliverable" to the
+ Note: @<i>domain</i> is a wild-card. When this form is applied to
+ recipient addresses, the Postfix SMTP server accepts mail for
+ any recipient in <i>domain</i>, regardless of whether that recipient
+ exists. This may turn your mail system into a backscatter
+ source: Postfix first accepts mail for non-existent recipients
+ and then tries to return that mail as "undeliverable" to the
often forged sender address.
- To avoid backscatter with mail for a wild-card domain, replace
- the wild-card mapping with explicit 1:1 mappings, or add a
+ To avoid backscatter with mail for a wild-card domain, replace
+ the wild-card mapping with explicit 1:1 mappings, or add a
<a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> restriction for that domain:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<b><a name="result_address_rewriting">RESULT ADDRESS REWRITING</a></b>
The lookup result is subject to address rewriting:
- <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
+ <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
the same <i>user</i> in <i>otherdomain</i>.
- <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
+ <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
without "@domain".
<b>o</b> When "<b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a>=yes</b>", append "<b>.$<a href="postconf.5.html#mydomain">mydomain</a></b>" to addresses
<b><a name="address_extension">ADDRESS EXTENSION</a></b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>user+foo</i>, <i>user</i>, and @<i>domain</i>.
- The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
+ The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
unmatched address extension (<i>+foo</i>) is propagated to the result of table
lookup.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
- ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
+ ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Results are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Results are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
available up to and including Postfix version 2.4.
- Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
- mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
+ Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
+ mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
stituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Results are the same as with indexed file lookups.
The table format does not understand quoting conventions.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
- below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
+ below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
details including examples.
- <b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient, header_sender,</b>
+ <b><a href="postconf.5.html#canonical_classes">canonical_classes</a> (envelope_sender, envelope_recipient, header_sender,</b>
<b>header_recipient)</b>
What addresses are subject to <a href="postconf.5.html#canonical_maps">canonical_maps</a> address mapping.
<b><a href="postconf.5.html#canonical_maps">canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for message headers and
+ Optional address mapping lookup tables for message headers and
envelopes.
<b><a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
recipient addresses.
<b><a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> (empty)</b>
- Optional address mapping lookup tables for envelope and header
+ Optional address mapping lookup tables for envelope and header
sender addresses.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The local network interface addresses that this mail system
+ The local network interface addresses that this mail system
receives mail on.
<b><a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> (<a href="postconf.5.html#permit_inet_interfaces">permit_inet_interfaces</a>)</b>
- Rewrite or add message headers in mail from these clients,
- updating incomplete addresses with the domain name in $<a href="postconf.5.html#myorigin">myorigin</a>
+ Rewrite or add message headers in mail from these clients,
+ updating incomplete addresses with the domain name in $<a href="postconf.5.html#myorigin">myorigin</a>
or $<a href="postconf.5.html#mydomain">mydomain</a>, and adding missing headers.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The remote network interface addresses that this mail system
- receives mail on by way of a proxy or network address transla-
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
tion unit.
<b><a href="postconf.5.html#masquerade_classes">masquerade_classes</a> (envelope_sender, header_sender, header_recipient)</b>
What addresses are subject to address masquerading.
<b><a href="postconf.5.html#masquerade_domains">masquerade_domains</a> (empty)</b>
- Optional list of domains whose subdomain structure will be
+ Optional list of domains whose subdomain structure will be
stripped off in email addresses.
<b><a href="postconf.5.html#masquerade_exceptions">masquerade_exceptions</a> (empty)</b>
- Optional list of user names that are not subjected to address
- masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
+ Optional list of user names that are not subjected to address
+ masquerading, even when their addresses match $<a href="postconf.5.html#masquerade_domains">masquer</a>-
<a href="postconf.5.html#masquerade_domains">ade_domains</a>.
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, localhost)</b>
- The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
+ The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
mail delivery transport.
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b><a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> (empty)</b>
- Rewrite or add message headers in mail from remote clients if
- the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
- updating incomplete addresses with the domain specified in the
+ Rewrite or add message headers in mail from remote clients if
+ the <a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter value is non-empty,
+ updating incomplete addresses with the domain specified in the
<a href="postconf.5.html#remote_header_rewrite_domain">remote_header_rewrite_domain</a> parameter, and adding missing head-
ers.
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional lookup tables. These tables are
- usually in <b>dbm</b> or <b>db</b> format. Alternatively, lookup tables can be spec-
- ified in CIDR (Classless Inter-Domain Routing) form. In this case, each
- input is compared against a list of patterns. When a match is found,
- the corresponding result is returned and the search is terminated.
+ usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b> format.
+
+ Alternatively, lookup tables can be specified in CIDR (Classless
+ Inter-Domain Routing) form. In this case, each input is compared
+ against a list of patterns. When a match is found, the corresponding
+ result is returned and the search is terminated.
To find out what types of lookup tables your Postfix system supports
use the "<b>postconf -m</b>" command.
(for example, the addresses that are used in SMTP protocol commands).
Normally, the <a href="generic.5.html"><b>generic</b>(5)</a> table is specified as a text file that serves
- as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file in <b>dbm</b>
- or <b>db</b> format, is used for fast searching by the mail system. Execute
- the command "<b>postmap /etc/postfix/generic</b>" to rebuild an indexed file
- after changing the corresponding text file.
+ as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for fast
+ lookup.
+
+ Execute the command "<b>postmap /etc/postfix/generic</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/generic</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
directed to a TCP-based server. In those cases, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern result</i>
- When <i>pattern</i> matches a mail address, replace it by the corre-
+ When <i>pattern</i> matches a mail address, replace it by the corre-
sponding <i>result</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b><a name="table_search_order">TABLE SEARCH ORDER</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
sequence of query patterns as described below.
Each query pattern is sent to each specified lookup table before trying
dence.
<i>user address</i>
- Replace <i>user</i>@<i>site</i> by <i>address</i> when <i>site</i> is equal to $<b><a href="postconf.5.html#myorigin">myorigin</a></b>,
- when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is listed in
+ Replace <i>user</i>@<i>site</i> by <i>address</i> when <i>site</i> is equal to $<b><a href="postconf.5.html#myorigin">myorigin</a></b>,
+ when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is listed in
$<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or $<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a></b>.
@<i>domain address</i>
<b><a name="result_address_rewriting">RESULT ADDRESS REWRITING</a></b>
The lookup result is subject to address rewriting:
- <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
+ <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
the same <i>user</i> in <i>otherdomain</i>.
- <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
+ <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
without "@domain".
<b>o</b> When "<b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a>=yes</b>", append "<b>.$<a href="postconf.5.html#mydomain">mydomain</a></b>" to addresses
<b><a name="address_extension">ADDRESS EXTENSION</a></b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>user+foo</i>, <i>user</i>, and @<i>domain</i>.
- The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
+ The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
unmatched address extension (<i>+foo</i>) is propagated to the result of table
lookup.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
- ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
+ ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Results are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Results are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
available in Postfix 2.5 and later.
- Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
- mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
+ Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
+ mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
stituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Results are the same as with indexed file lookups.
<b><a name="example">EXAMPLE</a></b>
- The following shows a generic mapping with an indexed file. When mail
- is sent to a remote host via SMTP, this replaces <i>his@localdomain.local</i>
+ The following shows a generic mapping with an indexed file. When mail
+ is sent to a remote host via SMTP, this replaces <i>his@localdomain.local</i>
by his ISP mail address, replaces <i>her@localdomain.local</i> by her ISP mail
address, and replaces other local addresses by his ISP account, with an
address extension of <i>+local</i> (this example assumes that the ISP supports
her@localdomain.local heraccount@herisp.example
@localdomain.local hisaccount+local@hisisp.example
- Execute the command "<b>postmap /etc/postfix/generic</b>" whenever the table
- is changed. Instead of <b>hash</b>, some systems use <b>dbm</b> database files. To
- find out what tables your system supports use the command "<b>postconf</b>
+ Execute the command "<b>postmap /etc/postfix/generic</b>" whenever the table
+ is changed. Instead of <b>hash</b>, some systems use <b>dbm</b> database files. To
+ find out what tables your system supports use the command "<b>postconf</b>
<b>-m</b>".
<b><a name="bugs">BUGS</a></b>
The table format does not understand quoting conventions.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
- below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
+ below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
details including examples.
<b><a href="postconf.5.html#smtp_generic_maps">smtp_generic_maps</a> (empty)</b>
- Optional lookup tables that perform address rewriting in the
- Postfix SMTP client, typically to transform a locally valid
- address into a globally valid address when sending mail across
+ Optional lookup tables that perform address rewriting in the
+ Postfix SMTP client, typically to transform a locally valid
+ address into a globally valid address when sending mail across
the Internet.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The local network interface addresses that this mail system
+ The local network interface addresses that this mail system
receives mail on.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The remote network interface addresses that this mail system
- receives mail on by way of a proxy or network address transla-
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
tion unit.
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, localhost)</b>
- The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
+ The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
mail delivery transport.
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b><a name="see_also">SEE ALSO</a></b>
<li> <a href="DATABASE_README.html"> Lookup table overview </a>
+<li> <a href="NON_BERKELEYDB_README.html"> Non-Berkeley-DB migration </a>
+
<li> <a href="DB_README.html"> Berkeley DB Howto </a>
<li> <a href="CDB_README.html"> CDB Howto </a>
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- Alternatively, lookup tables can be specified as LDAP databases.
+ Alternatively, lookup tables can be specified as LDAP databases. To
+ find out what types of lookup tables your Postfix system supports use
+ the "<b>postconf -m</b>" command.
- In order to use LDAP lookups, define an LDAP source as a lookup table
+ In order to use LDAP lookups, define an LDAP source as a lookup table
in <a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="ldap_table.5.html">ldap</a>:/etc/postfix/ldap-aliases.cf
- The file /etc/postfix/ldap-aliases.cf has the same format as the Post-
- fix <a href="postconf.5.html">main.cf</a> file, and can specify the parameters described below. An
+ The file /etc/postfix/ldap-aliases.cf has the same format as the Post-
+ fix <a href="postconf.5.html">main.cf</a> file, and can specify the parameters described below. An
example is given at the end of this manual.
- This configuration method is available with Postfix version 2.1 and
- later. See the section "OBSOLETE MAIN.CF PARAMETERS" below for older
+ This configuration method is available with Postfix version 2.1 and
+ later. See the section "OBSOLETE MAIN.CF PARAMETERS" below for older
Postfix versions.
- For details about LDAP SSL and STARTTLS, see the section on SSL and
+ For details about LDAP SSL and STARTTLS, see the section on SSL and
STARTTLS below.
<b><a name="list_membership">LIST MEMBERSHIP</a></b>
- When using LDAP to store lists such as $<a href="postconf.5.html#mynetworks">mynetworks</a>, $<a href="postconf.5.html#mydestination">mydestination</a>,
- $<a href="postconf.5.html#relay_domains">relay_domains</a>, $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>, etc., it is important to under-
+ When using LDAP to store lists such as $<a href="postconf.5.html#mynetworks">mynetworks</a>, $<a href="postconf.5.html#mydestination">mydestination</a>,
+ $<a href="postconf.5.html#relay_domains">relay_domains</a>, $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>, etc., it is important to under-
stand that the table must store each list member as a separate key. The
- table lookup verifies the *existence* of the key. See "Postfix lists
+ table lookup verifies the *existence* of the key. See "Postfix lists
versus tables" in the <a href="DATABASE_README.html">DATABASE_README</a> document for a discussion.
- Do NOT create tables that return the full list of domains in $<a href="postconf.5.html#mydestination">mydesti</a>-
+ Do NOT create tables that return the full list of domains in $<a href="postconf.5.html#mydestination">mydesti</a>-
<a href="postconf.5.html#mydestination">nation</a> or $<a href="postconf.5.html#relay_domains">relay_domains</a> etc., or IP addresses in $<a href="postconf.5.html#mynetworks">mynetworks</a>.
DO create tables with each matching item as a key and with an arbitrary
result_attribute = domain
<b><a name="general_ldap_parameters">GENERAL LDAP PARAMETERS</a></b>
- In the text below, default values are given in parentheses. Note:
- don't use quotes in these variables; at least, not until the Postfix
+ In the text below, default values are given in parentheses. Note:
+ don't use quotes in these variables; at least, not until the Postfix
configuration routines understand how to deal with quoted strings.
<b>server_host (default: localhost)</b>
server_host = ldap.example.com
- Depending on the LDAP client library you're using, it should be
+ Depending on the LDAP client library you're using, it should be
possible to specify multiple servers here, with the library try-
- ing them in order should the first one fail. It should also be
+ ing them in order should the first one fail. It should also be
possible to give each server in the list a different port (over-
riding <b>server_port</b> below), by naming them like
server_host = ldap.example.com:1444
- NOTE: this client will reconnect immediately after a single
- failure, and will fail a lookup request after a second attempt
+ NOTE: this client will reconnect immediately after a single
+ failure, and will fail a lookup request after a second attempt
also fails.
With OpenLDAP, a (list of) LDAP URLs can be used to specify both
server_host = <a href="ldap_table.5.html">ldap</a>://ldap.example.com:1444
<a href="ldap_table.5.html">ldap</a>://ldap2.example.com:1444
- All LDAP URLs accepted by the OpenLDAP library are supported,
- including connections over UNIX domain sockets, and LDAP SSL
- (the last one provided that OpenLDAP was compiled with support
+ All LDAP URLs accepted by the OpenLDAP library are supported,
+ including connections over UNIX domain sockets, and LDAP SSL
+ (the last one provided that OpenLDAP was compiled with support
for SSL):
server_host = <a href="ldap_table.5.html">ldapi</a>://%2Fsome%2Fpath
server_port = 778
<b>timeout (default: 10 seconds)</b>
- The number of seconds a search can take before timing out, e.g.
+ The number of seconds a search can take before timing out, e.g.
timeout = 5
<b>%%</b> This is replaced by a literal '%' character.
- <b>%s</b> This is replaced by the input key. <a href="https://tools.ietf.org/html/rfc2253">RFC 2253</a> quoting is
- used to make sure that the input key does not add unex-
+ <b>%s</b> This is replaced by the input key. <a href="https://tools.ietf.org/html/rfc2253">RFC 2253</a> quoting is
+ used to make sure that the input key does not add unex-
pected metacharacters.
<b>%u</b> When the input key is an address of the form user@domain,
<b>%u</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2253">RFC 2253</a>) quoted local part of the
- address. Otherwise, <b>%u</b> is replaced by the entire search
- string. If the localpart is empty, the search is sup-
+ address. Otherwise, <b>%u</b> is replaced by the entire search
+ string. If the localpart is empty, the search is sup-
pressed and returns no results.
<b>%d</b> When the input key is an address of the form user@domain,
- <b>%d</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2253">RFC 2253</a>) quoted domain part of
- the address. Otherwise, the search is suppressed and
+ <b>%d</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2253">RFC 2253</a>) quoted domain part of
+ the address. Otherwise, the search is suppressed and
returns no results.
<b>%[SUD]</b> For the <b>search_base</b> parameter, the upper-case equivalents
- of the above expansions behave identically to their
- lower-case counter-parts. With the <b>result_format</b> parame-
- ter (previously called <b>result_filter</b> see the OTHER OBSO-
+ of the above expansions behave identically to their
+ lower-case counter-parts. With the <b>result_format</b> parame-
+ ter (previously called <b>result_filter</b> see the OTHER OBSO-
LETE FEATURES section and below), they expand to the cor-
responding components of input key rather than the result
value.
- <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
- sponding most significant component of the input key's
- domain. If the input key is <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. If the input key
- is unqualified or does not have enough domain components
+ is unqualified or does not have enough domain components
to satisfy all the specified patterns, the search is sup-
pressed and returns no results.
<b>query_filter (default: mailacceptinggeneralid=%s)</b>
- The <a href="https://tools.ietf.org/html/rfc2254">RFC2254</a> filter used to search the directory, where <b>%s</b> is a
+ The <a href="https://tools.ietf.org/html/rfc2254">RFC2254</a> filter used to search the directory, where <b>%s</b> is a
substitute for the address Postfix is trying to resolve, e.g.
query_filter = (&(mail=%s)(paid_up=true))
<b>%%</b> This is replaced by a literal '%' character. (Postfix 2.2
and later).
- <b>%s</b> This is replaced by the input key. <a href="https://tools.ietf.org/html/rfc2254">RFC 2254</a> quoting is
- used to make sure that the input key does not add unex-
+ <b>%s</b> This is replaced by the input key. <a href="https://tools.ietf.org/html/rfc2254">RFC 2254</a> quoting is
+ used to make sure that the input key does not add unex-
pected metacharacters.
<b>%u</b> When the input key is an address of the form user@domain,
<b>%u</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2254">RFC 2254</a>) quoted local part of the
- address. Otherwise, <b>%u</b> is replaced by the entire search
- string. If the localpart is empty, the search is sup-
+ address. Otherwise, <b>%u</b> is replaced by the entire search
+ string. If the localpart is empty, the search is sup-
pressed and returns no results.
<b>%d</b> When the input key is an address of the form user@domain,
- <b>%d</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2254">RFC 2254</a>) quoted domain part of
- the address. Otherwise, the search is suppressed and
+ <b>%d</b> is replaced by the (<a href="https://tools.ietf.org/html/rfc2254">RFC 2254</a>) quoted domain part of
+ the address. Otherwise, the search is suppressed and
returns no results.
<b>%[SUD]</b> The upper-case equivalents of the above expansions behave
- in the <b>query_filter</b> parameter identically to their
- lower-case counter-parts. With the <b>result_format</b> parame-
- ter (previously called <b>result_filter</b> see the OTHER OBSO-
+ in the <b>query_filter</b> parameter identically to their
+ lower-case counter-parts. With the <b>result_format</b> parame-
+ ter (previously called <b>result_filter</b> see the OTHER OBSO-
LETE FEATURES section and below), they expand to the cor-
responding components of input key rather than the result
value.
- The above %S, %U and %D expansions are available with
+ The above %S, %U and %D expansions are available with
Postfix 2.2 and later.
- <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
- sponding most significant component of the input key's
- domain. If the input key is <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. If the input key
- is unqualified or does not have enough domain components
+ is unqualified or does not have enough domain components
to satisfy all the specified patterns, the search is sup-
pressed and returns no results.
The above %1, ..., %9 expansions are available with Post-
fix 2.2 and later.
- The "domain" parameter described below limits the input keys to
- addresses in matching domains. When the "domain" parameter is
- non-empty, LDAP queries for unqualified addresses or addresses
+ The "domain" parameter described below limits the input keys to
+ addresses in matching domains. When the "domain" parameter is
+ non-empty, LDAP queries for unqualified addresses or addresses
in non-matching domains are suppressed and return no results.
NOTE: DO NOT put quotes around the <b>query_filter</b> parameter.
<b>result_format (default: %s</b>)
- Called <b>result_filter</b> in Postfix releases prior to 2.2. Format
- template applied to result attributes. Most commonly used to
- append (or prepend) text to the result. This parameter supports
+ Called <b>result_filter</b> in Postfix releases prior to 2.2. Format
+ template applied to result attributes. Most commonly used to
+ append (or prepend) text to the result. This parameter supports
the following '%' expansions:
<b>%%</b> This is replaced by a literal '%' character. (Postfix 2.2
and later).
- <b>%s</b> This is replaced by the value of the result attribute.
+ <b>%s</b> This is replaced by the value of the result attribute.
When result is empty it is skipped.
<b>%u</b> When the result attribute value is an address of the form
- user@domain, <b>%u</b> is replaced by the local part of the
- address. When the result has an empty localpart it is
+ user@domain, <b>%u</b> is replaced by the local part of the
+ address. When the result has an empty localpart it is
skipped.
- <b>%d</b> When a result attribute value is an address of the form
- user@domain, <b>%d</b> is replaced by the domain part of the
- attribute value. When the result is unqualified it is
+ <b>%d</b> When a result attribute value is an address of the form
+ user@domain, <b>%d</b> is replaced by the domain part of the
+ attribute value. When the result is unqualified it is
skipped.
<b>%[SUD1-9]</b>
- The upper-case and decimal digit expansions interpolate
- the parts of the input key rather than the result. Their
- behavior is identical to that described with <b>query_fil-</b>
- <b>ter</b>, and in fact because the input key is known in
- advance, lookups whose key does not contain all the
- information specified in the result template are sup-
+ The upper-case and decimal digit expansions interpolate
+ the parts of the input key rather than the result. Their
+ behavior is identical to that described with <b>query_fil-</b>
+ <b>ter</b>, and in fact because the input key is known in
+ advance, lookups whose key does not contain all the
+ information specified in the result template are sup-
pressed and return no results.
- The above %S, %U, %D and %1, ..., %9 expansions are
+ The above %S, %U, %D and %1, ..., %9 expansions are
available with Postfix 2.2 and later.
For example, using "result_format = <a href="smtp.8.html">smtp</a>:[%s]" allows one to use
a mailHost attribute as the basis of a <a href="transport.5.html">transport(5)</a> table. After
- applying the result format, multiple values are concatenated as
- comma separated strings. The expansion_limit and size_limit
- parameters explained below allow one to restrict the number of
- values in the result, which is especially useful for maps that
+ applying the result format, multiple values are concatenated as
+ comma separated strings. The expansion_limit and size_limit
+ parameters explained below allow one to restrict the number of
+ values in the result, which is especially useful for maps that
should return a single value.
- The default value <b>%s</b> specifies that each attribute value should
+ The default value <b>%s</b> specifies that each attribute value should
be used as is.
- This parameter was called <b>result_filter</b> in Postfix releases
- prior to 2.2. If no "result_format" is specified, the value of
- "result_filter" will be used instead before resorting to the
- default value. This provides compatibility with old configura-
+ This parameter was called <b>result_filter</b> in Postfix releases
+ prior to 2.2. If no "result_format" is specified, the value of
+ "result_filter" will be used instead before resorting to the
+ default value. This provides compatibility with old configura-
tion files.
NOTE: DO NOT put quotes around the result format!
<b>domain (default: no domain list)</b>
- This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
+ This is a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
databases. When specified, only fully qualified search keys with
- a *non-empty* localpart and a matching domain are eligible for
+ a *non-empty* localpart and a matching domain are eligible for
lookup: 'user' lookups, bare domain lookups and "@domain"
- lookups are not performed. This can significantly reduce the
+ lookups are not performed. This can significantly reduce the
query load on the LDAP server.
domain = postfix.org, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
- It is best not to use LDAP to store the domains eligible for
+ It is best not to use LDAP to store the domains eligible for
LDAP lookups.
NOTE: DO NOT define this parameter for <a href="local.8.html">local(8)</a> aliases.
This feature is available in Postfix 1.0 and later.
<b>result_attribute (default: maildrop)</b>
- The attribute(s) Postfix will read from any directory entries
+ The attribute(s) Postfix will read from any directory entries
returned by the lookup, to be resolved to an email address.
result_attribute = mailbox, maildrop
- Don't rely on the default value ("maildrop"). Set the
- result_attribute explicitly in all ldap table configuration
+ Don't rely on the default value ("maildrop"). Set the
+ result_attribute explicitly in all ldap table configuration
files. This is particularly relevant when no result_attribute is
- applicable, e.g. cases in which leaf_result_attribute and/or
+ applicable, e.g. cases in which leaf_result_attribute and/or
terminal_result_attribute are used instead. The default value is
- harmless if "maildrop" is also listed as a leaf or terminal
+ harmless if "maildrop" is also listed as a leaf or terminal
result attribute, but it is best to not leave this to chance.
<b>special_result_attribute (default: empty)</b>
- The attribute(s) of directory entries that can contain DNs or
+ The attribute(s) of directory entries that can contain DNs or
<a href="https://tools.ietf.org/html/rfc2255">RFC 2255</a> LDAP URLs. If found, a recursive search is performed to
- retrieve the entry referenced by the DN, or the entries matched
+ retrieve the entry referenced by the DN, or the entries matched
by the URL query.
special_result_attribute = memberdn
- DN recursion retrieves the same result_attributes as the main
+ DN recursion retrieves the same result_attributes as the main
query, including the special attributes for further recursion.
URL processing retrieves only those attributes that are included
- in both the URL definition and as result attributes (ordinary,
- special, leaf or terminal) in the Postfix table definition. If
- the URL lists any of the table's special result attributes,
- these are retrieved and used recursively. A URL that does not
- specify any attribute selection, is equivalent (<a href="https://tools.ietf.org/html/rfc2255">RFC 2255</a>) to a
- URL that selects all attributes, in which case the selected
- attributes will be the full set of result attributes in the
+ in both the URL definition and as result attributes (ordinary,
+ special, leaf or terminal) in the Postfix table definition. If
+ the URL lists any of the table's special result attributes,
+ these are retrieved and used recursively. A URL that does not
+ specify any attribute selection, is equivalent (<a href="https://tools.ietf.org/html/rfc2255">RFC 2255</a>) to a
+ URL that selects all attributes, in which case the selected
+ attributes will be the full set of result attributes in the
Postfix table.
If an LDAP URL attribute-descriptor or the corresponding Postfix
- LDAP table result attribute (but not both) uses <a href="https://tools.ietf.org/html/rfc2255">RFC 2255</a>
- sub-type options ("attr;option"), the attribute requested from
- the LDAP server will include the sub-type option. In all other
- cases, the URL attribute and the table attribute must match
+ LDAP table result attribute (but not both) uses <a href="https://tools.ietf.org/html/rfc2255">RFC 2255</a>
+ sub-type options ("attr;option"), the attribute requested from
+ the LDAP server will include the sub-type option. In all other
+ cases, the URL attribute and the table attribute must match
exactly. Attributes with options in both the URL and the Postfix
- table are requested only when the options are identical. LDAP
- attribute-descriptor options are very rarely used, most LDAP
- users will not need to concern themselves with this level of
+ table are requested only when the options are identical. LDAP
+ attribute-descriptor options are very rarely used, most LDAP
+ users will not need to concern themselves with this level of
nuanced detail.
<b>terminal_result_attribute (default: empty)</b>
When one or more terminal result attributes are found in an LDAP
entry, all other result attributes are ignored and only the ter-
- minal result attributes are returned. This is useful for dele-
+ minal result attributes are returned. This is useful for dele-
gating expansion of group members to a particular host, by using
an optional "maildrop" attribute on selected groups to route the
- group to a specific host, where the group is expanded, possibly
+ group to a specific host, where the group is expanded, possibly
via mailing-list manager or other special processing.
result_attribute =
terminal_result_attribute = maildrop
- When using terminal and/or leaf result attributes, the
- result_attribute is best set to an empty value when it is not
+ When using terminal and/or leaf result attributes, the
+ result_attribute is best set to an empty value when it is not
used, or else explicitly set to the desired value, even if it is
the default value "maildrop".
This feature is available with Postfix 2.4 or later.
<b>leaf_result_attribute (default: empty)</b>
- When one or more special result attributes are found in a
- non-terminal (see above) LDAP entry, leaf result attributes are
- excluded from the expansion of that entry. This is useful when
- expanding groups and the desired mail address attribute(s) of
- the member objects obtained via DN or URI recursion are also
+ When one or more special result attributes are found in a
+ non-terminal (see above) LDAP entry, leaf result attributes are
+ excluded from the expansion of that entry. This is useful when
+ expanding groups and the desired mail address attribute(s) of
+ the member objects obtained via DN or URI recursion are also
present in the group object. To only return the attribute values
- from the leaf objects and not the containing group, add the
- attribute to the leaf_result_attribute list, and not the
- result_attribute list, which is always expanded. Note, the
- default value of "result_attribute" is not empty, you may want
+ from the leaf objects and not the containing group, add the
+ attribute to the leaf_result_attribute list, and not the
+ result_attribute list, which is always expanded. Note, the
+ default value of "result_attribute" is not empty, you may want
to set it explicitly empty when using "leaf_result_attribute" to
- expand the group to a list of member DN addresses. If groups
+ expand the group to a list of member DN addresses. If groups
have both member DN references AND attributes that hold multiple
string valued rfc822 addresses, then the string attributes go in
- "result_attribute". The attributes that represent the email
- addresses of objects referenced via a DN (or LDAP URI) go in
+ "result_attribute". The attributes that represent the email
+ addresses of objects referenced via a DN (or LDAP URI) go in
"leaf_result_attribute".
result_attribute = memberaddr
terminal_result_attribute = maildrop
leaf_result_attribute = mail
- When using terminal and/or leaf result attributes, the
- result_attribute is best set to an empty value when it is not
+ When using terminal and/or leaf result attributes, the
+ result_attribute is best set to an empty value when it is not
used, or else explicitly set to the desired value, even if it is
the default value "maildrop".
This feature is available with Postfix 2.4 or later.
<b>scope (default: sub)</b>
- The LDAP search scope: <b>sub</b>, <b>base</b>, or <b>one</b>. These translate into
+ The LDAP search scope: <b>sub</b>, <b>base</b>, or <b>one</b>. These translate into
LDAP_SCOPE_SUBTREE, LDAP_SCOPE_BASE, and LDAP_SCOPE_ONELEVEL.
<b>bind (default: yes)</b>
- Whether or how to bind to the LDAP server. Newer LDAP implemen-
- tations don't require clients to bind, which saves time. Exam-
+ Whether or how to bind to the LDAP server. Newer LDAP implemen-
+ tations don't require clients to bind, which saves time. Exam-
ple:
# Don't bind
# Use SASL bind
bind = sasl
- Postfix versions prior to 2.8 only support "bind = no" which
+ Postfix versions prior to 2.8 only support "bind = no" which
means don't bind, and "bind = yes" which means do a SIMPLE bind.
- Postfix 2.8 and later also supports "bind = SASL" when compiled
+ Postfix 2.8 and later also supports "bind = SASL" when compiled
with LDAP SASL support as described in <a href="LDAP_README.html">LDAP_README</a>, it also adds
- the synonyms "bind = none" and "bind = simple" for "bind = no"
- and "bind = yes" respectively. See the SASL section below for
+ the synonyms "bind = none" and "bind = simple" for "bind = no"
+ and "bind = yes" respectively. See the SASL section below for
additional parameters available with "bind = sasl".
- If you do need to bind, you might consider configuring Postfix
- to connect to the local machine on a port that's an SSL tunnel
- to your LDAP server. If your LDAP server doesn't natively sup-
- port SSL, put a tunnel (wrapper, proxy, whatever you want to
- call it) on that system too. This should prevent the password
+ If you do need to bind, you might consider configuring Postfix
+ to connect to the local machine on a port that's an SSL tunnel
+ to your LDAP server. If your LDAP server doesn't natively sup-
+ port SSL, put a tunnel (wrapper, proxy, whatever you want to
+ call it) on that system too. This should prevent the password
from traversing the network in the clear.
<b>bind_dn (default: empty)</b>
- If you do have to bind, do it with this distinguished name.
+ If you do have to bind, do it with this distinguished name.
Example:
bind_dn = uid=postfix, dc=your, dc=com
- With "bind = sasl" (see above) the DN may be optional for some
+ With "bind = sasl" (see above) the DN may be optional for some
SASL mechanisms, don't specify a DN if not needed.
<b>bind_pw (default: empty)</b>
- The password for the distinguished name above. If you have to
- use this, you probably want to make the map configuration file
- readable only by the Postfix user. When using the obsolete
- <a href="ldap_table.5.html">ldap</a>:ldapsource syntax, with map parameters in <a href="postconf.5.html">main.cf</a>, it is
- not possible to securely store the bind password. This is
- because <a href="postconf.5.html">main.cf</a> needs to be world readable to allow local
+ The password for the distinguished name above. If you have to
+ use this, you probably want to make the map configuration file
+ readable only by the Postfix user. When using the obsolete
+ <a href="ldap_table.5.html">ldap</a>:ldapsource syntax, with map parameters in <a href="postconf.5.html">main.cf</a>, it is
+ not possible to securely store the bind password. This is
+ because <a href="postconf.5.html">main.cf</a> needs to be world readable to allow local
accounts to submit mail via the sendmail command. Example:
bind_pw = postfixpw
- With "bind = sasl" (see above) the password may be optional for
+ With "bind = sasl" (see above) the password may be optional for
some SASL mechanisms, don't specify a password if not needed.
<b>cache (IGNORED with a warning)</b>
<b>cache_expiry (IGNORED with a warning)</b>
<b>cache_size (IGNORED with a warning)</b>
- The above parameters are NO LONGER SUPPORTED by Postfix. Cache
+ The above parameters are NO LONGER SUPPORTED by Postfix. Cache
support has been dropped from OpenLDAP as of release 2.1.13.
<b>recursion_limit (default: 1000)</b>
- A limit on the nesting depth of DN and URL special result
+ A limit on the nesting depth of DN and URL special result
attribute evaluation. The limit must be a non-zero positive num-
ber.
<b>expansion_limit (default: 0)</b>
- A limit on the total number of result elements returned (as a
+ A limit on the total number of result elements returned (as a
comma separated list) by a lookup against the map. A setting of
- zero disables the limit. Lookups fail with a temporary error if
- the limit is exceeded. Setting the limit to 1 ensures that
+ zero disables the limit. Lookups fail with a temporary error if
+ the limit is exceeded. Setting the limit to 1 ensures that
lookups do not return multiple values.
<b>size_limit (default: $expansion_limit)</b>
- A limit on the number of LDAP entries returned by any single
+ A limit on the number of LDAP entries returned by any single
LDAP search performed as part of the lookup. A setting of 0 dis-
- ables the limit. Expansion of DN and URL references involves
- nested LDAP queries, each of which is separately subjected to
+ ables the limit. Expansion of DN and URL references involves
+ nested LDAP queries, each of which is separately subjected to
this limit.
- Note: even a single LDAP entry can generate multiple lookup
- results, via multiple result attributes and/or multi-valued
- result attributes. This limit caps the per search resource uti-
- lization on the LDAP server, not the final multiplicity of the
- lookup result. It is analogous to the "-z" option of
+ Note: even a single LDAP entry can generate multiple lookup
+ results, via multiple result attributes and/or multi-valued
+ result attributes. This limit caps the per search resource uti-
+ lization on the LDAP server, not the final multiplicity of the
+ lookup result. It is analogous to the "-z" option of
"ldapsearch".
<b>dereference (default: 0)</b>
When to dereference LDAP aliases. (Note that this has nothing do
- with Postfix aliases.) The permitted values are those legal for
+ with Postfix aliases.) The permitted values are those legal for
the OpenLDAP/UM LDAP implementations:
0 never
3 always
- See ldap.h or the ldap_open(3) or ldapsearch(1) man pages for
- more information. And if you're using an LDAP package that has
- other possible values, please bring it to the attention of the
+ See ldap.h or the ldap_open(3) or ldapsearch(1) man pages for
+ more information. And if you're using an LDAP package that has
+ other possible values, please bring it to the attention of the
postfix-users@postfix.org mailing list.
<b>chase_referrals (default: 0)</b>
- Sets (or clears) LDAP_OPT_REFERRALS (requires LDAP version 3
+ Sets (or clears) LDAP_OPT_REFERRALS (requires LDAP version 3
support).
<b>version (default: 2)</b>
What level to set for debugging in the OpenLDAP libraries.
<b><a name="ldap_sasl_parameters">LDAP SASL PARAMETERS</a></b>
- If you're using the OpenLDAP libraries compiled with SASL support,
- Postfix 2.8 and later built with LDAP SASL support as described in
+ If you're using the OpenLDAP libraries compiled with SASL support,
+ Postfix 2.8 and later built with LDAP SASL support as described in
<a href="LDAP_README.html">LDAP_README</a> can authenticate to LDAP servers via SASL.
- This enables authentication to the LDAP server via mechanisms other
- than a simple password. The added flexibility has a cost: it is no
- longer practical to set an explicit timeout on the duration of an LDAP
- bind operation. Under adverse conditions, whether a SASL bind times
- out, or if it does, the duration of the timeout is determined by the
+ This enables authentication to the LDAP server via mechanisms other
+ than a simple password. The added flexibility has a cost: it is no
+ longer practical to set an explicit timeout on the duration of an LDAP
+ bind operation. Under adverse conditions, whether a SASL bind times
+ out, or if it does, the duration of the timeout is determined by the
LDAP and SASL libraries.
- It is best to use tables that use SASL binds via <a href="proxymap.8.html">proxymap(8)</a>, this way
- the requesting process can time-out the proxymap request. This also
- lets you tailer the process environment by overriding the <a href="proxymap.8.html">proxymap(8)</a>
- <a href="postconf.5.html#import_environment">import_environment</a> setting in <a href="master.5.html">master.cf</a>(5). Special environment set-
+ It is best to use tables that use SASL binds via <a href="proxymap.8.html">proxymap(8)</a>, this way
+ the requesting process can time-out the proxymap request. This also
+ lets you tailer the process environment by overriding the <a href="proxymap.8.html">proxymap(8)</a>
+ <a href="postconf.5.html#import_environment">import_environment</a> setting in <a href="master.5.html">master.cf</a>(5). Special environment set-
tings may be needed to configure GSSAPI credential caches or other SASL
- mechanism specific options. The GSSAPI credentials used for LDAP
- lookups may need to be different than say those used for the Postfix
+ mechanism specific options. The GSSAPI credentials used for LDAP
+ lookups may need to be different than say those used for the Postfix
SMTP client to authenticate to remote servers.
- Using SASL mechanisms requires LDAP protocol version 3, the default
- protocol version is 2 for backwards compatibility. You must set "ver-
+ Using SASL mechanisms requires LDAP protocol version 3, the default
+ protocol version is 2 for backwards compatibility. You must set "ver-
sion = 3" in addition to "bind = sasl".
The following parameters are relevant to using LDAP with SASL
The SASL authorization identity to assert, if applicable.
<b>sasl_minssf (default: 0)</b>
- The minimum required sasl security factor required to establish
+ The minimum required sasl security factor required to establish
a connection.
<b><a name="ldap_ssl_and_starttls_parameters">LDAP SSL AND STARTTLS PARAMETERS</a></b>
If you're using the OpenLDAP libraries compiled with SSL support, Post-
fix can connect to LDAP SSL servers and can issue the STARTTLS command.
- LDAP SSL service can be requested by using a LDAP SSL URL in the
+ LDAP SSL service can be requested by using a LDAP SSL URL in the
server_host parameter:
server_host = <a href="ldap_table.5.html">ldaps</a>://ldap.example.com:636
version = 3
- If any of the Postfix programs querying the map is configured in <a href="master.5.html">mas-
- ter.cf</a> to run chrooted, all the certificates and keys involved have to
- be copied to the chroot jail. Of course, the private keys should only
+ If any of the Postfix programs querying the map is configured in <a href="master.5.html">mas-
+ ter.cf</a> to run chrooted, all the certificates and keys involved have to
+ be copied to the chroot jail. Of course, the private keys should only
be readable by the user "postfix".
The following parameters are relevant to LDAP SSL and STARTTLS:
<b>start_tls (default: no)</b>
- Whether or not to issue STARTTLS upon connection to the server.
+ Whether or not to issue STARTTLS upon connection to the server.
Don't set this with LDAP SSL (the SSL session is setup automati-
cally when the TCP connection is opened).
<b>tls_ca_cert_dir (No default; set either this or tls_ca_cert_file)</b>
- Directory containing X509 Certification Authority certificates
- in PEM format which are to be recognized by the client in
- SSL/TLS connections. The files each contain one CA certificate.
+ Directory containing X509 Certification Authority certificates
+ in PEM format which are to be recognized by the client in
+ SSL/TLS connections. The files each contain one CA certificate.
The files are looked up by the CA subject name hash value, which
- must hence be available. If more than one CA certificate with
- the same name hash value exist, the extension must be different
- (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search is performed in
- the ordering of the extension number, regardless of other prop-
- erties of the certificates. Use the c_rehash utility (from the
+ must hence be available. If more than one CA certificate with
+ the same name hash value exist, the extension must be different
+ (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search is performed in
+ the ordering of the extension number, regardless of other prop-
+ erties of the certificates. Use the c_rehash utility (from the
OpenSSL distribution) to create the necessary links.
<b>tls_ca_cert_file (No default; set either this or tls_ca_cert_dir)</b>
File containing the X509 Certification Authority certificates in
- PEM format which are to be recognized by the client in SSL/TLS
+ PEM format which are to be recognized by the client in SSL/TLS
connections. This setting takes precedence over tls_ca_cert_dir.
<b>tls_cert (No default; you must set this)</b>
- File containing client's X509 certificate to be used by the
+ File containing client's X509 certificate to be used by the
client in SSL/ TLS connections.
<b>tls_key (No default; you must set this)</b>
- File containing the private key corresponding to the above
+ File containing the private key corresponding to the above
tls_cert.
<b>tls_require_cert (default: no)</b>
- Whether or not to request server's X509 certificate and check
- its validity when establishing SSL/TLS connections. The sup-
+ Whether or not to request server's X509 certificate and check
+ its validity when establishing SSL/TLS connections. The sup-
ported values are <b>no</b> and <b>yes</b>.
- With <b>no</b>, the server certificate trust chain is not checked, but
- with OpenLDAP prior to 2.1.13, the name in the server certifi-
- cate must still match the LDAP server name. With OpenLDAP 2.0.0
+ With <b>no</b>, the server certificate trust chain is not checked, but
+ with OpenLDAP prior to 2.1.13, the name in the server certifi-
+ cate must still match the LDAP server name. With OpenLDAP 2.0.0
to 2.0.11 the server name is not necessarily what you specified,
- rather it is determined (by reverse lookup) from the IP address
- of the LDAP server connection. With OpenLDAP prior to 2.0.13,
+ rather it is determined (by reverse lookup) from the IP address
+ of the LDAP server connection. With OpenLDAP prior to 2.0.13,
subjectAlternativeName extensions in the LDAP server certificate
- are ignored: the server name must match the subject CommonName.
- The <b>no</b> setting corresponds to the <b>never</b> value of <b>TLS_REQCERT</b> in
+ are ignored: the server name must match the subject CommonName.
+ The <b>no</b> setting corresponds to the <b>never</b> value of <b>TLS_REQCERT</b> in
LDAP client configuration files.
- Don't use TLS with OpenLDAP 2.0.x (and especially with x <= 11)
+ Don't use TLS with OpenLDAP 2.0.x (and especially with x <= 11)
if you can avoid it.
With <b>yes</b>, the server certificate must be issued by a trusted CA,
- and not be expired. The LDAP server name must match one of the
+ and not be expired. The LDAP server name must match one of the
name(s) found in the certificate (see above for OpenLDAP library
- version dependent behavior). The <b>yes</b> setting corresponds to the
- <b>demand</b> value of <b>TLS_REQCERT</b> in LDAP client configuration files.
+ version dependent behavior). The <b>yes</b> setting corresponds to the
+ <b>demand</b> value of <b>TLS_REQCERT</b> in LDAP client configuration files.
- The "try" and "allow" values of <b>TLS_REQCERT</b> have no equivalents
- here. They are not available with OpenLDAP 2.0, and in any case
+ The "try" and "allow" values of <b>TLS_REQCERT</b> have no equivalents
+ here. They are not available with OpenLDAP 2.0, and in any case
have questionable security properties. Either you want TLS veri-
fied LDAP connections, or you don't.
- The <b>yes</b> value only works correctly with Postfix 2.5 and later,
+ The <b>yes</b> value only works correctly with Postfix 2.5 and later,
or with OpenLDAP 2.0. Earlier Postfix releases or later OpenLDAP
releases don't work together with this setting. Support for LDAP
over TLS was added to Postfix based on the OpenLDAP 2.0 API.
<b>tls_random_file (No default)</b>
Path of a file to obtain random bits from when /dev/[u]random is
- not available, to be used by the client in SSL/TLS connections.
+ not available, to be used by the client in SSL/TLS connections.
<b>tls_cipher_suite (No default)</b>
Cipher suite to use in SSL/TLS negotiations.
<b><a name="example">EXAMPLE</a></b>
- Here's a basic example for using LDAP to look up <a href="local.8.html">local(8)</a> aliases.
+ Here's a basic example for using LDAP to look up <a href="local.8.html">local(8)</a> aliases.
Assume that in <a href="postconf.5.html">main.cf</a>, you have:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases,
server_host = ldap.example.com
search_base = dc=example, dc=com
- Upon receiving mail for a local address "ldapuser" that isn't found in
- the /etc/aliases database, Postfix will search the LDAP server listen-
- ing at port 389 on ldap.example.com. It will bind anonymously, search
- for any directory entries whose mailacceptinggeneralid attribute is
- "ldapuser", read the "maildrop" attributes of those found, and build a
- list of their maildrops, which will be treated as <a href="https://tools.ietf.org/html/rfc822">RFC822</a> addresses to
+ Upon receiving mail for a local address "ldapuser" that isn't found in
+ the /etc/aliases database, Postfix will search the LDAP server listen-
+ ing at port 389 on ldap.example.com. It will bind anonymously, search
+ for any directory entries whose mailacceptinggeneralid attribute is
+ "ldapuser", read the "maildrop" attributes of those found, and build a
+ list of their maildrops, which will be treated as <a href="https://tools.ietf.org/html/rfc822">RFC822</a> addresses to
which the message will be delivered.
<b>OBSOLETE MAIN.CF PARAMETERS</b>
- For backwards compatibility with Postfix version 2.0 and earlier, LDAP
- parameters can also be defined in <a href="postconf.5.html">main.cf</a>. Specify as LDAP source a
- name that doesn't begin with a slash or a dot. The LDAP parameters
+ For backwards compatibility with Postfix version 2.0 and earlier, LDAP
+ parameters can also be defined in <a href="postconf.5.html">main.cf</a>. Specify as LDAP source a
+ name that doesn't begin with a slash or a dot. The LDAP parameters
will then be accessible as the name you've given the source in its def-
inition, an underscore, and the name of the parameter. For example, if
- the map is specified as "<a href="ldap_table.5.html">ldap</a>:<i>ldapsource</i>", the "server_host" parameter
+ the map is specified as "<a href="ldap_table.5.html">ldap</a>:<i>ldapsource</i>", the "server_host" parameter
below would be defined in <a href="postconf.5.html">main.cf</a> as "<i>ldapsource</i>_server_host".
Note: with this form, the passwords for the LDAP sources are written in
- <a href="postconf.5.html">main.cf</a>, which is normally world-readable. Support for this form will
+ <a href="postconf.5.html">main.cf</a>, which is normally world-readable. Support for this form will
be removed in a future Postfix version.
<b><a name="other_obsolete_features">OTHER OBSOLETE FEATURES</a></b>
<b>result_filter (No default)</b>
- For backwards compatibility with the pre 2.2 LDAP clients,
+ For backwards compatibility with the pre 2.2 LDAP clients,
<b>result_filter</b> can for now be used instead of <b>result_format</b>, when
- the latter parameter is not also set. The new name better
- reflects the function of the parameter. This compatibility
+ the latter parameter is not also set. The new name better
+ reflects the function of the parameter. This compatibility
interface may be removed in a future release.
<b><a name="see_also">SEE ALSO</a></b>
The Secure Mailer license must be distributed with this software.
<b>AUTHOR(S)</b>
- Carsten Hoeger, Hery Rakotoarisoa, John Hensley, Keith Stevenson, LaM-
- ont Jones, Liviu Daia, Manuel Guesdon, Mike Mattice, Prabhat K Singh,
+ Carsten Hoeger, Hery Rakotoarisoa, John Hensley, Keith Stevenson, LaM-
+ ont Jones, Liviu Daia, Manuel Guesdon, Mike Mattice, Prabhat K Singh,
Sami Haahtinen, Samuel Tardieu, Victor Duchovni, and many others.
LDAP_TABLE(5)
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- Alternatively, lookup tables can be specified as memcache instances.
- To use memcache lookups, define a memcache source as a lookup table in
+ Alternatively, lookup tables can be specified as memcache instances. To
+ use memcache lookups, define a memcache source as a lookup table in
<a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="memcache_table.5.html">memcache</a>:/etc/postfix/memcache-aliases.cf
- The file /etc/postfix/memcache-aliases.cf has the same format as the
+ The file /etc/postfix/memcache-aliases.cf has the same format as the
Postfix <a href="postconf.5.html">main.cf</a> file, and specifies the parameters described below.
- The Postfix memcache client supports the lookup, update, delete and
- sequence (first/next) operations. The sequence operation requires a
+ The Postfix memcache client supports the lookup, update, delete and
+ sequence (first/next) operations. The sequence operation requires a
backup database that supports the operation.
<b><a name="memcache_main_parameters">MEMCACHE MAIN PARAMETERS</a></b>
<b>memcache (default: inet:localhost:11211)</b>
- The memcache server (note: singular) that Postfix will try to
- connect to. For a TCP server specify "inet:" followed by a
+ The memcache server (note: singular) that Postfix will try to
+ connect to. For a TCP server specify "inet:" followed by a
hostname or address, ":", and a port name or number. Specify an
- IPv6 address inside "[]". For a UNIX-domain server specify
+ IPv6 address inside "[]". For a UNIX-domain server specify
"unix:" followed by the socket pathname. Examples:
memcache = inet:memcache.example.com:11211
memcache = inet:[fc00:8d00:189::3]:11211
memcache = unix:/path/to/socket
- NOTE: to access a UNIX-domain socket with the <a href="proxymap.8.html">proxymap(8)</a>
- server, the socket must be accessible by the unprivileged post-
+ NOTE: to access a UNIX-domain socket with the <a href="proxymap.8.html">proxymap(8)</a>
+ server, the socket must be accessible by the unprivileged post-
fix user.
<b>backup (default: undefined)</b>
An optional Postfix database that provides persistent backup for
- the memcache database. The Postfix memcache client will update
- the memcache database whenever it looks up or changes informa-
- tion in the persistent database. Specify a Postfix "<a href="DATABASE_README.html">type:table</a>"
+ the memcache database. The Postfix memcache client will update
+ the memcache database whenever it looks up or changes informa-
+ tion in the persistent database. Specify a Postfix "<a href="DATABASE_README.html">type:table</a>"
database. Examples:
# Non-shared postscreen cache.
Access to remote proxymap servers is under development.
- NOTE 1: When sharing a persistent <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a>
- cache, disable automatic cache cleanup (set
- *_cache_cleanup_interval = 0) except with one Postfix instance
+ NOTE 1: When sharing a persistent <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a>
+ cache, disable automatic cache cleanup (set
+ *_cache_cleanup_interval = 0) except with one Postfix instance
that will be responsible for cache cleanup.
- NOTE 2: When multiple tables share the same memcache database,
- each table should use the <b>key_format</b> feature (see below) to
- prepend its own unique string to the lookup key. Otherwise,
+ NOTE 2: When multiple tables share the same memcache database,
+ each table should use the <b>key_format</b> feature (see below) to
+ prepend its own unique string to the lookup key. Otherwise,
automatic <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache cleanup may not work.
- NOTE 3: When the backup database is accessed with "<a href="proxymap.8.html">proxy</a>:"
- lookups, the full backup database name (including the "<a href="proxymap.8.html">proxy</a>:"
+ NOTE 3: When the backup database is accessed with "<a href="proxymap.8.html">proxy</a>:"
+ lookups, the full backup database name (including the "<a href="proxymap.8.html">proxy</a>:"
prefix) must be specified in the proxymap server's
- <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> or <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> setting (depending on
+ <a href="postconf.5.html#proxy_read_maps">proxy_read_maps</a> or <a href="postconf.5.html#proxy_write_maps">proxy_write_maps</a> setting (depending on
whether the access is read-only or read-write).
<b>flags (default: 0)</b>
- Optional flags that should be stored along with a memcache
+ Optional flags that should be stored along with a memcache
update. The flags are ignored when looking up information.
<b>ttl (default: 3600)</b>
The expiration time in seconds of memcache updates.
- NOTE 1: When using a memcache table as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>ver-</b></a>
- <a href="verify.8.html"><b>ify</b>(8)</a> cache without persistent backup, specify a zero
- *_cache_cleanup_interval value with all Postfix instances that
- use the memcache, and specify the largest <a href="postscreen.8.html"><b>postscreen</b>(8)</a> *_ttl
- value or <a href="verify.8.html"><b>verify</b>(8)</a> *_expire_time value as the memcache table's
+ NOTE 1: When using a memcache table as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>ver-</b></a>
+ <a href="verify.8.html"><b>ify</b>(8)</a> cache without persistent backup, specify a zero
+ *_cache_cleanup_interval value with all Postfix instances that
+ use the memcache, and specify the largest <a href="postscreen.8.html"><b>postscreen</b>(8)</a> *_ttl
+ value or <a href="verify.8.html"><b>verify</b>(8)</a> *_expire_time value as the memcache table's
<b>ttl</b> value.
- NOTE 2: According to memcache protocol documentation, a value
- greater than 30 days (2592000 seconds) specifies absolute UNIX
+ NOTE 2: According to memcache protocol documentation, a value
+ greater than 30 days (2592000 seconds) specifies absolute UNIX
time. Smaller values are relative to the time of the update.
<b><a name="memcache_key_parameters">MEMCACHE KEY PARAMETERS</a></b>
<b>key_digest (default: empty)</b>
- After processing the <b>key_format</b> setting, and before sending a
- request to the memcache server, run the key through the named
- message digest algorithm and convert the result to lowercase
- hexadecimal characters. This prevents a database access error
- when keys may exceed the memcache server's key length limit
+ After processing the <b>key_format</b> setting, and before sending a
+ request to the memcache server, run the key through the named
+ message digest algorithm and convert the result to lowercase
+ hexadecimal characters. This prevents a database access error
+ when keys may exceed the memcache server's key length limit
(usually, 250 bytes). Specify the name of a message digest algo-
rithm that is supported by OpenSSL, for example, <b>sha256</b>.
- This feature is available in Postfix 3.11 and later, and
+ This feature is available in Postfix 3.11 and later, and
requires that Postfix is built with TLS support.
<b>key_format (default: %s)</b>
- Format of the lookup and update keys that the Postfix memcache
- client sends to the memcache server. By default, these are the
- same as the lookup and update keys that the memcache client
+ Format of the lookup and update keys that the Postfix memcache
+ client sends to the memcache server. By default, these are the
+ same as the lookup and update keys that the memcache client
receives from Postfix applications.
- NOTE 1: The <b>key_format</b> feature is not used for <b>backup</b> database
+ NOTE 1: The <b>key_format</b> feature is not used for <b>backup</b> database
requests.
- NOTE 2: When multiple tables share the same memcache database,
- each table should prepend its own unique string to the lookup
- key. Otherwise, automatic <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache
+ NOTE 2: When multiple tables share the same memcache database,
+ each table should prepend its own unique string to the lookup
+ key. Otherwise, automatic <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache
cleanup may not work.
Examples:
<b>%s</b> This is replaced by the memcache client input key.
<b>%u</b> When the input key is an address of the form user@domain,
- <b>%u</b> is replaced by the SQL quoted local part of the
- address. Otherwise, <b>%u</b> is replaced by the entire search
- string. If the localpart is empty, a lookup is silently
- suppressed and returns no results (an update is skipped
+ <b>%u</b> is replaced by the SQL quoted local part of the
+ address. Otherwise, <b>%u</b> is replaced by the entire search
+ string. If the localpart is empty, a lookup is silently
+ suppressed and returns no results (an update is skipped
with a warning).
<b>%d</b> When the input key is an address of the form user@domain,
<b>%d</b> is replaced by the domain part of the address. Other-
- wise, a lookup is silently suppressed and returns no
+ wise, a lookup is silently suppressed and returns no
results (an update is skipped with a warning).
<b>%[SUD]</b> The upper-case equivalents of the above expansions behave
- in the <b>key_format</b> parameter identically to their
+ in the <b>key_format</b> parameter identically to their
lower-case counter-parts.
- <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
- sponding most significant component of the input key's
- domain. If the input key is <i>user@mail.example.com</i>, then
+ <b>%[1-9]</b> The patterns %1, %2, ... %9 are replaced by the corre-
+ sponding most significant component of the input key's
+ domain. If the input key is <i>user@mail.example.com</i>, then
%1 is <b>com</b>, %2 is <b>example</b> and %3 is <b>mail</b>. If the input key
- is unqualified or does not have enough domain components
- to satisfy all the specified patterns, a lookup is
- silently suppressed and returns no results (an update is
+ is unqualified or does not have enough domain components
+ to satisfy all the specified patterns, a lookup is
+ silently suppressed and returns no results (an update is
skipped with a warning).
<b>domain (default: no domain list)</b>
- This feature can significantly reduce database server load.
- Specify a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
- databases. When specified, only fully qualified search keys
- with a *non-empty* localpart and a matching domain are eligible
- for lookup or update: bare 'user' lookups, bare domain lookups
- and "@domain" lookups are silently skipped (updates are skipped
+ This feature can significantly reduce database server load.
+ Specify a list of domain names, paths to files, or "<a href="DATABASE_README.html">type:table</a>"
+ databases. When specified, only fully qualified search keys
+ with a *non-empty* localpart and a matching domain are eligible
+ for lookup or update: bare 'user' lookups, bare domain lookups
+ and "@domain" lookups are silently skipped (updates are skipped
with a warning). Example:
domain = example.com, <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/searchdomains
The maximal memcache reply line length in bytes.
<b>max_try (default: 2)</b>
- The number of times to try a memcache command before giving up.
- The memcache client does not retry a command when the memcache
+ The number of times to try a memcache command before giving up.
+ The memcache client does not retry a command when the memcache
server accepts no connection.
<b>retry_pause (default: 1)</b>
The time in seconds before retrying a failed memcache command.
<b>timeout (default: 2)</b>
- The time limit for sending a memcache command and for receiving
+ The time limit for sending a memcache command and for receiving
a memcache reply.
<b><a name="bugs">BUGS</a></b>
- The Postfix memcache client cannot be used for security-sensitive
+ The Postfix memcache client cannot be used for security-sensitive
tables such as <b><a href="postconf.5.html#alias_maps">alias_maps</a></b> (these may contain "<i>|command</i> and "<i>/file/name</i>"
- destinations), or <b><a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a></b>, <b><a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a></b> and <b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mail</a>-</b>
+ destinations), or <b><a href="postconf.5.html#virtual_uid_maps">virtual_uid_maps</a></b>, <b><a href="postconf.5.html#virtual_gid_maps">virtual_gid_maps</a></b> and <b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mail</a>-</b>
<b><a href="postconf.5.html#virtual_mailbox_maps">box_maps</a></b> (these specify UNIX process privileges for "<i>/file/name</i>" desti-
- nations). In a typical deployment a memcache database is writable by
- any process that can talk to the memcache server; in contrast, secu-
- rity-sensitive tables must never be writable by the unprivileged Post-
+ nations). In a typical deployment a memcache database is writable by
+ any process that can talk to the memcache server; in contrast, secu-
+ rity-sensitive tables must never be writable by the unprivileged Post-
fix user.
The Postfix memcache client requires additional configuration when used
- as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache. For details see the <b>backup</b> and
- <b>ttl</b> parameter discussions in the MEMCACHE MAIN PARAMETERS section
+ as <a href="postscreen.8.html"><b>postscreen</b>(8)</a> or <a href="verify.8.html"><b>verify</b>(8)</a> cache. For details see the <b>backup</b> and
+ <b>ttl</b> parameter discussions in the MEMCACHE MAIN PARAMETERS section
above.
<b><a name="see_also">SEE ALSO</a></b>
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- Alternatively, lookup tables can be specified as MongoDB databases. In
- order to use MongoDB lookups, define a MongoDB source as a lookup table
- in <a href="postconf.5.html">main.cf</a>, for example:
+ Alternatively, lookup tables can be specified as MongoDB databases. To
+ find out what types of lookup tables your Postfix system supports use
+ the "<b>postconf -m</b>" command.
+
+ In order to use MongoDB lookups, define a MongoDB source as a lookup
+ table in <a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="mongodb_table.5.html">mongodb</a>:/etc/postfix/mongodb-aliases.cf
In this example, the file /etc/postfix/mongodb-aliases.cf has the same
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- Alternatively, lookup tables can be specified as MySQL databases. In
- order to use MySQL lookups, define a MySQL source as a lookup table in
- <a href="postconf.5.html">main.cf</a>, for example:
+ Alternatively, lookup tables can be specified as MySQL databases. To
+ find out what types of lookup tables your Postfix system supports use
+ the "<b>postconf -m</b>" command.
+
+ In order to use MySQL lookups, define a MySQL source as a lookup table
+ in <a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="mysql_table.5.html">mysql</a>:/etc/postfix/mysql-aliases.cf
The file /etc/postfix/mysql-aliases.cf has the same format as the Post-
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "https://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+<title> Postfix manual - nbdb_reindexd(8) </title>
+</head> <body> <pre>
+NBDB_REINDEXD(8) NBDB_REINDEXD(8)
+
+<b><a name="name">NAME</a></b>
+ nbdb_reindexd - Postfix non-Berkeley-DB migration
+
+<b><a name="synopsis">SYNOPSIS</a></b>
+ <b>nbdb_reindexd</b> [generic Postfix daemon options]
+
+<b><a name="description">DESCRIPTION</a></b>
+ <i>NOTE: This service should be enabled only temporarily to generate most</i>
+ <i>of the non-Berkeley-DB indexed files that Postfix needs. Leaving this</i>
+ <i>service enabled may expose the system to privilege-escalation attacks.</i>
+
+ The <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> server handles requests to generate a non-Berke-
+ ley-DB indexed database file for an existing Berkeley DB database
+ (example: "<a href="DATABASE_README.html#types">hash</a>:/path/to/file" or "<a href="DATABASE_README.html#types">btree</a>:/path/to/file"). It implements
+ the service by running the <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> command with
+ appropriate privileges.
+
+ The service reports a success status when the non-Berkeley-DB indexed
+ file already exists. This can happen when multiple clients make the
+ same request. When one request is completed successfully, the service
+ also reports success for the other requests.
+
+ This service enforces the following safety policy:
+
+ <b>o</b> The legacy Berkeley DB indexed file must exist (file name ends
+ in ".db"). The <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> service will use the owner"s
+ (uid, gid) of this file, when it runs <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postal-</a>
+ <a href="postalias.1.html">ias(1)</a>. It also uses the (uid,gid) for a number of safety checks
+ as described next.
+
+ <b>o</b> The non-indexed source file must exist (file name without ".db"
+ suffix). This file is needed as input for <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postal-</a>
+ <a href="postalias.1.html">ias(1)</a>. The file must be owned by "root" or by the above uid,
+ and must not allow "group" or "other" write access.
+
+ <b>o</b> The parent directory must be owned by "root" or by the above
+ uid, and it must not allow "group" or "other" write access.
+
+ <b>o</b> Additionally, the "<a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a>" param-
+ eter limits the source file directory prefixes that are allowed
+ when this service needs to run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> with
+ "root" privileges.
+
+ <b>o</b> A similar parameter, "<a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a>",
+ limits the source file directory prefixes that are allowed when
+ this service needs to run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> as an
+ unprivileged user.
+
+<b><a name="security">SECURITY</a></b>
+ The <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> server is security sensitive. It accepts requests
+ only from processes that can access sockets under $<a href="postconf.5.html#queue_directory">queue_directory</a>/pri-
+ vate (i.e., processes that run with "root" or "<a href="postconf.5.html#mail_owner">mail_owner</a>" (usually,
+ postfix) privileges).
+
+ The threat is therefore a corrupted Postfix daemon process that wants
+ to elevate privileges, by sending requests with crafted pathnames, and
+ racing against the service by quickly swapping files or directories,
+ hoping that Postfix will be tricked to overwrite a sensitive file with
+ attacker-controlled data.
+
+ When the service runs <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> as "root", such racing
+ attacks should not be possible if <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a>
+ specifies only prefixes that are already trusted.
+
+ This service could block all requests with crafted pathnames, if given
+ complete information about all lookup tables that are referenced
+ through Postfix configuration files. Unfortunately that information was
+ not available at the time that this program was needed.
+
+<b><a name="diagnostics">DIAGNOSTICS</a></b>
+ Problems and transactions are logged to syslogd(8) or <a href="postlogd.8.html">postlogd(8)</a>. If
+ an attempt to create an index file fails, this service will attempt to
+ delete the incomplete file.
+
+<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
+ Changes to <a href="postconf.5.html">main.cf</a> are not picked up automatically, as <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>
+ processes are long-lived. Use the command "postfix reload" after a con-
+ figuration change.
+
+ The text below provides only a parameter summary. See <a href="postconf.5.html">postconf(5)</a> for
+ more details including examples.
+
+<b><a name="service-specific_controls">SERVICE-SPECIFIC CONTROLS</a></b>
+ <b><a href="postconf.5.html#non_bdb_migration_level">non_bdb_migration_level</a> (disable)</b>
+ The non-Berkeley-DB migration service level.
+
+ <b><a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a> (see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migra</a>-</b>
+ <b><a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">tion_allow_root_prefixes</a>' output)</b>
+ A list of trusted pathname prefixes that must be matched when
+ the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html"><b>nbdb_reindexd</b>(8)</a>) needs
+ to run <a href="postmap.1.html"><b>postmap</b>(1)</a> or <a href="postalias.1.html"><b>postalias</b>(1)</a> commands with "root" privi-
+ lege.
+
+ <b><a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a> (see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migra</a>-</b>
+ <b><a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">tion_allow_user_prefixes</a>' output)</b>
+ A list of trusted pathname prefixes that must be matched when
+ the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html"><b>nbdb_reindexd</b>(8)</a>) needs
+ to run <a href="postmap.1.html"><b>postmap</b>(1)</a> or <a href="postalias.1.html"><b>postalias</b>(1)</a> commands with non-root privi-
+ lege.
+
+<b><a name="miscellaneous_controls">MISCELLANEOUS CONTROLS</a></b>
+ <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ figuration files.
+
+ <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
+ The process ID of a Postfix command or daemon process.
+
+ <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
+ The process name of a Postfix command or daemon process.
+
+ <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
+ The syslog facility of Postfix logging.
+
+ <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
+ A prefix that is prepended to the process name in syslog
+ records, so that, for example, "smtpd" becomes "prefix/smtpd".
+
+ <b><a href="postconf.5.html#service_name">service_name</a> (read-only)</b>
+ The <a href="master.5.html">master.cf</a> service name of a Postfix daemon process.
+
+<b><a name="see_also">SEE ALSO</a></b>
+ <a href="postfix-non-bdb.1.html">postfix-non-bdb(1)</a>, migration management
+ <a href="postconf.5.html">postconf(5)</a>, configuration parameters
+ <a href="postlogd.8.html">postlogd(8)</a>, Postfix logging
+ syslogd(8), system logging
+
+<b><a name="readme_files">README FILES</a></b>
+ <a href="NON_BERKELEYDB_README.html">NON_BERKELEYDB_README</a>, Non-Berkeley-DB migration guide
+
+<b><a name="license">LICENSE</a></b>
+ The Secure Mailer license must be distributed with this software.
+
+<b><a name="history">HISTORY</a></b>
+ This service was introduced with Postfix version 3.11.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ porcupine.org
+
+ NBDB_REINDEXD(8)
+</pre> </body> </html>
<b>postmap -q - "<a href="nisplus_table.5.html">nisplus</a>:[</b><i>name</i><b>=%s];</b><i>name.name.</i><b>"</b> <<i>inputfile</i>
<b><a name="description">DESCRIPTION</a></b>
- The Postfix mail system uses optional lookup tables. These tables are
- usually in <b>dbm</b> or <b>db</b> format. Alternatively, lookup tables can be spec-
- ified as NIS+ databases.
+ The Postfix mail system uses optional lookup tables. rewriting or mail
+ routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b> for-
+ mat.
- To find out what types of lookup tables your Postfix system supports
- use the "<b>postconf -m</b>" command.
+ Alternatively, lookup tables can be specified as NIS+ databases. To
+ find out what types of lookup tables your Postfix system supports use
+ the "<b>postconf -m</b>" command.
- To test Postfix NIS+ lookup tables, use the "<b>postmap -q</b>" command as
+ To test Postfix NIS+ lookup tables, use the "<b>postmap -q</b>" command as
described in the SYNOPSIS above.
<b><a name="query_syntax">QUERY SYNTAX</a></b>
- Most of the NIS+ query is specified via the NIS+ map name. The general
+ Most of the NIS+ query is specified via the NIS+ map name. The general
format of a Postfix NIS+ map name is as follows:
<b><a href="nisplus_table.5.html">nisplus</a>:[</b><i>name</i><b>=%s];</b><i>name.name.name</i><b>.:</b><i>column</i>
- Postfix NIS+ map names differ from what one normally would use with
+ Postfix NIS+ map names differ from what one normally would use with
commands such as <b>niscat</b>:
- <b>o</b> With each NIS+ table lookup, "<b>%s</b>" is replaced by a version of
- the lookup string. There can be only one "<b>%s</b>" instance in a
+ <b>o</b> With each NIS+ table lookup, "<b>%s</b>" is replaced by a version of
+ the lookup string. There can be only one "<b>%s</b>" instance in a
Postfix NIS+ map name.
- <b>o</b> Postfix NIS+ map names use "<b>;</b>" instead of "<b>,</b>", because the lat-
- ter character is special in the Postfix <a href="postconf.5.html">main.cf</a> file. Postfix
- replaces "<b>;</b>" characters in the map name by "<b>,</b>" before making
+ <b>o</b> Postfix NIS+ map names use "<b>;</b>" instead of "<b>,</b>", because the lat-
+ ter character is special in the Postfix <a href="postconf.5.html">main.cf</a> file. Postfix
+ replaces "<b>;</b>" characters in the map name by "<b>,</b>" before making
NIS+ queries.
- <b>o</b> The ":<i>column</i>" part in the NIS+ map name is not part of the
+ <b>o</b> The ":<i>column</i>" part in the NIS+ map name is not part of the
actual NIS+ query. Instead, it specifies the number of the table
- column that provides the lookup result. When no ":<i>column</i>" is
+ column that provides the lookup result. When no ":<i>column</i>" is
specified the first column (1) is used.
<b><a name="example">EXAMPLE</a></b>
<b>postmap -bmq - <a href="pcre_table.5.html">pcre</a>:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
<b><a name="description">DESCRIPTION</a></b>
- The Postfix mail system uses optional tables for address rewriting,
- mail routing, or access control. These tables are usually in <b>dbm</b> or <b>db</b>
+ The Postfix mail system uses optional tables for address rewriting or
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
format.
Alternatively, lookup tables can be specified in Perl Compatible Regu-
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
+
+ Alternatively, lookup tables can be specified as PostgreSQL databases.
+ To find out what types of lookup tables your Postfix system supports
+ use the "<b>postconf -m</b>" command.
- Alternatively, lookup tables can be specified as PostgreSQL databases.
In order to use PostgreSQL lookups, define a PostgreSQL source as a
lookup table in <a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="pgsql_table.5.html">pgsql</a>:/etc/postfix/pgsql-aliases.cf
The database type. To find out what types are supported, use the
"<b>postconf -m</b>" command.
- The <a href="postalias.1.html"><b>postalias</b>(1)</a> command can query any supported file type, but
+ When no <i>file</i><b>_</b><i>type</i> is specified, the software uses the database
+ type specified via the <b><a href="postconf.5.html#default_database_type">default_database_type</a></b> configuration
+ parameter. The default value for this parameter depends on the
+ host environment.
+
+ The <a href="postalias.1.html"><b>postalias</b>(1)</a> command can query any supported file type, but
it can create only the following file types:
- <b>btree</b> The output is a btree file, named <i>file</i><b>_</b><i>name</i><b>.db</b>. This is
+ <b>btree</b> The output is a btree file, named <i>file</i><b>_</b><i>name</i><b>.db</b>. This is
available on systems with support for <b>db</b> databases.
- <b>cdb</b> The output is one file named <i>file</i><b>_</b><i>name</i><b>.cdb</b>. This is
+ <b>cdb</b> The output is one file named <i>file</i><b>_</b><i>name</i><b>.cdb</b>. This is
available on systems with support for <b>cdb</b> databases.
<b>dbm</b> The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
<i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>dbm</b> databases.
- <b>fail</b> A table that reliably fails all requests. The lookup ta-
- ble name is used for logging only. This table exists to
+ <b>fail</b> A table that reliably fails all requests. The lookup ta-
+ ble name is used for logging only. This table exists to
simplify Postfix error tests.
<b>hash</b> The output is a hashed file, named <i>file</i><b>_</b><i>name</i><b>.db</b>. This is
available on systems with support for <b>db</b> databases.
- <b>lmdb</b> The output is a btree-based file, named <i>file</i><b>_</b><i>name</i><b>.lmdb</b>.
- <b>lmdb</b> supports concurrent writes and reads from different
+ <b>lmdb</b> The output is a btree-based file, named <i>file</i><b>_</b><i>name</i><b>.lmdb</b>.
+ <b>lmdb</b> supports concurrent writes and reads from different
processes, unlike other supported file-based tables.
- This is available on systems with support for <b>lmdb</b> data-
+ This is available on systems with support for <b>lmdb</b> data-
bases.
<b>sdbm</b> The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
<i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>sdbm</b> databases.
- When no <i>file</i><b>_</b><i>type</i> is specified, the software uses the database
- type specified via the <b><a href="postconf.5.html#default_database_type">default_database_type</a></b> configuration
- parameter. The default value for this parameter depends on the
- host environment.
-
<i>file</i><b>_</b><i>name</i>
The name of the alias database source file when creating a data-
base.
<script type="text/javascript">
-// Kludge for <a href="https://support.google.com/chrome/thread/11993079">https://support.google.com/chrome/thread/11993079</a>
+// See support.google.com/chrome/thread/11993079
const isChrome = /Chrome/.test(navigator.userAgent)
&& /Google Inc/.test(navigator.vendor);
const hash = window.location.hash;
<pre>
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = $<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>:$<a href="postconf.5.html#data_directory">data_directory</a>/verify_cache
-<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">hash</a>:/var/lib/postfix/verify_cache
+<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="lmdb_table.5.html">lmdb</a>:/var/lib/postfix/verify_cache
<a href="postconf.5.html#address_verify_map">address_verify_map</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/verify_cache
</pre>
</p>
<pre>
-<a href="postconf.5.html#alias_database">alias_database</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases
-<a href="postconf.5.html#alias_database">alias_database</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/mail/aliases
+<a href="postconf.5.html#alias_database">alias_database</a> = $<a href="postconf.5.html#default_database_type">default_database_type</a>:/etc/aliases
+<a href="postconf.5.html#alias_database">alias_database</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/aliases
+<a href="postconf.5.html#alias_database">alias_database</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/mail/aliases
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
</DD>
database.
</p>
-<p>
-If you change the alias database, run "<b>postalias /etc/aliases</b>"
-(or wherever your system stores the mail alias file), or simply
-run "<b>newaliases</b>" to build the necessary DBM or DB file.
-</p>
-
<p>
The <a href="local.8.html">local(8)</a> delivery agent disallows regular expression substitution
of $1 etc. in <a href="postconf.5.html#alias_maps">alias_maps</a>, because that would open a security hole.
</p>
<pre>
-<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases, nis:mail.aliases
-<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/aliases
+<a href="postconf.5.html#alias_maps">alias_maps</a> = $<a href="postconf.5.html#default_database_type">default_database_type</a>:/etc/aliases, nis:mail.aliases
+<a href="postconf.5.html#alias_maps">alias_maps</a> = $<a href="postconf.5.html#default_database_type">default_database_type</a>:/etc/aliases
+<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/mail/aliases
+<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/aliases
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postalias <i>/path/to/aliases</i>" after you
+change the aliases file, to (re)build a default-type indexed file.
+Execute "postalias <i>type:/path/to/aliases</i>" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
Note: these lookups are recursive.
</p>
-<p>
-If you use this feature, run "<b>postmap /etc/postfix/canonical</b>" to
-build the necessary DBM or DB file after every change. The changes
-will become visible after a minute or so. Use "<b>postfix reload</b>"
-to eliminate the delay.
-</p>
-
<p> Note: with Postfix version 2.2, message header address mapping
happens only when message header address rewriting is enabled: </p>
</p>
<pre>
-<a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="DATABASE_README.html#types">dbm</a>:/etc/postfix/canonical
-<a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/canonical
+<a href="postconf.5.html#canonical_maps">canonical_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/canonical
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/canonical" after you
+change the canonical file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/canonical" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
<p>
The default database type for use in <a href="newaliases.1.html">newaliases(1)</a>, <a href="postalias.1.html">postalias(1)</a>
and <a href="postmap.1.html">postmap(1)</a> commands. On many UNIX systems the default type is
-either <b>dbm</b> or <b>hash</b>. The default setting is frozen
+either <b>lmdb</b> or <b>hash</b>. The default setting is frozen
when the Postfix system is built.
</p>
</p>
<pre>
+<a href="postconf.5.html#default_database_type">default_database_type</a> = lmdb
<a href="postconf.5.html#default_database_type">default_database_type</a> = hash
-<a href="postconf.5.html#default_database_type">default_database_type</a> = dbm
</pre>
<pre>
<a href="postconf.5.html#local_header_rewrite_clients">local_header_rewrite_clients</a> = <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
<a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> <a href="postconf.5.html#permit_tls_clientcerts">permit_tls_clientcerts</a>
- <a href="postconf.5.html#check_address_map">check_address_map</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/pop-before-smtp
+ <a href="postconf.5.html#check_address_map">check_address_map</a> <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/pop-before-smtp
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
</DD>
<a href="postconf.5.html#mynetworks">mynetworks</a> = !192.168.0.1, 192.168.0.0/28
<a href="postconf.5.html#mynetworks">mynetworks</a> = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:587::]/64
<a href="postconf.5.html#mynetworks">mynetworks</a> = $<a href="postconf.5.html#config_directory">config_directory</a>/mynetworks
-<a href="postconf.5.html#mynetworks">mynetworks</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/network_table
+<a href="postconf.5.html#mynetworks">mynetworks</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/network_table
<a href="postconf.5.html#mynetworks">mynetworks</a> = <a href="cidr_table.5.html">cidr</a>:/etc/postfix/network_table.cidr
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
</p>
+</DD>
+
+<DT><b><a name="non_bdb_custom_mapping">non_bdb_custom_mapping</a>
+(default: empty)</b></DT><DD>
+
+<p> When non-Berkeley-DB migration is enabled, an optional mapping
+from a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: type to a non-Berkeley-DB type. This mapping
+takes precedence over the default mapping from <a href="DATABASE_README.html#types">hash</a>: to
+$<a href="postconf.5.html#default_database_type">default_database_type</a>, and from <a href="DATABASE_README.html#types">btree</a>: to $<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>.
+</p>
+
+<ul>
+
+<li> <p> Specify a lookup table with a search keys that are a
+Berkeley DB <i>type</i> (without ':') or <i>type:name</i>. </p>
+
+<li> <p> A search key with the form <i>type:name</i> takes precedence
+over <i>type</i> (without ':'). </p>
+
+<li> <p> The lookup result must always be a non-Berkeley-DB <i>type</i>
+(without ':') and must not contain a <i>:name</i>. </p>
+
+<li> <p> The mapping table type must not be <b>hash</b> or <b>btree</b>.
+
+</ul>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+
+</DD>
+
+<DT><b><a name="non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a>
+(default: see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a>' output)</b></DT><DD>
+
+<p> A list of trusted pathname prefixes that must be matched when
+the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>) needs to
+run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> commands with "root" privilege.
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+
+</DD>
+
+<DT><b><a name="non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a>
+(default: see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a>' output)</b></DT><DD>
+
+<p> A list of trusted pathname prefixes that must be matched when
+the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>) needs to
+run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a> commands with non-root privilege. </p>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+
+</DD>
+
+<DT><b><a name="non_bdb_migration_level">non_bdb_migration_level</a>
+(default: disable)</b></DT><DD>
+
+<p> The non-Berkeley-DB migration service level. You are expected to use
+the command "<b><a href="postfix-non-bdb.1.html">postfix non-bdb</a> <i>name-of-level</i></b>" to correctly
+configure the migration service level (see <a href="postfix-non-bdb.1.html">postfix-non-bdb(1)</a>. </p>
+
+<dl>
+
+<dt><b>disable</b></dt>
+
+<dd> <p> Disable all non-Berkeley-DB migration features. See
+<a href="NON_BERKELEYDB_README.html#disable">NON_BERKELEYDB_README</a> for possible negative implications
+for integration with other software such as mailman. </p> </dd>
+
+<dt><b>enable-redirect</b> (aliasing)</dt>
+
+<dd> <p> Enable redirection (aliasing) from Berkeley DB hash to
+$<a href="postconf.5.html#default_database_type">default_database_type</a>, and from Berkeley DB btree to
+$<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>, but do not automatically create the new cdb
+or lmdb indexed database files that Postfix programs need. See
+<a href="NON_BERKELEYDB_README.html#enable-redirect">NON_BERKELEYDB_README</a> for details and limitations.
+</p> </dd>
+
+<dt><b>enable-reindex</b></dt>
+
+<dd> <p> In addition to enable-redirect, also create a non-Berkeley-DB
+indexed database file when a daemon program wants to access a file
+that does not yet exist. This feature uses the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>
+daemon to run <a href="postmap.1.html">postmap(1)</a> or <a href="postalias.1.html">postalias(1)</a>. See
+<a href="NON_BERKELEYDB_README.html#enable-reindex">NON_BERKELEYDB_README</a> for details and limitations.
+</p>
+
+<p> <i> NOTE: <b>enable-reindex</b> should be used only temporarily to
+generate most of the non-Berkeley-DB indexed database files that Postfix
+programs need. Leaving this level enabled may expose the system to
+privilege-escalation attacks. There are no security concerns for using
+<b>enable-redirect</b>. </i> </p> </dd>
+
+</dl>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+
+</DD>
+
+<DT><b><a name="non_bdb_migration_service_name">non_bdb_migration_service_name</a>
+(default: nbdb_reindex)</b></DT><DD>
+
+<p> The name of a <a href="master.5.html">master.cf</a> service that implements the non-Berkeley-DB
+migration service protocol. </p>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+
</DD>
<DT><b><a name="non_empty_end_of_header_action">non_empty_end_of_header_action</a>
</pre>
</dd>
-<dl>
+</dl>
<p> This feature is available in Postfix ≥ 3.11. </p>
<p> Persistent storage for the <a href="postscreen.8.html">postscreen(8)</a> server decisions. </p>
<p> To share a <a href="postscreen.8.html">postscreen(8)</a> cache between multiple <a href="postscreen.8.html">postscreen(8)</a>
-instances, use "<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">btree</a>:/path/to/file"
-or "<a href="proxymap.8.html">proxy</a>:<a href="lmdb_table.5.html">lmdb</a>:/path/to/file".
+instances, use "<a href="postconf.5.html#postscreen_cache_map">postscreen_cache_map</a> = <a href="proxymap.8.html">proxy</a>:<a href="lmdb_table.5.html">lmdb</a>:/path/to/file"
+or "<a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">btree</a>:/path/to/file".
This requires Postfix version 2.9 or later; earlier <a href="proxymap.8.html">proxymap(8)</a>
implementations don't support cache cleanup. For an alternative
approach see the <a href="memcache_table.5.html">memcache_table(5)</a> manpage. </p>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#rbl_reply_maps">rbl_reply_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/rbl_reply
+ <a href="postconf.5.html#rbl_reply_maps">rbl_reply_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/rbl_reply
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,
<a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a> <i>secret</i>.zen.dq.spamhaus.net=127.0.0.[2..11],
554 $rbl_class $rbl_what blocked using ZEN - see <a href="https://www.spamhaus.org/query/ip/$client_address">https://www.spamhaus.org/query/ip/$client_address</a> for details
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p>
NOTE: This feature differs from <a href="postconf.5.html#postscreen_dnsbl_reply_map">postscreen_dnsbl_reply_map</a> where
the table search key is only a domain name (no "<i>=address-filter</i>",
should be only a domain name (no free text, no <i>$name</i> variables).
</p>
+<p> Execute the command "postmap /etc/postfix/rbl_reply" after you
+change the rbl_reply file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/rbl_reply" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>
This feature is available in Postfix 2.0 and later.
The "=address-filter" feature is available in Postfix 2.8 and later.
</p>
<pre>
-<a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/recipient_bcc
+<a href="postconf.5.html#recipient_bcc_maps">recipient_bcc_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/recipient_bcc
</pre>
-<p>
-After a change, run "<b>postmap /etc/postfix/recipient_bcc</b>".
-</p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/recipient_bcc" after
+you change the recipient_bcc file, to (re)build a default-type indexed
+file. Execute "postmap <i>type</i>:/etc/postfix/recipient_bcc" to
+specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
<p>
This feature is available in Postfix 2.1 and later.
</p>
<pre>
-<a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/recipient_canonical
+<a href="postconf.5.html#recipient_canonical_maps">recipient_canonical_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/recipient_canonical
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/recipient_canonical"
+after you change the recipient_canonical file, to (re)build a
+default-type indexed file. Execute "postmap
+<i>type</i>:/etc/postfix/recipient_canonical" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
<p> Example: </p>
<pre>
-<a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relay_clientcerts
+<a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relay_clientcerts
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p>For more fine-grained control, use <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> to select
an appropriate <a href="access.5.html">access(5)</a> policy for each client.
See <a href="RESTRICTION_CLASS_README.html">RESTRICTION_CLASS_README</a>.</p>
+<p> Execute the command "postmap /etc/postfix/relay_clientcerts"
+after you change the <a href="postconf.5.html#relay_clientcerts">relay_clientcerts</a> file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/relay_clientcerts"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>This feature is available with Postfix version 2.2.</p>
</p>
<pre>
-<a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relay_recipients
+<a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relay_recipients
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relay_recipients"
+after you change the relay_recipients file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/relay_recipients"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>
This feature is available in Postfix 2.0 and later.
</p>
until a match is found.
</p>
-<p>
-If you use this feature, run "<b>postmap /etc/postfix/relocated</b>" to
-build the necessary DBM or DB file after change, then "<b>postfix
-reload</b>" to make the changes visible.
-</p>
-
<p>
Examples:
</p>
<pre>
-<a href="postconf.5.html#relocated_maps">relocated_maps</a> = <a href="DATABASE_README.html#types">dbm</a>:/etc/postfix/relocated
-<a href="postconf.5.html#relocated_maps">relocated_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relocated
+<a href="postconf.5.html#relocated_maps">relocated_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relocated
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/relocated" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#relocated_maps">relocated_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relocated
+ <a href="postconf.5.html#relocated_maps">relocated_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/relocated
<a href="postconf.5.html#relocated_prefix_enable">relocated_prefix_enable</a> = no
<br>
-<a href="DATABASE_README.html#types">hash</a>:/etc/postfix/relocated:
+/etc/postfix/relocated:
user@example.com 5.2.1 User account is disabled
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/relocated" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
+<p> This feature is available in Postfix 3.11 and later. </p>
+
</DD>
</p>
<pre>
-<a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_bcc
+<a href="postconf.5.html#sender_bcc_maps">sender_bcc_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sender_bcc
</pre>
-<p>
-After a change, run "<b>postmap /etc/postfix/sender_bcc</b>".
-</p>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/sender_bcc" after you
+change the sender_bcc file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/sender_bcc" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
<p>
This feature is available in Postfix 2.1 and later.
</p>
<pre>
-<a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/sender_canonical
+<a href="postconf.5.html#sender_canonical_maps">sender_canonical_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/sender_canonical
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/sender_canonical"
+after you change the sender_canonical file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/sender_canonical"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
+ <a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
</pre>
</blockquote>
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> Unselective use of the "data" target does no harm, but will
result in unnecessary "lost connection after DATA" events at remote
SMTP/LMTP servers. </p>
+<p> Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/transport" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 3.0 and later. </p>
(Punycode) before making a policy query; lookup tables must answer
ASCII-form queries. </p>
-<li> <p> A fixed-string table (such as <a href="DATABASE_README.html#types">hash</a>:, <a href="DATABASE_README.html#types">btree</a>:, or <a href="lmdb_table.5.html">lmdb</a>:) is
+<li> <p> A fixed-string table (such as <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, or <a href="DATABASE_README.html#types">hash</a>:) is
also searched with the next-hop ".parent" domains (in a table key,
prepend a '.' to a parent domain name). These ".parent" domain
queries are not made with pattern-based lookup tables such as <a href="regexp_table.5.html">regexp</a>:
<li> <p> To match any name below the domain "example.com" specify
a table entry with the storage key ".example.com" in <a href="DATABASE_README.html">type:table</a>
lookup tables that need an exact match. This is appropriate, for
-example, with <a href="DATABASE_README.html#types">hash</a>:, <a href="DATABASE_README.html#types">btree</a>: or <a href="lmdb_table.5.html">lmdb</a>:. </p>
+example, with <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>: or <a href="DATABASE_README.html#types">hash</a>:. </p>
<li> <p> Do not specify a match pattern for ".domain" with <a href="regexp_table.5.html">regexp</a>:,
<a href="pcre_table.5.html">pcre</a>:, <a href="socketmap_table.html">socketmap</a>:, or <a href="tcp_table.5.html">tcp</a>:, as <a href="postconf.5.html#smtp_requiretls_policy">smtp_requiretls_policy</a> will
<a href="cidr_table.5.html">cidr</a>:{
{ 0.0.0.0/0 opportunistic },
{ ::/0 opportunistic } },
- <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/requiretls-per-site
+ <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/requiretls-per-site
opportunistic+starttls
</pre>
<pre>
...
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/requiretls-per-site"
+after you change the requiretls-per-site file, to (re)build a
+default-type indexed file. Execute "postmap
+<i>type</i>:/etc/postfix/requiretls-per-site" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</ul>
<p>
<p> Examples: </p>
<pre>
-<a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> = <a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/sasl_auth_cache
<a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> = <a href="proxymap.8.html">proxy</a>:<a href="lmdb_table.5.html">lmdb</a>:/var/lib/postfix/sasl_auth_cache
+<a href="postconf.5.html#smtp_sasl_auth_cache_name">smtp_sasl_auth_cache_name</a> = <a href="proxymap.8.html">proxy</a>:<a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/sasl_auth_cache
</pre>
<p> This feature is available in Postfix 2.5 and later. </p>
<blockquote>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/tls_policy
+ <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/tls_policy
<a href="postconf.5.html#smtp_tls_fingerprint_digest">smtp_tls_fingerprint_digest</a> = sha256
</pre>
</blockquote>
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/tls_policy" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.5 and later. </p>
<pre>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
- <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/tls_policy
+ <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/tls_policy
# Postfix 2.5 and later.
#
# The default digest is sha256 with Postfix ≥ 3.6 and
match=51:e9:af:2e:1e:40:1f:...:64:0a:30:35:2d:09:16:31:5a:eb:82:76
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
<p> <b>Note:</b> The "hostname" strategy if listed in a non-default
setting of <a href="postconf.5.html#smtp_tls_secure_cert_match">smtp_tls_secure_cert_match</a> or in the "match" attribute
in the policy table can render the "secure" level vulnerable to
DNS forgery. Do not use the "hostname" strategy for secure-channel
configurations in environments where DNS security is not assured. </p>
+<p> Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/tls_policy" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
<p> Name of the file containing the optional Postfix SMTP client
TLS session cache. Specify a database type that supports enumeration,
-such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+such as <b>lmdb</b> or <b>btree</b>; there is no need to support
concurrent access. The file is created if it does not exist. The <a href="smtp.8.html">smtp(8)</a>
daemon does not use this parameter directly, rather the cache is
implemented indirectly in the <a href="tlsmgr.8.html">tlsmgr(8)</a> daemon. This means that
<p> Example: </p>
<pre>
-<a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/smtp_scache
<a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = <a href="lmdb_table.5.html">lmdb</a>:/var/lib/postfix/smtp_scache
+<a href="postconf.5.html#smtp_tls_session_cache_database">smtp_tls_session_cache_database</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/smtp_scache
</pre>
<p> This feature is available in Postfix 2.2 and later. </p>
<pre>
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> = <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>
<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> = <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>,
- <a href="postconf.5.html#check_sender_access">check_sender_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/access
+ <a href="postconf.5.html#check_sender_access">check_sender_access</a> <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/access
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/access" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#smtpd_tls_fingerprint_digest">smtpd_tls_fingerprint_digest</a> = sha256
<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> =
- <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/access,
+ <a href="postconf.5.html#check_ccert_access">check_ccert_access</a> <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/access,
reject
</pre>
<pre>
</pre>
</blockquote>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/access" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.5 and later. </p>
<p> Examples: </p>
<pre>
-<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/smtpd_scache
<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = <a href="lmdb_table.5.html">lmdb</a>:/var/lib/postfix/smtpd_scache
+<a href="postconf.5.html#smtpd_tls_session_cache_database">smtpd_tls_session_cache_database</a> = <a href="DATABASE_README.html#types">btree</a>:/var/lib/postfix/smtpd_scache
</pre>
<p> This feature is available in Postfix 2.2 and later. </p>
<p>
Specify zero or more "<a href="DATABASE_README.html">type:table</a>" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
-until a match is found. If you use this
-feature with local files, run "<b>postmap /etc/postfix/transport</b>"
-after making a change. </p>
+until a match is found. </p>
<p> Pattern matching of domain names is controlled by the presence
or absence of "<a href="postconf.5.html#transport_maps">transport_maps</a>" in the <a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a>
</p>
<pre>
-<a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">dbm</a>:/etc/postfix/transport
-<a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/transport
+<a href="postconf.5.html#transport_maps">transport_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/transport
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/transport" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
Note: these lookups are recursive.
</p>
-<p>
-If you use this feature with indexed files, run "<b>postmap
-/etc/postfix/virtual</b>" after changing the file.
-</p>
-
<p>
Examples:
</p>
<pre>
-<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">dbm</a>:/etc/postfix/virtual
-<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
+<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="lmdb_table.5.html">lmdb</a>:/etc/postfix/virtual
</pre>
+<p> Instead of <a href="lmdb_table.5.html">lmdb</a>:, some systems use <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>:. </p>
+
+<p> Execute the command "postmap /etc/postfix/virtual" after you
+change the virtual file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/virtual" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+<a href="postconf.5.html#default_database_type">default_database_type</a> parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</DD>
<li> <a href="postfix.1.html">postfix(1)</a>, Postfix control program
+<li> <a href="postfix-non-bdb.1.html">postfix-non-bdb(1)</a>, Postfix Non-Berkeley-DB migration
+
<li> <a href="postfix-tls.1.html">postfix-tls(1)</a>, Postfix TLS management
<li> <a href="postkick.1.html">postkick(1)</a>, trigger Postfix daemon
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "https://www.w3.org/TR/html4/loose.dtd">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+<title> Postfix manual - postfix-non-bdb(1) </title>
+</head> <body> <pre>
+POSTFIX-NON-BDB(1) POSTFIX-NON-BDB(1)
+
+<b><a name="name">NAME</a></b>
+ postfix-non-bdb - Postfix non-Berkeley-DB migration
+
+<b><a name="synopsis">SYNOPSIS</a></b>
+ <b><a href="postfix-non-bdb.1.html">postfix non-bdb</a></b> <i>subcommand</i>
+
+<b><a name="description">DESCRIPTION</a></b>
+ The "<b>postfix non-bdb</b> <i>subcommand</i>" feature edits <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a>,
+ to manage the migration of an existing Postfix configuration that uses
+ Berkeley DB type "<a href="DATABASE_README.html#types">hash</a>:" or "<a href="DATABASE_README.html#types">btree</a>:" tables (which are no longer sup-
+ ported on some OS distributions), to supported types such as "<a href="CDB_README.html">cdb</a>:" or
+ "<a href="lmdb_table.5.html">lmdb</a>:".
+
+ The following subcommands are available:
+
+ <b>status</b> Reports the non-Berkeley-DB migration status, without making any
+ changes.
+
+ <b>disable</b>
+ Edits <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a>, to turn off the <b>enable-redirect</b> and
+ <b>enable-reindex</b> features.
+
+ This will break integration with other software such as mailman
+ versions from before May 2025 when they want to use "postmap
+ <a href="DATABASE_README.html#types">hash</a>:/path/to/file", for example, to update a mailman-maintained
+ table.
+
+ <b>enable-redirect</b> (aliasing)
+ Edits <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a>, to enable redirection (aliasing)
+ from Berkeley DB types "hash" and "btree" to the non-Berkeley-DB
+ types specified with $<a href="postconf.5.html#default_database_type">default_database_type</a> and
+ $<a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a>. Custom redirection may be configured
+ with <a href="postconf.5.html#non_bdb_custom_mapping">non_bdb_custom_mapping</a>.
+
+ This configuration will not automatically create non-Berkeley-DB
+ indexed database files. Instead, Postfix programs will log an
+ error as they fail to open an indexed database file, and will
+ leave it to the system administrator to run <a href="postmap.1.html">postmap(1)</a> or
+ <a href="postalias.1.html">postalias(1)</a> to create that file.
+
+ This will fix integration with other software such as mailman
+ versions from before May 2025 when they want to use "postmap
+ <a href="DATABASE_README.html#types">hash</a>:/path/to/file", for example, to update a mailman-maintained
+ table.
+
+ This subcommand will not make any changes when <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> or <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> specify a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>:
+ type.
+
+ <b>enable-reindex</b>
+ Edits <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a>, to implement <b>enable-redirect</b>, and
+ to automatically create a non-Berkeley-DB indexed database file
+ when a daemon program wants to access a file that does not yet
+ exist. This uses the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> daemon to run <a href="postmap.1.html">postmap(1)</a>
+ or <a href="postalias.1.html">postalias(1)</a> as described in "SECURITY" below.
+
+ This subcommand immediately generates non-Berkeley-DB indexed
+ files for unprivileged command-line programs that cannot send
+ requests to the <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> daemon server. This involves
+ "<a href="DATABASE_README.html#types">hash</a>:" and "<a href="DATABASE_README.html#types">btree</a>:" tables that are used by <a href="postqueue.1.html">postqueue(1)</a> and
+ <a href="sendmail.1.html">sendmail(1)</a> as specified in <a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> and <a href="postconf.5.html#authorized_mailq_users">autho</a>-
+ <a href="postconf.5.html#authorized_mailq_users">rized_mailq_users</a>, and by <a href="sendmail.1.html">sendmail(1)</a> and <a href="postdrop.1.html">postdrop(1)</a> as speci-
+ fied in <a href="postconf.5.html#authorized_submit_users">authorized_submit_users</a> and <a href="postconf.5.html#local_login_sender_maps">local_login_sender_maps</a>.
+
+ This subcommand will not make any changes when <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> or <a href="postconf.5.html#default_cache_db_type">default_cache_db_type</a> specify a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>:
+ type.
+
+ <i>NOTE:</i> <b>enable-reindex</b> <i>should be used only temporarily to generate</i>
+ <i>most of the non-Berkeley-DB indexed files that Postfix needs.</i>
+ <i>Leaving this enabled may expose the system to privilege-escala-</i>
+ <i>tion attacks. There are no security concerns for using</i>
+ <b>enable-redirect</b>.
+
+<b><a name="security">SECURITY</a></b>
+ The <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> daemon automatically generates a non-Berkeley-DB
+ indexed file only if the database pathname matches the directory pre-
+ fixes specified with <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a> (for files
+ that must be owned by root), or with <a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_pre</a>-
+ <a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">fixes</a> (for files that must be owned by a non-root user). Additional
+ restrictions on file and directory ownership and permissions are docu-
+ mented in <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a>.
+
+<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
+ The "<b><a href="postfix-non-bdb.1.html">postfix non-bdb</a></b> <i>subcommand</i>" feature updates the following configu-
+ ration parameter:
+
+ <b><a href="postconf.5.html#non_bdb_migration_level">non_bdb_migration_level</a> (disable)</b>
+ The non-Berkeley-DB migration service level.
+
+ Other relevant parameters:
+
+ <b><a href="postconf.5.html#non_bdb_custom_mapping">non_bdb_custom_mapping</a> (empty)</b>
+ When non-Berkeley-DB migration is enabled, an optional mapping
+ from a <a href="DATABASE_README.html#types">hash</a>: or <a href="DATABASE_README.html#types">btree</a>: type to a non-Berkeley-DB type.
+
+ <b><a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migration_allow_root_prefixes</a> (see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">non_bdb_migra</a>-</b>
+ <b><a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">tion_allow_root_prefixes</a>' output)</b>
+ A list of trusted pathname prefixes that must be matched when
+ the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html"><b>nbdb_reindexd</b>(8)</a>) needs
+ to run <a href="postmap.1.html"><b>postmap</b>(1)</a> or <a href="postalias.1.html"><b>postalias</b>(1)</a> commands with "root" privi-
+ lege.
+
+ <b><a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migration_allow_user_prefixes</a> (see 'postconf -d <a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">non_bdb_migra</a>-</b>
+ <b><a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">tion_allow_user_prefixes</a>' output)</b>
+ A list of trusted pathname prefixes that must be matched when
+ the non-Berkeley-DB migration service (<a href="nbdb_reindexd.8.html"><b>nbdb_reindexd</b>(8)</a>) needs
+ to run <a href="postmap.1.html"><b>postmap</b>(1)</a> or <a href="postalias.1.html"><b>postalias</b>(1)</a> commands with non-root privi-
+ lege.
+
+<b><a name="see_also">SEE ALSO</a></b>
+ <a href="nbdb_reindexd.8.html">nbdb_reindexd(8)</a> reindexing service
+
+<b><a name="readme_files">README FILES</a></b>
+ <a href="NON_BERKELEYDB_README.html">NON_BERKELEYDB_README</a>, migration guide
+
+<b><a name="license">LICENSE</a></b>
+ The Secure Mailer license must be distributed with this software.
+
+<b><a name="history">HISTORY</a></b>
+ The "<b><a href="postfix-non-bdb.1.html">postfix non-bdb</a></b>" command was introduced with Postfix version 3.11.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ porcupine.org
+
+ POSTFIX-NON-BDB(1)
+</pre> </body> </html>
command specified with $<a href="postconf.5.html#maillog_file_compressor">maillog_file_compressor</a>. This will not
rotate /dev/* files.
- This feature is available in Postfix 3.4 and later.
+ <b>non-bdb</b> <i>subcommand</i>
+ Migrate a Postfix configuration that uses Berkeley DB <a href="DATABASE_README.html#types">hash</a>: or
+ <a href="DATABASE_README.html#types">btree</a>: tables, to a configuration that uses <a href="lmdb_table.5.html">lmdb</a>: or a combina-
+ tion of <a href="CDB_README.html">cdb</a>: and <a href="lmdb_table.5.html">lmdb</a>:. This is needed because some (Linux) dis-
+ tributions have removed Berkeley DB support. See post-
+ fix-nbdb(1) for documentation.
+
+ This feature is available in Postfix 3.11 and later.
<b>tls</b> <i>subcommand</i>
Enable opportunistic TLS in the Postfix SMTP client or server,
<a href="postconf.1.html">postconf(1)</a>, Postfix configuration utility
<a href="postdrop.1.html">postdrop(1)</a>, Postfix mail posting utility
<a href="postfix.1.html">postfix(1)</a>, Postfix control program
+ <a href="postfix-non-bdb.1.html">postfix-non-bdb(1)</a>, Postfix Non-Berkeley-DB migration
<a href="postfix-tls.1.html">postfix-tls(1)</a>, Postfix TLS management
<a href="postkick.1.html">postkick(1)</a>, trigger Postfix daemon
<a href="postlock.1.html">postlock(1)</a>, Postfix-compatible locking
The database type. To find out what types are supported, use the
"<b>postconf -m</b>" command.
+ When no <i>file</i><b>_</b><i>type</i> is specified, the software uses the database
+ type specified via the <b><a href="postconf.5.html#default_database_type">default_database_type</a></b> configuration
+ parameter. The default value for this parameter depends on the
+ host environment.
+
The <a href="postmap.1.html"><b>postmap</b>(1)</a> command can query any supported file type, but it
can create only the following file types:
- <b>btree</b> The output file is a btree file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
- This is available on systems with support for <b>db</b> data-
+ <b>btree</b> The output file is a btree file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
+ This is available on systems with support for <b>db</b> data-
bases.
- <b>cdb</b> The output consists of one file, named <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
- This is available on systems with support for <b>cdb</b> data-
+ <b>cdb</b> The output consists of one file, named <i>file</i><b>_</b><i>name</i><b>.cdb</b>.
+ This is available on systems with support for <b>cdb</b> data-
bases.
<b>dbm</b> The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
<i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>dbm</b> databases.
- <b>fail</b> A table that reliably fails all requests. The lookup ta-
- ble name is used for logging only. This table exists to
+ <b>fail</b> A table that reliably fails all requests. The lookup ta-
+ ble name is used for logging only. This table exists to
simplify Postfix error tests.
- <b>hash</b> The output file is a hashed file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
- This is available on systems with support for <b>db</b> data-
+ <b>hash</b> The output file is a hashed file, named <i>file</i><b>_</b><i>name</i><b>.db</b>.
+ This is available on systems with support for <b>db</b> data-
bases.
- <b>lmdb</b> The output is a btree-based file, named <i>file</i><b>_</b><i>name</i><b>.lmdb</b>.
- <b>lmdb</b> supports concurrent writes and reads from different
+ <b>lmdb</b> The output is a btree-based file, named <i>file</i><b>_</b><i>name</i><b>.lmdb</b>.
+ <b>lmdb</b> supports concurrent writes and reads from different
processes, unlike other supported file-based tables.
- This is available on systems with support for <b>lmdb</b> data-
+ This is available on systems with support for <b>lmdb</b> data-
bases.
<b>sdbm</b> The output consists of two files, named <i>file</i><b>_</b><i>name</i><b>.pag</b> and
<i>file</i><b>_</b><i>name</i><b>.dir</b>. This is available on systems with support
for <b>sdbm</b> databases.
- When no <i>file</i><b>_</b><i>type</i> is specified, the software uses the database
- type specified via the <b><a href="postconf.5.html#default_database_type">default_database_type</a></b> configuration
- parameter.
-
<i>file</i><b>_</b><i>name</i>
The name of the lookup table source file when rebuilding a data-
base.
<b><a name="diagnostics">DIAGNOSTICS</a></b>
- Problems are logged to the standard error stream and to <b>syslogd</b>(8) or
+ Problems are logged to the standard error stream and to <b>syslogd</b>(8) or
<a href="postlogd.8.html"><b>postlogd</b>(8)</a>. No output means that no problems were detected. Duplicate
entries are skipped and are flagged with a warning.
<a href="postmap.1.html"><b>postmap</b>(1)</a> terminates with zero exit status in case of success (includ-
- ing successful "<b>postmap -q</b>" lookup) and terminates with non-zero exit
+ ing successful "<b>postmap -q</b>" lookup) and terminates with non-zero exit
status in case of failure.
<b><a name="environment">ENVIRONMENT</a></b>
Enable verbose logging for debugging purposes.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
- gram. The text below provides only a parameter summary. See <a href="postconf.5.html"><b>post-</b></a>
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant to this pro-
+ gram. The text below provides only a parameter summary. See <a href="postconf.5.html"><b>post-</b></a>
<a href="postconf.5.html"><b>conf</b>(5)</a> for more details including examples.
<b><a href="postconf.5.html#berkeley_db_create_buffer_size">berkeley_db_create_buffer_size</a> (16777216)</b>
- The per-table I/O buffer size for programs that create Berkeley
+ The per-table I/O buffer size for programs that create Berkeley
DB hash or btree tables.
<b><a href="postconf.5.html#berkeley_db_read_buffer_size">berkeley_db_read_buffer_size</a> (131072)</b>
hash or btree tables.
<b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
- The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
+ The default location of the Postfix <a href="postconf.5.html">main.cf</a> and <a href="master.5.html">master.cf</a> con-
figuration files.
<b><a href="postconf.5.html#default_database_type">default_database_type</a> (see 'postconf -d' output)</b>
and <a href="postmap.1.html"><b>postmap</b>(1)</a> commands.
<b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
- The list of environment variables that a privileged Postfix
- process will import from a non-Postfix parent process, or
+ The list of environment variables that a privileged Postfix
+ process will import from a non-Postfix parent process, or
name=value environment overrides.
<b><a href="postconf.5.html#smtputf8_enable">smtputf8_enable</a> (yes)</b>
- Enable preliminary SMTPUTF8 support for the protocols described
+ Enable preliminary SMTPUTF8 support for the protocols described
in <a href="https://tools.ietf.org/html/rfc6531">RFC 6531</a>, <a href="https://tools.ietf.org/html/rfc6532">RFC 6532</a>, and <a href="https://tools.ietf.org/html/rfc6533">RFC 6533</a>.
<b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
The syslog facility of Postfix logging.
<b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
- A prefix that is prepended to the process name in syslog
+ A prefix that is prepended to the process name in syslog
records, so that, for example, "smtpd" becomes "prefix/smtpd".
Available in Postfix 2.11 and later:
<b>postmap -q - <a href="regexp_table.5.html">regexp</a>:/etc/postfix/</b><i>filename</i> <<i>inputfile</i>
<b><a name="description">DESCRIPTION</a></b>
- The Postfix mail system uses optional tables for address rewriting,
- mail routing, or access control. These tables are usually in <b>dbm</b> or <b>db</b>
+ The Postfix mail system uses optional tables for address rewriting or
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
format.
Alternatively, lookup tables can be specified in POSIX regular expres-
in "user has moved to <i>new</i><b>_</b><i>location</i>" bounce messages.
Normally, the <a href="relocated.5.html"><b>relocated</b>(5)</a> table is specified as a text file that
- serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file
- in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
- Execute the command "<b>postmap /etc/postfix/relocated</b>" to rebuild an
- indexed file after changing the corresponding relocated table.
+ serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for
+ fast lookup.
+
+ Execute the command "<b>postmap /etc/postfix/relocated</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/relocated</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
- directed to a TCP-based server. In those case, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
+ directed to a TCP-based server. In those case, the lookups are done in
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
Table lookups are case insensitive.
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
<b>o</b> By default, Postfix will prepend a hard-coded prefix "5.1.6 User
- has moved to " to a table lookup result, and the format for a
+ has moved to " to a table lookup result, and the format for a
table entry is as follows:
<i>pattern new</i><b>_</b><i>location</i>
- Where <i>new</i><b>_</b><i>location</i> specifies contact information such as an
- email address, or perhaps a street address or telephone number.
+ Where <i>new</i><b>_</b><i>location</i> specifies contact information such as an
+ email address, or perhaps a street address or telephone number.
- <b>o</b> Postfix 3.11 and later can optionally disable the hard-coded
- prefix. Specify "<a href="postconf.5.html#relocated_prefix_enable">relocated_prefix_enable</a> = no" in <a href="postconf.5.html">main.cf</a>, and
- specify <a href="postconf.5.html#relocated_maps">relocated_maps</a> entries with your own <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>-compliant
+ <b>o</b> Postfix 3.11 and later can optionally disable the hard-coded
+ prefix. Specify "<a href="postconf.5.html#relocated_prefix_enable">relocated_prefix_enable</a> = no" in <a href="postconf.5.html">main.cf</a>, and
+ specify <a href="postconf.5.html#relocated_maps">relocated_maps</a> entries with your own <a href="https://tools.ietf.org/html/rfc3463">RFC 3463</a>-compliant
enhanced status code and text, for example:
<i>pattern</i> 5.1.6 Mailbox has moved to user@example
<i>pattern</i> 5.2.0 Mailbox is unavailable
<i>pattern</i> 5.2.1 Mailbox is disabled
- <b>o</b> Empty lines and whitespace-only lines are ignored, as are lines
+ <b>o</b> Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
- <b>o</b> A logical line starts with non-whitespace text. A line that
+ <b>o</b> A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b><a name="table_search_order">TABLE SEARCH ORDER</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, patterns are tried in the order as
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
<i>user</i>@<i>domain</i>
- Matches <i>user</i>@<i>domain</i>. This form has precedence over all other
+ Matches <i>user</i>@<i>domain</i>. This form has precedence over all other
forms.
<i>user</i> Matches <i>user</i>@<i>site</i> when <i>site</i> is $<b><a href="postconf.5.html#myorigin">myorigin</a></b>, when <i>site</i> is listed in
- $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when <i>site</i> is listed in $<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or
+ $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when <i>site</i> is listed in $<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or
$<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a></b>.
@<i>domain</i>
- Matches other addresses in <i>domain</i>. This form has the lowest
+ Matches other addresses in <i>domain</i>. This form has the lowest
precedence.
<b><a name="address_extension">ADDRESS EXTENSION</a></b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>user+foo</i>, <i>user</i>, and @<i>domain</i>.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions or when lookups are directed
- to a TCP-based server. For a description of regular expression lookup
- table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>. For a description
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions or when lookups are directed
+ to a TCP-based server. For a description of regular expression lookup
+ table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>. For a description
of the TCP client/server table lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This
feature is available in Postfix 2.5 and later.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
- ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
+ ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Results are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Results are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
available in Postfix 2.5 and later.
- Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
- mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
+ Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
+ mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
stituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Results are the same as with indexed file lookups.
The table format does not understand quoting conventions.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
- below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
+ below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
details including examples.
<b><a href="postconf.5.html#relocated_maps">relocated_maps</a> (empty)</b>
Available with Postfix version 3.11 and later:
<b><a href="postconf.5.html#relocated_prefix_enable">relocated_prefix_enable</a> (yes)</b>
- Prepend the prefix "<b>5.1.6 User has moved to</b> " to all relo-
+ Prepend the prefix "<b>5.1.6 User has moved to</b> " to all relo-
cated_maps lookup results.
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The local network interface addresses that this mail system
+ The local network interface addresses that this mail system
receives mail on.
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, localhost)</b>
- The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
+ The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
mail delivery transport.
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The remote network interface addresses that this mail system
- receives mail on by way of a proxy or network address transla-
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
tion unit.
<b><a name="see_also">SEE ALSO</a></b>
<b>postmap -q - <a href="socketmap_table.html">socketmap</a>:unix:</b><i>pathname</i><b>:</b><i>name</i> <<i>inputfile</i>
<b><a name="description">DESCRIPTION</a></b>
- The Postfix mail system uses optional tables for address rewriting,
- mail routing or policy lookup.
+ The Postfix mail system uses optional tables for address rewriting or
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- The Postfix socketmap client expects TCP endpoint names of the form
- <b>inet:</b><i>host</i><b>:</b><i>port</i><b>:</b><i>name</i>, or UNIX-domain endpoints of the form <b>unix:</b><i>path-</i>
+ The Postfix socketmap client expects TCP endpoint names of the form
+ <b>inet:</b><i>host</i><b>:</b><i>port</i><b>:</b><i>name</i>, or UNIX-domain endpoints of the form <b>unix:</b><i>path-</i>
<i>name</i><b>:</b><i>name</i>. In both cases, <i>name</i> specifies the name field in a socketmap
client request (see "REQUEST FORMAT" below).
<b><a name="protocol">PROTOCOL</a></b>
Socketmaps use a simple protocol: the client sends one request, and the
- server sends one reply. Each request and each reply are sent as one
+ server sends one reply. Each request and each reply are sent as one
netstring object.
<b><a name="request_format">REQUEST FORMAT</a></b>
- The socketmap protocol supports only the lookup request. The request
+ The socketmap protocol supports only the lookup request. The request
has the following form:
<i>name</i> <<b>space</b>> <i>key</i>
Search the named socketmap for the specified key.
- Postfix will not generate partial search keys such as domain names
- without one or more subdomains, network addresses without one or more
- least-significant octets, or email addresses without the localpart,
- address extension or domain portion. This behavior is also found with
+ Postfix will not generate partial search keys such as domain names
+ without one or more subdomains, network addresses without one or more
+ least-significant octets, or email addresses without the localpart,
+ address extension or domain portion. This behavior is also found with
<a href="cidr_table.5.html">cidr</a>:, <a href="pcre_table.5.html">pcre</a>:, and <a href="regexp_table.5.html">regexp</a>: tables.
<b><a name="reply_format">REPLY FORMAT</a></b>
<b>TIMEOUT</b> <<b>space</b>> <i>reason</i>
<b>PERM</b> <<b>space</b>> <i>reason</i>
- The request failed. The reason, if non-empty, is descriptive
+ The request failed. The reason, if non-empty, is descriptive
text.
<b><a name="protocol_limits">PROTOCOL LIMITS</a></b>
- The Postfix socketmap client requires that replies are no longer than
- 100000 bytes (not including the netstring encapsulation). This limit
- can be changed with the <a href="postconf.5.html#socketmap_max_reply_size">socketmap_max_reply_size</a> configuration parame-
+ The Postfix socketmap client requires that replies are no longer than
+ 100000 bytes (not including the netstring encapsulation). This limit
+ can be changed with the <a href="postconf.5.html#socketmap_max_reply_size">socketmap_max_reply_size</a> configuration parame-
ter (Postfix 3.10 and later).
The Postfix socketmap client enforces a 100s time limit to connect to a
- socketmap server, to send a request, and to receive a reply. It closes
- an idle connection after 10s, and closes an active connection after
+ socketmap server, to send a request, and to receive a reply. It closes
+ an idle connection after 10s, and closes an active connection after
100s. These limits are not (yet) configurable.
<b><a name="security">SECURITY</a></b>
- This map cannot be used for security-sensitive information, because
+ This map cannot be used for security-sensitive information, because
neither the connection nor the server are authenticated.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
<b><a href="postconf.5.html#socketmap_max_reply_size">socketmap_max_reply_size</a> (100000)</b>
- The maximum allowed reply size from a socketmap server, not
+ The maximum allowed reply size from a socketmap server, not
including the netstring encapsulation.
<b><a name="see_also">SEE ALSO</a></b>
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- Alternatively, lookup tables can be specified as SQLite databases. In
- order to use SQLite lookups, define an SQLite source as a lookup table
- in <a href="postconf.5.html">main.cf</a>, for example:
+ Alternatively, lookup tables can be specified as SQLite databases. To
+ find out what types of lookup tables your Postfix system supports use
+ the "<b>postconf -m</b>" command.
+
+ In order to use SQLite lookups, define an SQLite source as a lookup ta-
+ ble in <a href="postconf.5.html">main.cf</a>, for example:
<a href="postconf.5.html#alias_maps">alias_maps</a> = <a href="sqlite_table.5.html">sqlite</a>:/etc/postfix/sqlite-aliases.cf
The file /etc/postfix/sqlite-aliases.cf has the same format as the
<b><a name="description">DESCRIPTION</a></b>
The Postfix mail system uses optional tables for address rewriting or
- mail routing. These tables are usually in <b>dbm</b> or <b>db</b> format. Alterna-
- tively, table lookups can be directed to a TCP server.
+ mail routing. These tables are usually in <b><a href="lmdb_table.5.html">lmdb</a>:</b>, <b><a href="CDB_README.html">cdb</a>:</b>, <b><a href="DATABASE_README.html#types">hash</a>:</b>, or <b><a href="DATABASE_README.html#types">dbm</a>:</b>
+ format.
- To find out what types of lookup tables your Postfix system supports
- use the "<b>postconf -m</b>" command.
-
- To test lookup tables, use the "<b>postmap -q</b>" command as described in the
- SYNOPSIS above.
+ Alternatively, table lookups can be directed to a TCP server. To test
+ lookup tables, use the "<b>postmap -q</b>" command as described in the SYNOP-
+ SIS above.
<b><a name="protocol_description">PROTOCOL DESCRIPTION</a></b>
The TCP map class implements a very simple protocol: the client sends a
<b><a href="postconf.5.html#relayhost">relayhost</a></b>, or from the recipient domain.
Normally, the <a href="transport.5.html"><b>transport</b>(5)</a> table is specified as a text file that
- serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file
- in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
- Execute the command "<b>postmap /etc/postfix/transport</b>" to rebuild an
- indexed file after changing the corresponding transport table.
+ serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for
+ fast lookup.
+
+ Execute the command "<b>postmap /etc/postfix/transport</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/transport</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
- directed to a TCP-based server. In those case, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
+ directed to a TCP-based server. In those case, the lookups are done in
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern result</i>
- When <i>pattern</i> matches the recipient address or domain, use the
+ When <i>pattern</i> matches the recipient address or domain, use the
corresponding <i>result</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
The <i>pattern</i> specifies an email address, a domain name, or a domain name
hierarchy, as described in section "TABLE SEARCH ORDER".
- The <i>result</i> is of the form <i>transport:nexthop</i> and specifies how or where
+ The <i>result</i> is of the form <i>transport:nexthop</i> and specifies how or where
to deliver mail. This is described in section "RESULT FORMAT".
<b><a name="table_search_order">TABLE SEARCH ORDER</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, patterns are tried in the order as
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
<i>user+extension@domain transport</i>:<i>nexthop</i>
Deliver mail for <i>domain</i> through <i>transport</i> to <i>nexthop</i>.
<i>.domain transport</i>:<i>nexthop</i>
- Deliver mail for any subdomain of <i>domain</i> through <i>transport</i> to
+ Deliver mail for any subdomain of <i>domain</i> through <i>transport</i> to
<i>nexthop</i>. This applies only when the string <b><a href="postconf.5.html#transport_maps">transport_maps</a></b> is not
listed in the <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a></b> configuration
setting. Otherwise, a domain name matches itself and its subdo-
mains.
<b>*</b> <i>transport</i>:<i>nexthop</i>
- The special pattern <b>*</b> represents any address (i.e. it functions
- as the wild-card pattern, and is unique to Postfix transport
+ The special pattern <b>*</b> represents any address (i.e. it functions
+ as the wild-card pattern, and is unique to Postfix transport
tables).
- Note 1: the null recipient address is looked up as
+ Note 1: the null recipient address is looked up as
<b>$<a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a></b>@<b>$<a href="postconf.5.html#myhostname">myhostname</a></b> (default: mailer-daemon@hostname).
- Note 2: <i>user@domain</i> or <i>user+extension@domain</i> lookup is available in
+ Note 2: <i>user@domain</i> or <i>user+extension@domain</i> lookup is available in
Postfix 2.0 and later.
<b><a name="result_format">RESULT FORMAT</a></b>
- The lookup result is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>transport</i>
- field specifies a mail delivery transport such as <b>smtp</b> or <b>local</b>. The
+ The lookup result is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>transport</i>
+ field specifies a mail delivery transport such as <b>smtp</b> or <b>local</b>. The
<i>nexthop</i> field specifies where and how to deliver mail.
- The transport field specifies the name of a mail delivery transport
- (the first name of a mail delivery service entry in the Postfix <a href="master.5.html"><b>mas-</b>
+ The transport field specifies the name of a mail delivery transport
+ (the first name of a mail delivery service entry in the Postfix <a href="master.5.html"><b>mas-</b>
<b>ter.cf</b></a> file).
- The nexthop field usually specifies one recipient domain or hostname.
+ The nexthop field usually specifies one recipient domain or hostname.
In the case of the Postfix SMTP/LMTP client, the nexthop field may con-
- tain a list of nexthop destinations separated by comma or whitespace
+ tain a list of nexthop destinations separated by comma or whitespace
(Postfix 3.5 and later).
The syntax of a nexthop destination is transport dependent. With SMTP,
(mail exchanger) DNS lookups with [<i>host</i>] or [<i>host</i>]:<i>port</i>. The [] form is
required when you specify an IP address instead of a hostname.
- A null <i>transport</i> and null <i>nexthop</i> field means "do not change": use the
- delivery transport and nexthop information that would be used when the
+ A null <i>transport</i> and null <i>nexthop</i> field means "do not change": use the
+ delivery transport and nexthop information that would be used when the
entire transport table did not exist.
A non-null <i>transport</i> field with a null <i>nexthop</i> field resets the nexthop
information to the recipient domain.
- A null <i>transport</i> field with non-null <i>nexthop</i> field does not modify the
+ A null <i>transport</i> field with non-null <i>nexthop</i> field does not modify the
transport information.
<b><a name="examples">EXAMPLES</a></b>
- In order to deliver internal mail directly, while using a mail relay
- for all other mail, specify a null entry for internal destinations (do
+ In order to deliver internal mail directly, while using a mail relay
+ for all other mail, specify a null entry for internal destinations (do
not change the delivery transport or the nexthop information) and spec-
ify a wildcard for all other destinations.
<b>.my.domain :</b>
<b>* <a href="smtp.8.html">smtp</a>:outbound-relay.my.domain</b>
- In order to send mail for <b>example.com</b> and its subdomains via the <b>uucp</b>
+ In order to send mail for <b>example.com</b> and its subdomains via the <b>uucp</b>
transport to the UUCP host named <b>example</b>:
<b>example.com uucp:example</b>
<b>.example.com uucp:example</b>
- When no nexthop destination is specified, Postfix uses (from low to
- high precedence): the recipient domain, the nexthop specified with
- <a href="postconf.5.html#relayhost">relayhost</a>, with <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> (for remote deliveries
+ When no nexthop destination is specified, Postfix uses (from low to
+ high precedence): the recipient domain, the nexthop specified with
+ <a href="postconf.5.html#relayhost">relayhost</a>, with <a href="postconf.5.html#sender_dependent_relayhost_maps">sender_dependent_relayhost_maps</a> (for remote deliveries
only), with the transport for the address domain class (see DESCRIPTION
- above), or with <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> (for remote
- deliveries only). For example, the following directs mail for
- <i>user</i>@<b>example.com</b> via the <b>slow</b> transport to a mail exchanger for <b>exam-</b>
- <b>ple.com</b>. The <b>slow</b> transport could be configured to run at most one
+ above), or with <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> (for remote
+ deliveries only). For example, the following directs mail for
+ <i>user</i>@<b>example.com</b> via the <b>slow</b> transport to a mail exchanger for <b>exam-</b>
+ <b>ple.com</b>. The <b>slow</b> transport could be configured to run at most one
delivery process at a time:
<b>example.com slow:</b>
When no transport is specified, Postfix uses the transport that matches
- the address domain class (see DESCRIPTION above), or the transport
- specified with <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> (for remote
- deliveries only). The following sends all mail for <b>example.com</b> and its
+ the address domain class (see DESCRIPTION above), or the transport
+ specified with <a href="postconf.5.html#sender_dependent_default_transport_maps">sender_dependent_default_transport_maps</a> (for remote
+ deliveries only). The following sends all mail for <b>example.com</b> and its
subdomains to host <b>gateway.example.com</b>:
<b>example.com :[gateway.example.com]</b>
<b>.example.com :[gateway.example.com]</b>
- In the above example, the [] suppress MX lookups. This prevents mail
+ In the above example, the [] suppress MX lookups. This prevents mail
routing loops when your machine is primary MX host for <b>example.com</b>.
- In the case of delivery via SMTP or LMTP, one may specify <i>host</i>:<i>service</i>
+ In the case of delivery via SMTP or LMTP, one may specify <i>host</i>:<i>service</i>
instead of just a host:
<b>example.com <a href="smtp.8.html">smtp</a>:bar.example:2025</b>
- This directs mail for <i>user</i>@<b>example.com</b> to host <b>bar.example</b> port <b>2025</b>.
- Instead of a numerical port a symbolic name may be used. Specify []
+ This directs mail for <i>user</i>@<b>example.com</b> to host <b>bar.example</b> port <b>2025</b>.
+ Instead of a numerical port a symbolic name may be used. Specify []
around the hostname if MX lookups must be disabled.
- Deliveries via SMTP or LMTP support multiple destinations (Postfix >=
+ Deliveries via SMTP or LMTP support multiple destinations (Postfix >=
3.5):
<b>example.com <a href="smtp.8.html">smtp</a>:bar.example, foo.example</b>
- This tries to deliver to <b>bar.example</b> before trying to deliver to
+ This tries to deliver to <b>bar.example</b> before trying to deliver to
<b>foo.example</b>.
The error mailer can be used to bounce mail:
This causes all mail for <i>user</i>@<i>anything</i><b>.example.com</b> to be bounced.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>some.domain.hierarchy</i> is not looked up
- via its parent domains, nor is <i>user+foo@domain</i> looked up as
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>some.domain.hierarchy</i> is not looked up
+ via its parent domains, nor is <i>user+foo@domain</i> looked up as
<i>user@domain</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
The <a href="trivial-rewrite.8.html"><b>trivial-rewrite</b>(8)</a> server disallows regular expression substitution
a security hole (Postfix version 2.3 and later).
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is not
available up to and including Postfix version 2.4.
- Each lookup operation uses the entire recipient address once. Thus,
- <i>some.domain.hierarchy</i> is not looked up via its parent domains, nor is
+ Each lookup operation uses the entire recipient address once. Thus,
+ <i>some.domain.hierarchy</i> is not looked up via its parent domains, nor is
<i>user+foo@domain</i> looked up as <i>user@domain</i>.
Results are the same as with indexed file lookups.
<b><a name="configuration_parameters">CONFIGURATION PARAMETERS</a></b>
- The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
- below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
+ The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant. The text
+ below provides only a parameter summary. See <a href="postconf.5.html"><b>postconf</b>(5)</a> for more
details including examples.
<b><a href="postconf.5.html#empty_address_recipient">empty_address_recipient</a> (MAILER-DAEMON)</b>
The recipient of mail addressed to the null address.
<b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf -d' output)</b>
- A list of Postfix features where the pattern "example.com" also
- matches subdomains of example.com, instead of requiring an
+ A list of Postfix features where the pattern "example.com" also
+ matches subdomains of example.com, instead of requiring an
explicit ".example.com" pattern.
<b><a href="postconf.5.html#transport_maps">transport_maps</a> (empty)</b>
- Optional lookup tables with mappings from recipient address to
+ Optional lookup tables with mappings from recipient address to
(message delivery transport, next-hop destination).
<b><a name="see_also">SEE ALSO</a></b>
header and envelope addresses in general.
Normally, the <a href="virtual.5.html"><b>virtual</b>(5)</a> alias table is specified as a text file that
- serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command. The result, an indexed file
- in <b>dbm</b> or <b>db</b> format, is used for fast searching by the mail system.
- Execute the command "<b>postmap /etc/postfix/virtual</b>" to rebuild an
- indexed file after changing the corresponding text file.
+ serves as input to the <a href="postmap.1.html"><b>postmap</b>(1)</a> command to create an indexed file for
+ fast lookup.
+
+ Execute the command "<b>postmap /etc/postfix/virtual</b>" to rebuild a
+ default-type indexed file after changing the text file, or execute
+ "<b>postmap</b> <i>type</i><b>:/etc/postfix/virtual</b>" to specify an explicit type.
+
+ The default indexed file type is configured with the <a href="postconf.5.html#default_database_type">default_data</a>-
+ <a href="postconf.5.html#default_database_type">base_type</a> parameter. Depending on the platform this may be one of
+ <a href="lmdb_table.5.html">lmdb</a>:, <a href="CDB_README.html">cdb</a>:, <a href="DATABASE_README.html#types">hash</a>:, or <a href="DATABASE_README.html#types">dbm</a>: (without the trailing ':').
When the table is provided via other means such as NIS, LDAP or SQL,
- the same lookups are done as for ordinary indexed files.
+ the same lookups are done as for ordinary indexed files. Managing such
+ databases is outside the scope of Postfix.
- Alternatively, the table can be provided as a regular-expression map
- where patterns are given as regular expressions, or lookups can be
- directed to a TCP-based server. In those case, the lookups are done in
- a slightly different way as described below under "REGULAR EXPRESSION
+ Alternatively, the table can be provided as a regular-expression map
+ where patterns are given as regular expressions, or lookups can be
+ directed to a TCP-based server. In those case, the lookups are done in
+ a slightly different way as described below under "REGULAR EXPRESSION
TABLES" or "TCP-BASED TABLES".
<b><a name="case_folding">CASE FOLDING</a></b>
- The search string is folded to lowercase before database lookup. As of
- Postfix 2.3, the search string is not case folded with database types
- such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
+ The search string is folded to lowercase before database lookup. As of
+ Postfix 2.3, the search string is not case folded with database types
+ such as <a href="regexp_table.5.html">regexp</a>: or <a href="pcre_table.5.html">pcre</a>: whose lookup fields can match both upper and
lower case.
<b><a name="table_format">TABLE FORMAT</a></b>
The input format for the <a href="postmap.1.html"><b>postmap</b>(1)</a> command is as follows:
<i>pattern address, address, ...</i>
- When <i>pattern</i> matches a mail address, replace it by the corre-
+ When <i>pattern</i> matches a mail address, replace it by the corre-
sponding <i>address</i>.
blank lines and comments
- Empty lines and whitespace-only lines are ignored, as are lines
+ Empty lines and whitespace-only lines are ignored, as are lines
whose first non-whitespace character is a `#'.
multi-line text
- A logical line starts with non-whitespace text. A line that
+ A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line.
<b><a name="table_search_order">TABLE SEARCH ORDER</a></b>
- With lookups from indexed files such as DB or DBM, or from networked
- tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
+ With lookups from indexed files such as DB or DBM, or from networked
+ tables such as NIS, LDAP or SQL, each <i>user</i>@<i>domain</i> query produces a
sequence of query patterns as described below.
Each query pattern is sent to each specified lookup table before trying
the next query pattern, until a match is found.
<i>user</i>@<i>domain address, address, ...</i>
- Redirect mail for <i>user</i>@<i>domain</i> to <i>address</i>. This form has the
+ Redirect mail for <i>user</i>@<i>domain</i> to <i>address</i>. This form has the
highest precedence.
<i>user address, address, ...</i>
- Redirect mail for <i>user</i>@<i>site</i> to <i>address</i> when <i>site</i> is equal to
- $<b><a href="postconf.5.html#myorigin">myorigin</a></b>, when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is
+ Redirect mail for <i>user</i>@<i>site</i> to <i>address</i> when <i>site</i> is equal to
+ $<b><a href="postconf.5.html#myorigin">myorigin</a></b>, when <i>site</i> is listed in $<b><a href="postconf.5.html#mydestination">mydestination</a></b>, or when it is
listed in $<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></b> or $<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a></b>.
- This functionality overlaps with the functionality of the local
- <i>aliases</i>(5) database. The difference is that <a href="virtual.5.html"><b>virtual</b>(5)</a> mapping
+ This functionality overlaps with the functionality of the local
+ <i>aliases</i>(5) database. The difference is that <a href="virtual.5.html"><b>virtual</b>(5)</a> mapping
can be applied to non-local addresses.
@<i>domain address, address, ...</i>
- Redirect mail for other users in <i>domain</i> to <i>address</i>. This form
+ Redirect mail for other users in <i>domain</i> to <i>address</i>. This form
has the lowest precedence.
- Note: @<i>domain</i> is a wild-card. With this form, the Postfix SMTP
- server accepts mail for any recipient in <i>domain</i>, regardless of
- whether that recipient exists. This may turn your mail system
- into a backscatter source: Postfix first accepts mail for
- non-existent recipients and then tries to return that mail as
+ Note: @<i>domain</i> is a wild-card. With this form, the Postfix SMTP
+ server accepts mail for any recipient in <i>domain</i>, regardless of
+ whether that recipient exists. This may turn your mail system
+ into a backscatter source: Postfix first accepts mail for
+ non-existent recipients and then tries to return that mail as
"undeliverable" to the often forged sender address.
- To avoid backscatter with mail for a wild-card domain, replace
- the wild-card mapping with explicit 1:1 mappings, or add a
+ To avoid backscatter with mail for a wild-card domain, replace
+ the wild-card mapping with explicit 1:1 mappings, or add a
<a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a> restriction for that domain:
<a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> =
<b><a name="result_address_rewriting">RESULT ADDRESS REWRITING</a></b>
The lookup result is subject to address rewriting:
- <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
- the same <i>user</i> in <i>otherdomain</i>. This works only for the first
+ <b>o</b> When the result has the form @<i>otherdomain</i>, the result becomes
+ the same <i>user</i> in <i>otherdomain</i>. This works only for the first
address in a multi-address lookup result.
- <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
+ <b>o</b> When "<b><a href="postconf.5.html#append_at_myorigin">append_at_myorigin</a>=yes</b>", append "<b>@$<a href="postconf.5.html#myorigin">myorigin</a></b>" to addresses
without "@domain".
<b>o</b> When "<b><a href="postconf.5.html#append_dot_mydomain">append_dot_mydomain</a>=yes</b>", append "<b>.$<a href="postconf.5.html#mydomain">mydomain</a></b>" to addresses
<b><a name="address_extension">ADDRESS EXTENSION</a></b>
When a mail address localpart contains the optional recipient delimiter
- (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
+ (e.g., <i>user+foo</i>@<i>domain</i>), the lookup order becomes: <i>user+foo</i>@<i>domain</i>,
<i>user</i>@<i>domain</i>, <i>user+foo</i>, <i>user</i>, and @<i>domain</i>.
- The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
+ The <b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a></b> parameter controls whether an
unmatched address extension (<i>+foo</i>) is propagated to the result of a ta-
ble lookup.
<b><a name="virtual_alias_domains">VIRTUAL ALIAS DOMAINS</a></b>
- Besides virtual aliases, the virtual alias table can also be used to
- implement <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domains</a>. With a virtual alias domain, all
+ Besides virtual aliases, the virtual alias table can also be used to
+ implement virtual alias domains. With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, all
recipient addresses are aliased to addresses in other domains.
- Virtual alias domains are not to be confused with the virtual mailbox
- domains that are implemented with the Postfix <a href="virtual.8.html"><b>virtual</b>(8)</a> mail delivery
- agent. With virtual mailbox domains, each recipient address can have
+ Virtual alias domains are not to be confused with the virtual mailbox
+ domains that are implemented with the Postfix <a href="virtual.8.html"><b>virtual</b>(8)</a> mail delivery
+ agent. With <a href="ADDRESS_CLASS_README.html#virtual_mailbox_class">virtual mailbox domains</a>, each recipient address can have
its own mailbox.
- With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the virtual domain has its own user name
- space. Local (i.e. non-virtual) usernames are not visible in a virtual
- alias domain. In particular, local <a href="aliases.5.html"><b>aliases</b>(5)</a> and local mailing lists
+ With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the virtual domain has its own user name
+ space. Local (i.e. non-virtual) usernames are not visible in a virtual
+ alias domain. In particular, local <a href="aliases.5.html"><b>aliases</b>(5)</a> and local mailing lists
are not visible as <i>localname@virtual-alias.domain</i>.
Support for a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> looks like:
/etc/postfix/<a href="postconf.5.html">main.cf</a>:
<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> = <a href="DATABASE_README.html#types">hash</a>:/etc/postfix/virtual
- Note: some systems use <b>dbm</b> databases instead of <b>hash</b>. See the output
+ Note: some systems use <b>dbm</b> databases instead of <b>hash</b>. See the output
from "<b>postconf -m</b>" for available database types.
/etc/postfix/virtual:
<i>user2@virtual-alias.domain address2, address3</i>
The <i>virtual-alias.domain anything</i> entry is required for a virtual alias
- domain. <b>Without this entry, mail is rejected with "relay access</b>
+ domain. <b>Without this entry, mail is rejected with "relay access</b>
<b>denied", or bounces with "mail loops back to myself".</b>
- Do not specify <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> names in the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b>
+ Do not specify <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a> names in the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b>
or <b><a href="postconf.5.html#relay_domains">relay_domains</a></b> configuration parameters.
- With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the Postfix SMTP server accepts mail for
+ With a <a href="ADDRESS_CLASS_README.html#virtual_alias_class">virtual alias domain</a>, the Postfix SMTP server accepts mail for
<i>known-user@virtual-alias.domain</i>, and rejects mail for <i>unknown-user</i>@<i>vir-</i>
<i>tual-alias.domain</i> as undeliverable.
- Instead of specifying the virtual alias domain name via the <b><a href="postconf.5.html#virtual_alias_maps">vir</a>-</b>
- <b><a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a></b> table, you may also specify it via the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#virtual_alias_domains">vir-</b>
+ Instead of specifying the virtual alias domain name via the <b><a href="postconf.5.html#virtual_alias_maps">vir</a>-</b>
+ <b><a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a></b> table, you may also specify it via the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#virtual_alias_domains">vir-</b>
<b>tual_alias_domains</a></b> configuration parameter. This latter parameter uses
the same syntax as the <a href="postconf.5.html"><b>main.cf</a> <a href="postconf.5.html#mydestination">mydestination</a></b> configuration parameter.
<b><a name="regular_expression_tables">REGULAR EXPRESSION TABLES</a></b>
- This section describes how the table lookups change when the table is
- given in the form of regular expressions. For a description of regular
+ This section describes how the table lookups change when the table is
+ given in the form of regular expressions. For a description of regular
expression lookup table syntax, see <a href="regexp_table.5.html"><b>regexp_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_table</b>(5)</a>.
- Each pattern is a regular expression that is applied to the entire
- address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
- ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
+ Each pattern is a regular expression that is applied to the entire
+ address being looked up. Thus, <i>user@domain</i> mail addresses are not bro-
+ ken up into their <i>user</i> and <i>@domain</i> constituent parts, nor is <i>user+foo</i>
broken up into <i>user</i> and <i>foo</i>.
- Patterns are applied in the order as specified in the table, until a
+ Patterns are applied in the order as specified in the table, until a
pattern is found that matches the search string.
- Results are the same as with indexed file lookups, with the additional
- feature that parenthesized substrings from the pattern can be interpo-
+ Results are the same as with indexed file lookups, with the additional
+ feature that parenthesized substrings from the pattern can be interpo-
lated as <b>$1</b>, <b>$2</b> and so on.
<b><a name="tcp-based_tables">TCP-BASED TABLES</a></b>
- This section describes how the table lookups change when lookups are
- directed to a TCP-based server. For a description of the TCP
- client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
+ This section describes how the table lookups change when lookups are
+ directed to a TCP-based server. For a description of the TCP
+ client/server lookup protocol, see <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>. This feature is
available in Postfix 2.5 and later.
- Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
- mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
+ Each lookup operation uses the entire address once. Thus, <i>user@domain</i>
+ mail addresses are not broken up into their <i>user</i> and <i>@domain</i> con-
stituent parts, nor is <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
Results are the same as with indexed file lookups.
<b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
Optional lookup tables that are often searched with a full email
- address (including domain) and that apply to all recipients:
- <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a> that
- are only searched with an email address localpart (no domain)
+ address (including domain) and that apply to all recipients:
+ <a href="local.8.html"><b>local</b>(8)</a>, virtual, and remote; this is unlike <a href="postconf.5.html#alias_maps">alias_maps</a> that
+ are only searched with an email address localpart (no domain)
and that apply only to <a href="local.8.html"><b>local</b>(8)</a> recipients.
<b><a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> ($<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)</b>
- Postfix is the final destination for the specified list of vir-
+ Postfix is the final destination for the specified list of vir-
tual alias domains, that is, domains for which all addresses are
aliased to addresses in other local or remote domains.
<b><a href="postconf.5.html#propagate_unmatched_extensions">propagate_unmatched_extensions</a> (canonical, virtual)</b>
- What address lookup tables copy an address extension from the
+ What address lookup tables copy an address extension from the
lookup key to the lookup result.
Other parameters of interest:
<b><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> (all)</b>
- The local network interface addresses that this mail system
+ The local network interface addresses that this mail system
receives mail on.
<b><a href="postconf.5.html#mydestination">mydestination</a> ($<a href="postconf.5.html#myhostname">myhostname</a>, localhost.$<a href="postconf.5.html#mydomain">mydomain</a>, localhost)</b>
- The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
+ The list of domains that are delivered via the $<a href="postconf.5.html#local_transport">local_transport</a>
mail delivery transport.
<b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
- The domain name that locally-posted mail appears to come from,
+ The domain name that locally-posted mail appears to come from,
and that locally posted mail is delivered to.
<b><a href="postconf.5.html#owner_request_special">owner_request_special</a> (yes)</b>
- Enable special treatment for owner-<i>listname</i> entries in the
+ Enable special treatment for owner-<i>listname</i> entries in the
<a href="aliases.5.html"><b>aliases</b>(5)</a> file, and don't split owner-<i>listname</i> and <i>list-</i>
- <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
+ <i>name</i>-request address localparts when the <a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> is
set to "-".
<b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
- The remote network interface addresses that this mail system
- receives mail on by way of a proxy or network address transla-
+ The remote network interface addresses that this mail system
+ receives mail on by way of a proxy or network address transla-
tion unit.
<b><a name="see_also">SEE ALSO</a></b>
: ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"}
: ${PLUGIN_LD="${CC-gcc} -shared"}
;;
- Linux.[3456].*)
+ Linux.[34567].*)
SYSTYPE=LINUX$RELEASE_MAJOR
case "$CCARGS" in
*-DNO_DB*) ;;
man8/oqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \
man8/verify.8 man8/trace.8 man8/proxymap.8 man8/anvil.8 \
man8/scache.8 man8/discard.8 man8/tlsmgr.8 man8/postscreen.8 \
- man8/dnsblog.8 man8/tlsproxy.8 man8/postlogd.8
+ man8/dnsblog.8 man8/tlsproxy.8 man8/postlogd.8 man8/nbdb_reindexd.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/postmulti.1 man1/postqueue.1 man1/postsuper.1 \
- man1/sendmail.1 man1/mailq.1 man1/newaliases.1 man1/postfix-tls.1
+ man1/sendmail.1 man1/mailq.1 man1/newaliases.1 man1/postfix-tls.1 \
+ man1/postfix-non-bdb.1
CONFIG = man5/access.5 man5/aliases.5 man5/canonical.5 man5/relocated.5 \
man5/transport.5 man5/virtual.5 man5/pcre_table.5 man5/regexp_table.5 \
man5/cidr_table.5 man5/tcp_table.5 man5/header_checks.5 \
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman $? >$@
+man8/nbdb_reindexd.8: ../src/nbdb_reindexd/nbdb_reindexd.c
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman $? >$@
+
man8/oqmgr.8: ../src/oqmgr/qmgr.c
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
(cmp -s junk $? || mv junk $?) && rm -f junk
../mantools/srctoman $? >$@
+man1/postfix-non-bdb.1: ../conf/postfix-non-bdb-script
+ ../mantools/fixman ../proto/postconf.proto $? >junk && \
+ (cmp -s junk $? || mv junk $?) && rm -f junk
+ ../mantools/srctoman - $? >$@
+
man1/postfix-tls.1: ../conf/postfix-tls-script
../mantools/fixman ../proto/postconf.proto $? >junk && \
(cmp -s junk $? || mv junk $?) && rm -f junk
The database type. To find out what types are supported, use
the "\fBpostconf \-m\fR" command.
+When no \fIfile_type\fR is specified, the software uses the database
+type specified via the \fBdefault_database_type\fR configuration
+parameter.
+The default value for this parameter depends on the host environment.
+
The \fBpostalias\fR(1) command can query any supported file type,
but it can create only the following file types:
.RS
The output consists of two files, named \fIfile_name\fB.pag\fR and
\fIfile_name\fB.dir\fR.
This is available on systems with support for \fBsdbm\fR databases.
-.PP
-When no \fIfile_type\fR is specified, the software uses the database
-type specified via the \fBdefault_database_type\fR configuration
-parameter.
-The default value for this parameter depends on the host environment.
.RE
.IP \fIfile_name\fR
The name of the alias database source file when creating a database.
--- /dev/null
+.TH POSTFIX-NON-BDB 1
+.ad
+.fi
+.SH NAME
+postfix-non-bdb
+\-
+Postfix non\-Berkeley\-DB migration
+.SH "SYNOPSIS"
+.na
+.nf
+\fBpostfix non\-bdb\fR \fIsubcommand\fR
+.SH DESCRIPTION
+.ad
+.fi
+The "\fBpostfix non\-bdb \fIsubcommand\fR" feature edits main.cf
+and master.cf, to manage the migration of an existing Postfix
+configuration that uses Berkeley DB type "hash:" or "btree:"
+tables (which are no longer supported on some OS distributions),
+to supported types such as "cdb:" or "lmdb:".
+
+The following subcommands are available:
+.IP \fBstatus\fR
+Reports the non\-Berkeley\-DB migration status, without making
+any changes.
+.IP \fBdisable\fR
+Edits main.cf and master.cf, to turn off the \fBenable\-redirect\fR
+and \fBenable\-reindex\fR features.
+.sp
+This will break integration with other software such as
+mailman versions from before May 2025 when they want to
+use "postmap hash:/path/to/file", for example, to update a
+mailman\-maintained table.
+.IP "\fBenable\-redirect\fR (aliasing)"
+Edits main.cf and master.cf, to enable redirection (aliasing)
+from Berkeley DB types "hash" and "btree" to the non\-Berkeley\-DB
+types specified with $default_database_type and
+$default_cache_db_type. Custom redirection may be configured
+with non_bdb_custom_mapping.
+.sp
+This configuration will not automatically create non\-Berkeley\-DB
+indexed database files. Instead, Postfix programs will log an
+error as they fail to open an indexed database file, and will
+leave it to the system administrator to run postmap(1) or
+postalias(1) to create that file.
+.sp
+This will fix integration with other software such as mailman
+versions from before May 2025 when they want to use "postmap
+hash:/path/to/file", for example, to update a mailman\-maintained
+table.
+.sp
+This subcommand will not make any changes when
+default_database_type or default_cache_db_type specify a hash:
+or btree: type.
+.IP \fBenable\-reindex\fR
+Edits main.cf and master.cf, to implement \fBenable\-redirect\fR,
+and to automatically create a non\-Berkeley\-DB indexed database
+file when a daemon program wants to access a file that does not
+yet exist. This uses the nbdb_reindexd(8) daemon to run postmap(1)
+or postalias(1) as described in "SECURITY" below.
+.sp
+This subcommand immediately generates non\-Berkeley\-DB indexed
+files for unprivileged command\-line programs that cannot send
+requests to the nbdb_reindexd(8) daemon server. This involves
+"hash:" and "btree:" tables that are used by postqueue(1) and
+sendmail(1) as specified in authorized_flush_users and
+authorized_mailq_users, and by sendmail(1) and postdrop(1)
+as specified in authorized_submit_users and
+local_login_sender_maps.
+.sp
+This subcommand will not make any changes when
+default_database_type or default_cache_db_type specify a hash:
+or btree: type.
+.sp
+\fINOTE: \fBenable\-reindex\fI should be used only temporarily
+to generate most of the non\-Berkeley\-DB indexed files that Postfix
+needs. Leaving this enabled may expose the system to
+privilege\-escalation attacks. There are no security
+concerns for using \fBenable\-redirect\fR.
+.SH "SECURITY"
+.na
+.nf
+.ad
+.fi
+The nbdb_reindexd(8) daemon automatically generates a
+non\-Berkeley\-DB indexed file only if the database pathname matches
+the directory prefixes specified with
+non_bdb_migration_allow_root_prefixes (for files that must be
+owned by root), or with non_bdb_migration_allow_user_prefixes
+(for files that must be owned by a non\-root user). Additional
+restrictions on file and directory ownership and permissions
+are documented in nbdb_reindexd(8).
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+The "\fBpostfix non\-bdb \fIsubcommand\fR" feature
+updates the following configuration parameter:
+.IP "\fBnon_bdb_migration_level (disable)\fR"
+The non\-Berkeley\-DB migration service level.
+.PP
+Other relevant parameters:
+.IP "\fBnon_bdb_custom_mapping (empty)\fR"
+When non\-Berkeley\-DB migration is enabled, an optional mapping
+from a hash: or btree: type to a non\-Berkeley\-DB type.
+.IP "\fBnon_bdb_migration_allow_root_prefixes (see 'postconf -d non_bdb_migration_allow_root_prefixes' output)\fR"
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with "root" privilege.
+.IP "\fBnon_bdb_migration_allow_user_prefixes (see 'postconf -d non_bdb_migration_allow_user_prefixes' output)\fR"
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with non\-root privilege.
+.SH "SEE ALSO"
+.na
+.nf
+nbdb_reindexd(8) reindexing service
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or
+"\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
+NON_BERKELEYDB_README, migration guide
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH HISTORY
+.ad
+.fi
+The "\fBpostfix non\-bdb\fR" command was introduced with Postfix
+version 3.11.
+.SH "AUTHOR(S)"
+.na
+.nf
+Wietse Venema
+porcupine.org
with the command specified with $maillog_file_compressor.
This will not rotate /dev/* files.
.sp
-This feature is available in Postfix 3.4 and later.
+.IP "\fBnon\-bdb\fR \fIsubcommand\fR"
+Migrate a Postfix configuration that uses Berkeley DB hash:
+or btree: tables, to a configuration that uses lmdb: or a
+combination of cdb: and lmdb:. This is needed because some
+(Linux) distributions have removed Berkeley DB support.
+See postfix\-nbdb(1) for documentation.
+.sp
+This feature is available in Postfix 3.11 and later.
.IP "\fBtls\fR \fIsubcommand\fR"
Enable opportunistic TLS in the Postfix SMTP client or
server, and manage Postfix SMTP server TLS private keys and
postconf(1), Postfix configuration utility
postdrop(1), Postfix mail posting utility
postfix(1), Postfix control program
+postfix\-non\-bdb(1), Postfix Non\-Berkeley\-DB migration
postfix\-tls(1), Postfix TLS management
postkick(1), trigger Postfix daemon
postlock(1), Postfix\-compatible locking
The database type. To find out what types are supported, use
the "\fBpostconf \-m\fR" command.
+When no \fIfile_type\fR is specified, the software uses the database
+type specified via the \fBdefault_database_type\fR configuration
+parameter.
+The default value for this parameter depends on the host environment.
+
The \fBpostmap\fR(1) command can query any supported file type,
but it can create only the following file types:
.RS
The output consists of two files, named \fIfile_name\fB.pag\fR and
\fIfile_name\fB.dir\fR.
This is available on systems with support for \fBsdbm\fR databases.
-.PP
-When no \fIfile_type\fR is specified, the software uses the database
-type specified via the \fBdefault_database_type\fR configuration
-parameter.
.RE
.IP \fIfile_name\fR
The name of the lookup table source file when rebuilding a database.
email messages.
Normally, the \fBaccess\fR(5) table is specified as a text file
-that serves as input to the \fBpostmap\fR(1) command.
-The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-is used for fast searching by the mail system. Execute the
-command "\fBpostmap /etc/postfix/access\fR" to rebuild an
-indexed file after changing the corresponding text file.
+that serves as input to the \fBpostmap\fR(1) command to create
+an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/access\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/access\fR" to
+specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
domain).
Normally, the \fBaliases\fR(5) table is specified as a text file
-that serves as input to the \fBpostalias\fR(1) command. The
-result, an indexed file in \fBdbm\fR or \fBdb\fR format, is
-used for fast lookup by the mail system. Execute the command
-\fBnewaliases\fR in order to rebuild the indexed file after
-changing the Postfix alias database.
+that serves as input to the \fBpostalias\fR(1) command to create
+an indexed file for fast lookup. The location of this file is
+system\-dependent. This text will use \fB/path/to/aliases\fR.
+
+Execute the command "\fBnewaliases\fR to rebuild the indexed
+file after changing the text file. Execute "\fBpostalias \-q
+\fIname\fB /path/to/aliases\fR" to query a default\-type indexed
+file, or execute "\fBpostalias \-q \fIname\fB
+\fItype\fB:/path/to/aliases\fR" to specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions. In
queue. The address mapping is recursive.
Normally, the \fBcanonical\fR(5) table is specified as a text file
-that serves as input to the \fBpostmap\fR(1) command.
-The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-is used for fast searching by the mail system. Execute the command
-"\fBpostmap /etc/postfix/canonical\fR" to rebuild an indexed
-file after changing the corresponding text file.
+that serves as input to the \fBpostmap\fR(1) command to create
+an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/canonical\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/canonical\fR"
+to specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
.ad
.fi
The Postfix mail system uses optional lookup tables.
-These tables are usually in \fBdbm\fR or \fBdb\fR format.
+These tables are usually in \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR,
+or \fBdbm:\fR format.
+
Alternatively, lookup tables can be specified in CIDR
(Classless Inter\-Domain Routing) form. In this case, each
input is compared against a list of patterns. When a match
Normally, the \fBgeneric\fR(5) table is specified as a
text file that serves as input to the \fBpostmap\fR(1)
-command. The result, an indexed file in \fBdbm\fR or
-\fBdb\fR format, is used for fast searching by the mail
-system. Execute the command "\fBpostmap /etc/postfix/generic\fR"
-to rebuild an indexed file after changing the corresponding
-text file.
+command to create an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/generic\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/generic\fR"
+to specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as LDAP databases.
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf \-m\fR" command.
In order to use LDAP lookups, define an LDAP source as a lookup
table in main.cf, for example:
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as memcache
-instances. To use memcache lookups, define a memcache
+instances. To use memcache lookups, define a memcache
source as a lookup table in main.cf, for example:
.nf
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as MongoDB
-databases. In order to use MongoDB lookups, define a MongoDB
+databases.
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf \-m\fR" command.
+
+In order to use MongoDB lookups, define a MongoDB
source as a lookup table in main.cf, for example:
.nf
alias_maps = mongodb:/etc/postfix/mongodb\-aliases.cf
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as MySQL databases.
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf \-m\fR" command.
+
In order to use MySQL lookups, define a MySQL source as a lookup
table in main.cf, for example:
.nf
.ad
.fi
The Postfix mail system uses optional lookup tables.
-These tables are usually in \fBdbm\fR or \fBdb\fR format.
+rewriting or mail routing. These tables are usually in
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
+
Alternatively, lookup tables can be specified as NIS+
databases.
-
To find out what types of lookup tables your Postfix system
supports use the "\fBpostconf \-m\fR" command.
.ad
.fi
The Postfix mail system uses optional tables for address
-rewriting, mail routing, or access control. These tables
-are usually in \fBdbm\fR or \fBdb\fR format.
+rewriting or mail routing. These tables are usually in
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified in Perl Compatible
Regular Expression form. In this case, each input is compared
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as PostgreSQL
-databases. In order to use PostgreSQL lookups, define a
+databases.
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf \-m\fR" command.
+
+In order to use PostgreSQL lookups, define a
PostgreSQL source as a lookup table in main.cf, for example:
.nf
alias_maps = pgsql:/etc/postfix/pgsql\-aliases.cf
.nf
.na
address_verify_map = $default_cache_db_type:$data_directory/verify_cache
-address_verify_map = hash:/var/lib/postfix/verify_cache
+address_verify_map = lmdb:/var/lib/postfix/verify_cache
address_verify_map = btree:/var/lib/postfix/verify_cache
.fi
.ad
.PP
.nf
.na
-alias_database = hash:/etc/aliases
-alias_database = hash:/etc/mail/aliases
+alias_database = $default_database_type:/etc/aliases
+alias_database = lmdb:/etc/aliases
+alias_database = lmdb:/etc/mail/aliases
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
.SH alias_maps (default: see "postconf \-d" output)
Optional lookup tables that are searched only with an email address
localpart (no domain) and that apply only to \fBlocal\fR(8) recipients;
default is to search the local alias database, then the NIS alias
database.
.PP
-If you change the alias database, run "\fBpostalias /etc/aliases\fR"
-(or wherever your system stores the mail alias file), or simply
-run "\fBnewaliases\fR" to build the necessary DBM or DB file.
-.PP
The \fBlocal\fR(8) delivery agent disallows regular expression substitution
of $1 etc. in alias_maps, because that would open a security hole.
.PP
.PP
.nf
.na
-alias_maps = hash:/etc/aliases, nis:mail.aliases
-alias_maps = hash:/etc/aliases
+alias_maps = $default_database_type:/etc/aliases, nis:mail.aliases
+alias_maps = $default_database_type:/etc/aliases
+alias_maps = lmdb:/etc/mail/aliases
+alias_maps = lmdb:/etc/aliases
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postalias \fI/path/to/aliases\fR" after you
+change the aliases file, to (re)build a default\-type indexed file.
+Execute "postalias \fItype:/path/to/aliases\fR" to specify an explicit
+type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH allow_mail_to_commands (default: alias, forward)
Restrict \fBlocal\fR(8) mail delivery to external commands. The default
is to disallow delivery to "|command" in :include: files (see
until a match is found.
Note: these lookups are recursive.
.PP
-If you use this feature, run "\fBpostmap /etc/postfix/canonical\fR" to
-build the necessary DBM or DB file after every change. The changes
-will become visible after a minute or so. Use "\fBpostfix reload\fR"
-to eliminate the delay.
-.PP
Note: with Postfix version 2.2, message header address mapping
happens only when message header address rewriting is enabled:
.IP \(bu
.PP
.nf
.na
-canonical_maps = dbm:/etc/postfix/canonical
-canonical_maps = hash:/etc/postfix/canonical
+canonical_maps = lmdb:/etc/postfix/canonical
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/canonical" after you
+change the canonical file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/canonical" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH cleanup_replace_stray_cr_lf (default: yes)
Replace each stray <CR> or <LF> character in message
content with a space character, to prevent outbound SMTP smuggling,
.SH default_database_type (default: see "postconf \-d" output)
The default database type for use in \fBnewaliases\fR(1), \fBpostalias\fR(1)
and \fBpostmap\fR(1) commands. On many UNIX systems the default type is
-either \fBdbm\fR or \fBhash\fR. The default setting is frozen
+either \fBlmdb\fR or \fBhash\fR. The default setting is frozen
when the Postfix system is built.
.PP
Examples:
.PP
.nf
.na
+default_database_type = lmdb
default_database_type = hash
-default_database_type = dbm
.fi
.ad
.SH default_delivery_slot_cost (default: 5)
.na
local_header_rewrite_clients = permit_mynetworks,
permit_sasl_authenticated permit_tls_clientcerts
- check_address_map hash:/etc/postfix/pop\-before\-smtp
+ check_address_map lmdb:/etc/postfix/pop\-before\-smtp
.fi
.ad
.in -4
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
.SH local_login_sender_maps (default: static:*)
A list of lookup tables that are searched by the UNIX login name,
and that return a list of allowed envelope sender patterns separated
mynetworks = !192.168.0.1, 192.168.0.0/28
mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:587::]/64
mynetworks = $config_directory/mynetworks
-mynetworks = hash:/etc/postfix/network_table
+mynetworks = lmdb:/etc/postfix/network_table
mynetworks = cidr:/etc/postfix/network_table.cidr
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH mynetworks_style (default: Postfix >= 3.0: host, Postfix < 3.0: subnet)
The method to generate the default value for the mynetworks parameter.
This is the list of trusted networks for relay access control etc.
Sendmail compatibility feature that specifies the location of the
\fBnewaliases\fR(1) command. This command can be used to rebuild the
\fBlocal\fR(8) \fBaliases\fR(5) database.
+.SH non_bdb_custom_mapping (default: empty)
+When non\-Berkeley\-DB migration is enabled, an optional mapping
+from a hash: or btree: type to a non\-Berkeley\-DB type. This mapping
+takes precedence over the default mapping from hash: to
+$default_database_type, and from btree: to $default_cache_db_type.
+.IP \(bu
+Specify a lookup table with a search keys that are a
+Berkeley DB \fItype\fR (without ':') or \fItype:name\fR.
+.IP \(bu
+A search key with the form \fItype:name\fR takes precedence
+over \fItype\fR (without ':').
+.IP \(bu
+The lookup result must always be a non\-Berkeley\-DB \fItype\fR
+(without ':') and must not contain a \fI:name\fR.
+.IP \(bu
+The mapping table type must not be \fBhash\fR or \fBbtree\fR.
+.br
+.PP
+This feature is available in Postfix >= 3.11.
+.SH non_bdb_migration_allow_root_prefixes (default: see 'postconf \-d non_bdb_migration_allow_root_prefixes' output)
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with "root" privilege.
+.PP
+This feature is available in Postfix >= 3.11.
+.SH non_bdb_migration_allow_user_prefixes (default: see 'postconf \-d non_bdb_migration_allow_user_prefixes' output)
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with non\-root privilege.
+.PP
+This feature is available in Postfix >= 3.11.
+.SH non_bdb_migration_level (default: disable)
+The non\-Berkeley\-DB migration service level. You are expected to use
+the command "\fBpostfix non\-bdb \fIname\-of\-level\fR\fR" to correctly
+configure the migration service level (see postfix\-non\-\fBbdb\fR(1).
+.IP "\fBdisable\fR"
+Disable all non\-Berkeley\-DB migration features. See
+NON_BERKELEYDB_README#disable for possible negative implications
+for integration with other software such as mailman.
+.br
+.IP "\fBenable\-redirect\fR (aliasing)"
+Enable redirection (aliasing) from Berkeley DB hash to
+$default_database_type, and from Berkeley DB btree to
+$default_cache_db_type, but do not automatically create the new cdb
+or lmdb indexed database files that Postfix programs need. See
+NON_BERKELEYDB_README#enable\-redirect for details and limitations.
+.br
+.IP "\fBenable\-reindex\fR"
+In addition to enable\-redirect, also create a non\-Berkeley\-DB
+indexed database file when a daemon program wants to access a file
+that does not yet exist. This feature uses the \fBnbdb_reindexd\fR(8)
+daemon to run \fBpostmap\fR(1) or \fBpostalias\fR(1). See
+NON_BERKELEYDB_README#enable\-reindex for details and limitations.
+.PP
+\fI NOTE: \fBenable\-reindex\fR should be used only temporarily to
+generate most of the non\-Berkeley\-DB indexed database files that Postfix
+programs need. Leaving this level enabled may expose the system to
+privilege\-escalation attacks. There are no security concerns for using
+\fBenable\-redirect\fR. \fR
+.br
+.br
+.PP
+This feature is available in Postfix >= 3.11.
+.SH non_bdb_migration_service_name (default: nbdb_reindex)
+The name of a master.cf service that implements the non\-Berkeley\-DB
+migration service protocol.
+.PP
+This feature is available in Postfix >= 3.11.
.SH non_empty_end_of_header_action (default: fix_quietly)
How the \fBcleanup\fR(8) daemon will process a message when the primary
message header is terminated with a non\-empty line.
.fi
.ad
.br
+.br
.PP
This feature is available in Postfix >= 3.11.
.SH non_fqdn_reject_code (default: 504)
Persistent storage for the \fBpostscreen\fR(8) server decisions.
.PP
To share a \fBpostscreen\fR(8) cache between multiple \fBpostscreen\fR(8)
-instances, use "postscreen_cache_map = proxy:btree:/path/to/file"
-or "proxy:lmdb:/path/to/file".
+instances, use "postscreen_cache_map = proxy:lmdb:/path/to/file"
+or "proxy:btree:/path/to/file".
This requires Postfix version 2.9 or later; earlier \fBproxymap\fR(8)
implementations don't support cache cleanup. For an alternative
approach see the \fBmemcache_table\fR(5) manpage.
.nf
.na
/etc/postfix/main.cf:
- rbl_reply_maps = hash:/etc/postfix/rbl_reply
+ rbl_reply_maps = lmdb:/etc/postfix/rbl_reply
smtpd_recipient_restrictions =
permit_mynetworks,
reject_rbl_client \fIsecret\fR.zen.dq.spamhaus.net=127.0.0.[2..11],
.fi
.ad
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
NOTE: This feature differs from postscreen_dnsbl_reply_map where
the table search key is only a domain name (no "\fI=address\-filter\fR",
no "\fI*weight\fR" factor) and where the lookup result
should be only a domain name (no free text, no \fI$name\fR variables).
.PP
+Execute the command "postmap /etc/postfix/rbl_reply" after you
+change the rbl_reply file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/rbl_reply" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 2.0 and later.
The "=address\-filter" feature is available in Postfix 2.8 and later.
.SH readme_directory (default: see "postconf \-d" output)
.PP
.nf
.na
-recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
+recipient_bcc_maps = lmdb:/etc/postfix/recipient_bcc
.fi
.ad
.PP
-After a change, run "\fBpostmap /etc/postfix/recipient_bcc\fR".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/recipient_bcc" after
+you change the recipient_bcc file, to (re)build a default\-type indexed
+file. Execute "postmap \fItype\fR:/etc/postfix/recipient_bcc" to
+specify an explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.PP
This feature is available in Postfix 2.1 and later.
.SH recipient_canonical_classes (default: envelope_recipient, header_recipient)
.PP
.nf
.na
-recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
+recipient_canonical_maps = lmdb:/etc/postfix/recipient_canonical
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/recipient_canonical"
+after you change the recipient_canonical file, to (re)build a
+default\-type indexed file. Execute "postmap
+\fItype\fR:/etc/postfix/recipient_canonical" to specify an explicit
+type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH recipient_delimiter (default: empty)
The set of characters that can separate an email address
localpart, user name, or a .forward file name from its extension.
.PP
.nf
.na
-relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+relay_clientcerts = lmdb:/etc/postfix/relay_clientcerts
.fi
.ad
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
For more fine\-grained control, use check_ccert_access to select
an appropriate \fBaccess\fR(5) policy for each client.
See RESTRICTION_CLASS_README.
.PP
+Execute the command "postmap /etc/postfix/relay_clientcerts"
+after you change the relay_clientcerts file, to (re)build a default\-type
+indexed file. Execute "postmap \fItype\fR:/etc/postfix/relay_clientcerts"
+to specify an explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available with Postfix version 2.2.
.SH relay_destination_concurrency_limit (default: $default_destination_concurrency_limit)
The maximal number of parallel deliveries to the same destination
.PP
.nf
.na
-relay_recipient_maps = hash:/etc/postfix/relay_recipients
+relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
.fi
.ad
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/relay_recipients"
+after you change the relay_recipients file, to (re)build a default\-type
+indexed file. Execute "postmap \fItype\fR:/etc/postfix/relay_recipients"
+to specify an explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 2.0 and later.
.SH relay_transport (default: relay)
The default mail delivery transport and next\-hop destination for
whitespace or comma. Tables will be searched in the specified order
until a match is found.
.PP
-If you use this feature, run "\fBpostmap /etc/postfix/relocated\fR" to
-build the necessary DBM or DB file after change, then "\fBpostfix
-reload\fR" to make the changes visible.
-.PP
Examples:
.PP
.nf
.na
-relocated_maps = dbm:/etc/postfix/relocated
-relocated_maps = hash:/etc/postfix/relocated
+relocated_maps = lmdb:/etc/postfix/relocated
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/relocated" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH relocated_prefix_enable (default: yes)
Prepend the prefix "\fB5.1.6 User has moved to \fR" to all
relocated_maps lookup results. With "relocated_prefix_enable =
.nf
.na
/etc/postfix/main.cf:
- relocated_maps = hash:/etc/postfix/relocated
+ relocated_maps = lmdb:/etc/postfix/relocated
relocated_prefix_enable = no
.br
-hash:/etc/postfix/relocated:
+/etc/postfix/relocated:
user@example.com 5.2.1 User account is disabled
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/relocated" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
+This feature is available in Postfix 3.11 and later.
.SH remote_header_rewrite_domain (default: empty)
Rewrite or add message headers in mail from remote clients if
the remote_header_rewrite_domain parameter value is non\-empty,
.PP
.nf
.na
-sender_bcc_maps = hash:/etc/postfix/sender_bcc
+sender_bcc_maps = lmdb:/etc/postfix/sender_bcc
.fi
.ad
.PP
-After a change, run "\fBpostmap /etc/postfix/sender_bcc\fR".
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/sender_bcc" after you
+change the sender_bcc file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/sender_bcc" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.PP
This feature is available in Postfix 2.1 and later.
.SH sender_canonical_classes (default: envelope_sender, header_sender)
.PP
.nf
.na
-sender_canonical_maps = hash:/etc/postfix/sender_canonical
+sender_canonical_maps = lmdb:/etc/postfix/sender_canonical
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/sender_canonical"
+after you change the sender_canonical file, to (re)build a default\-type
+indexed file. Execute "postmap \fItype\fR:/etc/postfix/sender_canonical"
+to specify an explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH sender_dependent_default_transport_maps (default: empty)
A sender\-dependent override for the global default_transport
parameter setting. The tables are searched by the envelope sender
.nf
.na
/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+ transport_maps = lmdb:/etc/postfix/transport
.fi
.ad
.in -4
.ad
.in -4
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
Unselective use of the "data" target does no harm, but will
result in unnecessary "lost connection after DATA" events at remote
SMTP/LMTP servers.
.PP
+Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/transport" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 3.0 and later.
.SH smtp_always_send_ehlo (default: yes)
Always send EHLO at the start of an SMTP session.
(Punycode) before making a policy query; lookup tables must answer
ASCII\-form queries.
.IP \(bu
-A fixed\-string table (such as hash:, btree:, or lmdb:) is
+A fixed\-string table (such as lmdb:, cdb:, or hash:) is
also searched with the next\-hop ".parent" domains (in a table key,
prepend a '.' to a parent domain name). These ".parent" domain
queries are not made with pattern\-based lookup tables such as regexp:
To match any name below the domain "example.com" specify
a table entry with the storage key ".example.com" in type:table
lookup tables that need an exact match. This is appropriate, for
-example, with hash:, btree: or lmdb:.
+example, with lmdb:, cdb: or hash:.
.IP \(bu
Do not specify a match pattern for ".domain" with regexp:,
pcre:, socketmap:, or tcp:, as smtp_requiretls_policy will
cidr:{
{ 0.0.0.0/0 opportunistic },
{ ::/0 opportunistic } },
- hash:/etc/postfix/requiretls\-per\-site
+ lmdb:/etc/postfix/requiretls\-per\-site
opportunistic+starttls
.sp
/etc/postfix/requiretls\-per\-site:
...
.fi
.ad
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/requiretls\-per\-site"
+after you change the requiretls\-per\-site file, to (re)build a
+default\-type indexed file. Execute "postmap
+\fItype\fR:/etc/postfix/requiretls\-per\-site" to specify an explicit
+type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.br
.PP
LMTP client examples. See REQUIRETLS_README for discussion.
.PP
.nf
.na
-smtp_sasl_auth_cache_name = proxy:btree:/var/lib/postfix/sasl_auth_cache
smtp_sasl_auth_cache_name = proxy:lmdb:/var/lib/postfix/sasl_auth_cache
+smtp_sasl_auth_cache_name = proxy:btree:/var/lib/postfix/sasl_auth_cache
.fi
.ad
.PP
.nf
.na
/etc/postfix/main.cf:
- smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
+ smtp_tls_policy_maps = lmdb:/etc/postfix/tls_policy
smtp_tls_fingerprint_digest = sha256
.fi
.ad
.ad
.in -4
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/tls_policy" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 2.5 and later.
.SH smtp_tls_fingerprint_digest (default: see "postconf \-d" output)
The message digest algorithm used to construct remote SMTP server
.nf
.na
/etc/postfix/main.cf:
- smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
+ smtp_tls_policy_maps = lmdb:/etc/postfix/tls_policy
# Postfix 2.5 and later.
#
# The default digest is sha256 with Postfix >= 3.6 and
.fi
.ad
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
\fBNote:\fR The "hostname" strategy if listed in a non\-default
setting of smtp_tls_secure_cert_match or in the "match" attribute
in the policy table can render the "secure" level vulnerable to
DNS forgery. Do not use the "hostname" strategy for secure\-channel
configurations in environments where DNS security is not assured.
.PP
+Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/tls_policy" to specify
+an explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 2.3 and later.
.SH smtp_tls_protocols (default: see 'postconf \-d' output)
TLS protocols that the Postfix SMTP client will use with
.SH smtp_tls_session_cache_database (default: empty)
Name of the file containing the optional Postfix SMTP client
TLS session cache. Specify a database type that supports enumeration,
-such as \fBbtree\fR or \fBsdbm\fR; there is no need to support
+such as \fBlmdb\fR or \fBbtree\fR; there is no need to support
concurrent access. The file is created if it does not exist. The \fBsmtp\fR(8)
daemon does not use this parameter directly, rather the cache is
implemented indirectly in the \fBtlsmgr\fR(8) daemon. This means that
.PP
.nf
.na
-smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
smtp_tls_session_cache_database = lmdb:/var/lib/postfix/smtp_scache
+smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
.fi
.ad
.PP
.na
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_sender_restrictions = reject_unknown_sender_domain,
- check_sender_access hash:/etc/postfix/access
+ check_sender_access lmdb:/etc/postfix/access
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/access" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH smtpd_service_name (default: smtpd)
The internal service that \fBpostscreen\fR(8) hands off allowed
connections to. In a future version there may be different
/etc/postfix/main.cf:
smtpd_tls_fingerprint_digest = sha256
smtpd_client_restrictions =
- check_ccert_access hash:/etc/postfix/access,
+ check_ccert_access lmdb:/etc/postfix/access,
reject
.sp
/etc/postfix/access:
.ad
.in -4
.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/access" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
+.PP
This feature is available in Postfix 2.5 and later.
.SH smtpd_tls_key_file (default: $smtpd_tls_cert_file)
File with the Postfix SMTP server RSA private key in PEM format.
.PP
.nf
.na
-smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtpd_tls_session_cache_database = lmdb:/var/lib/postfix/smtpd_scache
+smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
.fi
.ad
.PP
.PP
Specify zero or more "type:table" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
-until a match is found. If you use this
-feature with local files, run "\fBpostmap /etc/postfix/transport\fR"
-after making a change.
+until a match is found.
.PP
Pattern matching of domain names is controlled by the presence
or absence of "transport_maps" in the parent_domain_matches_subdomains
.PP
.nf
.na
-transport_maps = dbm:/etc/postfix/transport
-transport_maps = hash:/etc/postfix/transport
+transport_maps = lmdb:/etc/postfix/transport
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/transport" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH transport_minimum_delivery_slots (default: $default_minimum_delivery_slots)
A transport\-specific override for the default_minimum_delivery_slots
parameter value, where \fItransport\fR is the master.cf name of
until a match is found.
Note: these lookups are recursive.
.PP
-If you use this feature with indexed files, run "\fBpostmap
-/etc/postfix/virtual\fR" after changing the file.
-.PP
Examples:
.PP
.nf
.na
-virtual_alias_maps = dbm:/etc/postfix/virtual
-virtual_alias_maps = hash:/etc/postfix/virtual
+virtual_alias_maps = lmdb:/etc/postfix/virtual
.fi
.ad
+.PP
+Instead of lmdb:, some systems use cdb:, hash:, or dbm:.
+.PP
+Execute the command "postmap /etc/postfix/virtual" after you
+change the virtual file, to (re)build a default\-type indexed file.
+Execute "postmap \fItype\fR:/etc/postfix/virtual" to specify an
+explicit type.
+.PP
+The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf \-m".
+.PP
+Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay.
.SH virtual_alias_recursion_limit (default: 1000)
The maximal nesting depth of virtual alias expansion. Currently
the recursion limit is applied only to the left branch of the
.ad
.fi
The Postfix mail system uses optional tables for address
-rewriting, mail routing, or access control. These tables
-are usually in \fBdbm\fR or \fBdb\fR format.
+rewriting or mail routing. These tables are usually in
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified in POSIX regular
expression form. In this case, each input is compared against a
used in "user has moved to \fInew_location\fR" bounce messages.
Normally, the \fBrelocated\fR(5) table is specified as a text file
-that serves as input to the \fBpostmap\fR(1) command.
-The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-is used for fast searching by the mail system. Execute the command
-"\fBpostmap /etc/postfix/relocated\fR" to rebuild an indexed
-file after changing the corresponding relocated table.
+that serves as input to the \fBpostmap\fR(1) command to create
+an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/relocated\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/relocated\fR" to
+specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
.ad
.fi
The Postfix mail system uses optional tables for address
-rewriting, mail routing or policy lookup.
+rewriting or mail routing. These tables are usually in
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
The Postfix socketmap client expects TCP endpoint names of
the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
Alternatively, lookup tables can be specified as SQLite databases.
+To find out what types of lookup tables your Postfix system
+supports use the "\fBpostconf \-m\fR" command.
+
In order to use SQLite lookups, define an SQLite source as a lookup
table in main.cf, for example:
.nf
.fi
The Postfix mail system uses optional tables for address
rewriting or mail routing. These tables are usually in
-\fBdbm\fR or \fBdb\fR format. Alternatively, table lookups
-can be directed to a TCP server.
-
-To find out what types of lookup tables your Postfix system
-supports use the "\fBpostconf \-m\fR" command.
+\fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
+Alternatively, table lookups can be directed to a TCP server.
To test lookup tables, use the "\fBpostmap \-q\fR" command as
described in the SYNOPSIS above.
.SH "PROTOCOL DESCRIPTION"
\fBrelayhost\fR, or from the recipient domain.
.PP
Normally, the \fBtransport\fR(5) table is specified as a text file
-that serves as input to the \fBpostmap\fR(1) command.
-The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
-for fast searching by the mail system. Execute the command
-"\fBpostmap /etc/postfix/transport\fR" to rebuild an indexed
-file after changing the corresponding transport table.
+that serves as input to the \fBpostmap\fR(1) command to create
+an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/transport\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/transport\fR" to
+specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
mapping to rewrite header and envelope addresses in general.
Normally, the \fBvirtual\fR(5) alias table is specified as a text file
-that serves as input to the \fBpostmap\fR(1) command.
-The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-is used for fast searching by the mail system. Execute the command
-"\fBpostmap /etc/postfix/virtual\fR" to rebuild an indexed
-file after changing the corresponding text file.
+that serves as input to the \fBpostmap\fR(1) command to create
+an indexed file for fast lookup.
+
+Execute the command "\fBpostmap /etc/postfix/virtual\fR" to
+rebuild a default\-type indexed file after changing the text file,
+or execute "\fBpostmap \fItype\fB:/etc/postfix/virtual\fR" to
+specify an explicit type.
+
+The default indexed file type is configured with the
+default_database_type parameter. Depending on the platform this
+may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+\&':').
When the table is provided via other means such as NIS, LDAP
or SQL, the same lookups are done as for ordinary indexed files.
+Managing such databases is outside the scope of Postfix.
Alternatively, the table can be provided as a regular\-expression
map where patterns are given as regular expressions, or lookups
--- /dev/null
+.TH NBDB_REINDEXD 8
+.ad
+.fi
+.SH NAME
+nbdb_reindexd
+\-
+Postfix non\-Berkeley\-DB migration
+.SH "SYNOPSIS"
+.na
+.nf
+\fBnbdb_reindexd\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+\fINOTE: This service should be enabled only temporarily to
+generate most of the non\-Berkeley\-DB indexed files that Postfix
+needs. Leaving this service enabled may expose the system to
+privilege\-escalation attacks.\fR
+
+The nbdb_reindexd(8) server handles requests to generate
+a non\-Berkeley\-DB indexed database file for an existing Berkeley
+DB database (example: "hash:/path/to/file" or
+"btree:/path/to/file"). It implements the service by running
+the postmap(1) or postalias(1) command with appropriate
+privileges.
+
+The service reports a success status when the non\-Berkeley\-DB
+indexed file already exists. This can happen when multiple clients
+make the same request. When one request is completed successfully,
+the service also reports success for the other requests.
+
+This service enforces the following safety policy:
+.IP \(bu
+The legacy Berkeley DB indexed file must exist (file name ends in
+".db"). The nbdb_reindexd(8) service will use the owner"s (uid,
+gid) of this file, when it runs postmap(1) or postalias(1). It
+also uses the (uid,gid) for a number of safety checks as
+described next.
+.IP \(bu
+The non\-indexed source file must exist (file name without
+".db" suffix). This file is needed as input for postmap(1)
+or postalias(1). The file must be owned by "root" or by the
+above uid, and must not allow "group" or "other" write access.
+.IP \(bu
+The parent directory must be owned by "root" or by the above uid,
+and it must not allow "group" or "other" write access.
+.IP \(bu
+Additionally, the "non_bdb_migration_allow_root_prefixes"
+parameter limits the source file directory prefixes that are
+allowed when this service needs to run postmap(1) or postalias(1)
+with "root" privileges.
+.IP \(bu
+A similar parameter, "non_bdb_migration_allow_user_prefixes",
+limits the source file directory prefixes that are allowed when
+this service needs to run postmap(1) or postalias(1) as an
+unprivileged user.
+.SH "SECURITY"
+.na
+.nf
+.ad
+.fi
+The nbdb_reindexd(8) server is security sensitive. It accepts
+requests only from processes that can access sockets under
+$queue_directory/private (i.e., processes that run with "root"
+or "mail_owner" (usually, postfix) privileges).
+
+The threat is therefore a corrupted Postfix daemon process that
+wants to elevate privileges, by sending requests with crafted
+pathnames, and racing against the service by quickly swapping
+files or directories, hoping that Postfix will be tricked to
+overwrite a sensitive file with attacker\-controlled data.
+
+When the service runs postmap(1) or postalias(1) as
+"root", such racing attacks should not be possible if
+non_bdb_migration_allow_root_prefixes specifies only prefixes
+that are already trusted.
+
+This service could block all requests with crafted pathnames,
+if given complete information about all lookup tables that are
+referenced through Postfix configuration files. Unfortunately
+that information was not available at the time that this program
+was needed.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems and transactions are logged to syslogd(8) or
+postlogd(8). If an attempt to create an index file fails, this
+service will attempt to delete the incomplete file.
+.SH "CONFIGURATION PARAMETERS"
+.na
+.nf
+.ad
+.fi
+Changes to main.cf are not picked up automatically, as
+nbdb_reindexd(8) processes are long\-lived. Use the command
+"postfix reload" after a configuration change.
+
+The text below provides only a parameter summary. See
+postconf(5) for more details including examples.
+.SH "SERVICE-SPECIFIC CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBnon_bdb_migration_level (disable)\fR"
+The non\-Berkeley\-DB migration service level.
+.IP "\fBnon_bdb_migration_allow_root_prefixes (see 'postconf -d non_bdb_migration_allow_root_prefixes' output)\fR"
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with "root" privilege.
+.IP "\fBnon_bdb_migration_allow_user_prefixes (see 'postconf -d non_bdb_migration_allow_user_prefixes' output)\fR"
+A list of trusted pathname prefixes that must be matched when
+the non\-Berkeley\-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with non\-root privilege.
+.SH "MISCELLANEOUS CONTROLS"
+.na
+.nf
+.ad
+.fi
+.IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+The default location of the Postfix main.cf and master.cf
+configuration files.
+.IP "\fBprocess_id (read\-only)\fR"
+The process ID of a Postfix command or daemon process.
+.IP "\fBprocess_name (read\-only)\fR"
+The process name of a Postfix command or daemon process.
+.IP "\fBsyslog_facility (mail)\fR"
+The syslog facility of Postfix logging.
+.IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+A prefix that is prepended to the process name in syslog
+records, so that, for example, "smtpd" becomes "prefix/smtpd".
+.IP "\fBservice_name (read\-only)\fR"
+The master.cf service name of a Postfix daemon process.
+.SH "SEE ALSO"
+.na
+.nf
+postfix\-non\-bdb(1), migration management
+postconf(5), configuration parameters
+postlogd(8), Postfix logging
+syslogd(8), system logging
+.SH "README FILES"
+.na
+.nf
+.ad
+.fi
+Use "\fBpostconf readme_directory\fR" or
+"\fBpostconf html_directory\fR" to locate this information.
+.na
+.nf
+NON_BERKELEYDB_README, Non\-Berkeley\-DB migration guide
+.SH "LICENSE"
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH HISTORY
+.ad
+.fi
+.ad
+.fi
+This service was introduced with Postfix version 3.11.
+.SH "AUTHOR(S)"
+.na
+.nf
+Wietse Venema
+porcupine.org
/*) lynx -width=256 -dump file://$i;;
*) lynx -width=256 -dump file://`pwd`/$i;;
esac
-done | grep -v 'file:///'
+done | grep -E -v '(file|https?)://'
}
s;\bautho[-</bB>]*\n*[ <bB>]*rized_flush_users\b;<a href="postconf.5.html#authorized_flush_users">$&</a>;g;
s;\bautho[-</bB>]*\n*[ <bB>]*rized_mailq_users\b;<a href="postconf.5.html#authorized_mailq_users">$&</a>;g;
- s;\bautho[-</bB>]*\n*[ <bB>]*rized_submit_users\b;<a href="postconf.5.html#authorized_submit_users">$&</a>;g;
+ s;\bautho[-</bB>]*\n*[ <bB>]*rized_sub[-</bB>]*\n*[ <bB>]*mit_users\b;<a href="postconf.5.html#authorized_submit_users">$&</a>;g;
s;\bautho[-</bB>]*\n*[ <bB>]*rized_verp_clients\b;<a href="postconf.5.html#authorized_verp_clients">$&</a>;g;
s;\bdebugger_command\b;<a href="postconf.5.html#debugger_command">$&</a>;g;
s;\b2bounce_notice_recipi[-</bB>]*\n*[ <bB>]*ent\b;<a href="postconf.5.html#2bounce_notice_recipient">$&</a>;g;
s;\benable_threaded_bounces\b;<a href="postconf.5.html#enable_threaded_bounces">$&</a>;g;
s;\bknown_tcp_ports\b;<a href="postconf.5.html#known_tcp_ports">$&</a>;g;
+ s;\bnon_bdb_migra[-</Bb>]*\n* *[<Bb>]*tion_[-</Bb>]*\n* *[<Bb>]*allow_root_prefixes\b;<a href="postconf.5.html#non_bdb_migration_allow_root_prefixes">$&</a>;g;
+ s;\bnon_bdb_migra[-</Bb>]*\n* *[<Bb>]*tion_[-</Bb>]*\n* *[<Bb>]*allow_user_pre[-</Bb>]*\n* *[<Bb>]*fixes\b;<a href="postconf.5.html#non_bdb_migration_allow_user_prefixes">$&</a>;g;
+ s;\bnon_bdb_migration_level\b;<a href="postconf.5.html#non_bdb_migration_level">$&</a>;g;
+ s;\bnon_bdb_custom_mapping\b;<a href="postconf.5.html#non_bdb_custom_mapping">$&</a>;g;
+ s;\bnon_bdb_migration_service_name\b;<a href="postconf.5.html#non_bdb_migration_service_name">$&</a>;g;
+
# Transport-dependent magical parameters.
# Note: Accept non-italic "transport" prefix for content that has been
# converted from troff in C sources. Tooling doesn't support bold+italic.
s/[<bB>]*lmtp[<\/bB>]*\(8\)/<a href="lmtp.8.html">$&<\/a>/g;
s/[<bB>]*local[<\/bB>]*\(8\)/<a href="local.8.html">$&<\/a>/g;
s/[<bB>]*mas[-<\/bB>]*\n* *[<bB>]*ter[<\/bB>]*\(8\)/<a href="master.8.html">$&<\/a>/g;
+ s/[<bB>]*nbdb_reindexd[<\/bB>]*\(8\)/<a href="nbdb_reindexd.8.html">$&<\/a>/g;
s/[<bB>]*pickup[<\/bB>]*\(8\)/<a href="pickup.8.html">$&<\/a>/g;
s/[<bB>]*pipe[<\/bB>]*\(8\)/<a href="pipe.8.html">$&<\/a>/g;
s/[<bB>]*postlogd[<\/bB>]*\(8\)/<a href="postlogd.8.html">$&<\/a>/g;
s/[<bB>]*triv[-<\/bB>]*\n* *[<bB>]*ial-[<\/bB>]*\n* *[<bB>]*re[-<\/bB>]*\n*[ <bB>]*write[<\/bB>]*\(8\)/<a href="trivial-rewrite.8.html">$&<\/a>/g;
s/[<bB>]*mailq[<\/bB>]*\(1\)/<a href="mailq.1.html">$&<\/a>/g;
s/[<bB>]*newaliases[<\/bB>]*\(1\)/<a href="newaliases.1.html">$&<\/a>/g;
- s/[<bB>]*postalias[<\/bB>]*\(1\)/<a href="postalias.1.html">$&<\/a>/g;
+ s/[<bB>]*postal[-<\/bB>]*\n* *[<bB>]*ias[<\/bB>]*\(1\)/<a href="postalias.1.html">$&<\/a>/g;
s/[<bB>]*postcat[<\/bB>]*\(1\)/<a href="postcat.1.html">$&<\/a>/g;
s/[<bB>]*post[-<\/bB>]*\n*[ <bB>]*conf[<\/bB>]*\(1\)/<a href="postconf.1.html">$&<\/a>/g;
s/[<bB>]*postdrop[<\/bB>]*\(1\)/<a href="postdrop.1.html">$&<\/a>/g;
s/[<bB>]*post[-<\/bB>]*\n* *[<bB>]*fix[<\/bB>]*\(1\)/<a href="postfix.1.html">$&<\/a>/g;
s/[<bB>]*post[-<\/bB>]*\n* *[<bB>]*fix-tls[<\/bB>]*\(1\)/<a href="postfix-tls.1.html">$&<\/a>/g;
+ s/[<bB>]*postfix-non-bdb[<\/bB>]*\(1\)/<a href="postfix-non-bdb.1.html">$&<\/a>/g;
s/[<bB>]*postkick[<\/bB>]*\(1\)/<a href="postkick.1.html">$&<\/a>/g;
s/[<bB>]*postlock[<\/bB>]*\(1\)/<a href="postlock.1.html">$&<\/a>/g;
s/[<bB>]*postlog[<\/bB>]*\(1\)/<a href="postlog.1.html">$&<\/a>/g;
# Hyperlink README document names
- s/\b([A-Z][A-Z0-9_]*)[-]*\n*[ ]*([A-Z0-9_]*_README)\b/<a href="$1$2.html">$&<\/a>/g;
+ s/\b(([A-Z][A-Z0-9_]*)[-]*\n*[ ]*([A-Z0-9_]*_README))(#[-a-zA-Z0-9_]+)?\b/<a href="$2$3.html$4">$1<\/a>/g;
s/\bINSTALL\b/<a href="$&.html">$&<\/a>/g;
s/\bOVERVIEW\b/<a href="$&.html">$&<\/a>/g;
s/\btype:table\b/<a href="DATABASE_README.html">type:table<\/a>/g;
s;\bpostlog_service_name\b;<a href="postconf.5.html#postlog_service_name">$&</a>;g;
s;\bpostlogd_watchdog_timeout\b;<a href="postconf.5.html#postlogd_watchdog_timeout">$&</a>;g;
- s;\blocal_login_sender_maps\b;<a href="postconf.5.html#local_login_sender_maps">$&</a>;g;
+ s;\blocal_[-</bB>]*\n*[ <bB>]*login_[-</bB>]*\n*[ <bB>]*sender_maps\b;<a href="postconf.5.html#local_login_sender_maps">$&</a>;g;
s;\bempty_address_local_login_sender_maps_lookup_key\b;<a href="postconf.5.html#empty_address_local_login_sender_maps_lookup_key">$&</a>;g;
s;\buse_srv_lookup\b;<a href="postconf.5.html#use_srv_lookup">$&</a>;g;
s/\b(postfix *tls)\b/<a href="postfix-tls.1.html">$1<\/a>/g;
s/\b(local\s*aliasing)\b/<a href="ADDRESS_REWRITING_README.html#aliases">$1<\/a>/g;
s/\b(virtual\s*aliasing)\b/<a href="ADDRESS_REWRITING_README.html#virtual">$1<\/a>/g;
+ s/\b(postfix non-bdb)\b/<a href="postfix-non-bdb.1.html">$1<\/a>/g;
+ #s/\b(postfix tls)\b/<a href="postfix-tls.1.html">$1<\/a>/g;
# Hyperlink map types.
<tr> <td>config_directory</td> <td>/etc/postfix</td> </tr>
-<tr> <td>default_database_type</td> <td>lmdb or hash</td> </tr>
+<tr> <td>default_database_type</td> <td>lmdb, cdb, or hash</td> </tr>
<tr> <td>default_cache_db_type</td> <td>lmdb or btree</td> </tr>
<td>/etc/postfix</td> </tr>
<tr> <td>DEF_DB_TYPE</td> <td>default_database_type</td>
-<td>lmdb or hash</td> </tr>
+<td>lmdb, cdb, or hash</td> </tr>
<tr> <td>DEF_CACHE_DB_TYPE</td> <td>default_cache_db_type</td>
<td>lmdb or btree</td> </tr>
<tr> <td>DEF_SENDMAIL_PATH</td> <td>sendmail_path</td>
<td>/usr/sbin/sendmail</td> </tr>
+<tr> <td>DEF_SHLIB_DIR</td> <td>shlib_directory</td>
+<td>/usr/lib/postfix</td> </tr>
+
</table>
</blockquote>
<p> Note: the data_directory parameter (for caches and pseudo-random
-numbers) was introduced with Postfix version 2.5. </p>
+numbers) was introduced with Postfix version 2.5; shlib_directory
+(for shared-library objects and database plugins) with Postfix
+version 3.0. </p>
<h3><a name="build_other">4.7 - Overriding other compile-time
features</a></h3>
<tr> <td> </td> <td> -DNO_DB </td> <td> Do not build with Berkeley
DB support. By default, Berkeley DB support is compiled in on
-platforms that are known to support this feature. If you override
+platforms that have historically supported this feature. If you override
this, then you probably should also override default_database_type
or DEF_DB_TYPE as described in section 4.6. </td> </tr>
<p> First, be sure to update the text file with aliases for root,
postmaster and "postfix" that forward mail to a real person. Postfix
-has a sample aliases file /etc/postfix/aliases that you can adapt
-to local conditions. </p>
+has a sample aliases file /etc/postfix/aliases that you can copy
+and adapt to local conditions. /p>
<blockquote>
<pre>
</pre>
</blockquote>
+<p> The form "postalias /etc/aliases" builds a default-type indexed
+file. Use "postalias <i>type</i>:/etc/aliases" to specify an explicit
+type (it should match the type in the output from "postconf -x
+alias_maps"). </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<h2><a name="hamlet">11 - To chroot or not to chroot</a></h2>
<p> Postfix daemon processes can be configured (via master.cf) to
../html/MONGODB_README.html \
../html/MULTI_INSTANCE_README.html \
../html/MYSQL_README.html ../html/NFS_README.html \
+ ../html/NON_BERKELEYDB_README.html \
../html/OVERVIEW.html \
../html/PACKAGE_README.html ../html/PCRE_README.html \
../html/PGSQL_README.html \
../README_FILES/MONGODB_README \
../README_FILES/MULTI_INSTANCE_README \
../README_FILES/MYSQL_README ../README_FILES/NFS_README \
+ ../README_FILES/NON_BERKELEYDB_README \
../README_FILES/OVERVIEW \
../README_FILES/PACKAGE_README ../README_FILES/PCRE_README \
../README_FILES/PGSQL_README \
../html/NFS_README.html: NFS_README.html
$(DETAB) $? | $(POSTLINK) >$@
+../html/NON_BERKELEYDB_README.html: NON_BERKELEYDB_README.html
+ $(DETAB) $? | $(POSTLINK) >$@
+
../html/OVERVIEW.html: OVERVIEW.html
$(DETAB) $? | $(POSTLINK) >$@
../README_FILES/NFS_README: NFS_README.html
$(DETAB) $? | $(HT2READ) >$@
+../README_FILES/NON_BERKELEYDB_README: NON_BERKELEYDB_README.html
+ $(DETAB) $? | $(HT2READ) >$@
+
../README_FILES/OVERVIEW: OVERVIEW.html
$(DETAB) $? | $(HT2READ) >$@
--- /dev/null
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "https://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix Non-Berkeley-DB migration</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<link rel='stylesheet' type='text/css' href='postfix-doc.css'>
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+Non-Berkeley-DB migration</h1>
+
+<hr>
+
+<h2> Table of contents </h2>
+
+<ul>
+
+<li> <a href="#intro">Introduction </a>
+
+<li> <a href="#background">Background </a>
+
+<li> <a href="#build-conf">Skip this if not building Postfix from
+source, or if your system still supports Berkeley DB </a>
+
+<li> <a href="#level-overview"> Migration support level overview </a>
+
+<li> <a href="#disable"> Level 'disable': manual migration </a>
+
+<li> <a href="#enable-redirect"> Level 'enable-redirect': database
+aliasing </a>
+
+<li> <a href="#enable-reindex"> Level 'enable-reindex': redirect
+and automatically generate non-Berkeley-DB indexed files </a>
+
+<li> <a href="#addr-errors">Addressing errors with automatic indexed
+file generation </a>
+
+<li> <a href="#mailman">Appendix: Mailman integration </a>
+
+</ul>
+
+<h2> <a name="intro">Introduction </a> </h2>
+
+<p> (Please see the <a href="#mailman">Appendix</a> for Mailman
+integration tips.) </p>
+
+<p> After running the same Postfix configuration for a decade or
+more, there is a rude awakening when you update the OS to a newer
+version that has deleted its support for Berkeley DB. Postfix
+programs fail to open all hash: and btree: tables with messages
+like this: </p>
+
+<blockquote>
+<pre>
+Berkeley DB support for 'hash:/etc/postfix/virtual' is not available
+for this build; see https://www.postfix.org/NON_BERKELEYDB_README.html
+for alternatives
+</pre>
+</blockquote>
+
+<p> This document comes to the rescue, with strategies to migrate
+an existing Postfix configuration that uses Berkeley DB hash: and
+btree: database files, to an OS distribution that has removed
+Berkeley DB support, with a Postfix configuration that uses lmdb: (or
+a combination of cdb: and lmdb:). <p>
+
+<p> By the way, you don't have to wait until Berkeley DB support
+is removed; your can proactively use the steps described here on a
+system that still has Berkeley DB, to migrate a Postfix configuration
+from Berkeley DB to lmdb: (or a combination of cdb: and lmdb:).
+
+<h2> <a name="background">Background </a> </h2>
+
+<p> Historically, Postfix has used Berkeley DB hash: and btree: for
+key-value stores, as indicated in the "With Berkeley DB" table
+column below. In a world without Berkeley DB, good replacements are
+cdb: and lmdb: as indicated in the "No Berkeley DB" column. </p>
+
+<blockquote>
+
+<table border="1">
+
+<tr> <th> Purpose </th> <th> With Berkeley DB </th> <th> No Berkeley
+DB </th> </tr>
+
+<tr> <td> Mostly-static data such as aliases, transport_maps,
+access tables </td> <td> default_database_type=hash </td> <td>
+default_database_type=lmdb or default_database_type=cdb </td>
+</tr>
+
+<tr> <td> Dynamic caches maintained by postscreen(8), verify(8),
+tlsmgr(8) </td> <td> default_cache_db_type=btree </td> <td>
+default_cache_db_type=lmdb </td> </tr>
+
+</table>
+
+</blockquote>
+
+<p> The default values for default_database_type and default_cache_db_type
+may be specified at build time (see the <a href="#build-conf">section
+below</a>, and they may be changed later by editing main.cf, for
+example with the postconf(1) command.) </p>
+
+<p> The sections that follow present three migration strategies
+with different levels of assistance by tooling that was developed
+for Postfix 3.11 and later. </p>
+
+<h2> <a name="build-conf"> Skip this if not building Postfix from
+source, or if your system still supports Berkeley DB. </a> </h2>
+
+<p> <a href="#level-overview">Click here to skip to the next section</a>.
+
+<p> On systems that have removed Berkeley DB support, run "<tt>make
+makefiles</tt>" with a CCARGS value that (also) contains "-DNO_DB",
+and specify appropriate values for default_database_type (lmdb or cdb)
+and default_cache_db_type (lmdb). </p>
+
+<p> In the examples below, the "<tt>...</tt>" are place holders any
+dependencies that you build Postfix with, such as CDB, LDAP, LMDB,
+MySQL/MariaDB, OpenSSL, SASL, and so on.
+
+<p> Example 1: use lmdb: for both default_database_type (read-mostly
+lookup tables) and default_cache_db_type (read-write caches). Terminal
+input is <b>bold</b>, output is <tt>normal</tt> font. </p>
+
+<blockquote> <pre>
+$ <b>make makefiles CCARGS="-DNO_DB ..." \
+ default_database_type=lmdb \
+ default_cache_db_type=lmdb ... \
+ AUXLIBS...</b>
+</pre>
+</blockquote>
+
+<p> Example 2: alternative form that produces the same result.
+</p>
+
+<blockquote>
+<pre>
+$ <b>export CCARGS="-DNO_DB ..."</b>
+$ <b>export default_database_type=lmdb</b>
+$ <b>export default_cache_db_type=lmdb</b>
+$ <b>export AUXLIBS...</b>
+...
+$ <b>make makefiles</b>
+</pre>
+</blockquote>
+
+<p> Another alternative is to use cdb for default_database_type
+(read-mostly lookup tables) and lmdb for default_cache_db_type
+(read-write caches). </p>
+
+<h2> <a name="level-overview"> Migration support level overview </a> </h2>
+
+<p> The goal of the migration is clear: stop using hash: and btree:,
+and use lmdb: or cdb: instead. If your configuration is simple or
+if you are familiar with Postfix configuration, a few "<tt>grep</tt>"
+commands will find all the problems, and a few edits will be easy
+to make. </p>
+
+<p> If, on the other hand, you are not familiar with the details of your
+Postfix configuration, then this document provides options where Postfix
+can help. </p>
+
+<p> Postfix 3.11 introduces multiple levels of migration support.
+You can use the command "<tt>postfix non-bdb status</tt>" to view
+the migration support level. This is what the default should look
+like (terminal input is <tt><b>bold</b></tt>, output is <tt>normal</tt>
+font): </p>
+
+<blockquote>
+<pre>
+# <b>postfix non-bdb status</b>
+disable
+</pre>
+</blockquote>
+
+<p> In increasing order, the support levels are: </p>
+
+<dl>
+
+<dt> <a href="#disable">disable</a> (manual migration) </dt>
+
+<dd> <p> You start up Postfix, watch the logging when Postfix
+programs fail to open a hash: or btree: table, edit Postfix
+configuration files to use lmdb: or cdb:, then run postmap(1) or
+postalias(1) commands to create lmdb: or cdb: indexed database
+files. Use this option if you are familiar with Postfix configuration.
+</p>
+
+<p> This will not fix the integration with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software that are broken
+when they want to use "<tt>postmap hash:<i>/path/to/file</i></tt>".
+Mailman uses this to maintain a table with mailing list contact
+addresses. For that, you need to use the next-up level. </p> </dd>
+
+<dt> <a href="#enable-redirect">enable-redirect</a> (database
+aliasing) </dt>
+
+<dd> <p> This level implicitly redirects a request to access
+hash:<i>/path/to/file</i> to $default_database_type:<i>/path/to/file</i>,
+and redirects a request to access a btree:<i>/path/to/file</i> to
+$default_cache_db_type:<i>/path/to/file</i>. </p>
+
+<p> This still requires manually running postmap(1) or postalias(1)
+commands, but "fixes" the integration with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software when they want
+to use "<tt>postmap hash:<i>/path/to/file</i>"</tt>, and Berkeley
+DB support is not available. Such commands will implicitly create
+a new lmdb: or cdb: indexed database file, depending on the
+default_database_type value. </p> </dd>
+
+<dt> <a href="#enable-reindex"> enable-reindex </a> (aliasing, plus
+running postmap(1) or postalias(1))</dt>
+
+<dd> <p> This level implements "<tt>enable-redirect</tt> (database
+aliasing)", and also runs the postmap(1) or postalias(1) command to create
+a new lmdb or cdb indexed database file. This uses the nbdb_reindexd(8)
+daemon. </p>
+
+</dl>
+
+<p> The levels <a href="#enable-redirect">enable-redirect</a> and
+<a href="#enable-reindex"> enable-reindex </a> leave some technical
+debt: configurations that still say hash: or btree: (even if
+they use lmdb: or cdb: behind the scene). </p>
+
+<ul>
+
+<li> <p> Using these levels gives you extra time to prepare for a
+long-term configuration change that replaces hard-coded instances of hash:
+with the value of default_database_type, and that replaces btree: with
+the value of default_cache_db_type. </p>
+
+<li> <p> Depending on your use of other software that wants to use
+postmap(1) or postalias(1) commands, you may have to permanently
+the leave the <a href="#enable-redirect">enable-redirect</a> level
+active. </p>
+
+</ul>
+
+<p> After this overview, the sections that follow will go into more
+detail. </p>
+
+<h2> <a name="disable"> Level 'disable': manual migration </a> </h2>
+
+<p> To disable all non-Berkeley-DB migration features use
+the "<tt>postfix non-bdb</tt>" command:
+
+<blockquote>
+<pre>
+# <b>postfix non-bdb disable</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> This will edit main.cf to remove a non_bdb_migration_level setting
+and the level revert to its implicit default (disable), and will edit
+master.cf to remove an entry for the <tt>reindex</tt> service. </p>
+
+<p> This setting will cause problems with Mailman versions from
+before <a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c13214f43c7d32d">gitlab
+commit 8fa56b72</a> (May 2025) and other software that wants to use
+"<tt>postmap hash:<i>/path/to/file</i></tt>" (or similar postalias
+commands), and Berkeley DB support is no longer available. In that
+case, you will need the "<tt>enable-redirect</tt>" migration support
+level.
+
+<p> A manual migration process goes like this: </p>
+
+<ul>
+
+<li> <p> Stop Postfix. </p>
+
+<li> <p> Make lmdb: the default for both default_database_type
+(read-mostly lookup tables) and default_cache_db_type (read-write
+caches): </p>
+
+<pre>
+# <b>postconf default_database_type=lmdb default_cache_db_type=lmdb</b>
+</pre>
+
+<li> <p> Alternatively, make cdb: the default for default_database_type
+(read-mostly lookup tables) and lmdb: the default for
+default_cache_db_type (read-write caches): </p>
+
+<pre>
+# <b>postconf default_database_type=cdb default_cache_db_type=lmdb</b>
+</pre>
+
+<li> <p> Look for hash: and btree: references in Postfix
+configuration files. Instead of <tt>/etc/postfix</tt> use the pathname
+in the output from "<tt>postconf -x config_directory</tt>". </p>
+
+<pre>
+# <b>grep -E -r '(hash|btree):/' /etc/postfix</b>
+</pre>
+
+<li> <p> For each instance in the "<tt>grep</tt>" output : </p>
+
+<ul>
+
+<li> <p> Edit the configuration file and replace "hash" with "lmdb"
+or "cdb" (use the same value as the output from "<tt><b>postconf
+-hx default_database_type</b></tt>") and replace "btree" with "lmdb".
+</p>
+
+<li> <p> If this instance has no source file (only the ".db" file
+exists), proceed with the next instance of "<tt>grep</tt>" output.
+</p>
+
+<li> <p> If this instance appears in the output from "<tt><b>postconf
+-hPPx '*/*/alias_maps' | sort -u</b></tt>", run the postalias(1)
+command. If this instance is like "<tt>lmdb:/path/to/source</tt>":
+</p>
+
+<pre>
+# <b>postalias lmdb:/path/to/source</b>
+</pre>
+
+<p> Instead of "lmdb:" use "cdb:" if the instance is like
+"<tt>cdb:/path/to/source</tt>". </p>
+
+<li> <p> Otherwise, run the postmap(1) command. If this instance
+is like "<tt>lmdb:/path/to/source</tt>": </p>
+
+<pre>
+# <b>postmap lmdb:/path/to/source</b>
+</pre>
+
+<p> Instead of "lmdb:" use "cdb:" if this instance is like
+"<tt>cdb:/path/to/source</tt>". </p>
+
+</ul>
+
+<li> <p> Start Postfix, watch the log for warnings about files that
+cannot be opened, find the configuration file that still uses "hash"
+or "btree", and repeat the steps above. </p>
+
+<li> <p> It is now safe to delete the unused ".db" files. </p>
+
+</ul>
+
+<h2> <a name="enable-redirect"> Level 'enable-redirect': database
+aliasing </a> </h2>
+
+<p> To enable this migration support level, use: </p>
+
+<blockquote>
+<pre>
+# <b>postfix non-bdb enable-redirect</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p> This <tt>postfix non-bdb</tt>" command edits main.cf to enable
+redirection (aliasing) from Berkeley DB types "hash" and "btree"
+to the non-Berkeley-DB types specified with $default_database_type
+and $default_cache_db_type. Custom redirection may be configured
+with non_bdb_custom_mapping. This command also edits master.cf to
+remove an unused <tt>nbdb_reindex</tt> service entry. </p>
+
+<p> This migration support level will not automatically create
+non-Berkeley-DB indexed database files. Instead, Postfix programs
+will log an error as they fail to open an indexed database file,
+and will leave it to the system administrator to run postmap(1) or
+postalias(1) to create that file. </p>
+
+<p> For each instance of "<tt>hash:/path/to/source</tt>" or
+"<tt>btree:/path/to/source</tt>" that requires manually running
+postmap(1) or postalias(1): </p>
+
+<ul>
+
+<li> <p> If this instance appears in the output from "<tt><b>postconf
+-hPPx '*/*/alias_maps' | sort -u</b></tt>", run the postalias(1)
+command. If this instance is like "<tt>lmdb:/path/to/source</tt>":
+</p>
+
+<pre>
+# <b>postalias lmdb:/path/to/source</b>
+</pre>
+
+<p> Instead of "lmdb:" use "cdb:" if the instance is like
+"<tt>cdb:/path/to/source</tt>". </p>
+
+<li> <p> Otherwise, run the postmap(1) command. If this instance
+is like "<tt>lmdb:/path/to/source</tt>": </p>
+
+<pre>
+# <b>postmap lmdb:/path/to/source</b>
+</pre>
+
+<p> Instead of "lmdb:" use "cdb:" if this instance is like
+"<tt>cdb:/path/to/source</tt>". </p>
+
+</ul>
+
+<p> This migration support level will fix problems with Mailman
+versions from before May 2025 and other software that wants to use
+"<tt>postmap hash:<i>/path/to/file</i></tt>". With database
+redirection, such commands will implicitly create an indexed file
+for $default_database_type:<i>/path/to/file</i> (similar aliasing
+happens for postalias commands). </p>
+
+<p> The command "<tt>postfix non-bdb enable-redirect</tt>" will
+refuse to make any changes when default_database_type or
+default_cache_db_type specify a hash: or btree: type.
+
+<h2> <a name="enable-reindex"> Level 'enable-reindex': redirect and
+automatically generate non-Berkeley-DB indexed files </a> </h2>
+
+<p> <i> NOTE: this level should be used only temporarily to generate
+most of the non-Berkeley-DB indexed files that Postfix needs.
+Leaving this enabled may expose the system to privilege-escalation
+attacks. There are no security concerns for using enable-redirect.
+</i> </p>
+
+<p> To enable this migration support level, use: </p>
+
+<blockquote>
+<pre>
+# <b>postfix non-bdb enable-reindex</b>
+# <b>postfix reload</b>
+</pre>
+</blockquote>
+
+<p>This postfix non-bdb command edits main.cf to set the non-Berkeley-DB
+migration support level, and master.cf to add or replace an
+<tt>nbdb-reindex</tt> service entry. </p>
+
+<p> The resulting configuration implements not only the functionality
+of <a href="#enable-redirect"> enable-redirect</a>, but also
+automatically creates a non-Berkeley-DB indexed database file when
+a daemon program wants to access a file that does not exist. This
+uses the nbdb_reindexd(8) daemon to run postmap(1) or postalias(1)
+commands for databases that satisfy basic requirements to block
+privilege-escalation attacks. The number of requirements is large,
+but mainly, database files and their parent directory must not allow
+write access for group or other users, and their pathnames must
+match a list of trusted directory prefixes. The complete list of
+requirements is documented in nbdb_reindexd(8). <p>
+
+This command immediately generates non-Berkeley-DB indexed files
+for command-line programs that lack privileges to send requests to
+the nbdb_reindexd(8) indexing server. This applies to "hash:" and
+"btree:" tables that are used by postqueue(1) and sendmail(1) as
+configured with authorized_flush_users and authorized_mailq_users,
+and used by sendmail(1) and postdrop(1) as configured with
+authorized_submit_users and local_login_sender_maps. </p>
+
+<p> The command "<tt>postfix non-bdb enable-reindex</tt>" will
+refuse to make any changes when default_database_type or
+default_cache_db_type specify a hash: or btree: type.
+
+<p> The nbdb_reindexd(8) daemon will log when it successfully runs
+a postmap(1) or postalias(1) command. Examples, for a system with
+"<tt>default_database_type = lmdb</tt>": </p>
+
+<blockquote>
+<pre>
+successfully executed 'postmap lmdb:/etc/postfix/transport' as uid 0
+successfully executed 'postalias lmdb:/etc/aliases' as uid 0
+</pre>
+</blockquote>
+
+<p> See the section "<a href="addr-errors">Addressing errors
+with automatic indexed file generation</a>" for the most likely
+errors that Postfix programs may log. </p>
+
+<p> Once there are no more errors from Postfix programs for about
+24 hours, turn off automatic index generation by reducing the support
+level to <tt>enable-redirect</tt> with: </p>
+
+<blockquote>
+<pre>
+# postfix non-bdb enable-redirect
+# postfix reload
+</pre>
+</blockquote>
+
+<h2> <a name="addr-errors">Addressing errors with automatic
+indexed file generation </a> </h2>
+
+<h3> Unexpected pathname errors </h3>
+
+<p> Depending on the location of your Postfix lookup tables, Postfix
+programs may log a request to add a trusted directory to the
+directories listed with non_bdb_migration_allow_root_prefixes or
+non_bdb_migration_allow_user_prefixes. </p>
+
+<p> Example, with line breaks added for readability: </p>
+
+<blockquote>
+<pre>
+could not execute command 'postmap lmdb:/path/to/file': table
+/path/to/file has an unexpected pathname;
+
+to allow automatic indexing as root, append its parent directory
+to the non_bdb_migration_allow_root_prefixes setting (current setting
+is: "/etc /usr/local/etc");
+
+alternatively, execute the failed command by hand
+</pre>
+</blockquote>
+
+<p> You have two options: </p>
+
+<ol>
+
+<li> <p> If you think that the suggested change is safe, update the
+setting as proposed and execute "<tt>postfix reload</tt>". </p>
+
+<li> <p> Alternatively, you can execute the failed postmap(1) or
+postalias(1) command by hand, and Postfix will not log the same error
+again. </p>
+
+</ol>
+
+<p> A similar request may be logged when a file needs to be indexed as
+a non-root user. </p>
+
+<h3> Unexpected file or directory owner or permissions </h3>
+
+<p> Other errors may be logged when a database file or directory
+has an unexpected owner, or when it is writable by group or by other
+users. </p>
+
+<p> Example with line breaks added for readability: </p>
+
+<blockquote>
+<pre>
+could not execute command 'postmap lmdb:/path/to/file': legacy
+indexed file '/path/to/file.db' is owned by uid '0', but parent
+directory '/path/to' is owned or writable by other user;
+
+to allow automatic indexing, correct the ownership or permissions;
+
+alternatively, execute the failed command by hand
+</pre>
+</blockquote>
+
+<p> Again, you have two options: </p>
+
+<ol>
+
+<li> <p> Fix the ownership or permission error. </p>
+
+<li> <p> Execute the failed postmap(1) or postalias(1) command by
+hand, and Postfix will not log the same error again. </p>
+
+</ol>
+
+<p> Once there are no more errors from Postfix programs for about
+24 hours, turn off automatic index generation by reducing the
+support level to <tt>enable-redirect</tt> with: </p>
+
+<blockquote>
+<pre>
+# postfix non-bdb enable-redirect
+# postfix reload
+</pre>
+</blockquote>
+
+<h2> <a name="mailman">Appendix: Mailman integration </a> </h2>
+
+<p> This section has instructions to migrate an existing Mailman
+configuration that wants to use commands like "postmap
+hash:<i>/path/to/file</i>". Mailman uses such commands to maintain
+tables with mailing list contact addresses and domain names. This
+will break on systems that no longer have Berkeley DB support. </p>
+
+<p> Solutions: </p>
+
+<ul>
+
+<li> <p> (Not recommended) Upgrade to a Mailman version that contains
+<a
+href="https://gitlab.com/mailman/mailman/-/commit/8fa56b72dccd318c171b7f373c1321
+4f43c7d32d">gitlab commit 8fa56b72</a> (May 2025). Unfortunately,
+this has not yet been widely adopted by OS distributions. </p>
+
+<li> <p> Avoid Mailman changes, and use Postfix migration support
+described below. In a nutshell, the postmap command will execute
+the command "postmap hash:<i>/path/to/file</i>" as if the command
+specifies lmdb:<i>/path/to/file</i> (or cdb:, depending on Postfix
+configuration). </p>
+
+</ul>
+
+<p> With Mailman3 the integration with Postfix using LMTP may look
+like: </p>
+
+<blockquote>
+<pre>
+/var/lib/mailman3/data/postfix_domains (domain names)
+/var/lib/mailman3/data/postfix_domains.db (Berkeley DB hash file)
+/var/lib/mailman3/data/postfix_lmtp (transport map)
+/var/lib/mailman3/data/postfix_lmtp.db (Berkeley DB hash file)
+</pre>
+</blockquote>
+
+<blockquote> <i> Caution: the data directory may contain other files
+with names ending in "<tt>.db</tt>" that are not part of the
+Mailman-Postfix integration. Do not tamper with the other files. </i>
+</blockquote>
+
+<p> The relevant Postfix migration levels are: </p>
+
+<dl> <dt> <a href="#enable-redirect">enable-redirect</a> (redirect hash:
+to lmdb: or cdb:) </dt>
+
+<dd> <p> Command: <tt> # <b>postfix non-bdb enable-redirect</b></tt> </p>
+
+<p> This will fix the problem that Mailman wants to use commands like
+"<tt>postmap hash:<i>/path/to/</i>postfix_domains</tt>" and "<tt>postmap
+hash:<i>/path/to</i>/postfix_lmtp</tt>". </p>
+
+<p> Instead of complaining about an unsupported database type, these
+postmap commands will implicitly create "<tt>.lmdb</tt>" indexed
+files like (lmdb:<i>/path/to</i>/postfix_domains or
+lmdb:<i>/path/to</i>/postfix_lmtp, or their cdb: versions depending
+on the Postfix default_database_type setting). </p>
+
+<p> This will not fix the problem that Postfix wants to
+use databases like hash:<i>/path/to</i>/postfix_domains
+and hash::<i>/path/to</i>/postfix_lmtp. With <a
+href="#enable-redirect">enable-redirect</a>, these will redirect to
+"<tt>.lmdb</tt>" indexed files (good) but those files do not yet exist
+(bad). You will need to create them by hand with commands like: </p>
+
+<pre>
+# <b>postmap lmdb:<i>/path/to</i>/postfix_domains</b>
+# <b>postmap lmdb:<i>/path/to</i>/postfix_lmtp</b>
+</pre>
+
+<p> After this, no further human action will be needed. When Mailman
+needs to update these files, it will invoke postmap commands that
+will work as promised above. Leave the Postfix migration level at <a
+href="#enable-reindex">enable-reindex</a> until you can upgrade to a
+newer Mailman version that supports Postfix with non-Berkeley
+databases. </p>
+
+</dd>
+
+<dt><a href="#enable-reindex">enable-reindex</a> (also automatically
+run postmap commands)</dt>
+
+<dd> <p> Command: <tt> # <b>postfix non-bdb enable-redirect</b></tt> </p>
+
+<p> In addition to "<a href="#enable-redirect">enable-redirect</a>",
+Postfix will also try to run commands like "<tt>postmap
+lmdb:<i>/path/to</i>/postfix_domains</tt>" and "<tt>postmap
+lmdb:<i>/path/to</i>/postfix_lmtp</tt>". There will be some delay
+depending on the amount of mailing list traffic; you may want to post
+a test message to make the postmap commands happen sooner. </p>
+
+<p> Postfix will log the postmap commands (or will log a request to make
+some configuration changes; see "<a href="addr-errors">Addressing errors
+with automatic indexed file generation</a>" above). </p>
+
+<p> <i>Note: once these "postmap" commands have completed,
+you should reduce the migration support level with the command
+"<b>postfix non-bdb enable-redirect</b>". For security reasons the <a
+href="#enable-reindex">enable-reindex</a> level should not be permanently
+enabled. </i> </p>
+
+</dl>
+
+</body>
+
+</html>
<blockquote>
<pre>
/etc/postfix/main.cf:
- <strong>smtpd_sender_login_maps = hash:/etc/postfix/controlled_envelope_senders</strong>
+ <strong>smtpd_sender_login_maps =
+ lmdb:/etc/postfix/controlled_envelope_senders</strong>
smtpd_recipient_restrictions =
...
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "<b>postmap
+/etc/postfix/controlled_envelope_senders</b>" after you change the
+controlled_envelope_senders file, to (re)build a default-type indexed
+file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/controlled_envelope_senders</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<p> With this, the <code>reject_sender_login_mismatch</code>
restriction above will reject the sender address in the MAIL FROM
command if <code>smtpd_sender_login_maps</code> does not specify
/etc/postfix/main.cf:
smtpd_recipient_restrictions =
permit_mynetworks
- check_sasl_access hash:/etc/postfix/sasl_access
+ check_sasl_access lmdb:/etc/postfix/sasl_access
permit_sasl_authenticated
...
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/sasl_access</b>"
+after you change the sasl_access file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_access</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<h4><a name="id397172">Default authentication domain</a></h4>
<p> Postfix can append a domain name (or any other string) to a
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
</pre>
</blockquote>
<ul>
-<li> <p> Use the <code>postmap</code> command whenever you
-change the <code>/etc/postfix/sasl_passwd</code> file. </p> </li>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
+after changing the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p> </li>
<li> <p> If you specify the "<code>[</code>" and "<code>]</code>"
in the <code>relayhost</code> destination, then you must use the
<pre>
/etc/postfix/main.cf:
smtp_sender_dependent_authentication = yes
- sender_dependent_relayhost_maps = hash:/etc/postfix/sender_relay
+ sender_dependent_relayhost_maps =
+ lmdb:/etc/postfix/sender_relay
smtp_sasl_auth_enable = yes
- smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
+ smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd
relayhost = [mail.isp.example]
# Alternative form:
# relayhost = [mail.isp.example]:submission
<ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<li> <p> If you are creative, then you can try to combine the two
tables into one single MySQL database, and configure different
Postfix queries to extract the appropriate information. </p>
-<li> <p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
-
<li> <p> Execute the command "<b>postmap /etc/postfix/sasl_passwd</b>"
-whenever you change the sasl_passwd table. </p>
+after you change the sasl_passwd file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sasl_passwd</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<li> <p> Execute the command "<b>postmap /etc/postfix/sender_relay</b>"
-whenever you change the sender_relay table. </p>
+after you change the sender_relay file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/sender_relay</b>"
+to specify an explicit type.</p>
</ul>
<blockquote>
<pre>
1 /etc/postfix/main.cf:
-2 virtual_alias_maps = hash:/etc/postfix/virtual
+2 virtual_alias_maps = lmdb:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 postmaster postmaster@example.com
9b permit_mynetworks reject_unauth_destination
10b ...spam blocking rules....
<br>
-11 relay_recipient_maps = hash:/etc/postfix/relay_recipients
-12 transport_maps = hash:/etc/postfix/transport
+11 relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
+12 transport_maps = lmdb:/etc/postfix/transport
13
14 /etc/postfix/relay_recipients:
15 user1@example.com x
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/virtual</b>"
+whenever you change the virtual file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/relay_recipients</b>"
-whenever you change the relay_recipients table. </p>
+whenever you change the relay_recipients file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/relay_recipients</b>" to specify an explicit
+type.</p>
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the transport table. </p>
+whenever you change the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
<p> In some installations, there may be separate instances of Postfix
processing inbound and outbound mail on a multi-homed firewall. The
<blockquote>
<pre>
1 /etc/postfix/main.cf:
-2 virtual_alias_maps = hash:/etc/postfix/virtual
+2 virtual_alias_maps = lmdb:/etc/postfix/virtual
3
4 /etc/postfix/virtual:
5 root root@localhost
</ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-editing the file. </p>
+editing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<h2><a name="intranet">Running Postfix behind a firewall</a></h2>
<blockquote>
<pre>
1 /etc/postfix/main.cf:
- 2 transport_maps = hash:/etc/postfix/transport
+ 2 transport_maps = lmdb:/etc/postfix/transport
3 relayhost =
4 # Optional for a machine that isn't "always on"
5 #fallback_relay = [gateway.example.com]
</ul>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
+whenever you edit the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
-<p> Execute the command "<b>postmap /etc/postfix/transport</b>" whenever
-you edit the transport table. </p>
<h2><a name="backup">Configuring Postfix as primary or backup MX host for a remote site</a></h2>
11 # You must specify your NAT/proxy external address.
12 #proxy_interfaces = 1.2.3.4
13
-14 relay_recipient_maps = hash:/etc/postfix/relay_recipients
+14 relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
15
16 /etc/postfix/relay_recipients:
17 user1@the.backed-up.domain.tld x
<blockquote>
<pre>
20 /etc/postfix/main.cf:
-21 transport_maps = hash:/etc/postfix/transport
+21 transport_maps = lmdb:/etc/postfix/transport
22
23 /etc/postfix/transport:
24 the.backed-up.domain.tld relay:[their.mail.host.tld]
</ul>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "<b>postmap /etc/postfix/relay_recipients</b>"
+whenever you change the relay_recipients file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/relay_recipients</b>" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the transport table. </p>
+whenever you change the transport file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/transport</b>"
+to specify an explicit type. </p>
<p> NOTE for Postfix < 2.2: Do not use the fallback_relay feature
when relaying mail
<blockquote>
<pre>
1 /etc/postfix/main.cf:
-2 smtp_generic_maps = hash:/etc/postfix/generic
+2 smtp_generic_maps = lmdb:/etc/postfix/generic
3
4 /etc/postfix/generic:
5 his@localdomain.local hisaccount@hisisp.example
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
<p> Execute the command "<b>postmap /etc/postfix/generic</b>"
-whenever you change the generic table. </p>
+whenever you change the generic file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/generic</b>"
+to specify an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<h3>Solution 2: Postfix version 2.1 and earlier </h3>
2 myhostname = hostname.localdomain
3 mydomain = localdomain
4
- 5 canonical_maps = hash:/etc/postfix/canonical
+ 5 canonical_maps = lmdb:/etc/postfix/canonical
6
- 7 virtual_alias_maps = hash:/etc/postfix/virtual
+ 7 virtual_alias_maps = lmdb:/etc/postfix/virtual
8
9 /etc/postfix/canonical:
10 your-login-name your-account@your-isp.com
</ul>
-<p>Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what lookup
-tables Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
<p> Execute the command "<b>postmap /etc/postfix/canonical</b>"
-whenever you change the canonical table. </p>
+whenever you change the canonical file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/canonical</b>"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>"
-whenever you change the virtual table. </p>
+whenever you change the virtual file, to (re)build a default-type
+indexed file. Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>"
+to specify an explicit type. </p>
</body>
command without assistance from the shell, so there are no problems
with shell meta characters in command-line parameters. </p>
+<li> <p> Enable <b>transport</b> table lookups: </p>
+
+<pre>
+/etc/postfix/main.cf:
+ transport_maps = lmdb:/etc/postfix/transport
+</pre>
+
<li> <p> Specify that mail for <i>example.com</i>, should be
delivered via UUCP, to a host named <i>uucp-host</i>: </p>
.example.com uucp:uucp-host
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> See the transport(5) manual page for more details. </p>
<li> <p> Execute the command "<b>postmap /etc/postfix/transport</b>"
-whenever you change the <b>transport</b> file. </p>
-
-<li> <p> Enable <b>transport</b> table lookups: </p>
-
-<pre>
-/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
-</pre>
+whenever you change the <b>transport</b> file, to (re)build a
+default-type indexed file. Execute "<b>postmap
+<i>type</i>:/etc/postfix/transport</b>" to specify an explicit type.
+</p>
-<p> Specify <b>dbm</b> instead of <b>hash</b> if your system uses
-<b>dbm</b> files instead of <b>db</b> files. To find out what map
-types Postfix supports, use the command "<b>postconf -m</b>". </p>
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
<li> <p> Add <i>example.com</i> to the list of domains that your site
is willing to relay mail for. </p>
<li> <a href="#forwarding">Mail forwarding domains</a>
-<li> <a href="#mailing_lists">Mailing lists</a>
-
-<li> <a href="#autoreplies">Autoreplies</a>
+<li> <a href="#mailing_lists">Hosted mailing list domains</a>
</ul>
<h2><a name="local_vs_database">Local files versus network databases</a></h2>
<p> The examples in this text use table lookups from local files
-such as DBM or Berkeley DB. These are easy to debug with the
+such as lmdb:, cdb:, hash:, or dbm:. These are easy to debug with the
<b>postmap</b> command: </p>
<blockquote>
-Example: <tt>postmap -q info@example.com hash:/etc/postfix/virtual</tt>
+Example: <tt>postmap -q info@example.com /etc/postfix/virtual</tt>
</blockquote>
-<p> See the documentation in LDAP_README, MYSQL_README and PGSQL_README
-for how to replace local files by databases. The reader is strongly
-advised to make the system work with local files before migrating
-to network databases, and to use the <b>postmap</b> command to verify
-that network database lookups produce the exact same results as
-local file lookup. </p>
+<p> The above example assumes that the database is configured in
+main.cf as $default_database_type:/etc/postfix/virtual. Otherwise,
+use the command instead: </p>
+
+<blockquote>
+Example: <tt>postmap -q info@example.com
+<i>type</i>:/etc/postfix/virtual</tt>
+</blockquote>
+
+<p> and specify the explicit type that this table uses in main.cf. </p>
+
+<p> You can replace local file lookups with networked (LDAP, SQL
+etc.) lookups. See the documentation in LDAP_README, MYSQL_README,
+PGSQL_README, etc., for examples. The reader is strongly advised
+to make Postfix work with local files before migrating to network
+databases, and to use the <b>postmap</b> command to verify that
+network database lookups produce the exact same results as local
+file lookup. </p>
<blockquote>
Example: <tt>postmap -q info@example.com ldap:/etc/postfix/virtual.cf</tt>
<pre>
1 /etc/postfix/main.cf:
2 virtual_alias_domains = example.com ...other hosted domains...
- 3 virtual_alias_maps = hash:/etc/postfix/virtual
+ 3 virtual_alias_maps = lmdb:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
</ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p>Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, and execute the command "<b>postfix
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p>Execute the command "<b>postfix
reload</b>" after changing the main.cf file. </p>
<p> Note: virtual aliases can resolve to a local address or to a
1 /etc/postfix/main.cf:
2 virtual_mailbox_domains = example.com ...more domains...
3 virtual_mailbox_base = /var/mail/vhosts
- 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox
+ 4 virtual_mailbox_maps = lmdb:/etc/postfix/vmailbox
5 virtual_minimum_uid = 100
6 virtual_uid_maps = static:5000
7 virtual_gid_maps = static:5000
- 8 virtual_alias_maps = hash:/etc/postfix/virtual
+ 8 virtual_alias_maps = lmdb:/etc/postfix/virtual
9
10 /etc/postfix/vmailbox:
11 info@example.com example.com/info
</ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, execute "<b>postmap /etc/postfix/vmailbox</b>"
-after changing the vmailbox file, and execute the command "<b>postfix
-reload</b>" after changing the main.cf file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute "<b>postmap /etc/postfix/vmailbox</b>" after changing
+the vmailbox file, to (re)build a default-type indexed file. Execute
+"<b>postmap <i>type</i>:/etc/postfix/vmailbox</b>" to specify an
+explicit type. </p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+main.cf file. </p>
<p> Note: mail delivery happens with the recipient's UID/GID
privileges specified with virtual_uid_maps and virtual_gid_maps.
1 /etc/postfix/main.cf:
2 virtual_transport = ...see below...
3 virtual_mailbox_domains = example.com ...more domains...
- 4 virtual_mailbox_maps = hash:/etc/postfix/vmailbox
- 5 virtual_alias_maps = hash:/etc/postfix/virtual
+ 4 virtual_mailbox_maps = lmdb:/etc/postfix/vmailbox
+ 5 virtual_alias_maps = lmdb:/etc/postfix/virtual
6
7 /etc/postfix/vmailbox:
8 info@example.com whatever
</ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, execute "<b>postmap /etc/postfix/vmailbox</b>"
-after changing the vmailbox file, and execute the command "<b>postfix
-reload</b>" after changing the main.cf file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute the command "<b>postmap /etc/postfix/vmailbox</b>" after
+changing the vmailbox file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/vmailbox</b>" to
+specify an explicit type.</p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+main.cf file. </p>
<h2><a name="forwarding">Mail forwarding domains</a></h2>
<pre>
1 /etc/postfix/main.cf:
2 virtual_alias_domains = example.com ...other hosted domains...
- 3 virtual_alias_maps = hash:/etc/postfix/virtual
+ 3 virtual_alias_maps = lmdb:/etc/postfix/virtual
4
5 /etc/postfix/virtual:
6 postmaster@example.com postmaster
</ul>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> Execute the command "<b>postmap /etc/postfix/virtual</b>" after
-changing the virtual file, and execute the command "<b>postfix
-reload</b>" after changing the main.cf file. </p>
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
+<p> Execute the command "<b>postfix reload</b>" after changing the
+main.cf file. </p>
<p> More details about the virtual alias file are given in the
virtual(5) manual page, including multiple addresses on the right-hand
side. </p>
-<h2><a name="mailing_lists">Mailing lists</a></h2>
+<h2><a name="mailing_lists">Hosted mailing list domains</a></h2>
+
+<p> <i> Note: this section presents a historical approach to run a
+mailing list based on local aliases(5). This approach may still be
+useful for small mailing lists that are managed by hand or with the
+software like Majordomo. For a more contemporary and more scalable
+approach, see <a href="https://lists.org"> GNU Mailman</a>. </i>
+</p>
-<p> The examples that were given above already show how to direct
+<p>The examples that were given above already show how to direct
mail for virtual postmaster addresses to a local postmaster. You
can use the same method to direct mail for any address to a local
or remote address. </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
- virtual_alias_maps = hash:/etc/postfix/virtual
+ virtual_alias_maps = lmdb:/etc/postfix/virtual
+ virtual_mailbox_domains = example.com
/etc/postfix/virtual:
listname-request@example.com listname-request
listname@example.com listname
owner-listname@example.com owner-listname
+ postmaster@example.com postmaster
/etc/aliases:
listname: "|/some/where/majordomo/wrapper ..."
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p>Execute the command "<b>postmap /etc/postfix/virtual</b>" after
+changing the virtual file, to (re)build a default-type indexed file.
+Execute "<b>postmap <i>type</i>:/etc/postfix/virtual</b>" to specify
+an explicit type.</p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "<b>postconf -m</b>".</p>
+
<p> This example assumes that in main.cf, $myorigin is listed under
the mydestination parameter setting. If that is not the case,
specify an explicit domain name on the right-hand side of the
<ul>
-<li> In case of a virtual alias domain, there would need to be one
-identity mapping from each mailing list address to itself.
+<li> In the case of a virtual alias DOMAIN, there would need to be
+an identity mapping from each mailing list address to an address in a
+different domain.
-<li> In case of a virtual mailbox domain, there would need to be
-a dummy mailbox for each mailing list address.
+<li> In the case of a virtual mailbox DOMAIN, there would need to
+be a dummy virtual_mailbox_maps for each mailing list address.
</ul>
-<h2><a name="autoreplies">Autoreplies</a></h2>
-
-<p> In order to set up an autoreply for virtual recipients while
-still delivering mail as normal, set up a rule in a virtual alias
-table: </p>
-
-<blockquote>
-<pre>
-/etc/postfix/main.cf:
- virtual_alias_maps = hash:/etc/postfix/virtual
-
-/etc/postfix/virtual:
- user@domain.tld user@domain.tld, user@domain.tld@autoreply.mydomain.tld
-</pre>
-</blockquote>
-
-<p> This delivers mail to the recipient, and sends a copy of the
-mail to the address that produces automatic replies. The address
-can be serviced on a different machine, or it can be serviced
-locally by setting up a transport map entry that pipes all mail
-for autoreply.mydomain.tld into some script that sends an automatic
-reply back to the sender. </p>
-
-<p> DO NOT list autoreply.mydomain.tld in mydestination! </p>
-
-<blockquote>
-<pre>
-/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
-
-/etc/postfix/transport:
- autoreply.mydomain.tld autoreply:
-
-/etc/postfix/master.cf:
- # =============================================================
- # service type private unpriv chroot wakeup maxproc command
- # (yes) (yes) (yes) (never) (100)
- # =============================================================
- autoreply unix - n n - - pipe
- flags= user=nobody argv=/path/to/autoreply $sender $mailbox
-</pre>
-</blockquote>
-
-<p> This invokes /path/to/autoreply with the sender address and
-the user@domain.tld recipient address on the command line. </p>
-
-<p> For more information, see the pipe(8) manual page, and the
-comments in the Postfix master.cf file. </p>
-
</body>
</html>
# email messages.
#
# Normally, the \fBaccess\fR(5) table is specified as a text file
-# that serves as input to the \fBpostmap\fR(1) command.
-# The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-# is used for fast searching by the mail system. Execute the
-# command "\fBpostmap /etc/postfix/access\fR" to rebuild an
-# indexed file after changing the corresponding text file.
+# that serves as input to the \fBpostmap\fR(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/access\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/access\fR" to
+# specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
# domain).
#
# Normally, the \fBaliases\fR(5) table is specified as a text file
-# that serves as input to the \fBpostalias\fR(1) command. The
-# result, an indexed file in \fBdbm\fR or \fBdb\fR format, is
-# used for fast lookup by the mail system. Execute the command
-# \fBnewaliases\fR in order to rebuild the indexed file after
-# changing the Postfix alias database.
+# that serves as input to the \fBpostalias\fR(1) command to create
+# an indexed file for fast lookup. The location of this file is
+# system-dependent. This text will use \fB/path/to/aliases\fR.
+#
+# Execute the command "\fBnewaliases\fR to rebuild the indexed
+# file after changing the text file. Execute "\fBpostalias -q
+# \fIname\fB /path/to/aliases\fR" to query a default-type indexed
+# file, or execute "\fBpostalias -q \fIname\fB
+# \fItype\fB:/path/to/aliases\fR" to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions. In
# queue. The address mapping is recursive.
#
# Normally, the \fBcanonical\fR(5) table is specified as a text file
-# that serves as input to the \fBpostmap\fR(1) command.
-# The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-# is used for fast searching by the mail system. Execute the command
-# "\fBpostmap /etc/postfix/canonical\fR" to rebuild an indexed
-# file after changing the corresponding text file.
+# that serves as input to the \fBpostmap\fR(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/canonical\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/canonical\fR"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
# \fBpostmap -q - cidr:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional lookup tables.
-# These tables are usually in \fBdbm\fR or \fBdb\fR format.
+# These tables are usually in \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR,
+# or \fBdbm:\fR format.
+#
# Alternatively, lookup tables can be specified in CIDR
# (Classless Inter-Domain Routing) form. In this case, each
# input is compared against a list of patterns. When a match
#
# Normally, the \fBgeneric\fR(5) table is specified as a
# text file that serves as input to the \fBpostmap\fR(1)
-# command. The result, an indexed file in \fBdbm\fR or
-# \fBdb\fR format, is used for fast searching by the mail
-# system. Execute the command "\fBpostmap /etc/postfix/generic\fR"
-# to rebuild an indexed file after changing the corresponding
-# text file.
+# command to create an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/generic\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/generic\fR"
+# to specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
<li> <a href="DATABASE_README.html"> Lookup table overview </a>
+<li> <a href="NON_BERKELEYDB_README.html"> Non-Berkeley-DB migration </a>
+
<li> <a href="DB_README.html"> Berkeley DB Howto </a>
<li> <a href="CDB_README.html"> CDB Howto </a>
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as LDAP databases.
+# To find out what types of lookup tables your Postfix system
+# supports use the "\fBpostconf -m\fR" command.
#
# In order to use LDAP lookups, define an LDAP source as a lookup
# table in main.cf, for example:
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as memcache
-# instances. To use memcache lookups, define a memcache
+# instances. To use memcache lookups, define a memcache
# source as a lookup table in main.cf, for example:
#
# .nf
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as MongoDB
-# databases. In order to use MongoDB lookups, define a MongoDB
+# databases.
+# To find out what types of lookup tables your Postfix system
+# supports use the "\fBpostconf -m\fR" command.
+#
+# In order to use MongoDB lookups, define a MongoDB
# source as a lookup table in main.cf, for example:
# .nf
# alias_maps = mongodb:/etc/postfix/mongodb-aliases.cf
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as MySQL databases.
+# To find out what types of lookup tables your Postfix system
+# supports use the "\fBpostconf -m\fR" command.
+#
# In order to use MySQL lookups, define a MySQL source as a lookup
# table in main.cf, for example:
# .nf
# \fBpostmap -q - "nisplus:[\fIname\fB=%s];\fIname.name.\fB" <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional lookup tables.
-# These tables are usually in \fBdbm\fR or \fBdb\fR format.
+# rewriting or mail routing. These tables are usually in
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
+#
# Alternatively, lookup tables can be specified as NIS+
# databases.
-#
# To find out what types of lookup tables your Postfix system
# supports use the "\fBpostconf -m\fR" command.
#
# \fBpostmap -bmq - pcre:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional tables for address
-# rewriting, mail routing, or access control. These tables
-# are usually in \fBdbm\fR or \fBdb\fR format.
+# rewriting or mail routing. These tables are usually in
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified in Perl Compatible
# Regular Expression form. In this case, each input is compared
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as PostgreSQL
-# databases. In order to use PostgreSQL lookups, define a
+# databases.
+# To find out what types of lookup tables your Postfix system
+# supports use the "\fBpostconf -m\fR" command.
+#
+# In order to use PostgreSQL lookups, define a
# PostgreSQL source as a lookup table in main.cf, for example:
# .nf
# alias_maps = pgsql:/etc/postfix/pgsql-aliases.cf
<script type="text/javascript">
-// Kludge for https://support.google.com/chrome/thread/11993079
+// See support.google.com/chrome/thread/11993079
const isChrome = /Chrome/.test(navigator.userAgent)
&& /Google Inc/.test(navigator.vendor);
const hash = window.location.hash;
<pre>
address_verify_map = $default_cache_db_type:$data_directory/verify_cache
-address_verify_map = hash:/var/lib/postfix/verify_cache
+address_verify_map = lmdb:/var/lib/postfix/verify_cache
address_verify_map = btree:/var/lib/postfix/verify_cache
</pre>
</p>
<pre>
-alias_database = hash:/etc/aliases
-alias_database = hash:/etc/mail/aliases
+alias_database = $default_database_type:/etc/aliases
+alias_database = lmdb:/etc/aliases
+alias_database = lmdb:/etc/mail/aliases
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
%PARAM alias_maps see "postconf -d" output
<p>
default is to search the local alias database, then the NIS alias
database.
</p>
-
-<p>
-If you change the alias database, run "<b>postalias /etc/aliases</b>"
-(or wherever your system stores the mail alias file), or simply
-run "<b>newaliases</b>" to build the necessary DBM or DB file.
-</p>
<p>
The local(8) delivery agent disallows regular expression substitution
</p>
<pre>
-alias_maps = hash:/etc/aliases, nis:mail.aliases
-alias_maps = hash:/etc/aliases
+alias_maps = $default_database_type:/etc/aliases, nis:mail.aliases
+alias_maps = $default_database_type:/etc/aliases
+alias_maps = lmdb:/etc/mail/aliases
+alias_maps = lmdb:/etc/aliases
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postalias <i>/path/to/aliases</i>" after you
+change the aliases file, to (re)build a default-type indexed file.
+Execute "postalias <i>type:/path/to/aliases</i>" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM allow_mail_to_commands alias, forward
<p>
Note: these lookups are recursive.
</p>
-<p>
-If you use this feature, run "<b>postmap /etc/postfix/canonical</b>" to
-build the necessary DBM or DB file after every change. The changes
-will become visible after a minute or so. Use "<b>postfix reload</b>"
-to eliminate the delay.
-</p>
-
<p> Note: with Postfix version 2.2, message header address mapping
happens only when message header address rewriting is enabled: </p>
</p>
<pre>
-canonical_maps = dbm:/etc/postfix/canonical
-canonical_maps = hash:/etc/postfix/canonical
+canonical_maps = lmdb:/etc/postfix/canonical
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/canonical" after you
+change the canonical file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/canonical" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM canonical_classes envelope_sender, envelope_recipient, header_sender, header_recipient
<p> What addresses are subject to canonical_maps address mapping.
<p>
The default database type for use in newaliases(1), postalias(1)
and postmap(1) commands. On many UNIX systems the default type is
-either <b>dbm</b> or <b>hash</b>. The default setting is frozen
+either <b>lmdb</b> or <b>hash</b>. The default setting is frozen
when the Postfix system is built.
</p>
</p>
<pre>
+default_database_type = lmdb
default_database_type = hash
-default_database_type = dbm
</pre>
%PARAM default_delivery_slot_cost 5
mynetworks = !192.168.0.1, 192.168.0.0/28
mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:587::]/64
mynetworks = $config_directory/mynetworks
-mynetworks = hash:/etc/postfix/network_table
+mynetworks = lmdb:/etc/postfix/network_table
mynetworks = cidr:/etc/postfix/network_table.cidr
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM myorigin $myhostname
<p>
<pre>
/etc/postfix/main.cf:
- rbl_reply_maps = hash:/etc/postfix/rbl_reply
+ rbl_reply_maps = lmdb:/etc/postfix/rbl_reply
smtpd_recipient_restrictions =
permit_mynetworks,
reject_rbl_client <i>secret</i>.zen.dq.spamhaus.net=127.0.0.[2..11],
554 $rbl_class $rbl_what blocked using ZEN - see https://www.spamhaus.org/query/ip/$client_address for details
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p>
NOTE: This feature differs from postscreen_dnsbl_reply_map where
the table search key is only a domain name (no "<i>=address-filter</i>",
should be only a domain name (no free text, no <i>$name</i> variables).
</p>
+<p> Execute the command "postmap /etc/postfix/rbl_reply" after you
+change the rbl_reply file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/rbl_reply" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
+
<p>
This feature is available in Postfix 2.0 and later.
The "=address-filter" feature is available in Postfix 2.8 and later.
</p>
<pre>
-recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
+recipient_bcc_maps = lmdb:/etc/postfix/recipient_bcc
</pre>
-<p>
-After a change, run "<b>postmap /etc/postfix/recipient_bcc</b>".
-</p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/recipient_bcc" after
+you change the recipient_bcc file, to (re)build a default-type indexed
+file. Execute "postmap <i>type</i>:/etc/postfix/recipient_bcc" to
+specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>
This feature is available in Postfix 2.1 and later.
</p>
<pre>
-recipient_canonical_maps = hash:/etc/postfix/recipient_canonical
+recipient_canonical_maps = lmdb:/etc/postfix/recipient_canonical
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/recipient_canonical"
+after you change the recipient_canonical file, to (re)build a
+default-type indexed file. Execute "postmap
+<i>type</i>:/etc/postfix/recipient_canonical" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
+
%PARAM recipient_delimiter
<p> The set of characters that can separate an email address
</p>
<pre>
-relay_recipient_maps = hash:/etc/postfix/relay_recipients
+relay_recipient_maps = lmdb:/etc/postfix/relay_recipients
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relay_recipients"
+after you change the relay_recipients file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/relay_recipients"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>
This feature is available in Postfix 2.0 and later.
</p>
until a match is found.
</p>
-<p>
-If you use this feature, run "<b>postmap /etc/postfix/relocated</b>" to
-build the necessary DBM or DB file after change, then "<b>postfix
-reload</b>" to make the changes visible.
-</p>
-
<p>
Examples:
</p>
<pre>
-relocated_maps = dbm:/etc/postfix/relocated
-relocated_maps = hash:/etc/postfix/relocated
+relocated_maps = lmdb:/etc/postfix/relocated
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/relocated" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM relocated_prefix_enable yes
<p> Prepend the prefix "<b>5.1.6 User has moved to </b>" to all
<pre>
/etc/postfix/main.cf:
- relocated_maps = hash:/etc/postfix/relocated
+ relocated_maps = lmdb:/etc/postfix/relocated
relocated_prefix_enable = no
<br>
-hash:/etc/postfix/relocated:
+/etc/postfix/relocated:
user@example.com 5.2.1 User account is disabled
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/relocated" after you
+change the relocated file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/relocated" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
+<p> This feature is available in Postfix 3.11 and later. </p>
+
%PARAM require_home_directory no
<p>
</p>
<pre>
-sender_bcc_maps = hash:/etc/postfix/sender_bcc
+sender_bcc_maps = lmdb:/etc/postfix/sender_bcc
</pre>
-<p>
-After a change, run "<b>postmap /etc/postfix/sender_bcc</b>".
-</p>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/sender_bcc" after you
+change the sender_bcc file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/sender_bcc" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
<p>
This feature is available in Postfix 2.1 and later.
</p>
<pre>
-sender_canonical_maps = hash:/etc/postfix/sender_canonical
+sender_canonical_maps = lmdb:/etc/postfix/sender_canonical
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/sender_canonical"
+after you change the sender_canonical file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/sender_canonical"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM smtp_always_send_ehlo yes
<p>
<pre>
smtpd_sender_restrictions = reject_unknown_sender_domain
smtpd_sender_restrictions = reject_unknown_sender_domain,
- check_sender_access hash:/etc/postfix/access
+ check_sender_access lmdb:/etc/postfix/access
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/access" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM smtpd_timeout normal: 300s, overload: 10s
<p> When the Postfix SMTP server wants to send an SMTP server
<p>
Specify zero or more "type:table" lookup tables, separated by
whitespace or comma. Tables will be searched in the specified order
-until a match is found. If you use this
-feature with local files, run "<b>postmap /etc/postfix/transport</b>"
-after making a change. </p>
+until a match is found. </p>
<p> Pattern matching of domain names is controlled by the presence
or absence of "transport_maps" in the parent_domain_matches_subdomains
</p>
<pre>
-transport_maps = dbm:/etc/postfix/transport
-transport_maps = hash:/etc/postfix/transport
+transport_maps = lmdb:/etc/postfix/transport
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/transport" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM transport_retry_time 60s
<p>
Note: these lookups are recursive.
</p>
-<p>
-If you use this feature with indexed files, run "<b>postmap
-/etc/postfix/virtual</b>" after changing the file.
-</p>
-
<p>
Examples:
</p>
<pre>
-virtual_alias_maps = dbm:/etc/postfix/virtual
-virtual_alias_maps = hash:/etc/postfix/virtual
+virtual_alias_maps = lmdb:/etc/postfix/virtual
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/virtual" after you
+change the virtual file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/virtual" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
%PARAM virtual_alias_recursion_limit 1000
<p>
<pre>
local_header_rewrite_clients = permit_mynetworks,
permit_sasl_authenticated permit_tls_clientcerts
- check_address_map hash:/etc/postfix/pop-before-smtp
+ check_address_map lmdb:/etc/postfix/pop-before-smtp
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
%PARAM smtpd_tls_cert_file
<p> File with the Postfix SMTP server RSA certificate in PEM format.
<p> Examples: </p>
<pre>
-smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtpd_tls_session_cache_database = lmdb:/var/lib/postfix/smtpd_scache
+smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
</pre>
<p> This feature is available in Postfix 2.2 and later. </p>
<p> Example: </p>
<pre>
-relay_clientcerts = hash:/etc/postfix/relay_clientcerts
+relay_clientcerts = lmdb:/etc/postfix/relay_clientcerts
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p>For more fine-grained control, use check_ccert_access to select
an appropriate access(5) policy for each client.
See RESTRICTION_CLASS_README.</p>
+<p> Execute the command "postmap /etc/postfix/relay_clientcerts"
+after you change the relay_clientcerts file, to (re)build a default-type
+indexed file. Execute "postmap <i>type</i>:/etc/postfix/relay_clientcerts"
+to specify an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p>This feature is available with Postfix version 2.2.</p>
%PARAM smtpd_tls_cipherlist
<p> Name of the file containing the optional Postfix SMTP client
TLS session cache. Specify a database type that supports enumeration,
-such as <b>btree</b> or <b>sdbm</b>; there is no need to support
+such as <b>lmdb</b> or <b>btree</b>; there is no need to support
concurrent access. The file is created if it does not exist. The smtp(8)
daemon does not use this parameter directly, rather the cache is
implemented indirectly in the tlsmgr(8) daemon. This means that
<p> Example: </p>
<pre>
-smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
smtp_tls_session_cache_database = lmdb:/var/lib/postfix/smtp_scache
+smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
</pre>
<p> This feature is available in Postfix 2.2 and later. </p>
<pre>
/etc/postfix/main.cf:
- smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
+ smtp_tls_policy_maps = lmdb:/etc/postfix/tls_policy
# Postfix 2.5 and later.
#
# The default digest is sha256 with Postfix ≥ 3.6 and
match=51:e9:af:2e:1e:40:1f:...:64:0a:30:35:2d:09:16:31:5a:eb:82:76
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> <b>Note:</b> The "hostname" strategy if listed in a non-default
setting of smtp_tls_secure_cert_match or in the "match" attribute
in the policy table can render the "secure" level vulnerable to
DNS forgery. Do not use the "hostname" strategy for secure-channel
configurations in environments where DNS security is not assured. </p>
+<p> Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/tls_policy" to specify
+an explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.3 and later. </p>
%PARAM smtp_tls_mandatory_protocols see "postconf -d" output
<blockquote>
<pre>
/etc/postfix/main.cf:
- smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
+ smtp_tls_policy_maps = lmdb:/etc/postfix/tls_policy
smtp_tls_fingerprint_digest = sha256
</pre>
</blockquote>
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/tls_policy" after you
+change the tls_policy file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/tls_policy" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.5 and later. </p>
%PARAM lmtp_tls_fingerprint_cert_match
/etc/postfix/main.cf:
smtpd_tls_fingerprint_digest = sha256
smtpd_client_restrictions =
- check_ccert_access hash:/etc/postfix/access,
+ check_ccert_access lmdb:/etc/postfix/access,
reject
</pre>
<pre>
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/access" after you
+change the access file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/access" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 2.5 and later. </p>
%PARAM lmtp_pix_workaround_maps
<p> Examples: </p>
<pre>
-smtp_sasl_auth_cache_name = proxy:btree:/var/lib/postfix/sasl_auth_cache
smtp_sasl_auth_cache_name = proxy:lmdb:/var/lib/postfix/sasl_auth_cache
+smtp_sasl_auth_cache_name = proxy:btree:/var/lib/postfix/sasl_auth_cache
</pre>
<p> This feature is available in Postfix 2.5 and later. </p>
<p> Persistent storage for the postscreen(8) server decisions. </p>
<p> To share a postscreen(8) cache between multiple postscreen(8)
-instances, use "postscreen_cache_map = proxy:btree:/path/to/file"
-or "proxy:lmdb:/path/to/file".
+instances, use "postscreen_cache_map = proxy:lmdb:/path/to/file"
+or "proxy:btree:/path/to/file".
This requires Postfix version 2.9 or later; earlier proxymap(8)
implementations don't support cache cleanup. For an alternative
approach see the memcache_table(5) manpage. </p>
<blockquote>
<pre>
/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+ transport_maps = lmdb:/etc/postfix/transport
</pre>
</blockquote>
</pre>
</blockquote>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
<p> Unselective use of the "data" target does no harm, but will
result in unnecessary "lost connection after DATA" events at remote
SMTP/LMTP servers. </p>
+<p> Execute the command "postmap /etc/postfix/transport" after you
+change the transport file, to (re)build a default-type indexed file.
+Execute "postmap <i>type</i>:/etc/postfix/transport" to specify an
+explicit type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
<p> This feature is available in Postfix 3.0 and later. </p>
%PARAM lmtp_address_verify_target rcpt
(Punycode) before making a policy query; lookup tables must answer
ASCII-form queries. </p>
-<li> <p> A fixed-string table (such as hash:, btree:, or lmdb:) is
+<li> <p> A fixed-string table (such as lmdb:, cdb:, or hash:) is
also searched with the next-hop ".parent" domains (in a table key,
prepend a '.' to a parent domain name). These ".parent" domain
queries are not made with pattern-based lookup tables such as regexp:
<li> <p> To match any name below the domain "example.com" specify
a table entry with the storage key ".example.com" in type:table
lookup tables that need an exact match. This is appropriate, for
-example, with hash:, btree: or lmdb:. </p>
+example, with lmdb:, cdb: or hash:. </p>
<li> <p> Do not specify a match pattern for ".domain" with regexp:,
pcre:, socketmap:, or tcp:, as smtp_requiretls_policy will
cidr:{
{ 0.0.0.0/0 opportunistic },
{ ::/0 opportunistic } },
- hash:/etc/postfix/requiretls-per-site
+ lmdb:/etc/postfix/requiretls-per-site
opportunistic+starttls
</pre>
<pre>
...
</pre>
+<p> Instead of lmdb:, some systems use cdb:, hash:, or dbm:. </p>
+
+<p> Execute the command "postmap /etc/postfix/requiretls-per-site"
+after you change the requiretls-per-site file, to (re)build a
+default-type indexed file. Execute "postmap
+<i>type</i>:/etc/postfix/requiretls-per-site" to specify an explicit
+type. </p>
+
+<p> The default indexed file type is configured with the
+default_database_type parameter. To list available explicit types,
+execute the command "postconf -m". </p>
+
+<p> Configuration changes will become visible after a minute or so.
+Use "postfix reload" to eliminate the delay. </p>
+
</ul>
<p>
</pre>
</dd>
-<dl>
+</dl>
<p> This feature is available in Postfix ≥ 3.11. </p>
by default. </p>
<p> This feature is available in Postfix ≥ 3.11. </p>
+
+%PARAM non_bdb_migration_allow_root_prefixes see 'postconf -d non_bdb_migration_allow_root_prefixes' output
+
+<p> A list of trusted pathname prefixes that must be matched when
+the non-Berkeley-DB migration service (nbdb_reindexd(8)) needs to
+run postmap(1) or postalias(1) commands with "root" privilege.
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+%PARAM non_bdb_migration_allow_user_prefixes see 'postconf -d non_bdb_migration_allow_user_prefixes' output
+
+<p> A list of trusted pathname prefixes that must be matched when
+the non-Berkeley-DB migration service (nbdb_reindexd(8)) needs to
+run postmap(1) or postalias(1) commands with non-root privilege. </p>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+%PARAM non_bdb_custom_mapping empty
+
+<p> When non-Berkeley-DB migration is enabled, an optional mapping
+from a hash: or btree: type to a non-Berkeley-DB type. This mapping
+takes precedence over the default mapping from hash: to
+$default_database_type, and from btree: to $default_cache_db_type.
+</p>
+
+<ul>
+
+<li> <p> Specify a lookup table with a search keys that are a
+Berkeley DB <i>type</i> (without ':') or <i>type:name</i>. </p>
+
+<li> <p> A search key with the form <i>type:name</i> takes precedence
+over <i>type</i> (without ':'). </p>
+
+<li> <p> The lookup result must always be a non-Berkeley-DB <i>type</i>
+(without ':') and must not contain a <i>:name</i>. </p>
+
+<li> <p> The mapping table type must not be <b>hash</b> or <b>btree</b>.
+
+</ul>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+%PARAM non_bdb_migration_level disable
+
+<p> The non-Berkeley-DB migration service level. You are expected to use
+the command "<b>postfix non-bdb <i>name-of-level</i></b>" to correctly
+configure the migration service level (see postfix-non-bdb(1). </p>
+
+<dl>
+
+<dt><b>disable</b></dt>
+
+<dd> <p> Disable all non-Berkeley-DB migration features. See
+NON_BERKELEYDB_README#disable for possible negative implications
+for integration with other software such as mailman. </p> </dd>
+
+<dt><b>enable-redirect</b> (aliasing)</dt>
+
+<dd> <p> Enable redirection (aliasing) from Berkeley DB hash to
+$default_database_type, and from Berkeley DB btree to
+$default_cache_db_type, but do not automatically create the new cdb
+or lmdb indexed database files that Postfix programs need. See
+NON_BERKELEYDB_README#enable-redirect for details and limitations.
+</p> </dd>
+
+<dt><b>enable-reindex</b></dt>
+
+<dd> <p> In addition to enable-redirect, also create a non-Berkeley-DB
+indexed database file when a daemon program wants to access a file
+that does not yet exist. This feature uses the nbdb_reindexd(8)
+daemon to run postmap(1) or postalias(1). See
+NON_BERKELEYDB_README#enable-reindex for details and limitations.
+</p>
+
+<p> <i> NOTE: <b>enable-reindex</b> should be used only temporarily to
+generate most of the non-Berkeley-DB indexed database files that Postfix
+programs need. Leaving this level enabled may expose the system to
+privilege-escalation attacks. There are no security concerns for using
+<b>enable-redirect</b>. </i> </p> </dd>
+
+</dl>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
+
+%PARAM non_bdb_migration_service_name nbdb_reindex
+
+<p> The name of a master.cf service that implements the non-Berkeley-DB
+migration service protocol. </p>
+
+<p> This feature is available in Postfix ≥ 3.11. </p>
# \fBpostmap -q - regexp:/etc/postfix/\fIfilename\fB <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional tables for address
-# rewriting, mail routing, or access control. These tables
-# are usually in \fBdbm\fR or \fBdb\fR format.
+# rewriting or mail routing. These tables are usually in
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified in POSIX regular
# expression form. In this case, each input is compared against a
# used in "user has moved to \fInew_location\fR" bounce messages.
#
# Normally, the \fBrelocated\fR(5) table is specified as a text file
-# that serves as input to the \fBpostmap\fR(1) command.
-# The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-# is used for fast searching by the mail system. Execute the command
-# "\fBpostmap /etc/postfix/relocated\fR" to rebuild an indexed
-# file after changing the corresponding relocated table.
+# that serves as input to the \fBpostmap\fR(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/relocated\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/relocated\fR" to
+# specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
# \fBpostmap -q - socketmap:unix:\fIpathname\fB:\fIname\fB <\fIinputfile\fR
# DESCRIPTION
# The Postfix mail system uses optional tables for address
-# rewriting, mail routing or policy lookup.
+# rewriting or mail routing. These tables are usually in
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# The Postfix socketmap client expects TCP endpoint names of
# the form \fBinet:\fIhost\fB:\fIport\fB:\fIname\fR, or
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
# Alternatively, lookup tables can be specified as SQLite databases.
+# To find out what types of lookup tables your Postfix system
+# supports use the "\fBpostconf -m\fR" command.
+#
# In order to use SQLite lookups, define an SQLite source as a lookup
# table in main.cf, for example:
# .nf
jF
jM
jP
+subcommand
+CLI
+Fedor
+Vorobev
feature feature etc where
policies policy policy domain If null this defaults to the
bounce bounce defer trace
+dict_open dict_open looks up our DICT_OPEN_INFO with dict_fn and mkmap_fn
+mkmap_open mkmap_open looks up our DICT_OPEN_INFO with dict_fn and mkmap_fn
+ typedef struct MSG_CAPTURE MSG_CAPTURE
+MSG_CAPTURE MSG_CAPTURE msg_capt_create ssize_t init_size
src dns dns h
postconf postconf hc postconf postconf_master c
PPx proxy_read_maps Files postconf postconf hc
+proto proto stop proto stop double cc
+ proto stop spell proto html postfix postfix c
+ postalias postalias c postmap postmap c
+ proto stop spell proto html postfix postfix c conf postfix files
+ proto stop spell proto html postfix postfix c conf postfix files
+ File nbdb_reindexd nbdb_reindexd c
+ tls tls h tls tls_misc c tls tls_verify c
pattern number number number text
to to the lookup result With Postfix 3 11 and later specify
has moved to to a table lookup result and the format for a
+after stripping whitespace between the the value and the
after stripping whitespace betwen the the value and the
after stripping whitespace between the the value and the
smtp_requiretls_policy smtp_requiretls_policy inline
xn mumble mumble Punycode A label form that Postfix needs This works around a limitation that may be eliminated in a future Postfix version
in tt tt p
+mynetworks mynetworks lmdb etc postfix network_table
+ 25 enable redirect redirect hash to lmdb or cdb
joqvx
ajRv
allparams
+BERKELEYDB
+Chari
+MIGR
+Matchers
+Mockable
+NBDB
+Postmap
+REINDEX
+Sndump
+Un
+bdb
+cust
+ig
+maxtry
+mockable
+nbdb
+rdr
+reindex
+reindexd
+reindexed
+reindexing
+surr
+whoami
unbroke
PPx
unbroke
+smithing
+Scheiner
nomatch
nostarttls
mariadb
+BERKELEYDB
+bdb
+gitlab
+nbdb
+reindex
+reindexd
+hPP
+hPPx
+hx
# DESCRIPTION
# The Postfix mail system uses optional tables for address
# rewriting or mail routing. These tables are usually in
-# \fBdbm\fR or \fBdb\fR format. Alternatively, table lookups
-# can be directed to a TCP server.
-#
-# To find out what types of lookup tables your Postfix system
-# supports use the "\fBpostconf -m\fR" command.
+# \fBlmdb:\fR, \fBcdb:\fR, \fBhash:\fR, or \fBdbm:\fR format.
#
+# Alternatively, table lookups can be directed to a TCP server.
# To test lookup tables, use the "\fBpostmap -q\fR" command as
# described in the SYNOPSIS above.
# PROTOCOL DESCRIPTION
# \fBrelayhost\fR, or from the recipient domain.
# .PP
# Normally, the \fBtransport\fR(5) table is specified as a text file
-# that serves as input to the \fBpostmap\fR(1) command.
-# The result, an indexed file in \fBdbm\fR or \fBdb\fR format, is used
-# for fast searching by the mail system. Execute the command
-# "\fBpostmap /etc/postfix/transport\fR" to rebuild an indexed
-# file after changing the corresponding transport table.
+# that serves as input to the \fBpostmap\fR(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/transport\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/transport\fR" to
+# specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
# mapping to rewrite header and envelope addresses in general.
#
# Normally, the \fBvirtual\fR(5) alias table is specified as a text file
-# that serves as input to the \fBpostmap\fR(1) command.
-# The result, an indexed file in \fBdbm\fR or \fBdb\fR format,
-# is used for fast searching by the mail system. Execute the command
-# "\fBpostmap /etc/postfix/virtual\fR" to rebuild an indexed
-# file after changing the corresponding text file.
+# that serves as input to the \fBpostmap\fR(1) command to create
+# an indexed file for fast lookup.
+#
+# Execute the command "\fBpostmap /etc/postfix/virtual\fR" to
+# rebuild a default-type indexed file after changing the text file,
+# or execute "\fBpostmap \fItype\fB:/etc/postfix/virtual\fR" to
+# specify an explicit type.
+#
+# The default indexed file type is configured with the
+# default_database_type parameter. Depending on the platform this
+# may be one of lmdb:, cdb:, hash:, or dbm: (without the trailing
+# ':').
#
# When the table is provided via other means such as NIS, LDAP
# or SQL, the same lookups are done as for ordinary indexed files.
+# Managing such databases is outside the scope of Postfix.
#
# Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions, or lookups
info_log_addr_form.c sasl_mech_filter.c login_sender_match.c \
test_main.c compat_level.c config_known_tcp_ports.c \
hfrom_format.c rfc2047_code.c ascii_header_text.c sendopts.c \
- pol_stats.c
+ pol_stats.c nbdb_clnt.c nbdb_util.c allowed_prefix.c \
+ nbdb_redirect.c nbdb_surrogate.c
OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \
info_log_addr_form.o sasl_mech_filter.o login_sender_match.o \
test_main.o compat_level.o config_known_tcp_ports.o \
hfrom_format.o rfc2047_code.o ascii_header_text.o sendopts.o \
- pol_stats.o
+ pol_stats.o nbdb_clnt.o nbdb_util.o allowed_prefix.o \
+ nbdb_redirect.o nbdb_surrogate.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
info_log_addr_form.h sasl_mech_filter.h login_sender_match.h \
test_main.h compat_level.h config_known_tcp_ports.h \
hfrom_format.h rfc2047_code.h ascii_header_text.h sendopts.h \
- pol_stats.h
+ pol_stats.h nbdb_clnt.h nbdb_util.h allowed_prefix.h \
+ nbdb_redirect.h nbdb_surrogate.h
TESTSRC = rec2stream.c stream2rec.c recdump.c dict_sqlite_test.c \
- ehlo_mask_test.c haproxy_srvr_test.c sendopts_test.c pol_stats_test.c
+ ehlo_mask_test.c haproxy_srvr_test.c sendopts_test.c pol_stats_test.c \
+ allowed_prefix_test.c nbdb_util_test.c nbdb_redirect_test.c \
+ nbdb_surrogate_test.c
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
INCL =
fold_addr smtp_reply_footer mail_addr_map normalize_mailhost_addr \
haproxy_srvr_test map_search delivered_hdr login_sender_match_test \
compat_level config_known_tcp_ports hfrom_format rfc2047_code \
- ascii_header_text sendopts_test dict_sqlite_test pol_stats_test
+ ascii_header_text sendopts_test dict_sqlite_test pol_stats_test \
+ allowed_prefix_test nbdb_util_test nbdb_redirect_test \
+ nbdb_surrogate_test
+TESTLIB = $(LIB_DIR)/libtesting.a
LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
LIB_DIR = ../../lib
$(CC) $(CFLAGS) -DTEST -o $@ $@.c pol_stats.o $(LIB) $(LIBS) \
$(SYSLIBS)
+allowed_prefix_test: allowed_prefix_test.o $(TESTLIB) $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(TESTLIB) $(LIB) $(LIBS) $(SYSLIBS)
+
+nbdb_util_test: nbdb_util_test.o $(TESTLIB) $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(TESTLIB) $(LIB) $(LIBS) $(SYSLIBS)
+
+nbdb_redirect_test: nbdb_redirect_test.o $(TESTLIB) $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(TESTLIB) $(LIB) $(LIBS) $(SYSLIBS)
+
+nbdb_surrogate_test: nbdb_surrogate_test.o $(TESTLIB) $(LIB) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(TESTLIB) $(LIB) $(LIBS) $(SYSLIBS)
+
config_known_tcp_ports: config_known_tcp_ports.c $(LIB) $(LIBS)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
normalize_mailhost_addr_test test_haproxy_srvr map_search_test \
delivered_hdr_test test_login_sender_match compat_level_test \
config_known_tcp_ports_test hfrom_format_test rfc2047_code_test \
- ascii_header_text_test test_sendopts test_dict_sqlite test_pol_stats
+ ascii_header_text_test test_sendopts test_dict_sqlite test_pol_stats \
+ test_allowed_prefix nbdb_tests
+
+nbdb_tests: test_nbdb_util test_nbdb_redirect test_nbdb_surrogate
mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \
mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4
test_pol_stats: update pol_stats_test
$(SHLIB_ENV) $(VALGRIND) ./pol_stats_test
+test_allowed_prefix: update allowed_prefix_test
+ $(SHLIB_ENV) $(VALGRIND) ./allowed_prefix_test
+
+test_nbdb_util: update nbdb_util_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_util_test
+
+test_nbdb_redirect: update nbdb_redirect_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_redirect_test
+
+test_nbdb_surrogate: update nbdb_surrogate_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_surrogate_test
+
clean:
rm -f *.o $(LIB) *core $(TESTPROG) junk $(MAPS)
addr_match_list.o: ../../include/vstring.h
addr_match_list.o: addr_match_list.c
addr_match_list.o: addr_match_list.h
+allowed_prefix.o: ../../include/argv.h
+allowed_prefix.o: ../../include/check_arg.h
+allowed_prefix.o: ../../include/htable.h
+allowed_prefix.o: ../../include/msg.h
+allowed_prefix.o: ../../include/mymalloc.h
+allowed_prefix.o: ../../include/split_at.h
+allowed_prefix.o: ../../include/stringops.h
+allowed_prefix.o: ../../include/sys_defs.h
+allowed_prefix.o: ../../include/vbuf.h
+allowed_prefix.o: ../../include/vstring.h
+allowed_prefix.o: allowed_prefix.c
+allowed_prefix.o: allowed_prefix.h
+allowed_prefix_test.o: ../../include/argv.h
+allowed_prefix_test.o: ../../include/check_arg.h
+allowed_prefix_test.o: ../../include/msg.h
+allowed_prefix_test.o: ../../include/msg_capture.h
+allowed_prefix_test.o: ../../include/msg_vstream.h
+allowed_prefix_test.o: ../../include/stringops.h
+allowed_prefix_test.o: ../../include/sys_defs.h
+allowed_prefix_test.o: ../../include/vbuf.h
+allowed_prefix_test.o: ../../include/vstream.h
+allowed_prefix_test.o: ../../include/vstring.h
+allowed_prefix_test.o: allowed_prefix.h
+allowed_prefix_test.o: allowed_prefix_test.c
anvil_clnt.o: ../../include/attr.h
anvil_clnt.o: ../../include/attr_clnt.h
anvil_clnt.o: ../../include/check_arg.h
mail_params.o: mail_proto.h
mail_params.o: mail_version.h
mail_params.o: mynetworks.h
+mail_params.o: nbdb_util.h
mail_params.o: own_inet_addr.h
mail_params.o: recipient_list.h
mail_params.o: verp_sender.h
namadr_list.o: ../../include/vstring.h
namadr_list.o: namadr_list.c
namadr_list.o: namadr_list.h
+nbdb_clnt.o: ../../include/argv.h
+nbdb_clnt.o: ../../include/attr.h
+nbdb_clnt.o: ../../include/check_arg.h
+nbdb_clnt.o: ../../include/connect.h
+nbdb_clnt.o: ../../include/dict.h
+nbdb_clnt.o: ../../include/htable.h
+nbdb_clnt.o: ../../include/iostuff.h
+nbdb_clnt.o: ../../include/msg.h
+nbdb_clnt.o: ../../include/myflock.h
+nbdb_clnt.o: ../../include/mymalloc.h
+nbdb_clnt.o: ../../include/nvtable.h
+nbdb_clnt.o: ../../include/sys_defs.h
+nbdb_clnt.o: ../../include/vbuf.h
+nbdb_clnt.o: ../../include/vstream.h
+nbdb_clnt.o: ../../include/vstring.h
+nbdb_clnt.o: mail_params.h
+nbdb_clnt.o: mail_proto.h
+nbdb_clnt.o: nbdb_clnt.c
+nbdb_clnt.o: nbdb_clnt.h
+nbdb_clnt.o: nbdb_util.h
+nbdb_redirect.o: ../../include/argv.h
+nbdb_redirect.o: ../../include/check_arg.h
+nbdb_redirect.o: ../../include/dict.h
+nbdb_redirect.o: ../../include/dict_cdb.h
+nbdb_redirect.o: ../../include/dict_db.h
+nbdb_redirect.o: ../../include/dict_lmdb.h
+nbdb_redirect.o: ../../include/mkmap.h
+nbdb_redirect.o: ../../include/msg.h
+nbdb_redirect.o: ../../include/myflock.h
+nbdb_redirect.o: ../../include/mymalloc.h
+nbdb_redirect.o: ../../include/name_code.h
+nbdb_redirect.o: ../../include/stringops.h
+nbdb_redirect.o: ../../include/sys_defs.h
+nbdb_redirect.o: ../../include/vbuf.h
+nbdb_redirect.o: ../../include/vstream.h
+nbdb_redirect.o: ../../include/vstring.h
+nbdb_redirect.o: mail_params.h
+nbdb_redirect.o: nbdb_clnt.h
+nbdb_redirect.o: nbdb_redirect.c
+nbdb_redirect.o: nbdb_redirect.h
+nbdb_redirect.o: nbdb_util.h
+nbdb_redirect_test.o: ../../include/argv.h
+nbdb_redirect_test.o: ../../include/check_arg.h
+nbdb_redirect_test.o: ../../include/dict.h
+nbdb_redirect_test.o: ../../include/dict_cdb.h
+nbdb_redirect_test.o: ../../include/dict_db.h
+nbdb_redirect_test.o: ../../include/dict_inline.h
+nbdb_redirect_test.o: ../../include/dict_lmdb.h
+nbdb_redirect_test.o: ../../include/mkmap.h
+nbdb_redirect_test.o: ../../include/mock_dict.h
+nbdb_redirect_test.o: ../../include/msg.h
+nbdb_redirect_test.o: ../../include/msg_capture.h
+nbdb_redirect_test.o: ../../include/msg_vstream.h
+nbdb_redirect_test.o: ../../include/myflock.h
+nbdb_redirect_test.o: ../../include/mymalloc.h
+nbdb_redirect_test.o: ../../include/stringops.h
+nbdb_redirect_test.o: ../../include/sys_defs.h
+nbdb_redirect_test.o: ../../include/vbuf.h
+nbdb_redirect_test.o: ../../include/vstream.h
+nbdb_redirect_test.o: ../../include/vstring.h
+nbdb_redirect_test.o: mail_params.h
+nbdb_redirect_test.o: nbdb_redirect.h
+nbdb_redirect_test.o: nbdb_redirect_test.c
+nbdb_redirect_test.o: nbdb_util.h
+nbdb_surrogate.o: ../../include/argv.h
+nbdb_surrogate.o: ../../include/check_arg.h
+nbdb_surrogate.o: ../../include/dict.h
+nbdb_surrogate.o: ../../include/dict_db.h
+nbdb_surrogate.o: ../../include/mkmap.h
+nbdb_surrogate.o: ../../include/msg.h
+nbdb_surrogate.o: ../../include/myflock.h
+nbdb_surrogate.o: ../../include/sys_defs.h
+nbdb_surrogate.o: ../../include/vbuf.h
+nbdb_surrogate.o: ../../include/vstream.h
+nbdb_surrogate.o: ../../include/vstring.h
+nbdb_surrogate.o: nbdb_surrogate.c
+nbdb_surrogate.o: nbdb_surrogate.h
+nbdb_surrogate_test.o: ../../include/argv.h
+nbdb_surrogate_test.o: ../../include/check_arg.h
+nbdb_surrogate_test.o: ../../include/dict.h
+nbdb_surrogate_test.o: ../../include/dict_db.h
+nbdb_surrogate_test.o: ../../include/mkmap.h
+nbdb_surrogate_test.o: ../../include/msg.h
+nbdb_surrogate_test.o: ../../include/msg_capture.h
+nbdb_surrogate_test.o: ../../include/msg_vstream.h
+nbdb_surrogate_test.o: ../../include/myflock.h
+nbdb_surrogate_test.o: ../../include/mymalloc.h
+nbdb_surrogate_test.o: ../../include/stringops.h
+nbdb_surrogate_test.o: ../../include/sys_defs.h
+nbdb_surrogate_test.o: ../../include/vbuf.h
+nbdb_surrogate_test.o: ../../include/vstream.h
+nbdb_surrogate_test.o: ../../include/vstring.h
+nbdb_surrogate_test.o: mail_params.h
+nbdb_surrogate_test.o: nbdb_surrogate.h
+nbdb_surrogate_test.o: nbdb_surrogate_test.c
+nbdb_surrogate_test.o: nbdb_util.h
+nbdb_util.o: ../../include/argv.h
+nbdb_util.o: ../../include/check_arg.h
+nbdb_util.o: ../../include/dict.h
+nbdb_util.o: ../../include/dict_cdb.h
+nbdb_util.o: ../../include/dict_db.h
+nbdb_util.o: ../../include/dict_lmdb.h
+nbdb_util.o: ../../include/mkmap.h
+nbdb_util.o: ../../include/msg.h
+nbdb_util.o: ../../include/myflock.h
+nbdb_util.o: ../../include/mymalloc.h
+nbdb_util.o: ../../include/name_code.h
+nbdb_util.o: ../../include/split_at.h
+nbdb_util.o: ../../include/stringops.h
+nbdb_util.o: ../../include/sys_defs.h
+nbdb_util.o: ../../include/vbuf.h
+nbdb_util.o: ../../include/vstream.h
+nbdb_util.o: ../../include/vstring.h
+nbdb_util.o: mail_params.h
+nbdb_util.o: nbdb_redirect.h
+nbdb_util.o: nbdb_surrogate.h
+nbdb_util.o: nbdb_util.c
+nbdb_util.o: nbdb_util.h
+nbdb_util_test.o: ../../include/argv.h
+nbdb_util_test.o: ../../include/check_arg.h
+nbdb_util_test.o: ../../include/dict.h
+nbdb_util_test.o: ../../include/mock_dict.h
+nbdb_util_test.o: ../../include/msg.h
+nbdb_util_test.o: ../../include/msg_capture.h
+nbdb_util_test.o: ../../include/msg_vstream.h
+nbdb_util_test.o: ../../include/myflock.h
+nbdb_util_test.o: ../../include/stringops.h
+nbdb_util_test.o: ../../include/sys_defs.h
+nbdb_util_test.o: ../../include/vbuf.h
+nbdb_util_test.o: ../../include/vstream.h
+nbdb_util_test.o: ../../include/vstring.h
+nbdb_util_test.o: mail_params.h
+nbdb_util_test.o: nbdb_redirect.h
+nbdb_util_test.o: nbdb_util.h
+nbdb_util_test.o: nbdb_util_test.c
normalize_mailhost_addr.o: ../../include/check_arg.h
normalize_mailhost_addr.o: ../../include/inet_proto.h
normalize_mailhost_addr.o: ../../include/msg.h
--- /dev/null
+/*++
+/* NAME
+/* allowed_prefix 3
+/* SUMMARY
+/* Match a pathname against a list of allowed parent directories
+/* SYNOPSIS
+/* #include <allowed_prefix.h>
+/*
+/* ALLOWED_PREFIX *allowed_prefix_create(const char *prefixes)
+/*
+/* bool allowed_prefix_match(
+/* ALLOWED_PREFIX *tp,
+/* const char *candidate_path)
+/*
+/* void allowed_prefix_free(ALLOWED_PREFIX *tp)
+/* DESCRIPTION
+/* This module matches an absolute candidate pathname against a
+/* list of allowed absolute parent directory names. The matching
+/* is based solely on string comparisons.
+/*
+/* The matcher will not match relative pathnames, and logs a warning
+/* if it encounters one in its inputs.
+/*
+/* allowed_prefix_create() instantiates an allowed parent matcher
+/* and returns a pointer to the result. The input must be a list
+/* of directory absolute pathnames separated by comma or whitespace.
+/*
+/* allowed_prefix_match() matches a candidate absolute pathname
+/* against an ALLOWED_PREFIX instance.
+/*
+/* allowed_prefix_free() destroys an ALLOWED_PREFIX instance.
+/* BUGS
+/* Does not collapse multiple instances of '/' in the middle of a
+/* pathname.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <htable.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <split_at.h>
+#include <stringops.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+
+/* decline_request_with - shared nagging code */
+
+static bool decline_request_with(const char *what, const char *path)
+{
+ msg_warn("request to allowlist prefix with %s: '%s'", what, path);
+ return (false);
+}
+
+/* allowed_prefix_create - instantiate an allowed parent matcher */
+
+ALLOWED_PREFIX *allowed_prefix_create(const char *prefixes)
+{
+ ALLOWED_PREFIX *tp;
+ char *bp, *prefix, *saved_prefixes;
+ size_t len;
+
+ bp = saved_prefixes = mystrdup(prefixes);
+ tp = argv_alloc(5);
+ while ((prefix = mystrtok(&bp, CHARS_COMMA_SP)) != 0) {
+ if (*prefix != '/') {
+ (void) decline_request_with("relative pathname",prefix);
+ continue;
+ }
+ /* Trim trailing '/'. */
+ for (len = strlen(prefix); len > 0; len--) {
+ if (prefix[len - 1] != '/')
+ break;
+ }
+ prefix[len] = 0;
+ argv_add(tp, prefix, (char *) 0);
+ }
+ myfree(saved_prefixes);
+ return (tp);
+}
+
+/* allowed_prefix_match - match candidate against allowed prefixes */
+
+bool allowed_prefix_match(ALLOWED_PREFIX *tp, const char *candidate_path)
+{
+ char **cpp;
+ ssize_t len;
+
+ if (*candidate_path != '/')
+ return (decline_request_with("relative pathname", candidate_path));
+ if (strstr(candidate_path, "/../") != 0)
+ return (decline_request_with("'/../'", candidate_path));
+
+ /*
+ * The number of allowed prefixes will be limited. linear search will be
+ * OK.
+ */
+ for (cpp = tp->argv; *cpp; cpp++) {
+ len = strlen(*cpp);
+ if (strncmp(*cpp, candidate_path, len) == 0
+ && candidate_path[len] == '/')
+ return (true);
+ }
+ return (false);
+}
+
+/* allowed_prefix_free - destroy allowed parent matcher */
+
+void allowed_prefix_free(ALLOWED_PREFIX *tp)
+{
+ argv_free(tp);
+}
--- /dev/null
+#ifndef _ALLOWED_PARENT_H_INCLUDED_
+#define _ALLOWED_PARENT_H_INCLUDED_
+
+/*++
+/* NAME
+/* allowed_prefix 3h
+/* SUMMARY
+/* Match a pathname against a list of allowed parent directories
+/* SYNOPSIS
+/* #include <allowed_prefix.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+
+ /*
+ * External interface.
+ */
+typedef ARGV ALLOWED_PREFIX;
+extern ALLOWED_PREFIX *allowed_prefix_create(const char *);
+extern bool allowed_prefix_match(ALLOWED_PREFIX *, const char *);
+extern void allowed_prefix_free(ALLOWED_PREFIX *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* allowed_prefix_test 1t
+/* SUMMARY
+/* allowed_prefix unit test
+/* SYNOPSIS
+/* ./allowed_prefix_test
+/* DESCRIPTION
+/* allowed_prefix_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <stringops.h>
+#include <msg_vstream.h>
+#include <vstring.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+
+ /*
+ * Testing library.
+ */
+#include <msg_capture.h>
+
+ /*
+ * Test structure. Some tests may bring their own.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+ const char *candidate;
+ const char *parents;
+ const bool want_match;
+ const char *want_warning;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+#define bool_to_text(b) ((b) ? "true" : "false")
+
+/* test_allowed_prefixes - generic test wrapper */
+
+static int test_allowed_prefixes(const TEST_CASE *tp)
+{
+ MSG_CAPTURE *capture = msg_capt_create(100);
+ ALLOWED_PREFIX *ap;
+ bool got_match;
+ const char *got_warning;
+
+ /* Run the test with captured VSTREAM_ERR stream. */
+ msg_capt_start(capture);
+ ap = allowed_prefix_create(tp->parents);
+ got_match = allowed_prefix_match(ap, tp->candidate);
+ allowed_prefix_free(ap);
+ msg_capt_stop(capture);
+
+ /* Verify the results. */
+ got_warning = msg_capt_expose(capture);
+ if (tp->want_warning == 0 && *got_warning != 0) {
+ msg_warn("got warning ``%s'', want ``null''", got_warning);
+ return (FAIL);
+ }
+ if (tp->want_warning != 0
+ && strstr(got_warning, tp->want_warning) == 0) {
+ msg_warn("got warning ``%s'', want ``%s''",
+ got_warning, tp->want_warning);
+ return (FAIL);
+ }
+ if (tp->want_match != got_match) {
+ msg_warn("got match ``%s'', want ``%s''",
+ bool_to_text(got_match), bool_to_text(tp->want_match));
+ return (FAIL);
+ }
+ msg_capt_free(capture);
+ return (PASS);
+}
+
+ /*
+ * The list of test cases.
+ */
+static const TEST_CASE test_cases[] = {
+ {.label = "all_absolute_non_root_with_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix /etc/other, /foo/bar",
+ .candidate = "/etc/other/foo",
+ .want_match = true,
+ },
+ {.label = "all_absolute_non_root_no_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix /etc/other, /foo/bar",
+ .candidate = "/etc/foo/other",
+ .want_match = false,
+ },
+ {.label = "all_absolute_root_candidate_short_overlap",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix /etc/other, /foo/bar",
+ .candidate = "/",
+ .want_match = false,
+ },
+ {.label = "all_absolute_root_parent_with_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix, /, /foo/bar",
+ .candidate = "/whatever",
+ .want_match = true,
+ },
+ {.label = "one_relative_root_parent_with_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix foo /foo/bar",
+ .candidate = "/foo/bar/whatever",
+ .want_match = true,
+ .want_warning = "to allowlist prefix with relative pathname: 'foo'",
+ },
+ {.label = "absolute_parent_relative_candidate_no_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix /etc/other /foo/bar",
+ .candidate = "bar",
+ .want_match = false,
+ .want_warning = "to allowlist prefix with relative pathname: 'bar'",
+ },
+ {.label = "absolute_parent_dot_dot_candidate_no_match",
+ .action = test_allowed_prefixes,
+ .parents = "/etc/postfix /etc/other /foo/bar",
+ .candidate = "/etc/postfix/../other",
+ .want_match = false,
+ .want_warning = "allowlist prefix with '/../': '/etc/postfix/../other'",
+ },
+ {.label = "trusted_root_directory_allows_all",
+ .action = test_allowed_prefixes,
+ .parents = "/ /foo/bar",
+ .candidate = "/whatever",
+ .want_match = true,
+ },
+
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
/* bool var_relay_before_rcpt_checks;
/* bool var_respectful_logging;
/* char *var_known_tcp_ports;
+/*
+/* char *var_nbdb_level;
+/* char *var_nbdb_service;
+/* char *var_nbdb_cust_map;
/* DESCRIPTION
/* This module (actually the associated include file) defines
/* the names and defaults of all mail configuration parameters.
#include <verp_sender.h>
#include <own_inet_addr.h>
#include <mail_params.h>
+#include <nbdb_util.h>
#include <compat_level.h>
#include <config_known_tcp_ports.h>
bool var_respectful_logging;
char *var_known_tcp_ports;
+char *var_nbdb_level;
+char *var_nbdb_service;
+char *var_nbdb_cust_map;
+
const char null_format_string[1] = "";
/*
VAR_SMTPUTF8_AUTOCLASS, DEF_SMTPUTF8_AUTOCLASS, &var_smtputf8_autoclass, 1, 0,
VAR_DROP_HDRS, DEF_DROP_HDRS, &var_drop_hdrs, 0, 0,
VAR_INFO_LOG_ADDR_FORM, DEF_INFO_LOG_ADDR_FORM, &var_info_log_addr_form, 1, 0,
+ VAR_NBDB_LEVEL, DEF_NBDB_LEVEL, &var_nbdb_level, 1, 0,
+ VAR_NBDB_SERVICE, DEF_NBDB_SERVICE, &var_nbdb_service, 0, 0,
+ VAR_NBDB_CUST_MAP, DEF_NBDB_CUST_MAP, &var_nbdb_cust_map, 0, 0,
0,
};
static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
msg_fatal("file %s/%s: parameters %s and %s: %s",
var_config_dir, MAIN_CONF_FILE,
VAR_VERP_DELIMS, VAR_VERP_FILTER, cp);
+
+ /*
+ * Non-Berkeley-DB migration support.
+ */
+ nbdb_util_init(var_nbdb_level);
}
#define DEF_SMTPD_REJECT_FILTER_MAPS ""
extern char *var_smtpd_reject_filter_maps;
+ /*
+ * Non-Berkeley-DB migration.
+ */
+#define NBDB_LEV_NAME_NONE "disable"
+#define NBDB_LEV_NAME_REDIRECT "enable-redirect"
+#define NBDB_LEV_NAME_REINDEX "enable-reindex"
+
+#define VAR_NBDB_LEVEL "non_bdb_migration_level"
+#define DEF_NBDB_LEVEL NBDB_LEV_NAME_NONE
+extern char *var_nbdb_level;
+
+#define VAR_NBDB_CUST_MAP "non_bdb_custom_mapping"
+#define DEF_NBDB_CUST_MAP ""
+extern char *var_nbdb_cust_map;
+
+#define VAR_NBDB_SERVICE "non_bdb_migration_service_name"
+#define DEF_NBDB_SERVICE "nbdb_reindex"
+extern char *var_nbdb_service;
+
+#define VAR_NBDB_ALLOW_ROOT_PFXS "non_bdb_migration_allow_root_prefixes"
+#define DEF_NBDB_ALLOW_ROOT_PFXS "/etc /usr/local/etc"
+extern char *var_nbdb_allow_root_pfxs;
+
+#define VAR_NBDB_ALLOW_USER_PFXS "non_bdb_migration_allow_user_prefixes"
+#define DEF_NBDB_ALLOW_USER_PFXS "$" VAR_DATA_DIR " /var/lib/mailman" \
+ " /var/lib/mailman3"
+extern char *var_nbdb_allow_user_pfxs;
+
/* LICENSE
/* .ad
/* .fi
*/
#define MAIL_ATTR_SERVER_NAME "server_name"
+ /*
+ * Non-Berkeley-DB migration.
+ */
+#define MAIL_ATTR_PROTO_NBDB_REINDEX "nbdb_reindex" /* Re-index protocol */
+#define MAIL_ATTR_NBDB_TYPE "nbdb_type" /* maptype */
+#define MAIL_ATTR_NBDB_PATH "nbdb_path" /* mapname */
+
/* LICENSE
/* .ad
/* .fi
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20260218"
+#define MAIL_RELEASE_DATE "20260227"
#define MAIL_VERSION_NUMBER "3.12"
#ifdef SNAPSHOT
--- /dev/null
+/*++
+/* NAME
+/* nbdb_clnt 3
+/* SUMMARY
+/* Non-Berkeley-DB migration client
+/* SYNOPSIS
+/* #include <nbdb_clnt.h>
+/*
+/* void nbdb_clnt_request(
+/* const char *type,
+r* const char *source_path,
+/* int maxtry,
+/* int timeout,
+/* int delay,
+/* VSTRING *why)
+/* DESCRIPTION
+/* nbdb_clnt_request() asks the reindexing server to index a source
+/* file using a non-legacy database type. The result is one of
+/* the following:
+/* .IP NBDB_STAT_OK
+/* The request was successful.
+/* .IP NBDB_STAT_ERROR
+/* The request failed. A description of the problem is returned
+/* in \fBwhy\fR.
+/*
+/* Arguments:
+/* .IP type
+/* A legacy database type. The reindexing server will map it
+/* to a non-legacy type.
+/* .IP path
+/* The pathname of the database source file (no '.db' suffix).
+/* .IP maxtry
+/* The number of attempts to make before giving up.
+/* .IP timeout
+/* The time limit (seconds) to connect, write, or read.
+/* Specify enough time to index a large table.
+/* .IP delay
+/* The amount of time (seconds) between retries.
+/* .IP Implicit inputs:
+/* var_nbdb_service, nbdb_reindex service name.
+/* .IP why
+/* Storage that is updated with an applicable error description.
+/* SEE ALSO
+/* nbdb_reindexd(8) reindexing server.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <attr.h>
+#include <connect.h>
+#include <msg.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <nbdb_clnt.h>
+
+#define STR(x) vstring_str(x)
+
+/* try_one - single request attempt */
+
+static int try_one(const char *service_path, const char *type,
+ const char *path, int timeout, int delay, VSTRING *why)
+{
+ int fd;
+ VSTREAM *reindexd_stream = 0;
+ int status;
+
+#define NBDB_MIGR_CLNT_RETURN(x) do { \
+ if (reindexd_stream) \
+ vstream_fclose(reindexd_stream); \
+ return (x); \
+ } while (0)
+
+ if ((fd = LOCAL_CONNECT(service_path, BLOCKING, timeout)) < 0) {
+ vstring_sprintf(why, "connection to %s service: %m", service_path);
+ NBDB_MIGR_CLNT_RETURN(NBDB_STAT_ERROR);
+ }
+ reindexd_stream = vstream_fdopen(fd, O_RDWR);
+ vstream_control(reindexd_stream,
+ CA_VSTREAM_CTL_TIMEOUT(timeout),
+ CA_VSTREAM_CTL_START_DEADLINE,
+ CA_VSTREAM_CTL_END);
+ /* Enforce the server protocol type. */
+ if (attr_scan(reindexd_stream, ATTR_FLAG_STRICT,
+ RECV_ATTR_STREQ(MAIL_ATTR_PROTO,
+ MAIL_ATTR_PROTO_NBDB_REINDEX),
+ ATTR_TYPE_END) != 0) {
+ vstring_sprintf(why, "error receiving %s service initial response",
+ service_path);
+ NBDB_MIGR_CLNT_RETURN(NBDB_STAT_ERROR);
+ }
+ /* Send the reindexing request. */
+ attr_print(reindexd_stream, ATTR_FLAG_NONE,
+ SEND_ATTR_STR(MAIL_ATTR_NBDB_TYPE, type),
+ SEND_ATTR_STR(MAIL_ATTR_NBDB_PATH, path),
+ ATTR_TYPE_END);
+ /* Do not flush the stream yet (would clobber errno). */
+ if (vstream_ferror(reindexd_stream) != 0) {
+ vstring_sprintf(why, "error sending request to %s service: %m",
+ service_path);
+ NBDB_MIGR_CLNT_RETURN(NBDB_STAT_ERROR);
+ }
+ /* Receive the reindexing status. */
+ if (attr_scan(reindexd_stream, ATTR_FLAG_STRICT,
+ RECV_ATTR_INT(MAIL_ATTR_STATUS, &status),
+ RECV_ATTR_STR(MAIL_ATTR_WHY, why),
+ ATTR_TYPE_END) != 2) {
+ vstring_sprintf(why, "error receiving response from %s service: %m",
+ service_path);
+ NBDB_MIGR_CLNT_RETURN(NBDB_STAT_ERROR);
+ }
+ NBDB_MIGR_CLNT_RETURN(status);
+}
+
+/* nbdb_clnt_request - send a request and don't hang forever */
+
+int nbdb_clnt_request(const char *type, const char *path,
+ int max_try, int timeout, int delay,
+ VSTRING *why)
+{
+ VSTRING *service_path = vstring_alloc(100);
+ int status;
+ int count;
+
+ /*
+ * A custom client endpoint that tries only a few times and that may be
+ * called by:
+ *
+ * - A daemon process. This should keep running if the reindexing service is
+ * unavailable, and needs to specify a relative service pathname in case
+ * it is chrooted.
+ *
+ * - A command-line process. This almost always needs to specify an absolute
+ * pathname. This usage is limited to the super-user.
+ */
+ vstring_sprintf(service_path, "%s/%s", MAIL_CLASS_PRIVATE,
+ var_nbdb_service);
+ if (access(STR(service_path), F_OK) != 0)
+ vstring_sprintf(service_path, "%s/%s/%s", var_queue_dir,
+ MAIL_CLASS_PRIVATE, var_nbdb_service);
+ for (count = 0; count < max_try; count++) {
+ status = try_one(STR(service_path), type, path, timeout, delay, why);
+ if (status == NBDB_STAT_OK)
+ break;
+ if (count < max_try - 1)
+ sleep(delay);
+ }
+ vstring_free(service_path);
+ return (status);
+}
--- /dev/null
+#ifndef _NBDB_CLNT_H_INCLUDED_
+#define _NBDB_CLNT_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_clnt 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration client
+/* SYNOPSIS
+/* #include <nbdb_clnt.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <nbdb_util.h>
+
+extern int nbdb_clnt_request(const char *, const char *, int, int, int, VSTRING *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_redirect 3
+/* SUMMARY
+/* Non-Berkeley-DB migration support
+/* SYNOPSIS
+/* #include <nbdb_redirect.h>
+/*
+/* void nbdb_rdr_init(int level)
+/* DESCRIPTION
+/* This module contains code that may be called by command-line
+/* tools and by clients of the non-Berkeley-DB migration service.
+/*
+/* nbdb_rdr_init() destructively registers surrogate dict_open()
+/* and mkmap_open() handlers for legacy types 'hash' and 'btree',
+/* that map these type names to $var_db_type and $var_cache_db_type,
+/* respectively, and that may send requests to a reindexing
+/* server. The mapping from legacy to non-legacy type names is
+/* implemented by nbdb_map_leg_type().
+/* SEE ALSO
+/* nbdb_reindexd(8), helper daemon to reindex legacy tables
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict_cdb.h>
+#include <dict_db.h>
+#include <dict.h>
+#include <dict_lmdb.h>
+#include <mkmap.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <name_code.h>
+#include <stringops.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_clnt.h>
+#include <nbdb_redirect.h>
+#include <nbdb_util.h>
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+
+ /*
+ * Application-specific.
+ */
+
+static VSTRING *why = 0;
+
+/* call_nbdb_reindexd - wrapper for nbdb_reindexd client */
+
+static DICT *call_nbdb_reindexd(const char *leg_type, const char *name,
+ int open_flags, int dict_flags)
+{
+ DICT *surrogate;
+ VSTRING *why;
+ int nbdb_stat;
+
+ /*
+ * TODO(wietse) make this go away.
+ */
+#define MAX_TRY 2
+#define TIMEOUT 30
+#define DELAY 1
+
+
+ why = vstring_alloc(100);
+ switch (nbdb_stat = nbdb_clnt_request(leg_type, name, MAX_TRY, TIMEOUT,
+ DELAY, why)) {
+ case NBDB_STAT_OK:
+ if (msg_verbose)
+ msg_info("%s: delegated '%s:%s'", __func__, leg_type, name);
+ surrogate = 0;
+ break;
+ case NBDB_STAT_ERROR:
+ msg_warn("Non-Berkeley-DB migration error: %s", STR(why));
+ surrogate =
+ dict_surrogate(leg_type, name, open_flags, dict_flags,
+ "Non-Berkeley-DB migration error: %s", STR(why));
+ break;
+ default:
+ msg_warn("Non-Berkeley-DB migration error: malformed "
+ "bad reindexing status: %d", nbdb_stat);
+ surrogate = dict_surrogate(leg_type, name, open_flags, dict_flags,
+ "Non-Berkeley-DB migration error: "
+ "bad reindexing server status: %d",
+ nbdb_stat);
+ }
+ vstring_free(why);
+ return (surrogate);
+}
+
+ /*
+ * Code to redirect dict_open() requests to non-legacy database types. This
+ * code may be called from daemon processes, and therefore all errors are
+ * handled by creating a surrogate database instance that returns an error
+ * status for each request, and that logs why.
+ *
+ * Program flow:
+ *
+ * - A client program calls dict_open().
+ *
+ * - dict_open() looks up "our" DICT_OPEN_INFO with dict_fn and mkmap_fn
+ * members that resolve to functions in this code module.
+ *
+ * - dict_open() calls our DICT_OPEN_INFO.dict_fn() function which calls the
+ * dict_xxx_open() method of the non-legacy type. That function returns a
+ * DICT object for the non-legacy implementation (typically, cdb or lmdb).
+ */
+
+/* nbdb_dict_open - redirect dict_open() to non-Berkeley-DB type */
+
+static DICT *nbdb_dict_open(const char *leg_type, const char *name,
+ int open_flags, int dict_flags)
+{
+ const DICT_OPEN_INFO *open_info;
+ const char *non_leg_type;
+ char *non_leg_index_path;
+ const char *non_leg_suffix;
+ int stat_res, saved_errno;
+ DICT *surrogate;
+ struct stat st;
+
+ if (why == 0)
+ why = vstring_alloc(100);
+
+ /*
+ * Look up the type mapping, which may depend on the database name.
+ */
+ non_leg_type = nbdb_map_leg_type(leg_type, name, &open_info, why);
+ if (non_leg_type == 0) {
+ msg_warn("non-Berkeley-DB type mapping lookup error for '%s:%s': %s",
+ leg_type, name, STR(why));
+ return (dict_surrogate(leg_type, name, open_flags, dict_flags,
+ "Berkeley DB type mapping lookup error for "
+ "'%s:%s': %s", leg_type, name, STR(why)));
+ }
+
+ /*
+ * Do not delegate dict_open() requests to create an indexed file (this
+ * is typical for daemon-maintained caches). If a process does not have
+ * permissions to create the indexed file, then the nbdb reindexing
+ * service must not create it for them.
+ */
+ if ((open_flags & O_CREAT) == 0
+ && nbdb_level >= NBDB_LEV_CODE_REINDEX) {
+
+ /*
+ * If the non-legacy indexed file does not already exist, call the
+ * nbdb reindexing service to create a non-legacy indexed file, and
+ * then access the indexed file directly. The service will enforce a
+ * safety policy based on the ownership of the legacy indexed file.
+ */
+ if ((non_leg_suffix = nbdb_find_non_leg_suffix(non_leg_type)) == 0) {
+ msg_warn("non-Berkeley-DB mapped type '%s' has no known pathname "
+ "suffix", non_leg_type);
+ return (dict_surrogate(leg_type, name, open_flags, dict_flags,
+ "non-Berkeley-DB mapped type '%s' has no "
+ "known pathname suffix", non_leg_type));
+ }
+ non_leg_index_path = concatenate(name, non_leg_suffix, (char *) 0);
+ stat_res = stat (non_leg_index_path, &st);
+
+ saved_errno = errno;
+ myfree(non_leg_index_path);
+ if (stat_res < 0 && saved_errno == ENOENT
+ && (surrogate = call_nbdb_reindexd(leg_type, name, open_flags,
+ dict_flags)) != 0)
+ return (surrogate);
+ }
+ return (open_info->dict_fn(name, open_flags, dict_flags));
+}
+
+/* nbdb_dict_hash_open - map hash legacy type to non-legacy type */
+
+static DICT *nbdb_dict_hash_open(const char *name, int open_flags, int dict_flags)
+{
+ return (nbdb_dict_open(DICT_TYPE_HASH, name, open_flags, dict_flags));
+}
+
+/* nbdb_dict_btree_open - map btree legacy type to non-legacy type */
+
+static DICT *nbdb_dict_btree_open(const char *name, int open_flags, int dict_flags)
+{
+ return (nbdb_dict_open(DICT_TYPE_BTREE, name, open_flags, dict_flags));
+}
+
+ /*
+ * Code that is used by postmap and postalias bulk create and incremental
+ * mode, to redirect requests with a legacy type name to a non-legacy type.
+ * These requests are always executed without delegation to a privileged
+ * daemon. If the user does not have permission to create or update the
+ * table, then the request is invalid. As this code is called from
+ * command-line tools, all errors are fatal.
+ *
+ * Limitation: because this code does not call the reindexing service, this
+ * will not work for postmap and postalias incremental updates ("postmap -i"
+ * etc.) when a database has not yet been reindexed. Fortunately, Postfix
+ * itself does not make incremental non-cache updates.
+ *
+ * Program flow:
+ *
+ * - The postmap or postalias commands call mkmap_open().
+ *
+ * - mkmap_open() looks up "our" DICT_OPEN_INFO with dict_fn and mkmap_fn
+ * members that resolve to functions in this code module.
+ *
+ * - mkmap_open() calls our DICT_OPEN_INFO.mkmap_fn() function which calls the
+ * mkmap_xxx_open() method of the non-legacy type. That function returns a
+ * MKMAP object with function pointers for the non-legacy implementation
+ * (typically, cdb or lmdb).
+ *
+ * - mkmap_open() then calls MKMAP.open() (in bulk and incremental mode), and
+ * calls other MKMAP function members as appropriate, for example to manage
+ * a lock.
+ */
+
+/* nbdb_mkmap_open - redirect legacy type to non-legacy */
+
+static MKMAP *nbdb_mkmap_open(const char *leg_type, const char *name)
+{
+ const DICT_OPEN_INFO *open_info;
+ const char *non_leg_type;
+
+ if (why == 0)
+ why = vstring_alloc(100);
+
+ /*
+ * Look up the legacy type to non-legacy type mapping, which may depend
+ * on the database name. Errors are fatal.
+ */
+ non_leg_type = nbdb_map_leg_type(leg_type, name, &open_info, why);
+ if (non_leg_type == 0)
+ msg_fatal("non_bdb migration mapping lookup error for '%s': %s",
+ leg_type, STR(why));
+ if (open_info->mkmap_fn == 0)
+ msg_fatal("no 'map create' support for non_bdb mapped type: %s",
+ non_leg_type);
+ return (open_info->mkmap_fn(name));
+}
+
+/* nbdb_mkmap_hash_open - map hash legacy type to non-legacy type */
+
+static MKMAP *nbdb_mkmap_hash_open(const char *path)
+{
+ return (nbdb_mkmap_open(DICT_TYPE_HASH, path));
+}
+
+/* nbdb_mkmap_btree_open - map btree legacy type to non-legacy type */
+
+static MKMAP *nbdb_mkmap_btree_open(const char *path)
+{
+ return (nbdb_mkmap_open(DICT_TYPE_BTREE, path));
+}
+
+ /*
+ * Surrogate hash: and btree: support for dict_open(). These handlers will
+ * typically redirect hash: requests to the default database type (for
+ * mostly-constant tables) and will redirect btree: requests to the default
+ * cache type (mostly for daemon cache).
+ */
+static const DICT_OPEN_INFO nbdb_info[] = {
+ DICT_TYPE_HASH, nbdb_dict_hash_open, nbdb_mkmap_hash_open,
+ DICT_TYPE_BTREE, nbdb_dict_btree_open, nbdb_mkmap_btree_open,
+ 0,
+};
+
+/* nbdb_rdr_init - redirect legacy open() requests to nbdb handlers */
+
+void nbdb_rdr_init(void)
+{
+ const DICT_OPEN_INFO *info;
+
+ /*
+ * Un-register each legacy type handler. This is needed if the system was
+ * built without -DNO_DB). Then, register the forward-compatibility
+ * handlers.
+ */
+ if (nbdb_level >= NBDB_LEV_CODE_REDIRECT) {
+ for (info = nbdb_info; info->type; info++) {
+ if (dict_open_lookup(info->type) != 0)
+ dict_open_unregister(info->type);
+ if (msg_verbose)
+ msg_info("%s: installing custom handlers for '%s'",
+ __func__, info->type);
+ dict_open_register(info);
+ }
+ }
+}
--- /dev/null
+#ifndef _NBDB_REDIRECT_H_INCLUDED_
+#define _NBDB_REDIRECT_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_redirect 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration support
+/* SYNOPSIS
+/* #include <nbdb_redirect.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * External API.
+ */
+extern void nbdb_rdr_init(void);
+
+#define NBDB_LEGACY_SUFFIX ".db"
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_redirect_test 1t
+/* SUMMARY
+/* nbdb_redirect unit test
+/* SYNOPSIS
+/* ./nbdb_redirect_test
+/* DESCRIPTION
+/* nbdb_redirect_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict_cdb.h>
+#include <dict_db.h>
+#include <dict.h>
+#include <dict_inline.h>
+#include <dict_lmdb.h>
+#include <mkmap.h>
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_util.h>
+#include <nbdb_redirect.h>
+
+ /*
+ * Testing library.
+ */
+#include <msg_capture.h>
+#include <mock_dict.h>
+
+#define PASS (0)
+#define FAIL (1)
+
+#define STR(x) vstring_str(x)
+
+char *var_nbdb_cust_map = DEF_NBDB_CUST_MAP;
+
+ /*
+ * Tests that a dict_open() request for 'hash' or 'btree' will redirect to
+ * $default_database_type or $default_cache_db_type. These use mock cdb and
+ * lmdb clients that will respond with their type when queried for "whoami".
+ *
+ * The redirect unit tests do not cover the 'bulk create' code paths; those
+ * will be tested with postmap/postalias 'whole program' tests.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+} TEST_CASE;
+
+static void setup_common_mock_open_info(void)
+{
+ nbdb_level = NBDB_LEV_CODE_REDIRECT;
+
+ nbdb_reindexing_lockout = 0;
+ setup_mock_cdb("{{whoami = mock cdb}}");
+ setup_mock_lmdb("{{whoami = mock lmdb}}");
+ nbdb_rdr_init();
+}
+
+static int redirects_dict_open_hash_to_def_db_type(const TEST_CASE *tp)
+{
+ const char *got_whoami;
+ DICT *dict;
+ int status = PASS;
+ const char *want_whoami;
+
+ /*
+ * Setup. Use the mapping hash->cdb.
+ */
+ setup_common_mock_open_info();
+ var_db_type = "cdb";
+
+ /*
+ * Verify that 'hash' redirects to $default_database_type ('cdb').
+ */
+ want_whoami = "mock cdb";
+ dict = dict_open3(DICT_TYPE_HASH, "ignored", O_RDONLY, 0);
+ if ((got_whoami = dict_get(dict, "whoami")) == 0) {
+ msg_warn("'whoami' query returned 'not found'");
+ status = FAIL;
+ } else if (strstr(got_whoami, want_whoami) == 0) {
+ msg_warn("unexpected result; got: '%s', want: '%s'",
+ got_whoami, want_whoami);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ return (status);
+}
+
+static int redirects_dict_open_btree_to_def_cache_db_type(const TEST_CASE *tp)
+{
+ const char *got_whoami;
+ DICT *dict;
+ int status = PASS;
+ const char *want_whoami;
+
+ /*
+ * Setup. Use the mapping btree->lmdb.
+ */
+ setup_common_mock_open_info();
+ var_cache_db_type = "lmdb";
+
+ /*
+ * Verify that 'btree' redirects to $default_cache_db_type ('lmdb').
+ */
+ want_whoami = "mock lmdb";
+ dict = dict_open3(DICT_TYPE_BTREE, "ignored", O_RDONLY, 0);
+ if ((got_whoami = dict_get(dict, "whoami")) == 0) {
+ msg_warn("'whoami' query returned 'not found'");
+ status = FAIL;
+ } else if (strstr(got_whoami, "mock lmdb") == 0) {
+ msg_warn("unexpected result; got: '%s', want: '%s'",
+ got_whoami, want_whoami);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ return (status);
+}
+
+static int redirects_mkmap_open_hash_to_def_db_type(const TEST_CASE *tp)
+{
+ const char *got_whoami;
+ MKMAP *mkmap;
+ int status = PASS;
+ const char *want_whoami;
+
+ /*
+ * Setup. Use the mapping hash->cdb.
+ */
+ setup_common_mock_open_info();
+ var_db_type = "cdb";
+
+ /*
+ * Verify that mkmap_open("hash"...) redirects to $default_database_type
+ * ('cdb').
+ */
+ want_whoami = "mock cdb";
+ mkmap = mkmap_open(DICT_TYPE_HASH, "ignored", O_RDONLY, 0);
+ if ((got_whoami = dict_get(mkmap->dict, "whoami")) == 0) {
+ msg_warn("'whoami' query returned 'not found'");
+ status = FAIL;
+ } else if (strstr(got_whoami, want_whoami) == 0) {
+ msg_warn("unexpected result; got: '%s', want: '%s'",
+ got_whoami, want_whoami);
+ status = FAIL;
+ }
+ mkmap_close(mkmap);
+
+ return (status);
+}
+
+static int redirects_mkmap_open_btree_to_def_cache_db_type(const TEST_CASE *tp)
+{
+ const char *got_whoami;
+ MKMAP *mkmap;
+ int status = PASS;
+ const char *want_whoami;
+
+ /*
+ * Setup. Use the mapping btree->lmdb.
+ */
+ setup_common_mock_open_info();
+ var_cache_db_type = "lmdb";
+
+ /*
+ * Verify that mkmap_open("btree"...) redirects to $default_cache_db_type
+ * ('lmdb').
+ */
+ want_whoami = "mock lmdb";
+ mkmap = mkmap_open(DICT_TYPE_BTREE, "ignored", O_RDONLY, 0);
+ if ((got_whoami = dict_get(mkmap->dict, "whoami")) == 0) {
+ msg_warn("'whoami' query returned 'not found'");
+ status = FAIL;
+ } else if (strstr(got_whoami, want_whoami) == 0) {
+ msg_warn("unexpected result; got: '%s', want: '%s'",
+ got_whoami, want_whoami);
+ status = FAIL;
+ }
+ mkmap_close(mkmap);
+
+ return (status);
+}
+
+static int nbdb_dict_xxx_open_handles_mapping_error(const TEST_CASE *tp)
+{
+ DICT *dict;
+ int status = PASS;
+ MSG_CAPTURE *capture;
+ const char *got_warning;
+ const char *want_warning;
+
+ /*
+ * Setup.
+ */
+ nbdb_util_init("enable-reindex");
+ dict_allow_surrogate = 1;
+ capture = msg_capt_create(100);
+
+ /*
+ * Run the test for nbdb_dict_hash_open().
+ */
+ var_db_type = "foo";
+
+ msg_capt_start(capture);
+ dict = dict_open3(DICT_TYPE_HASH, "ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+
+ got_warning = msg_capt_expose(capture);
+ want_warning = "unsupported database type: 'foo'";
+
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("unexpected hash redirect; got: non-surrogate "
+ "dictionary, want: surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning, want_warning) == 0) {
+ msg_warn("got unexpected warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ /*
+ * Run the test for nbdb_dict_btree_open().
+ */
+ var_cache_db_type = "bar";
+
+ msg_capt_start(capture);
+ dict = dict_open3(DICT_TYPE_BTREE, "ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+
+ got_warning = msg_capt_expose(capture);
+ want_warning = "unsupported database type: 'bar'";
+
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("unexpected btree redirect; got: non-surrogate "
+ "dictionary, want: surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning, want_warning) == 0) {
+ msg_warn("got unexpected warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ msg_capt_free(capture);
+ return (status);
+}
+
+static int nbdb_dict_xxx_open_handles_no_suffix_error(const TEST_CASE *tp)
+{
+ DICT *dict;
+ int status = PASS;
+ MSG_CAPTURE *capture;
+ const char *got_warning;
+ const char *want_warning;
+
+ /*
+ * Setup.
+ */
+ nbdb_util_init("enable-reindex");
+ dict_allow_surrogate = 1;
+ capture = msg_capt_create(100);
+
+ /*
+ * Run the test for nbdb_dict_hash_open().
+ */
+ var_db_type = "static";
+
+ msg_capt_start(capture);
+ dict = dict_open3(DICT_TYPE_HASH, "ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+
+ got_warning = msg_capt_expose(capture);
+ want_warning = "'static' has no known pathname suffix";
+
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("unexpected hash redirect; got: non-surrogate "
+ "dictionary, want: surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning, want_warning) == 0) {
+ msg_warn("got unexpected warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ /*
+ * Run the test for nbdb_dict_btree_open().
+ */
+ var_cache_db_type = "static";
+
+ msg_capt_start(capture);
+ dict = dict_open3(DICT_TYPE_BTREE, "ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+
+ got_warning = msg_capt_expose(capture);
+ want_warning = "'static' has no known pathname suffix";
+
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("unexpected btree redirect; got: non-surrogate "
+ "dictionary, want: surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning, want_warning) == 0) {
+ msg_warn("got unexpected warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+
+ msg_capt_free(capture);
+ return (status);
+}
+
+ /*
+ * TODO(wietse) also verify the msg_fatal() calls. That requires conversion
+ * to PTEST.
+ */
+static const TEST_CASE test_cases[] = {
+ {.label = "redirects_dict_open_hash_to_def_db_type",
+ redirects_dict_open_hash_to_def_db_type,
+ },
+ {.label = "redirects_dict_open_btree_to_def_cache_db_type",
+ redirects_dict_open_btree_to_def_cache_db_type,
+ },
+ {.label = "redirects_mkmap_open_hash_to_def_db_type",
+ redirects_mkmap_open_hash_to_def_db_type,
+ },
+ {.label = "redirects_mkmap_open_btree_to_def_cache_db_type",
+ redirects_mkmap_open_btree_to_def_cache_db_type,
+ },
+ {.label = "nbdb_dict_xxx_open_handles_mapping_error",
+ nbdb_dict_xxx_open_handles_mapping_error,
+ },
+ {.label = "nbdb_dict_xxx_open_handles_no_suffix_error",
+ nbdb_dict_xxx_open_handles_no_suffix_error,
+ },
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* nbdb_surrogate 3
+/* SUMMARY
+/* surrogate Berkeley DB handlers that log hints
+/* SYNOPSIS
+/* #include <nbdb_surrogate.h>
+/*
+/* void nbdb_surr_init()
+/* DESCRIPTION
+/* nbdb_surr_init() installs dict_open() and mkmap_open() surrogates
+/* for Berkeley DB types 'hash' and 'btree. These handlers log that
+/* Berkeley DB support is unavailable and provide a link to the
+/* NON_BERKELEYDB_README web page. The dict_open() handlers return
+/* a pointer to DICT instance that fails all requests, and the
+/* mkmap_open() handlers terminate the process.
+/*
+/* This code does not require prior initialization with
+/* mail_conf_read() or mail_params_init().
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+#include <dict_db.h>
+#include <mkmap.h>
+#include <msg.h>
+
+ /*
+ * Global library.
+ */
+#include <nbdb_surrogate.h>
+
+ /*
+ * Inform the user that Berkeley DB is gone, and offer alternatives.
+ */
+static const char boilerplate[] =
+"Berkeley DB support for '%s:%s' is not available for this OS distribution; "
+"see https://www.postfix.org/NON_BERKELEYDB_README.html for alternatives";
+
+/* surrogate dict_{hash,btree}_open() */
+
+static DICT *surrogate_dict_bdb_open(const char *type, const char *name,
+ int open_flags, int dict_flags)
+{
+ return (dict_surrogate(type, name, open_flags, dict_flags, boilerplate,
+ type, name));
+}
+
+static DICT *surrogate_dict_hash_open(const char *name, int open_flags,
+ int dict_flags)
+{
+ return (surrogate_dict_bdb_open(DICT_TYPE_HASH, name, open_flags,
+ dict_flags));
+}
+
+static DICT *surrogate_dict_btree_open(const char *name, int open_flags,
+ int dict_flags)
+{
+ return (surrogate_dict_bdb_open(DICT_TYPE_BTREE, name, open_flags,
+ dict_flags));
+}
+
+/* surrogates for mkmap_{hash,btree}_open() */
+
+static MKMAP *surrogate_mkmap_bdb_open(const char *type, const char *path)
+{
+ msg_fatal(boilerplate, type, path);
+}
+
+static MKMAP *surrogate_mkmap_hash_open(const char *path)
+{
+ return (surrogate_mkmap_bdb_open(DICT_TYPE_HASH, path));
+}
+
+static MKMAP *surrogate_mkmap_btree_open(const char *path)
+{
+ return (surrogate_mkmap_bdb_open(DICT_TYPE_BTREE, path));
+}
+
+static const DICT_OPEN_INFO surrogate_bdb_info[] = {
+ {DICT_TYPE_HASH, surrogate_dict_hash_open, surrogate_mkmap_hash_open},
+ {DICT_TYPE_BTREE, surrogate_dict_btree_open, surrogate_mkmap_btree_open},
+};
+
+/* nbdb_surr_init - register the above surrogates */
+
+void nbdb_surr_init(void)
+{
+ const DICT_OPEN_INFO *open_info;
+
+ for (open_info = surrogate_bdb_info; open_info->type; open_info++) {
+ if (dict_open_lookup(open_info->type) != 0)
+ dict_open_unregister(open_info->type);
+ if (msg_verbose)
+ msg_info("%s: installing custom hanndlers for '%s'",
+ __func__, open_info->type);
+ dict_open_register(open_info);
+ }
+}
--- /dev/null
+#ifndef _NBDB_SURROGATE_H_
+#define _NBDB_SURROGATE_H_
+
+/*++
+/* NAME
+/* nbdb_surrogate 3h
+/* SUMMARY
+/* surrogate Berkeley DB handlers that log hints
+/* SYNOPSIS
+/* #include <nbdb_surrogate.h>
+/* DESCRIPTION
+* .nf
+
+ /*
+ * External interface.
+ */
+extern void nbdb_surr_init(void);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_surrogate_test 1t
+/* SUMMARY
+/* nbdb_surrogate unit test
+/* SYNOPSIS
+/* ./nbdb_surrogate_test
+/* DESCRIPTION
+/* nbdb_surrogate_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict_db.h>
+#include <dict.h>
+#include <mkmap.h>
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_util.h>
+#include <nbdb_surrogate.h>
+
+ /*
+ * Testing library.
+ */
+#include <msg_capture.h>
+
+ /*
+ * Application-specific.
+ */
+int dict_allow_surrogate = 1;
+
+#define PASS (0)
+#define FAIL (1)
+
+#define STR(x) vstring_str(x)
+
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+} TEST_CASE;
+
+static int redirects_dict_open_hash_to_surrogate(const TEST_CASE *tp)
+{
+ MSG_CAPTURE *capture = msg_capt_create(100);
+ DICT *dict;
+ int status = PASS;
+ const char *want_warning = "support for 'hash:ignored' is not available";
+ const char *got_warning;
+
+ /*
+ * Setup.
+ */
+ nbdb_surr_init();
+
+ /*
+ * Test and verify.
+ */
+ msg_capt_start(capture);
+ dict = dict_open("hash:ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("dict_open(\"hash:...\", ...) did not return surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning = msg_capt_expose(capture),
+ want_warning) == 0) {
+ msg_warn("got warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+ msg_capt_free(capture);
+
+ return (status);
+}
+
+static int redirects_dict_open_btree_to_surrogate(const TEST_CASE *tp)
+{
+ MSG_CAPTURE *capture = msg_capt_create(100);
+ DICT *dict;
+ int status = PASS;
+ const char *want_warning = "support for 'btree:ignored' is not available";
+ const char *got_warning;
+
+ /*
+ * Setup.
+ */
+ nbdb_surr_init();
+
+ /*
+ * Test and verify.
+ */
+ msg_capt_start(capture);
+ dict = dict_open("btree:ignored", O_RDONLY, 0);
+ msg_capt_stop(capture);
+ if ((dict->flags & DICT_FLAG_SURROGATE) == 0) {
+ msg_warn("dict_open(\"btree:...\", ...) did not return surrogate");
+ status = FAIL;
+ } else if (strstr(got_warning = msg_capt_expose(capture),
+ want_warning) == 0) {
+ msg_warn("got warning: '%s', want: '%s'",
+ got_warning, want_warning);
+ status = FAIL;
+ }
+ dict_close(dict);
+ msg_capt_free(capture);
+
+ return (status);
+}
+
+ /*
+ * TODO(wietse) also verify the msg_fatal() calls. That requires conversion
+ * to PTEST.
+ */
+static const TEST_CASE test_cases[] = {
+ {.label = "redirects_dict_open_hash_to_surrogate",
+ redirects_dict_open_hash_to_surrogate,
+ },
+ {.label = "redirects_dict_open_btree_to_surrogate",
+ redirects_dict_open_btree_to_surrogate,
+ },
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* nbdb_util 3
+/* SUMMARY
+/* Non-Berkeley-DB migration support
+/* SYNOPSIS
+/* #include <nbdb_util.h>
+/*
+/* int nbdb_level;
+/* bool nbdb_reindexing_lockout;
+/*
+/* void nbdb_util_init(const char *level_name)
+/*
+/* int nbdb_is_legacy_type(const char *type)
+/*
+/* const char *nbdb_find_non_leg_suffix(const char *non_leg_type)
+/*
+/* const char *nbdb_map_leg_type(
+/* const char *leg_type,
+/* const char *name,
+/* const DICT_OPEN_INFO **open_info,
+/* VSTRING *why)
+/* DESCRIPTION
+/* This module contains utilities that may be called by clients
+/* and servers of the non-Berkeley-DB migration service.
+/*
+/* nbdb_is_legacy_type() returns true if the specified database
+/* type is a Berkeley DB type ('hash' or 'btree').
+/*
+/* nbdb_find_non_leg_suffix() returns the database pathname suffix
+/* for the specified non-legacy database, or null if no suffix
+/* was found.
+/*
+/* nbdb_map_leg_type() implements the mapping from expected legacy
+/* type names to expected non-legacy type names. This supports
+/* a user-defined mapping override, indexed by legacy type or legacy
+/* type:name. nbdb_map_leg_type() returns null in case of error:
+/* a table lookup error, an unexpected input type, or an unexpected
+/* output type.
+/* .IP leg_type
+/* A legacy database type to be mapped to a non-legacy type.
+/* .IP name
+/* A database name.
+/* .IP open_info
+/* Null pointer, or pointer to DICT_OPEN_INFO pointer with function
+/* pointers to open the non-legacy database.
+/* .IP why
+/* Storage for descriptive text in case of error.
+/* .PP
+/*
+/* nbdb_util_init() converts the non-Berkeley-DB migration level
+/* from text to internal form, and updates the nbdb_level global
+/* variable:
+/* .IP "redirect (internal form: NBDB_LEV_CODE_REDIRECT)"
+/* Enables the mapping from legacy Berkeley DB types to preferred
+/* types.
+/* .IP "reindex (internal form: NBDB_LEV_CODE_REINDEX)"
+/* As "redirect", but also makes requests to a reindexing service
+/* if the non-legacy indexed file does not exist.
+/* Exception: calling a reindexing service will remain disabled
+/* if the process sets nbdb_reindexing_lockout to 'true'.
+/* SEE ALSO
+/* nbdb_reindexd(8), helper daemon to reindex legacy tables
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <string.h>
+#include <errno.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict_cdb.h>
+#include <dict_db.h>
+#include <dict.h>
+#include <dict_lmdb.h>
+#include <mkmap.h>
+#include <msg.h>
+#include <mymalloc.h>
+#include <name_code.h>
+#include <split_at.h>
+#include <stringops.h>
+#include <vstring.h>
+#include <stringops.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_util.h>
+#include <nbdb_redirect.h>
+#include <nbdb_surrogate.h>
+
+ /*
+ * Application-specific.
+ */
+int nbdb_level;
+bool nbdb_reindexing_lockout;
+
+ /*
+ * Mapping from legacy type to non-legacy.
+ */
+static DICT *nbdb_cust_map;
+
+ /*
+ * Mapping from non-legacy type to pathname suffix. This should be provided
+ * by individual table implementations, but that would require changes to
+ * the dict/mkmap plugin API.
+ */
+typedef struct {
+ const char *type;
+ const char *suffix;
+} NBDB_PATH_SUFFIX;
+
+static const NBDB_PATH_SUFFIX nbdb_path_suffixes[] = {
+ DICT_TYPE_CDB, ".cdb",
+ DICT_TYPE_LMDB, ".lmdb",
+ 0, 0, /* Default case */
+};
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+
+/* nbdb_map_leg_type - map legacy type to non-legacy type, null means error */
+
+const char *nbdb_map_leg_type(const char *leg_type, const char *name,
+ const DICT_OPEN_INFO **open_info,
+ VSTRING *why)
+{
+ static VSTRING *type_name = 0;
+ const char *non_leg_type = 0;
+ const DICT_OPEN_INFO *my_open_info;
+
+ if (type_name == 0)
+ type_name = vstring_alloc(100);
+
+ /*
+ * Sanity check.
+ */
+ if (!nbdb_is_legacy_type(leg_type)) {
+ vstring_sprintf(why, "request to map from non-Berkeley-DB type: '%s'",
+ leg_type);
+ return (0);
+ }
+ /* Search for custom mapping with the type:name. */
+ if (nbdb_cust_map != 0) {
+ vstring_sprintf(type_name, "%s:%s", leg_type, name);
+ if ((non_leg_type = dict_get(nbdb_cust_map, STR(type_name))) == 0
+ && nbdb_cust_map->error == 0)
+ /* Search with the 'bare' type only. */
+ non_leg_type = dict_get(nbdb_cust_map, leg_type);
+ if (non_leg_type == 0 && nbdb_cust_map->error != 0) {
+ vstring_sprintf(why, "%s:%s lookup error for '%s'",
+ nbdb_cust_map->type, nbdb_cust_map->name,
+ STR(type_name));
+ return (0);
+ }
+ }
+
+ /*
+ * No custom mapping: use the default.
+ */
+ if (non_leg_type == 0) {
+ if (strcmp(leg_type, DICT_TYPE_HASH) == 0) {
+ non_leg_type = (var_db_type);
+ } else if (strcmp(leg_type, DICT_TYPE_BTREE) == 0) {
+ non_leg_type = (var_cache_db_type);
+ } else {
+ msg_panic("%s: no default mapping for Berkeley DB type: '%s'",
+ __func__, leg_type);
+ }
+ }
+
+ /*
+ * More sanity checks.
+ */
+ if (!allalnum(non_leg_type)) {
+ vstring_sprintf(why, "bad non-legacy database type syntax: '%s'",
+ non_leg_type);
+ return (0);
+ }
+ if (nbdb_is_legacy_type(non_leg_type)) {
+ vstring_sprintf(why, "mapping from '%s' to legacy type '%s'",
+ leg_type, non_leg_type);
+ return (0);
+ }
+ if ((my_open_info = dict_open_lookup(non_leg_type)) == 0) {
+ vstring_sprintf(why, "mapping to unsupported database type: '%s'",
+ non_leg_type);
+ return (0);
+ }
+ if (open_info != 0)
+ *open_info = my_open_info;
+ return (non_leg_type);
+}
+
+/* nbdb_is_legacy_type - sanity check */
+
+int nbdb_is_legacy_type(const char *leg_type)
+{
+ return (strcmp(leg_type, DICT_TYPE_HASH) == 0
+ || strcmp(leg_type, DICT_TYPE_BTREE) == 0);
+}
+
+/* nbdb_find_non_leg_suffix - find file suffix for non-legacy type */
+
+const char *nbdb_find_non_leg_suffix(const char *non_leg_type)
+{
+ const NBDB_PATH_SUFFIX *sp;
+
+ for (sp = nbdb_path_suffixes; sp->type != 0; sp++)
+ if (strcmp(non_leg_type, sp->type) == 0)
+ break;
+ return (sp->suffix);
+}
+
+/* nbdb_util_init - redirect legacy open() requests to nbdb handlers */
+
+void nbdb_util_init(const char *level_name)
+{
+ static NAME_CODE nbdb_level_table[] = {
+ NBDB_LEV_NAME_NONE, NBDB_LEV_CODE_NONE,
+ NBDB_LEV_NAME_REDIRECT, NBDB_LEV_CODE_REDIRECT,
+ NBDB_LEV_NAME_REINDEX, NBDB_LEV_CODE_REINDEX,
+ 0, -1,
+ };
+
+ /*
+ * Convert the non-Berkeley-DB migration level to internal form. If
+ * migration support is disabled, then do not tun the code below.
+ */
+ nbdb_level = name_code(nbdb_level_table, NAME_CODE_FLAG_NONE, level_name);
+ if (nbdb_level == NBDB_LEV_CODE_ERROR)
+ msg_fatal("invalid non-Berkeley-DB migration level: '%s'", level_name);
+ if (nbdb_level == NBDB_LEV_CODE_NONE) {
+#ifdef NO_DB
+ nbdb_surr_init();
+#endif
+ return;
+ }
+
+ /*
+ * Initialize the custom legacy to non-legacy mapping. Discard an
+ * existing mapping, to simplify testing. To avoid a dependency loop,
+ * this mapping should never use a legacy database type.
+ */
+ if (nbdb_cust_map) {
+ dict_close(nbdb_cust_map);
+ nbdb_cust_map = 0;
+ }
+ if (*var_nbdb_cust_map) {
+ char *map_type = mystrdup(var_nbdb_cust_map);
+ char *map_name = split_at(map_type, ':');
+
+ if (map_name != 0 && (strcmp(map_type, DICT_TYPE_HASH) == 0
+ || strcmp(map_type, DICT_TYPE_BTREE) == 0)) {
+ nbdb_cust_map = dict_surrogate(map_type, map_name,
+ O_RDONLY, DICT_FLAG_LOCK,
+ "%s must not use legacy type: '%s'",
+ VAR_NBDB_CUST_MAP,
+ map_type);
+ } else {
+ nbdb_cust_map = dict_open(var_nbdb_cust_map, O_RDONLY,
+ DICT_FLAG_LOCK
+ | DICT_FLAG_FOLD_FIX
+ | DICT_FLAG_UTF8_REQUEST);
+ }
+ myfree(map_type);
+ }
+
+ /*
+ * If this process does not provide the reindexing service, turn on the
+ * forward-compatibility redirection for legacy database types and
+ * reindexing server callouts.
+ *
+ * The reindexing server should never attempt to use legacy database types,
+ * and should never be calling reindexing service client code.
+ */
+ if (!nbdb_reindexing_lockout)
+ nbdb_rdr_init();
+}
--- /dev/null
+#ifndef _NBDB_UTIL_H_INCLUDED_
+#define _NBDB_UTIL_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_util 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration utilities
+/* SYNOPSIS
+/* #include <nbdb_util.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+Utility library. */
+#include <dict.h>
+
+ /*
+ * External API.
+ */
+#define NBDB_STAT_OK 0
+#define NBDB_STAT_ERROR 1
+
+extern int nbdb_level;
+extern bool nbdb_reindexing_lockout;
+
+extern void nbdb_util_init(const char *);
+extern int nbdb_is_legacy_type(const char *);
+extern const char *nbdb_find_non_leg_suffix(const char *);
+extern const char *nbdb_map_leg_type(const char *, const char *,
+ const DICT_OPEN_INFO **, VSTRING *);
+
+#define NBDB_LEGACY_SUFFIX ".db"
+
+ /*
+ * Migration level internal forms.
+ */
+#define NBDB_LEV_CODE_ERROR (-1)
+#define NBDB_LEV_CODE_NONE (0)
+#define NBDB_LEV_CODE_REDIRECT (1)
+#define NBDB_LEV_CODE_REINDEX (2)
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_util_test 1t
+/* SUMMARY
+/* nbdb_util unit test
+/* SYNOPSIS
+/* ./nbdb_util_test
+/* DESCRIPTION
+/* nbdb_util_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <stringops.h>
+#include <msg_vstream.h>
+#include <vstring.h>
+#include <vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_util.h>
+#include <nbdb_redirect.h>
+
+ /*
+ * Testing library.
+ */
+#include <mock_dict.h>
+#include <msg_capture.h>
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+#define PASS (0)
+#define FAIL (1)
+
+#define BOOL_TO_TEXT(b) ((b) ? "true" : "false")
+
+ /*
+ * Scaffolding.
+ */
+
+char *var_nbdb_cust_map = DEF_NBDB_CUST_MAP;
+
+/* dummy nbdb_rdr_init() support */
+
+void nbdb_rdr_init(void)
+{
+}
+
+ /*
+ * tests for nbdb_util_init(),
+ */
+struct nbdb_util_init_test {
+ const char *label;
+ int (*action) (const struct nbdb_util_init_test *);
+ const char *in_level;
+ bool in_reindexing_lockout;
+ int want_level;
+};
+
+#define STR_OR_NULL(s) ((s) ? (s) : "(null)")
+
+static int test_nbdb_util_init(const struct nbdb_util_init_test * tp)
+{
+ nbdb_util_init(tp->in_level);
+ if (nbdb_level != tp->want_level) {
+ msg_warn("unexpected nbdb_level, got: %d, want: %d",
+ nbdb_level, tp->want_level);
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+static const struct nbdb_util_init_test nbdb_util_init_tests[] = {
+ {.label = "nbdb_util_init_level_none",
+ .action = test_nbdb_util_init,
+ .in_level = "disable",
+ .want_level = NBDB_LEV_CODE_NONE,
+ },
+ {.label = "nbdb_util_init_level_redirect",
+ .action = test_nbdb_util_init,
+ .in_level = "enable-redirect",
+ .want_level = NBDB_LEV_CODE_REDIRECT,
+ },
+ {.label = "nbdb_util_init_level_reindex",
+ .action = test_nbdb_util_init,
+ .in_level = "enable-reindex",
+ .want_level = NBDB_LEV_CODE_REINDEX,
+ },
+ {.label = "nbdb_util_init_level_reindexing_with_lockout",
+ .action = test_nbdb_util_init,
+ .in_level = "enable-reindex",
+ .in_reindexing_lockout = true,
+ .want_level = NBDB_LEV_CODE_REINDEX,
+ },
+ /* TODO: trap msg_fatal() call after bad level name. */
+ {0},
+};
+
+ /*
+ * Tests for nbdb_is_legacy_type().
+ */
+struct nbdb_is_legacy_type_test {
+ const char *label;
+ int (*action) (const struct nbdb_is_legacy_type_test *);
+ const char *in_type;
+ bool want_result;
+};
+
+static int test_nbdb_is_legacy_type(const struct nbdb_is_legacy_type_test * tp)
+{
+ bool got_result;
+
+ got_result = nbdb_is_legacy_type(tp->in_type);
+ if (got_result != tp->want_result) {
+ msg_warn("unexpected result; got '%s', want: ''%s'",
+ BOOL_TO_TEXT(got_result), BOOL_TO_TEXT(tp->want_result));
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+static const struct nbdb_is_legacy_type_test nbdb_is_legacy_type_tests[] = {
+ {.label = "nbdb_is_legacy_type_hash_true",
+ .action = test_nbdb_is_legacy_type,
+ .in_type = "hash",
+ .want_result = true,
+ },
+ {.label = "nbdb_is_legacy_type_btree_true",
+ .action = test_nbdb_is_legacy_type,
+ .in_type = "btree",
+ .want_result = true,
+ },
+ {.label = "nbdb_is_legacy_type_lmdb_false",
+ .action = test_nbdb_is_legacy_type,
+ .in_type = "lmdb",
+ .want_result = false,
+ },
+ {.label = "nbdb_is_legacy_type_cdb_false",
+ .action = test_nbdb_is_legacy_type,
+ .in_type = "cdb",
+ .want_result = false,
+ },
+ {0},
+};
+
+ /*
+ * Tests for find_non_leg_suffix().
+ */
+struct find_non_leg_suffix_test {
+ const char *label;
+ int (*action) (const struct find_non_leg_suffix_test *);
+ const char *in_type;
+ const char *want_suffix;
+};
+
+#define STR_OR_NULL(s) ((s) ? (s) : "(null)")
+
+static int test_find_non_leg_suffix(const struct find_non_leg_suffix_test * tp)
+{
+ const char *got_suffix;
+
+ got_suffix = nbdb_find_non_leg_suffix(tp->in_type);
+ if (!got_suffix != !tp->want_suffix) {
+ msg_warn("unexpected suffix; got: '%s', want: '%s'",
+ STR_OR_NULL(got_suffix), STR_OR_NULL(tp->want_suffix));
+ return (FAIL);
+ }
+ if (got_suffix && strcmp(got_suffix, tp->want_suffix) != 0) {
+ msg_warn("unexpected suffix; got: '%s', want: '%s'",
+ got_suffix, tp->want_suffix);
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+static const struct find_non_leg_suffix_test find_non_leg_suffix_tests[] = {
+ {.label = "find_non_leg_suffix_lmdb",
+ .action = test_find_non_leg_suffix,
+ .in_type = "lmdb",
+ .want_suffix = ".lmdb",
+ },
+ {.label = "find_non_leg_suffix_cdb",
+ .action = test_find_non_leg_suffix,
+ .in_type = "cdb",
+ .want_suffix = ".cdb",
+ },
+ {.label = "find_non_leg_suffix_hash",
+ .action = test_find_non_leg_suffix,
+ .in_type = "hash",
+ .want_suffix = 0,
+ },
+ {.label = "find_non_leg_suffix_btree",
+ .action = test_find_non_leg_suffix,
+ .in_type = "btree",
+ .want_suffix = 0,
+ },
+ {0},
+};
+
+ /*
+ * Tests for map_leg_type().
+ */
+struct map_leg_type_test {
+ const char *label;
+ int (*action) (const struct map_leg_type_test *);
+ const char *in_db_type;
+ const char *in_cache_db_type;
+ const char *in_custom_map;
+ const char *in_type;
+ const char *in_name;
+ const char *want_type;
+ const char *want_why;
+ const char *want_warning;
+};
+
+static int test_map_leg_type(const struct map_leg_type_test * tp)
+{
+ VSTRING *got_why = vstring_alloc(100);
+ MSG_CAPTURE *capture = msg_capt_create(100);
+ char *saved_db_type = var_db_type;
+ char *saved_cache_db_type = var_cache_db_type;
+ char *saved_cust_map = var_nbdb_cust_map;
+ const char *got_type;
+ const char *got_warning;
+ int status = PASS;
+
+ /* Setup. */
+ setup_mock_cdb("{{x = x}}");
+ setup_mock_lmdb("{{x = x}}");
+ dict_allow_surrogate = 1;
+ var_nbdb_cust_map = (char *) tp->in_custom_map;
+ var_db_type = (char *) tp->in_db_type;
+ var_cache_db_type = (char *) tp->in_cache_db_type;
+
+ msg_capt_start(capture);
+ nbdb_util_init("enable-redirect");
+ got_type = nbdb_map_leg_type(tp->in_type, tp->in_name,
+ (const DICT_OPEN_INFO **) 0, got_why);
+ msg_capt_stop(capture);
+ got_warning = msg_capt_expose(capture);
+
+ /* Verify results. */
+ if (!LEN(got_why) != !tp->want_why) {
+ msg_warn("got error text: `%s', want: `%s'",
+ STR(got_why), STR_OR_NULL(tp->want_why));
+ status = FAIL;
+ } else if (tp->want_why && strstr(STR(got_why), tp->want_why) == 0) {
+ msg_warn("got error text: `%s', want: `%s'",
+ STR(got_why), tp->want_why);
+ status = FAIL;
+ } else if (!tp->want_warning != !got_warning[0]) {
+ msg_warn("got warning: '%s', want: '%s'",
+ got_warning, STR_OR_NULL(tp->want_warning));
+ status = FAIL;
+ } else if (tp->want_warning && strstr(got_warning, tp->want_warning) == 0) {
+ msg_warn("got warning: '%s', want: '%s'",
+ got_warning, tp->want_warning);
+ status = FAIL;
+ } else if (!got_type != !tp->want_type) {
+ msg_warn("got unexpected type: '%s', want: '%s'",
+ STR_OR_NULL(got_type), STR_OR_NULL(tp->want_type));
+ status = FAIL;
+ } else if (got_type && strcmp(got_type, tp->want_type) != 0) {
+ msg_warn("got unexpected type: '%s', want: '%s'",
+ got_type, tp->want_type);
+ status = FAIL;
+ }
+ var_nbdb_cust_map = saved_cust_map;
+ var_db_type = saved_db_type;
+ var_cache_db_type = saved_cache_db_type;
+ vstring_free(got_why);
+ msg_capt_free(capture);
+ return (status);
+}
+
+static const struct map_leg_type_test map_leg_type_tests[] = {
+ {"map_leg_type:default_hash_to_cdb",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = "cdb",
+ },
+ {"map_leg_type:default_btree_to_lmdb",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "",
+ .in_type = "btree",
+ .in_name = "/some/where/blah",
+ .want_type = "lmdb",
+ },
+ {"map_leg_type:custom_hash_with_path_to_lmdb",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{hash:/some/where/blah = lmdb}}",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = "lmdb",
+ },
+ {"map_leg_type:custom_btree_with_path_to_cdb",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{btree:/some/where/blah = cdb}}",
+ .in_type = "btree",
+ .in_name = "/some/where/blah",
+ .want_type = "cdb",
+ },
+ {"map_leg_type:custom_hash_to_lmdb",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{hash = lmdb}}",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = "lmdb",
+ },
+ {"map_leg_type:custom_mapping_type_must_not_use_hash",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "hash:/whatever",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = 0,
+ .want_why = "lookup error for 'hash:/some/where/blah'",
+ .want_warning = "mapping must not use legacy type: 'hash'"
+ },
+ {"map_leg_type:custom_mapping_type_must_not_use_btree",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "btree:/whatever",
+ .in_type = "btree",
+ .in_name = "/some/where/blah",
+ .want_type = 0,
+ .want_why = "lookup error for 'btree:/some/where/blah'",
+ .want_warning = "mapping must not use legacy type: 'btree'",
+ },
+ {"map_leg_type:custom_hash_to_composite",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{hash = proxy:lmdb}}",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = 0,
+ .want_why = "bad non-legacy database type syntax: 'proxy:lmdb'",
+ },
+ {"map_leg_type:custom_hash_to_legacy",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{hash = btree}}",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = 0,
+ .want_why = "mapping from 'hash' to legacy type 'btree'",
+ },
+ {"map_leg_type:custom_hash_to_unsupported",
+ .action = test_map_leg_type,
+ .in_db_type = "cdb",
+ .in_cache_db_type = "lmdb",
+ .in_custom_map = "inline:{{hash = foo}}",
+ .in_type = "hash",
+ .in_name = "/some/where/blah",
+ .want_type = 0,
+ .want_why = "unsupported database type: 'foo'",
+ },
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ int pass = 0;
+ int fail = 0;
+
+#define RUN_TEST(tp) do { \
+ int test_failed; \
+ msg_info("RUN %s", tp->label); \
+ test_failed = tp->action(tp); \
+ if (test_failed) { \
+ msg_info("FAIL %s", tp->label); \
+ fail++; \
+ } else { \
+ msg_info("PASS %s", tp->label); \
+ pass++; \
+ } \
+ } while (0)
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+ /* nbdb_util_init tests. */
+ {
+ const struct nbdb_util_init_test *tp;
+
+ for (tp = nbdb_util_init_tests; tp->label != 0; tp++)
+ RUN_TEST(tp);
+ }
+ /* nbdb_is_legacy_type() tests. */
+ {
+ const struct nbdb_is_legacy_type_test *tp;
+
+ for (tp = nbdb_is_legacy_type_tests; tp->label != 0; tp++)
+ RUN_TEST(tp);
+ }
+ /* find_non_leg_suffix() tests. */
+ {
+ const struct find_non_leg_suffix_test *tp;
+
+ for (tp = find_non_leg_suffix_tests; tp->label != 0; tp++)
+ RUN_TEST(tp);
+ }
+ /* map_leg_type() tests. */
+ {
+ const struct map_leg_type_test *tp;
+
+ for (tp = map_leg_type_tests; tp->label != 0; tp++)
+ RUN_TEST(tp);
+ }
+
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+SHELL = /bin/sh
+SRCS = nbdb_reindexd.c nbdb_sniffer.c nbdb_safe.c \
+ nbdb_index_as.c nbdb_process.c
+OBJS = nbdb_reindexd.o nbdb_sniffer.o nbdb_safe.o \
+ nbdb_index_as.o nbdb_process.o
+HDRS = nbdb_reindexd.h nbdb_sniffer.h nbdb_safe.h \
+ nbdb_index_as.h nbdb_process.h
+TESTSRC = nbdb_sniffer_test.c nbdb_safe_test.c
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+PROG = nbdb_reindexd
+TESTPROG= nbdb_sniffer_test nbdb_safe_test nbdb_index_as_test nbdb_process_test
+TESTLIB = ../../lib/libtesting.a
+INC_DIR = ../../include
+LIBS = ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \
+ ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
+ ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) $(SHLIB_RPATH) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+$(OBJS): ../../conf/makedefs.out
+
+Makefile: Makefile.in
+ cat ../../conf/makedefs.out $? >$@
+
+test: $(TESTPROG)
+
+tests: test_nbdb_sniffer test_nbdb_safe test_nbdb_index_as test_nbdb_process
+
+root_tests:
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+
+tidy: clean
+
+SNIFFER_TEST_OBJ = nbdb_sniffer.o $(TESTLIB)
+
+nbdb_sniffer_test: nbdb_sniffer_test.o $(SNIFFER_TEST_OBJ) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(SNIFFER_TEST_OBJ) $(LIBS) $(SYSLIBS)
+
+test_nbdb_sniffer: nbdb_sniffer_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_sniffer_test
+
+SAFE_TEST_OBJ = nbdb_safe.o
+
+nbdb_safe_test: nbdb_safe_test.o $(SAFE_TEST_OBJ) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(SAFE_TEST_OBJ) $(LIBS) $(SYSLIBS)
+
+test_nbdb_safe: nbdb_safe_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_safe_test
+
+INDEX_AS_TEST_OBJ = nbdb_index_as.o $(TESTLIB)
+
+nbdb_index_as_test: nbdb_index_as_test.o $(INDEX_AS_TEST_OBJ) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(INDEX_AS_TEST_OBJ) $(LIBS) $(SYSLIBS)
+
+test_nbdb_index_as: nbdb_index_as_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_index_as_test
+
+PROCESS_TEST_OBJ = nbdb_process.o nbdb_index_as.o nbdb_sniffer.o nbdb_safe.o \
+ $(TESTLIB)
+
+nbdb_process_test: nbdb_process_test.o $(PROCESS_TEST_OBJ) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $@.o $(PROCESS_TEST_OBJ) $(LIBS) $(SYSLIBS)
+
+test_nbdb_process: nbdb_process_test
+ $(SHLIB_ENV) $(VALGRIND) ./nbdb_process_test
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | grep -v '[<>]' | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' \
+ -e 's/o: \.\//o: /' -e p -e '}' ; \
+ done | LANG=C sort -u) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+nbdb_index_as.o: ../../include/argv.h
+nbdb_index_as.o: ../../include/check_arg.h
+nbdb_index_as.o: ../../include/dict.h
+nbdb_index_as.o: ../../include/iostuff.h
+nbdb_index_as.o: ../../include/mail_params.h
+nbdb_index_as.o: ../../include/mail_parm_split.h
+nbdb_index_as.o: ../../include/myflock.h
+nbdb_index_as.o: ../../include/nbdb_util.h
+nbdb_index_as.o: ../../include/spawn_command.h
+nbdb_index_as.o: ../../include/stringops.h
+nbdb_index_as.o: ../../include/sys_defs.h
+nbdb_index_as.o: ../../include/vbuf.h
+nbdb_index_as.o: ../../include/vstream.h
+nbdb_index_as.o: ../../include/vstring.h
+nbdb_index_as.o: nbdb_index_as.c
+nbdb_index_as.o: nbdb_index_as.h
+nbdb_index_as_test.o: ../../include/argv.h
+nbdb_index_as_test.o: ../../include/check_arg.h
+nbdb_index_as_test.o: ../../include/dict.h
+nbdb_index_as_test.o: ../../include/mock_spawn_command.h
+nbdb_index_as_test.o: ../../include/msg.h
+nbdb_index_as_test.o: ../../include/msg_vstream.h
+nbdb_index_as_test.o: ../../include/myflock.h
+nbdb_index_as_test.o: ../../include/nbdb_util.h
+nbdb_index_as_test.o: ../../include/spawn_command.h
+nbdb_index_as_test.o: ../../include/stringops.h
+nbdb_index_as_test.o: ../../include/sys_defs.h
+nbdb_index_as_test.o: ../../include/vbuf.h
+nbdb_index_as_test.o: ../../include/vstream.h
+nbdb_index_as_test.o: ../../include/vstring.h
+nbdb_index_as_test.o: nbdb_index_as.h
+nbdb_index_as_test.o: nbdb_index_as_test.c
+nbdb_process.o: ../../include/allowed_prefix.h
+nbdb_process.o: ../../include/argv.h
+nbdb_process.o: ../../include/attr.h
+nbdb_process.o: ../../include/check_arg.h
+nbdb_process.o: ../../include/dict.h
+nbdb_process.o: ../../include/htable.h
+nbdb_process.o: ../../include/mail_params.h
+nbdb_process.o: ../../include/msg.h
+nbdb_process.o: ../../include/myflock.h
+nbdb_process.o: ../../include/mymalloc.h
+nbdb_process.o: ../../include/nbdb_util.h
+nbdb_process.o: ../../include/nvtable.h
+nbdb_process.o: ../../include/spawn_command.h
+nbdb_process.o: ../../include/sys_defs.h
+nbdb_process.o: ../../include/vbuf.h
+nbdb_process.o: ../../include/vstream.h
+nbdb_process.o: ../../include/vstring.h
+nbdb_process.o: ../../include/wrap_stat.h
+nbdb_process.o: nbdb_index_as.h
+nbdb_process.o: nbdb_process.c
+nbdb_process.o: nbdb_process.h
+nbdb_process.o: nbdb_reindexd.h
+nbdb_process.o: nbdb_safe.h
+nbdb_process.o: nbdb_sniffer.h
+nbdb_process_test.o: ../../include/allowed_prefix.h
+nbdb_process_test.o: ../../include/argv.h
+nbdb_process_test.o: ../../include/check_arg.h
+nbdb_process_test.o: ../../include/dict.h
+nbdb_process_test.o: ../../include/dict_cdb.h
+nbdb_process_test.o: ../../include/dict_lmdb.h
+nbdb_process_test.o: ../../include/mail_params.h
+nbdb_process_test.o: ../../include/mkmap.h
+nbdb_process_test.o: ../../include/mock_dict.h
+nbdb_process_test.o: ../../include/mock_open_as.h
+nbdb_process_test.o: ../../include/mock_spawn_command.h
+nbdb_process_test.o: ../../include/mock_stat.h
+nbdb_process_test.o: ../../include/msg.h
+nbdb_process_test.o: ../../include/msg_capture.h
+nbdb_process_test.o: ../../include/msg_vstream.h
+nbdb_process_test.o: ../../include/myflock.h
+nbdb_process_test.o: ../../include/nbdb_util.h
+nbdb_process_test.o: ../../include/open_as.h
+nbdb_process_test.o: ../../include/spawn_command.h
+nbdb_process_test.o: ../../include/stringops.h
+nbdb_process_test.o: ../../include/sys_defs.h
+nbdb_process_test.o: ../../include/vbuf.h
+nbdb_process_test.o: ../../include/vstream.h
+nbdb_process_test.o: ../../include/vstring.h
+nbdb_process_test.o: nbdb_index_as.h
+nbdb_process_test.o: nbdb_process.h
+nbdb_process_test.o: nbdb_process_test.c
+nbdb_process_test.o: nbdb_safe.h
+nbdb_reindexd.o: ../../include/allowed_prefix.h
+nbdb_reindexd.o: ../../include/argv.h
+nbdb_reindexd.o: ../../include/attr.h
+nbdb_reindexd.o: ../../include/check_arg.h
+nbdb_reindexd.o: ../../include/dict.h
+nbdb_reindexd.o: ../../include/htable.h
+nbdb_reindexd.o: ../../include/iostuff.h
+nbdb_reindexd.o: ../../include/mail_conf.h
+nbdb_reindexd.o: ../../include/mail_params.h
+nbdb_reindexd.o: ../../include/mail_proto.h
+nbdb_reindexd.o: ../../include/mail_server.h
+nbdb_reindexd.o: ../../include/mail_task.h
+nbdb_reindexd.o: ../../include/mail_version.h
+nbdb_reindexd.o: ../../include/msg.h
+nbdb_reindexd.o: ../../include/msg_vstream.h
+nbdb_reindexd.o: ../../include/myflock.h
+nbdb_reindexd.o: ../../include/mymalloc.h
+nbdb_reindexd.o: ../../include/nbdb_util.h
+nbdb_reindexd.o: ../../include/nvtable.h
+nbdb_reindexd.o: ../../include/set_eugid.h
+nbdb_reindexd.o: ../../include/split_at.h
+nbdb_reindexd.o: ../../include/sys_defs.h
+nbdb_reindexd.o: ../../include/vbuf.h
+nbdb_reindexd.o: ../../include/vstream.h
+nbdb_reindexd.o: ../../include/vstring.h
+nbdb_reindexd.o: ../../include/wrap_stat.h
+nbdb_reindexd.o: nbdb_index_as.h
+nbdb_reindexd.o: nbdb_process.h
+nbdb_reindexd.o: nbdb_reindexd.c
+nbdb_reindexd.o: nbdb_reindexd.h
+nbdb_reindexd.o: nbdb_safe.h
+nbdb_reindexd.o: nbdb_sniffer.h
+nbdb_safe.o: ../../include/allowed_prefix.h
+nbdb_safe.o: ../../include/argv.h
+nbdb_safe.o: ../../include/check_arg.h
+nbdb_safe.o: ../../include/mail_conf.h
+nbdb_safe.o: ../../include/mail_params.h
+nbdb_safe.o: ../../include/sys_defs.h
+nbdb_safe.o: ../../include/vbuf.h
+nbdb_safe.o: ../../include/vstring.h
+nbdb_safe.o: ../../include/wrap_stat.h
+nbdb_safe.o: nbdb_reindexd.h
+nbdb_safe.o: nbdb_safe.c
+nbdb_safe.o: nbdb_safe.h
+nbdb_safe_test.o: ../../include/allowed_prefix.h
+nbdb_safe_test.o: ../../include/argv.h
+nbdb_safe_test.o: ../../include/check_arg.h
+nbdb_safe_test.o: ../../include/mail_conf.h
+nbdb_safe_test.o: ../../include/mail_params.h
+nbdb_safe_test.o: ../../include/msg.h
+nbdb_safe_test.o: ../../include/msg_vstream.h
+nbdb_safe_test.o: ../../include/stringops.h
+nbdb_safe_test.o: ../../include/sys_defs.h
+nbdb_safe_test.o: ../../include/vbuf.h
+nbdb_safe_test.o: ../../include/vstream.h
+nbdb_safe_test.o: ../../include/vstring.h
+nbdb_safe_test.o: nbdb_safe.h
+nbdb_safe_test.o: nbdb_safe_test.c
+nbdb_sniffer.o: ../../include/allowed_prefix.h
+nbdb_sniffer.o: ../../include/argv.h
+nbdb_sniffer.o: ../../include/check_arg.h
+nbdb_sniffer.o: ../../include/dict.h
+nbdb_sniffer.o: ../../include/mail_params.h
+nbdb_sniffer.o: ../../include/msg.h
+nbdb_sniffer.o: ../../include/myflock.h
+nbdb_sniffer.o: ../../include/nbdb_util.h
+nbdb_sniffer.o: ../../include/open_as.h
+nbdb_sniffer.o: ../../include/readlline.h
+nbdb_sniffer.o: ../../include/resolve_clnt.h
+nbdb_sniffer.o: ../../include/stringops.h
+nbdb_sniffer.o: ../../include/sys_defs.h
+nbdb_sniffer.o: ../../include/tok822.h
+nbdb_sniffer.o: ../../include/vbuf.h
+nbdb_sniffer.o: ../../include/vstream.h
+nbdb_sniffer.o: ../../include/vstring.h
+nbdb_sniffer.o: nbdb_reindexd.h
+nbdb_sniffer.o: nbdb_sniffer.c
+nbdb_sniffer.o: nbdb_sniffer.h
+nbdb_sniffer_test.o: ../../include/check_arg.h
+nbdb_sniffer_test.o: ../../include/mock_open_as.h
+nbdb_sniffer_test.o: ../../include/msg.h
+nbdb_sniffer_test.o: ../../include/msg_vstream.h
+nbdb_sniffer_test.o: ../../include/open_as.h
+nbdb_sniffer_test.o: ../../include/stringops.h
+nbdb_sniffer_test.o: ../../include/sys_defs.h
+nbdb_sniffer_test.o: ../../include/vbuf.h
+nbdb_sniffer_test.o: ../../include/vstream.h
+nbdb_sniffer_test.o: ../../include/vstring.h
+nbdb_sniffer_test.o: nbdb_sniffer.h
+nbdb_sniffer_test.o: nbdb_sniffer_test.c
--- /dev/null
+/*++
+/* NAME
+/* nbdb_index_as 3
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_index_as.h>
+/*
+/* int nbdb_index_as(
+/* const char *command,
+/* const char *new_type,
+/* const char *source_path,
+/* uid_t uid,
+/* gid_t gid,
+/* VSTRING *why)
+/* DESCRIPTION
+/* nbdb_index_as() runs a command with the specified effective
+/* uid and gid, to create an indexed file from a source file.
+/* The command is killed after 100s. A limited amount of command
+/* output is returned after failure.
+/*
+/* The result value is one of the following:
+/* .IP NBDB_STAT_OK
+/* The request was successful.
+/* .IP NBDB_STAT_ERROR
+/* The request failed. A description of the problem is returned
+/* in \fBwhy\fR.
+/* .PP
+/* Arguments:
+/* .IP command
+/* Run this command, "postmap" or "postalias".
+/* .IP new_type
+/* Create an indexed file of this type.
+/* .IP source_path
+/* The pathname of the Berkeley DB source file.
+/* .IP uid, gid
+/* Run the command with these effective uid and gid,
+/* .IP why
+/* Storage that is updated with an applicable error description.
+/* SEE ALSO
+/* nbdb_index_as_test(1t), unit test
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+ /*
+ * Utility library.
+ */
+#include <argv.h>
+#include <iostuff.h>
+#include <spawn_command.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <mail_parm_split.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_index_as.h>
+#include <nbdb_util.h>
+
+#define STR(x) vstring_str(x)
+
+/* nbdb_index_as - index a database with specified type and privileges */
+
+int nbdb_index_as(const char *command, const char *new_type,
+ const char *source_path, uid_t uid, gid_t gid, VSTRING *why)
+{
+ VSTRING *command_path;
+ VSTRING *command_arg;
+ char *cmd_argv[3];
+ ARGV *export_env;
+ static int devnull_fd = -1;
+ int cmd_out[2];
+ int status;
+
+ /*
+ * Redirect the command's stdin to /dev/null. If we are going to do this
+ * in multiple programs, then we should make it a library feature.
+ */
+ if (devnull_fd < 0 && (devnull_fd = open("/dev/null", O_RDWR, 0)) < 0) {
+ vstring_sprintf(why, "open /dev/null O_RDWR: %m");
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Redirect the command's stdout and stderr to a pipe. See comments in
+ * pipe_command.c for a similar strategy to capture a limited amount of
+ * command output.
+ */
+ if (pipe(cmd_out) < 0) {
+ vstring_sprintf(why, "create %s output pipe: %m", command);
+ return (NBDB_STAT_ERROR);
+ }
+ non_blocking(cmd_out[0], NON_BLOCKING); /* us */
+ non_blocking(cmd_out[1], NON_BLOCKING); /* them */
+
+ /*
+ * Run the command with a generous time limit. If we kill the command
+ * then we leave behind a broken database.
+ *
+ * TODO(wietse) extend spawn_command() with an option to return instead of
+ * terminating after fork() or wait() failure, maybe with fake command
+ * output, and certainly without file descriptor leaks.
+ */
+ cmd_argv[0] = STR(vstring_sprintf(command_path = vstring_alloc(100),
+ "%s/%s", var_command_dir, command));
+ cmd_argv[1] = STR(vstring_sprintf(command_arg = vstring_alloc(100),
+ "%s:%s", new_type, source_path));
+ cmd_argv[2] = 0;
+ export_env = mail_parm_split(VAR_EXPORT_ENVIRON, var_export_environ);
+ status = spawn_command(CA_SPAWN_CMD_STDIN(devnull_fd),
+ CA_SPAWN_CMD_STDOUT(cmd_out[1]),
+ CA_SPAWN_CMD_STDERR(cmd_out[1]),
+ CA_SPAWN_CMD_ARGV(cmd_argv),
+ CA_SPAWN_CMD_UID(uid),
+ CA_SPAWN_CMD_GID(gid),
+ CA_SPAWN_CMD_EXPORT(export_env->argv),
+ CA_SPAWN_CMD_TIME_LIMIT(100),
+ CA_SPAWN_CMD_END);
+
+ /*
+ * If the command failed, capture a limited amount of command output.
+ */
+ close(cmd_out[1]); /* them */
+ if (status != 0) {
+ ssize_t count;
+
+#define NBDB_MIN(x, y) ((x) < (y) ? (x) : (y))
+
+ VSTRING_RESET(why);
+ VSTRING_SPACE(why, VSTREAM_BUFSIZE);
+ errno = 0;
+ if (read_wait(cmd_out[0], 0) < 0 ||
+ (count = peekfd(cmd_out[0])) <= 0 ||
+ (count = read(cmd_out[0], STR(why),
+ NBDB_MIN(count, vstring_avail(why)))) <= 0) {
+ vstring_sprintf(why, "(%s failure reason unavailable: %m)",
+ command);
+ } else {
+ /* Apply some basic hygiene. */
+ vstring_set_payload_size(why, count);
+ VSTRING_TERMINATE(why);
+ (void) translit(STR(why), "\b\r\n", "__");
+ }
+ }
+ close(cmd_out[0]); /* us */
+ vstring_free(command_arg);
+ vstring_free(command_path);
+ argv_free(export_env);
+
+ return (status == 0 ? NBDB_STAT_OK : NBDB_STAT_ERROR);
+}
--- /dev/null
+#ifndef _NBDB_INDEX_AS_H_INCLUDED_
+#define _NBDB_INDEX_AS_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_index_as.h 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_index_as.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <nbdb_util.h>
+
+ /*
+ * Internal API.
+ */
+extern int nbdb_index_as(const char *, const char *, const char *,
+ uid_t, gid_t, VSTRING *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_index_as_test 1t
+/* SUMMARY
+/* index_as unit test
+/* SYNOPSIS
+/* ./nbdb_index_as_test
+/* DESCRIPTION
+/* index_as_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <spawn_command.h>
+
+ /*
+ * Global library.
+ */
+#include <nbdb_util.h>
+
+ /*
+ * Testing library.
+ */
+#include <mock_spawn_command.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_index_as.h>
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+ /*
+ * Scaffolding for parameter dependencies.
+ */
+char *var_command_dir = DEF_COMMAND_DIR;
+char *var_export_environ = "TZ MAIL_CONFIG LANG";
+
+ /*
+ * Test structure. Some tests may bring their own.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+
+ /*
+ * nbdb_index_as() mock dependencies.
+ */
+ MOCK_SPAWN_CMD_REQ mock_spawn;
+
+ /*
+ * nbdb_index_as() inputs and expected outputs.
+ */
+ struct index_info {
+ const char *in_command;
+ const char *in_new_type;
+ const char *in_source_path;
+ uid_t in_uid;
+ gid_t in_gid;
+ int want_status;
+ const char *want_why;
+ } index;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+/* test_nbdb_index_as */
+
+static int test_nbdb_index_as(const TEST_CASE *tp)
+{
+ int got_status;
+ VSTRING *got_why;
+ int pass = 1;
+
+ setup_mock_spawn_command(&tp->mock_spawn);
+ got_why = vstring_alloc(100);
+ got_status =
+ nbdb_index_as(tp->index.in_command, tp->index.in_new_type,
+ tp->index.in_source_path, tp->index.in_uid,
+ tp->index.in_gid, got_why);
+
+ if (got_status != tp->index.want_status) {
+ msg_warn("got status '%d', want '%d'", got_status,
+ tp->index.want_status);
+ pass = 0;
+ } else if (got_status != 0
+ && strstr(STR(got_why), tp->index.want_why) == 0) {
+ msg_warn("got reason '%s' want '%s'", STR(got_why),
+ tp->index.want_why);
+ pass = 0;
+ }
+ vstring_free(got_why);
+ return (pass ? PASS : FAIL);
+}
+
+ /*
+ * The list of test cases.
+ */
+static const TEST_CASE test_cases[] = {
+ {.label = "normal_completion",
+ .action = test_nbdb_index_as,
+ .mock_spawn = {
+ .want_args = {
+ .argv = (char *[]) {DEF_COMMAND_DIR "/postmap", "lmdb:/path/to/foo", 0,},
+ .uid = 0,
+ .gid = 0,
+ .export = (char *[]) {"TZ", "MAIL_CONFIG", "LANG", 0,},
+ .time_limit = 100,
+ },
+ .out_status = NBDB_STAT_OK,
+ .out_text = 0,
+ },
+ .index = {
+ .in_command = "postmap",
+ .in_new_type = "lmdb",
+ .in_source_path = "/path/to/foo",
+ .in_uid = 0,
+ .in_gid = 0,
+ .want_status = NBDB_STAT_OK,
+ .want_why = 0,
+ },
+ },
+ {.label = "propagates_non_zero_status_and_text",
+ .action = test_nbdb_index_as,
+ .mock_spawn = {
+ .want_args = {
+ .argv = (char *[]) {DEF_COMMAND_DIR "/postmap", "lmdb:/path/to/foo", 0,},
+ .uid = 0,
+ .gid = 0,
+ .export = (char *[]) {"TZ", "MAIL_CONFIG", "LANG", 0,},
+ .time_limit = 100,
+ },
+ .out_status = NBDB_STAT_ERROR,
+ .out_text = "sorry, I cannot do that",
+ },
+ .index = {
+ .in_command = "postmap",
+ .in_new_type = "lmdb",
+ .in_source_path = "/path/to/foo",
+ .in_uid = 0,
+ .in_gid = 0,
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "I cannot do that",
+ },
+ },
+
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* nbdb_process 3
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_process.h>
+/*
+/* int nbdb_process(
+/* const char *legacy_type,
+/* const char *source_path,
+/* VSTRING *why)
+/* DESCRIPTION
+/* nbdb_process() integrates the safety policy and content policy,
+/* and calls spawn_command() to generate an indexed file for
+/* $non_legacy_type:$source_path.
+/*
+/* The result value is NBDB_MIGR_OK (success) or NBDB_MIGR_ERROR
+/* (failure).
+/*
+/* Arguments:
+/* .IP new_type
+/* A non-legacy database type.
+/* .P source_path
+/* The pathname for the source text file (no database suffix).
+/* .IP why
+/* Storage for descriptive text in case of error.
+/* SEE ALSO
+/* nbdb_safe(3), safety policy
+/* nbdb_sniffer(3), content policy
+/* nbdb_process_test(1t), unit test
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <libgen.h> /* dirname() */
+
+ /*
+ * Utility library.
+ */
+#include <attr.h>
+#include <msg.h>
+#include <spawn_command.h>
+#include <vstring.h>
+#include <wrap_stat.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+#include <mail_params.h>
+#include <nbdb_util.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_reindexd.h>
+#include <nbdb_safe.h>
+#include <nbdb_sniffer.h>
+#include <nbdb_index_as.h>
+#include <nbdb_process.h>
+
+#define STR(x) vstring_str(x)
+
+/* nbdb_process - main processing flow */
+
+int nbdb_process(const char *leg_type, const char *source_path,
+ VSTRING *why)
+{
+ const char *new_type;
+ struct stat source_st;
+ static VSTRING *new_idx_path;
+ struct stat new_idx_st;
+ static VSTRING *leg_idx_path;
+ struct stat leg_idx_st;
+ static VSTRING *parent_dir_buf;
+ struct stat parent_dir_st;
+ char *parent_dir;
+ const char *new_suffix;
+ const char *index_cmd;
+ int status;
+
+ if (new_idx_path == 0) {
+ new_idx_path = vstring_alloc(100);
+ leg_idx_path = vstring_alloc(100);
+ parent_dir_buf = vstring_alloc(100);
+ }
+
+ /*
+ * First things first.
+ */
+ if (nbdb_level < NBDB_LEV_CODE_REINDEX) {
+ vstring_sprintf(why, "the %s service is disabled", var_servname);
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * nbdb_map_leg_type() will allow only mapping from an expected Berkeley
+ * DB type to an expected non-Berkeley-DB type.
+ */
+ if ((new_type = nbdb_map_leg_type(leg_type, source_path,
+ (const DICT_OPEN_INFO **) 0, why)) == 0) {
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Look up the non-legacy pathname suffix and build the pathname that
+ * needs to be created. If no suffix exists then the client is in error.
+ */
+ if ((new_suffix = nbdb_find_non_leg_suffix(new_type)) == 0) {
+ vstring_sprintf(why, "non-Berkeley-DB type '%s' has no known suffix",
+ new_type);
+ return (NBDB_STAT_ERROR);
+ }
+ vstring_sprintf(new_idx_path, "%s%s", source_path, new_suffix);
+
+ /*
+ * If the target indexed pathname already exists, then do nothing. All
+ * indexing requests are handled sequentially (to avoid collisions), and
+ * the client may have connected to this service before the file was
+ * indexed.
+ */
+ if (stat (STR(new_idx_path), &new_idx_st) == 0 && new_idx_st.st_size > 0) {
+ msg_info("target file '%s' already exists, skipping this request",
+ STR(new_idx_path));
+ return (NBDB_STAT_OK);
+ }
+
+ /*
+ * Require that the legacy indexed file exists. We need this to determine
+ * the owner's (uid, gid) to run the postmap or postalias command with.
+ */
+ vstring_sprintf(leg_idx_path, "%s%s", source_path, NBDB_LEGACY_SUFFIX);
+ if (stat (STR(leg_idx_path), &leg_idx_st) < 0) {
+ vstring_sprintf(why, "look up status for legacy indexed file '%s': %m",
+ STR(leg_idx_path));
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Require that the source path exists. We need it as input for indexing,
+ * and will reject the request if the source has unsafe permissions for
+ * the uid that we would run postmap or postalias with.
+ */
+ if (stat (source_path, &source_st) < 0) {
+ vstring_sprintf(why, "look up status for source file '%s': %m",
+ source_path);
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Require that the parent directory exists. We will reject the request
+ * if the directory has unsafe permissions for the uid that we would run
+ * postmap or postalias with.
+ */
+ vstring_strcpy(parent_dir_buf, source_path);
+ parent_dir = dirname(STR(parent_dir_buf));
+ if (stat (parent_dir, &parent_dir_st) < 0) {
+ vstring_sprintf(why, "look up status for parent directory '%s': %m",
+ parent_dir);
+ return (NBDB_STAT_ERROR);
+ }
+
+ /*
+ * Should we run postmap or postalias? Open the source file with the same
+ * (uid, gid) as the postmap or postalias commands would, so that we can
+ * detect permission errors quickly.
+ *
+ * Note: we do this before the file allowlist/owner/permission safety
+ * checks, so that we can log the concrete postmap or postalias command
+ * if a safety check fails.
+ */
+ if ((index_cmd = nbdb_get_index_cmd_as(source_path, leg_idx_st.st_uid,
+ leg_idx_st.st_gid, why)) == 0)
+ return (NBDB_STAT_ERROR);
+
+ /*
+ * Allow indexing as the legacy indexed file owner if it is considered
+ * "safe".
+ */
+ if (!nbdb_safe_to_index_as_legacy_index_owner(source_path, &source_st,
+ STR(leg_idx_path), &leg_idx_st,
+ parent_dir, &parent_dir_st, why)) {
+ status = NBDB_STAT_ERROR;
+ }
+
+ /*
+ * Finally!
+ */
+ else {
+ status = nbdb_index_as(index_cmd, new_type, source_path,
+ leg_idx_st.st_uid, leg_idx_st.st_gid, why);
+ if (status != NBDB_STAT_OK)
+ /* Don't leave behind a broken indexed file. */
+ (void) unlink(STR(new_idx_path));
+ }
+
+ /*
+ * If the command failed, or was not safe to execute automatically, give
+ * the user the concrete command so that they could run it by hand.
+ */
+ if (status == NBDB_STAT_OK) {
+ msg_info("successfully executed '%s %s:%s' as uid %d",
+ index_cmd, new_type, source_path, leg_idx_st.st_uid);
+ } else {
+ vstring_sprintf_prepend(why, "could not execute command '%s %s:%s': ",
+ index_cmd, new_type, source_path);
+ vstring_strcat(why,
+ "; alternatively, execute the failed command by hand");
+ }
+ return (status);
+}
--- /dev/null
+#ifndef _NBDB_PROCESS_H_INCLUDED_
+#define _NBDB_PROCESS_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_process.h 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_process.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <nbdb_util.h>
+
+ /*
+ * Internal API.
+ */
+extern int nbdb_process(const char *, const char *, VSTRING *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_process_test 1t
+/* SUMMARY
+/* nbdb_process unit test
+/* SYNOPSIS
+/* ./nbdb_process_test
+/* DESCRIPTION
+/* nbdb_process_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict_cdb.h>
+#include <dict_lmdb.h>
+#include <msg.h>
+#include <msg_vstream.h>
+#include <mock_dict.h>
+#include <mock_stat.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+#include <nbdb_util.h>
+#include <mail_params.h>
+#include <msg_capture.h>
+
+ /*
+ * Testing library.
+ */
+#include <mock_spawn_command.h>
+#include <mock_stat.h>
+#include <mock_open_as.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_index_as.h>
+#include <nbdb_safe.h>
+#include <nbdb_index_as.h>
+#include <nbdb_process.h>
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+ /*
+ * Scaffolding for static parameter dependencies.
+ */
+char *var_command_dir = DEF_COMMAND_DIR;
+char *var_export_environ = "TZ MAIL_CONFIG LANG";
+char *var_servname = "nbdb_reindexd";
+char *var_db_type = DICT_TYPE_CDB;
+char *var_cache_db_type = DICT_TYPE_LMDB;
+char *var_nbdb_cust_map = DEF_NBDB_CUST_MAP;
+
+ /*
+ * Test-dependent configuration parameters.
+ */
+bool var_nbdb_enable = 0;
+
+char *var_nbdb_allow_root_pfxs = DEF_NBDB_ALLOW_ROOT_PFXS;
+char *var_nbdb_allow_user_pfxs = DEF_NBDB_ALLOW_USER_PFXS;
+
+ALLOWED_PREFIX *parsed_allow_root_pfxs;
+ALLOWED_PREFIX *parsed_allow_user_pfxs;
+
+ /*
+ * Test structure. TODO(wietse) readability problem: there are many test
+ * inputs, their values have a lot of overlap, and the tests data are far
+ * away from the code that uses it. For readability sake, consider using
+ * dedicated test-case functions with test data in local variables.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+
+ /*
+ * Mock dependencies.
+ */
+ MOCK_STAT_REQ mock_stat_source;
+ MOCK_STAT_REQ mock_stat_leg_idx;
+ MOCK_STAT_REQ mock_stat_parent;
+ MOCK_STAT_REQ mock_stat_new_idx;
+ MOCK_OPEN_AS_REQ mock_open;
+ MOCK_SPAWN_CMD_REQ mock_spawn;
+
+ /*
+ * nbdb_process() inputs and expected outputs.
+ */
+ struct {
+ const char *in_new_type;
+ const char *in_source_path;
+ int want_status;
+ const char *want_why;
+ const char *want_msg;
+ } process;
+
+ /*
+ * Configuration parameter settings.
+ */
+ struct {
+ const char *migr_level;
+ const char *allow_root_pfxs;
+ const char *allow_user_pfxs;
+ } params;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+/* test_nbdb_process */
+
+static int test_nbdb_process(const TEST_CASE *tp)
+{
+ MSG_CAPTURE *capture;
+ const char *got_msg;
+ int got_status;
+ VSTRING *got_why;
+ int pass = 1;
+
+ nbdb_util_init(tp->params.migr_level);
+ setup_mock_cdb("{{x = x}}");
+ setup_mock_lmdb("{{x = x}}");
+ if (nbdb_level >= NBDB_LEV_CODE_REINDEX) {
+ var_nbdb_allow_root_pfxs = (char *) tp->params.allow_root_pfxs;
+ var_nbdb_allow_user_pfxs = (char *) tp->params.allow_user_pfxs;
+
+ parsed_allow_root_pfxs = allowed_prefix_create(var_nbdb_allow_root_pfxs);
+ parsed_allow_user_pfxs = allowed_prefix_create(var_nbdb_allow_user_pfxs);
+
+ setup_mock_stat(&tp->mock_stat_source);
+ setup_mock_stat(&tp->mock_stat_leg_idx);
+ setup_mock_stat(&tp->mock_stat_parent);
+ setup_mock_stat(&tp->mock_stat_new_idx);
+ setup_mock_vstream_fopen_as(&tp->mock_open);
+ setup_mock_spawn_command(&tp->mock_spawn);
+ }
+ capture = msg_capt_create(100);
+ got_why = vstring_alloc(100);
+
+ msg_capt_start(capture);
+ got_status =
+ nbdb_process(tp->process.in_new_type, tp->process.in_source_path,
+ got_why);
+ msg_capt_stop(capture);
+ got_msg = msg_capt_expose(capture);
+
+ if (tp->process.want_why == 0 && LEN(got_why) > 0) {
+ msg_warn("got unexpected reason '%s', want (none)", STR(got_why));
+ pass = 0;
+ }
+ if (tp->process.want_msg == 0 && *got_msg != 0) {
+ msg_warn("got unexpected message '%s', want (none)", got_msg);
+ pass = 0;
+ }
+ if (tp->process.want_msg && strstr(got_msg, tp->process.want_msg) == 0) {
+ msg_warn("got unexpected message '%s', want '%s'",
+ got_msg, tp->process.want_msg);
+ pass = 0;
+ }
+ if (got_status != tp->process.want_status) {
+ msg_warn("got status '%d', want '%d'", got_status,
+ tp->process.want_status);
+ pass = 0;
+ } else if (got_status != 0
+ && strstr(STR(got_why), tp->process.want_why) == 0) {
+ msg_warn("got reason '%s', want '%s'", STR(got_why),
+ tp->process.want_why);
+ pass = 0;
+ }
+ vstring_free(got_why);
+ msg_capt_free(capture);
+ if (nbdb_level >= NBDB_LEV_CODE_REINDEX) {
+ allowed_prefix_free(parsed_allow_root_pfxs);
+ allowed_prefix_free(parsed_allow_user_pfxs);
+ }
+ return (pass ? PASS : FAIL);
+}
+
+ /*
+ * The list of test cases. If you want to figure out what the tests do, the
+ * data below shows their recipe.
+ */
+static const TEST_CASE test_cases[] = {
+
+ {.label = "normal_completion",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 0,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .mock_spawn = {
+ .want_args = {
+ .argv = (char *[]) {DEF_COMMAND_DIR "/postmap", "cdb:/path/to/file", 0,},
+ .uid = 0,
+ .gid = 0,
+ .export = (char *[]) {"TZ", "MAIL_CONFIG", "LANG", 0,},
+ .time_limit = 100,
+ },
+ .out_status = 0,
+ .out_text = 0,
+ },
+ .params = {
+ .allow_root_pfxs = "/path/to",
+ .allow_user_pfxs = "/home/foo",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_OK,
+ .want_why = 0,
+ .want_msg = "successfully executed",
+ },
+ },
+
+ {.label = "respects_migr_level_disable",
+ .action = test_nbdb_process,
+ .params = {
+ .migr_level = "disable",
+ },
+ .process = {
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "service is disabled",
+ },
+ },
+
+ {.label = "propagates_nbdb_index_as_error",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 0,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .mock_spawn = {
+ .want_args = {
+ .argv = (char *[]) {DEF_COMMAND_DIR "/postmap", "cdb:/path/to/file", 0,},
+ .uid = 0,
+ .gid = 0,
+ .export = (char *[]) {"TZ", "MAIL_CONFIG", "LANG", 0,},
+ .time_limit = 100,
+ },
+ .out_status = NBDB_STAT_ERROR,
+ .out_text = "sorry, I cannot do that",
+ },
+ .params = {
+ .allow_root_pfxs = "/path/to",
+ .allow_user_pfxs = "/home/foo",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "cannot do that",
+ },
+ },
+
+ {.label = "propagates_nbdb_safe_to_index_error",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IWGRP,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 0,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .params = {
+ .allow_root_pfxs = "/path/to",
+ .allow_user_pfxs = "/home/foo",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "owned or writable by other user",
+ },
+ },
+
+ {.label = "propagates_nbdb_sniffer_error",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 0,
+ .want_gid = 0,
+ .out_errno = EACCES,
+ .out_data = 0,
+ },
+ .params = {
+ .allow_root_pfxs = "/path/to",
+ .allow_user_pfxs = "/home/foo",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "open lookup table source file /path/to/file",
+ },
+ },
+
+ /*
+ * Pathname prefix safety is enforced by nbdb_safe_to_index_as_xxx but it
+ * is important enough to have its own end-to-end test.
+ */
+ {.label = "respects_allow_root_prefix",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {
+ .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
+ },
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {
+ .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
+ },
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {
+ .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
+ },
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 1,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .params = {
+ .allow_root_pfxs = "/other/path",
+ .allow_user_pfxs = "/home/foo",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "could not execute command 'postmap cdb:/path/to/file': table /path/to/file has an unexpected pathname",
+ },
+ },
+
+ {.label = "normal_completion_non_root_case",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 1,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .mock_spawn = {
+ .want_args = {
+ .argv = (char *[]) {DEF_COMMAND_DIR "/postmap", "cdb:/path/to/file", 0,},
+ .uid = 1,
+ .gid = 0,
+ .export = (char *[]) {"TZ", "MAIL_CONFIG", "LANG", 0,},
+ .time_limit = 100,
+ },
+ .out_status = 0,
+ .out_text = 0,
+ },
+ .params = {
+ .allow_root_pfxs = "/somewhere",
+ .allow_user_pfxs = "/path/to",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_OK,
+ .want_why = 0,
+ .want_msg = "successfully executed",
+ },
+ },
+
+ {.label = "respects_allow_user_prefix",
+ .action = test_nbdb_process,
+ .mock_stat_source = {
+ .want_path = "/path/to/file",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_leg_idx = {
+ .want_path = "/path/to/file.db",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_parent = {
+ .want_path = "/path/to",
+ .out_errno = 0,
+ .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
+ },
+ .mock_stat_new_idx = {
+ .want_path = "/path/to/file.cdb",
+ .out_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "/path/to/file",
+ .want_uid = 0,
+ .want_gid = 0,
+ .out_errno = 0,
+ .out_data = "foo bar\nfoo :bar",
+ },
+ .params = {
+ .allow_root_pfxs = "/somewhere",
+ .allow_user_pfxs = "/other/path",
+ .migr_level = "enable-reindex",
+ },
+ .process = {
+ .in_new_type = "hash",
+ .in_source_path = "/path/to/file",
+ .want_status = NBDB_STAT_ERROR,
+ .want_why = "unexpected pathname",
+ },
+ },
+
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* nbdb_reindexd 8
+/* SUMMARY
+/* Postfix non-Berkeley-DB migration
+/* SYNOPSIS
+/* \fBnbdb_reindexd\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* \fINOTE: This service should be enabled only temporarily to
+/* generate most of the non-Berkeley-DB indexed files that Postfix
+/* needs. Leaving this service enabled may expose the system to
+/* privilege-escalation attacks.\fR
+/*
+/* The nbdb_reindexd(8) server handles requests to generate
+/* a non-Berkeley-DB indexed database file for an existing Berkeley
+/* DB database (example: "hash:/path/to/file" or
+/* "btree:/path/to/file"). It implements the service by running
+/* the postmap(1) or postalias(1) command with appropriate
+/* privileges.
+/*
+/* The service reports a success status when the non-Berkeley-DB
+/* indexed file already exists. This can happen when multiple clients
+/* make the same request. When one request is completed successfully,
+/* the service also reports success for the other requests.
+/*
+/* This service enforces the following safety policy:
+/* .IP \(bu
+/* The legacy Berkeley DB indexed file must exist (file name ends in
+/* ".db"). The nbdb_reindexd(8) service will use the owner"s (uid,
+/* gid) of this file, when it runs postmap(1) or postalias(1). It
+/* also uses the (uid,gid) for a number of safety checks as
+/* described next.
+/* .IP \(bu
+/* The non-indexed source file must exist (file name without
+/* ".db" suffix). This file is needed as input for postmap(1)
+/* or postalias(1). The file must be owned by "root" or by the
+/* above uid, and must not allow "group" or "other" write access.
+/* .IP \(bu
+/* The parent directory must be owned by "root" or by the above uid,
+/* and it must not allow "group" or "other" write access.
+/* .IP \(bu
+/* Additionally, the "non_bdb_migration_allow_root_prefixes"
+/* parameter limits the source file directory prefixes that are
+/* allowed when this service needs to run postmap(1) or postalias(1)
+/* with "root" privileges.
+/* .IP \(bu
+/* A similar parameter, "non_bdb_migration_allow_user_prefixes",
+/* limits the source file directory prefixes that are allowed when
+/* this service needs to run postmap(1) or postalias(1) as an
+/* unprivileged user.
+/* SECURITY
+/* .ad
+/* .fi
+/* The nbdb_reindexd(8) server is security sensitive. It accepts
+/* requests only from processes that can access sockets under
+/* $queue_directory/private (i.e., processes that run with "root"
+/* or "mail_owner" (usually, postfix) privileges).
+/*
+/* The threat is therefore a corrupted Postfix daemon process that
+/* wants to elevate privileges, by sending requests with crafted
+/* pathnames, and racing against the service by quickly swapping
+/* files or directories, hoping that Postfix will be tricked to
+/* overwrite a sensitive file with attacker-controlled data.
+/*
+/* When the service runs postmap(1) or postalias(1) as
+/* "root", such racing attacks should not be possible if
+/* non_bdb_migration_allow_root_prefixes specifies only prefixes
+/* that are already trusted.
+/*
+/* This service could block all requests with crafted pathnames,
+/* if given complete information about all lookup tables that are
+/* referenced through Postfix configuration files. Unfortunately
+/* that information was not available at the time that this program
+/* was needed.
+/* DIAGNOSTICS
+/* Problems and transactions are logged to syslogd(8) or
+/* postlogd(8). If an attempt to create an index file fails, this
+/* service will attempt to delete the incomplete file.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* Changes to main.cf are not picked up automatically, as
+/* nbdb_reindexd(8) processes are long-lived. Use the command
+/* "postfix reload" after a configuration change.
+/*
+/* The text below provides only a parameter summary. See
+/* postconf(5) for more details including examples.
+/* SERVICE-SPECIFIC CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBnon_bdb_migration_level (disable)\fR"
+/* The non-Berkeley-DB migration service level.
+/* .IP "\fBnon_bdb_migration_allow_root_prefixes (see 'postconf -d non_bdb_migration_allow_root_prefixes' output)\fR"
+/* A list of trusted pathname prefixes that must be matched when
+/* the non-Berkeley-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+/* run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with "root" privilege.
+/* .IP "\fBnon_bdb_migration_allow_user_prefixes (see 'postconf -d non_bdb_migration_allow_user_prefixes' output)\fR"
+/* A list of trusted pathname prefixes that must be matched when
+/* the non-Berkeley-DB migration service (\fBnbdb_reindexd\fR(8)) needs to
+/* run \fBpostmap\fR(1) or \fBpostalias\fR(1) commands with non-root privilege.
+/* MISCELLANEOUS CONTROLS
+/* .ad
+/* .fi
+/* .IP "\fBconfig_directory (see 'postconf -d' output)\fR"
+/* The default location of the Postfix main.cf and master.cf
+/* configuration files.
+/* .IP "\fBprocess_id (read-only)\fR"
+/* The process ID of a Postfix command or daemon process.
+/* .IP "\fBprocess_name (read-only)\fR"
+/* The process name of a Postfix command or daemon process.
+/* .IP "\fBsyslog_facility (mail)\fR"
+/* The syslog facility of Postfix logging.
+/* .IP "\fBsyslog_name (see 'postconf -d' output)\fR"
+/* A prefix that is prepended to the process name in syslog
+/* records, so that, for example, "smtpd" becomes "prefix/smtpd".
+/* .IP "\fBservice_name (read-only)\fR"
+/* The master.cf service name of a Postfix daemon process.
+/* SEE ALSO
+/* postfix-non-bdb(1), migration management
+/* postconf(5), configuration parameters
+/* postlogd(8), Postfix logging
+/* syslogd(8), system logging
+/* README FILES
+/* .ad
+/* .fi
+/* Use "\fBpostconf readme_directory\fR" or
+/* "\fBpostconf html_directory\fR" to locate this information.
+/* .na
+/* .nf
+/* NON_BERKELEYDB_README, Non-Berkeley-DB migration guide
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* HISTORY
+/* .ad
+/* .fi
+/* This service was introduced with Postfix version 3.11.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+ /*
+ * Utility library.
+ */
+#include <attr.h>
+#include <msg.h>
+#include <set_eugid.h>
+#include <vstream.h>
+#include <vstring.h>
+#include <wrap_stat.h>
+#include <split_at.h>
+#include <msg_vstream.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <mail_task.h>
+#include <mail_version.h>
+#include <nbdb_util.h>
+
+/* Single-threaded server skeleton. */
+
+#include <mail_server.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_index_as.h>
+#include <nbdb_process.h>
+#include <nbdb_reindexd.h>
+#include <nbdb_safe.h>
+#include <nbdb_sniffer.h>
+
+char *var_nbdb_allow_root_pfxs;
+char *var_nbdb_allow_user_pfxs;
+
+ALLOWED_PREFIX *parsed_allow_root_pfxs;
+ALLOWED_PREFIX *parsed_allow_user_pfxs;
+
+#define STR(x) vstring_str(x)
+
+/* nbdb_service - CLI or RPC protocol wrapper */
+
+static void nbdb_service(VSTREAM *stream, char *service, char **argv)
+{
+ static VSTRING *leg_type;
+ static VSTRING *source_path;
+ static VSTRING *why;
+ int status;
+
+ if (leg_type == 0) {
+ leg_type = vstring_alloc(10);
+ source_path = vstring_alloc(100);
+ why = vstring_alloc(100);
+ } else {
+ VSTRING_RESET(why);
+ VSTRING_TERMINATE(why);
+ }
+
+ /*
+ * Command-line mode (a.k.a. stand-alone).
+ */
+ if (stream == VSTREAM_IN) {
+ char *path;
+
+ msg_vstream_init(mail_task(var_procname), VSTREAM_ERR);
+ if (*argv == 0 || argv[1] != 0)
+ msg_fatal("stand-alone mode requires one type:/path argument");
+ vstring_strcpy(leg_type, *argv);
+ if ((path = split_at(STR(leg_type), ':')) == 0 || *path != '/')
+ msg_fatal("stand-alone mode called with bad argument: '%s'", *argv);
+ if ((status = nbdb_process(STR(leg_type), path, why)) != 0)
+ msg_warn("stand-alone request to re-index '%s:%s' failed: %s",
+ STR(leg_type), path, STR(why));
+ exit(status != 0);
+ }
+
+ /*
+ * Daemon mode.
+ */
+ attr_print(stream, ATTR_FLAG_NONE,
+ SEND_ATTR_STR(MAIL_ATTR_PROTO, MAIL_ATTR_PROTO_NBDB_REINDEX),
+ ATTR_TYPE_END);
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
+ RECV_ATTR_STR(MAIL_ATTR_NBDB_TYPE, leg_type),
+ RECV_ATTR_STR(MAIL_ATTR_NBDB_PATH, source_path),
+ ATTR_TYPE_END) != 2)
+ return;
+ status = nbdb_process(STR(leg_type), STR(source_path), why);
+ if (status != NBDB_STAT_OK)
+ msg_warn("request to index %s:%s failed: %s",
+ STR(leg_type), STR(source_path), STR(why));
+ attr_print(stream, ATTR_FLAG_NONE,
+ SEND_ATTR_INT(MAIL_ATTR_STATUS, status),
+ SEND_ATTR_STR(MAIL_ATTR_WHY, STR(why)),
+ ATTR_TYPE_END);
+}
+
+/* post_init - late initialization */
+
+static void post_init(char *unused_name, char **unused_argv)
+{
+
+ /*
+ * Drop root privileges most of the time. Modern UNIX-like systems will
+ * prevent a process with mail_owner privs from manipulating this process
+ * which still runs with a real uid of root.
+ */
+ set_eugid(var_owner_uid, var_owner_gid);
+
+ /*
+ * Initialize the allowed pathname prefix matcher.
+ */
+ parsed_allow_root_pfxs = allowed_prefix_create(var_nbdb_allow_root_pfxs);
+ parsed_allow_user_pfxs = allowed_prefix_create(var_nbdb_allow_user_pfxs);
+
+ /*
+ * TODO(wietse) alternatively, maybe run "proxymap -Sndump-xxxx" commands
+ * while privileged, so that the result cannot be manipulated by a
+ * compromised non-root process. Unfortunately, proxymap still does find
+ * lookup tables in "domain" matchlists of LDAP, SQL, etc. clients.
+ */
+}
+
+ /*
+ * Fingerprint executables and core dumps.
+ */
+MAIL_VERSION_STAMP_DECLARE;
+
+int main(int argc, char **argv)
+{
+
+ /*
+ * var_nbdb_enable and var_nbdb_cust_map are used in many programs,
+ * therefore they are managed by mail_params.c.
+ */
+ static const CONFIG_STR_TABLE str_table[] = {
+ VAR_NBDB_ALLOW_ROOT_PFXS, DEF_NBDB_ALLOW_ROOT_PFXS, &var_nbdb_allow_root_pfxs, 0, 0,
+ VAR_NBDB_ALLOW_USER_PFXS, DEF_NBDB_ALLOW_USER_PFXS, &var_nbdb_allow_user_pfxs, 0, 0,
+ 0,
+ };
+
+ /*
+ * Fingerprint executables and core dumps.
+ */
+ MAIL_VERSION_STAMP_ALLOCATE;
+
+ /*
+ * Disable sending database reindexing requests.
+ */
+ nbdb_reindexing_lockout = true;
+
+ single_server_main(argc, argv, nbdb_service,
+ CA_MAIL_SERVER_STR_TABLE(str_table),
+ CA_MAIL_SERVER_POST_INIT(post_init),
+ CA_MAIL_SERVER_PRIVILEGED,
+ CA_MAIL_SERVER_SOLITARY,
+ 0);
+}
--- /dev/null
+#ifndef _NBDB_REINDEXD_H_INCLUDED_
+#define _NBDB_REINDEXD_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_reindexd.h 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_reindexd.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+
+ /*
+ * Internal API.
+ */
+extern ALLOWED_PREFIX *parsed_allow_root_pfxs;
+extern ALLOWED_PREFIX *parsed_allow_user_pfxs;
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_safe 3
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_safe.h>
+/*
+/* bool nbdb_safe_for_uid(
+/* uid_t uid,
+/* const struct stat *st)
+/*
+/* bool nbdb_safe_to_index_as_legacy_index_owner(
+/* const char *source_path,
+/* const struct stat *source_st,
+/* const char *leg_idx_path,
+/* const struct stat *leg_idx_st,
+/* const char *parent_dir,
+/* const struct stat *parent_dir_st,
+/* VSTRING *why)
+/* DESCRIPTION
+/* nbdb_safe_for_uid() determines if the file or directory properties
+/* in "st" are safe for a process that runs with "uid". That is,
+/* the file or directory is owned "root" or by "uid", and does not
+/* allow 'group' or 'other' write access. This predicate ignores
+/* the safety of other pathname components. It is a good idea to
+/* trust only a limited number of pathname prefixes.
+/*
+/* nbdb_safe_to_index_as_legacy_index_owner() determines
+/* if a Berkeley DB source file and parent directory are 'safe'
+/* for the uid of the Berkeley DB indexed file.
+/* .PP
+/* Arguments:
+/* .IP source_path, source_st
+/* Berkeley DB source file pathname and metadata.
+/* .IP leg_idx_path, leg_idx_st
+/* Berkeley DB indexed file pathname and metadata.
+/* .IP parent_dir, parent_dir_st
+/* Parent directory pathname and metadata.
+/* .IP why
+/* Storage that is updated with an applicable error description.
+/* SEE ALSO
+/* nbdb_sniffer_test(1t), unit test
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/stat.h>
+
+ /*
+ * Utility library.
+ */
+#include <wrap_stat.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+#include <mail_conf.h>
+#include <mail_params.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_safe.h>
+#include <nbdb_reindexd.h>
+
+/* nbdb_safe_for_uid - owned by the user or root, not group or other writable */
+
+bool nbdb_safe_for_uid(uid_t uid, const struct stat *st)
+{
+
+ /*
+ * This "safe for" predicate is weaker than the one used in by Chari et
+ * al. in "Where do you want to go today?", which checks every pathname
+ * component (including pathname components in symlink targets). For this
+ * reason, the root user must have additional constraints on the pathname
+ * prefix.
+ */
+ return ((st->st_uid == 0 || uid == st->st_uid)
+ && (st->st_mode & (S_IWGRP | S_IWOTH)) == 0);
+}
+
+/* nbdb_safe_to_index_as_legacy_index_owner - OK to run postmap/postalias */
+
+bool nbdb_safe_to_index_as_legacy_index_owner(
+ const char *source_path, const struct stat *source_st,
+ const char *leg_idx_path, const struct stat *leg_idx_st,
+ const char *parent_dir, const struct stat *parent_dir_st,
+ VSTRING *why)
+{
+ uid_t runas_uid;
+
+ /*
+ * Run postmap or postalias as the legacy indexed file owner, if the
+ * source file, legacy indexed file, and parent directory are safe for
+ * that user, with pathname constraints for 'root' or non-root.
+ */
+ runas_uid = leg_idx_st->st_uid;
+
+ /*
+ * Allow root-privileged execution only for authorized pathnames. This
+ * prevents a corrupted Postfix daemon from submitting requests with
+ * pathnames that appear to be owned by root, under a directory that is
+ * in part under their control, and then run a race attack against us.
+ */
+ if (runas_uid == 0) {
+ if (!allowed_prefix_match(parsed_allow_root_pfxs, source_path)) {
+ vstring_sprintf(why, "table %s has an unexpected pathname; to "
+ "allow automatic indexing as root, append its "
+ "parent directory to the '%s' setting "
+ "(current setting is: \"%s\")",
+ source_path, VAR_NBDB_ALLOW_ROOT_PFXS,
+ var_nbdb_allow_root_pfxs);
+ return (false);
+ }
+ } else {
+ if (!allowed_prefix_match(parsed_allow_user_pfxs, source_path)) {
+ vstring_sprintf(why, "table %s has an unexpected pathname; to "
+ "allow automatic indexing as non-root, append its "
+ "parent directory to the '%s' setting "
+ "(current setting is: \"%s\")",
+ source_path, VAR_NBDB_ALLOW_USER_PFXS,
+ var_nbdb_allow_user_pfxs);
+ return (false);
+ }
+ }
+
+ /*
+ * Allow automated indexing only if the source file and parent directory
+ * are not writable by other users.
+ */
+ if (!nbdb_safe_for_uid(runas_uid, source_st)) {
+ vstring_sprintf(why, "legacy indexed file '%s' is owned by "
+ "uid '%d', but source file '%s' is owned or "
+ "writable by other user; to allow automatic "
+ "indexing, correct the ownership or permissions",
+ leg_idx_path, (int) runas_uid, source_path);
+ return (false);
+ }
+ if (!nbdb_safe_for_uid(runas_uid, parent_dir_st)) {
+ vstring_sprintf(why, "legacy indexed file '%s' is owned by "
+ "uid '%d', but parent directory '%s' is "
+ "owned or writable by other user; to allow "
+ "automatic indexing, correct the ownership or"
+ "permissions", leg_idx_path, (int) runas_uid,
+ parent_dir);
+ return (false);
+ }
+
+ /*
+ * No objections.
+ */
+ return (true);
+}
--- /dev/null
+#ifndef _NBDB_SAFE_H_INCLUDED_
+#define _NBDB_SAFE_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_safe.h 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_safe.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <sys/stat.h>
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * Internal API.
+ */
+extern bool nbdb_safe_for_uid(uid_t, const struct stat *);
+extern bool nbdb_safe_to_index_as_legacy_index_owner(
+ const char *, const struct stat *,
+ const char *, const struct stat *,
+ const char *, const struct stat *,
+ VSTRING *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* nbdb_safe_test 1t
+/* SUMMARY
+/* nbdb_safe unit test
+/* SYNOPSIS
+/* ./nbdb_safe_test
+/* DESCRIPTION
+/* nbdb_safe_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+#include <stringops.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <allowed_prefix.h>
+#include <mail_conf.h>
+#include <mail_params.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_safe.h>
+
+ /*
+ * Scaffolding.
+ */
+ALLOWED_PREFIX *parsed_allow_root_pfxs;
+ALLOWED_PREFIX *parsed_allow_user_pfxs;
+
+char *var_nbdb_allow_root_pfxs;
+char *var_nbdb_allow_user_pfxs;
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+ /*
+ * Test structure.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+ bool want_bool;
+ /* nbdb_safe_for_uid inputs. */
+ uid_t uid;
+ struct stat st;
+ /* nbdb_safe_to_index_as_legacy_index_owner inputs. */
+ const char *source_path;
+ struct stat source_st;
+ const char *leg_idx_path;
+ struct stat leg_idx_st;
+ const char *parent_dir;
+ struct stat parent_dir_st;
+ const char *allow_root_pfxs;
+ const char *allow_user_pfxs;
+ const char *want_why;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+/* test_nbdb_safe_for_uid - single-line vote */
+
+static int test_nbdb_safe_for_uid(const TEST_CASE *tp)
+{
+ bool got_bool;
+
+ /* Run the code under test. */
+ got_bool = nbdb_safe_for_uid(tp->uid, &tp->st);
+
+#define bool_to_text(b) ((b) ? "true" : "false")
+
+ /* Verify the result. */
+ if (got_bool != tp->want_bool) {
+ msg_warn("got result: `%s', want `%s''",
+ bool_to_text(got_bool), bool_to_text(tp->want_bool));
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+/* test_nbdb_safe_to_index_as_legacy_index_owner - majority vote */
+
+static int test_nbdb_safe_to_index_as_legacy_index_owner(const TEST_CASE *tp)
+{
+ static VSTRING *got_why;
+ bool got_bool;
+
+ if (got_why == 0)
+ got_why = vstring_alloc(100);
+
+ /* Run the code under test. */
+ VSTRING_RESET(got_why);
+ var_nbdb_allow_root_pfxs = (char *) tp->allow_root_pfxs;
+ var_nbdb_allow_user_pfxs = (char *) tp->allow_user_pfxs;
+ parsed_allow_root_pfxs = allowed_prefix_create(var_nbdb_allow_root_pfxs);
+ parsed_allow_user_pfxs = allowed_prefix_create(var_nbdb_allow_user_pfxs);
+ got_bool = nbdb_safe_to_index_as_legacy_index_owner(
+ tp->source_path, &tp->source_st,
+ tp->leg_idx_path, &tp->leg_idx_st,
+ tp->parent_dir, &tp->parent_dir_st,
+ got_why);
+ allowed_prefix_free(parsed_allow_root_pfxs);
+ allowed_prefix_free(parsed_allow_user_pfxs);
+
+#define STR_OR_NULL(s) (((s) && *(s)) ? (s) : "(null)")
+
+ /* Verify the result. */
+ if (!LEN(got_why) != !tp->want_why) {
+ msg_warn("got warning: '%s', want: %s",
+ STR_OR_NULL(STR(got_why)), STR_OR_NULL(tp->want_why));
+ return (FAIL);
+ }
+ if (tp->want_why && strstr(STR(got_why), tp->want_why) == 0) {
+ msg_warn("got warning: '%s', want: '%s'",
+ STR(got_why), tp->want_why);
+ return (FAIL);
+ }
+ if (got_bool != tp->want_bool) {
+ msg_warn("got result: '%s', want: '%s'",
+ bool_to_text(got_bool), bool_to_text(tp->want_bool));
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+ /*
+ * The list of test cases.
+ *
+ * TODO(wietse) Almost all tests take a 'good' test case and make one small
+ * mutation. Figure out a way to mutate a copy of a 'good' test cases, and
+ * store only the delta. That would make tests much more readable.
+ */
+static const TEST_CASE test_cases[] = {
+
+ /*
+ * nbdb_safe_for_uid tests.
+ */
+ {.label = "test_safe_for_root:good_configuration",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 0,.st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .want_bool = true,
+ },
+ {.label = "test_safe_for_root:not_owned_by_root",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 0,.st = {.st_uid = 1,.st_mode = S_IRWXU,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_root:group_writable",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 0,.st = {.st_uid = 0,.st_mode = S_IWGRP,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_root:other_writable",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 0,.st = {.st_uid = 0,.st_mode = S_IWOTH,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_non_root:good_root_owned_configuration",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .want_bool = true,
+ },
+ {.label = "test_safe_for_non_root:good_user_owned_configuration",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 1,.st_mode = S_IRWXU,},
+ .want_bool = true,
+ },
+ {.label = "test_safe_for_non_root:root_owned_group_write",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 0,.st_mode = S_IWGRP,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_non_root:root_owned_other_write",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 0,.st_mode = S_IWOTH,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_non_root:user_owned_group_write",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 1,.st_mode = S_IWGRP,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_non_root:user_owned_other_write",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 1,.st_mode = S_IWOTH,},
+ .want_bool = false,
+ },
+ {.label = "test_safe_for_non_root:other_owned",
+ .action = test_nbdb_safe_for_uid,
+ .uid = 1,.st = {.st_uid = 2,.st_mode = 0,},
+ .want_bool = false,
+ },
+
+ /*
+ * The above tests cover all nbdb_safe_for_uid code paths. The tests
+ * below do not need to cover all those code paths again, just enough to
+ * demonstrate that nbdb_safe_to_index_as_legacy_index_owner() will
+ * propagate nbdb_safe_for_uid() results properly.
+ */
+
+ /* nbdb_safe_to_index_as_legacy_index_owner tests. */
+ {.label = "safe_to_index_as_root:good_configuration",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = true,
+ },
+ /* nbdb_safe_to_index_as_legacy_index_owner tests. */
+ {.label = "safe_to_index_as_root:bad_pathname_prefix",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/posttfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "table /etc/postfix/access has an unexpected pathname",
+ },
+ {.label = "safe_to_index_as_root:bad_source_owner",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 1,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix/access' is owned or writable by other user",
+ },
+ {.label = "safe_to_index_as_root:source_group_write",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IWGRP,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix/access' is owned or writable by other user",
+ },
+ {.label = "safe_to_index_as_root:source_other_write",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IWOTH,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix/access' is owned or writable by other user",
+ },
+ {.label = "safe_to_index_as_root:bad_parent_owner",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 1,.st_mode = S_IRWXU,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix' is owned or writable by other user",
+ },
+ {.label = "safe_to_index_as_root:parent_group_write",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IWGRP,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix' is owned or writable by other user",
+ },
+ {.label = "safe_to_index_as_root:parent_other_write",
+ .action = test_nbdb_safe_to_index_as_legacy_index_owner,
+ .source_path = "/etc/postfix/access",
+ .source_st = {.st_uid = 0,.st_mode = S_IRWXU,},
+ .leg_idx_path = "/etc/postfix/access.db",
+ .leg_idx_st = {.st_uid = 0,},
+ .parent_dir = "/etc/postfix",
+ .parent_dir_st = {.st_uid = 0,.st_mode = S_IWOTH,},
+ .allow_root_pfxs = "/etc/postfix",
+ .allow_user_pfxs = "",
+ .want_bool = false,
+ .want_why = "'/etc/postfix' is owned or writable by other user",
+ },
+ /* TODO(wietse) tests for non-root user. */
+
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
--- /dev/null
+/*++
+/* NAME
+/* nbdb_sniffer 3
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_sniffer.h>
+/*
+/* bool nbdb_parse_as_postmap(VSTRING *line_buffer)
+/*
+/* bool nbdb_parse_as_postalias(VSTRING *line_buffer)
+/*
+/* const char *nbdb_get_index_cmd_as(
+/* const char *source_path,
+/* uid_t uid,
+/* gid_t gid,
+/* VSTRING *why)
+/* DESCRIPTION
+/* nbdb_parse_as_postmap() determines if a text line buffer contains
+/* valid input for the "postmap" command. nbdb_parse_as_postalias()
+/* does a similar thing for "postalias". Both functions modify
+/* their input.
+/*
+/* nbdb_get_index_cmd_as() examines the first handful lines of an
+/* Berkeley DB source file, and returns "postmap", "postalias",
+/* or null in case of a file open error.
+/* .PP
+/* Arguments:
+/* .IP line_buffer
+/* The input sample. This will be parsed destructively.
+/* .IP source_path
+/* Berkeley DB source file pathname.
+/* .IP uid, gid
+/* The privileges used for opening the Berkeley DB source file.
+/* .IP why
+/* Storage that is updated with an applicable error description.
+/* SEE ALSO
+/* nbdb_sniffer_test(1t), unit test
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <ctype.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <open_as.h>
+#include <readlline.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+#include <mail_params.h>
+#include <nbdb_util.h>
+#include <tok822.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_reindexd.h>
+#include <nbdb_sniffer.h>
+
+#define STR(x) vstring_str(x)
+
+/* nbdb_parse_as_postmap - sniff a source line and parse as key space value */
+
+bool nbdb_parse_as_postmap(VSTRING *line_buffer)
+{
+ int in_quotes = 0;
+ char *key;
+ char *value;
+
+ /*
+ * Split on the first whitespace character, then trim leading and
+ * trailing whitespace from key and value. Note that postalias does not
+ * require a space after the ':'.
+ */
+ for (value = STR(line_buffer); *value; value++) {
+ if (*value == '\\') {
+ if (*++value == 0)
+ break;
+ } else if (ISSPACE(*value)) {
+ if (!in_quotes)
+ break;
+ } else if (*value == '"') {
+ in_quotes = !in_quotes;
+ }
+ }
+
+ /*
+ * Keys should not contain an unbalanced double quote (input that is
+ * skipped by postmap and dict_thash).
+ */
+ if (in_quotes)
+ return (false);
+ if (*value)
+ *value++ = 0;
+ while (ISSPACE(*value))
+ value++;
+ trimblanks(value, 0)[0] = 0;
+ key = STR(line_buffer);
+
+ /*
+ * Input should be in "key whitespace value" form (other input is skipped
+ * by postmap and dict_thash). Empty keys are not allowed because some
+ * lookup tables did not support that. Additionally, the Postfix lookup
+ * table API does not allow empty values. Instead, programs are supposed
+ * to return a "not found" result.
+ */
+ if (*key == 0 || *value == 0)
+ return (false);
+
+ /*
+ * Postmap and dict_thash accept keys ending in ':' but also log
+ * warnings. Flag keys as 'postmap' format only if we have positive
+ * evidence of well-formed input.
+ */
+ if (key[strlen(key) - 1] == ':')
+ return (false);
+
+ return (true);
+}
+
+/* nbdb_parse_as_postalias - sniff a source line and parse as key ':' value */
+
+bool nbdb_parse_as_postalias(VSTRING *line_buffer)
+{
+ TOK822 *tok_list;
+ TOK822 *colon;
+ bool retval;
+
+ /*
+ * The postalias format requires a ':' between key and value. Do a quick
+ * check to eliminate obvious cases without actually parsing the input.
+ */
+ if (strchr(STR(line_buffer), ':') == 0)
+ return (false);
+
+ /*
+ * Tokenize the input, so that we do the right thing when a quoted
+ * localpart contains special characters such as ":" and so on.
+ */
+ if ((tok_list = tok822_scan(STR(line_buffer), (TOK822 **) 0)) == 0)
+ return (false);
+
+ /*
+ * Enforce the key:value format. Disallow missing keys, multi-address
+ * keys, or missing values. In order to specify an empty string or value,
+ * enclose it in double quotes. Note: postalias format does not require
+ * space after ':'.
+ */
+ retval = !((colon = tok822_find_type(tok_list, ':')) == 0
+ || colon->prev == 0 || colon->next == 0
+ || tok822_rfind_type(colon, ','));
+ tok822_free_tree(tok_list);
+ return (retval);
+}
+
+/* get_index_cmd_as - sniff the table format: postmap, or postalias, or error */
+
+const char *nbdb_get_index_cmd_as(const char *source_path, uid_t uid, gid_t gid,
+ VSTRING *why)
+{
+ VSTREAM *fp;
+
+ /*
+ * Some lookup tables may contain sensitive information (passwords, etc.)
+ * and should not be world-readable. If a process with index owner
+ * privilege cannot open this source file, then it also cannot index this
+ * table with the postmap or postalias command.
+ */
+ if ((fp = vstream_fopen_as(source_path, O_RDONLY, 0, uid, gid)) == 0) {
+ vstring_sprintf(why, "open lookup table source file %s as uid=%d "
+ "gid=%d: %m", source_path, (int) uid, (int) gid);
+ return (0);
+ } else {
+ VSTRING *line_buffer = vstring_alloc(100);
+ VSTRING *copy = vstring_alloc(100);
+ int postmap_score = 0;
+ int postalias_score = 0;
+
+ /*
+ * TODO(wietse) Eliminating 'format sniffing' code would require
+ * matching the source_path against the values of $alias_maps and
+ * $alias_database for every master.cf service. Such information is
+ * available from postconf(1).
+ */
+#define NO_LINENO ((int *) 0)
+#define NO_LAST_LINE ((int *) 0)
+
+ while (readllines(line_buffer, fp, NO_LINENO, NO_LAST_LINE)) {
+ vstring_strcpy(copy, STR(line_buffer));
+ if (nbdb_parse_as_postmap(copy))
+ postmap_score += 1;
+ if (nbdb_parse_as_postalias(line_buffer))
+ postalias_score += 1;
+ if (postmap_score + postalias_score == 10)
+ break;
+ }
+ vstream_fclose(fp);
+ vstring_free(line_buffer);
+ vstring_free(copy);
+ if (postalias_score > postmap_score)
+ return "postalias";
+ else
+ return ("postmap");
+ }
+}
--- /dev/null
+#ifndef _NBDB_SNIFFER_H_INCLUDED_
+#define _NBDB_SNIFFER_H_INCLUDED_
+
+/*++
+/* NAME
+/* nbdb_sniffer.h 3h
+/* SUMMARY
+/* Non-Berkeley-DB migration service
+/* SYNOPSIS
+/* #include <nbdb_sniffer.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <unistd.h>
+
+ /*
+ * Utility library.
+ */
+#include <vstring.h>
+
+ /*
+ * Internal API.
+ */
+extern bool nbdb_parse_as_postmap(VSTRING *);
+extern bool nbdb_parse_as_postalias(VSTRING *);
+const char *nbdb_get_index_cmd_as(const char *, uid_t, gid_t, VSTRING *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* nbdb_sniffer_test 1t
+/* SUMMARY
+/* nbdb_sniffer unit test
+/* SYNOPSIS
+/* ./nbdb_sniffer_test
+/* DESCRIPTION
+/* nbdb_sniffer_test runs and logs each configured test, reports if
+/* a test is a PASS or FAIL, and returns an exit status of zero if
+/* all tests are a PASS.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <msg_vstream.h>
+#include <open_as.h>
+#include <stringops.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Global library.
+ */
+
+ /*
+ * Testing library.
+ */
+#include <mock_open_as.h>
+
+ /*
+ * Application-specific.
+ */
+#include <nbdb_sniffer.h>
+
+#define STR(x) vstring_str(x)
+#define LEN(x) VSTRING_LEN(x)
+
+ /*
+ * Test structure. Some tests may bring their own.
+ */
+typedef struct TEST_CASE {
+ const char *label;
+ int (*action) (const struct TEST_CASE *);
+
+ /*
+ * nbdb_parse_as_xxx() inputs and expectations.
+ */
+ struct {
+ const char *in_line;
+ bool out_want_postmap;
+ bool out_want_postalias;
+ } parse_as;
+
+ /*
+ * nbdb_get_index_cmd_as() mock dependencies.
+ */
+ MOCK_OPEN_AS_REQ mock_open;
+
+ /*
+ * nbdb_get_index_cmd_as() inputs and expectations.
+ */
+ struct {
+ const char *in_path;
+ uid_t in_uid;
+ gid_t in_gid;
+ const char *want_cmd;
+ const char *want_why;
+ int want_errno;
+ } index_cmd;
+} TEST_CASE;
+
+#define PASS (0)
+#define FAIL (1)
+
+/* test_parse_line - single-line vote */
+
+static int test_parse_line(const TEST_CASE *tp)
+{
+ bool got_postmap, got_postalias;
+ VSTRING *buffer;
+
+ buffer = vstring_alloc(strlen(tp->parse_as.in_line));
+ vstring_strcpy(buffer, tp->parse_as.in_line);
+ got_postmap = nbdb_parse_as_postmap(buffer);
+
+ vstring_strcpy(buffer, tp->parse_as.in_line);
+ got_postalias = nbdb_parse_as_postalias(buffer);
+ vstring_free(buffer);
+
+#define bool_to_text(b) ((b) ? "true" : "false")
+
+ /* Verify the results. */
+ if (got_postmap != tp->parse_as.out_want_postmap) {
+ msg_warn("got postmap: `%s', want `%s''",
+ bool_to_text(got_postmap),
+ bool_to_text(tp->parse_as.out_want_postmap));
+ return (FAIL);
+ }
+ if (got_postalias != tp->parse_as.out_want_postalias) {
+ msg_warn("got postalias: `%s', want `%s''",
+ bool_to_text(got_postalias),
+ bool_to_text(tp->parse_as.out_want_postalias));
+ return (FAIL);
+ }
+ return (PASS);
+}
+
+/* test_index_command - multi-line vote */
+
+static int test_index_command(const TEST_CASE *tp)
+{
+ static VSTRING *msg_buf;
+ static VSTRING *got_why;
+ const char *got_cmd;
+
+ if (msg_buf == 0) {
+ msg_buf = vstring_alloc(100);
+ got_why = vstring_alloc(100);
+ }
+ /* Run the test with fake file data. */
+ VSTRING_RESET(got_why);
+ setup_mock_vstream_fopen_as(&tp->mock_open);
+ got_cmd = nbdb_get_index_cmd_as(tp->index_cmd.in_path,
+ tp->index_cmd.in_uid,
+ tp->index_cmd.in_gid,
+ got_why);
+
+#define CMD_OR_NULL(s) ((s) ? (s) : "(null)")
+
+ /* Verify the results. */
+ if (!got_cmd != !tp->index_cmd.want_cmd) {
+ msg_warn("got command: `%s', want `%s''",
+ CMD_OR_NULL(got_cmd), CMD_OR_NULL(tp->index_cmd.want_cmd));
+ return (FAIL);
+ }
+ if (tp->index_cmd.want_cmd == 0) {
+ if (LEN(got_why) == 0
+ || strstr(STR(got_why), tp->index_cmd.want_why) == 0) {
+ msg_warn("got warning: '%s', want: '%s'",
+ STR(got_why), tp->index_cmd.want_why);
+ return (FAIL);
+ }
+ if (tp->index_cmd.want_errno != errno) {
+ msg_warn("got errno: '%s', want: '%s'",
+ strerror(errno), strerror(tp->index_cmd.want_errno));
+ return (FAIL);
+ }
+ } else {
+ if (tp->index_cmd.want_errno != 0)
+ msg_panic("want non-null result AND errno=%d",
+ tp->index_cmd.want_errno);
+ if (strcmp(got_cmd, tp->index_cmd.want_cmd) != 0) {
+ msg_warn("got command ``%s'', want ``%s''",
+ got_cmd, tp->index_cmd.want_cmd);
+ return (FAIL);
+ }
+ }
+ return (PASS);
+}
+
+ /*
+ * The list of test cases.
+ */
+static const TEST_CASE test_cases[] = {
+
+ /*
+ * Line-level tests.
+ */
+ {.label = "key_space_value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "foo bar",
+ .out_want_postmap = true,
+ .out_want_postalias = false,
+ },
+ },
+ {.label = "colon_in_quoted_key_space_text",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "\"foobar:\" baz",
+ .out_want_postmap = true,
+ .out_want_postalias = false,
+ },
+ },
+ {.label = "quoted_key_colon_value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "\"foo bar\":baz",
+ .out_want_postmap = false,
+ .out_want_postalias = true,
+ },
+ },
+ {.label = "key_space_colon_text",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "foo :bar",
+ .out_want_postmap = true,
+ .out_want_postalias = true,
+ },
+ },
+ {.label = "key_colon_value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "foo:bar",
+ .out_want_postmap = false,
+ .out_want_postalias = true,
+ },
+ },
+ {.label = "colon_value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = ":bar",
+ .out_want_postmap = false,
+ .out_want_postalias = false,
+ },
+ },
+ {.label = "key_without value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "bar",
+ .out_want_postmap = false,
+ .out_want_postalias = false,
+ },
+ },
+ {.label = "key_colon_without value",
+ .action = test_parse_line,
+ .parse_as = {
+ .in_line = "bar:",
+ .out_want_postmap = false,
+ .out_want_postalias = false,
+ },
+ },
+
+ /*
+ * File-level tests (multiple lines with majority voting).
+ */
+ {.label = "file_open_error_enoent",
+ .action = test_index_command,
+ .index_cmd = {
+ .in_path = "path/to/file",
+ .want_why = "open lookup table source file",
+ .want_errno = ENOENT,
+ },
+ .mock_open = {
+ .want_path = "path/to/file",
+ .out_data = 0,
+ .out_errno = ENOENT,
+ },
+ },
+ {.label = "file_open_error_eacces",
+ .action = test_index_command,
+ .index_cmd = {
+ .in_path = "path/to/file",
+ .in_uid = 1,
+ .want_why = "open lookup table source file",
+ .want_errno = EACCES,
+ },
+ .mock_open = {
+ .want_path = "path/to/file",
+ .want_uid = 1,
+ .out_errno = EACCES,
+ },
+ },
+ {.label = "mostly_postmap",
+ .action = test_index_command,
+ .index_cmd = {
+ .in_path = "path/to/file",
+ .want_cmd = "postmap",
+ },
+ .mock_open = {
+ .want_path = "path/to/file",
+ .out_data = "foo:bar\nfoo bar\nfoo :bar",
+ },
+ },
+ {.label = "mostly_postalias",
+ .action = test_index_command,
+ .index_cmd = {
+ .in_path = "path/to/file",
+ .want_cmd = "postalias",
+ },
+ .mock_open = {
+ .want_path = "path/to/file",
+ .out_data = "foo:bar\n\"foo bar\":baz\nfoo :bar",
+ },
+ },
+
+ {0},
+};
+
+int main(int argc, char **argv)
+{
+ const TEST_CASE *tp;
+ int pass = 0;
+ int fail = 0;
+
+ msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);
+
+ for (tp = test_cases; tp->label != 0; tp++) {
+ int test_failed;
+
+ msg_info("RUN %s", tp->label);
+ test_failed = tp->action(tp);
+ if (test_failed) {
+ msg_info("FAIL %s", tp->label);
+ fail++;
+ } else {
+ msg_info("PASS %s", tp->label);
+ pass++;
+ }
+ }
+ msg_info("PASS=%d FAIL=%d", pass, fail);
+ exit(fail != 0);
+}
/* The database type. To find out what types are supported, use
/* the "\fBpostconf -m\fR" command.
/*
+/* When no \fIfile_type\fR is specified, the software uses the database
+/* type specified via the \fBdefault_database_type\fR configuration
+/* parameter.
+/* The default value for this parameter depends on the host environment.
+/*
/* The \fBpostalias\fR(1) command can query any supported file type,
/* but it can create only the following file types:
/* .RS
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available on systems with support for \fBsdbm\fR databases.
-/* .PP
-/* When no \fIfile_type\fR is specified, the software uses the database
-/* type specified via the \fBdefault_database_type\fR configuration
-/* parameter.
-/* The default value for this parameter depends on the host environment.
/* .RE
/* .IP \fIfile_name\fR
/* The name of the alias database source file when creating a database.
/* with the command specified with $maillog_file_compressor.
/* This will not rotate /dev/* files.
/* .sp
-/* This feature is available in Postfix 3.4 and later.
+/* .IP "\fBnon-bdb\fR \fIsubcommand\fR"
+/* Migrate a Postfix configuration that uses Berkeley DB hash:
+/* or btree: tables, to a configuration that uses lmdb: or a
+/* combination of cdb: and lmdb:. This is needed because some
+/* (Linux) distributions have removed Berkeley DB support.
+/* See postfix-nbdb(1) for documentation.
+/* .sp
+/* This feature is available in Postfix 3.11 and later.
/* .IP "\fBtls\fR \fIsubcommand\fR"
/* Enable opportunistic TLS in the Postfix SMTP client or
/* server, and manage Postfix SMTP server TLS private keys and
/* postconf(1), Postfix configuration utility
/* postdrop(1), Postfix mail posting utility
/* postfix(1), Postfix control program
+/* postfix-non-bdb(1), Postfix Non-Berkeley-DB migration
/* postfix-tls(1), Postfix TLS management
/* postkick(1), trigger Postfix daemon
/* postlock(1), Postfix-compatible locking
/* The database type. To find out what types are supported, use
/* the "\fBpostconf -m\fR" command.
/*
+/* When no \fIfile_type\fR is specified, the software uses the database
+/* type specified via the \fBdefault_database_type\fR configuration
+/* parameter.
+/* The default value for this parameter depends on the host environment.
+/*
/* The \fBpostmap\fR(1) command can query any supported file type,
/* but it can create only the following file types:
/* .RS
/* The output consists of two files, named \fIfile_name\fB.pag\fR and
/* \fIfile_name\fB.dir\fR.
/* This is available on systems with support for \fBsdbm\fR databases.
-/* .PP
-/* When no \fIfile_type\fR is specified, the software uses the database
-/* type specified via the \fBdefault_database_type\fR configuration
-/* parameter.
/* .RE
/* .IP \fIfile_name\fR
/* The name of the lookup table source file when rebuilding a database.
@$(EXPORT) make -f Makefile.in Makefile 1>&2
# do not edit below this line - it is generated by 'make depend'
+fake_strcmp.o: ../../include/mail_params.h
+fake_strcmp.o: ../../include/msg.h
+fake_strcmp.o: ../../include/sys_defs.h
+fake_strcmp.o: fake_strcmp.c
postmulti.o: ../../include/argv.h
postmulti.o: ../../include/check_arg.h
postmulti.o: ../../include/clean_env.h
for (i = 0; i < sk_X509_num(sk); i++) {
X509 *cert = sk_X509_value(sk, i);
char buf[CCERT_BUFSIZ];
- X509_NAME *xn;
+ const X509_NAME *xn;
char *digest;
if ((xn = X509_get_subject_name(cert)) != 0) {
STR(iter->host));
return (0);
}
- break;
+ break;
case SMTP_REQTLS_POLICY_ACT_OPP_TLS:
if (tls->level == TLS_LEV_NONE) {
if (state->tls_stats)
SHELL = /bin/sh
-SRCS = nosleep.c dict_test_helper.c
-LIB_OBJ = dict_test_helper.o
+SRCS = nosleep.c dict_test_helper.c mock_open_as.c mock_spawn_command.c \
+ mock_stat.c msg_capture.c mock_dict.c
+LIB_OBJ = dict_test_helper.o mock_open_as.o mock_spawn_command.o \
+ mock_stat.o msg_capture.o mock_dict.o
MOCK_OBJ=
TEST_OBJ=
-HDRS = dict_test_helper.h
+HDRS = dict_test_helper.h mock_open_as.h mock_spawn_command.h \
+ mock_stat.h msg_capture.h mock_dict.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
CFLAGS = $(DEBUG) $(OPT) $(DEFS)
dict_test_helper.o: ../../include/vstring.h
dict_test_helper.o: dict_test_helper.c
dict_test_helper.o: dict_test_helper.h
+mock_dict.o: ../../include/argv.h
+mock_dict.o: ../../include/check_arg.h
+mock_dict.o: ../../include/dict.h
+mock_dict.o: ../../include/dict_cdb.h
+mock_dict.o: ../../include/dict_inline.h
+mock_dict.o: ../../include/dict_lmdb.h
+mock_dict.o: ../../include/mkmap.h
+mock_dict.o: ../../include/myflock.h
+mock_dict.o: ../../include/mymalloc.h
+mock_dict.o: ../../include/sys_defs.h
+mock_dict.o: ../../include/vbuf.h
+mock_dict.o: ../../include/vstream.h
+mock_dict.o: ../../include/vstring.h
+mock_dict.o: mock_dict.c
+mock_dict.o: mock_dict.h
+mock_open_as.o: ../../include/check_arg.h
+mock_open_as.o: ../../include/msg.h
+mock_open_as.o: ../../include/open_as.h
+mock_open_as.o: ../../include/sys_defs.h
+mock_open_as.o: ../../include/vbuf.h
+mock_open_as.o: ../../include/vstream.h
+mock_open_as.o: ../../include/vstring.h
+mock_open_as.o: mock_open_as.c
+mock_open_as.o: mock_open_as.h
+mock_spawn_command.o: ../../include/check_arg.h
+mock_spawn_command.o: ../../include/msg.h
+mock_spawn_command.o: ../../include/spawn_command.h
+mock_spawn_command.o: ../../include/stringops.h
+mock_spawn_command.o: ../../include/sys_defs.h
+mock_spawn_command.o: ../../include/vbuf.h
+mock_spawn_command.o: ../../include/vstring.h
+mock_spawn_command.o: mock_spawn_command.c
+mock_spawn_command.o: mock_spawn_command.h
+mock_stat.o: ../../include/htable.h
+mock_stat.o: ../../include/msg.h
+mock_stat.o: ../../include/sys_defs.h
+mock_stat.o: ../../include/wrap_stat.h
+mock_stat.o: mock_stat.c
+mock_stat.o: mock_stat.h
+msg_capture.o: ../../include/check_arg.h
+msg_capture.o: ../../include/msg.h
+msg_capture.o: ../../include/mymalloc.h
+msg_capture.o: ../../include/sys_defs.h
+msg_capture.o: ../../include/vbuf.h
+msg_capture.o: ../../include/vstream.h
+msg_capture.o: ../../include/vstring.h
+msg_capture.o: msg_capture.c
+msg_capture.o: msg_capture.h
nosleep.o: nosleep.c
--- /dev/null
+/*++
+/* NAME
+/* mock_dict 3
+/* SUMMARY
+/* mock tables
+/* SYNOPSIS
+/* $include <mock_dict.h>
+/*
+/* setup_mock_cdb(const char *name_payload)
+/*
+/* setup_mock_lmdb(const char *name_payload)
+/* DESCRIPTION
+/* setup_mock_cdb (or setup_mock_lmdb) instantiates a mock cdb
+/* (or lmdb) table with a name_payload that uses inline: syntax.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+#include <dict_cdb.h>
+#include <dict_inline.h>
+#include <dict_lmdb.h>
+#include <mkmap.h>
+#include <mymalloc.h>
+
+ /*
+ * Global library.
+ */
+
+ /*
+ * Testing library.
+ */
+#include <mock_dict.h>
+
+static char *mock_cdb_name_payload;
+
+static DICT *mock_dict_cdb_open(const char *dict_name, int open_flags,
+ int dict_flags)
+{
+ return (dict_open3(DICT_TYPE_INLINE, mock_cdb_name_payload,
+ open_flags, dict_flags));
+}
+
+static MKMAP *mock_mkmap_cdb_open(const char *path)
+{
+ MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
+
+ mkmap->open = mock_dict_cdb_open;
+ mkmap->after_open = 0;
+ mkmap->after_close = 0;
+ return (mkmap);
+}
+
+static const DICT_OPEN_INFO mock_cdb_info = {
+ "cdb", mock_dict_cdb_open, mock_mkmap_cdb_open,
+};
+
+void setup_mock_cdb(const char *name_payload)
+{
+ if (mock_cdb_name_payload != 0)
+ myfree(mock_cdb_name_payload);
+
+ mock_cdb_name_payload = mystrdup(name_payload);
+
+ if (dict_open_lookup(mock_cdb_info.type))
+ dict_open_unregister(mock_cdb_info.type);
+ dict_open_register(&mock_cdb_info);
+}
+
+static char *mock_lmdb_name_payload;
+
+static DICT *mock_dict_lmdb_open(const char *dict_name, int open_flags,
+ int dict_flags)
+{
+ return (dict_open3(DICT_TYPE_INLINE, mock_lmdb_name_payload,
+ open_flags, dict_flags));
+}
+
+static MKMAP *mock_mkmap_lmdb_open(const char *path)
+{
+ MKMAP *mkmap = (MKMAP *) mymalloc(sizeof(*mkmap));
+
+ mkmap->open = mock_dict_lmdb_open;
+ mkmap->after_open = 0;
+ mkmap->after_close = 0;
+ return (mkmap);
+}
+
+static const DICT_OPEN_INFO mock_lmdb_info = {
+ "lmdb", mock_dict_lmdb_open, mock_mkmap_lmdb_open,
+};
+
+void setup_mock_lmdb(const char *name_payload)
+{
+ if (mock_lmdb_name_payload != 0)
+ myfree(mock_lmdb_name_payload);
+
+ mock_lmdb_name_payload = mystrdup(name_payload);
+
+ if (dict_open_lookup(mock_lmdb_info.type))
+ dict_open_unregister(mock_lmdb_info.type);
+ dict_open_register(&mock_lmdb_info);
+}
--- /dev/null
+#ifndef _MOCK_DICT_H_INCLUDED_
+#define _MOCK_DICT_H_INCLUDED_
+
+/*++
+/* NAME
+/* mock_dict 3h
+/* SUMMARY
+/* mock tables
+/* SYNOPSIS
+/* #include <mock_dict.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+extern void setup_mock_cdb(const char *);
+extern void setup_mock_lmdb(const char *);
+
+/* LICENSE
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* mock_open_as 3
+/* SUMMARY
+/* test scaffolding
+/* SYNOPSIS
+/* #include <mock_open_as.h>
+/*
+/* typedef struct MOCK_OPEN_AS_REQ {
+/* in +4
+/* const char *want_path,
+/* uid_t want_uid,
+/* gid_t want_gid,
+/* const char *out_data,
+/* int out_errno)
+/* .in -4
+/* } MOCK_OPEN_AS_REQ;
+/*
+/* void setup_mock_vstream_fopen_as(const MOCK_OPEN_AS_REQ *request)
+/* DESCRIPTION
+/* This module provides a mock vstream_fopen_as() implementation
+/* that returns static results for expected calls.
+/*
+/* setup_mock_vstream_fopen_as() makes a shallow copy of its input:
+/* .IP want_path, want_uid, want_gid
+/* The expected vstream_fopen_as() arguments. If the mock
+/* vstream_fopen_as() is called with an unexpected argument, the
+/* mock terminates the test with a fatal error.
+/* .IP out_data
+/* The data that can be read from the stream returned by
+/* vstream_fopen_as().
+/* .IP out_errno
+/* If not NULL, vstream_fopen_as() will return NULL and set errno
+/* to the value of this argument.
+/* SEE ALSO
+/* open_as(3), the real thing
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <open_as.h>
+#include <vstring.h>
+
+ /*
+ * Application-specific.
+ */
+#include <mock_open_as.h>
+
+static MOCK_OPEN_AS_REQ mock_req;
+
+/* setup_mock_vstream_fopen_as - set up expectation */
+
+void setup_mock_vstream_fopen_as(const MOCK_OPEN_AS_REQ *request)
+{
+ mock_req = *request;
+}
+
+/* vstream_fopen_as - fake implementation */
+
+VSTREAM *vstream_fopen_as(const char *path, int flags, mode_t mode,
+ uid_t uid, gid_t gid)
+{
+ VSTREAM *stream;
+ VSTRING *data_buffer;
+
+ /* TODO(wietse) replace with match_str() and match_decimal(). */
+ if (strcmp(path, mock_req.want_path) != 0)
+ msg_fatal("vstream_fopen: got path '%s', want '%s'",
+ path, mock_req.want_path);
+ if (uid != mock_req.want_uid)
+ msg_fatal("vstream_fopen: got uid '%d', want '%d'",
+ (int) uid, (int) mock_req.want_uid);
+ if (gid != mock_req.want_gid)
+ msg_fatal("vstream_fopen: got gid '%d', want '%d'",
+ (int) gid, (int) mock_req.want_gid);
+
+ if (mock_req.out_errno != 0) {
+ errno = mock_req.out_errno;
+ return (0);
+ }
+ data_buffer = vstring_alloc(strlen(mock_req.out_data));
+ vstring_strcpy(data_buffer, mock_req.out_data);
+ stream = vstream_memopen(data_buffer, flags);
+ vstream_control(stream, CA_VSTREAM_CTL_OWN_VSTRING, CA_VSTREAM_CTL_END);
+ return (stream);
+}
--- /dev/null
+#ifndef _MOCK_OPEN_AS_H_INCLUDED_
+#define _MOCK_OPEN_AS_H_INCLUDED_
+
+/*++
+/* NAME
+/* mock_open_as 3h
+/* SUMMARY
+/* fake open_as
+/* SYNOPSIS
+/* #include <mock_open_as.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <unistd.h>
+
+ /*
+ * Utility library.
+ */
+#include <open_as.h>
+#include <vstream.h>
+
+ /*
+ * External interface.
+ */
+typedef struct MOCK_OPEN_AS_REQ {
+ const char *want_path;
+ uid_t want_uid;
+ gid_t want_gid;
+ const char *out_data;
+ int out_errno;
+} MOCK_OPEN_AS_REQ;
+
+extern void setup_mock_vstream_fopen_as(const MOCK_OPEN_AS_REQ *);
+
+/* LICENSE
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* mock_spawn_command 3t
+/* SUMMARY
+/* spawn_command() mocker
+/* SYNOPSIS
+/* #include <mock_spawn_command.h>
+/*
+/* typedef struct MOCK_SPAWN_CMD_REQ {
+/* struct spawn_args *want_args;
+/* int out_status;
+/* const char *out_text;
+P/*
+/* void setup_mock_spawn_command(const MOCK_SPAWN_CMD_REQ *request)
+/* DESCRIPTION
+/* setup_mock_spawn_command() instantiates a spawn_command() mocker,
+/* that given the expected inputs, will produce the specified
+/* outputs, without any additional dependencies or side effects.
+/*
+/* This implementation supports only one instance of expectations
+/* and outputs, and makes a shallow copy of its inputs:
+/* .IP want_args
+/* The inputs that the mock spawn_command() instance must
+/* receive. Otherwise, The mocker will terminate the test.
+/* .IP out_status
+/* The spawn_command() result value.
+/* .IP out_text
+/* Pointer to null-terminated text that will be written to the
+/* simulated command's standard error stream.
+/* SEE ALSO
+/* spawn_command(3), command spawner
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <stringops.h>
+
+ /*
+ * Testing library.
+ */
+#include <mock_spawn_command.h>
+
+ /*
+ * Input expectations and outputs. For now we support only one instance.
+ */
+static MOCK_SPAWN_CMD_REQ mock_req;
+
+void setup_mock_spawn_command(const MOCK_SPAWN_CMD_REQ *request)
+{
+
+ /*
+ * Validate the output requirements.
+ */
+ if (request->out_status == 0) {
+ if (request->out_text != 0)
+ msg_fatal("setup_spawn_command: out_status is zero, but out_text "
+ "is not null");
+ } else {
+ if (request->out_text == 0 || *request->out_text == 0) {
+ msg_fatal("setup_spawn_command: out_status is not zero, but "
+ "out_text is null or empty");
+ }
+ }
+
+ /*
+ * Make a shallow copy of the arguments.
+ */
+ mock_req = *request;
+}
+
+ /*
+ * Matchers. TODO(wietse) factor out.
+ */
+typedef void PRINTFLIKE(1, 2) (*MATCH_WARN) (const char *,...);
+
+#define STR_OR_NULL(s) ((s) ? (s) : "(null)")
+#define NOT_NULL_OR_NULL(arg) ((arg) ? "(not null)" : "(null)")
+
+/* match_decimal - match integers, report difference in decimal */
+
+static bool match_decimal(const char *what, MATCH_WARN warn, int want, int got)
+{
+ if (want != got) {
+ if (warn)
+ warn("%s: want %d, got %d", what, want, got);
+ return (false);
+ }
+ return (true);
+}
+
+/* match_str - match null-terminated strings */
+
+static int match_str(const char *what, MATCH_WARN warn,
+ const char *want, const char *got)
+{
+ if (want == 0 && got == 0)
+ return (true);
+ if (!want != !got) {
+ if (warn)
+ warn("%s: want '%s', got '%s'", what, STR_OR_NULL(want),
+ STR_OR_NULL(got));
+ return (false);
+ }
+ if (strcmp(got, want) != 0) {
+ if (warn)
+ warn("%s: want %s, got %s", what, want, got);
+ return (false);
+ }
+ return (true);
+}
+
+/* match_cpp - match (char **) instances */
+
+static bool match_cpp(const char *what, MATCH_WARN warn,
+ char **want, char **got)
+{
+ char **wpp, **gpp;
+
+ if (want == 0 && got == 0)
+ return (true);
+ if (!want != !got) {
+ if (warn)
+ warn("%s: want %s, got %s", what, NOT_NULL_OR_NULL(want),
+ NOT_NULL_OR_NULL(got));
+ return (false);
+ }
+ for (wpp = want, gpp = got; /* void */ ; wpp++, gpp++) {
+ if (*wpp == 0 && *gpp == 0) {
+ return (true);
+ } else if (*wpp == 0 || *gpp == 0) {
+ if (warn)
+ warn("%s: want '%s', got '%s'",
+ what, STR_OR_NULL(*wpp), STR_OR_NULL(*gpp));
+ return (false);
+ } else if (!match_str(what, warn, *gpp, *wpp)) {
+ return (false);
+ }
+ }
+ return (true);
+}
+
+/* match_spawn_args - compare expected against actual */
+
+static bool match_spawn_args(MATCH_WARN warn, struct spawn_args *want,
+ struct spawn_args *got)
+{
+ return (match_cpp("argv", warn, want->argv, got->argv)
+ && match_str("command", warn,
+ want->command, got->command)
+ && match_decimal("uid", warn, want->uid, got->uid)
+ && match_cpp("env", warn, want->env, got->env)
+ && match_cpp("export", warn,
+ want->export, got->export)
+ && match_str("shell", warn, want->shell, got->shell)
+ && match_decimal("time_limit", warn,
+ want->time_limit, got->time_limit));
+}
+
+/* spawn_command - mock */
+
+int spawn_command(int key,...)
+{
+ struct spawn_args got_args;
+ va_list ap;
+
+ va_start(ap, key);
+ get_spawn_args(&got_args, key, ap);
+ va_end(ap);
+
+ /*
+ * Match spawn_command() arguments against expectations or terminate.
+ */
+ if (!match_spawn_args(msg_warn, &mock_req.want_args, &got_args))
+ msg_fatal("spawn_command called with unexpected argument");
+
+ /* Now output some info as if the command was executed. */
+ if (mock_req.out_status != 0)
+ write(got_args.stderr_fd, mock_req.out_text, strlen(mock_req.out_text));
+ return (mock_req.out_status);
+}
--- /dev/null
+#ifndef _MOCK_SPAWN_COMMAND_H_INCLUDED_
+#define _MOCK_SPAWN_COMMAND_H_INCLUDED_
+
+/*++
+/* NAME
+/* mock_spawn_command.h 3h
+/* SUMMARY
+/* spawn_command() mocker
+/* SYNOPSIS
+/* #include <mock_spawn_command.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <spawn_command.h>
+
+ /*
+ * External API.
+ */
+typedef struct MOCK_SPAWN_CMD_REQ {
+ struct spawn_args want_args;
+ int out_status;
+ const char *out_text;
+} MOCK_SPAWN_CMD_REQ;
+
+extern void setup_mock_spawn_command(const MOCK_SPAWN_CMD_REQ *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* mock_stat 3
+/* SUMMARY
+/* test scaffolding
+/* SYNOPSIS
+/* #include <mock_stat.h>
+/*
+/* typedef struct MOCK_STAT_REQ {
+/* .in +4
+/* const char *want_path;
+/* int out_errno;
+/* struct stat st;
+/* .in -4
+/* } MOCK_STAT_REQ;
+/*
+/* void setup_mock_stat(const MOCK_STAT_REQ *request)
+/*
+/* void teardown_mock_stat(void)
+/* DESCRIPTION
+/* This module provides a mock stat() implementation that returns
+/* static results for expected calls.
+/*
+/* setup_mock_stat() adds a mapping from pathname to struct
+/* stat_info pointer. It is an error to enter multiple mappings
+/* for one pathname. If makes a shallow copy ig its input:
+/* .IP want_path
+/* The lookup key for file status information.
+/* .IP out_errno
+/* If non-zero, mock stat() will return -1 and set the global
+/* errno variable.
+/* .IP st
+/* File status information, ignored when out_errno is non-zero.
+/* .PP
+/* teardown_mock_stat() destroys all mappings entered with
+/* setup_mock_stat().
+/*
+/* The mock stat() function looks up the MOCK_STAT_REQ information
+/* for a pathname and terminates the test if the pathname is not
+/* expected. If the mapping contains a non-zero out_errno value,
+/* it simulates an error, sets the global errno value, and returns
+/* -1. Otherwise it copies the stat_info.st value to the storage
+/* provided with the st argument.
+/* SEE ALSO
+/* stat(2), the real thing
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+ /*
+ * Utility library.
+ */
+#include <htable.h>
+#include <msg.h>
+#include <wrap_stat.h>
+
+ /*
+ * Test library.
+ */
+#include <mock_stat.h>
+
+ /*
+ * Application-specific.
+ */
+static HTABLE *mock_stat_table;
+
+/* setup_mock_stat - add path-to-status mapping */
+
+void setup_mock_stat(const MOCK_STAT_REQ *request)
+{
+ if (mock_stat_table == 0)
+ mock_stat_table = htable_create(10);
+ htable_enter(mock_stat_table, request->want_path, (void *) request);
+}
+
+/* teardown_mock_stat - destroy all path-to-status mappings */
+
+void teardown_mock_stat(void)
+{
+ if (mock_stat_table) {
+ htable_free(mock_stat_table, (void (*) (void *)) 0);
+ mock_stat_table = 0;
+ }
+}
+
+/* stat - mock stat() implementation */
+
+int stat(const char *path, struct stat *st) {
+ MOCK_STAT_REQ *mock_info;
+
+ if ((mock_info = (MOCK_STAT_REQ *) htable_find(mock_stat_table, path)) == 0)
+ msg_fatal("mock stat: unexpected pathname: '%s'", path);
+
+ if (mock_info->out_errno != 0) {
+ errno = mock_info->out_errno;
+ return (-1);
+ } else {
+ *st = mock_info->out_st;
+ return (0);
+ }
+}
--- /dev/null
+#ifndef _MOCK_STAT_H_INCLUDED_
+#define _MOCK_STAT_H_INCLUDED_
+
+/*++
+/* NAME
+/* mock_stat 3h
+/* SUMMARY
+/* mock stat
+/* SYNOPSIS
+/* #include <mock_stat.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <sys/stat.h>
+#include <unistd.h>
+
+ /*
+ * External interface.
+ */
+typedef struct MOCK_STAT_REQ {
+ const char *want_path;
+ struct stat out_st;
+ int out_errno;
+} MOCK_STAT_REQ;
+
+extern void setup_mock_stat(const MOCK_STAT_REQ *);
+extern void teardown_mock_stat(void);
+
+/* LICENSE
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
--- /dev/null
+/*++
+/* NAME
+/* msg_capture 3
+/* SUMMARY
+/* message capture support
+/* SYNOPSIS
+/* #include <msg_capture.h>
+/*
+/* typedef struct MSG_CAPTURE MSG_CAPTURE;
+/*
+/* MSG_CAPTURE *msg_capt_create(ssize_t init_size)
+/*
+/* void msg_capt_start(MSG_CAPTURE *mp)
+/*
+/* void msg_capt_stop(MSG_CAPTURE *mp)
+/*
+/* const char *msg_capt_expose(MSG_CAPTURE *mp)
+/*
+/* void msg_capt_free(MSG_CAPTURE *mp)
+/* DESCRIPTION
+/* This module captures msg(3) logging by temporarily redirecting
+/* VSTREAM_ER to a buffer.
+/*
+/* msg_capt_create() creates a MSG_CAPTURE instance.
+/*
+/* msg_capt_start() starts "recording" msg(3) output. It is an
+/* error to call this function while a recording is in progress.
+/*
+/* msg_capt_stop() stops a "recording". It is an error to call this
+/* function while no recording is in progress.
+/*
+/* msg_capt_expose() exposes the contents of a recording as a
+/* null-terminated string. It is an error to call this function
+/* while a recording is in progress.
+/*
+/* msg_capt_free() destroys a MSG_CAPTURE instance.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstream.h>
+#include <vstring.h>
+
+ /*
+ * Testing library.
+ */
+#include <msg_capture.h>
+
+ /*
+ * TODO(wietse) make this a proper VSTREAM interface or test helper API.
+ */
+
+/* vstream_swap - capture output for testing */
+
+static void vstream_swap(VSTREAM *one, VSTREAM *two)
+{
+ VSTREAM save;
+
+ save = *one;
+ *one = *two;
+ *two = save;
+}
+
+struct MSG_CAPTURE {
+ VSTRING *buffer;
+ VSTREAM *stream;
+};
+
+MSG_CAPTURE *msg_capt_create(ssize_t init_size)
+{
+ MSG_CAPTURE *mp;
+
+ mp = (MSG_CAPTURE *) mymalloc(sizeof(*mp));
+ mp->buffer = vstring_alloc(init_size);
+ mp->stream = 0;
+ return (mp);
+}
+
+void msg_capt_start(MSG_CAPTURE *mp)
+{
+ if (mp->stream != 0)
+ msg_panic("%s: capture is in progress", __func__);
+ VSTRING_RESET(mp->buffer);
+ VSTRING_TERMINATE(mp->buffer);
+ if ((mp->stream = vstream_memopen(mp->buffer, O_WRONLY)) == 0)
+ msg_fatal("open memory stream: %m");
+ vstream_swap(VSTREAM_ERR, mp->stream);
+}
+
+void msg_capt_stop(MSG_CAPTURE *mp)
+{
+ if (mp->stream == 0)
+ msg_panic("%s: no capture in progress", __func__);
+ vstream_swap(mp->stream, VSTREAM_ERR);
+ if (vstream_fclose(mp->stream))
+ msg_fatal("close memory stream: %m");
+ mp->stream = 0;
+ VSTRING_TERMINATE(mp->buffer);
+}
+
+const char *msg_capt_expose(MSG_CAPTURE *mp)
+{
+ if (mp->stream != 0)
+ msg_panic("%s: capture is in progress", __func__);
+ return (vstring_str(mp->buffer));
+}
+
+void msg_capt_free(MSG_CAPTURE *mp)
+{
+ if (mp->stream != 0)
+ msg_capt_stop(mp);
+ vstring_free(mp->buffer);
+ myfree((void *) mp);
+}
--- /dev/null
+#ifndef _MSB_CAPTURE_H_INCLUDED_
+#define _MSB_CAPTURE_H_INCLUDED_
+
+/*++
+/* NAME
+/* msg_capture 3h
+/* SUMMARY
+/* message capture support
+/* SYNOPSIS
+/* #include <msg_capture.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External API.
+ */
+typedef struct MSG_CAPTURE MSG_CAPTURE;
+
+extern MSG_CAPTURE *msg_capt_create(ssize_t init_size);
+extern void msg_capt_start(MSG_CAPTURE *mp);
+extern void msg_capt_stop(MSG_CAPTURE *mp);
+extern const char *msg_capt_expose(MSG_CAPTURE *mp);
+extern void msg_capt_free(MSG_CAPTURE *mp);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif
SSL_group_to_name((ssl), SSL_get_negotiated_group(ssl))
#else
#define TLS_GROUP_NAME(ssl) ((const char *)0)
+#endif
+
+#if OPENSSL_VERSION_PREREQ(4,0)
+#define TLS_ADD1_HOST SSL_add1_dnsname
+#define TLS_SET1_HOST SSL_set1_dnsname
+#else
+#define TLS_ADD1_HOST SSL_add1_host
+#define TLS_SET1_HOST SSL_set1_host
#endif
/*
VSTREAM *stream; /* Blocking-mode SMTP session */
/* DANE TLSA trust input and verification state */
const TLS_DANE *dane; /* DANE TLSA digests */
- X509 *errorcert; /* Error certificate closest to leaf */
+ const X509 *errorcert; /* Error certificate closest to leaf */
int errordepth; /* Chain depth of error cert */
int errorcode; /* First error at error depth */
int must_fail; /* Failed to load trust settings */
#endif
if (!match_subdomain) {
- if (SSL_add1_host(ssl, name))
+ if (TLS_ADD1_HOST(ssl, name))
++namechecks_count;
else
msg_warn("%s: error loading match name: \"%s\"",
} else {
char *dot_name = concatenate(".", name, (char *) 0);
- if (SSL_add1_host(ssl, dot_name))
+ if (TLS_ADD1_HOST(ssl, dot_name))
++namechecks_count;
else
msg_warn("%s: error loading match name: \"%s\"",
if (TLScontext->srvr_sig_dgst)
myfree((void *) TLScontext->srvr_sig_dgst);
if (TLScontext->errorcert)
- X509_free(TLScontext->errorcert);
+ X509_free((X509 *) TLScontext->errorcert);
if (TLScontext->ffail_type)
myfree(TLScontext->ffail_type);
/* update_error_state - safely stash away error state */
static void update_error_state(X509_STORE_CTX *ctx, TLS_SESS_STATE *TLScontext,
- int depth, X509 *errorcert, int errorcode)
+ int depth, const X509 *errorcert, int errorcode)
{
/*
* being there until later.
*/
if (TLScontext->errorcert != 0)
- X509_free(TLScontext->errorcert);
+ X509_free((X509 *) TLScontext->errorcert);
if (errorcert != 0)
- X509_up_ref(errorcert);
+ X509_up_ref((X509 *) errorcert);
TLScontext->errorcert = errorcert;
TLScontext->errorcode = errorcode;
TLScontext->errordepth = depth;
int tls_verify_certificate_callback(int ok, X509_STORE_CTX *ctx)
{
char buf[CCERT_BUFSIZ];
- X509 *cert;
+ const X509 *cert;
int err;
int depth;
SSL *con;
{
char buf[CCERT_BUFSIZ];
int err = TLScontext->errorcode;
- X509 *cert = TLScontext->errorcert;
+ const X509 *cert = TLScontext->errorcert;
int depth = TLScontext->errordepth;
#ifdef USE_TLSRPT
/* tls_text_name - extract certificate property value by name */
-static char *tls_text_name(X509_NAME *name, int nid, const char *label,
+static char *tls_text_name(const X509_NAME *name, int nid, const char *label,
const TLS_SESS_STATE *TLScontext, int gripe)
{
const char *myname = "tls_text_name";
int pos;
- X509_NAME_ENTRY *entry;
- ASN1_STRING *entry_str;
+ const X509_NAME_ENTRY *entry;
+ const ASN1_STRING *entry_str;
int asn1_type;
int utf8_length;
unsigned char *utf8_value;
int ch;
unsigned char *cp;
- if (name == 0 || (pos = X509_NAME_get_index_by_NID(name, nid, -1)) < 0) {
+ if (name == 0 || (pos = X509_NAME_get_index_by_NID((X509_NAME *) name, nid, -1)) < 0) {
if (gripe != DONT_GRIPE) {
msg_warn("%s: %s: peer certificate has no %s",
myname, TLScontext->namaddr, label);
char *tls_issuer_CN(X509 *peer, const TLS_SESS_STATE *TLScontext)
{
- X509_NAME *name;
+ const X509_NAME *name;
char *cn;
name = X509_get_issuer_name(peer);
inet_addr_sizes.c quote_for_json.c mystrerror.c \
sane_sockaddr_to_hostaddr.c normalize_ws.c valid_uri_scheme.c \
clean_ascii_cntrl_space.c normalize_v4mapped_addr.c ossl_digest.c \
- mac_midna.c
+ mac_midna.c wrap_stat.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o \
quote_for_json.o mystrerror.o sane_sockaddr_to_hostaddr.o \
normalize_ws.o valid_uri_scheme.o clean_ascii_cntrl_space.o \
- normalize_v4mapped_addr.o ossl_digest.o mac_midna.o
+ normalize_v4mapped_addr.o ossl_digest.o mac_midna.o wrap_stat.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.h \
inet_prefix_top.h inet_addr_sizes.h valid_uri_scheme.h \
clean_ascii_cntrl_space.h normalize_v4mapped_addr.h ossl_digest.h \
- mac_midna.h
+ mac_midna.h wrap_stat.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
nvtable.o: nvtable.c
nvtable.o: nvtable.h
nvtable.o: sys_defs.h
+open_as.o: check_arg.h
open_as.o: msg.h
open_as.o: open_as.c
open_as.o: open_as.h
open_as.o: set_eugid.h
open_as.o: sys_defs.h
+open_as.o: vbuf.h
+open_as.o: vstream.h
open_limit.o: iostuff.h
open_limit.o: open_limit.c
open_limit.o: sys_defs.h
watchdog.o: sys_defs.h
watchdog.o: watchdog.c
watchdog.o: watchdog.h
+wrap_stat.o: sys_defs.h
+wrap_stat.o: wrap_stat.c
+wrap_stat.o: wrap_stat.h
write_buf.o: iostuff.h
write_buf.o: msg.h
write_buf.o: sys_defs.h
#define DICT_FLAG_UTF8_ACTIVE (1<<20) /* UTF-8 proxy layer is present */
#define DICT_FLAG_SRC_RHS_IS_FILE \
(1<<21) /* Map source RHS is a file */
+#define DICT_FLAG_SURROGATE (1<22) /* This is a surrogate dictionary */
#define DICT_FLAG_UTF8_MASK (DICT_FLAG_UTF8_REQUEST)
extern DICT *dict_open(const char *, int, int);
extern DICT *dict_open3(const char *, const char *, int, int);
extern void dict_open_register(const DICT_OPEN_INFO *);
+extern void dict_open_unregister(const char *);
extern const DICT_OPEN_INFO *dict_open_lookup(const char *);
extern DICT_OPEN_EXTEND_FN dict_open_extend(DICT_OPEN_EXTEND_FN);
*/
switch (function) {
case DICT_SEQ_FUN_FIRST:
- if (dict_db->cursor == 0)
- DICT_DB_CURSOR(db, &(dict_db->cursor));
+ if (dict_db->cursor == 0
+ && (status = DICT_DB_CURSOR(db, &(dict_db->cursor))) != 0)
+ msg_fatal("error [%d] initializing cursor for %s: %m",
+ status, dict_db->dict.name);
db_function = DB_FIRST;
break;
case DICT_SEQ_FUN_NEXT:
/* void dict_open_register(open_info)
/* DICT_OPEN_INFO *open_info;
/*
+/* void dict_open_unregister(dict_type)
+/* const char *dict_type;
+/*
/* const DICT_OPEN_INFO *dict_open_lookup(dict_type)
/* const char *dict_type;
/*
/* associated data structures.
/*
/* dict_open_register() adds support for a new dictionary type.
-/* NOTE: this function does not copy its argument.
+/* NOTE: this function does not copy its argument. It is an error
+/* to add an existing type.
+/*
+/* dict_open_unregister() removes support for a dictionary type.
+/* NOTE: it is an error to delete a non-existent type.
/*
/* dict_open_lookup() returns a pointer to the DICT_OPEN_INFO
/* for the specified dictionary type, or a null pointer if the
/* be lifted.
/* DIAGNOSTICS
/* Fatal error: open error, unsupported dictionary type, attempt to
-/* update non-writable dictionary.
+/* update non-writable dictionary, attempt to unregister a type
+/* that is not registered.
/*
/* The lookup routine returns non-null when the request is
/* satisfied. The update, delete and sequence routines return
(void) htable_enter(dict_open_hash, dp->type, (void *) dp);
}
+/* dict_open_unregister - unregister dictionary type */
+
+void dict_open_unregister(const char *dict_type)
+{
+ const char *myname = "dict_open_unregister";
+
+ if (msg_verbose > 1)
+ msg_info("%s: %s", myname, dict_type);
+ if (NEED_DICT_OPEN_INIT())
+ dict_open_init();
+ htable_delete(dict_open_hash, dict_type, (void (*) (void *)) 0);
+}
+
/* dict_open_lookup - look up DICT_OPEN_INFO for dictionary type */
const DICT_OPEN_INFO *dict_open_lookup(const char *dict_type)
if (msg_verbose > 1)
msg_info("%s: %s", myname, dict_type);
+ if (NEED_DICT_OPEN_INIT())
+ dict_open_init();
if ((dp = (DICT_OPEN_INFO *) htable_find(dict_open_hash, dict_type)) == 0
&& dict_open_extend_hook != 0
&& (dp = dict_open_extend_hook(dict_type)) != 0)
/* SUMMARY
/* surrogate table for graceful "open" failure
/* SYNOPSIS
-/* #include <dict_surrogate.h>
+/* #include <dict.h>
/*
/* DICT *dict_surrogate(dict_type, dict_name,
/* open_flags, dict_flags,
}
dp->dict.sequence = dict_surrogate_sequence;
dp->dict.close = dict_surrogate_close;
- dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
+ dp->dict.flags = dict_flags | DICT_FLAG_PATTERN | DICT_FLAG_SURROGATE;
dp->dict.owner.status = DICT_OWNER_TRUSTED;
buf = vstring_alloc(10);
errno = saved_errno;
/* const char *path;
/* int mode;
/* uid_t euid;
+/*
+/* int vstream_fopen_as(path, flags, mode, euid, egid)
+/* const char *path;
+/* int flags;
+/* mode_t mode;
+/* uid_t euid;
/* gid_t egid;
/* DESCRIPTION
/* open_as() opens the named \fIpath\fR with the named \fIflags\fR
/* and \fImode\fR, and with the effective rights specified by \fIeuid\fR
/* and \fIegid\fR. A -1 result means the open failed.
+/*
+/* vstream_fopen_as() implements a VSTREAM wrapper with the same
+/* functionality.
/* DIAGNOSTICS
/* Fatal error: no permission to change privilege level.
/* SEE ALSO
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* porcupine.org
/*--*/
/* System library. */
#include "msg.h"
#include "set_eugid.h"
#include "open_as.h"
+#include "vstream.h"
/* open_as - open file as user */
return (fd);
}
+
+/* vstream_fopen_as - VSTREAM wrapper */
+
+VSTREAM *vstream_fopen_as(const char *path, int flags, mode_t mode,
+ uid_t euid, gid_t egid)
+{
+ int fd;
+
+ if ((fd = open(path, flags, mode)) < 0)
+ return (0);
+ return (vstream_fdopen(fd, flags));
+}
/* DESCRIPTION
/* .nf
+ /*
+ * Utility library.
+ */
+#include <vstream.h>
+
/* External interface. */
extern int open_as(const char *, int, int, uid_t, gid_t);
+extern VSTREAM *vstream_fopen_as(const char *, int, mode_t, uid_t, gid_t);
/* LICENSE
/* .ad
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* porcupine.org
/*--*/
#endif
/* SYNOPSIS
/* #include <spawn_command.h>
/*
-/* WAIT_STATUS_T spawn_command(key, value, ...)
+/* WAIT_STATUS_T spawn_command(key, ...)
/* int key;
+/* AUXILIARY FUNCTIONS
+/* get_spawn_args(
+/* struct spawn_args *args,
+/* int key,
+/* va_list ap)
/* DESCRIPTION
/* spawn_command() runs a command in a child process and returns
/* the command exit status.
/* Application-specific. */
-struct spawn_args {
- char **argv; /* argument vector */
- char *command; /* or a plain string */
- int stdin_fd; /* read stdin here */
- int stdout_fd; /* write stdout here */
- int stderr_fd; /* write stderr here */
- uid_t uid; /* privileges */
- gid_t gid; /* privileges */
- char **env; /* extra environment */
- char **export; /* exportable environment */
- char *shell; /* command shell */
- int time_limit; /* command time limit */
-};
-
/* get_spawn_args - capture the variadic argument list */
-static void get_spawn_args(struct spawn_args * args, int init_key, va_list ap)
+void get_spawn_args(struct spawn_args *args, int init_key, va_list ap)
{
const char *myname = "get_spawn_args";
int key;
/* DESCRIPTION
/* .nf
+ /*
+ * System library.
+ */
+#include <stdarg.h>
+
/*
* Utility library.
*/
extern WAIT_STATUS_T spawn_command(int,...);
+ /*
+ * Internal API, needed by fake_spawn_command().
+ */
+struct spawn_args {
+ char **argv; /* argument vector */
+ char *command; /* or a plain string */
+ int stdin_fd; /* read stdin here */
+ int stdout_fd; /* write stdout here */
+ int stderr_fd; /* write stderr here */
+ uid_t uid; /* privileges */
+ gid_t gid; /* privileges */
+ char **env; /* extra environment */
+ char **export; /* exportable environment */
+ char *shell; /* command shell */
+ int time_limit; /* command time limit */
+};
+
+extern void get_spawn_args(struct spawn_args *, int, va_list);
+
/* LICENSE
/* .ad
/* .fi
#define HAS_SA_LEN
#define NATIVE_DB_TYPE "hash"
#if (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 104250000)
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases" /* sendmail 8.10 */
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases" /* sendmail 8.10 */
#endif
#if (defined(OpenBSD) && OpenBSD >= 200006)
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases" /* OpenBSD 2.7 */
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases" /* OpenBSD 2.7 */
#endif
#ifndef ALIAS_DB_MAP
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#endif
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define HAS_DB
#define HAS_SA_LEN
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define ROOT_PATH "/bin:/usr/bin:/sbin:/usr/sbin"
#define USE_STATFS
/* might be set by makedef */
#ifdef HAS_DB
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#else
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#endif
extern int optind;
extern char *optarg;
#define HAVE_BASENAME
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/var/adm/sendmail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/var/adm/sendmail/aliases"
extern int optind; /* XXX use <getopt.h> */
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
extern int optind;
extern char *optarg;
extern int opterr;
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS
#ifndef NO_NISPLUS
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#ifndef NO_NIS
#define HAS_NIS */
#endif
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
* LINUX.
*/
#if defined(LINUX2) || defined(LINUX3) || defined(LINUX4) || defined(LINUX5) \
- || defined(LINUX6)
+ || defined(LINUX6) || defined(LINUX7)
#define SUPPORTED
#define UINT32_TYPE unsigned int
#define UINT16_TYPE unsigned short
#define HAS_FSYNC
#define HAS_DB
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DB
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define HAS_FSYNC
#define HAS_DB
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
#ifndef NO_NIS
#define HAS_NIS
#endif
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
#ifndef NO_NIS
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#define ROOT_PATH "/usr/bin:/sbin:/usr/sbin"
#define MISSING_SETENV
#ifndef NO_NIS
#define MISSING_RLIMIT_FSIZE
#define GETTIMEOFDAY(t) gettimeofday(t,(struct timezone *) 0)
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/usr/lib/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/usr/lib/aliases"
#define ROOT_PATH "/bin:/usr/bin:/etc"
#define _PATH_BSHELL "/bin/sh"
#define _PATH_MAILDIR "/usr/mail"
#define USE_SYS_SOCKIO_H
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/var/adm/sendmail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/var/adm/sendmail/aliases"
extern int optind; /* XXX use <getopt.h> */
extern char *optarg; /* XXX use <getopt.h> */
extern int opterr; /* XXX use <getopt.h> */
#define DEF_MAILBOX_LOCK "fcntl, dotlock"
#define HAS_FSYNC
#define NATIVE_DB_TYPE "hash"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/aliases"
/* Uncomment the following line if you have NIS package installed */
/* #define HAS_NIS */
#define USE_SYS_SOCKIO_H
#define HAS_FSYNC
#define HAS_DBM
#define NATIVE_DB_TYPE "dbm"
-#define ALIAS_DB_MAP DEF_DB_TYPE ":/etc/mail/aliases"
+#define ALIAS_DB_MAP "$default_database_type:/etc/mail/aliases"
#define DBM_NO_TRAILING_NULL
#ifndef NO_NIS
#define HAS_NIS
#define CA_VSTREAM_CTL_SWAP_FD(v) VSTREAM_CTL_SWAP_FD, CHECK_PTR(VSTREAM_CTL, VSTREAM, (v))
#define CA_VSTREAM_CTL_START_DEADLINE VSTREAM_CTL_START_DEADLINE
#define CA_VSTREAM_CTL_STOP_DEADLINE VSTREAM_CTL_STOP_DEADLINE
+#define CA_VSTREAM_CTL_OWN_VSTRING VSTREAM_CTL_OWN_VSTRING
#define CA_VSTREAM_CTL_MIN_DATA_RATE(v) VSTREAM_CTL_MIN_DATA_RATE, CHECK_VAL(VSTREAM_CTL, int, (v))
CHECK_VAL_HELPER_DCL(VSTREAM_CTL, ssize_t);
--- /dev/null
+/*++
+/* NAME
+/* wrap_stat 3
+/* SUMMARY
+/* mockable stat/lstat wrappers
+/* SYNOPSIS
+/* #include <wrap_stat.h>
+/*
+/* int wrap_stat(
+/* const char *path,
+/* struct stat *st)
+/*
+/* int wrap_lstat(
+/* const char *path,
+/* struct stat *st)
+/* DESCRIPTION
+/* This module is a NOOP when the NO_MOCK_WRAPPERS macro is
+/* defined.
+/*
+/* By default this module redirects stat() and lstat() calls to
+/* the above listed wrapper functions that may be overridden with
+/* mocks. This arrangement prevents mock stat() or lstat() functions
+/* from interfering with stat() or lstat() calls made by system
+/* libraries or by third-party libraries.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/stat.h>
+
+ /*
+ * Utility library.
+ */
+#include <wrap_stat.h>
+
+/* wrap_stat - mockable wrapper */
+
+int wrap_stat(const char *path, struct stat *st)
+{
+#undef stat
+ return (stat (path, st));
+}
+
+/* wrap_lstat - mockable wrapper */
+
+int wrap_lstat(const char *path, struct stat *st)
+{
+#undef lstat
+ return (lstat(path, st));
+}
--- /dev/null
+#ifndef _WRAP_STAT_H_INCLUDED_
+#define _WRAP_STAT_H_INCLUDED_
+
+/*++
+/* NAME
+/* wrap_stat 3h
+/* SUMMARY
+/* mockable stat/lstat wrappers
+/* SYNOPSIS
+/* #include <wrap_stat.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <sys/stat.h>
+
+ /*
+ * Mockable API.
+ */
+#ifndef NO_MOCK_WRAPPERS
+extern int wrap_stat(const char *, struct stat *);
+extern int wrap_lstat(const char *, struct stat *);
+
+#define stat(path, st) wrap_stat(path, st)
+#define lstat(path, st) wrap_lstat(path, st)
+#endif
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* porcupine.org
+/*--*/
+
+#endif