From: Wietse Venema Date: Fri, 9 Dec 2011 05:00:00 +0000 (-0500) Subject: postfix-2.9-20111209 X-Git-Tag: v2.9.0-RC1~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c538d673ac1da2cc229d8b7dfe458b5c482f5213;p=thirdparty%2Fpostfix.git postfix-2.9-20111209 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 4756b0266..d2e1c26f5 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -71,6 +71,7 @@ -TDICT_ENV -TDICT_HT -TDICT_LDAP +-TDICT_MC -TDICT_MYSQL -TDICT_NI -TDICT_NIS @@ -148,6 +149,7 @@ -TMAIL_PRINT -TMAIL_SCAN -TMAIL_STREAM +-TMAIL_VERSION -TMAI_HOSTADDR_STR -TMAI_HOSTNAME_STR -TMAI_SERVNAME_STR diff --git a/postfix/HISTORY b/postfix/HISTORY index 969e18671..c8473aa89 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -17231,3 +17231,55 @@ Apologies for any names omitted. Bugfix: tlsproxy(8) stored TLS sessions with a serverID of "tlsproxy" instead of "smtpd", wasting an opportunity for session reuse. File: tlsproxy/tlsproxy.c. + +20111206 + + Documentation: removed descriptions of Postfix < 2.3 user + interface from TLS_README. Users of earlier releases are + referred to TLS_LEGACY_README. File: proto/TLS_README.html. + +20111207 + + Cleanup: tlsproxy(8) now receives the session cache serverID + from its client (postscreen(8)). Files: global/mail_proto.h, + postscreen/postscreen_starttls.c, tlsproxy/tlsproxy.[hc], + tlsproxy_state.c. + + Cleanup: the postscreen(8) daemon did not support a zero + cache cleanup interval. This is needed for memcache support. + File: postscreen/postscreen.c. + + Bugfix (introduced: 20110227): null pointer bug while + updating dictionary owner attributes, after reading an empty + (database) configuration file. File: util/dict.c. + +20111208 + + Cleanup: db_common_parse_domain() could not be called without + preceding db_common_parse() call. Files: global/db_common.[hc]. + +20111209 + + Feature: memcache client support. This implementation is + based on the under-documented libmemcache library, and + therefore supports only libmemcache version 1.4.0. Files: + conf/postfix-files, global/dict_memcache.[hc], global/mail_dict.c, + html/index.html, mantools/postlink, postconf/postconf.c, + postfix/postfix.c, proto/DATABASE_README.html, + proto/MEMCACHE_README.html, proto/memcache_table. + +20111209 + + Cleanup: support for scripted and manual database tests with + LDAP, *SQL, and memcache. Files: util/dict_test.c, util/dict.c, + global/mail_dict.c. + + Workaround: apparently, some distributions don't use proper + so-number versioning, causing programs to fail erratically + after an update replaces the Postfix library but not the + program. Files: global/mail_version.[hc], master/*server.c, + master/master.c, src/postalias/postalias.c, + src/postdrop/postdrop.c, src/postfix/postfix.c, + src/postlog/postlog.c, src/postmap/postmap.c, + src/postmulti/postmulti.c, src/postqueue/postqueue.c, + src/postsuper/postsuper.c, src/sendmail/sendmail.c. diff --git a/postfix/README_FILES/AAAREADME b/postfix/README_FILES/AAAREADME index 605390d51..7a93a6ba4 100644 --- a/postfix/README_FILES/AAAREADME +++ b/postfix/README_FILES/AAAREADME @@ -48,6 +48,7 @@ LLooookkuupp ttaabblleess ((ddaattaabbaasseess)) * DB_README: Berkeley DB Howto * CDB_README: CDB Howto * LDAP_README: LDAP Howto + * MEMCACHE_README: Memcache Howto * MYSQL_README: MySQL Howto * PCRE_README: PCRE Howto * PGSQL_README: PostgreSQL Howto diff --git a/postfix/README_FILES/DATABASE_README b/postfix/README_FILES/DATABASE_README index 22d5801e6..dcd395294 100644 --- a/postfix/README_FILES/DATABASE_README +++ b/postfix/README_FILES/DATABASE_README @@ -210,6 +210,9 @@ To find out what database types your Postfix system supports, use the "ppooss llddaapp (read-only) Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5). + mmeemmccaacchhee (read-write) + Perform memcache database lookups or updates. Configuration details are + given in memcache_table(5). mmyyssqqll (read-only) Perform MySQL database lookups. Configuration details are given in mysql_table(5). diff --git a/postfix/README_FILES/MEMCACHE_README b/postfix/README_FILES/MEMCACHE_README new file mode 100644 index 000000000..9c17f5551 --- /dev/null +++ b/postfix/README_FILES/MEMCACHE_README @@ -0,0 +1,75 @@ +PPoossttffiixx mmeemmccaacchhee cclliieenntt HHoowwttoo + +------------------------------------------------------------------------------- + +IInnttrroodduuccttiioonn + +The Postfix memcache client type allows you to hook up Postfix to a memcache +server. This implementation supports multiple memcache servers for redundancy, +and multiple memcache clients that you can use for different table lookups. The +Postfix memcache client supports both lookup and update operations. + +Typically, a memcache map is used to reduce query load on a database server, or +to share a low-latency database among different Postfix instances. + +LLiimmiittaattiioonnss + + * The Postfix memcache client is based on libmemcache, which will terminate + its process after a memcache server goes down. To avoid this, set up + redundant memcache servers that have no common source of failure. + + * The Postfix memcache client cannot be used for security-sensitive tables + such as alias_maps (these may contain "|command" and "/file/name" + destinations), or virtual_uid_maps and virtual_gid_maps (these specify UNIX + process privileges). Typically, a memcache database is shared via a TCP + socket, and is writable not only by Postfix, but by any process that can + talk to the memcache server. + + * The Postfix memcache client requires additional configuration when used + with the postscreen(8) and verify(8) daemons. For details see the ttl + parameter discussion in the memcache_table(5) manual page. + + * The Postfix memcache client is supported only with libmemcache version + 1.4.0. Some libmemcache features are documented by reading libmemcache + source code, instead of a proper API. + +BBuuiillddiinngg PPoossttffiixx wwiitthh mmeemmccaacchhee ssuuppppoorrtt + +To build Postfix with memcache client support, specify -DHAS_MEMCACHE, the +location of the libmemcache include files, and the location of the libmemcache +object library. + +For example: + + % make -f Makefile.init makefiles \ + 'CCARGS=-DHAS_MEMCACHE -I/usr/local/include' \ + 'AUXLIBS=-L/usr/local/lib -lmemcache' + +Then run 'make'. + +If the build fails with "undefined reference to `mcm_buf_len'" (and with a +similar error message for mcm_buf_remain_off), then you need to edit +libmemcache source code. + +The following instructions apply to libmemcache 1.4.0.rc2. + + * Open the libmemcache source file include/memcache/buffer.h. + + * Delete the "inline" words before the functions that were reported in the + "undefined reference" error messages. + + * Recompile and reinstall libmemcache. + +Then, continue building Postfix by running 'make'. + +CCoonnffiigguurriinngg mmeemmccaacchhee llooookkuupp ttaabblleess + +Configuration is described in the memcache_table(5) manpage. + +CCrreeddiittss + +The first memcache client for Postfix was written by Omar Kilani. + +Wietse wrote a new memcache client from the ground up. Besides also using +libmemcache, the current implementation bears no resemblance to Omar's work. + diff --git a/postfix/README_FILES/MULTI_INSTANCE_README b/postfix/README_FILES/MULTI_INSTANCE_README index 3ac94733f..b6e15d2e3 100644 --- a/postfix/README_FILES/MULTI_INSTANCE_README +++ b/postfix/README_FILES/MULTI_INSTANCE_README @@ -492,8 +492,8 @@ Shared among all instances: $readme_directory. * Entries in /etc/passwd and /etc/group for the $mail_owner user and - $setgid_group group. The the $mail_owner user provides the mail system with - a protected (non-root) execution context. The $setgid_group group is used + $setgid_group group. The $mail_owner user provides the mail system with a + protected (non-root) execution context. The $setgid_group group is used exclusively to support the setgid postdrop(1) and postqueue(1) utilities (it mmuusstt nnoott be the primary group or secondary group of any users, including the $mail_owner user). diff --git a/postfix/README_FILES/TLS_README b/postfix/README_FILES/TLS_README index f37d187c7..2ac714f1f 100644 --- a/postfix/README_FILES/TLS_README +++ b/postfix/README_FILES/TLS_README @@ -10,21 +10,17 @@ thousands and thousands of lines of OpenSSL library code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix. -At this time, you should no longer be using OpenSSL releases prior to the most -recent 0.9.8 release unless all relevant security fixes have been backported to -the earlier release by you or your O/S vendor. OpenSSL 0.9.7 and earlier are no -longer maintained by the OpenSSL team. - WWhhaatt PPoossttffiixx TTLLSS ssuuppppoorrtt ddooeess ffoorr yyoouu Transport Layer Security (TLS, formerly called SSL) provides certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. -This document describes a TLS user interface that was introduced with Postfix -version 2.3. Support for an older user interface is documented in -TLS_LEGACY_README, which also describes the differences between Postfix and the -third-party patch on which Postfix version 2.2 TLS support was based. + NOTE: This document describes a TLS user interface that was introduced + with Postfix version 2.3. Support for an older user interface is documented + in TLS_LEGACY_README, which also describes the differences between Postfix + and the third-party patch on which Postfix version 2.2 TLS support was + based. Topics covered in this document: @@ -48,12 +44,15 @@ programs. Other colored boxes represent storage elements. * The smtpd(8) server implements the SMTP over TLS server side. - * The smtp(8) client implements the SMTP over TLS client side. + * The smtp(8) client implements the SMTP (and LMTP) over TLS client side. * The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server and smtp(8) client processes, and maintains the TLS session key cache files. +Not shown in the figure are the tlsproxy(8) server and the postscreen(8) +server. These use TLS in the same manner as smtpd(8). + <---seed---- ----seed---> Network-> smtpd(8) tlsmgr(8) smtp(8) ->Network <-key/cert-> <-key/cert-> @@ -94,7 +93,7 @@ Public Internet MX hosts without certificates signed by a "reputable" CA must generate, and be prepared to present to most clients, a self-signed or private- CA signed certificate. The remote SMTP client will generally not be able to authenticate the self-signed certificate, but unless the client is running -Postfix 2.3 or similar software, it will still insist on a server certificate. +Postfix or similar software, it will still insist on a server certificate. For servers that are nnoott public Internet MX hosts, Postfix supports configurations with no certificates. This entails the use of just the anonymous @@ -254,16 +253,12 @@ EEnnaabblliinngg TTLLSS iinn tthhee PPoossttffiixx SSMM By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on with -"smtpd_tls_security_level = may" (Postfix 2.3 and later) or "smtpd_use_tls = -yes" (obsolete but still supported). +"smtpd_tls_security_level = may". Example: /etc/postfix/main.cf: - # Postfix 2.3 and later smtpd_tls_security_level = may - # Obsolete, but still supported - smtpd_use_tls = yes With this, the Postfix SMTP server announces STARTTLS support to remote SMTP clients, but does not require that clients use TLS encryption. @@ -274,18 +269,14 @@ private key. This is intended behavior. You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting -"smtpd_tls_security_level = encrypt" (Postfix 2.3 and later) or -"smtpd_enforce_tls = yes" (obsolete but still supported). According to RFC 2487 -this MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. -This option is off by default and should only seldom be used. +"smtpd_tls_security_level = encrypt". According to RFC 2487 this MUST NOT be +applied in case of a publicly-referenced Postfix SMTP server. This option is +off by default and should only seldom be used. Example: /etc/postfix/main.cf: - # Postfix 2.3 and later smtpd_tls_security_level = encrypt - # Obsolete, but still supported - smtpd_enforce_tls = yes TLS is sometimes used in the non-standard "wrapper" mode where a server always uses TLS, instead of announcing STARTTLS support and waiting for remote SMTP @@ -316,7 +307,7 @@ TLS negotiation when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. A server that wants client certificates -must first present its own certificate. While Postfix 2.3 by default offers +must first present its own certificate. While Postfix by default offers anonymous ciphers to remote SMTP clients, these are automatically suppressed when the Postfix SMTP server is configured to ask for client certificates. @@ -324,10 +315,7 @@ Example: /etc/postfix/main.cf: smtpd_tls_ask_ccert = yes - # Postfix 2.3 and later smtpd_tls_security_level = may - # Obsolete, but still supported - smtpd_use_tls = yes When TLS is enforced you may also decide to REQUIRE a remote SMTP client certificate for all TLS connections, by setting "smtpd_tls_req_ccert = yes". @@ -338,10 +326,7 @@ Example: /etc/postfix/main.cf: smtpd_tls_req_ccert = yes - # Postfix 2.3 and later smtpd_tls_security_level = encrypt - # Obsolete, but still supported - smtpd_enforce_tls = yes The client certificate verification depth is specified with the main.cf smtpd_tls_ccert_verifydepth parameter. The default verification depth is 9 (the @@ -363,14 +348,13 @@ Example: SSuuppppoorrttiinngg AAUUTTHH oovveerr TTLLSS oonnllyy Sending AUTH data over an unencrypted channel poses a security risk. When TLS -layer encryption is required ("smtpd_tls_security_level = encrypt" or the -obsolete "smtpd_enforce_tls = yes"), the Postfix SMTP server will announce and -accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS -layer encryption is optional ("smtpd_tls_security_level = may" or the obsolete -"smtpd_enforce_tls = no"), it may however still be useful to only offer AUTH -when TLS is active. To maintain compatibility with non-TLS clients, the default -is to accept AUTH without encryption. In order to change this behavior, set -"smtpd_tls_auth_only = yes". +layer encryption is required ("smtpd_tls_security_level = encrypt"), the +Postfix SMTP server will announce and accept AUTH only after the TLS layer has +been activated with STARTTLS. When TLS layer encryption is optional +("smtpd_tls_security_level = may"), it may however still be useful to only +offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, +the default is to accept AUTH without encryption. In order to change this +behavior, set "smtpd_tls_auth_only = yes". Example: @@ -480,11 +464,6 @@ host: SSeerrvveerr--ssiiddee cciipphheerr ccoonnttrroollss -The description below is for Postfix 2.3; for Postfix < 2.3 the -smtpd_tls_cipherlist parameter specifies the acceptable ciphers as an explicit -OpenSSL cipherlist. The obsolete setting applies even when TLS encryption is -not enforced. Use of this control on public MX hosts is strongly discouraged. - The Postfix SMTP server supports 5 distinct cipher security levels as specified by the smtpd_tls_mandatory_ciphers configuration parameter, which determines the cipher grade with mandatory TLS encryption. The default value is "medium" @@ -511,7 +490,7 @@ mandatory TLS protocol list is specified via the smtpd_tls_mandatory_protocols configuration parameter. The corresponding smtpd_tls_protocols parameter (Postfix >= 2.6) controls the SSL/TLS protocols used with opportunistic TLS. -For a server that is not a public Internet MX host, Postfix (>= 2.3) supports +For a server that is not a public Internet MX host, Postfix supports configurations with no server certificates that use oonnllyy the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" and not specifying an smtpd_tls_dcert_file or smtpd_tls_eccert_file. @@ -610,8 +589,6 @@ Topics covered in this section: * Client-side TLS session cache * Client TLS limitations * Per-destination TLS policy - * Obsolete per-site TLS policy support - * Closing a DNS loophole with obsolete per-site TLS policies * Discovering servers that support TLS * Server certificate verification depth * Client-side cipher controls @@ -659,28 +636,23 @@ authentication without encryption. NNoo TTLLSS eennccrryyppttiioonn At the "none" TLS security level, TLS encryption is disabled. This is the -default security level. With Postfix 2.3 and later, it can be configured -explicitly by setting "smtp_tls_security_level = none". - -With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its -default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_use_tls = no" and "smtp_enforce_tls = no". With either -approach, TLS is not used even if supported by the server. For LMTP, use the -corresponding "lmtp_" parameters. +default security level, and can be configured explicitly by setting +"smtp_tls_security_level = none". For LMTP, use the corresponding "lmtp_" +parameter. -Per destination settings may override this default setting, in which case TLS +Per-destination settings may override this default setting, in which case TLS is used selectively, only with destinations explicitly configured for TLS. You can disable TLS for a subset of destinations, while leaving it enabled for -the rest. With the Postfix 2.3 and later TLS policy table, specify the "none" -security level. With the obsolete per-site table, specify the "NONE" keyword. +the rest. With the Postfix TLS policy table, specify the "none" security level. OOppppoorrttuunniissttiicc TTLLSS At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the -server. Otherwise, messages are sent in the clear. With Postfix 2.3 and later, -opportunistic TLS can be configured by setting "smtp_tls_security_level = may". +server. Otherwise, messages are sent in the clear. Opportunistic TLS can be +configured by setting "smtp_tls_security_level = may". For LMTP, use the +corresponding "lmtp_" parameter. Since sending in the clear is acceptable, demanding stronger than default TLS security mostly reduces inter-operability. If you must restrict TLS protocol or @@ -690,15 +662,10 @@ over the protocols and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled. -With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its -default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_use_tls = yes" and "smtp_enforce_tls = no". For LMTP use the -corresponding "lmtp_" parameters. - With opportunistic TLS, mail delivery continues even if the server certificate -is untrusted or bears the wrong name. Starting with Postfix 2.3, when the TLS -handshake fails for an opportunistic TLS session, rather than give up on mail -delivery, the transaction is retried with TLS disabled. Trying an unencrypted +is untrusted or bears the wrong name. When the TLS handshake fails for an +opportunistic TLS session, rather than give up on mail delivery, the Postfix +SMTP client retries the transaction with TLS disabled. Trying an unencrypted connection makes it possible to deliver mail to sites with non-interoperable server TLS implementations. @@ -711,8 +678,7 @@ configure opportunistic encryption of LMTP sessions will be ignored with a warning written to the mail logs. You can enable opportunistic TLS just for selected destinations. With the -Postfix 2.3 and later TLS policy table, specify the "may" security level. With -the obsolete per-site table, specify the "MAY" keyword. +Postfix TLS policy table, specify the "may" security level. This is the most common security level for TLS protected SMTP sessions, stronger security is not generally available and, if needed, is typically only @@ -724,21 +690,15 @@ Example: /etc/postfix/main.cf: smtp_tls_security_level = may -Postfix 2.2 syntax: - - /etc/postfix/main.cf: - smtp_use_tls = yes - smtp_enforce_tls = no - MMaannddaattoorryy TTLLSS eennccrryyppttiioonn At the "encrypt" TLS security level, messages are sent only over TLS encrypted sessions. The SMTP transaction is aborted unless the STARTTLS ESMTP feature is supported by the remote SMTP server. If no suitable servers are found, the -message will be deferred. With Postfix 2.3 and later, mandatory TLS encryption -can be configured by setting "smtp_tls_security_level = encrypt". Even though -TLS encryption is always used, mail delivery continues even if the server -certificate is untrusted or bears the wrong name. +message will be deferred. Mandatory TLS encryption can be configured by setting +"smtp_tls_security_level = encrypt". Even though TLS encryption is always used, +mail delivery continues even if the server certificate is untrusted or bears +the wrong name. For LMTP, use the corresponding "lmtp_" parameter. At this security level and higher, the smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers configuration parameters determine the list of @@ -747,11 +707,6 @@ the protocol or cipher requirements are not met, the mail transaction is aborted. The documentation for these parameters includes useful interoperability and security guidelines. -With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its -default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = no". For -LMTP use the corresponding "lmtp_" parameters. - Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to the public Internet. Most MX hosts do not support TLS at all, and some of those @@ -760,11 +715,7 @@ Internet, you should not configure mandatory TLS encryption as the default security level. You can enable mandatory TLS encryption just for specific destinations. With -the Postfix 2.3 and later TLS policy table, specify the "encrypt" security -level. With the obsolete per-site table, specify the "MUST_NOPEERMATCH" -keyword. While the obsolete approach still works with Postfix 2.3, it is -strongly discouraged: users of Postfix 2.3 and later should use the new TLS -policy settings. +the Postfix TLS policy table, specify the "encrypt" security level. Examples: @@ -781,15 +732,6 @@ default for all "encrypt" security level sessions. example.com encrypt .example.com encrypt -Postfix 2.2 syntax (no support for sub-domains without resorting to regexp -tables). With Postfix 2.3 and later, do not use the obsolete per-site table. - - /etc/postfix/main.cf: - smtp_tls_per_site = hash:/etc/postfix/tls_per_site - - /etc/postfix/tls_per_site: - example.com MUST_NOPEERMATCH - In the next example, secure message submission is configured via the MSA " [example.net]:587". TLS sessions are encrypted without authentication, because this MSA does not possess an acceptable certificate. This MSA is known to be @@ -817,21 +759,6 @@ not specified consistently. [example.net]:msa encrypt protocols=TLSv1 ciphers=high [example.net]:submission encrypt protocols=TLSv1 ciphers=high -Postfix 2.2 syntax: - -NNoottee:: Avoid policy lookups with the bare hostname (for example, "example.net"). -Instead, use the destination (for example, "[example.net]:587"), as the per- -site table lookup key (a recipient domain or MX-enabled transport nexthop with -no port suffix may look like a bare hostname, but is still a suitable -destination). With Postfix 2.3 and later, do not use the obsolete per-site -table; use the new policy table instead. - - /etc/postfix/main.cf: - smtp_tls_per_site = hash:/etc/postfix/tls_per_site - - /etc/postfix/tls_per_site: - [example.net]:587 MUST_NOPEERMATCH - CCeerrttiiffiiccaattee ffiinnggeerrpprriinntt vveerriiffiiccaattiioonn Certificate fingerprint verification is available with Postfix 2.5 and later. @@ -898,12 +825,8 @@ certificate name matches a known pattern. Mandatory server certificate verification can be configured by setting "smtp_tls_security_level = verify". The smtp_tls_verify_cert_match parameter can override the default "hostname" certificate name matching strategy. Fine-tuning the matching strategy is -generally only appropriate for secure-channel destinations. - -With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its -default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes". -For LMTP use the corresponding "lmtp_" parameters. +generally only appropriate for secure-channel destinations. For LMTP use the +corresponding "lmtp_" parameters. If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate @@ -927,11 +850,8 @@ STARTTLS support. In such cases, you can often use a secure-channel configuration instead. You can enable mandatory server certificate verification just for specific -destinations. With the Postfix 2.3 and later TLS policy table, specify the -"verify" security level. With the obsolete per-site table, specify the "MUST" -keyword. While the obsolete approach still works with Postfix 2.3, it is -strongly discouraged: users of Postfix 2.3 and later should use the new TLS -policy settings. +destinations. With the Postfix TLS policy table, specify the "verify" security +level. Example: @@ -948,30 +868,15 @@ uses "high" grade ciphers. /etc/postfix/tls_policy: example.com verify ciphers=high -Postfix 2.2 syntax: - - /etc/postfix/main.cf: - indexed = ${default_database_type}:${config_directory}/ - smtp_tls_CAfile = ${config_directory}/CAfile.pem - smtp_tls_per_site = ${indexed}tls_per_site - - /etc/postfix/tls_per_site: - example.com MUST - SSeeccuurree sseerrvveerr cceerrttiiffiiccaattee vveerriiffiiccaattiioonn At the secure TLS security level, messages are sent only over secure-channel TLS sessions where DNS forgery resistant server certificate verification -succeeds. If no suitable servers are found, the message will be deferred. With -Postfix 2.3 and later, secure-channels can be configured by setting -"smtp_tls_security_level = secure". The smtp_tls_secure_cert_match parameter -can override the default "nexthop, dot-nexthop" certificate match strategy. - -With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to its -default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" -with additional settings to harden peer certificate verification against forged -DNS data. For LMTP, use the corresponding "lmtp_" parameters. +succeeds. If no suitable servers are found, the message will be deferred. +Postfix secure-channels can be configured by setting "smtp_tls_security_level = +secure". The smtp_tls_secure_cert_match parameter can override the default +"nexthop, dot-nexthop" certificate match strategy. For LMTP, use the +corresponding "lmtp_" parameters. If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate @@ -994,97 +899,70 @@ would be a client that sends all email to a central mailhub that offers the necessary STARTTLS support. You can enable secure TLS verification just for specific destinations. With the -Postfix 2.3 and later TLS policy table, specify the "secure" security level. -With the obsolete per-site table, specify the "MUST" keyword and harden the -certificate verification against DNS forgery. While the obsolete approach still -works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and -later should use the new TLS policy settings. +Postfix TLS policy table, specify the "secure" security level. Examples: -Secure-channel TLS without transport(5) table overrides: - -The Postfix SMTP client will encrypt all traffic and verify the destination -name immune from forged DNS responses. MX lookups are still used to find the -hostnames of the SMTP servers for example.com, but these hostnames are not used -when checking the names in the server certificate(s). Rather, the requirement -is that the MX hosts for example.com have trusted certificates with a subject -name of example.com or a sub-domain, see the documentation for the -smtp_tls_secure_cert_match parameter. - -The related domains example.co.uk and example.co.jp are hosted on the same MX -hosts as the primary example.com domain, and traffic to these is secured by -verifying the primary example.com domain in the server certificates. This frees -the server administrator from needing the CA to sign certificates that list all -the secondary domains. The downside is that clients that want secure channels -to the secondary domains need explicit TLS policy table entries. - -Note, there are two ways to handle related domains. The first is to use the -default routing for each domain, but add policy table entries to override the -expected certificate subject name. The second is to override the next-hop in -the transport table, and use a single policy table entry for the common -nexthop. We choose the first approach, because it works better when domain -ownership changes. With the second approach we securely deliver mail to the -wrong destination, with the first approach, authentication fails and mail stays -in the local queue, the first approach is more appropriate in most cases. - - /etc/postfix/main.cf: - smtp_tls_CAfile = /etc/postfix/CAfile.pem - smtp_tls_policy_maps = hash:/etc/postfix/tls_policy - - /etc/postfix/transport: - - /etc/postfix/tls_policy: - example.com secure - example.co.uk secure match=example.com:.example.com - example.co.jp secure match=example.com:.example.com - -Secure-channel TLS with transport(5) table overrides: - -In this case traffic to example.com and its related domains is sent to a single -logical gateway (to avoid a single point of failure, its name may resolve to -one or more load-balancer addresses, or to the combined addresses of multiple -physical hosts). All the physical hosts reachable via the gateway's IP -addresses have the logical gateway name listed in their certificates. This -secure-channel configuration can also be implemented via a hardened variant of -the MUST policy in the obsolete per-site table. As stated above, this approach -has the potential to mis-deliver email if the related domains change hands. + * Secure-channel TLS without transport(5) table overrides: + + The Postfix SMTP client will encrypt all traffic and verify the destination + name immune from forged DNS responses. MX lookups are still used to find + the hostnames of the SMTP servers for example.com, but these hostnames are + not used when checking the names in the server certificate(s). Rather, the + requirement is that the MX hosts for example.com have trusted certificates + with a subject name of example.com or a sub-domain, see the documentation + for the smtp_tls_secure_cert_match parameter. + + The related domains example.co.uk and example.co.jp are hosted on the same + MX hosts as the primary example.com domain, and traffic to these is secured + by verifying the primary example.com domain in the server certificates. + This frees the server administrator from needing the CA to sign + certificates that list all the secondary domains. The downside is that + clients that want secure channels to the secondary domains need explicit + TLS policy table entries. + + Note, there are two ways to handle related domains. The first is to use the + default routing for each domain, but add policy table entries to override + the expected certificate subject name. The second is to override the next- + hop in the transport table, and use a single policy table entry for the + common nexthop. We choose the first approach, because it works better when + domain ownership changes. With the second approach we securely deliver mail + to the wrong destination, with the first approach, authentication fails and + mail stays in the local queue, the first approach is more appropriate in + most cases. - /etc/postfix/main.cf: - smtp_tls_CAfile = /etc/postfix/CAfile.pem - transport_maps = hash:/etc/postfix/transport - smtp_tls_policy_maps = hash:/etc/postfix/tls_policy + /etc/postfix/main.cf: + smtp_tls_CAfile = /etc/postfix/CAfile.pem + smtp_tls_policy_maps = hash:/etc/postfix/tls_policy - /etc/postfix/transport: - example.com smtp:[tls.example.com] - example.co.uk smtp:[tls.example.com] - example.co.jp smtp:[tls.example.com] + /etc/postfix/transport: - /etc/postfix/tls_policy: - [tls.example.com] secure match=tls.example.com + /etc/postfix/tls_policy: + example.com secure + example.co.uk secure match=example.com:.example.com + example.co.jp secure match=example.com:.example.com -Postfix 2.2.9 and later syntax: + * Secure-channel TLS with transport(5) table overrides: -NNoottee:: Avoid policy lookups with the bare hostname (for example, -"tls.example.com"). Instead, use the destination (for example, " -[tls.example.com]") as the per-site table lookup key (a recipient domain or MX- -enabled transport nexthop with no port suffix may look like a bare hostname, -but is still a suitable destination). With Postfix 2.3 and later, do not use -the obsolete per-site table; use the new policy table instead. + In this case traffic to example.com and its related domains is sent to a + single logical gateway (to avoid a single point of failure, its name may + resolve to one or more load-balancer addresses, or to the combined + addresses of multiple physical hosts). All the physical hosts reachable via + the gateway's IP addresses have the logical gateway name listed in their + certificates. - /etc/postfix/main.cf: - smtp_cname_overrides_servername = no - smtp_tls_CAfile = /etc/postfix/CAfile.pem - transport_maps = hash:/etc/postfix/transport - smtp_tls_per_site = hash:/etc/postfix/tls_per_site + /etc/postfix/main.cf: + smtp_tls_CAfile = /etc/postfix/CAfile.pem + transport_maps = hash:/etc/postfix/transport + smtp_tls_policy_maps = hash:/etc/postfix/tls_policy - /etc/postfix/transport: - example.com smtp:[tls.example.com] - example.co.uk smtp:[tls.example.com] - example.co.jp smtp:[tls.example.com] + /etc/postfix/transport: + example.com smtp:[tls.example.com] + example.co.uk smtp:[tls.example.com] + example.co.jp smtp:[tls.example.com] - /etc/postfix/tls_per_site: - [tls.example.com] MUST + /etc/postfix/tls_policy: + [tls.example.com] secure match=tls.example.com CClliieenntt--ssiiddee TTLLSS aaccttiivviittyy llooggggiinngg @@ -1322,10 +1200,9 @@ immune to man-in-the-middle attacks) impose constraints on the sending and receiving sites that preclude ubiquitous deployment. One needs to manually configure this type of security for each destination domain, and in many cases implement non-default TLS policy table entries for additional domains hosted at -a common secured destination. With Postfix 2.3, we make secure-channel -configurations substantially easier to configure, but they will never be the -norm. For the generic domain with which you have made no specific security -arrangements, this security level is not a good fit. +a common secured destination. For these reasons secure-channel configurations +will never be the norm. For the generic domain with which you have made no +specific security arrangements, this security level is not a good fit. Given that strong authentication is not generally possible, and that verifiable certificates cost time and money, many servers that implement TLS use self- @@ -1333,30 +1210,24 @@ signed certificates or private CAs. This further limits the applicability of verified TLS on the public Internet. Historical note: while the documentation of these issues and many of the -related features are new with Postfix 2.3, the issue was well understood before -Postfix 1.0, when Lutz Jänicke was designing the first unofficial Postfix TLS -patch. See his original post http://www.imc.org/ietf-apps-tls/mail-archive/ -msg00304.html and the first response http://www.imc.org/ietf-apps-tls/mail- -archive/msg00305.html. The problem is not even unique to SMTP or even TLS, +related features were new with Postfix 2.3, the issue was well understood +before Postfix 1.0, when Lutz Jänicke was designing the first unofficial +Postfix TLS patch. See his original post http://www.imc.org/ietf-apps-tls/mail- +archive/msg00304.html and the first response http://www.imc.org/ietf-apps-tls/ +mail-archive/msg00305.html. The problem is not even unique to SMTP or even TLS, similar issues exist for secure connections via aliases for HTTPS and Kerberos. SMTP merely uses indirect naming (via MX records) more frequently. TTLLSS ppoolliiccyy ttaabbllee -The current TLS policy table was introduced with Postfix 2.3. For earlier -releases, read the description of the obsolete Postfix 2.2 per-site table. - A small fraction of servers offer STARTTLS but the negotiation consistently -fails. With Postfix 2.3, so long as encryption is not enforced, the delivery is -immediately retried with TLS disabled. You no longer need to explicitly disable -TLS for the problem destinations. As soon as their TLS software or -configuration is repaired, encryption will be used. +fails. As long as encryption is not mandatory, the Postfix SMTP client retries +the delivery immediately with TLS disabled, without any need to explicitly +disable TLS for the problem destinations. -The new policy table is specified via the smtp_tls_policy_maps parameter. This +The policy table is specified via the smtp_tls_policy_maps parameter. This lists optional lookup tables with the Postfix SMTP client TLS security policy -by next-hop destination. When $smtp_tls_policy_maps is not empty, the obsolete -smtp_tls_per_site parameter is ignored (a warning is written to the logs if -both parameter values are non-empty). +by next-hop destination. The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop specified in the @@ -1479,164 +1350,6 @@ 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. -OObbssoolleettee ppeerr--ssiittee TTLLSS ppoolliiccyy ssuuppppoorrtt - -This section describes an obsolete per-site TLS policy mechanism. Unlike the -Postfix 2.3 policy table mechanism, this uses as a policy lookup key a -potentially untrusted server hostname, and lacks control over what names can -appear in server certificates. Because of this, the obsolete mechanism is -typically vulnerable to false DNS hostname information in MX or CNAME records. -These attacks can be eliminated only with great difficulty. The new policy -table makes secure-channel configurations easier and provides more control over -the cipher and protocol selection for sessions with mandatory encryption. - -Avoid policy lookups with the bare hostname. Instead, use the full destination -nexthop (enclosed in [] with a possible ":port" suffix) as the per-site table -lookup key (a recipient domain or MX-enabled transport nexthop with no port -suffix may look like a bare hostname, but is still a suitable destination). -With Postfix 2.3 and later, use of the obsolete approach documented here is -strongly discouraged: use the new policy table instead. - -Starting with Postfix 2.3, the underlying TLS enforcement levels are common to -the obsolete per-site table and the new policy table. The main.cf -smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols parameters control -the TLS ciphers and protocols for mandatory encryption regardless of which -table is used. The smtp_tls_verify_cert_match parameter determines the match -strategy for the obsolete "MUST" keyword in the same way as for the "verify" -level in the new policy. - -With Postfix < 2.3, the obsolete smtp_tls_cipherlist parameter is also applied -for opportunistic TLS sessions, and should be used with care, or not at all. -Setting cipherlist restrictions that are incompatible with a remote SMTP server -render that server unreachable, TLS handshakes are always attempted and always -fail. - -When smtp_tls_policy_maps is empty (default) and smtp_tls_per_site is not -empty, the per-site table is searched for a policy that matches the following -information: - - remote SMTP server hostname - This is simply the DNS name of the server that the Postfix SMTP client - connects to; this name may be obtained from other DNS lookups, such as - MX lookups or CNAME lookups. Use of the hostname lookup key is - discouraged; always use the next-hop destination instead. - next-hop destination - This is normally the domain portion of the recipient address, but it - may be overridden by information from the transport(5) table, from the - relayhost parameter setting, or from the relay_transport setting. When - it is not the recipient domain, the next-hop destination can have the - Postfix-specific form "[name]", "[name]:port", "name" or "name:port". - This is the recommended lookup key for per-site policy lookups (and - incidentally for SASL password lookups). - -When both the hostname lookup and the next-hop lookup succeed, the host policy -does not automatically override the next-hop policy. Instead, precedence is -given to either the more specific or the more secure per-site policy as -described below. - -The smtp_tls_per_site table uses a simple "name whitespace value" format. -Specify host names or next-hop destinations on the left-hand side; no wildcards -are allowed. On the right hand side specify one of the following keywords: - - NONE - No TLS. This overrides a less specific "MAY" lookup result from the - alternate host or next-hop lookup key, and overrides the global - smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername settings. - MAY - Opportunistic TLS. This has less precedence than a more specific result - (including "NONE") from the alternate host or next-hop lookup key, and - has less precedence than the more specific global "smtp_enforce_tls = - yes" or "smtp_tls_enforce_peername = yes". - MUST_NOPEERMATCH - Mandatory TLS encryption. This overrides a less secure "NONE" or a less - specific "MAY" lookup result from the alternate host or next-hop lookup - key, and overrides the global smtp_use_tls, smtp_enforce_tls and - smtp_tls_enforce_peername settings. - MUST - Mandatory server certificate verification. This overrides a less secure - "NONE" and "MUST_NOPEERMATCH" or a less specific "MAY" lookup result - from the alternate host or next-hop lookup key, and overrides the - global smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername - settings. - -The precedences between global (main.cf) and per-site TLS policies can be -summarized as follows: - - * When neither the remote SMTP server hostname nor the next-hop destination - are found in the smtp_tls_per_site table, the policy is based on - smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername. Note: - "smtp_enforce_tls = yes" and "smtp_tls_enforce_peername = yes" imply - "smtp_use_tls = yes". - - * When both hostname and next-hop destination lookups produce a result, the - more specific per-site policy (NONE, MUST, etc) overrides the less specific - one (MAY), and the more secure per-site policy (MUST, etc) overrides the - less secure one (NONE). - - * After the per-site policy lookups are combined, the result generally - overrides the global policy. The exception is the less specific "MAY" per- - site policy, which is overruled by the more specific global - "smtp_enforce_tls = yes" with server certificate verification as specified - with the smtp_tls_enforce_peername parameter. - -CClloossiinngg aa DDNNSS lloooopphhoollee wwiitthh oobbssoolleettee ppeerr--ssiittee TTLLSS ppoolliicciieess - -For a general discussion of TLS security for SMTP see TLS limitations above. -What follows applies only to Postfix 2.2.9 and subsequent Postfix 2.2 patch -levels. Do not use this approach with Postfix 2.3 and later; instead see the -instructions under secure server certificate verification. - -As long as no secure DNS lookup mechanism is available, false hostnames in MX -or CNAME responses can change Postfix's notion of the server hostname that is -used for TLS policy lookup and server certificate verification. Even with a -perfect match between the server hostname and the server certificate, there is -no guarantee that Postfix is connected to the right server. To avoid this -loophole, take all of the following steps: - - 1. Use a dedicated message delivery transport (for example, "securetls") as - illustrated below. - - 2. Eliminate MX lookups. Specify local transport(5) table entries for - sensitive domains with explicit securetls:[mailhost] or securetls: - [mailhost]:port destinations (you can assure security of this table unlike - DNS). This prevents false hostname information in DNS MX records from - changing Postfix's notion of the server hostname that is used for TLS - policy lookup and server certificate verification. The "securetls" - transport is configured to enforce TLS with peername verification, and to - disable the SMTP connection cache which could interfere with enforcement of - smtp_tls_per_site policies. - - 3. Disallow CNAME hostname overrides. In main.cf, specify - "smtp_cname_overrides_servername = no". This prevents false hostname - information in DNS CNAME records from changing the server hostname that - Postfix uses for TLS policy lookup and server certificate verification. - This feature requires Postfix 2.2.9 or later. The default value is "no" - starting with Postfix 2.3. - -Example: - -We give the non-default "securetls" transport an explicit master.cf process -limit, so that we don't raise its process limit when raising -$default_process_limit. The total process limit for *all* transports should -stay somewhat under 1024 (the typical select() file descriptor limit); -otherwise transports may be throttled under steady high load, compounding -congestion. It is not uncommon at high volume sites to set the default process -limit to 500 or more. - -We also default the "securetls" transport TLS security level to MUST, obviating -the need for per-site table entries for secure-channel destinations. - - /etc/postfix/main.cf: - transport_maps = hash:/etc/postfix/transport - - /etc/postfix/transport: - example.com securetls:[tls.example.com] - - /etc/postfix/master.cf: - securetls unix - - n - 100 smtp - -o smtp_enforce_tls=yes - -o smtp_tls_enforce_peername=yes - DDiissccoovveerriinngg sseerrvveerrss tthhaatt ssuuppppoorrtt TTLLSS As we decide on a "per site" basis whether or not to use TLS, it would be good @@ -1971,10 +1684,7 @@ indicates a super-user shell. smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom - # Postfix 2.3 and later smtpd_tls_security_level = may - # Obsolete, but still supported - smtpd_use_tls = yes BBuuiillddiinngg PPoossttffiixx wwiitthh TTLLSS ssuuppppoorrtt diff --git a/postfix/README_FILES/TUNING_README b/postfix/README_FILES/TUNING_README index b704fb2d2..56f87da73 100644 --- a/postfix/README_FILES/TUNING_README +++ b/postfix/README_FILES/TUNING_README @@ -390,12 +390,12 @@ TTuunniinngg tthhee nnuummbbeerr ooff PPoossttffiixx pp The default_process_limit configuration parameter gives direct control over how many daemon processes Postfix will run. As of Postfix 2.0 the default limit is -100 smtp client processes, 100 smtp server processes, and so on. This may +100 SMTP client processes, 100 SMTP server processes, and so on. This may overwhelm systems with little memory, as well as networks with low bandwidth. You can change the global process limit by specifying a non-default -default_process_limit in the main.cf file. For example, to run up to 10 smtp -client processes, 10 smtp server processes, and so on: +default_process_limit in the main.cf file. For example, to run up to 10 SMTP +client processes, 10 SMTP server processes, and so on: /etc/postfix/main.cf: default_process_limit = 10 diff --git a/postfix/WISHLIST b/postfix/WISHLIST index d305283a0..d2a4e8cb9 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -2,14 +2,18 @@ Wish list: Things to do before the stable release: + Either make all void dict_* operations return an error code, + or require that they reset dict_errno on entry, either exit + with a fatal error or set dict_errno on error. + + Is it possible to replace msg_fatal calls in match_ops.c + by msg_warn and longjmp? The callers will have to specify + if they want the code to return instead of terminate. + Remove this file from the stable release. Things to do after the stable release: - Investigate viability of memcached for applications - that require performance for low-security operations - such as sharing the postscreen cache. - What is the feasibility of adding an mta_name (personality) attribute that is propagated via queue files and delivery agent requests? It would default to myhostname. diff --git a/postfix/conf/postfix-files b/postfix/conf/postfix-files index d3911d633..90ef9575a 100644 --- a/postfix/conf/postfix-files +++ b/postfix/conf/postfix-files @@ -166,6 +166,7 @@ $manpage_directory/man5/generic.5:f:root:-:644 $manpage_directory/man5/header_checks.5:f:root:-:644 $manpage_directory/man5/ldap_table.5:f:root:-:644 $manpage_directory/man5/master.5:f:root:-:644 +$manpage_directory/man5/memcache_table.5:f:root:-:644 $manpage_directory/man5/mysql_table.5:f:root:-:644 $manpage_directory/man5/sqlite_table.5:f:root:-:644 $manpage_directory/man5/nisplus_table.5:f:root:-:644 @@ -264,6 +265,7 @@ $readme_directory/LINUX_README:f:root:-:644 $readme_directory/LOCAL_RECIPIENT_README:f:root:-:644 $readme_directory/MACOSX_README:f:root:-:644:o $readme_directory/MAILDROP_README:f:root:-:644 +$readme_directory/MEMCACHE_README:f:root:-:644 $readme_directory/MILTER_README:f:root:-:644 $readme_directory/MULTI_INSTANCE_README:f:root:-:644 $readme_directory/MYSQL_README:f:root:-:644 @@ -369,6 +371,7 @@ $html_directory/local.8.html:f:root:-:644 $html_directory/mailq.1.html:f:root:-:644 $html_directory/master.5.html:f:root:-:644 $html_directory/master.8.html:f:root:-:644 +$html_directory/memcache_table.5.html:f:root:-:644 $html_directory/mysql_table.5.html:f:root:-:644 $html_directory/sqlite_table.5.html:f:root:-:644 $html_directory/nisplus_table.5.html:f:root:-:644 diff --git a/postfix/html/DATABASE_README.html b/postfix/html/DATABASE_README.html index b2166e9cb..f394976c5 100644 --- a/postfix/html/DATABASE_README.html +++ b/postfix/html/DATABASE_README.html @@ -310,6 +310,11 @@ a process terminates.
Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5).
+
memcache (read-write)
+ +
Perform memcache database lookups or updates. Configuration +details are given in memcache_table(5).
+
mysql (read-only)
Perform MySQL database lookups. Configuration details are given @@ -367,7 +372,7 @@ in sqlite_table(5).
static (read-only)
Always returns its lookup table name as lookup result. For -example, the lookup table "static:foobar" always returns the string +example, the lookup table "static:foobar" always returns the string "foobar" as lookup result.
tcp
@@ -383,8 +388,8 @@ number.
This produces similar results as hash: files, except that you don't have to run the postmap(1) command before you can use the -file, and that texthash: does not detect changes after the file is -read. The lookup table name is "texthash:filename", where the file +file, and that texthash: does not detect changes after the file is +read. The lookup table name is "texthash:filename", where the file name is taken literally; no suffix is appended.
unix (read-only)
diff --git a/postfix/html/MEMCACHE_README.html b/postfix/html/MEMCACHE_README.html new file mode 100644 index 000000000..ff96b8bc9 --- /dev/null +++ b/postfix/html/MEMCACHE_README.html @@ -0,0 +1,113 @@ + + + + + + +Postfix memcache client Howto + + + + + + + +

Postfix memcache client Howto

+ +
+ +

Introduction

+ +

The Postfix memcache client type allows you to hook up Postfix to +a memcache server. This implementation supports multiple memcache +servers for redundancy, and multiple memcache clients that you can +use for different table lookups. The Postfix memcache client +supports both lookup and update operations.

+ +

Typically, a memcache map is used to reduce query load on a +database server, or to share a low-latency database among different +Postfix instances.

+ +

Limitations

+ + + +

Building Postfix with memcache support

+ +

To build Postfix with memcache client support, specify +-DHAS_MEMCACHE, the location of the libmemcache include +files, and the location of the libmemcache object library.

+ +

For example:

+ +
+
+% make -f Makefile.init makefiles \
+        'CCARGS=-DHAS_MEMCACHE -I/usr/local/include' \
+	'AUXLIBS=-L/usr/local/lib -lmemcache'
+
+
+ +

Then run 'make'.

+ +

If the build fails with "undefined reference to `mcm_buf_len'" +(and with a similar error message for mcm_buf_remain_off), +then you need to edit libmemcache source code.

+ +

The following instructions apply to libmemcache 1.4.0.rc2.

+ + + +

Then, continue building Postfix by running 'make'.

+ +

Configuring memcache lookup tables

+ +

Configuration is described in the memcache_table(5) manpage.

+ +

Credits

+ +

The first memcache client for Postfix was written by Omar Kilani.

+ +

Wietse wrote a new memcache client from the ground up. Besides +also using libmemcache, the current implementation bears no resemblance +to Omar's work.

+ + + + diff --git a/postfix/html/MULTI_INSTANCE_README.html b/postfix/html/MULTI_INSTANCE_README.html index d4874bae9..f22433874 100644 --- a/postfix/html/MULTI_INSTANCE_README.html +++ b/postfix/html/MULTI_INSTANCE_README.html @@ -620,7 +620,7 @@ $daemon_directory.

$manpage_directory and $readme_directory.

  • Entries in /etc/passwd and /etc/group for the $mail_owner user and -$setgid_group group. The the $mail_owner user provides the mail system +$setgid_group group. The $mail_owner user provides the mail system with a protected (non-root) execution context. The $setgid_group group is used exclusively to support the setgid postdrop(1) and postqueue(1) utilities (it must not be the primary group or secondary group diff --git a/postfix/html/Makefile.in b/postfix/html/Makefile.in index 36327f2be..2778e7bac 100644 --- a/postfix/html/Makefile.in +++ b/postfix/html/Makefile.in @@ -20,6 +20,7 @@ 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 \ ldap_table.5.html mysql_table.5.html pgsql_table.5.html \ + memcache_table.5.html \ master.5.html nisplus_table.5.html generic.5.html bounce.5.html \ postfix-wrapper.5.html sqlite_table.5.html OTHER = postfix-manuals.html @@ -272,6 +273,10 @@ master.5.html: ../proto/master PATH=../mantools:$$PATH; \ srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ +memcache_table.5.html: ../proto/memcache_table + PATH=../mantools:$$PATH; \ + srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ + mysql_table.5.html: ../proto/mysql_table PATH=../mantools:$$PATH; \ srctoman - $? | $(AWK) | nroff -man | uniq | $(MAN2HTML) | postlink >$@ diff --git a/postfix/html/TLS_README.html b/postfix/html/TLS_README.html index 2ce5805b2..d7ce9a8a1 100644 --- a/postfix/html/TLS_README.html +++ b/postfix/html/TLS_README.html @@ -27,11 +27,6 @@ code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix.

    -

    At this time, you should no longer be using OpenSSL releases prior -to the most recent 0.9.8 release unless all relevant security fixes have -been backported to the earlier release by you or your O/S vendor. OpenSSL -0.9.7 and earlier are no longer maintained by the OpenSSL team.

    -

    What Postfix TLS support does for you

    Transport Layer Security (TLS, formerly called SSL) provides @@ -39,11 +34,13 @@ certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. -

    This document describes a TLS user interface that was introduced -with Postfix version 2.3. Support for an older user interface is -documented in TLS_LEGACY_README, which also describes the differences -between Postfix and the third-party patch on which Postfix version -2.2 TLS support was based.

    +

    NOTE: This document describes a TLS +user interface that was introduced with Postfix version 2.3. Support +for an older user interface is documented in TLS_LEGACY_README, +which also describes the differences between Postfix and the +third-party patch on which Postfix version 2.2 TLS support was +based.

    Topics covered in this document:

    @@ -85,8 +82,8 @@ represent storage elements.

  • The smtpd(8) server implements the SMTP over TLS server side.

    -
  • The smtp(8) client implements the SMTP over TLS client -side.

    +
  • The smtp(8) client implements the SMTP (and LMTP) over TLS +client side.

  • The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server @@ -95,6 +92,10 @@ cache files.

    +

    Not shown in the figure are the tlsproxy(8) server and the +postscreen(8) server. These use TLS in the same manner as smtpd(8). +

    +
    Network->

    For servers that are not public Internet MX hosts, Postfix @@ -389,19 +390,14 @@ since the headers may be changed by intermediate servers.

    By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on -with "smtpd_tls_security_level = may" (Postfix 2.3 and -later) or "smtpd_use_tls = yes" (obsolete but still -supported).

    +with "smtpd_tls_security_level = may".

    Example:

     /etc/postfix/main.cf:
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = may
    -    # Obsolete, but still supported
    -    smtpd_use_tls = yes
     
    @@ -417,9 +413,8 @@ private key. This is intended behavior.

    You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting -"smtpd_tls_security_level = encrypt" (Postfix 2.3 and -later) or "smtpd_enforce_tls = yes" (obsolete but still -supported). According to RFC 2487 this MUST NOT be applied in case +"smtpd_tls_security_level = encrypt". According to RFC 2487 this +MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used.

    @@ -428,10 +423,7 @@ by default and should only seldom be used.

     /etc/postfix/main.cf:
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = encrypt
    -    # Obsolete, but still supported
    -    smtpd_enforce_tls = yes
     
    @@ -473,7 +465,7 @@ when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. A server that wants client certificates -must first present its own certificate. While Postfix 2.3 by default +must first present its own certificate. While Postfix by default offers anonymous ciphers to remote SMTP clients, these are automatically suppressed when the Postfix SMTP server is configured to ask for client @@ -485,10 +477,7 @@ certificates.

     /etc/postfix/main.cf:
         smtpd_tls_ask_ccert = yes
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = may
    -    # Obsolete, but still supported
    -    smtpd_use_tls = yes
     
    @@ -505,10 +494,7 @@ logged.

     /etc/postfix/main.cf:
         smtpd_tls_req_ccert = yes
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = encrypt
    -    # Obsolete, but still supported
    -    smtpd_enforce_tls = yes
     
    @@ -539,12 +525,10 @@ configured to supply its intermediate CA certificate).

    Sending AUTH data over an unencrypted channel poses a security risk. When TLS layer encryption is required -("smtpd_tls_security_level = encrypt" or the obsolete -"smtpd_enforce_tls = yes"), the Postfix SMTP server will +("smtpd_tls_security_level = encrypt"), the Postfix SMTP server will announce and accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS layer encryption is optional -("smtpd_tls_security_level = may" or the obsolete -"smtpd_enforce_tls = no"), it may however still be useful +("smtpd_tls_security_level = may"), it may however still be useful to only offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, the default is to accept AUTH without encryption. In order to change this behavior, set @@ -695,12 +679,6 @@ the name of the user or host:

    Server-side cipher controls

    -

    The description below is for Postfix 2.3; for Postfix < 2.3 the -smtpd_tls_cipherlist parameter specifies the acceptable ciphers as an -explicit OpenSSL cipherlist. The obsolete setting applies even when TLS -encryption is not enforced. Use of this control on public MX hosts is -strongly discouraged.

    -

    The Postfix SMTP server supports 5 distinct cipher security levels as specified by the smtpd_tls_mandatory_ciphers configuration parameter, which determines the cipher grade with mandatory TLS encryption. The @@ -732,7 +710,7 @@ is optional. The mandatory TLS protocol list is specified via the corresponding smtpd_tls_protocols parameter (Postfix ≥ 2.6) controls the SSL/TLS protocols used with opportunistic TLS.

    -

    For a server that is not a public Internet MX host, Postfix (≥ 2.3) +

    For a server that is not a public Internet MX host, Postfix supports configurations with no server certificates that use only the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" @@ -870,10 +848,6 @@ key configuration

  • Per-destination TLS policy -
  • Obsolete per-site TLS policy support - -
  • Closing a DNS loophole with obsolete per-site TLS policies -
  • Discovering servers that support TLS
  • Server certificate verification depth @@ -934,32 +908,26 @@ The "null" ciphers provide authentication without encryption.

    No TLS encryption

    At the "none" TLS security level, TLS encryption is -disabled. This is the default security level. With Postfix 2.3 and later, -it can be configured explicitly by setting "smtp_tls_security_level = none".

    +disabled. This is the default security level, and +can be configured explicitly by setting "smtp_tls_security_level = none". +For LMTP, use the corresponding "lmtp_" parameter.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to -its default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_use_tls = no" and "smtp_enforce_tls = no". -With either approach, TLS is not used even if supported by the server. -For LMTP, use the corresponding "lmtp_" parameters.

    - -

    Per destination settings may override this default setting, in which case +

    Per-destination settings may override this default setting, in which case TLS is used selectively, only with destinations explicitly configured for TLS.

    You can disable TLS for a subset of destinations, while leaving -it enabled for the rest. With the Postfix 2.3 and later TLS policy table, specify the "none" -security level. With the obsolete per-site -table, specify the "NONE" keyword.

    +security level.

    Opportunistic TLS

    At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear. -With Postfix 2.3 and later, opportunistic TLS can be configured by -setting "smtp_tls_security_level = may". +Opportunistic TLS can be configured by setting "smtp_tls_security_level = may". +For LMTP, use the corresponding "lmtp_" parameter.

    Since sending in the clear is acceptable, demanding stronger than default TLS security mostly reduces inter-operability. If you @@ -970,17 +938,12 @@ and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level is -set to its default (backwards compatible) empty value, the appropriate -configuration settings are "smtp_use_tls = yes" and -"smtp_enforce_tls = no". -For LMTP use the corresponding "lmtp_" parameters.

    -

    With opportunistic TLS, mail delivery continues even if the -server certificate is untrusted or bears the wrong name. Starting -with Postfix 2.3, when the TLS handshake fails for an opportunistic -TLS session, rather than give up on mail delivery, the transaction -is retried with TLS disabled. Trying an unencrypted connection makes +server certificate is untrusted or bears the wrong name. +When the TLS handshake fails for an opportunistic +TLS session, rather than give up on mail delivery, the Postfix SMTP +client retries the transaction +with TLS disabled. Trying an unencrypted connection makes it possible to deliver mail to sites with non-interoperable server TLS implementations.

    @@ -994,9 +957,8 @@ Attempts to configure opportunistic encryption of LMTP sessions will be ignored with a warning written to the mail logs.

    You can enable opportunistic TLS just for selected destinations. With -the Postfix 2.3 and later TLS policy table, -specify the "may" security level. With the obsolete per-site table, specify the "MAY" keyword.

    +the Postfix TLS policy table, +specify the "may" security level.

    This is the most common security level for TLS protected SMTP sessions, stronger security is not generally available and, if needed, @@ -1012,27 +974,18 @@ on TLS limitations above.

    -

    Postfix 2.2 syntax:

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_use_tls = yes
    -    smtp_enforce_tls = no
    -
    -
    -

    Mandatory TLS encryption

    At the "encrypt" TLS security level, messages are sent only over TLS encrypted sessions. The SMTP transaction is aborted unless the STARTTLS ESMTP feature is supported by the remote SMTP server. If no suitable -servers are found, the message will be deferred. With Postfix 2.3 -and later, mandatory TLS encryption can be configured by setting +servers are found, the message will be deferred. +Mandatory TLS encryption can be configured by setting "smtp_tls_security_level = encrypt". Even though TLS encryption is always used, mail delivery continues even if the server -certificate is untrusted or bears the wrong name.

    +certificate is untrusted or bears the wrong name. +For LMTP, use the corresponding "lmtp_" parameter.

    At this security level and higher, the smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers configuration parameters determine @@ -1042,12 +995,6 @@ met, the mail transaction is aborted. The documentation for these parameters includes useful interoperability and security guidelines.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" -and "smtp_tls_enforce_peername = no". For LMTP use the corresponding -"lmtp_" parameters.

    -

    Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to the public Internet. Most MX hosts do not support TLS at @@ -1056,12 +1003,9 @@ that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level.

    You can enable mandatory TLS encryption just for specific destinations. -With the Postfix 2.3 and later TLS policy -table, specify the "encrypt" security level. With the -obsolete per-site table, specify the -"MUST_NOPEERMATCH" keyword. While the obsolete approach still works -with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later -should use the new TLS policy settings.

    +With the Postfix TLS policy +table, specify the "encrypt" security level. +

    Examples:

    @@ -1083,20 +1027,6 @@ level sessions.

    -

    Postfix 2.2 syntax (no support for sub-domains without resorting to -regexp tables). With Postfix 2.3 and later, do not use the obsolete per-site table.

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    example.com       MUST_NOPEERMATCH
    -
    -
    -

    In the next example, secure message submission is configured via the MSA "[example.net]:587". TLS sessions are encrypted without authentication, because this MSA does not possess an acceptable @@ -1128,28 +1058,6 @@ just in case the transport table entries are not specified consistently.

    -

    Postfix 2.2 syntax:

    - -

    Note: Avoid policy lookups with the bare hostname (for -example, "example.net"). Instead, -use the destination (for example, "[example.net]:587"), as the per-site table lookup key (a recipient domain -or MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -do not use the obsolete per-site table; -use the new policy table instead.

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    [example.net]:587   MUST_NOPEERMATCH
    -
    -
    -

    Certificate fingerprint verification

    Certificate fingerprint verification is available with Postfix @@ -1234,13 +1142,8 @@ server certificate verification can be configured by setting smtp_tls_verify_cert_match parameter can override the default "hostname" certificate name matching strategy. Fine-tuning the matching strategy is generally only appropriate for secure-channel destinations.

    - -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" and -"smtp_tls_enforce_peername = yes". For LMTP use the corresponding -"lmtp_" parameters.

    +href="#client_tls_secure">secure-channel destinations. +For LMTP use the corresponding "lmtp_" parameters.

    If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName @@ -1269,12 +1172,9 @@ href="#client_tls_secure">secure-channel configuration instead.

    You can enable mandatory server certificate verification just -for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "verify" -security level. With the obsolete per-site -table, specify the "MUST" keyword. While the obsolete approach -still works with Postfix 2.3, it is strongly discouraged: users of -Postfix 2.3 and later should use the new TLS policy settings.

    +security level.

    Example:

    @@ -1295,36 +1195,16 @@ to example.com recipients uses "high" grade ciphers.

    -

    Postfix 2.2 syntax:

    -
    -
    -/etc/postfix/main.cf:
    -    indexed = ${default_database_type}:${config_directory}/
    -    smtp_tls_CAfile = ${config_directory}/CAfile.pem
    -    smtp_tls_per_site = ${indexed}tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    example.com         MUST
    -
    -
    -

    Secure server certificate verification

    At the secure TLS security level, messages are sent only over secure-channel TLS sessions where DNS forgery resistant server certificate verification succeeds. If no suitable servers are found, the -message will be deferred. With Postfix 2.3 and later, secure-channels +message will be deferred. Postfix secure-channels can be configured by setting "smtp_tls_security_level = secure". The smtp_tls_secure_cert_match parameter can override the default -"nexthop, dot-nexthop" certificate match strategy.

    - -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" -and "smtp_tls_enforce_peername = yes" with additional settings to -harden peer certificate verification -against forged DNS data. For LMTP, use the corresponding "lmtp_" -parameters.

    +"nexthop, dot-nexthop" certificate match strategy. +For LMTP, use the corresponding "lmtp_" parameters.

    If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate @@ -1351,18 +1231,14 @@ sends all email to a central mailhub that offers the necessary STARTTLS support.

    You can enable secure TLS verification just for specific destinations. -With the Postfix 2.3 and later TLS policy table, -specify the "secure" security level. With the obsolete -per-site table, specify the "MUST" -keyword and harden the certificate -verification against DNS forgery. While the obsolete approach still -works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 -and later -should use the new TLS policy settings.

    +With the Postfix TLS policy table, +specify the "secure" security level.

    Examples:

    -

    Secure-channel TLS without transport(5) table overrides:

    +
      + +
    • Secure-channel TLS without transport(5) table overrides:

      The Postfix SMTP client will encrypt all traffic and verify the destination name @@ -1408,18 +1284,14 @@ the first approach is more appropriate in most cases.

      -

      Secure-channel TLS with transport(5) table overrides:

      +

    • Secure-channel TLS with transport(5) table overrides:

      In this case traffic to example.com and its related domains is sent to a single logical gateway (to avoid a single point of failure, its name may resolve to one or more load-balancer addresses, or to the combined addresses of multiple physical hosts). All the physical hosts reachable via the gateway's IP addresses have the logical gateway name -listed in their certificates. This secure-channel configuration can also -be implemented via a hardened variant of -the MUST policy in the obsolete per-site -table. As stated above, this approach has the potential to mis-deliver -email if the related domains change hands.

      +listed in their certificates.

      @@ -1438,35 +1310,7 @@ email if the related domains change hands. 

      -

      Postfix 2.2.9 and later syntax:

      - -

      Note: Avoid policy lookups with the bare hostname (for -example, "tls.example.com"). Instead, use the destination (for -example, "[tls.example.com]") as the per-site table lookup key (a recipient domain -or MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -do not use the obsolete per-site table; -use the new policy table instead.

      - -
      -
      -/etc/postfix/main.cf:
      -    smtp_cname_overrides_servername = no
      -    smtp_tls_CAfile = /etc/postfix/CAfile.pem
      -    transport_maps = hash:/etc/postfix/transport
      -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
      -
      -/etc/postfix/transport:
      -    example.com     smtp:[tls.example.com]
      -    example.co.uk   smtp:[tls.example.com]
      -    example.co.jp   smtp:[tls.example.com]
      -
      -/etc/postfix/tls_per_site:
      -    [tls.example.com]       MUST
      -
      -
      +

    Client-side TLS activity logging

    @@ -1778,9 +1622,9 @@ constraints on the sending and receiving sites that preclude ubiquitous deployment. One needs to manually configure this type of security for each destination domain, and in many cases implement non-default TLS policy table entries for additional -domains hosted at a common secured destination. With Postfix 2.3, we -make secure-channel configurations substantially easier to configure, -but they will never be the norm. For the generic domain with which you +domains hosted at a common secured destination. For these reasons +secure-channel configurations +will never be the norm. For the generic domain with which you have made no specific security arrangements, this security level is not a good fit.

    @@ -1790,7 +1634,7 @@ TLS use self-signed certificates or private CAs. This further limits the applicability of verified TLS on the public Internet.

    Historical note: while the documentation of these issues and many of the -related features are new with Postfix 2.3, the issue was well +related features were new with Postfix 2.3, the issue was well understood before Postfix 1.0, when Lutz Jänicke was designing the first unofficial Postfix TLS patch. See his original post http://www.imc.org/ietf-apps-tls/mail-archive/msg00304.html @@ -1803,23 +1647,15 @@ uses indirect naming (via MX records) more frequently.

    TLS policy table

    -

    The current TLS policy table was introduced with Postfix 2.3. For -earlier releases, read the description of the obsolete Postfix 2.2 per-site table.

    -

    A small fraction of servers offer STARTTLS but the negotiation -consistently fails. With Postfix 2.3, so long as encryption is not -enforced, the delivery is immediately retried with TLS disabled. You no -longer need to explicitly disable TLS for the problem destinations. -As soon as their TLS software or configuration is repaired, encryption -will be used.

    +consistently fails. As long as encryption is not mandatory, the +Postfix SMTP client retries the delivery immediately with TLS +disabled, without any need to explicitly disable TLS for the problem +destinations.

    -

    The new policy table is specified via the smtp_tls_policy_maps +

    The policy table is specified via the smtp_tls_policy_maps parameter. This lists optional lookup tables with the Postfix SMTP client -TLS security policy by next-hop destination. When $smtp_tls_policy_maps -is not empty, the obsolete smtp_tls_per_site parameter is ignored -(a warning is written to the logs if both parameter values are -non-empty).

    +TLS security policy by next-hop destination.

    The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop @@ -1968,211 +1804,6 @@ 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.

    -

    Obsolete per-site TLS policy support -

    - -

    This section describes an obsolete per-site TLS policy mechanism. -Unlike the Postfix 2.3 policy table -mechanism, this uses as a policy lookup key a potentially untrusted -server hostname, and lacks control over what names can appear in -server certificates. Because of this, the obsolete mechanism is -typically vulnerable to false DNS hostname information in MX or -CNAME records. These attacks can be eliminated only with great -difficulty. The new policy table -makes secure-channel configurations -easier and provides more control over the cipher and protocol selection -for sessions with mandatory encryption.

    - -

    Avoid policy lookups with the bare hostname. Instead, use the -full destination nexthop (enclosed in [] with a possible ":port" -suffix) as the per-site table lookup key (a recipient domain or -MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -use of the obsolete approach documented here is strongly discouraged: -use the new policy table instead.

    - -

    Starting with Postfix 2.3, the underlying TLS enforcement levels are -common to the obsolete per-site table and the new policy table. The -main.cf smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols -parameters control the TLS ciphers and protocols for mandatory -encryption regardless of which table is used. The -smtp_tls_verify_cert_match parameter determines the match strategy -for the obsolete "MUST" keyword in the same way as for the "verify" -level in the new policy.

    - -

    With Postfix < 2.3, the obsolete smtp_tls_cipherlist parameter -is also applied for opportunistic TLS sessions, and should be used with -care, or not at all. Setting cipherlist restrictions that are incompatible -with a remote SMTP server render that server unreachable, TLS handshakes -are always attempted and always fail.

    - -

    When smtp_tls_policy_maps is empty (default) and smtp_tls_per_site -is not empty, the per-site table is searched for a policy that matches -the following information:

    - -
    - -
    - -
    remote SMTP server hostname
    This is simply the DNS -name of the server that the Postfix SMTP client connects to; this -name may be obtained from other DNS lookups, such as MX lookups or -CNAME lookups. Use of the hostname lookup key is discouraged; always -use the next-hop destination instead.
    - -
    next-hop destination
    This is normally the domain portion -of the recipient address, but it may be overridden by information from -the transport(5) table, from the relayhost parameter setting, or from -the relay_transport setting. When it is not the recipient domain, the -next-hop destination can have the Postfix-specific form "[name]", -"[name]:port", "name" or "name:port". This is -the recommended lookup key for per-site policy lookups (and incidentally -for SASL password lookups).
    - -
    - -
    - -

    When both the hostname lookup and the next-hop lookup succeed, -the host policy does not automatically override the next-hop policy. -Instead, precedence is given to either the more specific or the -more secure per-site policy as described below.

    - -

    The smtp_tls_per_site table uses a simple "name whitespace -value" format. Specify host names or next-hop destinations on -the left-hand side; no wildcards are allowed. On the right hand -side specify one of the following keywords:

    - -
    - -
    - -
    NONE
    No TLS. This overrides a less specific "MAY" lookup -result from the alternate host or next-hop lookup key, and overrides -the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername -settings.
    - -
    MAY
    Opportunistic TLS. This has less precedence than -a more specific result (including "NONE") from the alternate host or -next-hop lookup key, and has less precedence than the more specific global -"smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes".
    - -
    MUST_NOPEERMATCH
    Mandatory TLS encryption. This -overrides a less secure "NONE" or a less specific "MAY" lookup result -from the alternate host or next-hop lookup key, and overrides the global -smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. -
    - -
    MUST
    Mandatory server certificate verification. -This overrides a less secure "NONE" and "MUST_NOPEERMATCH" or a -less specific "MAY" lookup result from the alternate host or next-hop -lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls -and smtp_tls_enforce_peername settings.
    - -
    - -
    - -

    The precedences between global (main.cf) and per-site TLS -policies can be summarized as follows:

    - -
      - -
    • When neither the remote SMTP server hostname nor the -next-hop destination are found in the smtp_tls_per_site table, the -policy is based on smtp_use_tls, smtp_enforce_tls and -smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and -"smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes".

      - -
    • When both hostname and next-hop destination lookups produce -a result, the more specific per-site policy (NONE, MUST, etc) -overrides the less specific one (MAY), and the more secure per-site -policy (MUST, etc) overrides the less secure one (NONE).

      - -
    • After the per-site policy lookups are combined, the result -generally overrides the global policy. The exception is the less -specific "MAY" per-site policy, which is overruled by the more -specific global "smtp_enforce_tls = yes" with server certificate -verification as specified with the smtp_tls_enforce_peername -parameter.

      - -
    - -

    Closing a DNS loophole with -obsolete per-site TLS policies

    - -

    For a general discussion of TLS security for SMTP see TLS limitations above. What follows applies -only to Postfix 2.2.9 and subsequent Postfix 2.2 patch levels. Do -not use this approach with Postfix 2.3 -and later; instead see the instructions under secure server certificate verification.

    - -

    As long as no secure DNS lookup mechanism is available, false -hostnames in MX or CNAME responses can change Postfix's notion of the -server hostname that is used for TLS policy lookup and server certificate -verification. Even with a perfect match between the server hostname and -the server certificate, there is no guarantee that Postfix is connected -to the right server. To avoid this loophole, take all of the following -steps:

    - -
      - -
    1. Use a dedicated message delivery transport (for example, -"securetls") as illustrated below.

      - -
    2. Eliminate MX lookups. Specify local transport(5) table -entries for sensitive domains with explicit securetls:[mailhost] -or securetls:[mailhost]:port destinations (you can -assure security of this table unlike DNS). This prevents false -hostname information in DNS MX records from changing Postfix's -notion of the server hostname that is used for TLS policy lookup -and server certificate verification. The "securetls" transport is -configured to enforce TLS with peername verification, and to disable -the SMTP connection cache which could interfere with enforcement -of smtp_tls_per_site policies.

      - -
    3. Disallow CNAME hostname overrides. In main.cf, specify -"smtp_cname_overrides_servername = no". This prevents false hostname -information in DNS CNAME records from changing the server hostname -that Postfix uses for TLS policy lookup and server certificate -verification. This feature requires Postfix 2.2.9 or later. The -default value is "no" starting with Postfix 2.3.

      - -
    - -

    Example:

    - -

    We give the non-default -"securetls" transport an explicit master.cf process limit, so that we -don't raise its process limit when raising $default_process_limit. The -total process limit for *all* transports should stay somewhat under 1024 -(the typical select() file descriptor limit); otherwise transports may -be throttled under steady high load, compounding congestion. It is not -uncommon at high volume sites to set the default process limit to 500 -or more.

    - -

    We also default the "securetls" transport TLS security level to -MUST, obviating the need for per-site table entries for secure-channel -destinations.

    - -
    -
    -/etc/postfix/main.cf:
    -    transport_maps = hash:/etc/postfix/transport
    -
    -/etc/postfix/transport:
    -    example.com         securetls:[tls.example.com]
    -
    -/etc/postfix/master.cf:
    -    securetls unix  -       -       n       -       100     smtp
    -        -o smtp_enforce_tls=yes
    -        -o smtp_tls_enforce_peername=yes
    -
    -
    -

    Discovering servers that support TLS

    @@ -2601,10 +2232,7 @@ but don't require them from all clients.

    smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom - # Postfix 2.3 and later smtpd_tls_security_level = may - # Obsolete, but still supported - smtpd_use_tls = yes diff --git a/postfix/html/TUNING_README.html b/postfix/html/TUNING_README.html index 343e424e1..48f59f2ff 100644 --- a/postfix/html/TUNING_README.html +++ b/postfix/html/TUNING_README.html @@ -551,13 +551,13 @@ mail deliveries.

    The default_process_limit configuration parameter gives direct control over how many daemon processes Postfix will run. As of -Postfix 2.0 the default limit is 100 smtp client processes, 100 -smtp server processes, and so on. This may overwhelm systems with +Postfix 2.0 the default limit is 100 SMTP client processes, 100 +SMTP server processes, and so on. This may overwhelm systems with little memory, as well as networks with low bandwidth.

    You can change the global process limit by specifying a non-default default_process_limit in the main.cf file. For example, -to run up to 10 smtp client processes, 10 smtp server processes, +to run up to 10 SMTP client processes, 10 SMTP server processes, and so on:

    diff --git a/postfix/html/index.html b/postfix/html/index.html index 619986836..77544f5ad 100644 --- a/postfix/html/index.html +++ b/postfix/html/index.html @@ -132,6 +132,8 @@ Per-client/user/etc. access
  • LDAP Howto +
  • Memcache Howto +
  • MySQL Howto
  • PCRE Howto diff --git a/postfix/html/memcache_table.5.html b/postfix/html/memcache_table.5.html new file mode 100644 index 000000000..ddf5db8c0 --- /dev/null +++ b/postfix/html/memcache_table.5.html @@ -0,0 +1,178 @@ + + + + Postfix manual - memcache_table(5) +
    +MEMCACHE_TABLE(5)                                            MEMCACHE_TABLE(5)
    +
    +NAME
    +       memcache_table - Postfix memcache client configuration
    +
    +SYNOPSIS
    +       postmap -q "string" memcache:/etc/postfix/filename
    +
    +       postmap -q - memcache:/etc/postfix/filename <inputfile
    +
    +DESCRIPTION
    +       The  Postfix  mail system uses optional tables for address
    +       rewriting or mail routing. These tables are usually in dbm
    +       or db format.
    +
    +       Alternatively,  lookup tables can be specified as memcache
    +       instances.  In order to use  memcache  lookups,  define  a
    +       memcache source as a lookup table in main.cf, for example:
    +
    +           virtual_alias_maps = memcache:/etc/postfix/memcache-aliases.cf
    +
    +       The file  /etc/postfix/memcache-aliases.cf  has  the  same
    +       format  as  the  Postfix  main.cf  file, and specifies the
    +       parameters described below.
    +
    +       The Postfix memcache client supports the lookup and update
    +       operations.
    +
    +MEMCACHE PARAMETERS
    +       hosts (default: localhost:11211)
    +              The  memcache servers that Postfix will try to con-
    +              nect to.  Specify a hostname or address, optionally
    +              followed  by  ":"  and  a  port name or number. The
    +              default port is 11211.  Examples:
    +
    +                  hosts = memcache01.example.com
    +                      memcache02.example.com
    +
    +       key_format (default: %s)
    +              Format of the lookup and update  keys  in  memcache
    +              queries.   By  default,  these  are the same as the
    +              lookup and update keys that are given to the  Post-
    +              fix memcache client.
    +
    +              When  the  same  memcache database is used to cache
    +              information from multiple tables, you can  use  the
    +              key_format  feature  to  avoid  name  collisions by
    +              prepending a fixed string.  Examples:
    +
    +                  key_format = aliases:%s
    +                  key_format = access:%s
    +
    +              The key_format parameter supports the following '%'
    +              expansions:
    +
    +              %%     This is replaced by a literal '%' character.
    +
    +              %s     This is  replaced  by  the  memcache  client
    +                     input key.
    +
    +              %u     When the input key is an address of the form
    +                     user@domain,  %u  is  replaced  by  the  SQL
    +                     quoted  local  part  of the address.  Other-
    +                     wise, %u 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 warn-
    +                     ing).
    +
    +              %d     When the input key is an address of the form
    +                     user@domain,  %d  is  replaced by the domain
    +                     part of the address.  Otherwise, a lookup is
    +                     silently  suppressed  and returns no results
    +                     (an update is skipped with a warning).
    +
    +              %[SUD] The  upper-case  equivalents  of  the  above
    +                     expansions  behave in the key_format parame-
    +                     ter identically to their lower-case counter-
    +                     parts.
    +
    +              %[1-9] The  patterns %1, %2, ... %9 are replaced by
    +                     the corresponding most significant component
    +                     of  the input key's domain. If the input key
    +                     is user@mail.example.com, then %1 is com, %2
    +                     is  example and %3 is mail. If the input key
    +                     is  unqualified  or  does  not  have  enough
    +                     domain  components to satisfy all the speci-
    +                     fied patterns, a  lookup  is  silently  sup-
    +                     pressed and returns no results (an update is
    +                     skipped with a warning).
    +
    +       domain (default: no domain list)
    +              This  feature  can  significantly  reduce  database
    +              server load.  Specify a list of domain names, paths
    +              to files, or dictionaries.   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, hash:/etc/postfix/searchdomains
    +
    +       flags (default: 0)
    +              Optional  flags  that should be stored along with a
    +              memcache update.
    +
    +       ttl (default: 604800)
    +              The expiration time in seconds of memcache updates.
    +              The default is one week.
    +
    +              When  using  memcache  tables with postscreen(8) or
    +              verify(8), specify a zero  *_cache_cleanup_interval
    +              value,  and specify the largest postscreen(8) *_ttl
    +              value or verify(8) *_expire_time value as the  mem-
    +              cache map's ttl value.
    +
    +              Note: 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.
    +
    +BUGS
    +       The Postfix memcache client is based on libmemcache, which
    +       will  terminate  its  process after a memcache server goes
    +       down. To avoid this, set  up  redundant  memcache  servers
    +       that have no common source of failure.
    +
    +       The  Postfix  memcache client cannot be used for security-
    +       sensitive tables such as  alias_maps  (these  may  contain
    +       "|command   and   "/file/name"   destinations),   or  vir-
    +       tual_uid_maps and  virtual_gid_maps  (these  specify  UNIX
    +       process  privileges).   In a typical deployment a memcache
    +       database is shared via a  TCP  socket,  and  is  therefore
    +       writable  not only by Postfix, but by any process that can
    +       talk to the memcache server.
    +
    +       The Postfix memcache client requires additional configura-
    +       tion  when  used with the postscreen(8) and verify(8) dae-
    +       mons.  For details see the ttl parameter discussion at the
    +       end of the MEMCACHE PARAMETERS section in this document.
    +
    +       The Postfix memcache client is supported only with libmem-
    +       cache version 1.4.0.  Some libmemcache features are  docu-
    +       mented  by  reading  libmemcache  source  code,  instead a
    +       proper API.
    +
    +SEE ALSO
    +       postmap(1), Postfix lookup table manager
    +       postconf(5), configuration parameters
    +
    +README FILES
    +       DATABASE_README, Postfix lookup table overview
    +       MEMCACHE_README, Postfix memcache client guide
    +
    +LICENSE
    +       The  Secure  Mailer  license must be distributed with this
    +       software.
    +
    +HISTORY
    +       The first memcache client for Postfix was written by  Omar
    +       Kilani.   Besides  being  implemented on libmemcache, this
    +       implementation bears no resemblance to his work.
    +
    +AUTHOR(S)
    +       Wietse Venema
    +       IBM T.J. Watson Research
    +       P.O. Box 704
    +       Yorktown Heights, NY 10598, USA
    +
    +                                                             MEMCACHE_TABLE(5)
    +
    diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 1d1948e75..cf4086fc7 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -193,127 +193,131 @@ POSTCONF(1) POSTCONF(1) Perform lookups using the LDAP protocol. This is described in ldap_table(5). + memcache (read-write) + Perform lookups using the memcache protocol. + This is described in memcache_table(5). + mysql (read-only) - Perform lookups using the MYSQL protocol. + Perform lookups using the MYSQL protocol. This is described in mysql_table(5). pcre (read-only) A lookup table based on Perl Compatible Reg- - ular Expressions. The file format is + ular Expressions. The file format is described in pcre_table(5). pgsql (read-only) - Perform lookups using the PostgreSQL proto- + Perform lookups using the PostgreSQL proto- col. This is described in pgsql_table(5). proxy (read-only) - A lookup table that is implemented via the - Postfix proxymap(8) service. The table name + A lookup table that is implemented via the + Postfix proxymap(8) service. The table name syntax is type:name. regexp (read-only) A lookup table based on regular expressions. - The file format is described in regexp_ta- + The file format is described in regexp_ta- ble(5). sdbm An indexed file type based on hashing. This - is available on systems with support for + is available on systems with support for SDBM databases. sqlite (read-only) - Perform lookups from SQLite database files. + Perform lookups from SQLite database files. This is described in sqlite_table(5). static (read-only) - A table that always returns its name as - lookup result. For example, static:foobar - always returns the string foobar as lookup + A table that always returns its name as + lookup result. For example, static:foobar + always returns the string foobar as lookup result. tcp (read-only) Perform lookups using a simple request-reply - protocol that is described in tcp_table(5). + protocol that is described in tcp_table(5). texthash (read-only) - Produces similar results as hash: files, + Produces similar results as hash: files, except that you don't need to run the - postmap(1) command before you can use the - file, and that it does not detect changes + postmap(1) command before you can use the + file, and that it does not detect changes after the file is read. unix (read-only) - A limited way to query the UNIX authentica- + A limited way to query the UNIX authentica- tion database. The following tables are implemented: unix:passwd.byname - The table is the UNIX password data- - base. The key is a login name. The - result is a password file entry in + The table is the UNIX password data- + base. The key is a login name. The + result is a password file entry in passwd(5) format. unix:group.byname The table is the UNIX group database. - The key is a group name. The result - is a group file entry in group(5) + The key is a group name. The result + is a group file entry in group(5) format. - Other table types may exist depending on how Post- + Other table types may exist depending on how Post- fix was built. - -M Show master.cf file contents instead of main.cf - file contents. Specify -Mf to fold long lines for + -M Show master.cf file contents instead of main.cf + file contents. Specify -Mf to fold long lines for human readability. If service ... is specified, only the matching ser- - vices will be output. For example, "postconf -Mf - inet" will output all services that listen on the + vices will be output. For example, "postconf -Mf + inet" will output all services that listen on the network. - Specify zero or more arguments, each with a ser- - vice-type name (inet, unix, fifo, or pass) or with - a service-name.service-type pair, where service- + Specify zero or more arguments, each with a ser- + vice-type name (inet, unix, fifo, or pass) or with + a service-name.service-type pair, where service- name is the first field of a master.cf entry. - This feature is available with Postfix 2.9 and + This feature is available with Postfix 2.9 and later. - -n Print main.cf parameter settings that are explic- - itly specified in main.cf. Specify -nf to fold - long lines for human readability (Postfix 2.9 and + -n Print main.cf parameter settings that are explic- + itly specified in main.cf. Specify -nf to fold + long lines for human readability (Postfix 2.9 and later). -t [template_file] - Display the templates for text that appears at the - beginning of delivery status notification (DSN) + Display the templates for text that appears at the + beginning of delivery status notification (DSN) messages, without expanding $name expressions. - To override the built-in templates, specify a tem- - plate file name at the end of the postconf(1) com- - mand line, or specify a file name in main.cf with + To override the built-in templates, specify a tem- + plate file name at the end of the postconf(1) com- + mand line, or specify a file name in main.cf with the bounce_template_file parameter. To force selection of the built-in templates, spec- - ify an empty template file name on the postconf(1) + ify an empty template file name on the postconf(1) command line (in shell language: ""). - This feature is available with Postfix 2.3 and + This feature is available with Postfix 2.3 and later. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. - -# Edit the main.cf configuration file, and comment + -# Edit the main.cf configuration file, and comment out the parameters given on the postconf(1) command - line, so that those parameters revert to their - default values. The file is copied to a temporary - file then renamed into place. Specify a list of + line, so that those parameters revert to their + default values. The file is copied to a temporary + file then renamed into place. Specify a list of parameter names, not name=value pairs. There is no - postconf(1) command to perform the reverse opera- + postconf(1) command to perform the reverse opera- tion. - This feature is available with Postfix 2.6 and + This feature is available with Postfix 2.6 and later. DIAGNOSTICS @@ -324,18 +328,18 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant + The following main.cf parameters are especially relevant to this program. - The text below provides only a parameter summary. See + The text below provides only a parameter summary. See postconf(5) for more details including examples. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and + The default location of the Postfix main.cf and master.cf configuration files. bounce_template_file (empty) - Pathname of a configuration file with bounce mes- + Pathname of a configuration file with bounce mes- sage templates. FILES @@ -351,7 +355,7 @@ POSTCONF(1) POSTCONF(1) 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) diff --git a/postfix/html/postfix-manuals.html b/postfix/html/postfix-manuals.html index 36cdfa5b2..4397bd7c3 100644 --- a/postfix/html/postfix-manuals.html +++ b/postfix/html/postfix-manuals.html @@ -155,6 +155,8 @@ the following convention:

  • ldap_table(5), Postfix LDAP client +
  • memcache_table(5), Postfix memcache client +
  • mysql_table(5), Postfix MYSQL client
  • nisplus_table(5), Postfix NIS+ client diff --git a/postfix/html/postfix.1.html b/postfix/html/postfix.1.html index c4bb73a25..b62e5a8b1 100644 --- a/postfix/html/postfix.1.html +++ b/postfix/html/postfix.1.html @@ -296,6 +296,7 @@ POSTFIX(1) POSTFIX(1) Table lookup mechanisms: cidr_table(5), Associate CIDR pattern with value ldap_table(5), Postfix LDAP client + memcache_table(5), Postfix memcache client mysql_table(5), Postfix MYSQL client nisplus_table(5), Postfix NIS+ client pcre_table(5), Associate PCRE pattern with value diff --git a/postfix/html/postqueue.1.html b/postfix/html/postqueue.1.html index a49832868..4a5dfc560 100644 --- a/postfix/html/postqueue.1.html +++ b/postfix/html/postqueue.1.html @@ -157,11 +157,11 @@ POSTQUEUE(1) POSTQUEUE(1) Available in Postfix version 2.2 and later: - authorized_flush_users (static:anyone) + authorized_flush_users (static:anyone) List of users who are authorized to flush the queue. - authorized_mailq_users (static:anyone) + authorized_mailq_users (static:anyone) List of users who are authorized to view the queue. FILES diff --git a/postfix/man/Makefile.in b/postfix/man/Makefile.in index 912ace409..c8a80e53b 100644 --- a/postfix/man/Makefile.in +++ b/postfix/man/Makefile.in @@ -16,7 +16,8 @@ COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.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 \ - man5/body_checks.5 man5/ldap_table.5 man5/mysql_table.5 \ + man5/body_checks.5 man5/ldap_table.5 man5/memcache_table.5 \ + man5/mysql_table.5 \ man5/pgsql_table.5 man5/master.5 man5/nisplus_table.5 \ man5/generic.5 man5/bounce.5 man5/postfix-wrapper.5 \ man5/sqlite_table.5 @@ -276,6 +277,9 @@ man5/ldap_table.5: ../proto/ldap_table man5/master.5: ../proto/master ../mantools/srctoman - $? >$@ +man5/memcache_table.5: ../proto/memcache_table + ../mantools/srctoman - $? >$@ + man5/mysql_table.5: ../proto/mysql_table ../mantools/srctoman - $? >$@ diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 3ad161761..c2a83503f 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -181,6 +181,9 @@ when a process terminates. .IP "\fBldap\fR (read-only)" Perform lookups using the LDAP protocol. This is described in \fBldap_table\fR(5). +.IP "\fBmemcache\fR (read-write)" +Perform lookups using the memcache protocol. This is described +in \fBmemcache_table\fR(5). .IP "\fBmysql\fR (read-only)" Perform lookups using the MYSQL protocol. This is described in \fBmysql_table\fR(5). diff --git a/postfix/man/man1/postfix.1 b/postfix/man/man1/postfix.1 index 95a313506..3cf7b9cae 100644 --- a/postfix/man/man1/postfix.1 +++ b/postfix/man/man1/postfix.1 @@ -254,6 +254,7 @@ virtual(5), Postfix virtual aliasing Table lookup mechanisms: cidr_table(5), Associate CIDR pattern with value ldap_table(5), Postfix LDAP client +memcache_table(5), Postfix memcache client mysql_table(5), Postfix MYSQL client nisplus_table(5), Postfix NIS+ client pcre_table(5), Associate PCRE pattern with value diff --git a/postfix/man/man5/memcache_table.5 b/postfix/man/man5/memcache_table.5 new file mode 100644 index 000000000..3e617b82d --- /dev/null +++ b/postfix/man/man5/memcache_table.5 @@ -0,0 +1,188 @@ +.TH MEMCACHE_TABLE 5 +.ad +.fi +.SH NAME +memcache_table +\- +Postfix memcache client configuration +.SH "SYNOPSIS" +.na +.nf +\fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/filename\fR + +\fBpostmap -q - memcache:/etc/postfix/\fIfilename\fR <\fIinputfile\fR +.SH DESCRIPTION +.ad +.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, lookup tables can be specified as memcache +instances. In order to use memcache lookups, define a +memcache source as a lookup table in main.cf, for example: + +.nf + virtual_alias_maps = memcache:/etc/postfix/memcache-aliases.cf +.fi + +The file /etc/postfix/memcache-aliases.cf has the same +format as the Postfix main.cf file, and specifies the +parameters described below. + +The Postfix memcache client supports the lookup and update +operations. +.SH "MEMCACHE PARAMETERS" +.na +.nf +.ad +.fi +.IP "\fBhosts (default: localhost:11211)\fR" +The memcache servers that Postfix will try to connect to. +Specify a hostname or address, optionally followed by ":" +and a port name or number. The default port is 11211. +Examples: + +.nf + hosts = memcache01.example.com + memcache02.example.com +.fi +.IP "\fBkey_format (default: %s)\fB" +Format of the lookup and update keys in memcache queries. +By default, these are the same as the lookup and update +keys that are given to the Postfix memcache client. + +When the same memcache database is used to cache information +from multiple tables, you can use the \fBkey_format\fR +feature to avoid name collisions by prepending a fixed +string. Examples: + +.nf + key_format = aliases:%s + key_format = access:%s +.fi + +The \fBkey_format\fR parameter supports the following '%' +expansions: +.RS +.IP "\fB\fB%%\fR\fR" +This is replaced by a literal '%' character. +.IP "\fB\fB%s\fR\fR" +This is replaced by the memcache client input key. +.IP "\fB\fB%u\fR\fR" +When the input key is an address of the form user@domain, +\fB%u\fR is replaced by the SQL quoted local part of the +address. Otherwise, \fB%u\fR 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). +.IP "\fB\fB%d\fR\fR" +When the input key is an address of the form user@domain, +\fB%d\fR is replaced by the domain part of the address. +Otherwise, a lookup is silently suppressed and returns no +results (an update is skipped with a warning). +.IP "\fB\fB%[SUD]\fR\fR" +The upper-case equivalents of the above expansions behave +in the \fBkey_format\fR parameter identically to their +lower-case counter-parts. +.IP "\fB\fB%[1-9]\fR\fR" +The patterns %1, %2, ... %9 are replaced by the corresponding +most significant component of the input key's domain. If +the input key is \fIuser@mail.example.com\fR, then %1 is +\fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR. 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 skipped with a warning). +.RE +.IP "\fBdomain (default: no domain list)\fR" +This feature can significantly reduce database server load. +Specify a list of domain names, paths to files, or dictionaries. +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: + +.nf + domain = example.com, hash:/etc/postfix/searchdomains +.fi +.IP "\fBflags (default: 0)\fR" +Optional flags that should be stored along with a memcache +update. +.IP "\fBttl (default: 604800)\fR" +The expiration time in seconds of memcache updates. +The default is one week. + +When using memcache tables with \fBpostscreen\fR(8) or +\fBverify\fR(8), specify a zero *_cache_cleanup_interval +value, and specify the largest \fBpostscreen\fR(8) *_ttl +value or \fBverify\fR(8) *_expire_time value as the memcache +map's \fBttl\fR value. + +Note: 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. +.SH BUGS +.ad +.fi +The Postfix memcache client is based on libmemcache, which +will terminate its process after a memcache server goes +down. To avoid this, set up redundant memcache servers that +have no common source of failure. + +The Postfix memcache client cannot be used for security-sensitive +tables such as \fBalias_maps\fR (these may contain +"\fI|command\fR and "\fI/file/name\fR" destinations), or +\fBvirtual_uid_maps\fR and \fBvirtual_gid_maps\fR (these +specify UNIX process privileges). In a typical deployment +a memcache database is shared via a TCP socket, and is +therefore writable not only by Postfix, but by any process +that can talk to the memcache server. + +The Postfix memcache client requires additional configuration +when used with the \fBpostscreen\fR(8) and \fBverify\fR(8) +daemons. For details see the \fBttl\fR parameter discussion +at the end of the MEMCACHE PARAMETERS section in this +document. + +The Postfix memcache client is supported only with libmemcache +version 1.4.0. Some libmemcache features are documented +by reading libmemcache source code, instead a proper API. +.SH "SEE ALSO" +.na +.nf +postmap(1), Postfix lookup table manager +postconf(5), configuration parameters +.SH "README FILES" +.na +.nf +.ad +.fi +Use "\fBpostconf readme_directory\fR" or +"\fBpostconf html_directory\fR" to locate this information. +.na +.nf +DATABASE_README, Postfix lookup table overview +MEMCACHE_README, Postfix memcache client guide +.SH "LICENSE" +.na +.nf +.ad +.fi +The Secure Mailer license must be distributed with this software. +.SH "HISTORY" +.na +.nf +.ad +.fi +The first memcache client for Postfix was written by Omar +Kilani. Besides being implemented on libmemcache, this +implementation bears no resemblance to his work. +.SH "AUTHOR(S)" +.na +.nf +Wietse Venema +IBM T.J. Watson Research +P.O. Box 704 +Yorktown Heights, NY 10598, USA diff --git a/postfix/mantools/double b/postfix/mantools/double index dfefd72b0..a573a9244 100755 --- a/postfix/mantools/double +++ b/postfix/mantools/double @@ -3,5 +3,5 @@ for i in $* do echo === $i === - dehtml $i | double + dehtml $i | tr A-Z a-z | double done diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 5831ffe25..8f3b7f274 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -776,6 +776,7 @@ while (<>) { s/[]*gener[-<\/bB>]*\n* *[]*ic[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*ldap[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*mas[-<\/bB>]*\n* *[]*ter[<\/bB>]*\(5\)/$&<\/a>/g; + s/[]*memcache[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*mysql[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*nisplus[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*pcre[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; @@ -788,7 +789,7 @@ while (<>) { s/[]*scache[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*sqlite[<\/bBiI>]*_[<\/iIbB>]*ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*trans[-<\/bB>]*\n*[ ]*port[<\/bB>]*\(5\)/$&<\/a>/g; - s/[]*verify[<\/bB>]*\(8\)/$&<\/a>/g; + s/[]*ver[-<\/bB>]*\n*[ ]*ify[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*vir[-<\/bB>]*\n*[ ]*tual[<\/bB>]*\(5\)/$&<\/a>/g; s/[]*vir[-<\/bB>]*\n*[ ]*tual[<\/bB>]*\(8\)/$&<\/a>/g; s/[]*cidr_ta[-<\/bB>]*\n*[ ]*ble[<\/bB>]*\(5\)/$&<\/a>/g; @@ -1064,6 +1065,7 @@ while (<>) { s/\b(static):/$1<\/a>:/g; s/\b(tcp):/$1<\/a>:/g; s/\b(texthash):/$1<\/a>:/g; + s/\b(memcache):/$1<\/a>:/g; # Do nice links for smtp:host:port etc. diff --git a/postfix/proto/DATABASE_README.html b/postfix/proto/DATABASE_README.html index e1541a985..1b0237b37 100644 --- a/postfix/proto/DATABASE_README.html +++ b/postfix/proto/DATABASE_README.html @@ -310,6 +310,11 @@ a process terminates.
    Perform lookups using the LDAP protocol. Configuration details are given in the ldap_table(5).
    +
    memcache (read-write)
    + +
    Perform memcache database lookups or updates. Configuration +details are given in memcache_table(5).
    +
    mysql (read-only)
    Perform MySQL database lookups. Configuration details are given diff --git a/postfix/proto/MEMCACHE_README.html b/postfix/proto/MEMCACHE_README.html new file mode 100644 index 000000000..fbf9006c7 --- /dev/null +++ b/postfix/proto/MEMCACHE_README.html @@ -0,0 +1,113 @@ + + + + + + +Postfix memcache client Howto + + + + + + + +

    Postfix memcache client Howto

    + +
    + +

    Introduction

    + +

    The Postfix memcache client type allows you to hook up Postfix to +a memcache server. This implementation supports multiple memcache +servers for redundancy, and multiple memcache clients that you can +use for different table lookups. The Postfix memcache client +supports both lookup and update operations.

    + +

    Typically, a memcache map is used to reduce query load on a +database server, or to share a low-latency database among different +Postfix instances.

    + +

    Limitations

    + +
      + +
    • The Postfix memcache client is based on libmemcache, which +will terminate its process after a memcache server goes down. To +avoid this, set up redundant memcache servers that have no common +source of failure.

      + +
    • The Postfix memcache client cannot be used for security-sensitive +tables such as alias_maps (these may contain "|command" +and "/file/name" destinations), or virtual_uid_maps +and virtual_gid_maps (these specify UNIX process privileges). +Typically, a memcache database is shared via a TCP socket, and is +writable not only by Postfix, but by any process that can talk to +the memcache server.

      + +
    • The Postfix memcache client requires additional configuration +when used with the postscreen(8) and verify(8) daemons. For details +see the ttl parameter discussion in the memcache_table(5) +manual page.

      + +
    • The Postfix memcache client is supported only with libmemcache +version 1.4.0. Some libmemcache features are documented by reading +libmemcache source code, instead of a proper API.

      + +
    + +

    Building Postfix with memcache support

    + +

    To build Postfix with memcache client support, specify +-DHAS_MEMCACHE, the location of the libmemcache include +files, and the location of the libmemcache object library.

    + +

    For example:

    + +
    +
    +% make -f Makefile.init makefiles \
    +        'CCARGS=-DHAS_MEMCACHE -I/usr/local/include' \
    +	'AUXLIBS=-L/usr/local/lib -lmemcache'
    +
    +
    + +

    Then run 'make'.

    + +

    If the build fails with "undefined reference to `mcm_buf_len'" +(and with a similar error message for mcm_buf_remain_off), +then you need to edit libmemcache source code.

    + +

    The following instructions apply to libmemcache 1.4.0.rc2.

    + +
      + +
    • Open the libmemcache source file +include/memcache/buffer.h.

      + +
    • Delete the "inline" words before the functions +that were reported in the "undefined reference" error +messages.

      + +
    • Recompile and reinstall libmemcache.

      + +
    + +

    Then, continue building Postfix by running 'make'.

    + +

    Configuring memcache lookup tables

    + +

    Configuration is described in the memcache_table(5) manpage.

    + +

    Credits

    + +

    The first memcache client for Postfix was written by Omar Kilani.

    + +

    Wietse wrote a new memcache client from the ground up. Besides +also using libmemcache, the current implementation bears no resemblance +to Omar's work.

    + + + + diff --git a/postfix/proto/MULTI_INSTANCE_README.html b/postfix/proto/MULTI_INSTANCE_README.html index 375c58cab..fe6fc7c6d 100644 --- a/postfix/proto/MULTI_INSTANCE_README.html +++ b/postfix/proto/MULTI_INSTANCE_README.html @@ -620,7 +620,7 @@ $daemon_directory.

    $manpage_directory and $readme_directory.

  • Entries in /etc/passwd and /etc/group for the $mail_owner user and -$setgid_group group. The the $mail_owner user provides the mail system +$setgid_group group. The $mail_owner user provides the mail system with a protected (non-root) execution context. The $setgid_group group is used exclusively to support the setgid postdrop(1) and postqueue(1) utilities (it must not be the primary group or secondary group diff --git a/postfix/proto/Makefile.in b/postfix/proto/Makefile.in index 39033c17d..d71454fc0 100644 --- a/postfix/proto/Makefile.in +++ b/postfix/proto/Makefile.in @@ -23,6 +23,7 @@ HTML = ../html/ADDRESS_CLASS_README.html \ ../html/LDAP_README.html \ ../html/LINUX_README.html \ ../html/LOCAL_RECIPIENT_README.html ../html/MAILDROP_README.html \ + ../html/MEMCACHE_README.html \ ../html/MILTER_README.html \ ../html/MULTI_INSTANCE_README.html \ ../html/MYSQL_README.html ../html/NFS_README.html \ @@ -63,6 +64,7 @@ README = ../README_FILES/ADDRESS_CLASS_README \ ../README_FILES/LDAP_README \ ../README_FILES/LINUX_README \ ../README_FILES/LOCAL_RECIPIENT_README ../README_FILES/MAILDROP_README \ + ../README_FILES/MEMCACHE_README \ ../README_FILES/MILTER_README \ ../README_FILES/MULTI_INSTANCE_README \ ../README_FILES/MYSQL_README ../README_FILES/NFS_README \ @@ -199,6 +201,9 @@ clobber: ../html/MAILDROP_README.html: MAILDROP_README.html $(POSTLINK) $? >$@ +../html/MEMCACHE_README.html: MEMCACHE_README.html + $(POSTLINK) $? >$@ + ../html/MILTER_README.html: MILTER_README.html $(POSTLINK) $? >$@ @@ -355,6 +360,9 @@ clobber: ../README_FILES/MAILDROP_README: MAILDROP_README.html $(HT2READ) $? >$@ +../README_FILES/MEMCACHE_README: MEMCACHE_README.html + $(HT2READ) $? >$@ + ../README_FILES/MILTER_README: MILTER_README.html $(HT2READ) $? >$@ diff --git a/postfix/proto/TLS_README.html b/postfix/proto/TLS_README.html index caa7112f2..b2500d351 100644 --- a/postfix/proto/TLS_README.html +++ b/postfix/proto/TLS_README.html @@ -27,11 +27,6 @@ code. Assuming that OpenSSL is written as carefully as Wietse's own code, every 1000 lines introduce one additional bug into Postfix.

    -

    At this time, you should no longer be using OpenSSL releases prior -to the most recent 0.9.8 release unless all relevant security fixes have -been backported to the earlier release by you or your O/S vendor. OpenSSL -0.9.7 and earlier are no longer maintained by the OpenSSL team.

    -

    What Postfix TLS support does for you

    Transport Layer Security (TLS, formerly called SSL) provides @@ -39,11 +34,13 @@ certificate-based authentication and encrypted sessions. An encrypted session protects the information that is transmitted with SMTP mail or with SASL authentication. -

    This document describes a TLS user interface that was introduced -with Postfix version 2.3. Support for an older user interface is -documented in TLS_LEGACY_README, which also describes the differences -between Postfix and the third-party patch on which Postfix version -2.2 TLS support was based.

    +

    NOTE: This document describes a TLS +user interface that was introduced with Postfix version 2.3. Support +for an older user interface is documented in TLS_LEGACY_README, +which also describes the differences between Postfix and the +third-party patch on which Postfix version 2.2 TLS support was +based.

    Topics covered in this document:

    @@ -85,8 +82,8 @@ represent storage elements.

  • The smtpd(8) server implements the SMTP over TLS server side.

    -
  • The smtp(8) client implements the SMTP over TLS client -side.

    +
  • The smtp(8) client implements the SMTP (and LMTP) over TLS +client side.

  • The tlsmgr(8) server maintains the pseudo-random number generator (PRNG) that seeds the TLS engines in the smtpd(8) server @@ -95,6 +92,10 @@ cache files.

    +

    Not shown in the figure are the tlsproxy(8) server and the +postscreen(8) server. These use TLS in the same manner as smtpd(8). +

    +
    Network->

    For servers that are not public Internet MX hosts, Postfix @@ -389,19 +390,14 @@ since the headers may be changed by intermediate servers.

    By default, TLS is disabled in the Postfix SMTP server, so no difference to plain Postfix is visible. Explicitly switch it on -with "smtpd_tls_security_level = may" (Postfix 2.3 and -later) or "smtpd_use_tls = yes" (obsolete but still -supported).

    +with "smtpd_tls_security_level = may".

    Example:

     /etc/postfix/main.cf:
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = may
    -    # Obsolete, but still supported
    -    smtpd_use_tls = yes
     
    @@ -417,9 +413,8 @@ private key. This is intended behavior.

    You can ENFORCE the use of TLS, so that the Postfix SMTP server announces STARTTLS and accepts no mail without TLS encryption, by setting -"smtpd_tls_security_level = encrypt" (Postfix 2.3 and -later) or "smtpd_enforce_tls = yes" (obsolete but still -supported). According to RFC 2487 this MUST NOT be applied in case +"smtpd_tls_security_level = encrypt". According to RFC 2487 this +MUST NOT be applied in case of a publicly-referenced Postfix SMTP server. This option is off by default and should only seldom be used.

    @@ -428,10 +423,7 @@ by default and should only seldom be used.

     /etc/postfix/main.cf:
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = encrypt
    -    # Obsolete, but still supported
    -    smtpd_enforce_tls = yes
     
    @@ -473,7 +465,7 @@ when client certificates are requested, and abort the SMTP session. So this option is "off" by default. You will however need the certificate if you want to use certificate based relaying with, for example, the permit_tls_clientcerts feature. A server that wants client certificates -must first present its own certificate. While Postfix 2.3 by default +must first present its own certificate. While Postfix by default offers anonymous ciphers to remote SMTP clients, these are automatically suppressed when the Postfix SMTP server is configured to ask for client @@ -485,10 +477,7 @@ certificates.

     /etc/postfix/main.cf:
         smtpd_tls_ask_ccert = yes
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = may
    -    # Obsolete, but still supported
    -    smtpd_use_tls = yes
     
    @@ -505,10 +494,7 @@ logged.

     /etc/postfix/main.cf:
         smtpd_tls_req_ccert = yes
    -    # Postfix 2.3 and later
         smtpd_tls_security_level = encrypt
    -    # Obsolete, but still supported
    -    smtpd_enforce_tls = yes
     
    @@ -539,12 +525,10 @@ configured to supply its intermediate CA certificate).

    Sending AUTH data over an unencrypted channel poses a security risk. When TLS layer encryption is required -("smtpd_tls_security_level = encrypt" or the obsolete -"smtpd_enforce_tls = yes"), the Postfix SMTP server will +("smtpd_tls_security_level = encrypt"), the Postfix SMTP server will announce and accept AUTH only after the TLS layer has been activated with STARTTLS. When TLS layer encryption is optional -("smtpd_tls_security_level = may" or the obsolete -"smtpd_enforce_tls = no"), it may however still be useful +("smtpd_tls_security_level = may"), it may however still be useful to only offer AUTH when TLS is active. To maintain compatibility with non-TLS clients, the default is to accept AUTH without encryption. In order to change this behavior, set @@ -695,12 +679,6 @@ the name of the user or host:

    Server-side cipher controls

    -

    The description below is for Postfix 2.3; for Postfix < 2.3 the -smtpd_tls_cipherlist parameter specifies the acceptable ciphers as an -explicit OpenSSL cipherlist. The obsolete setting applies even when TLS -encryption is not enforced. Use of this control on public MX hosts is -strongly discouraged.

    -

    The Postfix SMTP server supports 5 distinct cipher security levels as specified by the smtpd_tls_mandatory_ciphers configuration parameter, which determines the cipher grade with mandatory TLS encryption. The @@ -732,7 +710,7 @@ smtpd_tls_mandatory_protocols configuration parameter. The corresponding smtpd_tls_protocols parameter (Postfix ≥ 2.6) controls the SSL/TLS protocols used with opportunistic TLS.

    -

    For a server that is not a public Internet MX host, Postfix (≥ 2.3) +

    For a server that is not a public Internet MX host, Postfix supports configurations with no server certificates that use only the anonymous ciphers. This is enabled by explicitly setting "smtpd_tls_cert_file = none" @@ -870,10 +848,6 @@ key configuration

  • Per-destination TLS policy -
  • Obsolete per-site TLS policy support - -
  • Closing a DNS loophole with obsolete per-site TLS policies -
  • Discovering servers that support TLS
  • Server certificate verification depth @@ -934,32 +908,26 @@ The "null" ciphers provide authentication without encryption.

    No TLS encryption

    At the "none" TLS security level, TLS encryption is -disabled. This is the default security level. With Postfix 2.3 and later, -it can be configured explicitly by setting "smtp_tls_security_level = none".

    +disabled. This is the default security level, and +can be configured explicitly by setting "smtp_tls_security_level = none". +For LMTP, use the corresponding "lmtp_" parameter.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level is set to -its default (backwards compatible) empty value, the appropriate configuration -settings are "smtp_use_tls = no" and "smtp_enforce_tls = no". -With either approach, TLS is not used even if supported by the server. -For LMTP, use the corresponding "lmtp_" parameters.

    - -

    Per destination settings may override this default setting, in which case +

    Per-destination settings may override this default setting, in which case TLS is used selectively, only with destinations explicitly configured for TLS.

    You can disable TLS for a subset of destinations, while leaving -it enabled for the rest. With the Postfix 2.3 and later TLS policy table, specify the "none" -security level. With the obsolete per-site -table, specify the "NONE" keyword.

    +security level.

    Opportunistic TLS

    At the "may" TLS security level, TLS encryption is opportunistic. The SMTP transaction is encrypted if the STARTTLS ESMTP feature is supported by the server. Otherwise, messages are sent in the clear. -With Postfix 2.3 and later, opportunistic TLS can be configured by -setting "smtp_tls_security_level = may". +Opportunistic TLS can be configured by setting "smtp_tls_security_level = may". +For LMTP, use the corresponding "lmtp_" parameter.

    Since sending in the clear is acceptable, demanding stronger than default TLS security mostly reduces inter-operability. If you @@ -970,17 +938,12 @@ and cipher grade used with opportunistic TLS. With earlier releases the opportunistic TLS cipher grade is always "export" and no protocols are disabled.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level is -set to its default (backwards compatible) empty value, the appropriate -configuration settings are "smtp_use_tls = yes" and -"smtp_enforce_tls = no". -For LMTP use the corresponding "lmtp_" parameters.

    -

    With opportunistic TLS, mail delivery continues even if the -server certificate is untrusted or bears the wrong name. Starting -with Postfix 2.3, when the TLS handshake fails for an opportunistic -TLS session, rather than give up on mail delivery, the transaction -is retried with TLS disabled. Trying an unencrypted connection makes +server certificate is untrusted or bears the wrong name. +When the TLS handshake fails for an opportunistic +TLS session, rather than give up on mail delivery, the Postfix SMTP +client retries the transaction +with TLS disabled. Trying an unencrypted connection makes it possible to deliver mail to sites with non-interoperable server TLS implementations.

    @@ -994,9 +957,8 @@ Attempts to configure opportunistic encryption of LMTP sessions will be ignored with a warning written to the mail logs.

    You can enable opportunistic TLS just for selected destinations. With -the Postfix 2.3 and later TLS policy table, -specify the "may" security level. With the obsolete per-site table, specify the "MAY" keyword.

    +the Postfix TLS policy table, +specify the "may" security level.

    This is the most common security level for TLS protected SMTP sessions, stronger security is not generally available and, if needed, @@ -1012,27 +974,18 @@ on TLS limitations above.

    -

    Postfix 2.2 syntax:

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_use_tls = yes
    -    smtp_enforce_tls = no
    -
    -
    -

    Mandatory TLS encryption

    At the "encrypt" TLS security level, messages are sent only over TLS encrypted sessions. The SMTP transaction is aborted unless the STARTTLS ESMTP feature is supported by the remote SMTP server. If no suitable -servers are found, the message will be deferred. With Postfix 2.3 -and later, mandatory TLS encryption can be configured by setting +servers are found, the message will be deferred. +Mandatory TLS encryption can be configured by setting "smtp_tls_security_level = encrypt". Even though TLS encryption is always used, mail delivery continues even if the server -certificate is untrusted or bears the wrong name.

    +certificate is untrusted or bears the wrong name. +For LMTP, use the corresponding "lmtp_" parameter.

    At this security level and higher, the smtp_tls_mandatory_protocols and smtp_tls_mandatory_ciphers configuration parameters determine @@ -1042,12 +995,6 @@ met, the mail transaction is aborted. The documentation for these parameters includes useful interoperability and security guidelines.

    -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" -and "smtp_tls_enforce_peername = no". For LMTP use the corresponding -"lmtp_" parameters.

    -

    Despite the potential for eliminating passive eavesdropping attacks, mandatory TLS encryption is not viable as a default security level for mail delivery to the public Internet. Most MX hosts do not support TLS at @@ -1056,12 +1003,9 @@ that delivers mail to the Internet, you should not configure mandatory TLS encryption as the default security level.

    You can enable mandatory TLS encryption just for specific destinations. -With the Postfix 2.3 and later TLS policy -table, specify the "encrypt" security level. With the -obsolete per-site table, specify the -"MUST_NOPEERMATCH" keyword. While the obsolete approach still works -with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 and later -should use the new TLS policy settings.

    +With the Postfix TLS policy +table, specify the "encrypt" security level. +

    Examples:

    @@ -1083,20 +1027,6 @@ level sessions.

    -

    Postfix 2.2 syntax (no support for sub-domains without resorting to -regexp tables). With Postfix 2.3 and later, do not use the obsolete per-site table.

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    example.com       MUST_NOPEERMATCH
    -
    -
    -

    In the next example, secure message submission is configured via the MSA "[example.net]:587". TLS sessions are encrypted without authentication, because this MSA does not possess an acceptable @@ -1128,28 +1058,6 @@ just in case the transport table entries are not specified consistently.

    -

    Postfix 2.2 syntax:

    - -

    Note: Avoid policy lookups with the bare hostname (for -example, "example.net"). Instead, -use the destination (for example, "[example.net]:587"), as the per-site table lookup key (a recipient domain -or MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -do not use the obsolete per-site table; -use the new policy table instead.

    - -
    -
    -/etc/postfix/main.cf:
    -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    [example.net]:587   MUST_NOPEERMATCH
    -
    -
    -

    Certificate fingerprint verification

    Certificate fingerprint verification is available with Postfix @@ -1234,13 +1142,8 @@ server certificate verification can be configured by setting smtp_tls_verify_cert_match parameter can override the default "hostname" certificate name matching strategy. Fine-tuning the matching strategy is generally only appropriate for secure-channel destinations.

    - -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" and -"smtp_tls_enforce_peername = yes". For LMTP use the corresponding -"lmtp_" parameters.

    +href="#client_tls_secure">secure-channel destinations. +For LMTP use the corresponding "lmtp_" parameters.

    If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName @@ -1269,12 +1172,9 @@ href="#client_tls_secure">secure-channel configuration instead.

    You can enable mandatory server certificate verification just -for specific destinations. With the Postfix 2.3 and later TLS policy table, specify the "verify" -security level. With the obsolete per-site -table, specify the "MUST" keyword. While the obsolete approach -still works with Postfix 2.3, it is strongly discouraged: users of -Postfix 2.3 and later should use the new TLS policy settings.

    +security level.

    Example:

    @@ -1295,36 +1195,16 @@ to example.com recipients uses "high" grade ciphers.

    -

    Postfix 2.2 syntax:

    -
    -
    -/etc/postfix/main.cf:
    -    indexed = ${default_database_type}:${config_directory}/
    -    smtp_tls_CAfile = ${config_directory}/CAfile.pem
    -    smtp_tls_per_site = ${indexed}tls_per_site
    -
    -/etc/postfix/tls_per_site:
    -    example.com         MUST
    -
    -
    -

    Secure server certificate verification

    At the secure TLS security level, messages are sent only over secure-channel TLS sessions where DNS forgery resistant server certificate verification succeeds. If no suitable servers are found, the -message will be deferred. With Postfix 2.3 and later, secure-channels +message will be deferred. Postfix secure-channels can be configured by setting "smtp_tls_security_level = secure". The smtp_tls_secure_cert_match parameter can override the default -"nexthop, dot-nexthop" certificate match strategy.

    - -

    With Postfix 2.2 and earlier, or when smtp_tls_security_level -is set to its default (backwards compatible) empty value, the -appropriate configuration settings are "smtp_enforce_tls = yes" -and "smtp_tls_enforce_peername = yes" with additional settings to -harden peer certificate verification -against forged DNS data. For LMTP, use the corresponding "lmtp_" -parameters.

    +"nexthop, dot-nexthop" certificate match strategy. +For LMTP, use the corresponding "lmtp_" parameters.

    If the server certificate chain is trusted (see smtp_tls_CAfile and smtp_tls_CApath), any DNS names in the SubjectAlternativeName certificate @@ -1351,18 +1231,14 @@ sends all email to a central mailhub that offers the necessary STARTTLS support.

    You can enable secure TLS verification just for specific destinations. -With the Postfix 2.3 and later TLS policy table, -specify the "secure" security level. With the obsolete -per-site table, specify the "MUST" -keyword and harden the certificate -verification against DNS forgery. While the obsolete approach still -works with Postfix 2.3, it is strongly discouraged: users of Postfix 2.3 -and later -should use the new TLS policy settings.

    +With the Postfix TLS policy table, +specify the "secure" security level.

    Examples:

    -

    Secure-channel TLS without transport(5) table overrides:

    +
      + +
    • Secure-channel TLS without transport(5) table overrides:

      The Postfix SMTP client will encrypt all traffic and verify the destination name @@ -1408,18 +1284,14 @@ the first approach is more appropriate in most cases.

      -

      Secure-channel TLS with transport(5) table overrides:

      +

    • Secure-channel TLS with transport(5) table overrides:

      In this case traffic to example.com and its related domains is sent to a single logical gateway (to avoid a single point of failure, its name may resolve to one or more load-balancer addresses, or to the combined addresses of multiple physical hosts). All the physical hosts reachable via the gateway's IP addresses have the logical gateway name -listed in their certificates. This secure-channel configuration can also -be implemented via a hardened variant of -the MUST policy in the obsolete per-site -table. As stated above, this approach has the potential to mis-deliver -email if the related domains change hands.

      +listed in their certificates.

      @@ -1438,35 +1310,7 @@ email if the related domains change hands. 

      -

      Postfix 2.2.9 and later syntax:

      - -

      Note: Avoid policy lookups with the bare hostname (for -example, "tls.example.com"). Instead, use the destination (for -example, "[tls.example.com]") as the per-site table lookup key (a recipient domain -or MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -do not use the obsolete per-site table; -use the new policy table instead.

      - -
      -
      -/etc/postfix/main.cf:
      -    smtp_cname_overrides_servername = no
      -    smtp_tls_CAfile = /etc/postfix/CAfile.pem
      -    transport_maps = hash:/etc/postfix/transport
      -    smtp_tls_per_site = hash:/etc/postfix/tls_per_site
      -
      -/etc/postfix/transport:
      -    example.com     smtp:[tls.example.com]
      -    example.co.uk   smtp:[tls.example.com]
      -    example.co.jp   smtp:[tls.example.com]
      -
      -/etc/postfix/tls_per_site:
      -    [tls.example.com]       MUST
      -
      -
      +

    Client-side TLS activity logging

    @@ -1778,9 +1622,9 @@ constraints on the sending and receiving sites that preclude ubiquitous deployment. One needs to manually configure this type of security for each destination domain, and in many cases implement non-default TLS policy table entries for additional -domains hosted at a common secured destination. With Postfix 2.3, we -make secure-channel configurations substantially easier to configure, -but they will never be the norm. For the generic domain with which you +domains hosted at a common secured destination. For these reasons +secure-channel configurations +will never be the norm. For the generic domain with which you have made no specific security arrangements, this security level is not a good fit.

    @@ -1790,7 +1634,7 @@ TLS use self-signed certificates or private CAs. This further limits the applicability of verified TLS on the public Internet.

    Historical note: while the documentation of these issues and many of the -related features are new with Postfix 2.3, the issue was well +related features were new with Postfix 2.3, the issue was well understood before Postfix 1.0, when Lutz Jänicke was designing the first unofficial Postfix TLS patch. See his original post http://www.imc.org/ietf-apps-tls/mail-archive/msg00304.html @@ -1803,23 +1647,15 @@ uses indirect naming (via MX records) more frequently.

    TLS policy table

    -

    The current TLS policy table was introduced with Postfix 2.3. For -earlier releases, read the description of the obsolete Postfix 2.2 per-site table.

    -

    A small fraction of servers offer STARTTLS but the negotiation -consistently fails. With Postfix 2.3, so long as encryption is not -enforced, the delivery is immediately retried with TLS disabled. You no -longer need to explicitly disable TLS for the problem destinations. -As soon as their TLS software or configuration is repaired, encryption -will be used.

    +consistently fails. As long as encryption is not mandatory, the +Postfix SMTP client retries the delivery immediately with TLS +disabled, without any need to explicitly disable TLS for the problem +destinations.

    -

    The new policy table is specified via the smtp_tls_policy_maps +

    The policy table is specified via the smtp_tls_policy_maps parameter. This lists optional lookup tables with the Postfix SMTP client -TLS security policy by next-hop destination. When $smtp_tls_policy_maps -is not empty, the obsolete smtp_tls_per_site parameter is ignored -(a warning is written to the logs if both parameter values are -non-empty).

    +TLS security policy by next-hop destination.

    The TLS policy table is indexed by the full next-hop destination, which is either the recipient domain, or the verbatim next-hop @@ -1968,211 +1804,6 @@ 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.

    -

    Obsolete per-site TLS policy support -

    - -

    This section describes an obsolete per-site TLS policy mechanism. -Unlike the Postfix 2.3 policy table -mechanism, this uses as a policy lookup key a potentially untrusted -server hostname, and lacks control over what names can appear in -server certificates. Because of this, the obsolete mechanism is -typically vulnerable to false DNS hostname information in MX or -CNAME records. These attacks can be eliminated only with great -difficulty. The new policy table -makes secure-channel configurations -easier and provides more control over the cipher and protocol selection -for sessions with mandatory encryption.

    - -

    Avoid policy lookups with the bare hostname. Instead, use the -full destination nexthop (enclosed in [] with a possible ":port" -suffix) as the per-site table lookup key (a recipient domain or -MX-enabled transport nexthop with no port suffix may look like a bare -hostname, but is still a suitable destination). With Postfix 2.3 -and later, -use of the obsolete approach documented here is strongly discouraged: -use the new policy table instead.

    - -

    Starting with Postfix 2.3, the underlying TLS enforcement levels are -common to the obsolete per-site table and the new policy table. The -main.cf smtp_tls_mandatory_ciphers and smtp_tls_mandatory_protocols -parameters control the TLS ciphers and protocols for mandatory -encryption regardless of which table is used. The -smtp_tls_verify_cert_match parameter determines the match strategy -for the obsolete "MUST" keyword in the same way as for the "verify" -level in the new policy.

    - -

    With Postfix < 2.3, the obsolete smtp_tls_cipherlist parameter -is also applied for opportunistic TLS sessions, and should be used with -care, or not at all. Setting cipherlist restrictions that are incompatible -with a remote SMTP server render that server unreachable, TLS handshakes -are always attempted and always fail.

    - -

    When smtp_tls_policy_maps is empty (default) and smtp_tls_per_site -is not empty, the per-site table is searched for a policy that matches -the following information:

    - -
    - -
    - -
    remote SMTP server hostname
    This is simply the DNS -name of the server that the Postfix SMTP client connects to; this -name may be obtained from other DNS lookups, such as MX lookups or -CNAME lookups. Use of the hostname lookup key is discouraged; always -use the next-hop destination instead.
    - -
    next-hop destination
    This is normally the domain portion -of the recipient address, but it may be overridden by information from -the transport(5) table, from the relayhost parameter setting, or from -the relay_transport setting. When it is not the recipient domain, the -next-hop destination can have the Postfix-specific form "[name]", -"[name]:port", "name" or "name:port". This is -the recommended lookup key for per-site policy lookups (and incidentally -for SASL password lookups).
    - -
    - -
    - -

    When both the hostname lookup and the next-hop lookup succeed, -the host policy does not automatically override the next-hop policy. -Instead, precedence is given to either the more specific or the -more secure per-site policy as described below.

    - -

    The smtp_tls_per_site table uses a simple "name whitespace -value" format. Specify host names or next-hop destinations on -the left-hand side; no wildcards are allowed. On the right hand -side specify one of the following keywords:

    - -
    - -
    - -
    NONE
    No TLS. This overrides a less specific "MAY" lookup -result from the alternate host or next-hop lookup key, and overrides -the global smtp_use_tls, smtp_enforce_tls, and smtp_tls_enforce_peername -settings.
    - -
    MAY
    Opportunistic TLS. This has less precedence than -a more specific result (including "NONE") from the alternate host or -next-hop lookup key, and has less precedence than the more specific global -"smtp_enforce_tls = yes" or "smtp_tls_enforce_peername = yes".
    - -
    MUST_NOPEERMATCH
    Mandatory TLS encryption. This -overrides a less secure "NONE" or a less specific "MAY" lookup result -from the alternate host or next-hop lookup key, and overrides the global -smtp_use_tls, smtp_enforce_tls and smtp_tls_enforce_peername settings. -
    - -
    MUST
    Mandatory server certificate verification. -This overrides a less secure "NONE" and "MUST_NOPEERMATCH" or a -less specific "MAY" lookup result from the alternate host or next-hop -lookup key, and overrides the global smtp_use_tls, smtp_enforce_tls -and smtp_tls_enforce_peername settings.
    - -
    - -
    - -

    The precedences between global (main.cf) and per-site TLS -policies can be summarized as follows:

    - -
      - -
    • When neither the remote SMTP server hostname nor the -next-hop destination are found in the smtp_tls_per_site table, the -policy is based on smtp_use_tls, smtp_enforce_tls and -smtp_tls_enforce_peername. Note: "smtp_enforce_tls = yes" and -"smtp_tls_enforce_peername = yes" imply "smtp_use_tls = yes".

      - -
    • When both hostname and next-hop destination lookups produce -a result, the more specific per-site policy (NONE, MUST, etc) -overrides the less specific one (MAY), and the more secure per-site -policy (MUST, etc) overrides the less secure one (NONE).

      - -
    • After the per-site policy lookups are combined, the result -generally overrides the global policy. The exception is the less -specific "MAY" per-site policy, which is overruled by the more -specific global "smtp_enforce_tls = yes" with server certificate -verification as specified with the smtp_tls_enforce_peername -parameter.

      - -
    - -

    Closing a DNS loophole with -obsolete per-site TLS policies

    - -

    For a general discussion of TLS security for SMTP see TLS limitations above. What follows applies -only to Postfix 2.2.9 and subsequent Postfix 2.2 patch levels. Do -not use this approach with Postfix 2.3 -and later; instead see the instructions under secure server certificate verification.

    - -

    As long as no secure DNS lookup mechanism is available, false -hostnames in MX or CNAME responses can change Postfix's notion of the -server hostname that is used for TLS policy lookup and server certificate -verification. Even with a perfect match between the server hostname and -the server certificate, there is no guarantee that Postfix is connected -to the right server. To avoid this loophole, take all of the following -steps:

    - -
      - -
    1. Use a dedicated message delivery transport (for example, -"securetls") as illustrated below.

      - -
    2. Eliminate MX lookups. Specify local transport(5) table -entries for sensitive domains with explicit securetls:[mailhost] -or securetls:[mailhost]:port destinations (you can -assure security of this table unlike DNS). This prevents false -hostname information in DNS MX records from changing Postfix's -notion of the server hostname that is used for TLS policy lookup -and server certificate verification. The "securetls" transport is -configured to enforce TLS with peername verification, and to disable -the SMTP connection cache which could interfere with enforcement -of smtp_tls_per_site policies.

      - -
    3. Disallow CNAME hostname overrides. In main.cf, specify -"smtp_cname_overrides_servername = no". This prevents false hostname -information in DNS CNAME records from changing the server hostname -that Postfix uses for TLS policy lookup and server certificate -verification. This feature requires Postfix 2.2.9 or later. The -default value is "no" starting with Postfix 2.3.

      - -
    - -

    Example:

    - -

    We give the non-default -"securetls" transport an explicit master.cf process limit, so that we -don't raise its process limit when raising $default_process_limit. The -total process limit for *all* transports should stay somewhat under 1024 -(the typical select() file descriptor limit); otherwise transports may -be throttled under steady high load, compounding congestion. It is not -uncommon at high volume sites to set the default process limit to 500 -or more.

    - -

    We also default the "securetls" transport TLS security level to -MUST, obviating the need for per-site table entries for secure-channel -destinations.

    - -
    -
    -/etc/postfix/main.cf:
    -    transport_maps = hash:/etc/postfix/transport
    -
    -/etc/postfix/transport:
    -    example.com         securetls:[tls.example.com]
    -
    -/etc/postfix/master.cf:
    -    securetls unix  -       -       n       -       100     smtp
    -        -o smtp_enforce_tls=yes
    -        -o smtp_tls_enforce_peername=yes
    -
    -
    -

    Discovering servers that support TLS

    @@ -2601,10 +2232,7 @@ but don't require them from all clients.

    smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_tls_session_cache tls_random_source = dev:/dev/urandom - # Postfix 2.3 and later smtpd_tls_security_level = may - # Obsolete, but still supported - smtpd_use_tls = yes diff --git a/postfix/proto/TUNING_README.html b/postfix/proto/TUNING_README.html index 5c7b5b39b..09a362a96 100644 --- a/postfix/proto/TUNING_README.html +++ b/postfix/proto/TUNING_README.html @@ -551,13 +551,13 @@ mail deliveries.

    The default_process_limit configuration parameter gives direct control over how many daemon processes Postfix will run. As of -Postfix 2.0 the default limit is 100 smtp client processes, 100 -smtp server processes, and so on. This may overwhelm systems with +Postfix 2.0 the default limit is 100 SMTP client processes, 100 +SMTP server processes, and so on. This may overwhelm systems with little memory, as well as networks with low bandwidth.

    You can change the global process limit by specifying a non-default default_process_limit in the main.cf file. For example, -to run up to 10 smtp client processes, 10 smtp server processes, +to run up to 10 SMTP client processes, 10 SMTP server processes, and so on:

    diff --git a/postfix/proto/memcache_table b/postfix/proto/memcache_table new file mode 100644 index 000000000..83d687a39 --- /dev/null +++ b/postfix/proto/memcache_table @@ -0,0 +1,169 @@ +#++ +# NAME +# memcache_table 5 +# SUMMARY +# Postfix memcache client configuration +# SYNOPSIS +# \fBpostmap -q "\fIstring\fB" memcache:/etc/postfix/filename\fR +# +# \fBpostmap -q - memcache:/etc/postfix/\fIfilename\fR <\fIinputfile\fR +# 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, lookup tables can be specified as memcache +# instances. In order to use memcache lookups, define a +# memcache source as a lookup table in main.cf, for example: +# +# .nf +# virtual_alias_maps = memcache:/etc/postfix/memcache-aliases.cf +# .fi +# +# The file /etc/postfix/memcache-aliases.cf has the same +# format as the Postfix main.cf file, and specifies the +# parameters described below. +# +# The Postfix memcache client supports the lookup and update +# operations. +# MEMCACHE PARAMETERS +# .ad +# .fi +# .IP "\fBhosts (default: localhost:11211)\fR" +# The memcache servers that Postfix will try to connect to. +# Specify a hostname or address, optionally followed by ":" +# and a port name or number. The default port is 11211. +# Examples: +# +# .nf +# hosts = memcache01.example.com +# memcache02.example.com +# .fi +# .IP "\fBkey_format (default: %s)\fB" +# Format of the lookup and update keys in memcache queries. +# By default, these are the same as the lookup and update +# keys that are given to the Postfix memcache client. +# +# When the same memcache database is used to cache information +# from multiple tables, you can use the \fBkey_format\fR +# feature to avoid name collisions by prepending a fixed +# string. Examples: +# +# .nf +# key_format = aliases:%s +# key_format = access:%s +# .fi +# +# The \fBkey_format\fR parameter supports the following '%' +# expansions: +# .RS +# .IP "\fB\fB%%\fR\fR" +# This is replaced by a literal '%' character. +# .IP "\fB\fB%s\fR\fR" +# This is replaced by the memcache client input key. +# .IP "\fB\fB%u\fR\fR" +# When the input key is an address of the form user@domain, +# \fB%u\fR is replaced by the SQL quoted local part of the +# address. Otherwise, \fB%u\fR 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). +# .IP "\fB\fB%d\fR\fR" +# When the input key is an address of the form user@domain, +# \fB%d\fR is replaced by the domain part of the address. +# Otherwise, a lookup is silently suppressed and returns no +# results (an update is skipped with a warning). +# .IP "\fB\fB%[SUD]\fR\fR" +# The upper-case equivalents of the above expansions behave +# in the \fBkey_format\fR parameter identically to their +# lower-case counter-parts. +# .IP "\fB\fB%[1-9]\fR\fR" +# The patterns %1, %2, ... %9 are replaced by the corresponding +# most significant component of the input key's domain. If +# the input key is \fIuser@mail.example.com\fR, then %1 is +# \fBcom\fR, %2 is \fBexample\fR and %3 is \fBmail\fR. 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 skipped with a warning). +# .RE +# .IP "\fBdomain (default: no domain list)\fR" +# This feature can significantly reduce database server load. +# Specify a list of domain names, paths to files, or dictionaries. +# 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: +# +# .nf +# domain = example.com, hash:/etc/postfix/searchdomains +# .fi +# .IP "\fBflags (default: 0)\fR" +# Optional flags that should be stored along with a memcache +# update. +# .IP "\fBttl (default: 604800)\fR" +# The expiration time in seconds of memcache updates. +# The default is one week. +# +# When using memcache tables with \fBpostscreen\fR(8) or +# \fBverify\fR(8), specify a zero *_cache_cleanup_interval +# value, and specify the largest \fBpostscreen\fR(8) *_ttl +# value or \fBverify\fR(8) *_expire_time value as the memcache +# map's \fBttl\fR value. +# +# Note: 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. +# BUGS +# The Postfix memcache client is based on libmemcache, which +# will terminate its process after a memcache server goes +# down. To avoid this, set up redundant memcache servers that +# have no common source of failure. +# +# The Postfix memcache client cannot be used for security-sensitive +# tables such as \fBalias_maps\fR (these may contain +# "\fI|command\fR and "\fI/file/name\fR" destinations), or +# \fBvirtual_uid_maps\fR and \fBvirtual_gid_maps\fR (these +# specify UNIX process privileges). In a typical deployment +# a memcache database is shared via a TCP socket, and is +# therefore writable not only by Postfix, but by any process +# that can talk to the memcache server. +# +# The Postfix memcache client requires additional configuration +# when used with the \fBpostscreen\fR(8) and \fBverify\fR(8) +# daemons. For details see the \fBttl\fR parameter discussion +# at the end of the MEMCACHE PARAMETERS section in this +# document. +# +# The Postfix memcache client is supported only with libmemcache +# version 1.4.0. Some libmemcache features are documented +# by reading libmemcache source code, instead a proper API. +# SEE ALSO +# postmap(1), Postfix lookup table manager +# postconf(5), configuration parameters +# README FILES +# .ad +# .fi +# Use "\fBpostconf readme_directory\fR" or +# "\fBpostconf html_directory\fR" to locate this information. +# .na +# .nf +# DATABASE_README, Postfix lookup table overview +# MEMCACHE_README, Postfix memcache client guide +# LICENSE +# .ad +# .fi +# The Secure Mailer license must be distributed with this software. +# HISTORY +# .ad +# .fi +# The first memcache client for Postfix was written by Omar +# Kilani. Besides being implemented on libmemcache, this +# implementation bears no resemblance to his work. +# AUTHOR(S) +# Wietse Venema +# IBM T.J. Watson Research +# P.O. Box 704 +# Yorktown Heights, NY 10598, USA +#-- diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 365b5b1ad..489027763 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -30,7 +30,8 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \ fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \ - smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c + smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \ + dict_memcache.c mail_version.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 \ @@ -62,7 +63,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \ fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \ - smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o + smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \ + dict_memcache.o mail_version.o HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \ conv_time.h db_common.h debug_peer.h debug_process.h defer.h \ @@ -88,7 +90,7 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ verp_sender.h wildcard_inet_addr.h xtext.h delivered_hdr.h \ fold_addr.h header_body_checks.h data_redirect.h match_service.h \ addr_match_list.h smtp_reply_footer.h safe_ultostr.h \ - verify_sender_addr.h + verify_sender_addr.h dict_memcache.h TESTSRC = rec2stream.c stream2rec.c recdump.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) @@ -101,7 +103,8 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \ quote_821_local mail_conf_time mime_state strip_addr \ verify_clnt xtext anvil_clnt scache ehlo_mask \ valid_mailhost_addr own_inet_addr header_body_checks \ - data_redirect addr_match_list safe_ultostr verify_sender_addr + data_redirect addr_match_list safe_ultostr verify_sender_addr \ + mail_version mail_dict LIBS = ../../lib/libutil.a LIB_DIR = ../../lib @@ -293,9 +296,16 @@ safe_ultostr: safe_ultostr.c $(LIB) $(LIBS) verify_sender_addr: verify_sender_addr.c $(LIB) $(LIBS) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) +mail_version: mail_version.c $(LIB) $(LIBS) + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) + +mail_dict: mail_dict.c $(LIB) $(LIBS) + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) + tests: tok822_test mime_tests strip_addr_test tok822_limit_test \ xtext_test scache_multi_test ehlo_mask_test \ - namadr_list_test mail_conf_time_test header_body_checks_tests + namadr_list_test mail_conf_time_test header_body_checks_tests \ + mail_version_test 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 @@ -387,6 +397,11 @@ xtext_test: xtext cmp xtext.ref xtext.tmp rm -f xtext.ref xtext.tmp +mail_version_test: mail_version mail_version.in mail_version.ref + ./mail_version mail_version.tmp + diff mail_version.ref mail_version.tmp + rm -f mail_version.tmp + # Requires: Postfix running, root privileges rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref @@ -850,6 +865,23 @@ dict_ldap.o: dict_ldap.c dict_ldap.o: dict_ldap.h dict_ldap.o: mail_conf.h dict_ldap.o: string_list.h +dict_memcache.o: ../../include/argv.h +dict_memcache.o: ../../include/binhash.h +dict_memcache.o: ../../include/dict.h +dict_memcache.o: ../../include/match_list.h +dict_memcache.o: ../../include/match_ops.h +dict_memcache.o: ../../include/msg.h +dict_memcache.o: ../../include/mymalloc.h +dict_memcache.o: ../../include/stringops.h +dict_memcache.o: ../../include/sys_defs.h +dict_memcache.o: ../../include/vbuf.h +dict_memcache.o: ../../include/vstream.h +dict_memcache.o: ../../include/vstring.h +dict_memcache.o: cfg_parser.h +dict_memcache.o: db_common.h +dict_memcache.o: dict_memcache.c +dict_memcache.o: dict_memcache.h +dict_memcache.o: string_list.h dict_mysql.o: ../../include/argv.h dict_mysql.o: ../../include/dict.h dict_mysql.o: ../../include/events.h @@ -1302,6 +1334,7 @@ mail_dict.o: ../../include/vbuf.h mail_dict.o: ../../include/vstream.h mail_dict.o: ../../include/vstring.h mail_dict.o: dict_ldap.h +mail_dict.o: dict_memcache.h mail_dict.o: dict_mysql.h mail_dict.o: dict_pgsql.h mail_dict.o: dict_proxy.h @@ -1437,7 +1470,14 @@ mail_trigger.o: ../../include/vstream.h mail_trigger.o: mail_params.h mail_trigger.o: mail_proto.h mail_trigger.o: mail_trigger.c +mail_version.o: ../../include/mymalloc.h +mail_version.o: ../../include/split_at.h +mail_version.o: ../../include/stringops.h +mail_version.o: ../../include/sys_defs.h +mail_version.o: ../../include/vbuf.h +mail_version.o: ../../include/vstring.h mail_version.o: mail_version.c +mail_version.o: mail_version.h maps.o: ../../include/argv.h maps.o: ../../include/dict.h maps.o: ../../include/msg.h @@ -1520,7 +1560,15 @@ mime_state.o: mail_params.h mime_state.o: mime_state.c mime_state.o: mime_state.h mime_state.o: rec_type.h +mkmap_cdb.o: ../../include/argv.h +mkmap_cdb.o: ../../include/dict.h +mkmap_cdb.o: ../../include/dict_cdb.h +mkmap_cdb.o: ../../include/mymalloc.h mkmap_cdb.o: ../../include/sys_defs.h +mkmap_cdb.o: ../../include/vbuf.h +mkmap_cdb.o: ../../include/vstream.h +mkmap_cdb.o: ../../include/vstring.h +mkmap_cdb.o: mkmap.h mkmap_cdb.o: mkmap_cdb.c mkmap_db.o: ../../include/argv.h mkmap_db.o: ../../include/dict.h diff --git a/postfix/src/global/db_common.c b/postfix/src/global/db_common.c index 6a2fa4bec..4dbeedb93 100644 --- a/postfix/src/global/db_common.c +++ b/postfix/src/global/db_common.c @@ -49,6 +49,9 @@ /* value indicates that data-depedent '%' expansions were found in the input /* template. /* +/* db_common_alloc() provides a way to use db_common_parse_domain() +/* etc. without prior db_common_parse() call. +/* /* \fIdb_common_expand\fR expands the specifiers in \fIformat\fR. /* When the input data lacks all fields needed for the expansion, zero /* is returned and the query or result should be skipped. Otherwise @@ -163,6 +166,20 @@ typedef struct { int nparts; } DB_COMMON_CTX; +/* db_common_alloc - allocate db_common context */ + +void *db_common_alloc(DICT *dict) +{ + DB_COMMON_CTX *ctx; + + ctx = (DB_COMMON_CTX *) mymalloc(sizeof *ctx); + ctx->dict = dict; + ctx->domain = 0; + ctx->flags = 0; + ctx->nparts = 0; + return ((void *) ctx); +} + /* db_common_parse - validate query or result template */ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query) @@ -171,13 +188,9 @@ int db_common_parse(DICT *dict, void **ctxPtr, const char *format, int query const char *cp; int dynamic = 0; - if (ctx == 0) { - ctx = (DB_COMMON_CTX *) (*ctxPtr = mymalloc(sizeof *ctx)); - ctx->dict = dict; - ctx->domain = 0; - ctx->flags = 0; - ctx->nparts = 0; - } + if (ctx == 0) + ctx = (DB_COMMON_CTX *) (*ctxPtr = db_common_alloc(dict)); + for (cp = format; *cp; ++cp) if (*cp == '%') switch (*++cp) { diff --git a/postfix/src/global/db_common.h b/postfix/src/global/db_common.h index ce7adc1e1..26ebf9731 100644 --- a/postfix/src/global/db_common.h +++ b/postfix/src/global/db_common.h @@ -21,6 +21,7 @@ typedef void (*db_quote_callback_t)(DICT *, const char *, VSTRING *); extern int db_common_parse(DICT *, void **, const char *, int); +extern void *db_common_alloc(DICT *); extern void db_common_parse_domain(CFG_PARSER *, void *); extern int db_common_dict_partial(void *); extern int db_common_expand(void *, const char *, const char *, diff --git a/postfix/src/global/dict_memcache.c b/postfix/src/global/dict_memcache.c new file mode 100644 index 000000000..ee3c33c6a --- /dev/null +++ b/postfix/src/global/dict_memcache.c @@ -0,0 +1,493 @@ +/*++ +/* NAME +/* dict_memcache 3 +/* SUMMARY +/* dictionary interface to memcache databases +/* SYNOPSIS +/* #include +/* +/* DICT *dict_memcache_open(name, open_flags, dict_flags) +/* const char *name; +/* int open_flags; +/* int dict_flags; +/* DESCRIPTION +/* dict_memcache_open() opens a memcache database, providing +/* a dictionary interface for Postfix key->value mappings. +/* The result is a pointer to the installed dictionary. +/* +/* Configuration parameters are described in memcache_table(5). +/* +/* Arguments: +/* .IP name +/* Either the path to the Postfix memcache configuration file +/* (if it starts with '/' or '.'), or the parameter name prefix +/* which will be used to obtain main.cf configuration parameters. +/* .IP open_flags +/* O_RDONLY or O_RDWR. This function ignores flags that don't +/* specify a read, write or append mode. +/* .IP dict_flags +/* See dict_open(3). +/* SEE ALSO +/* dict(3) generic dictionary manager +/* BUGS +/* This code requires libmemcache 1.4.0, because some parts +/* of their API are documented by looking at the implementation. +/* HISTORY +/* The first memcache client for Postfix was written by: +/* Omar Kilani +/* omar@tinysofa.com +/* This implementation bears no resemblance to his work. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include "sys_defs.h" + +#ifdef HAS_MEMCACHE +#include +#include + +#if !defined(MEMCACHE_VERNUM) || MEMCACHE_VERNUM != 10400 +#error "Postfix memcache supports only libmemcache version 1.4.0" +#endif + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include + +/* Application-specific. */ + +#include + + /* + * Robustness tests (with a single memcache server) proved disappointing. + * + * After failure to connect to the memcache server, libmemcache reports the + * error once. From then on it silently discards all updates and always + * reports "not found" for all lookups, without ever reporting an error. To + * avoid this, we destroy the memcache client and create a new one after + * libmemcache reports an error. + * + * Even more problematic is that libmemcache will terminate the process when + * the memcache server connection is lost (the libmemcache error message is: + * "read(2) failed: Socket is already connected"). Unfortunately, telling + * libmemcache not to terminate the process will result in an assertion + * failure followed by core dump. + * + * Conclusion: if we want robust code, then we should use our own memcache + * protocol implementation instead of libmemcache. + */ + + /* + * Structure of one memcache dictionary handle. + */ +typedef struct { + DICT dict; /* parent class */ + struct memcache_ctxt *mc_ctxt; /* libmemcache context */ + struct memcache *mc; /* libmemcache object */ + CFG_PARSER *parser; /* common parameter parser */ + void *dbc_ctxt; /* db_common context */ + char *key_format; /* query key translation */ + int mc_ttl; /* memcache expiration */ + int mc_flags; /* memcache flags */ + VSTRING *key_buf; /* lookup key */ + VSTRING *res_buf; /* lookup result */ +} DICT_MC; + + /* + * Default memcache options. + */ +#define DICT_MC_DEF_HOST "localhost" +#define DICT_MC_DEF_PORT "11211" +#define DICT_MC_DEF_HOST_PORT DICT_MC_DEF_HOST ":" DICT_MC_DEF_PORT +#define DICT_MC_DEF_KEY_FMT "%s" +#define DICT_MC_DEF_TTL (7 * 86400) +#define DICT_MC_DEF_FLAGS 0 + + /* + * libmemcache can report errors through an application call-back function, + * but there is no support for passing application context to the call-back. + * The call-back API has two documented arguments: pointer to memcache_ctxt, + * and pointer to memcache_ectxt. The memcache_ctxt data structure has no + * space for application context, and the mcm_err() function zero-fills the + * memcache_ectxt data structure, making it useless for application context. + * + * We use our own hash table to find our dictionary handle, so that we can + * report errors in the proper context. + */ +static BINHASH *dict_mc_hash; + + /* + * SLMs. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + +/*#define msg_verbose 1*/ + +/* dict_memcache_error_cb - error call-back */ + +static int dict_memcache_error_cb(MCM_ERR_FUNC_ARGS) +{ + const char *myname = "dict_memcache_error_cb"; + const struct memcache_ctxt *ctxt; + struct memcache_err_ctxt *ectxt; + DICT_MC *dict_mc; + void (*log_fn) (const char *,...); + + /* + * Play by the rules of the libmemcache API. + */ + MCM_ERR_INIT_CTXT(ctxt, ectxt); + + /* + * Locate our own dictionary handle for error reporting context. + * Unfortunately, the ctxt structure does not store application context, + * and mcm_err() zero-fills the ectxt structure, making it useless for + * storing application context. We use our own hash table instead. + */ + if ((dict_mc = (DICT_MC *) binhash_find(dict_mc_hash, (char *) &ctxt, + sizeof(ctxt))) == 0) + msg_panic("%s: can't locate DICT_MC database handle", myname); + + /* + * Report the error in our context, and set dict_errno for possible + * errors. We override dict_errno when an error was recoverable. + */ + switch (ectxt->severity) { + default: +#ifdef DICT_MC_RECOVER_FROM_DISCONNECT + /* Code below causes an assert failure and core dump. */ + if (ectxt->errcode == MCM_ERR_SYS_READ) + /* Also: MCM_ERR_SYS_WRITEV, MCM_ERR_SYS_SETSOCKOPT */ + ectxt->cont = 'y'; +#endif + /* FALLTHROUGH */ + case MCM_ERR_LVL_NOTICE: + log_fn = msg_warn; + dict_errno = 1; + break; + case MCM_ERR_LVL_INFO: + log_fn = msg_info; + break; + } + log_fn((ectxt)->errnum ? "database %s:%s: libmemcache error: %s: %m" : + "database %s:%s: libmemcache error: %s", + DICT_TYPE_MEMCACHE, dict_mc->dict.name, (ectxt)->errstr); + return (0); +} + +static void dict_memcache_mc_free(DICT_MC *); +static void dict_memcache_mc_init(DICT_MC *); + +/* dict_memcache_recover - recover after libmemcache error */ + +static void dict_memcache_recover(DICT_MC *dict_mc) +{ + int saved_dict_errno; + + /* + * XXX If we don't try to recover from the first error, libmemcache will + * silently skip all subsequent database operations. + */ + saved_dict_errno = dict_errno; + dict_memcache_mc_free(dict_mc); + dict_memcache_mc_init(dict_mc); + dict_errno = saved_dict_errno; +} + +/* dict_memcache_prepare_key - prepare lookup key */ + +static int dict_memcache_prepare_key(DICT_MC *dict_mc, const char *name) +{ + + /* + * Optionally case-fold the search string. + */ + if (dict_mc->dict.flags & DICT_FLAG_FOLD_FIX) { + if (dict_mc->dict.fold_buf == 0) + dict_mc->dict.fold_buf = vstring_alloc(10); + vstring_strcpy(dict_mc->dict.fold_buf, name); + name = lowercase(STR(dict_mc->dict.fold_buf)); + } + + /* + * Optionally expand the query key format. + */ +#define DICT_MC_NO_KEY (0) +#define DICT_MC_NO_QUOTING ((void (*)(DICT *, const char *, VSTRING *)) 0) + + if (dict_mc->key_format != 0 + && strcmp(dict_mc->key_format, DICT_MC_DEF_KEY_FMT) != 0) { + VSTRING_RESET(dict_mc->key_buf); + if (db_common_expand(dict_mc->dbc_ctxt, dict_mc->key_format, + name, DICT_MC_NO_KEY, dict_mc->key_buf, + DICT_MC_NO_QUOTING) == 0) + return (0); + } else { + vstring_strcpy(dict_mc->key_buf, name); + } + + /* + * The length indicates whether the expansion is empty or not. + */ + return (LEN(dict_mc->key_buf)); +} + +/* dict_memcache_update - update memcache database */ + +static void dict_memcache_update(DICT *dict, const char *name, + const char *value) +{ + const char *myname = "dict_memcache_update"; + DICT_MC *dict_mc = (DICT_MC *) dict; + + /* + * Skip updates with a null key, noisily. This would result in loss of + * information. + */ + if (dict_memcache_prepare_key(dict_mc, name) == 0) { + dict_errno = 1; + msg_warn("database %s:%s: name \"%s\" expands to empty lookup key " + "-- skipping update", DICT_TYPE_MEMCACHE, + dict_mc->dict.name, name); + return; + } + + /* + * Our error call-back routine will report errors and set dict_errno. + */ + dict_errno = (mcm_set(dict_mc->mc_ctxt, dict_mc->mc, STR(dict_mc->key_buf), + LEN(dict_mc->key_buf), value, strlen(value), + dict_mc->mc_ttl, dict_mc->mc_flags) != 0); + if (msg_verbose) + msg_info("%s: %s: update key \"%s\" => \"%s\" %s", + myname, dict_mc->dict.name, STR(dict_mc->key_buf), value, + dict_errno ? "(error)" : "(no error)"); + + /* + * Recover after server failure. + */ + if (dict_errno) + dict_memcache_recover(dict_mc); +} + +/* dict_memcache_lookup - lookup memcache database */ + +static const char *dict_memcache_lookup(DICT *dict, const char *name) +{ + const char *myname = "dict_memcache_lookup"; + DICT_MC *dict_mc = (DICT_MC *) dict; + struct memcache_req *req; + struct memcache_res *res; + const char *retval; + + /* + * Skip lookups with a null key, silently. This is just asking for + * information that cannot exist. + */ +#define DICT_MC_SKIP(why, map_name, key) do { \ + if (msg_verbose) \ + msg_info("%s: %s: skipping lookup of key \"%s\": %s", \ + myname, (map_name), (key), (why)); \ + return (0); \ + } while (0) + + if (*name == 0) + DICT_MC_SKIP("empty lookup key", dict_mc->dict.name, name); + if (db_common_check_domain(dict_mc->dbc_ctxt, name) == 0) + DICT_MC_SKIP("domain mismatch", dict_mc->dict.name, name); + if (dict_memcache_prepare_key(dict_mc, name) == 0) + DICT_MC_SKIP("empty lookup key expansion", dict_mc->dict.name, name); + + /* + * Our error call-back routine will report errors and set dict_errno. We + * reset dict_errno after an error turns out to be recoverable. + */ + if ((req = mcm_req_new(dict_mc->mc_ctxt)) == 0) + msg_fatal("%s: can't create new request: %m", myname); /* XXX */ + /* Not: mcm_req_add(), because that makes unnecessary copy of the key. */ + if ((res = mcm_req_add_ref(dict_mc->mc_ctxt, req, STR(dict_mc->key_buf), + LEN(dict_mc->key_buf))) == 0) + msg_fatal("%s: can't create new result: %m", myname); /* XXX */ + + dict_errno = 0; + mcm_get(dict_mc->mc_ctxt, dict_mc->mc, req); + if (mcm_res_found(dict_mc->mc_ctxt, res) && res->bytes) { + vstring_strncpy(dict_mc->res_buf, res->val, res->bytes); + retval = STR(dict_mc->res_buf); + dict_errno = 0; + } else { + retval = 0; + } + mcm_res_free(dict_mc->mc_ctxt, req, res); + mcm_req_free(dict_mc->mc_ctxt, req); + + if (msg_verbose) + msg_info("%s: %s: key %s => %s", + myname, dict_mc->dict.name, STR(dict_mc->key_buf), + retval ? STR(dict_mc->res_buf) : + dict_errno ? "(error)" : "(not found)"); + + /* + * Recover after server failure. + */ + if (dict_errno) + dict_memcache_recover(dict_mc); + + return (retval); +} + +/* dict_memcache_mc_free - destroy libmemcache objects */ + +static void dict_memcache_mc_free(DICT_MC *dict_mc) +{ + binhash_delete(dict_mc_hash, (char *) &dict_mc->mc_ctxt, + sizeof(dict_mc->mc_ctxt), (void (*) (char *)) 0); + mcm_free(dict_mc->mc_ctxt, dict_mc->mc); + mcMemFreeCtxt(dict_mc->mc_ctxt); +} + +/* dict_memcache_mc_init - create libmemcache objects */ + +static void dict_memcache_mc_init(DICT_MC *dict_mc) +{ + const char *myname = "dict_memcache_mc_init"; + char *servers; + char *server; + char *cp; + + /* + * Create the libmemcache objects. + */ + dict_mc->mc_ctxt = + mcMemNewCtxt((mcFreeFunc) myfree, (mcMallocFunc) mymalloc, + (mcMallocFunc) mymalloc, (mcReallocFunc) myrealloc); + if (dict_mc->mc_ctxt == 0) + msg_fatal("error creating memcache context: %m"); /* XXX */ + dict_mc->mc = mcm_new(dict_mc->mc_ctxt); + if (dict_mc->mc == 0) + msg_fatal("error creating memcache object: %m"); /* XXX */ + + /* + * Set up call-back info for error reporting. + */ + if (dict_mc_hash == 0) + dict_mc_hash = binhash_create(1); + binhash_enter(dict_mc_hash, (char *) &dict_mc->mc_ctxt, + sizeof(dict_mc->mc_ctxt), (char *) dict_mc); + mcErrSetupCtxt(dict_mc->mc_ctxt, dict_memcache_error_cb); + + /* + * Add the server list. + */ + cp = servers = cfg_get_str(dict_mc->parser, "hosts", + DICT_MC_DEF_HOST_PORT, 0, 0); + while ((server = mystrtok(&cp, " ,\t\r\n")) != 0) { + if (msg_verbose) + msg_info("%s: database %s:%s: adding server %s", + myname, DICT_TYPE_MEMCACHE, dict_mc->dict.name, server); + if (mcm_server_add4(dict_mc->mc_ctxt, dict_mc->mc, server) < 0) + msg_warn("database %s:%s: error adding server %s", + DICT_TYPE_MEMCACHE, dict_mc->dict.name, server); + } + myfree(servers); +} + +/* dict_memcache_close - close memcache database */ + +static void dict_memcache_close(DICT *dict) +{ + DICT_MC *dict_mc = (DICT_MC *) dict; + + dict_memcache_mc_free(dict_mc); + cfg_parser_free(dict_mc->parser); + db_common_free_ctx(dict_mc->dbc_ctxt); + vstring_free(dict_mc->key_buf); + vstring_free(dict_mc->res_buf); + if (dict_mc->key_format) + myfree(dict_mc->key_format); + if (dict->fold_buf) + vstring_free(dict->fold_buf); + dict_free(dict); +} + +/* dict_memcache_open - open memcache database */ + +DICT *dict_memcache_open(const char *name, int open_flags, int dict_flags) +{ + DICT_MC *dict_mc; + + /* + * Sanity checks. + */ + if (dict_flags & DICT_FLAG_NO_UNAUTH) + msg_fatal("%s:%s map is not allowed for security-sensitive data", + DICT_TYPE_MEMCACHE, name); + open_flags &= (O_RDONLY | O_RDWR | O_WRONLY | O_APPEND); + if (open_flags != O_RDONLY && open_flags != O_RDWR) + msg_fatal("%s:%s map requires O_RDONLY or O_RDWR access mode", + DICT_TYPE_MEMCACHE, name); + + /* + * Create the dictionary object. + */ + dict_mc = (DICT_MC *) dict_alloc(DICT_TYPE_MEMCACHE, name, + sizeof(*dict_mc)); + dict_mc->dict.lookup = dict_memcache_lookup; + if (open_flags == O_RDWR) + dict_mc->dict.update = dict_memcache_update; + dict_mc->dict.close = dict_memcache_close; + dict_mc->dict.flags = dict_flags; + dict_mc->key_buf = vstring_alloc(10); + dict_mc->res_buf = vstring_alloc(10); + + /* + * Parse the configuration file. + */ + dict_mc->parser = cfg_parser_alloc(name); + dict_mc->key_format = cfg_get_str(dict_mc->parser, "key_format", + DICT_MC_DEF_KEY_FMT, 0, 0); + dict_mc->mc_ttl = cfg_get_int(dict_mc->parser, "ttl", + DICT_MC_DEF_TTL, 0, 0); + dict_mc->mc_flags = cfg_get_int(dict_mc->parser, "flags", + DICT_MC_DEF_FLAGS, 0, 0); + + /* + * Initialize the memcache objects. + */ + dict_memcache_mc_init(dict_mc); + + /* + * Parse templates and common database parameters. Maps that use + * substring keys should only be used with the full input key. + */ + dict_mc->dbc_ctxt = 0; + db_common_parse(&dict_mc->dict, &dict_mc->dbc_ctxt, + dict_mc->key_format, 1); + db_common_parse_domain(dict_mc->parser, dict_mc->dbc_ctxt); + if (db_common_dict_partial(dict_mc->dbc_ctxt)) + /* Breaks recipient delimiters */ + dict_mc->dict.flags |= DICT_FLAG_PATTERN; + else + dict_mc->dict.flags |= DICT_FLAG_FIXED; + + return (&dict_mc->dict); +} + +#endif diff --git a/postfix/src/global/dict_memcache.h b/postfix/src/global/dict_memcache.h new file mode 100644 index 000000000..3b6e7a406 --- /dev/null +++ b/postfix/src/global/dict_memcache.h @@ -0,0 +1,38 @@ +#ifndef _DICT_MEMCACHE_INCLUDED_ +#define _DICT_MEMCACHE_INCLUDED_ + +/*++ +/* NAME +/* dict_memcache 3h +/* SUMMARY +/* dictionary interface to memcache databases +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +#define DICT_TYPE_MEMCACHE "memcache" + +extern DICT *dict_memcache_open(const char *name, int unused_flags, + int dict_flags); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/global/mail_dict.c b/postfix/src/global/mail_dict.c index 337861d11..3d456ea7d 100644 --- a/postfix/src/global/mail_dict.c +++ b/postfix/src/global/mail_dict.c @@ -37,6 +37,7 @@ #include #include #include +#include #include typedef struct { @@ -57,6 +58,9 @@ static const DICT_OPEN_INFO dict_open_info[] = { #endif #ifdef HAS_SQLITE DICT_TYPE_SQLITE, dict_sqlite_open, +#endif +#ifdef HAS_MEMCACHE + DICT_TYPE_MEMCACHE, dict_memcache_open, #endif 0, }; @@ -70,3 +74,17 @@ void mail_dict_init(void) for (dp = dict_open_info; dp->type; dp++) dict_open_register(dp->type, dp->open); } + +#ifdef TEST + + /* + * Proof-of-concept test program. + */ +int main(int argc, char **argv) +{ + mail_dict_init(); + dict_test(argc, argv); + return (0); +} + +#endif diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index ad0505b98..da5dc31af 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -257,6 +257,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_CIPHER_NAME "cipher_name" #define MAIL_ATTR_CIPHER_USEBITS "cipher_usebits" #define MAIL_ATTR_CIPHER_ALGBITS "cipher_algbits" +#define MAIL_ATTR_SERVER_ID "server_id" /* * SMTP reply footer support. diff --git a/postfix/src/global/mail_version.c b/postfix/src/global/mail_version.c index e69de29bb..6b2402132 100644 --- a/postfix/src/global/mail_version.c +++ b/postfix/src/global/mail_version.c @@ -0,0 +1,258 @@ +/*++ +/* NAME +/* mail_version 3 +/* SUMMARY +/* time-dependent probe sender addresses +/* SYNOPSIS +/* #include +/* +/* typedef struct { +/* char *program; /* postfix */ +/* int major; /* 2 */ +/* int minor; /* 9 */ +/* int patch; /* patchlevel or -1 */ +/* char *snapshot; /* null or snapshot info */ +/* } MAIL_VERSION; +/* +/* MAIL_VERSION *mail_version_parse(version_string, why) +/* const char *version_string; +/* const char **why; +/* +/* void mail_version_free(mp) +/* MAIL_VERSION *mp; +/* +/* const char *get_mail_version() +/* +/* int check_mail_version(version_string) +/* const char *version_string; +/* DESCRIPTION +/* This module understands the format of Postfix version strings +/* (for example the default value of "mail_version"), and +/* provides support to compare the compile-time version of a +/* Postfix program with the run-time version of a Postfix +/* library. Apparently, some distributions don't use proper +/* so-number versioning, causing programs to fail erratically +/* after an update replaces the library but not the program. +/* +/* A Postfix version string consists of two or three parts +/* separated by a single "-" character: +/* .IP \(bu +/* The first part is a string with the program name. +/* .IP \(bu +/* The second part is the program version: either two or three +/* non-negative integer numbers separated by single "." +/* character. Stable releases have a major version, minor +/* version and patchlevel; experimental releases (snapshots) +/* have only major and minor version numbers. +/* .IP \(bu +/* The third part is ignored with a stable release, otherwise +/* it is a string with the snapshot release date plus some +/* optional information. +/* +/* mail_version_parse() parses a version string. +/* +/* get_mail_version() returns the version string (the value +/* of DEF_MAIL_VERSION) that is compiled into the library. +/* +/* check_mail_version() compares the caller's version string +/* (usually the value of DEF_MAIL_VERSION) that is compiled +/* into the caller, and logs a warning when the strings differ. +/* DIAGNOSTICS +/* In the case of a parsing error, mail_version_parse() returns +/* a null pointer, and sets the why argument to a string with +/* problem details. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include + +/* Global library. */ + +#include + +/* mail_version_int - convert integer */ + +static int mail_version_int(const char *strval) +{ + char *end; + int intval; + long longval; + + errno = 0; + intval = longval = strtol(strval, &end, 10); + if (*strval == 0 || *end != 0 || errno == ERANGE || longval != intval) + intval = (-1); + return (intval); +} + +/* mail_version_worker - do the parsing work */ + +static const char *mail_version_worker(MAIL_VERSION *mp, char *cp) +{ + char *major_field; + char *minor_field; + char *patch_field; + + /* + * Program name. + */ + if ((mp->program = mystrtok(&cp, "-")) == 0) + return ("no program name"); + + /* + * Major, minor, patchlevel. If this is a stable release, then we ignore + * text after the patchlevel, in case there are vendor extensions. + */ + if ((major_field = mystrtok(&cp, "-")) == 0) + return ("missing major version"); + + if ((minor_field = split_at(major_field, '.')) == 0) + return ("missing minor version"); + if ((mp->major = mail_version_int(major_field)) < 0) + return ("bad major version"); + patch_field = split_at(minor_field, '.'); + if ((mp->minor = mail_version_int(minor_field)) < 0) + return ("bad minor version"); + + if (patch_field == 0) + mp->patch = -1; + else if ((mp->patch = mail_version_int(patch_field)) < 0) + return ("bad patchlevel"); + + /* + * Experimental release. If this is not a stable release, we take + * everything to the end of the string. + */ + if (patch_field != 0) + mp->snapshot = 0; + else if ((mp->snapshot = mystrtok(&cp, "")) == 0) + return ("missing snapshot field"); + + return (0); +} + +/* mail_version_parse - driver */ + +MAIL_VERSION *mail_version_parse(const char *string, const char **why) +{ + MAIL_VERSION *mp; + char *saved_string; + const char *err; + + mp = (MAIL_VERSION *) mymalloc(sizeof(*mp)); + saved_string = mystrdup(string); + if ((err = mail_version_worker(mp, saved_string)) != 0) { + *why = err; + myfree(saved_string); + myfree((char *) mp); + return (0); + } else { + return (mp); + } +} + +/* mail_version_free - destroy version information */ + +void mail_version_free(MAIL_VERSION *mp) +{ + myfree(mp->program); + myfree((char *) mp); +} + +/* get_mail_version - return parsed mail version string */ + +const char *get_mail_version(void) +{ + return (DEF_MAIL_VERSION); +} + +/* check_mail_version - compare caller version with library version */ + +void check_mail_version(const char *version_string) +{ + if (strcmp(version_string, DEF_MAIL_VERSION) != 0) + msg_warn("Postfix library version mis-match: wanted %s, found %s", + version_string, DEF_MAIL_VERSION); +} + +#ifdef TEST + +#include +#include +#include +#include + +#define STR(x) vstring_str(x) + +/* parse_sample - parse a sample string from argv or stdin */ + +static void parse_sample(const char *sample) +{ + MAIL_VERSION *mp; + const char *why; + + mp = mail_version_parse(sample, &why); + if (mp == 0) { + vstream_printf("ERROR: %s: %s\n", sample, why); + } else { + vstream_printf("program: %s\t", mp->program); + vstream_printf("major: %d\t", mp->major); + vstream_printf("minor: %d\t", mp->minor); + if (mp->patch < 0) + vstream_printf("snapshot: %s\n", mp->snapshot); + else + vstream_printf("patch: %d\n", mp->patch); + mail_version_free(mp); + } + vstream_fflush(VSTREAM_OUT); +} + +/* main - the main program */ + +int main(int argc, char **argv) +{ + VSTRING *inbuf = vstring_alloc(1); + int have_tty = isatty(0); + + if (argc > 1) { + while (--argc > 0 && *++argv) + parse_sample(*argv); + } else { + for (;;) { + if (have_tty) { + vstream_printf("> "); + vstream_fflush(VSTREAM_OUT); + } + if (vstring_fgets_nonl(inbuf, VSTREAM_IN) <= 0) + break; + if (have_tty == 0) + vstream_printf("> %s\n", STR(inbuf)); + if (*STR(inbuf) == 0 || *STR(inbuf) == '#') + continue; + parse_sample(STR(inbuf)); + } + } + vstring_free(inbuf); + return (0); +} + +#endif diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index b7c89e0f6..2f815b661 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20111205" +#define MAIL_RELEASE_DATE "20111209" #define MAIL_VERSION_NUMBER "2.9" #ifdef SNAPSHOT @@ -67,6 +67,29 @@ extern char *var_mail_release; #define MAIL_VERSION_STAMP_ALLOCATE \ mail_version_stamp = strdup(VAR_MAIL_VERSION "=" DEF_MAIL_VERSION) + /* + * Mail version string parser, plus support to compare the compile-time + * version string of a Postfix program with the run-time version string of a + * Postfix shared library. When programs are not updated, they may fail in + * erratic ways when linked against a newer run-time library. Of course the + * right solution is so-number versioning of the Postfix run-time library. + */ +typedef struct { + char *program; /* postfix */ + int major; /* 2 */ + int minor; /* 9 */ + int patch; /* null */ + char *snapshot; /* 20111209-nonprod */ +} MAIL_VERSION; + +extern MAIL_VERSION *mail_version_parse(const char *, const char **); +extern void mail_version_free(MAIL_VERSION *); +extern const char *get_mail_version(void); +extern void check_mail_version(const char *); + +#define MAIL_VERSION_CHECK \ + check_mail_version(DEF_MAIL_VERSION) + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.in b/postfix/src/global/mail_version.in new file mode 100644 index 000000000..1cf75d8af --- /dev/null +++ b/postfix/src/global/mail_version.in @@ -0,0 +1,8 @@ +1 +1-2 +1-2.3 +1-2.3.4.5 +1-2.3.4-5 +1-2.3-5 +1-2.3-5-6 +1-2.3-5.6 diff --git a/postfix/src/global/mail_version.ref b/postfix/src/global/mail_version.ref new file mode 100644 index 000000000..5dbc3ab08 --- /dev/null +++ b/postfix/src/global/mail_version.ref @@ -0,0 +1,16 @@ +> 1 +ERROR: 1: missing major version +> 1-2 +ERROR: 1-2: missing minor version +> 1-2.3 +ERROR: 1-2.3: missing snapshot field +> 1-2.3.4.5 +ERROR: 1-2.3.4.5: bad patchlevel +> 1-2.3.4-5 +program: 1 major: 2 minor: 3 patch: 4 +> 1-2.3-5 +program: 1 major: 2 minor: 3 snapshot: 5 +> 1-2.3-5-6 +program: 1 major: 2 minor: 3 snapshot: 5-6 +> 1-2.3-5.6 +program: 1 major: 2 minor: 3 snapshot: 5.6 diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index 53f65bd9e..a78173916 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -92,6 +92,7 @@ event_server.o: ../../include/mail_conf.h event_server.o: ../../include/mail_dict.h event_server.o: ../../include/mail_params.h event_server.o: ../../include/mail_task.h +event_server.o: ../../include/mail_version.h event_server.o: ../../include/msg.h event_server.o: ../../include/msg_syslog.h event_server.o: ../../include/msg_vstream.h @@ -278,6 +279,7 @@ multi_server.o: ../../include/mail_conf.h multi_server.o: ../../include/mail_dict.h multi_server.o: ../../include/mail_params.h multi_server.o: ../../include/mail_task.h +multi_server.o: ../../include/mail_version.h multi_server.o: ../../include/msg.h multi_server.o: ../../include/msg_syslog.h multi_server.o: ../../include/msg_vstream.h @@ -307,6 +309,7 @@ single_server.o: ../../include/mail_conf.h single_server.o: ../../include/mail_dict.h single_server.o: ../../include/mail_params.h single_server.o: ../../include/mail_task.h +single_server.o: ../../include/mail_version.h single_server.o: ../../include/msg.h single_server.o: ../../include/msg_syslog.h single_server.o: ../../include/msg_vstream.h @@ -336,6 +339,7 @@ trigger_server.o: ../../include/mail_conf.h trigger_server.o: ../../include/mail_dict.h trigger_server.o: ../../include/mail_params.h trigger_server.o: ../../include/mail_task.h +trigger_server.o: ../../include/mail_version.h trigger_server.o: ../../include/msg.h trigger_server.o: ../../include/msg_syslog.h trigger_server.o: ../../include/msg_vstream.h diff --git a/postfix/src/master/event_server.c b/postfix/src/master/event_server.c index 21ff0d5a9..37d7e0970 100644 --- a/postfix/src/master/event_server.c +++ b/postfix/src/master/event_server.c @@ -226,6 +226,7 @@ #include #include #include +#include /* Process manager. */ @@ -577,6 +578,11 @@ NORETURN event_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if (msg_verbose) msg_info("daemon started"); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Initialize from the configuration file. Allow command-line options to * override compiled-in defaults or configured parameter values. diff --git a/postfix/src/master/master.c b/postfix/src/master/master.c index cef01e401..532eb789e 100644 --- a/postfix/src/master/master.c +++ b/postfix/src/master/master.c @@ -293,6 +293,11 @@ int main(int argc, char **argv) */ msg_syslog_init(mail_task(var_procname), LOG_PID, LOG_FACILITY); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * The mail system must be run by the superuser so it can revoke * privileges for selected operations. That's right - it takes privileges diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 6477894f5..0b5e678c6 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -214,6 +214,7 @@ #include #include #include +#include /* Process manager. */ @@ -573,6 +574,11 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) if (msg_verbose) msg_info("daemon started"); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Initialize from the configuration file. Allow command-line options to * override compiled-in defaults or configured parameter values. diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 94937eb97..aba479cd5 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -191,6 +191,7 @@ #include #include #include +#include /* Process manager. */ @@ -456,6 +457,11 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) if (msg_verbose) msg_info("daemon started"); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Initialize from the configuration file. Allow command-line options to * override compiled-in defaults or configured parameter values. diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index 10d6621a2..df3bf2054 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -201,6 +201,7 @@ #include #include #include +#include /* Process manager. */ @@ -467,6 +468,11 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. if (msg_verbose) msg_info("daemon started"); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Initialize from the configuration file. Allow command-line options to * override compiled-in defaults or configured parameter values. diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index 34336cd7e..9b17d0207 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -669,6 +669,11 @@ int main(int argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Parse JCL. */ diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index 0de2b48ec..eea582ac6 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -175,6 +175,9 @@ /* .IP "\fBldap\fR (read-only)" /* Perform lookups using the LDAP protocol. This is described /* in \fBldap_table\fR(5). +/* .IP "\fBmemcache\fR (read-write)" +/* Perform lookups using the memcache protocol. This is described +/* in \fBmemcache_table\fR(5). /* .IP "\fBmysql\fR (read-only)" /* Perform lookups using the MYSQL protocol. This is described /* in \fBmysql_table\fR(5). diff --git a/postfix/src/postdrop/postdrop.c b/postfix/src/postdrop/postdrop.c index a2df01ece..84f8e69e0 100644 --- a/postfix/src/postdrop/postdrop.c +++ b/postfix/src/postdrop/postdrop.c @@ -265,6 +265,11 @@ int main(int argc, char **argv) msg_syslog_init(mail_task("postdrop"), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Parse JCL. This program is set-gid and must sanitize all command-line * arguments. The configuration directory argument is validated by the diff --git a/postfix/src/postfix/postfix.c b/postfix/src/postfix/postfix.c index c7b8c97ec..60343668e 100644 --- a/postfix/src/postfix/postfix.c +++ b/postfix/src/postfix/postfix.c @@ -240,6 +240,7 @@ /* Table lookup mechanisms: /* cidr_table(5), Associate CIDR pattern with value /* ldap_table(5), Postfix LDAP client +/* memcache_table(5), Postfix memcache client /* mysql_table(5), Postfix MYSQL client /* nisplus_table(5), Postfix NIS+ client /* pcre_table(5), Associate PCRE pattern with value @@ -436,6 +437,11 @@ int main(int argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * The mail system must be run by the superuser so it can revoke * privileges for selected operations. That's right - it takes privileges @@ -524,7 +530,7 @@ int main(int argc, char **argv) /* * Run the management script. */ - if (force_single_instance + if (force_single_instance || argv_split(var_multi_conf_dirs, "\t\r\n, ")->argc == 0) { script = concatenate(var_daemon_dir, "/postfix-script", (char *) 0); if (optind < 1) diff --git a/postfix/src/postlog/postlog.c b/postfix/src/postlog/postlog.c index 000ff70d6..67715ae9e 100644 --- a/postfix/src/postlog/postlog.c +++ b/postfix/src/postlog/postlog.c @@ -208,6 +208,11 @@ int main(int argc, char **argv) msg_syslog_init(tag, LOG_PID, LOG_FACILITY); tag = 0; + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Parse switches. */ diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index e956aed9b..19bb02e5b 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -784,6 +784,11 @@ int main(int argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Parse JCL. */ @@ -857,7 +862,7 @@ int main(int argc, char **argv) if (strcmp(var_syslog_name, DEF_SYSLOG_NAME) != 0) msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); mail_dict_init(); - if ((query == 0 || strcmp(query, "-") != 0) + if ((query == 0 || strcmp(query, "-") != 0) && (postmap_flags & POSTMAP_FLAG_ANY_KEY)) msg_fatal("specify -b -h or -m only with \"-q -\""); diff --git a/postfix/src/postmulti/postmulti.c b/postfix/src/postmulti/postmulti.c index 30633ae26..c0ff9df36 100644 --- a/postfix/src/postmulti/postmulti.c +++ b/postfix/src/postmulti/postmulti.c @@ -1658,6 +1658,11 @@ int main(int argc, char **argv) msg_vstream_init(argv[0], VSTREAM_ERR); msg_syslog_init(argv[0], LOG_PID, LOG_FACILITY); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + if ((config_dir = getenv(CONF_ENV_PATH)) != 0 && strcmp(config_dir, DEF_CONFIG_DIR) != 0) msg_fatal("Non-default configuration directory: %s=%s", diff --git a/postfix/src/postqueue/postqueue.c b/postfix/src/postqueue/postqueue.c index 4dfedabb7..d6ed5ccc4 100644 --- a/postfix/src/postqueue/postqueue.c +++ b/postfix/src/postqueue/postqueue.c @@ -477,6 +477,11 @@ int main(int argc, char **argv) msg_syslog_init(mail_task("postqueue"), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Parse JCL. This program is set-gid and must sanitize all command-line * parameters. The configuration directory argument is validated by the diff --git a/postfix/src/postscreen/postscreen.c b/postfix/src/postscreen/postscreen.c index d7307f8dc..3b79900b8 100644 --- a/postfix/src/postscreen/postscreen.c +++ b/postfix/src/postscreen/postscreen.c @@ -1121,7 +1121,7 @@ int main(int argc, char **argv) VAR_PSC_NSMTP_TTL, DEF_PSC_NSMTP_TTL, &var_psc_nsmtp_ttl, 1, 0, VAR_PSC_BARLF_TTL, DEF_PSC_BARLF_TTL, &var_psc_barlf_ttl, 1, 0, VAR_PSC_CACHE_RET, DEF_PSC_CACHE_RET, &var_psc_cache_ret, 1, 0, - VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 1, 0, + VAR_PSC_CACHE_SCAN, DEF_PSC_CACHE_SCAN, &var_psc_cache_scan, 0, 0, VAR_PSC_WATCHDOG, DEF_PSC_WATCHDOG, &var_psc_watchdog, 10, 0, 0, }; diff --git a/postfix/src/postscreen/postscreen_starttls.c b/postfix/src/postscreen/postscreen_starttls.c index eb5d95a52..f9ad58bcd 100644 --- a/postfix/src/postscreen/postscreen_starttls.c +++ b/postfix/src/postscreen/postscreen_starttls.c @@ -229,6 +229,7 @@ void psc_starttls_open(PSC_STATE *smtp_state, EVENT_NOTIFY_FN resume_event) ATTR_TYPE_STR, MAIL_ATTR_REMOTE_ENDPT, STR(remote_endpt), ATTR_TYPE_INT, MAIL_ATTR_FLAGS, TLS_PROXY_FLAG_ROLE_SERVER, ATTR_TYPE_INT, MAIL_ATTR_TIMEOUT, psc_normal_cmd_time_limit, + ATTR_TYPE_STR, MAIL_ATTR_SERVER_ID, MAIL_SERVICE_SMTPD, /* XXX */ ATTR_TYPE_END); if (vstream_fflush(tlsproxy_stream) != 0) { msg_warn("error sending request to %s service: %m", psc_tlsp_service); diff --git a/postfix/src/postsuper/postsuper.c b/postfix/src/postsuper/postsuper.c index fba2f1a39..7e3b2b98c 100644 --- a/postfix/src/postsuper/postsuper.c +++ b/postfix/src/postsuper/postsuper.c @@ -1137,6 +1137,11 @@ int main(int argc, char **argv) msg_syslog_init(mail_task(argv[0]), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Disallow unsafe practices, and refuse to run set-uid (or as the child * of a set-uid process). Whenever a privileged wrapper program is diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index a1a5dd792..9560f4840 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -1016,6 +1016,11 @@ int main(int argc, char **argv) msg_syslog_init(mail_task("sendmail"), LOG_PID, LOG_FACILITY); set_mail_conf_str(VAR_PROCNAME, var_procname = mystrdup(argv[0])); + /* + * Check the Postfix library version as soon as we enable logging. + */ + MAIL_VERSION_CHECK; + /* * Some sites mistakenly install Postfix sendmail as set-uid root. Drop * set-uid privileges only when root, otherwise some systems will not diff --git a/postfix/src/tlsproxy/tlsproxy.c b/postfix/src/tlsproxy/tlsproxy.c index 8a0fd74d7..8195f1b01 100644 --- a/postfix/src/tlsproxy/tlsproxy.c +++ b/postfix/src/tlsproxy/tlsproxy.c @@ -692,7 +692,7 @@ static void tlsp_start_tls(TLSP_STATE *state) timeout = 0, /* unused */ requirecert = (var_tlsp_tls_req_ccert && var_tlsp_enforce_tls), - serverid = MAIL_SERVICE_SMTPD, /* XXX */ + serverid = state->server_id, namaddr = state->remote_endpt, cipher_grade = cipher_grade, cipher_exclusions = STR(cipher_exclusions), @@ -775,6 +775,7 @@ static void tlsp_get_request_event(int event, char *context) VSTREAM *plaintext_stream = state->plaintext_stream; int plaintext_fd = vstream_fileno(plaintext_stream); static VSTRING *remote_endpt; + static VSTRING *server_id; int req_flags; int timeout; int ready; @@ -782,8 +783,10 @@ static void tlsp_get_request_event(int event, char *context) /* * One-time initialization. */ - if (remote_endpt == 0) + if (remote_endpt == 0) { remote_endpt = vstring_alloc(10); + server_id = vstring_alloc(10); + } /* * At this point we still manually manage plaintext read/write/timeout @@ -803,7 +806,8 @@ static void tlsp_get_request_event(int event, char *context) ATTR_TYPE_STR, MAIL_ATTR_REMOTE_ENDPT, remote_endpt, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, &req_flags, ATTR_TYPE_INT, MAIL_ATTR_TIMEOUT, &timeout, - ATTR_TYPE_END) != 3) { + ATTR_TYPE_STR, MAIL_ATTR_SERVER_ID, server_id, + ATTR_TYPE_END) != 4) { msg_warn("%s: receive request attributes: %m", myname); event_disable_readwrite(plaintext_fd); tlsp_state_free(state); @@ -835,6 +839,7 @@ static void tlsp_get_request_event(int event, char *context) */ else { state->remote_endpt = mystrdup(STR(remote_endpt)); + state->server_id = mystrdup(STR(server_id)); msg_info("CONNECT %s %s", (req_flags & TLS_PROXY_FLAG_ROLE_SERVER) ? "from" : (req_flags & TLS_PROXY_FLAG_ROLE_CLIENT) ? "to" : diff --git a/postfix/src/tlsproxy/tlsproxy.h b/postfix/src/tlsproxy/tlsproxy.h index 340e02fff..e3e1d11fa 100644 --- a/postfix/src/tlsproxy/tlsproxy.h +++ b/postfix/src/tlsproxy/tlsproxy.h @@ -32,6 +32,7 @@ typedef struct { EVENT_NOTIFY_FN ciphertext_timer; /* kludge */ int timeout; /* read/write time limit */ char *remote_endpt; /* printable remote endpoint */ + char *server_id; /* cache management */ TLS_SESS_STATE *tls_context; /* llibtls state */ int ssl_last_err; /* TLS I/O state */ } TLSP_STATE; diff --git a/postfix/src/tlsproxy/tlsproxy_state.c b/postfix/src/tlsproxy/tlsproxy_state.c index 1dcf5b889..1161b89f5 100644 --- a/postfix/src/tlsproxy/tlsproxy_state.c +++ b/postfix/src/tlsproxy/tlsproxy_state.c @@ -46,6 +46,9 @@ /* .IP remote_endpt /* Printable remote endpoint name. /* The destructor will automatically destroy the string. +/* .IP server_id +/* TLS session cache identifier. +/* The destructor will automatically destroy the string. /* DIAGNOSTICS /* All errors are fatal. /* LICENSE @@ -103,6 +106,7 @@ TLSP_STATE *tlsp_state_create(const char *service, state->ciphertext_timer = 0; state->timeout = -1; state->remote_endpt = 0; + state->server_id = 0; state->tls_context = 0; return (state); @@ -126,6 +130,8 @@ void tlsp_state_free(TLSP_STATE *state) msg_info("DISCONNECT %s", state->remote_endpt); myfree(state->remote_endpt); } + if (state->server_id) + myfree(state->server_id); if (state->tls_context) tls_free_context(state->tls_context); myfree((char *) state); diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 13c4048aa..7ecf8b319 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -33,7 +33,7 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ allascii.c load_file.c killme_after.c vstream_tweak.c \ unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \ unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \ - ip_match.c nbbio.c stream_pass_connect.c base32_code.c + ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.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 \ @@ -68,7 +68,7 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ allascii.o load_file.o killme_after.o vstream_tweak.o \ unix_pass_listen.o unix_pass_trigger.o edit_file.o inet_windowsize.o \ unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \ - ip_match.o nbbio.o stream_pass_connect.o base32_code.o + ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \ dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \ @@ -1039,6 +1039,17 @@ dict_tcp.o: vbuf.h dict_tcp.o: vstream.h dict_tcp.o: vstring.h dict_tcp.o: vstring_vstream.h +dict_test.o: argv.h +dict_test.o: dict.h +dict_test.o: dict_test.c +dict_test.o: msg.h +dict_test.o: msg_vstream.h +dict_test.o: stringops.h +dict_test.o: sys_defs.h +dict_test.o: vbuf.h +dict_test.o: vstream.h +dict_test.o: vstring.h +dict_test.o: vstring_vstream.h dict_thash.o: argv.h dict_thash.o: dict.h dict_thash.o: dict_thash.c diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index af41c7663..0731a2b87 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -401,12 +401,26 @@ void dict_load_file(const char *dict_name, const char *path) void dict_load_fp(const char *dict_name, VSTREAM *fp) { + const char *myname = "dict_load_fp"; VSTRING *buf; char *member; char *val; int lineno; const char *err; struct stat st; + DICT_NODE *node; + DICT *dict; + + /* + * Instantiate the dictionary even if the file is empty. + */ + if ((node = dict_node(dict_name)) == 0) { + if (dict_unknown_allowed == 0) + msg_fatal("%s: unknown dictionary: %s", myname, dict_name); + dict = dict_ht_open(dict_name, O_CREAT | O_RDWR, 0); + dict_register(dict_name, dict); + } else + dict = node->dict; buf = vstring_alloc(100); lineno = 0; @@ -417,11 +431,13 @@ void dict_load_fp(const char *dict_name, VSTREAM *fp) if ((err = split_nameval(STR(buf), &member, &val)) != 0) msg_fatal("%s, line %d: %s: \"%s\"", VSTREAM_PATH(fp), lineno, err, STR(buf)); - dict_update(dict_name, member, val); + if (msg_verbose > 1) + msg_info("%s: %s = %s", myname, member, val); + dict->update(dict, member, val); } vstring_free(buf); - dict_handle(dict_name)->owner.uid = st.st_uid; - dict_handle(dict_name)->owner.status = (st.st_uid != 0); + dict->owner.uid = st.st_uid; + dict->owner.status = (st.st_uid != 0); } /* dict_eval_lookup - macro parser call-back routine */ diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index e8449491d..36d49c89f 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -164,6 +164,11 @@ extern int dict_changed(void); extern const char *dict_changed_name(void); extern const char *dict_flags_str(int); + /* + * Driver for interactive or scripted tests. + */ +void dict_test(int, char **); + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/util/dict_open.c b/postfix/src/util/dict_open.c index 766fa0098..d5ae3d5a0 100644 --- a/postfix/src/util/dict_open.c +++ b/postfix/src/util/dict_open.c @@ -382,135 +382,11 @@ ARGV *dict_mapnames() #ifdef TEST /* - * Proof-of-concept test program. Create, update or read a database. When - * the input is a name=value pair, the database is updated, otherwise the - * program assumes that the input specifies a lookup key and prints the - * corresponding value. + * Proof-of-concept test program. */ - -/* System library. */ - -#include -#include -#include -#include - -/* Utility library. */ - -#include "vstring.h" -#include "vstream.h" -#include "msg_vstream.h" -#include "vstring_vstream.h" - -static NORETURN usage(char *myname) -{ - msg_fatal("usage: %s type:file read|write|create [fold] [sync]", myname); -} - int main(int argc, char **argv) { - VSTRING *keybuf = vstring_alloc(1); - VSTRING *inbuf = vstring_alloc(1); - DICT *dict; - char *dict_name; - int open_flags; - char *bufp; - char *cmd; - const char *key; - const char *value; - int ch; - int dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; - int n; - - signal(SIGPIPE, SIG_IGN); - - msg_vstream_init(argv[0], VSTREAM_ERR); - while ((ch = GETOPT(argc, argv, "v")) > 0) { - switch (ch) { - default: - usage(argv[0]); - case 'v': - msg_verbose++; - break; - } - } - optind = OPTIND; - if (argc - optind < 2) - usage(argv[0]); - if (strcasecmp(argv[optind + 1], "create") == 0) - open_flags = O_CREAT | O_RDWR | O_TRUNC; - else if (strcasecmp(argv[optind + 1], "write") == 0) - open_flags = O_RDWR; - else if (strcasecmp(argv[optind + 1], "read") == 0) - open_flags = O_RDONLY; - else - msg_fatal("unknown access mode: %s", argv[2]); - for (n = 2; argv[optind + n]; n++) { - if (strcasecmp(argv[optind + 2], "fold") == 0) - dict_flags |= DICT_FLAG_FOLD_ANY; - else if (strcasecmp(argv[optind + 2], "sync") == 0) - dict_flags |= DICT_FLAG_SYNC_UPDATE; - else - usage(argv[0]); - } - dict_name = argv[optind]; - dict = dict_open(dict_name, open_flags, dict_flags); - dict_register(dict_name, dict); - while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { - bufp = vstring_str(inbuf); - if (!isatty(0)) { - vstream_printf("> %s\n", bufp); - vstream_fflush(VSTREAM_OUT); - } - if (*bufp == '#') - continue; - if ((cmd = mystrtok(&bufp, " ")) == 0) { - vstream_printf("usage: del key|get key|put key=value|first|next\n"); - vstream_fflush(VSTREAM_OUT); - continue; - } - if (dict_changed_name()) - msg_warn("dictionary has changed"); - key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; - value = mystrtok(&bufp, " ="); - if (strcmp(cmd, "del") == 0 && key && !value) { - if (dict_del(dict, key)) - vstream_printf("%s: not found\n", key); - else - vstream_printf("%s: deleted\n", key); - } else if (strcmp(cmd, "get") == 0 && key && !value) { - if ((value = dict_get(dict, key)) == 0) { - vstream_printf("%s: %s\n", key, - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); - } else { - vstream_printf("%s=%s\n", key, value); - } - } else if (strcmp(cmd, "put") == 0 && key && value) { - dict_put(dict, key, value); - vstream_printf("%s=%s\n", key, value); - } else if (strcmp(cmd, "first") == 0 && !key && !value) { - if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) - vstream_printf("%s=%s\n", key, value); - else - vstream_printf("%s\n", - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); - } else if (strcmp(cmd, "next") == 0 && !key && !value) { - if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) - vstream_printf("%s=%s\n", key, value); - else - vstream_printf("%s\n", - dict_errno == DICT_ERR_RETRY ? - "soft error" : "not found"); - } else { - vstream_printf("usage: del key|get key|put key=value|first|next\n"); - } - vstream_fflush(VSTREAM_OUT); - } - vstring_free(keybuf); - vstring_free(inbuf); - dict_close(dict); + dict_test(argc, argv); return (0); } diff --git a/postfix/src/util/dict_test.c b/postfix/src/util/dict_test.c new file mode 100644 index 000000000..e4f780b6a --- /dev/null +++ b/postfix/src/util/dict_test.c @@ -0,0 +1,141 @@ + /* + * Proof-of-concept test program. Create, update or read a database. When + * the input is a name=value pair, the database is updated, otherwise the + * program assumes that the input specifies a lookup key and prints the + * corresponding value. + */ + +/* System library. */ + +#include +#include +#include +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include + +static NORETURN usage(char *myname) +{ + msg_fatal("usage: %s type:file read|write|create [fold] [sync]", myname); +} + +void dict_test(int argc, char **argv) +{ + VSTRING *keybuf = vstring_alloc(1); + VSTRING *inbuf = vstring_alloc(1); + DICT *dict; + char *dict_name; + int open_flags; + char *bufp; + char *cmd; + const char *key; + const char *value; + int ch; + int dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE; + int n; + + signal(SIGPIPE, SIG_IGN); + + msg_vstream_init(argv[0], VSTREAM_ERR); + while ((ch = GETOPT(argc, argv, "v")) > 0) { + switch (ch) { + default: + usage(argv[0]); + case 'v': + msg_verbose++; + break; + } + } + optind = OPTIND; + if (argc - optind < 2) + usage(argv[0]); + if (strcasecmp(argv[optind + 1], "create") == 0) + open_flags = O_CREAT | O_RDWR | O_TRUNC; + else if (strcasecmp(argv[optind + 1], "write") == 0) + open_flags = O_RDWR; + else if (strcasecmp(argv[optind + 1], "read") == 0) + open_flags = O_RDONLY; + else + msg_fatal("unknown access mode: %s", argv[2]); + for (n = 2; argv[optind + n]; n++) { + if (strcasecmp(argv[optind + 2], "fold") == 0) + dict_flags |= DICT_FLAG_FOLD_ANY; + else if (strcasecmp(argv[optind + 2], "sync") == 0) + dict_flags |= DICT_FLAG_SYNC_UPDATE; + else + usage(argv[0]); + } + dict_name = argv[optind]; + dict = dict_open(dict_name, open_flags, dict_flags); + dict_register(dict_name, dict); + while (vstring_fgets_nonl(inbuf, VSTREAM_IN)) { + bufp = vstring_str(inbuf); + if (!isatty(0)) { + vstream_printf("> %s\n", bufp); + vstream_fflush(VSTREAM_OUT); + } + if (*bufp == '#') + continue; + if ((cmd = mystrtok(&bufp, " ")) == 0) { + vstream_printf("usage: del key|get key|put key=value|first|next\n"); + vstream_fflush(VSTREAM_OUT); + continue; + } + if (dict_changed_name()) + msg_warn("dictionary has changed"); + key = *bufp ? vstring_str(unescape(keybuf, mystrtok(&bufp, " ="))) : 0; + value = mystrtok(&bufp, " ="); + if (strcmp(cmd, "del") == 0 && key && !value) { + if (dict_del(dict, key)) + vstream_printf("%s: not found\n", key); + else + vstream_printf("%s: deleted\n", key); + } else if (strcmp(cmd, "get") == 0 && key && !value) { + if ((value = dict_get(dict, key)) == 0) { + vstream_printf("%s: %s\n", key, + dict_errno == DICT_ERR_RETRY ? + "soft error" : "not found"); + } else { + vstream_printf("%s=%s\n", key, value); + } + } else if (strcmp(cmd, "put") == 0 && key && value) { + /* XXX dict_put returns void, so dict_memcache sets dict_errno. */ + dict_errno = 0; + dict_put(dict, key, value); + if (dict_errno) + vstream_printf("%s: soft error\n", key); + else + vstream_printf("%s=%s\n", key, value); + } else if (strcmp(cmd, "first") == 0 && !key && !value) { + if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0) + vstream_printf("%s=%s\n", key, value); + else + vstream_printf("%s\n", + dict_errno == DICT_ERR_RETRY ? + "soft error" : "not found"); + } else if (strcmp(cmd, "next") == 0 && !key && !value) { + if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0) + vstream_printf("%s=%s\n", key, value); + else + vstream_printf("%s\n", + dict_errno == DICT_ERR_RETRY ? + "soft error" : "not found"); + } else { + vstream_printf("usage: del key|get key|put key=value|first|next\n"); + } + vstream_fflush(VSTREAM_OUT); + } + vstring_free(keybuf); + vstring_free(inbuf); + dict_close(dict); +}