-TDICT_PCRE_PRESCAN_CONTEXT
-TDICT_PCRE_REGEXP
-TDICT_PCRE_RULE
+-TDICT_PROXY
-TDICT_REGEXP
-TDICT_REGEXP_EXPAND_CONTEXT
-TDICT_REGEXP_IF_RULE
properly quoted just like the null address. File:
global/quote_82[12]_local.c.
-
20021217
Cleanup: more work on the trivial-rewrite address rewriting
virtual alias class (error:User unknown) result. File:
trivial-rewrite/transport.c.
+20030101
+
+ Documentation update: new-style virtual domains broke the
+ advanced content filtering example. Files: FILTER_README,
+ RELEASE_NOTES.
+
+20030104
+
+ Cleanup: avoid warnings about flag mismatches when the same
+ lookup table is listed under both virtual_alias_maps and
+ virtual_mailbox_maps. Files: global/virtual8.h, virtual/virtual.c.
+
+ Bugfix: an obscure memory leak that puzzled me for more
+ than a year until I found out how to reproduce it. File:
+ util/vstream.c.
+
+20030106
+
+ Robustness: the master no longer aborts with "address
+ already in use" when inet_interfaces specifies the same IP
+ address multiple times, or when a TCP service in master.cf
+ specifies a hostname for which the same IP address is listed
+ multiple times. File: master/master_ent.c.
+
+20030107
+
+ Robustness: check that FILTER actions in SMTPD access maps
+ or cleanup header/body_checks have plausible syntax. Files:
+ smtpd/smtpd_check.c, cleanup/cleanup_message.c.
+
+20030110
+
+ Cleanup: the virtual_mailbox_maps parameter is now optional
+ even when virtual_mailbox_domains is specified. This makes
+ virtual mailbox domains more like relay domains and the
+ local domain.
+
+ Portability: the makedefs script now uses the pcre-config
+ utility to find out where things are installed.
+
+ Bugfix: the SMTP server did not recognize the local built-in
+ double bounce address as local. Reported by Matthias Andree.
+ For safety sake, threw in the local postmaster address as
+ well. File: smtpd/smtpd_check.c.
+
Open problems:
Low: after successful delivery, per-queue window += 1/window,
src/lmtp src/trivial-rewrite src/qmgr src/smtp src/bounce src/pipe \
src/showq src/postalias src/postcat src/postconf src/postdrop \
src/postkick src/postlock src/postlog src/postmap src/postqueue \
- src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual
+ src/postsuper src/nqmgr src/qmqpd src/spawn src/flush src/virtual \
+ src/proxymap
MANDIRS = proto man html
default: update
is $virtual_alias_maps for Postfix 1.1 compatibility)
virtual For hosted domains with their own mailboxes
-mailbox Known recipients are listed in $virtual_mailbox_maps
+mailbox Known recipients are listed in $virtual_mailbox_maps (if
+ this parameter is empty, the Postfix SMTP server accepts
+ all recipients for domains listed in $virtual_mailbox_domains)
Domain names are listed in $virtual_mailbox_domains (default
is $virtual_mailbox_maps for Postfix 1.1 compatibility)
Default delivery agent: virtual
relay For remote destinations that list your system as MX host
Domain names are listed in $relay_domains
- Known recipients are listed in $relay_recipient_maps (default
- is empty; if $relay_recipient_maps is empty, the Postfix
- SMTP server accepts all recipients)
+ Known recipients are listed in $relay_recipient_maps (if
+ this parameter is empty, the Postfix SMTP server accepts
+ all recipients for domains listed in $relay_domains)
Default delivery agent: relay (clone of default smtp agent)
other Restricted to mail from authorized clients
+Introduction
+============
+
This is a very first implementation of Postfix content filtering.
A Postfix content filter receives unfiltered mail from Postfix and
-either bounces the mail or re-injects filtered mail back into Postfix.
+does one of the following:
+
+- re-injects the mail back into Postfix, perhaps after changing content
+- rejects the mail (by sending a suitable status code back to
+ Postfix) so that it is returned to sender.
+- sends the mail somewhere else
+
+This document describes two approaches to content filtering: simple
+and advanced. Both filter all the mail by default.
-This document describes two approaches to content filtering.
+At the end are examples that show how to filter only mail from
+users, about using different filters for different domains that
+you provide MX service for, and about selective filtering on the
+basis of message envelope and/or header/body patterns.
Simple content filtering example
================================
The first example is simple to set up. It uses a shell script that
receives unfiltered mail from the Postfix pipe delivery agent, and
that feeds filtered mail back into the Postfix sendmail command.
+
Only mail arriving via SMTP will be content filtered.
..................................
| |
+-Postfix sendmail<----filter script<--+
-The /some/where/filter program can be a simple shell script like this:
+Mail is filtered by a /some/where/filter program. This can be a
+simple shell script like this:
#!/bin/sh
exit $?
The idea is to first capture the message to file and then run the
-content through a third-party content filter program. If the
-mail cannot be captured to file, mail delivery is deferred by
-terminating with exit status 75 (EX_TEMPFAIL). If the content
-filter program finds a problem, the mail is bounced by terminating
-the shell script with exit status 69 (EX_UNAVAILABLE). If the
-content is OK, it is given as input to Postfix sendmail, and the
-exit status of the filter command is whatever exit status Postfix
-sendmail produces.
-
-I suggest that you play with this script for a while until you are
-satisfied with the results. Run it with a real message (headers+body)
-as input:
+content through a third-party content filter program.
+
+- If the mail cannot be captured to file, mail delivery is deferred
+ by terminating with exit status 75 (EX_TEMPFAIL). Postfix will
+ try again after some delay.
+
+- If the content filter program finds a problem, the mail is bounced
+ by terminating with exit status 69 (EX_UNAVAILABLE). Postfix
+ will return the message to the sender as undeliverable.
+
+- If the content is OK, it is given as input to the Postfix sendmail
+ command, and the exit status of the filter command is whatever
+ exit status the Postfix sendmail command produces. Postfix will
+ deliver the message as usual.
+
+I suggest that you run this script by hand until you are satisfied
+with the results. Run it with a real message (headers+body) as
+input:
% /some/where/filter -f sender recipient... <message-file
flags=Rq user=filter argv=/somewhere/filter -f ${sender} -- ${recipient}
To turn on content filtering for mail arriving via SMTP only, append
-"-o content_filter=filter:" to the master.cf entry that defines
+"-o content_filter=filter:dummy" to the master.cf entry that defines
the Postfix SMTP server:
/etc/postfix/master.cf:
- smtp inet ...stuff... smtpd
- -o content_filter=filter:
+ smtp inet ...stuff... smtpd
+ -o content_filter=filter:dummy
-Note the ":" at the end!! The content_filter configuration parameter
-accepts the same syntax as the right-hand side in a Postfix transport
-table. Execute "postfix reload" to complete the change.
+The content_filter configuration parameter accepts the same syntax
+as the right-hand side in a Postfix transport table. Execute
+"postfix reload" to complete the change.
To turn off content filtering, edit the master.cf file, remove the
-"-o content_filter=filter:" text from the entry that defines the
-Postfix SMTP server, and execute another "postfix reload".
+"-o content_filter=filter:dummy" text from the entry that defines
+the Postfix SMTP server, and execute another "postfix reload".
With the shell script as shown above you will lose a factor of four
in Postfix performance for transit mail that arrives and leaves
=================================
The problem with content filters like the one above is that they
-are not very robust, because the software does not talk a well-defined
-protocol with Postfix. If the filter shell script aborts because
-the shell runs into some memory allocation problem, the script will
-not produce a nice exit status as per /usr/include/sysexits.h and
-mail will probably bounce. The same lack of robustness is possible
+are not very robust. The reason is that the software does not talk
+a well-defined protocol with Postfix. If the filter shell script
+aborts because the shell runs into some memory allocation problem,
+the script will not produce a nice exit status as defined in the
+file /usr/include/sysexits.h. Instead of going to the deferred
+queue, mail will bounce. The same lack of robustness can happen
when the content filtering software itself runs into a resource
problem.
Advanced content filtering example
===================================
-The second example is considerably more complex, but can give much
-better performance, and is less likely to bounce mail when the
-machine runs into a resource problem. This approach uses content
-filtering software that can receive and deliver mail via SMTP.
+The second example is more complex, but can give much better
+performance, and is less likely to bounce mail when the machine
+runs into a resource problem. This approach uses content filtering
+software that can receive and deliver mail via SMTP.
+
+Some Anti-virus software is built to receive and deliver mail via
+SMTP and is ready to use as an advanced Postfix content filter.
+For non-SMTP capable content filtering software, Bennett Todd's
+SMTP proxy implements a nice PERL/SMTP content filtering framework.
+See: http://bent.latency.net/smtpprox/
+
+The example given here filters all mail, including mail that arrives
+via SMTP and mail that is locally submitted via the Postfix sendmail
+command.
You can expect to lose about a factor of two in Postfix performance
for transit mail that arrives and leaves via SMTP, provided that
new parameter:
/etc/postfix/main.cf:
- content_filter = scan:localhost:10025
+ content_filter = scan:localhost:10025
This causes Postfix to add one extra content filtering record to
each incoming mail message, with content scan:localhost:10025.
/etc/postfix/master.cf:
scan unix - - n - 10 smtp
- -o disable_dns_lookups=yes
-
-Turning off DNS lookups at this point can make a great difference
-in content filtering performance. It also isolates the content
-filtering process from temporary outages in DNS service.
-Instead of 10, use whatever limit is feasible for your machine.
-Content inspection software can gobble up a lot of system resources,
-so you don't want to have too much of it running at the same time.
+Instead of a limit of 10 concurrent processes, use whatever process
+limit is feasible for your machine. Content inspection software
+can gobble up a lot of system resources, so you don't want to have
+too much of it running at the same time.
The content filter can be set up with the Postfix spawn service,
which is the Postfix equivalent of inetd. For example, to instantiate
up to 10 content filtering processes on demand:
/etc/postfix/master.cf:
- localhost:10025 inet n n n - 10 spawn
- user=filter argv=/some/where/filter localhost 10026
+ localhost:10025 inet n n n - 10 spawn
+ user=filter argv=/some/where/filter localhost 10026
"filter" is a dedicated local user account. The user will never
log in, and can be given a "*" password and non-existent shell and
program.
Note: the localhost port 10025 SMTP server filter should announce
-itself as "220 localhost...", to silence warnings in the log.
+itself as "220 localhost...". Postfix aborts delivery when it
+connects to an SMTP server that uses the same hostname, because
+that normally means you have a mail delivery loop problem.
-The /some/where/filter command is most likely a PERL script. PERL
-has modules that make talking SMTP easy. The command-line specifies
-that mail should be sent back into Postfix via localhost port 10026.
-
-For now, it is left up to the Postfix users to come up with a
-PERL/SMTP framework for Postfix content filtering. If done well,
-it can be used with other mailers too, which is a nice spin-off.
+The example here assumes that the /some/where/filter command is a
+PERL script. PERL has modules that make talking SMTP easy. The
+command-line specifies that mail should be sent back into Postfix
+via localhost port 10026.
The simplest content filter just copies SMTP commands and data
between its inputs and outputs. If it has a problem, all it has to
/etc/postfix/master.cf:
localhost:10026 inet n - n - 10 smtpd
- -o content_filter=
- -o local_recipient_maps=
- -o myhostname=localhost.domain.tld
- -o smtpd_helo_restrictions=
- -o smtpd_client_restrictions=
- -o smtpd_sender_restrictions=
- -o smtpd_recipient_restrictions=permit_mynetworks,reject
- -o mynetworks=127.0.0.0/8
-
-This is just another SMTP server. The "-o content_filter=" requests
-no content filtering for incoming mail. The server has the same
-process limit as the "filter" master.cf entry.
-
-The "-o local_recipient_maps=" is a safety in case you have specified
-local_recipient_maps in the main.cf file. That could interfere with
-content filtering.
+ -o content_filter=
+ -o local_recipient_maps=
+ -o relay_recipient_maps=
+ -o myhostname=localhost.domain.tld
+ -o smtpd_helo_restrictions=
+ -o smtpd_client_restrictions=
+ -o smtpd_sender_restrictions=
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+ -o mynetworks=127.0.0.0/8
+
+Warning for Postfix version 2 users: in this SMTP server after the
+content filter, do not override main.cf settings for virtual_alias_maps
+or virtual_alias_domains. That would cause mail to be rejected with
+"User unknown".
+
+This SMTP server has the same process limit as the "filter" master.cf
+entry.
+
+The "-o content_filter=" requests no content filtering for incoming
+mail.
+
+The "-o local_recipient_maps=" and "-o relay_recipient_maps=" avoid
+unnecessary table lookups.
The "-o myhostname=localhost.domain.tld" avoids a possible problem
-if the content filter is picky about the hostname that Postfix
-sends in SMTP server replies.
+if your content filter is based on a proxy that simply relays SMTP
+commands.
The "-o smtpd_xxx_restrictions" and "-o mynetworks=127.0.0.0/8"
turn off UCE controls that would only waste time here.
Many refinements are possible, such as running a specially-configured
smtp delivery agent for feeding mail into the content filter, and
-turning off address rewriting before or after content filtering.
+turning off address rewriting before content filtering.
As the example below shows, things quickly become very complex,
because a lot of main.cf like information gets listed in the
If you need to squeeze out more performance, it is probably simpler
to run multiple Postfix instances, one before and one after the
content filter. That way, each instance can have simple main.cf
-and master.cf files, and the system will be easier to understand.
+and master.cf files, each instance can have its own mail queue,
+and the system will be easier to understand.
As before, we will set up a content filtering program that receives
SMTP mail via localhost port 10025, and that submits SMTP mail back
#
smtp inet n - n - - smtpd
#
+# ------------------------------------------------------------------
+#
# This is the cleanup daemon that handles messages in front of
-# the content filter, it does header_checks and body_checks (if
-# any), but does not do any address rewriting.
+# the content filter. It does header_checks and body_checks (if
+# any), but does no virtual alias or canonical address mapping.
#
-# The address rewriting happens in the second cleanup phase after
-# the content filter. This gives the content_filter access to
-# *largely* unmodified addresses for maximum flexibility.
+# Virtual alias or canonical address mapping happens in the second
+# cleanup phase after the content filter. This gives the content_filter
+# access to *largely* unmodified addresses for maximum flexibility.
#
-# The trivial-rewrite daemon handles the logic of append_myorigin
-# and append_dot_mydomain, turning these off requires two
-# trivial-rewrite services, by which point (if you are not
-# already) you are much better off with two complete Postfix
-# instances one in front of and one behind the content filter.
+# Turning off append_myorigin/append_dot_mydomain address rewriting
+# before the content filter would require two instances of the
+# trivial-rewrite daemon. If you want to go to this trouble then
+# you're clearly better off with two complete Postfix instances: one
+# in front of and one behind the content filter.
#
# Note that some sites may specifically want to do the opposite:
# perform rewrites in front of the content_filter which would
-# then see only cleaned up addresses, in this case the parameter
-# settings below should be moved to the second "cleanup"
-# instance.
+# then see only cleaned up addresses. In that case the "-o" parameter
+# settings below should be moved to the second "cleanup" instance.
#
cleanup unix n - n - 0 cleanup
- -o canonical_maps=
- -o sender_canonical_maps=
- -o recipient_canonical_maps=
- -o masquerade_domains=
- -o virtual_maps=
+ -o canonical_maps=
+ -o sender_canonical_maps=
+ -o recipient_canonical_maps=
+ -o masquerade_domains=
+ -o virtual_alias_maps=
+#
+# ------------------------------------------------------------------
#
# This is the delivery agent that injects mail into the content
-# filter. It is tuned for low latency and low concurrency, most
-# content filters burn CPU and high concurrency causes thrashing.
-# The process limit of 10 reenforces the effect of
-# $default_destination_concurrency_limit, even without an
-# explicit process limit, the concurrency is bounded because all
-# messages heading into the content filter have the same
-# destination. The "disable_dns_lookups" setting prevents the
-# delivery agent from consuming precious "bandwidth" in the
-# narrow deliver channel waiting for slow DNS responses. It also
-# ensures that the original envelope recipient is seen by the
-# content filter.
+# filter. It is tuned for low concurrency, because most content
+# filters burn CPU and use lots of memory. The process limit of 10
+# re-enforces the effect of $default_destination_concurrency_limit.
+# Even without an explicit process limit, the concurrency is bounded
+# because all messages heading into the content filter have the same
+# destination.
#
scan unix - - n - 10 smtp
- -o disable_dns_lookups=yes
+#
+# ------------------------------------------------------------------
#
# This is the SMTP listener that receives filtered messages from
# the content filter. It *MUST* clear the content_filter
# parameter to avoid loops, and use a different hostname to avoid
# triggering the Postfix SMTP loop detection code.
#
-#
-# Since all recipients have been validated by the first "smtpd",
-# clear local_recipient_maps, virtual_maps and
-# virtual_mailbox_maps.
-#
# This "smtpd" uses a separate cleanup that does no header or
# body checks, but does do the various address rewrites disabled
# in the first cleanup.
-o content_filter=
-o myhostname=localhost.domain.tld
-o local_recipient_maps=
- -o virtual_maps=
- -o virtual_mailbox_maps=
+ -o relay_recipient_maps=
-o cleanup_service_name=cleanup2
-o mynetworks=127.0.0.0/8
-o mynetworks_style=host
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
#
-# This is the second cleanup daemon. No header or body checks.
-# If preferable, enable rewrites in the first cleanup daemon, and
-# disable them here.
+# Do not override main.cf settings here for virtual_alias_maps or
+# virtual_mailbox_maps. This causes mail to be rejected with "User
+# unknown in virtual (alias|mailbox) recipient table".
+#
+# ------------------------------------------------------------------
+#
+# This is the second cleanup daemon. No header or body checks,
+# because those have already been taken care of by the cleanup instance
+# before the content filter. The second cleanup instance does all the
+# virtual alias and canonical address mapping that was disabled in
+# the first cleanup instance.
+#
+# If it is preferable to do the virtual alias and canonical address
+# mapping before the content filter, delete the "-o" lines that
+# disable canonical and virtual mappings in the above cleanup daemon
+# instance and insert them here.
#
cleanup2 unix n - n - 0 cleanup
-o header_checks=
-o nested_header_checks=
-o body_checks=
#
+# ------------------------------------------------------------------
+#
# The normal "smtp" delivery agent for contrast with "scan".
-# Definitely do not set "disable_dns_lookups = yes" here if you
-# send mail to the Internet.
#
smtp unix - - n - - smtp
-This causes Postfix to add one extra content filtering record to
-each incoming mail message, with content scan:localhost:10025.
+The above example causes Postfix to add one content filtering record
+to each incoming mail message, with content scan:localhost:10025.
You can use the same syntax as in the right-hand side of a Postfix
transport table. The content filtering records are added by the
smtpd and pickup servers.
See the previous example for setting up the content filter with
the Postfix spawn service; you can of course use any server that
can be run stand-alone outside the Postfix environment.
+
+Filtering mail from outside users only
+======================================
+
+The easiest approach is to configure ONE Postfix instance with TWO
+SMTP server addresses in master.cf:
+
+- One SMTP server address for inside users only that never invokes
+ content filtering.
+
+- One SMTP server address for outside users that always invokes
+ content filtering.
+
+/etc/postfix.master.cf:
+ # SMTP service for internal users only, no content filtering.
+ 1.2.3.4:smtp inet n - n - - smtpd
+ -o smtpd_client_restrictions=permit_mynetworks,reject
+ 127.0.0.1:smtp inet n - n - - smtpd
+ -o smtpd_client_restrictions=permit_mynetworks,reject
+
+ # SMTP service for external users, with content filtering.
+ 1.2.3.5:smtp inet n - n - - smtpd
+ -o content_filter=foo:bar
+
+Different content filters for different MX domains
+==================================================
+
+This is a variant on the previous example. You configure ONE
+Postfix instance with multiple SMTP server addresses. Each
+SMTP server invokes a different content filter.
+
+/etc/postfix.master.cf:
+ # MX server for destinations that use the foo:bar content filter.
+ 1.2.3.5:smtp inet n - n - - smtpd
+ -o content_filter=foo:bar
+ -o relay_domains=/etc/postfix/foo-bar-domains
+ -o smtpd_recipient_restrictions=reject_unauth_destination
+
+ # MX server for destinations that use the bar:baz content filter.
+ 1.2.3.6:smtp inet n - n - - smtpd
+ -o content_filter=bar:baz
+ -o relay_domains=/etc/postfix/bar-baz-domains
+ -o smtpd_recipient_restrictions=reject_unauth_destination
+
+ # SMTP servers for internal users only.
+ 1.2.3.4:smtp inet n - n - - smtpd
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+ 127.0.0.1:smtp inet n - n - - smtpd
+ -o smtpd_recipient_restrictions=permit_mynetworks,reject
+
+Getting really nasty
+====================
+
+The above filtering configurations are static. Mail that follows
+a given path is either always filtered or it is never filtered. As
+of Postfix 2.0 you can also turn on content filtering on the fly.
+The Postfix UCE features allow you to specify a filtering action
+on the fly:
+
+ FILTER foo:bar
+
+You can do this in smtpd access maps as well as the cleanup server's
+header/body_checks. This feature must be used with great care:
+you must disable all the UCE features in the after-filter smtpd
+and cleanup daemons or else you will have a content filtering loop.
+
+Limitations:
+
+- There can be only one content filter action per message.
+
+- FILTER actions from smtpd access maps and header/body_checks take
+ precedence over filters specified with the main.cf content_filter
+ parameter.
+
+- Only the last FILTER action from smtpd access maps or in
+ header/body_checks takes effect.
+
+- The same content filter is applied to all the recipients of a
+ given message.
You need to add the database that lists the non-UNIX users:
/etc/postfix/main.cf
- local_recipient_maps = unix_passwd.byname, $alias_maps,
+ local_recipient_maps = unix:passwd.byname, $alias_maps,
<the database with non-UNIX accounts>
Your database will be searched for the user@domain address as
Older Microsoft SMTP client software implements a non-standard
version of the AUTH protocol syntax, and expects that the SMTP
server replies to EHLO with "250 AUTH=stuff" instead of "250 AUTH
-stuff". To accomodate such clients in addition to conformant
+stuff". To accommodate such clients in addition to conformant
clients, set "broken_sasl_auth_clients = yes" in the main.cf file.
Testing SASL authentication in the Postfix SMTP server
+==============================================================
+NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+==============================================================
+Before upgrading from Postfix 1.1 you must stop Postfix ("postfix
+stop"). Some internal protocols have changed. No mail will be
+lost if you fail to stop and restart Postfix, but Postfix won't be
+able to receive any new mail, either.
+==============================================================
+NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
+==============================================================
+
In the text below, changes are labeled with the Postfix snapshot
that introduced the change, and whether the change introduced a
feature, an incompatibility, or whether the feature is obsolete.
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
-Major changes with Postfix version 2.0.0 (released 20021222)
+Incompatible changes with Postfix version 2.0.1 (released 20030112)
+===================================================================
+
+If you upgrade from Postfix 1.1 you need to restart Postfix.
+
+If you upgrade from Postfix 2.0 you need to "reload" Postfix.
+
+Version 2.0.1 introduces the proxymap service for centralized table
+lookup. The upgrade procedure adds the proxymap service to the
+master.cf file. If you see errors about problems contacting the
+proxymap service, then you did not properly upgrade Postfix.
+
+The Postfix SMTP server now by default looks up the UNIX passwd
+file via the new proxymap service, in order to make chrooted
+operation easier.
+
+The Postfix build procedure now uses the pcre-config utility (part
+of PCRE version 3) to find out the pathnames of the PCRE include
+file and object library, instead of probing /usr/include and/or
+/usr/lib. To build with PCRE version 2 support you will have to
+specify pathnames as described in PCRE_README. To build without
+PCRE support, specify: make Makefiles CCARGS="-DNO_PRCE".
+
+Major changes with Postfix version 2.0.1 (released 20030112)
============================================================
+This release introduces the proxymap service for Postfix lookup
+table access. This can be used to overcome chroot restrictions in
+the Postfix SMTP server (specify proxy:unix:passwd.byname for
+password file lookup through the proxymap server) and can be used
+to consolidate the number of open tables by sharing one open table
+among multiple processes (specify proxy:mysql:/file/name to avoid
+"too many connections" conditions). The proxy_read_maps parameter
+specifies what maps are approved for access via the proxy service
+(only map references starting with "proxy:" are considered approved).
+
+Major changes with Postfix version 2.0.0 (released 20021222, 20021223)
+======================================================================
+
First comes the bad news - things that may break when you upgrade
from Postfix 1.1. Then comes the good news - things that evolved
in snapshots over the past year.
For details, see the VIRTUAL_README file.
+[Incompat 20021209] If you use the "advanced content filter"
+technique, you MUST NOT override the virtual aliases and virtual
+mailbox settings in the SMTP server that receives mail from the
+content filter, or else mail for virtual recipients will be rejected
+with "User unknown".
+
+For details, see the FILTER_README file.
+
Incompatible queue file format changes
======================================
MIME headers in attachments. This is much more efficient than
previous versions that recognized MIME headers via body_checks.
MIME headers are now processed one multi-line header at a time,
-instead of one body line at a time. To get the the old behavior,
+instead of one body line at a time. To get the old behavior,
specify "disable_mime_input_processing = yes". More details in
conf/sample-filter.cf.
given in the pcre_table(5) and regexp_table(5) manual pages.
[Feature 20020717] The default timeout for establishing an SMTP
-connection has been reduced to 30 seconds, because many systems
-have an atrociously large default timeout value.
+connection has been reduced to 30 seconds, because many system
+TCP/IP stacks have an atrociously large default timeout value.
[Feature 20020505] Finer control over Berkeley DB memory usage,
The parameter "berkeley_db_create_buffer_size" (default: 16 MBytes)
specifies the buffer size for the postmap and postalias commands.
-The parameter "berkeley_db_read_buffer_size" (default: 256 kBytes)
-speficies the buffer size for all other applications. Specify
+The parameter "berkeley_db_read_buffer_size" (default: 128 kBytes)
+specifies the buffer size for all other applications. Specify
"berkeley_db_read_buffer_size = 1048576" to get the old read buffer
-size. For more information, see the last paragraphs of the DB_README
-file.
+size. Contributed by Victor Duchovni. For more information, see
+the last paragraphs of the DB_README file.
-Improved compatibitity
+[Incompat 20021211] The default process limit is doubled from 50
+to 100. The default limits on the number of active queue files or
+recipients are doubled from 10000 to 20000. The default concurrency
+for parallel delivery to the same destination is doubled from 10
+to 20.
+
+Improved compatibility
======================
[Feature 20020527] The Postfix SMTP client will now convert 8BITMIME
MIME headers in attachments. This is much more efficient than
previous versions that recognized MIME headers via body_checks.
MIME headers are now processed one multi-line header at a time,
-instead of one body line at a time. To get the the old behavior,
+instead of one body line at a time. To get the old behavior,
specify "disable_mime_input_processing = yes". More details in
conf/sample-filter.cf.
the original recipient address in the X-Original-To: message header.
This header can also be emitted by the pipe(8) delivery agent.
+[Incompat 20021028] With "domain in one mailbox", one message with
+multiple recipients is no longer delivered only once. It is now
+delivered as one copy for each original recipient, with the original
+recipient address listed in the X-Original-To: message header.
+
[Feature 20021024] New proxy_interfaces parameter, for sites behind a
network address translation gateway or other type of proxy. You
should specify all the proxy network addresses here, to avoid avoid
The parameter "berkeley_db_create_buffer_size" (default: 16 MBytes)
specifies the buffer size for the postmap and postalias commands.
The parameter "berkeley_db_read_buffer_size" (default: 256 kBytes)
-speficies the buffer size for all other applications. Specify
+specifies the buffer size for all other applications. Specify
"berkeley_db_read_buffer_size = 1048576" to get the old read buffer
size. For more information, see the last paragraphs of the DB_README
file.
#
# - You define $mydestination domain recipients in files other than
# /etc/passwd, /etc/aliases, or the $virtual_alias_maps files.
-# For example, you define $mydestination domain recipients in
+# For example, you define $mydestination domain recipients in
# the $virtual_mailbox_maps files.
#
-# - You redefined the local delivery agent in master.cf.
+# - You redefine the local delivery agent in master.cf.
#
-# - You redefined the "local_transport" setting in main.cf.
+# - You redefine the "local_transport" setting in main.cf.
#
# - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
# feature of the Postfix local delivery agent (see sample-local.cf).
#
# Beware: if the Postfix SMTP server runs chrooted, you probably have
-# to copy the passwd (not shadow) database into the jail, and perhaps
-# other files. This is system dependent.
+# to access the passwd file via the proxymap service, in order to
+# overcome chroot restrictions. The alternative, having a copy of
+# the system passwd file in the chroot jail is just not practical.
#
#local_recipient_maps = unix:passwd.byname $alias_maps
+#local_recipient_maps = proxy:unix:passwd.byname $alias_maps
#local_recipient_maps =
# The unknown_local_recipient_reject_code specifies the SMTP server
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
-# (yes) (yes) (yes) (never) (50)
+# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
#628 inet n - n - - qmqpd
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
flush unix n - n 1000? 0 flush
+proxymap unix - - n - - proxymap
smtp unix - - n - - smtp
relay unix - - n - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
$POSTCONF -e "$unknown_local = 450" || exit 1
fi
+ # Add missing proxymap service to master.cf.
+
+ grep '^proxymap.*proxymap' $config_directory/master.cf >/dev/null || {
+ echo Editing $config_directory/master.cf, adding missing entry for proxymap service
+ cat >>$config_directory/master.cf <<EOF || exit 1
+proxymap unix - - n - - proxymap
+EOF
+ }
+
}
# A reminder if this is the first time Postfix is being installed.
$daemon_directory/nqmgr:f:root:-:755
$daemon_directory/pickup:f:root:-:755
$daemon_directory/pipe:f:root:-:755
+$daemon_directory/proxymap:f:root:-:755
$daemon_directory/qmgr:f:root:-:755
$daemon_directory/qmqpd:f:root:-:755
$daemon_directory/showq:f:root:-:755
$manpage_directory/man8/nqmgr.8:f:root:-:644
$manpage_directory/man8/pickup.8:f:root:-:644
$manpage_directory/man8/pipe.8:f:root:-:644
+$manpage_directory/man8/proxymap.8:f:root:-:644
$manpage_directory/man8/qmgr.8:f:root:-:644
$manpage_directory/man8/qmqpd.8:f:root:-:644
$manpage_directory/man8/showq.8:f:root:-:644
# /^postmaster@/ OK
#
# # Protect your outgoing majordomo exploders
-# /^(.*)-outgoing@(.*)$/!/^owner-/ 550 Use ${1}@${2} instead
+# if !/^owner-/
+# /^(.*)-outgoing@(.*)$/ 550 Use ${1}@${2} instead
+# endif
#
# EXAMPLE HEADER FILTER MAP
# # These were once common in junk mail.
# precedence, from highest to lowest priority: mailbox_transport,
# mailbox_command_maps, mailbox_command, home_mailbox.
+#
+# MISCELLANEOUS PARAMETERS
+#
+
# The biff parameter specifies whether or not to contact the biff
# server. This server sends "new mail" notifications to users who
# have requested new mail notification with "biff y".
# The ipc_idle parameter bounds the idle time for internal communication
# channels after which a client disconnects voluntarily. The purpose
# is to allow servers to terminate voluntarily after they become
-# idle. Currently this is used by the address resolving and rewriting
-# clients.
+# idle. This is used, for example, by the address resolving and
+# rewriting clients.
#
# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
# The default time unit is s (seconds).
# a name matches a lookup key. Continue long lines by starting the
# next line with whitespace.
#
-# See sample-local.cf for a description of the local_recipient_maps
+# See sample-smtpd.cf for a description of the local_recipient_maps
# and unknown_local_recipient_reject_code parameters. By default,
# the SMTP server rejects mail for recipients not listed with the
# local_recipient_maps parameter.
# message header filtering. See pcre_table(5) for syntax description.
#
# Message headers are filtered one at a time. This filter understands
-# multi-line message headers. However, the message header filter has
-# no knowledge of MIME headers that are embedded in the message body.
+# multi-line message headers, including MIME headers in the message
+# body.
#
# The first field is a perl-like regular expression. The expression
# delimiter can be any character except whitespace, or characters
# destination. This is the default limit for delivery via SMTP, via
# the local delivery agent and via the pipe mailer.
#
-default_destination_concurrency_limit = 10
+default_destination_concurrency_limit = 20
# The default_destination_recipient_limit parameter specifies a
# default limit on the number of recipients per message delivery.
# for a description of the syntax.
#
# Message headers are filtered one at a time. This filter understands
-# multi-line mail headers. However, the message header filter has no
-# knowledge of MIME headers that are embedded in the message body.
+# multi-line mail headers, including MIME headers in the message body.
#
# The general format of a table entry is PATTERN RESULT.
#
# The default limit is the default_destination_concurrency_limit
# parameter. It is probably safer to limit the concurrency to 10.
#
-smtp_destination_concurrency_limit = 10
+smtp_destination_concurrency_limit = 20
# The smtp_destination_recipient_limit parameter limits the number
# of recipients per delivery via the smtp delivery agent.
# This file contains example settings of Postfix configuration parameters
# that control the SMTP server program.
+# REJECTING MAIL FOR UNKNOWN LOCAL USERS
+#
+# The local_recipient_maps parameter specifies optional lookup tables
+# with all names or addresses of users that are local with respect
+# to $mydestination and $inet_interfaces.
+#
+# If this parameter is defined, then the SMTP server will reject
+# mail for unknown local users. This parameter is defined by default.
+#
+# To turn off local recipient checking in the SMTP server, specify
+# local_recipient_maps = (i.e. empty).
+#
+# The default setting assumes that you use the default Postfix local
+# delivery agent for local delivery. You need to update the
+# local_recipient_maps setting if:
+#
+# - You define $mydestination domain recipients in files other than
+# /etc/passwd, /etc/aliases, or the $virtual_alias_maps files.
+# For example, you define $mydestination domain recipients in
+# the $virtual_mailbox_maps files.
+#
+# - You redefine the local delivery agent in master.cf.
+#
+# - You redefine the "local_transport" setting in main.cf.
+#
+# - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
+# feature of the Postfix local delivery agent (see sample-local.cf).
+#
+# Beware: if the Postfix SMTP server runs chrooted, you probably have
+# to access the passwd file via the proxymap service, in order to
+# overcome chroot restrictions. The alternative, having a copy of
+# the system passwd file in the chroot jail is just not practical.
+#
+#local_recipient_maps =
+#local_recipient_maps = unix:passwd.byname $alias_maps
+local_recipient_maps = proxy:unix:passwd.byname $alias_maps
+
+# The unknown_local_recipient_reject_code specifies the SMTP server
+# response code when a recipient domain matches $mydestination or
+# $inet_interfaces, while $local_recipient_maps is non-empty and the
+# recipient address or address local-part is not found.
+#
+# The default setting is 550 (reject mail) but it is safer to start
+# with 450 (try again later) until you are certain that your
+# local_recipient_maps settings are OK.
+#
+#unknown_local_recipient_reject_code = 450
+unknown_local_recipient_reject_code = 550
+
+# REJECTING UNKNOWN RELAY USERS
+#
+# The relay_recipient_maps parameter specifies optional lookup tables
+# with all addresses in the domains that match $relay_domains.
+#
+# If this parameter is defined, then the SMTP server will reject
+# mail for unknown relay users. This feature is off by default.
+#
+#relay_recipient_maps = hash:/etc/postfix/relay_recipients
+
#
# SENDER ANTI-SPOOFING
#
for dir in etc/default etc/inet dev usr/lib usr/share/lib/zoneinfo ; do
if [ ! -d ${CHROOT}/${dir} ]; then mkdir -p ${CHROOT}/${dir} ; fi
done
-chmod -R 755 ${CHROOT}
+#chmod -R 755 ${CHROOT}
# AFS support.
if [ "`echo $CHROOT | cut -c1-4`" = "/afs" ]; then
DAEMONS = bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
lmtp.8.html master.8.html pickup.8.html pipe.8.html qmgr.8.html \
showq.8.html smtp.8.html smtpd.8.html trivial-rewrite.8.html \
- nqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html
+ nqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
+ proxymap.8.html
COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
+proxymap.8.html: ../src/proxymap/proxymap.c
+ PATH=../mantools:$$PATH; \
+ srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
+
qmgr.8.html: ../src/qmgr/qmgr.c
PATH=../mantools:$$PATH; \
srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
<p>
+<li>The <a href="proxymap.8.html">proxymap</a> daemon provides
+read-only lookup service to Postfix client processes. The purpose
+is to overcome chroot restrictions, and to consolidate the number
+of open lookup tables by sharing one open table among multiple
+processes.
+
+<p>
+
<li>The <a href="spawn.8.html">spawn</a> daemon listens on a TCP
port, UNIX-domain socket or FIFO, and runs non-Postfix commands on
request, with the socket or FIFO connected to the standard input,
<li><a href="#nopass">What does "warning: cannot access UNIX password database" mean?</a>
+<li><a href="#loop">What does "Error: too many hops" mean?</a>
+
<li><a href="#noalias">What does "fatal: open database /etc/aliases.db" mean?</a>
<li><a href="#noservice">What does "fatal: unknown service: smtp/tcp" mean?</a>
<a name="content_filtering"><h3>Content filtering</h3>
+<ul>
+
+<li><a href="#loop">What does "Error: too many hops" mean?</a>
+
</ul>
<a name="other_transports"><h3>Other transports: UUCP, FAX, etc.</h3>
Specify what recipients exist (so that your queue does not fill up
with undeliverable mail from spammers).
-<p.
+<p>
Specify <tt>local_recipient_maps =</tt> if maintaining recipient
information is not practical.
<p>
-Your problem could be that the disk is saturated with I/O from
-receiving mail, so that the Postfix queue manager gets insufficient
-chance to process the requests (many SMTP server processes are
-competing for disk access against one poor queue manager).
+Your problem could be one of several.
+
+<p>
+
+<ul>
+
+<li>You're trying to send mail to difficult to reach sites (Hotmail,
+Yahoo, etc.). Solution: set up transport map entries that give special
+treatment (many parallel connections, short connection timeouts):
+
+<p>
+
+<pre>
+/etc/postfix/main.cf:
+ transport_maps = hash:/etc/postfix/transport
+ deadbeats_destination_concurrency_limit = 50
+
+/etc/postfix/transport:
+ hotmail.com deadbeats:
+ yahoo.com deadbeats:
+
+/etc/postfix/master.cf:
+ deadbeats unix - - n - - smtp
+ -o smtp_connect_timeout=5 -o smtp_helo_timeout=5
+</pre>
+
+<p>
+
+<li>Incoming mail, destined for a small number of inside mailhubs,
+is competing with outgoing mail to the Internet. As of Postfix
+version 2, this should be less of a problem. However, when a single
+internal mailhub goes down, it can totally ruin the performance
+because Postfix is wasting huge amounts of time on connection
+timeouts. The solution is to specify shorter connection timeouts
+for the inbound <b>relay</b> transport:
<p>
-You solve the problem by getting faster disks.
+<pre>
+/etc/postfix/main.cf:
+ mydestination = my.own.host.name
+ relay_domains = my.corp.domain
+ relay_transport = relay
+
+/etc/postfix/master.cf:
+ relay unix - - n - - smtp
+ -o smtp_connect_timeout=2 -o smtp_helo_timeout=2
+</pre>
<p>
-I am still solving the scheduling problem from the software side,
-but don't hold your breath.
+<li>The disk is saturated with I/O from
+receiving mail, so that the Postfix queue manager gets insufficient
+chance to process the requests (many SMTP server processes are
+competing for disk access against one poor queue manager).
+
+<p>
+
+You solve the problem by getting faster disks, and/or by using
+different disk drives for logging, mail queue, and mailboxes.
<p>
inet_interfaces = $myhostname
</pre>
+</ul>
+
<hr>
<a name="delay"><h3>Postfix responds slowly to incoming SMTP connections</h3></a>
DNS servers are broken and produce no reply when asked for a
non-existent MX record.
+<p> <li> Secondly, the nslookup test is invalid if you ran it as
+a privileged user. Postfix DNS lookups are known to fail because
+of incorrect permissions on system files and directories. For
+example, a common beginner's mistake is to lose world read permission
+for the <b>/etc/resolv.conf</b> file.
+
<p> <li>
Check out your Postfix <b>master.cf</b> file. If the SMTP client
<p>
-The warning message means that new mail notificiation failed because
-the <b>comsat</b> network service is turned off.
+The Postfix warning message means that new mail notification failed
+because the <b>comsat</b> network service is turned off.
<p>
<p>
+Note: recent versions of <b>procmail</b> also produce <b>biff</b>
+notifications. To silence <b>biff</b> completely you may also have
+to update <b>procmail</b> configuration files.
+
+<p>
+
To enable the <b>comsat</b> network service, uncomment the
corresponding entry in the <b>inetd.conf</b> file, and <b>kill -HUP</b>
the <b>inetd</b> process.
<pre>
/etc/postfix/main.cf:
- local_recipient_maps = $alias_maps, unix:passwd.byname
+ local_recipient_maps = $alias_maps, proxy:unix:passwd.byname
</pre>
<p>
+You need the <b>proxy:</b> part only if <b>master.cf</b> specifies
+that the Postfix SMTP server runs chrooted. As distributed by the
+author, Postfix runs no daemons chrooted.
+
+<p>
+
The local recipients tables are searched by the recipient address
(user@domain) and by the recipient name (the address minus the
domain). Postfix does not care what the lookup result looks like,
<ul>
-<li> If you run the Postfix SMTP server chrooted, it may be necessary
-to place a copy of the passwd file inside the chroot jail (typically:
-in <b>/var/spool/postfix/etc</b>). This is system dependent. The
-only way to find out is to try.
+<li> If you run the Postfix SMTP server chrooted, you need to access
+the system password database through the Postfix <a href="proxymap.8.html">
+proxymap</a> service, as shown in the above example. The alternative
+is simply not practical: placing a copy of the passwd file inside
+the chroot jail (typically: in <b>/var/spool/postfix/etc</b>)
+together with a list of system dependent files.
<p>
This message is logged when, for example, the Postfix SMTP server
is unable to access the UNIX password database.
+<p>
+
<ul>
<li> If you're running the Postfix SMTP server chrooted (see
-<b>master.cf</b>) then you may have to copy the password file and
-perhaps a bunch of other files into Postfix queue directory; a
-typical destination would be <b>/var/spool/postfix/etc</b>. See also
-the chroot setup scripts in the <b>examples</b> directory of the
-Postfix source code distribution.
+<b>master.cf</b>) then you need to access the system password
+database through the Postfix <a href="proxymap.8.html">proxymap</a>
+service. The alternative is not practical: copying the password
+file and perhaps a bunch of other system dependent files into the
+Postfix queue directory.
<p>
-<li> Be sure that you have world execute permissions on directories
-and world read permission on the passwd file and any auxiliary
-files that may be needed (such as <b>/etc/nsswitch.conf</b> and
-<b>libnss*.so*</b> files referenced by <b>/etc/nsswitch.conf</b>).
+<pre>
+ /etc/postfix/main.cf:
+ local_recipient_maps = proxy:unix:passwd.byname $alias_maps ...
+</pre>
+
+<p>
+
+<li> Chrooted or not, be sure that you have world execute permissions
+on directories and world read permission on the passwd file and
+any auxiliary files that may be needed (such as <b>/etc/nsswitch.conf</b>
+and <b>libnss*.so*</b> files referenced by <b>/etc/nsswitch.conf</b>).
</ul>
<p>
-Quick answer: set up a transport map entry that gives the mail to
-the Postfix local delivery agent:
+Quick answer: set up "punch through" virtual aliases that redirect
+the mail to local Postfix aliases:
<p>
<pre>
/etc/postfix/main.cf:
- transport_maps = hash:/etc/postfix/transport
+ virtual_alias_maps = hash:/etc/postfix/virtual
- /etc/postfix/transport:
- listname@virtual.tld local:
- owner-listname@virtual.tld local:
- listname-request@virtual.tld local:
+ /etc/postfix/virtual:
+ listname@virtual.tld listname
+ owner-listname@virtual.tld owner-listname
+ listname-request@virtual.tld listname-request
/etc/aliases:
listname: "|whatever"
<p>
+This redirects mail for virtual address <i>listname@virtual.tld</i>
+etc. to local address <i>listname@your.domain.tld</i> etc.. Mail
+for these local aliases is then delivered to external commands or
+files etc. by the Postfix local delivery agent.
+
+<p>
+
Long answer:
<p>
<hr>
+<a name="loop"><h3>What does "Error: too many hops" mean?</h3></a>
+
+Short answer: this message means that mail is probably looping. If
+you see this after you turned on Postfix content filtering, then
+you have made a mistake that causes mail to be filtered repeatedly.
+This is cured by appropriate use of <tt>content_filter=</tt>,
+<tt>header_checks=</tt>, and <tt>body_checks=</tt>.
+
+<p>
+
+Long answer: the message has too many Received: message headers.
+A received header is added whenever Postfix (or any MTA) receives
+a message. A large number of Received: message headers
+is an indication that mail is looping around.
+
+<p>
+
+Side comment: email uses the opposite of the technique that is used
+to avoid IP forwarding loops. With IP, the sender sets a TTL (time
+to live) field in the IP header. The field is decremented by each
+router. When the TTL reaches zero the packet is discarded and an
+ICMP error message is returned to the sender.
+
+<hr>
+
+
<a name="uucp-tcp"><h3>Using UUCP over TCP</h3>
This subject comes up whenever someone asks about a "domain in
were left behind after abnormal termination.
<b>-m</b> List the names of all supported lookup table types.
+ Postfix lookup tables are specified as <i>type</i><b>:</b><i>name</i>,
+ where <i>type</i> is one of the types listed below. The
+ table <i>name</i> syntax depends on the lookup table type.
- <b>btree</b> A sorted, balanced tree structure. This is
- available only on systems with support for
+ <b>btree</b> A sorted, balanced tree structure. This is
+ available only on systems with support for
Berkeley DB databases.
<b>dbm</b> An indexed file type based on hashing. This
- is available only on systems with support
+ is available only on systems with support
for DBM databases.
<b>environ</b>
The UNIX process environment array. The
- lookup key is the variable name. Originally
- implemented for testing, someone may find
+ lookup key is the variable name. Originally
+ implemented for testing, someone may find
this useful someday.
<b>hash</b> An indexed file type based on hashing. This
- is available only on systems with support
+ is available only on systems with support
for Berkeley DB databases.
<b>ldap</b> (read-only)
- Perform lookups using the LDAP protocol.
+ Perform lookups using the LDAP protocol.
This is described in an LDAP_README file.
<b>mysql</b> (read-only)
- Perform lookups using the MYSQL protocol.
+ Perform lookups using the MYSQL protocol.
This is described in a MYSQL_README file.
<b>pcre</b> (read-only)
A lookup table based on Perl Compatible Reg-
- ular Expressions. The file format is
+ ular Expressions. The file format is
described in <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
+ <b>proxy</b> (read-only)
+ A lookup table that is implemented via the
+ Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
+ syntax is <i>type</i><b>:</b><i>name</i>.
+
<b>regexp</b> (read-only)
A lookup table based on regular expressions.
- The file format is described in <a href="regexp_table.5.html"><b>reg-</b>
+ The file format is described in <a href="regexp_table.5.html"><b>reg-</b>
<b>exp</b><i>_</i><b>table</b>(5)</a>.
<b>static</b> (read-only)
- A table that always returns its name as
- lookup result. For example, <b>static:foobar</b>
- always returns the string <b>foobar</b> as lookup
+ A table that always returns its name as
+ lookup result. For example, <b>static:foobar</b>
+ always returns the string <b>foobar</b> as lookup
result.
<b>unix</b> (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:
<b>unix:passwd.byname</b>
- The table is the UNIX password
- database. The key is a login name.
- The result is a password file entry
+ The table is the UNIX password
+ database. The key is a login name.
+ The result is a password file entry
in passwd(5) format.
<b>unix:group.byname</b>
- The table is the UNIX group
- database. The key is a group name.
- The result is a group file entry in
+ The table is the UNIX group
+ database. 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 Postfix was
+ Other table types may exist depending on how Postfix was
built.
<b>-n</b> Print non-default parameter settings only.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
<b>DIAGNOSTICS</b>
Directory with Postfix configuration files.
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
<b>DESCRIPTION</b>
The <b>postqueue</b> program implements the Postfix user inter-
- face for queue management. It implements all the opera-
- tions that are traditionally available via the <a href="sendmail.1.html"><b>sendmail</b>(1)</a>
- command.
+ face for queue management. It implements operations that
+ are traditionally available via the <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command.
+ See the <a href="postsuper.1.html"><b>postsuper</b>(1)</a> command for queue operations that
+ require super-user privileges such as deleting a message
+ from the queue or changing the status of a message.
The following options are recognized:
request and in the <b>sendmail</b> <b>-qR</b> command.
<b>SEE</b> <b>ALSO</b>
- sendmail(8) sendmail-compatible user interface
+ <a href="sendmail.1.html">sendmail(1)</a> sendmail-compatible user interface
+ <a href="postsuper.1.html">postsuper(1)</a> privileged queue operations
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<a href="showq.8.html">showq(8)</a> list mail queue
<a href="flushd.8.html">flush(8)</a> fast flush service
<b>DESCRIPTION</b>
The <b>postsuper</b> command does maintenance jobs on the Postfix
queue. Use of the command is restricted to the superuser.
+ See the <b>postqueue</b> command for unprivileged queue opera-
+ tions such as listing or flushing the mail queue.
- By default, <b>postsuper</b> performs the operations requested
- with the <b>-s</b> and <b>-p</b> command-line options on all Postfix
+ By default, <b>postsuper</b> performs the operations requested
+ with the <b>-s</b> and <b>-p</b> command-line options on all Postfix
queue directories - this includes the <b>incoming</b>, <b>active</b> and
<b>deferred</b> directories with mail files and the <b>bounce</b>, <b>defer</b>
and <b>flush</b> directories with log files.
Options:
<b>-c</b> <i>config_dir</i>
- The <b>main.cf</b> configuration file is in the named
+ The <b>main.cf</b> configuration file is in the named
directory instead of the default configuration
- directory. See also the MAIL_CONFIG environment
+ directory. See also the MAIL_CONFIG environment
setting below.
<b>-d</b> <i>queue_id</i>
Delete one message with the named queue ID from the
- named mail queue(s) (default: <b>hold</b>, <b>incoming</b>,
+ named mail queue(s) (default: <b>hold</b>, <b>incoming</b>,
<b>active</b> and <b>deferred</b>). If a <i>queue_id</i> of <b>-</b> is speci-
- fied, the program reads queue IDs from standard
- input. For example, to delete all mail from or to
+ fied, the program reads queue IDs from standard
+ input. For example, to delete all mail from or to
<b>user@example.com</b>:
mailq | tail +2 | awk 'BEGIN { RS = "" } \
' | tr -d '*!' | postsuper -d -
Specify <b>-d</b> <b>ALL</b> to remove all messages; for example,
- specify <b>-d</b> <b>ALL</b> <b>deferred</b> to delete mail in the
- <b>deferred</b> queue. As a safety measure, the word <b>ALL</b>
+ specify <b>-d</b> <b>ALL</b> <b>deferred</b> to delete mail in the
+ <b>deferred</b> queue. As a safety measure, the word <b>ALL</b>
must be specified in upper case.
- <b>Postfix</b> <b>queue</b> <b>IDs</b> <b>are</b> <b>reused.</b> <b>There</b> <b>is</b> <b>a</b> <b>very</b>
- <b>small</b> <b>possibility</b> <b>that</b> <b>postsuper</b> <b>deletes</b> <b>the</b> <b>wrong</b>
- <b>message</b> <b>file</b> <b>when</b> <b>it</b> <b>is</b> <b>executed</b> <b>while</b> <b>the</b> <b>Postfix</b>
+ <b>Postfix</b> <b>queue</b> <b>IDs</b> <b>are</b> <b>reused.</b> <b>There</b> <b>is</b> <b>a</b> <b>very</b>
+ <b>small</b> <b>possibility</b> <b>that</b> <b>postsuper</b> <b>deletes</b> <b>the</b> <b>wrong</b>
+ <b>message</b> <b>file</b> <b>when</b> <b>it</b> <b>is</b> <b>executed</b> <b>while</b> <b>the</b> <b>Postfix</b>
<b>mail</b> <b>system</b> <b>is</b> <b>running.</b>
The scenario is as follows:
- 1) The Postfix queue manager deletes the mes-
- sage that <b>postsuper</b> is supposed to delete,
- because Postfix is finished with the mes-
+ 1) The Postfix queue manager deletes the mes-
+ sage that <b>postsuper</b> is supposed to delete,
+ because Postfix is finished with the mes-
sage.
- 2) New mail arrives, and the new message is
- given the same queue ID as the message that
+ 2) New mail arrives, and the new message is
+ given the same queue ID as the message that
<b>postsuper</b> is supposed to delete. The proba-
- bility for reusing a deleted queue ID is
- about 1 in 2**15 (the number of different
+ bility for reusing a deleted queue ID is
+ about 1 in 2**15 (the number of different
microsecond values that the system clock can
distinguish within a second).
- 3) <b>postsuper</b> deletes the new message, instead
- of the old message that it should have
+ 3) <b>postsuper</b> deletes the new message, instead
+ of the old message that it should have
deleted.
<b>-h</b> <i>queue_id</i>
- Put mail "on hold" so that no attempt is made to
- deliver it. Move one message with the named queue
+ Put mail "on hold" so that no attempt is made to
+ deliver it. Move one message with the named queue
ID from the named mail queue(s) (default: <b>incoming</b>,
- <b>active</b> and <b>deferred</b>) to the <b>hold</b> queue. If a
+ <b>active</b> and <b>deferred</b>) to the <b>hold</b> queue. If a
<i>queue_id</i> of <b>-</b> is specified, the program reads queue
IDs from standard input.
- Specify <b>-h</b> <b>ALL</b> to hold all messages; for example,
+ Specify <b>-h</b> <b>ALL</b> to hold all messages; for example,
specify <b>-h</b> <b>ALL</b> <b>deferred</b> to hold mail in the
- <b>deferred</b> queue. As a safety measure, the word <b>ALL</b>
+ <b>deferred</b> queue. As a safety measure, the word <b>ALL</b>
must be specified in upper case.
- Note: mail that is put "on hold" will not expire
- when its time in the queue exceeds the <b>maxi-</b>
+ Note: mail that is put "on hold" will not expire
+ when its time in the queue exceeds the <b>maxi-</b>
<b>mal</b><i>_</i><b>queue</b><i>_</i><b>lifetime</b> setting.
<b>-H</b> <i>queue_id</i>
Release mail that was put "on hold". Move one mes-
- sage with the named queue ID from the named mail
+ sage with the named queue ID from the named mail
queue(s) (default: <b>hold</b>) to the <b>deferred</b> queue. If
- a <i>queue_id</i> of <b>-</b> is specified, the program reads
+ a <i>queue_id</i> of <b>-</b> is specified, the program reads
queue IDs from standard input.
- Specify <b>-H</b> <b>ALL</b> to release all mail that is "on
- hold". As a safety measure, the word <b>ALL</b> must be
+ Specify <b>-H</b> <b>ALL</b> to release all mail that is "on
+ hold". As a safety measure, the word <b>ALL</b> must be
specified in upper case.
- <b>-p</b> Purge old temporary files that are left over after
+ <b>-p</b> Purge old temporary files that are left over after
system or software crashes.
<b>-r</b> <i>queue_id</i>
- Requeue the message with the named queue ID from
- the named mail queue(s) (default: <b>hold</b>, <b>incoming</b>,
- <b>active</b> and <b>deferred</b>). To requeue multiple mes-
- sages, specify multiple <b>-r</b> command-line options.
+ Requeue the message with the named queue ID from
+ the named mail queue(s) (default: <b>hold</b>, <b>incoming</b>,
+ <b>active</b> and <b>deferred</b>). To requeue multiple mes-
+ sages, specify multiple <b>-r</b> command-line options.
Alternatively, if a <i>queue_id</i> of <b>-</b> is specified, the
program reads queue IDs from standard input.
Specify <b>-r</b> <b>ALL</b> to requeue all messages. As a safety
- measure, the word <b>ALL</b> must be specified in upper
+ measure, the word <b>ALL</b> must be specified in upper
case.
- A requeued message is moved to the <b>maildrop</b> queue,
- from where it is copied by the pickup daemon to a
- new file whose name is guaranteed to match the new
+ A requeued message is moved to the <b>maildrop</b> queue,
+ from where it is copied by the pickup daemon to a
+ new file whose name is guaranteed to match the new
queue file inode number. The new queue file is sub-
- jected again to mail address rewriting and substi-
+ jected again to mail address rewriting and substi-
tution. This is useful when rewriting rules or vir-
tual mappings have changed.
- Postfix queue IDs are reused. There is a very
+ Postfix queue IDs are reused. There is a very
small possibility that <b>postsuper</b> requeues the wrong
- message file when it is executed while the Postfix
+ message file when it is executed while the Postfix
mail system is running, but no harm should be done.
<b>-s</b> Structure check and structure repair. It is highly
- recommended to perform this operation once before
+ recommended to perform this operation once before
Postfix startup.
- <b>o</b> Rename files whose name does not match the
+ <b>o</b> Rename files whose name does not match the
message file inode number. This operation is
- necessary after restoring a mail queue from
+ necessary after restoring a mail queue from
a different machine, or from backup media.
<b>o</b> Move queue files that are in the wrong place
in the file system hierarchy and remove sub-
directories that are no longer needed. File
- position rearrangements are necessary after
+ position rearrangements are necessary after
a change in the <b>hash</b><i>_</i><b>queue</b><i>_</i><b>names</b> and/or
<b>hash</b><i>_</i><b>queue</b><i>_</i><b>depth</b> configuration parameters.
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
- tiple <b>-v</b> options make the software increasingly
+ tiple <b>-v</b> options make the software increasingly
verbose.
<b>DIAGNOSTICS</b>
- Problems are reported to the standard error stream and to
+ Problems are reported to the standard error stream and to
<b>syslogd</b>.
- <b>postsuper</b> reports the number of messages deleted with <b>-d</b>,
+ <b>postsuper</b> reports the number of messages deleted with <b>-d</b>,
the number of messages requeued with <b>-r</b>, and the number of
- messages whose queue file name was fixed with <b>-s</b>. The
+ messages whose queue file name was fixed with <b>-s</b>. The
report is written to the standard error stream and to <b>sys-</b>
<b>logd</b>.
Directory with the <b>main.cf</b> file.
<b>BUGS</b>
- Mail that is not sanitized by Postfix (i.e. mail in the
+ Mail that is not sanitized by Postfix (i.e. mail in the
<b>maildrop</b> queue) cannot be placed "on hold".
<b>CONFIGURATION</b> <b>PARAMETERS</b>
- See the Postfix <b>main.cf</b> file for syntax details and for
+ See the Postfix <b>main.cf</b> file for syntax details and for
default values.
<b>hash</b><i>_</i><b>queue</b><i>_</i><b>depth</b>
Number of subdirectory levels for hashed queues.
<b>hash</b><i>_</i><b>queue</b><i>_</i><b>names</b>
- The names of queues that are organized into multi-
+ The names of queues that are organized into multi-
ple levels of subdirectories.
+<b>SEE</b> <b>ALSO</b>
+ <a href="sendmail.1.html">sendmail(1)</a> sendmail-compatible user interface
+ <a href="postqueue.1.html">postqueue(1)</a> unprivileged queue operations
+
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
--- /dev/null
+<html> <head> </head> <body> <pre>
+PROXYMAP(8) PROXYMAP(8)
+
+<b>NAME</b>
+ proxymap - Postfix lookup table proxy server
+
+<b>SYNOPSIS</b>
+ <b>proxymap</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+ The <b>proxymap</b> server provides read-only table lookup ser-
+ vice to Postfix client processes. The purpose of the ser-
+ vice is:
+
+ <b>o</b> To overcome chroot restrictions. For example, a
+ chrooted SMTP server needs access to the system
+ passwd file in order to reject mail for non-exis-
+ tent local addresses, but it is not practical to
+ maintain a copy of the passwd file in the chroot
+ jail. The solution:
+
+ local_recipient_maps =
+ proxy:unix:passwd.byname $alias_maps
+
+ <b>o</b> To consolidate the number of open lookup tables by
+ sharing one open table among multiple processes.
+ For example, making mysql connections from every
+ Postfix daemon process results in "too many connec-
+ tions" errors. The solution:
+
+ virtual_alias_maps =
+ proxy:mysql:/etc/postfix/virtual.cf
+
+ The total number of connections is limited by the
+ number of proxymap server server processes.
+
+ The proxymap server implements the following requests:
+
+ <b>PROXY</b><i>_</i><b>REQ</b><i>_</i><b>OPEN</b> <i>maptype:mapname</i> <i>flags</i>
+ Open the table with type <i>maptype</i> and name <i>mapname</i>,
+ as controlled by <i>flags</i>. The reply is the request
+ completion status code (below) and the map type
+ dependent flags.
+
+ <b>PROXY</b><i>_</i><b>REQ</b><i>_</i><b>LOOKUP</b> <i>maptype:mapname</i> <i>flags</i> <i>key</i>
+ Look up the data stored under the requested key.
+ The reply is the request completion status code
+ (below) and the lookup result value. The <i>map-</i>
+ <i>type:mapname</i> and <i>flags</i> are the same as with the
+ <b>PROXY</b><i>_</i><b>REQ</b><i>_</i><b>OPEN</b> request.
+
+ There is no close command, nor are tables implicitly
+ closed when a client disconnects. One of the purposes of
+ the proxymap server is to share tables among multiple
+ client processes.
+
+ The request completion status code is one of:
+
+ <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
+ The specified table was opened, or the requested
+ entry was found.
+
+ <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>NOKEY</b>
+ The requested table entry was not found.
+
+ <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>BAD</b>
+ The request was rejected (bad request parameter
+ value).
+
+ <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>RETRY</b>
+ The lookup request could not be completed.
+
+ <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>DENY</b>
+ The specified table was not approved for access via
+ the proxymap service.
+
+<b>SERVER</b> <b>PROCESS</b> <b>MANAGEMENT</b>
+ The proxymap servers run under control by the Postfix mas-
+ ter server. Each server can handle multiple simultaneous
+ connections. When all servers are busy while a client
+ connects, the master creates a new proxymap server pro-
+ cess, provided that the proxymap server process limit is
+ not exceeded. Each proxymap server terminates after serv-
+ ing at least <b>$max</b><i>_</i><b>use</b> clients or after <b>$max</b><i>_</i><b>idle</b> seconds
+ of idle time.
+
+<b>SECURITY</b>
+ The proxymap server opens only tables that are approved
+ via the <b>proxy</b><i>_</i><b>read</b><i>_</i><b>maps</b> configuration parameter, does not
+ talk to users, and can run at fixed low privilege,
+ chrooted or not.
+
+ The proxymap server is not a trusted daemon process, and
+ must not be used to look up sensitive information such as
+ user or group IDs, mailbox file/directory names or exter-
+ nal commands.
+
+<b>DIAGNOSTICS</b>
+ Problems and transactions are logged to <b>syslogd</b>(8).
+
+<b>BUGS</b>
+ The proxymap server provides service to multiple clients,
+ and must therefore not be used for tables that have high-
+ latency lookups.
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+ The following main.cf parameters are especially relevant
+ to this program. Use the <b>postfix</b> <b>reload</b> command after a
+ configuration change.
+
+ <b>proxy</b><i>_</i><b>read</b><i>_</i><b>maps</b>
+ A list of zero or more parameter values that may
+ contain references to Postfix lookup tables. Only
+ table references that begin with <b>proxy:</b> are
+ approved for read-only access via the proxymap
+ server.
+
+<b>SEE</b> <b>ALSO</b>
+ dict_proxy(3) proxy map client
+
+<b>LICENSE</b>
+ The Secure Mailer license must be distributed with this
+ software.
+
+<b>AUTHOR(S)</b>
+ Wietse Venema
+ IBM T.J. Watson Research
+ P.O. Box 704
+ Yorktown Heights, NY 10598, USA
+
+ PROXYMAP(8)
+</pre> </body> </html>
You can override this setting for specific Postfix daemons by
editing the <b>master.cf</b> file. For example, if you do not
-wish to receive 50 SMTP messages at the same time, you could specify:
+wish to receive 100 SMTP messages at the same time, you could specify:
<dl>
<dd> <pre>
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
-# (yes) (yes) (yes) (never) (50)
+# (yes) (yes) (yes) (never) (100)
# ==========================================================================
. . .
smtp inet n - - - 5 smtpd
<p>
The <b>default_destination_concurrency_limit</b> parameter
-(default: 10) controls how many messages may be sent to the same
+(default: 20) controls how many messages may be sent to the same
destination simultaneously. You can override this setting for
specific delivery channels (<b>local, smtp, uucp</b> etc.). The
<b>main.cf</b> file recommends the following:
<dd> <b>local_destination_concurrency_limit = 2</b>
-<dd> <b>default_destination_concurrency_limit = 10</b>
+<dd> <b>default_destination_concurrency_limit = 20</b>
</dl>
<p>
-A destination concurrency limit of 10 for SMTP delivery seems enough
+A destination concurrency limit of 20 for SMTP delivery seems enough
to noticeably load a system without bringing it to its knees. Be
careful when changing this to a much larger number.
/^postmaster@/ OK
# Protect your outgoing majordomo exploders
- /^(.*)-outgoing@(.*)$/!/^owner-/ 550 Use ${1}@${2} instead
+ if !/^owner-/
+ /^(.*)-outgoing@(.*)$/ 550 Use ${1}@${2} instead
+ endif
<b>EXAMPLE</b> <b>HEADER</b> <b>FILTER</b> <b>MAP</b>
# These were once common in junk mail.
<b>DEFAULT</b> <b>DELIVERY</b> <b>METHODS</b>
By default, Postfix uses one of the following delivery
methods. This may be overruled with the optional <a href="transport.5.html">trans-</a>
- <a href="transport.5.html">port(5)</a> table.
-
- <b>o</b> The recipient domain matches <b>$mydestination</b> or
- <b>$inet</b><i>_</i><b>interfaces</b>. The transport and optional nex-
- thop are specified with <b>$local</b><i>_</i><b>transport</b>. The
- default nexthop is the recipient domain.
-
- <b>o</b> The recipient domain matches <b>$virtual</b><i>_</i><b>mail-</b>
- <b>box</b><i>_</i><b>domains</b>. The transport and optional nexthop
- are specified with <b>$virtual</b><i>_</i><b>transport</b>. The default
- nexthop is the recipient domain.
-
- <b>o</b> The recipient domain matches <b>$relay</b><i>_</i><b>domains</b>. The
- transport and optional nexthop are specified with
- <b>$relay</b><i>_</i><b>transport</b>. This overrides the optional nex-
- thop information that is specified with <b>$relayhost</b>.
- The default nexthop is the recipient domain.
-
- <b>o</b> All other destinations. the transport and optional
- nexthop are specified with <b>$relay</b><i>_</i><b>transport</b>. This
- overrides the optional nexthop information that is
- specified with <b>$relayhost</b>. The default nexthop is
+ <a href="transport.5.html">port(5)</a> table. The default delivery method is selected by
+ matching the recipient address domain against one of the
+ following:
+
+ <b>$mydestination</b>
+
+ <b>$inet</b><i>_</i><b>interfaces</b>
+ The transport and optional nexthop are specified
+ with <b>$local</b><i>_</i><b>transport</b>. The default nexthop is the
+ recipient domain.
+
+ <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>
+ The recipient address is undeliverable (user
+ unknown). By definition, all known addresses in a
+ virtual alias domain are aliased to other
+ addresses.
+
+ <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>
+ The transport and optional nexthop are specified
+ with <b>$virtual</b><i>_</i><b>transport</b>. The default nexthop is
the recipient domain.
+ <b>$relay</b><i>_</i><b>domains</b>
+ The transport and optional nexthop are specified
+ with <b>$relay</b><i>_</i><b>transport</b>. This overrides the optional
+ nexthop information that is specified with <b>$relay-</b>
+ <b>host</b>. The default nexthop is the recipient domain.
+
+ none of the above
+ The transport and optional nexthop are specified
+ with <b>$default</b><i>_</i><b>transport</b>. This overrides the
+ optional nexthop information that is specified with
+ <b>$relayhost</b>. The default nexthop is the recipient
+ domain.
+
+<b>SERVER</b> <b>PROCESS</b> <b>MANAGEMENT</b>
+ The trivial-rewrite servers run under control by the Post-
+ fix master server. Each server can handle multiple simul-
+ taneous connections. When all servers are busy while a
+ client connects, the master creates a new server process,
+ provided that the trivial-rewrite server process limit is
+ not exceeded. Each trivial-rewrite server terminates
+ after serving at least <b>$max</b><i>_</i><b>use</b> clients of after <b>$max</b><i>_</i><b>idle</b>
+ seconds of idle time.
+
<b>STANDARDS</b>
None. The command does not interact with the outside
world.
etc. is disallowed, because that would open a secu-
rity hole.
+ For security reasons, proxied table lookup is not
+ allowed, because that would open a security hole.
+
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>
- The list of domains that should be delivered via
- the Postfix virtual delivery agent. This uses the
+ The list of domains that should be delivered via
+ the Postfix virtual delivery agent. This uses the
same syntax as the <b>mydestination</b> configuration
parameter.
<b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b>
- Specifies a minimum uid that will be accepted as a
- return from a <b>virtual</b><i>_</i><b>owner</b><i>_</i><b>maps</b> or <b>vir-</b>
- <b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned values less than
- this will be rejected, and the message will be
+ Specifies a minimum uid that will be accepted as a
+ return from a <b>virtual</b><i>_</i><b>owner</b><i>_</i><b>maps</b> or <b>vir-</b>
+ <b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup. Returned values less than
+ this will be rejected, and the message will be
deferred.
<b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
Recipients are looked up in these maps to determine
- the user ID to be used when writing to the target
+ the user ID to be used when writing to the target
mailbox.
- While searching a lookup table, an address exten-
+ While searching a lookup table, an address exten-
sion (<i>user+foo@domain.tld</i>) is ignored.
- In a lookup table, specify a left-hand side of
- <i>@domain.tld</i> to match any user in the specified
- domain that does not have a specific
+ In a lookup table, specify a left-hand side of
+ <i>@domain.tld</i> to match any user in the specified
+ domain that does not have a specific
<i>user@domain.tld</i> entry.
- For security reasons, regular expression maps are
- allowed but regular expression substitution of $1
+ For security reasons, regular expression maps are
+ allowed but regular expression substitution of $1
etc. is disallowed, because that would open a secu-
rity hole.
+ For security reasons, proxied table lookup is not
+ allowed, because that would open a security hole.
+
<b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>
Recipients are looked up in these maps to determine
the group ID to be used when writing to the target
etc. is disallowed, because that would open a secu-
rity hole.
+ For security reasons, proxied table lookup is not
+ allowed, because that would open a security hole.
+
<b>Locking</b> <b>controls</b>
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>lock</b>
- How to lock UNIX-style mailboxes: one or more of
- <b>flock</b>, <b>fcntl</b> or <b>dotlock</b>. The <b>dotlock</b> method
- requires that the recipient UID or GID has write
+ How to lock UNIX-style mailboxes: one or more of
+ <b>flock</b>, <b>fcntl</b> or <b>dotlock</b>. The <b>dotlock</b> method
+ requires that the recipient UID or GID has write
access to the parent directory of the mailbox file.
- This setting is ignored with <b>maildir</b> style deliv-
+ This setting is ignored with <b>maildir</b> style deliv-
ery, because such deliveries are safe without
explicit locks.
- Use the command <b>postconf</b> <b>-l</b> to find out what lock-
+ Use the command <b>postconf</b> <b>-l</b> to find out what lock-
ing methods are available on your system.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
- Limit the number of attempts to acquire an exclu-
+ Limit the number of attempts to acquire an exclu-
sive lock on a UNIX-style mailbox file.
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
Time (default: seconds) between successive attempts
- to acquire an exclusive lock on a UNIX-style mail-
- box file. The actual delay is slightly randomized.
+ to acquire an exclusive lock on a UNIX-style mail-
+ box file. The actual delay is slightly randomized.
<b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
- Limit the time after which a stale lockfile is
- removed (applicable to UNIX-style mailboxes only).
+ Limit the time after which a stale lockfile is
+ removed (applicable to UNIX-style mailboxes only).
<b>Resource</b> <b>controls</b>
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
Limit the number of parallel deliveries to the same
domain via the <b>virtual</b> delivery agent. The default
limit is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>concur-</b>
- <b>rency</b><i>_</i><b>limit</b> parameter. The limit is enforced by
+ <b>rency</b><i>_</i><b>limit</b> parameter. The limit is enforced by
the Postfix queue manager.
<b>virtual</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
Limit the number of recipients per message delivery
- via the <b>virtual</b> delivery agent. The default limit
- is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
- <b>ent</b><i>_</i><b>limit</b> parameter. The limit is enforced by the
+ via the <b>virtual</b> delivery agent. The default limit
+ is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
+ <b>ent</b><i>_</i><b>limit</b> parameter. The limit is enforced by the
Postfix queue manager.
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>limit</b>
- The maximal size in bytes of a mailbox or maildir
+ The maximal size in bytes of a mailbox or maildir
file. Set to zero to disable the limit.
<b>HISTORY</b>
- This agent was originally based on the Postfix local
+ This agent was originally based on the Postfix local
delivery agent. Modifications mainly consisted of removing
- code that either was not applicable or that was not safe
- in this context: aliases, ~user/.forward files, delivery
+ code that either was not applicable or that was not safe
+ in this context: aliases, ~user/.forward files, delivery
to "|command" or to /file/name.
- The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
+ The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
Daniel Bernstein.
- The <b>maildir</b> structure appears in the <b>qmail</b> system by
+ The <b>maildir</b> structure appears in the <b>qmail</b> system by
Daniel Bernstein.
<b>SEE</b> <b>ALSO</b>
<a href="qmgr.8.html">qmgr(8)</a> queue manager
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
echo "See the RELEASE_NOTES file for more information." 1>&2
exit 1
fi
- if [ -f /usr/include/pcre/pcre.h ]
- then
- CCARGS="$CCARGS -DHAS_PCRE -I/usr/include/pcre"
- fi
# GDBM locks the DBM .pag file after open. This breaks postmap.
# if [ -f /usr/include/gdbm-ndbm.h ]
# then
# GDBM_LIBS=gdbm
# fi
SYSLIBS="-ldb"
- for name in nsl resolv pcre $GDBM_LIBS
+ for name in nsl resolv $GDBM_LIBS
do
test -e /usr/lib/lib$name.a -o -e /usr/lib/lib$name.so \
-o -e /lib/lib$name.a -o -e /lib/lib$name.so \
*) echo "Unknown system type: $SYSTEM $RELEASE" 1>&2; exit 1;;
esac
+#
+# PCRE 3.x has a pcre-config utility so we don't have to guess.
+#
+case "$CCARGS" in
+*-DHAS_PCRE*) ;;
+ *-DNO_PCRE*) ;;
+ *) pcre_cflags=`(pcre-config --cflags) 2>/dev/null`
+ pcre_libs=`(pcre-config --libs) 2>/dev/null`
+ if [ -n "$pcre_cflags" -a -n "$pcre_libs" ]
+ then
+ CCARGS="$CCARGS -DHAS_PCRE $pcre_cflags"
+ AUXLIBS="$AUXLIBS $pcre_libs"
+ fi
+ ;;
+esac
+
# Defaults that can be overruled (make makefiles CC=cc OPT=-O6 DEBUG=)
# Disable optimizations by default when compiling for Purify. Disable
# optimizations by default with gcc 2.8, until the compiler is known to
DAEMONS = man8/bounce.8 man8/defer.8 man8/cleanup.8 man8/error.8 man8/local.8 \
man8/lmtp.8 man8/master.8 man8/pickup.8 man8/pipe.8 man8/qmgr.8 \
man8/showq.8 man8/smtp.8 man8/smtpd.8 man8/trivial-rewrite.8 \
- man8/nqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8
+ man8/nqmgr.8 man8/spawn.8 man8/flush.8 man8/virtual.8 man8/qmqpd.8 \
+ man8/proxymap.8
COMMANDS= man1/postalias.1 man1/postcat.1 man1/postconf.1 man1/postfix.1 \
man1/postkick.1 man1/postlock.1 man1/postlog.1 man1/postdrop.1 \
man1/postmap.1 man1/sendmail.1 man1/mailq.1 man1/newaliases.1 \
man8/pipe.8: ../src/pipe/pipe.c
../mantools/srctoman $? >$@
+man8/proxymap.8: ../src/proxymap/proxymap.c
+ ../mantools/srctoman $? >$@
+
man8/qmgr.8: ../src/qmgr/qmgr.c
../mantools/srctoman $? >$@
stale lock files that were left behind after abnormal termination.
.RE
.IP \fB-m\fR
-List the names of all supported lookup table types.
+List the names of all supported lookup table types. Postfix
+lookup tables are specified as \fItype\fB:\fIname\fR, where
+\fItype\fR is one of the types listed below. The table \fIname\fR
+syntax depends on the lookup table type.
.RS
.IP \fBbtree\fR
A sorted, balanced tree structure.
.IP "\fBpcre\fR (read-only)"
A lookup table based on Perl Compatible Regular Expressions. The
file format is described in \fBpcre_table\fR(5).
+.IP "\fBproxy\fR (read-only)"
+A lookup table that is implemented via the Postfix
+\fBproxymap\fR(8) service. The table name syntax is
+\fItype\fB:\fIname\fR.
.IP "\fBregexp\fR (read-only)"
A lookup table based on regular expressions. The file format is
described in \fBregexp_table\fR(5).
.ad
.fi
The \fBpostqueue\fR program implements the Postfix user interface
-for queue management. It implements all the operations that are
+for queue management. It implements operations that are
traditionally available via the \fBsendmail\fR(1) command.
+See the \fBpostsuper\fR(1) command for queue operations
+that require super-user privileges such as deleting a message
+from the queue or changing the status of a message.
The following options are recognized:
.IP "\fB-c \fIconfig_dir\fR"
.SH SEE ALSO
.na
.nf
-sendmail(8) sendmail-compatible user interface
+sendmail(1) sendmail-compatible user interface
+postsuper(1) privileged queue operations
qmgr(8) queue manager
showq(8) list mail queue
flush(8) fast flush service
.fi
The \fBpostsuper\fR command does maintenance jobs on the Postfix
queue. Use of the command is restricted to the superuser.
+See the \fBpostqueue\fR command for unprivileged queue operations
+such as listing or flushing the mail queue.
By default, \fBpostsuper\fR performs the operations requested with the
\fB-s\fR and \fB-p\fR command-line options on all Postfix queue
.IP \fBhash_queue_names\fR
The names of queues that are organized into multiple levels of
subdirectories.
+.SH SEE ALSO
+.na
+.nf
+sendmail(1) sendmail-compatible user interface
+postqueue(1) unprivileged queue operations
.SH LICENSE
.na
.nf
/^postmaster@/ OK
# Protect your outgoing majordomo exploders
-/^(.*)-outgoing@(.*)$/!/^owner-/ 550 Use ${1}@${2} instead
+if !/^owner-/
+/^(.*)-outgoing@(.*)$/ 550 Use ${1}@${2} instead
+endif
.SH EXAMPLE HEADER FILTER MAP
.na
.nf
--- /dev/null
+.TH PROXYMAP 8
+.ad
+.fi
+.SH NAME
+proxymap
+\-
+Postfix lookup table proxy server
+.SH SYNOPSIS
+.na
+.nf
+\fBproxymap\fR [generic Postfix daemon options]
+.SH DESCRIPTION
+.ad
+.fi
+The \fBproxymap\fR server provides read-only table
+lookup service to Postfix client processes. The purpose
+of the service is:
+.IP \(bu
+To overcome chroot restrictions. For example, a chrooted SMTP
+server needs access to the system passwd file in order to
+reject mail for non-existent local addresses, but it is not
+practical to maintain a copy of the passwd file in the chroot
+jail. The solution:
+.sp
+local_recipient_maps =
+.ti +4
+proxy:unix:passwd.byname $alias_maps
+.IP \(bu
+To consolidate the number of open lookup tables by sharing
+one open table among multiple processes. For example, making
+mysql connections from every Postfix daemon process results
+in "too many connections" errors. The solution:
+.sp
+virtual_alias_maps =
+.ti +4
+proxy:mysql:/etc/postfix/virtual.cf
+.sp
+The total number of connections is limited by the number of
+proxymap server server processes.
+.PP
+The proxymap server implements the following requests:
+.IP "\fBPROXY_REQ_OPEN\fI maptype:mapname flags\fR"
+Open the table with type \fImaptype\fR and name \fImapname\fR,
+as controlled by \fIflags\fR.
+The reply is the request completion status code (below) and the
+map type dependent flags.
+.IP "\fBPROXY_REQ_LOOKUP\fI maptype:mapname flags key\fR"
+Look up the data stored under the requested key.
+The reply is the request completion status code (below) and
+the lookup result value.
+The \fImaptype:mapname\fR and \fIflags\fR are the same
+as with the \fBPROXY_REQ_OPEN\fR request.
+.PP
+There is no close command, nor are tables implicitly closed
+when a client disconnects. One of the purposes of the proxymap
+server is to share tables among multiple client processes.
+
+The request completion status code is one of:
+.IP \fBPROXY_STAT_OK\fR
+The specified table was opened, or the requested entry was found.
+.IP \fBPROXY_STAT_NOKEY\fR
+The requested table entry was not found.
+.IP \fBPROXY_STAT_BAD\fR
+The request was rejected (bad request parameter value).
+.IP \fBPROXY_STAT_RETRY\fR
+The lookup request could not be completed.
+.IP \fBPROXY_STAT_DENY\fR
+The specified table was not approved for access via the
+proxymap service.
+.SH SERVER PROCESS MANAGEMENT
+.na
+.nf
+.ad
+.fi
+The proxymap servers run under control by the Postfix master
+server. Each server can handle multiple simultaneous connections.
+When all servers are busy while a client connects, the master
+creates a new proxymap server process, provided that the proxymap
+server process limit is not exceeded.
+Each proxymap server terminates after serving
+at least \fB$max_use\fR clients or after \fB$max_idle\fR seconds
+of idle time.
+.SH SECURITY
+.na
+.nf
+.ad
+.fi
+The proxymap server opens only tables that are approved via the
+\fBproxy_read_maps\fR configuration parameter, does not talk to
+users, and can run at fixed low privilege, chrooted or not.
+
+The proxymap server is not a trusted daemon process, and must
+not be used to look up sensitive information such as user or
+group IDs, mailbox file/directory names or external commands.
+.SH DIAGNOSTICS
+.ad
+.fi
+Problems and transactions are logged to \fBsyslogd\fR(8).
+.SH BUGS
+.ad
+.fi
+The proxymap server provides service to multiple clients,
+and must therefore not be used for tables that have high-latency
+lookups.
+.SH CONFIGURATION PARAMETERS
+.na
+.nf
+.ad
+.fi
+The following main.cf parameters are especially relevant
+to this program. Use the \fBpostfix reload\fR command
+after a configuration change.
+.IP \fBproxy_read_maps\fR
+A list of zero or more parameter values that may contain
+references to Postfix lookup tables. Only table references
+that begin with \fBproxy:\fR are approved for read-only
+access via the proxymap server.
+.SH SEE ALSO
+.na
+.nf
+dict_proxy(3) proxy map client
+.SH LICENSE
+.na
+.nf
+.ad
+.fi
+The Secure Mailer license must be distributed with this software.
+.SH AUTHOR(S)
+.na
+.nf
+Wietse Venema
+IBM T.J. Watson Research
+P.O. Box 704
+Yorktown Heights, NY 10598, USA
.fi
By default, Postfix uses one of the following delivery methods.
This may be overruled with the optional transport(5) table.
-.IP \(bu
-The recipient domain matches \fB$mydestination\fR or
-\fB$inet_interfaces\fR. The transport and optional nexthop
+The default delivery method is selected by matching the
+recipient address domain against one of the following:
+.IP \fB$mydestination\fR
+.IP \fB$inet_interfaces\fR
+The transport and optional nexthop
are specified with \fB$local_transport\fR.
The default nexthop is the recipient domain.
-.IP \(bu
-The recipient domain matches \fB$virtual_mailbox_domains\fR.
+.IP \fB$virtual_alias_domains\fR
+The recipient address is undeliverable (user unknown).
+By definition, all known addresses in a virtual alias domain
+are aliased to other addresses.
+.IP \fB$virtual_mailbox_domains\fR
The transport and optional nexthop are specified with
\fB$virtual_transport\fR.
The default nexthop is the recipient domain.
-.IP \(bu
-The recipient domain matches \fB$relay_domains\fR. The
-transport and optional nexthop are specified with
+.IP \fB$relay_domains\fR
+The transport and optional nexthop are specified with
\fB$relay_transport\fR. This overrides the optional nexthop
information that is specified with \fB$relayhost\fR.
The default nexthop is the recipient domain.
-.IP \(bu
-All other destinations. the transport and optional nexthop are
-specified with \fB$relay_transport\fR.
+.IP "none of the above"
+The transport and optional nexthop are specified with
+\fB$default_transport\fR.
This overrides the optional nexthop information that is specified
with \fB$relayhost\fR.
The default nexthop is the recipient domain.
+.SH SERVER PROCESS MANAGEMENT
+.na
+.nf
+.ad
+.fi
+The trivial-rewrite servers run under control by the Postfix master
+server. Each server can handle multiple simultaneous connections.
+When all servers are busy while a client connects, the master
+creates a new server process, provided that the trivial-rewrite
+server process limit is not exceeded.
+Each trivial-rewrite server terminates after
+serving at least \fB$max_use\fR clients of after \fB$max_idle\fR
+seconds of idle time.
.SH STANDARDS
.na
.nf
For security reasons, regular expression maps are allowed but
regular expression substitution of $1 etc. is disallowed,
because that would open a security hole.
+
+For security reasons, proxied table lookup is not allowed,
+because that would open a security hole.
.IP \fBvirtual_mailbox_domains\fR
The list of domains that should be delivered via the Postfix virtual
delivery agent. This uses the same syntax as the \fBmydestination\fR
For security reasons, regular expression maps are allowed but
regular expression substitution of $1 etc. is disallowed,
because that would open a security hole.
+
+For security reasons, proxied table lookup is not allowed,
+because that would open a security hole.
.IP \fBvirtual_gid_maps\fR
Recipients are looked up in these maps to determine the group ID to be
used when writing to the target mailbox.
For security reasons, regular expression maps are allowed but
regular expression substitution of $1 etc. is disallowed,
because that would open a security hole.
+
+For security reasons, proxied table lookup is not allowed,
+because that would open a security hole.
.SH "Locking controls"
.ad
.fi
s/[<bB>]*canonical[</bB>]*(5)/<a href="canonical.5.html">&<\/a>/
s/[<bB>]*etrn[</bB>]*(5)/<a href="etrn.5.html">&<\/a>/
s/[<bB>]*pcre[</bBiI>]*_[</iIbB>]*table[</bB>]*(5)/<a href="pcre_table.5.html">&<\/a>/
+ s/[<bB>]*proxymap[</bB>]*(8)/<a href="proxymap.8.html">&<\/a>/
s/[<bB>]*reg[-</bB>]*\n*[ <bB>]*exp[</bBiI>]*_[</iIbB>]*table[</bB>]*(5)/<a href="regexp_table.5.html">&<\/a>/
s/[<bB>]*relocated[</bB>]*(5)/<a href="relocated.5.html">&<\/a>/
s/[<bB>]*trans[-</bB>]*\n*[ <bB>]*port[</bB>]*(5)/<a href="transport.5.html">&<\/a>/
# /^postmaster@/ OK
#
# # Protect your outgoing majordomo exploders
-# /^(.*)-outgoing@(.*)$/!/^owner-/ 550 Use ${1}@${2} instead
+# if !/^owner-/
+# /^(.*)-outgoing@(.*)$/ 550 Use ${1}@${2} instead
+# endif
# EXAMPLE HEADER FILTER MAP
# # These were once common in junk mail.
# /^Subject: make money fast/ REJECT
if (STREQUAL(value, "FILTER", command_len)) {
if (*optional_text == 0) {
msg_warn("missing FILTER command argument in %s map", map_class);
+ } else if (strchr(optional_text, ':') == 0) {
+ msg_warn("bad FILTER command %s in %s, need transport:destination",
+ optional_text, map_class);
} else {
if (state->filter)
myfree(state->filter);
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
verp_sender.c match_parent_style.c mime_state.c header_token.c \
- strip_addr.c virtual8_maps.c hold_message.c
+ strip_addr.c virtual8_maps.c hold_message.c dict_proxy.c mail_dict.c
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
debug_peer.o debug_process.o defer.o deliver_completed.o \
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
verp_sender.o match_parent_style.o mime_state.o header_token.o \
- strip_addr.o virtual8_maps.o hold_message.o
+ strip_addr.o virtual8_maps.o hold_message.o dict_proxy.o mail_dict.o
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h \
match_parent_style.h quote_flags.h mime_state.h header_token.h \
- lex_822.h strip_addr.h virtual8_maps.h hold_message.h
+ lex_822.h strip_addr.h virtual8_maps.h hold_message.h dict_proxy.h \
+ mail_dict.h
TESTSRC = rec2stream.c stream2rec.c recdump.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
deliver_request.o: mail_open_ok.h
deliver_request.o: recipient_list.h
deliver_request.o: deliver_request.h
+dict_proxy.o: dict_proxy.c
+dict_proxy.o: ../../include/sys_defs.h
+dict_proxy.o: ../../include/msg.h
+dict_proxy.o: ../../include/mymalloc.h
+dict_proxy.o: ../../include/stringops.h
+dict_proxy.o: ../../include/vstring.h
+dict_proxy.o: ../../include/vbuf.h
+dict_proxy.o: ../../include/vstream.h
+dict_proxy.o: ../../include/attr.h
+dict_proxy.o: ../../include/dict.h
+dict_proxy.o: ../../include/argv.h
+dict_proxy.o: mail_proto.h
+dict_proxy.o: ../../include/iostuff.h
+dict_proxy.o: mail_params.h
+dict_proxy.o: clnt_stream.h
+dict_proxy.o: dict_proxy.h
domain_list.o: domain_list.c
domain_list.o: ../../include/sys_defs.h
domain_list.o: ../../include/match_list.h
mail_date.o: ../../include/vstring.h
mail_date.o: ../../include/vbuf.h
mail_date.o: mail_date.h
+mail_dict.o: mail_dict.c
+mail_dict.o: ../../include/sys_defs.h
+mail_dict.o: ../../include/dict.h
+mail_dict.o: ../../include/vstream.h
+mail_dict.o: ../../include/vbuf.h
+mail_dict.o: ../../include/argv.h
+mail_dict.o: ../../include/msg.h
+mail_dict.o: dict_proxy.h
+mail_dict.o: mail_dict.h
mail_error.o: mail_error.c
mail_error.o: ../../include/sys_defs.h
mail_error.o: mail_error.h
--- /dev/null
+/*++
+/* NAME
+/* dict_proxy 3
+/* SUMMARY
+/* generic dictionary proxy client
+/* SYNOPSIS
+/* #include <dict_proxy.h>
+/*
+/* DICT *dict_proxy_open(map, open_flags, dict_flags)
+/* const char *map;
+/* int dummy;
+/* int dict_flags;
+/* DESCRIPTION
+/* dict_proxy_open() relays read-only operations through
+/* the Postfix proxymap server.
+/*
+/* The \fIopen_flags\fR argument must specify O_RDONLY.
+/*
+/* The connection to the Postfix proxymap server is automatically
+/* closed after $ipc_idle seconds of idle time.
+/* SECURITY
+/* The proxy map server is not meant to be a trusted process. Proxy
+/* maps must not be used to look up security sensitive information
+/* such as user/group IDs, output files, or external commands.
+/* SEE ALSO
+/* dict(3) generic dictionary manager
+/* clnt_stream(3) client endpoint connection management
+/* DIAGNOSTICS
+/* Fatal errors: out of memory, unimplemented operation,
+/* bad request parameter, map not approved for proxy access.
+/* 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 <sys_defs.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <attr.h>
+#include <dict.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <mail_params.h>
+#include <clnt_stream.h>
+#include <dict_proxy.h>
+
+/* Application-specific. */
+
+typedef struct {
+ DICT dict; /* generic members */
+ int in_flags; /* caller-specified flags */
+ VSTRING *result; /* storage */
+} DICT_PROXY;
+
+ /*
+ * SLMs.
+ */
+#define STR(x) vstring_str(x)
+#define VSTREQ(v,s) (strcmp(STR(v),s) == 0)
+
+ /*
+ * All proxied maps within a process share the same query/reply socket.
+ */
+static CLNT_STREAM *proxy_stream;
+
+/* dict_proxy_lookup - find table entry */
+
+static const char *dict_proxy_lookup(DICT *dict, const char *key)
+{
+ const char *myname = "dict_proxy_lookup";
+ DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
+ VSTREAM *stream;
+ int status;
+
+ /*
+ * The client and server live in separate processes that may start and
+ * terminate independently. We cannot rely on a persistent connection,
+ * let alone on persistent state (such as a specific open table) that is
+ * associated with a specific connection. Each lookup needs to specify
+ * the table and the flags that were specified to dict_proxy_open().
+ */
+ VSTRING_RESET(dict_proxy->result);
+ VSTRING_TERMINATE(dict_proxy->result);
+ for (;;) {
+ stream = clnt_stream_access(proxy_stream);
+ errno = 0;
+ if (attr_print(stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_LOOKUP,
+ ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict->name,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, dict_proxy->in_flags,
+ ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
+ ATTR_TYPE_END) != 0
+ || vstream_fflush(stream)
+ || attr_scan(stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
+ ATTR_TYPE_STR, MAIL_ATTR_VALUE, dict_proxy->result,
+ ATTR_TYPE_END) != 2) {
+ if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ msg_warn("%s: service %s: %m", myname, VSTREAM_PATH(stream));
+ } else {
+ if (msg_verbose)
+ msg_info("%s: table=%s flags=0%o key=%s -> status=%d result=%s",
+ myname, dict->name, dict_proxy->in_flags, key,
+ status, STR(dict_proxy->result));
+ switch (status) {
+ case PROXY_STAT_BAD:
+ msg_fatal("%s lookup failed for table \"%s\" key \"%s\": "
+ "invalid request",
+ MAIL_SERVICE_PROXYMAP, dict->name, key);
+ case PROXY_STAT_DENY:
+ msg_fatal("%s service is not configured for table \"%s\"",
+ MAIL_SERVICE_PROXYMAP, dict->name);
+ case PROXY_STAT_OK:
+ return (STR(dict_proxy->result));
+ case PROXY_STAT_NOKEY:
+ dict_errno = 0;
+ return (0);
+ case PROXY_STAT_RETRY:
+ dict_errno = DICT_ERR_RETRY;
+ return (0);
+ default:
+ msg_warn("%s lookup failed for table \"%s\" key \"%s\": "
+ "unexpected reply status %d",
+ MAIL_SERVICE_PROXYMAP, dict->name, key, status);
+ }
+ }
+ clnt_stream_recover(proxy_stream);
+ sleep(1); /* XXX make configurable */
+ }
+}
+
+/* dict_proxy_close - disconnect */
+
+static void dict_proxy_close(DICT *dict)
+{
+ DICT_PROXY *dict_proxy = (DICT_PROXY *) dict;
+
+ vstring_free(dict_proxy->result);
+ dict_free(dict);
+}
+
+/* dict_proxy_open - open remote map */
+
+DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
+{
+ const char *myname = "dict_proxy_open";
+ DICT_PROXY *dict_proxy;
+ VSTREAM *stream;
+ int server_flags;
+ int status;
+ char *kludge = 0;
+ char *prefix;
+
+ /*
+ * Sanity checks.
+ */
+ if (dict_flags & DICT_FLAG_NO_PROXY)
+ msg_fatal("%s: proxy map must not be used with this map type", map);
+ if (open_flags != O_RDONLY)
+ msg_fatal("%s: proxy map open requires O_RDONLY access mode", map);
+
+ /*
+ * Local initialization.
+ */
+ dict_proxy = (DICT_PROXY *)
+ dict_alloc(DICT_TYPE_PROXY, map, sizeof(*dict_proxy));
+ dict_proxy->dict.lookup = dict_proxy_lookup;
+ dict_proxy->dict.close = dict_proxy_close;
+ dict_proxy->in_flags = dict_flags;
+ dict_proxy->result = vstring_alloc(10);
+
+ /*
+ * Use a shared stream for all proxied table lookups.
+ *
+ * XXX Use absolute pathname to make this work from non-daemon processes.
+ */
+ if (proxy_stream == 0) {
+ if (access(MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYMAP, F_OK) == 0)
+ prefix = MAIL_CLASS_PRIVATE;
+ else
+ prefix = kludge = concatenate(var_queue_dir, "/",
+ MAIL_CLASS_PRIVATE, (char *) 0);
+ proxy_stream = clnt_stream_create(prefix,
+ MAIL_SERVICE_PROXYMAP,
+ var_ipc_idle_limit);
+ if (kludge)
+ myfree(kludge);
+ }
+
+ /*
+ * Establish initial contact and get the map type specific flags.
+ *
+ * XXX Should retrieve flags from local instance.
+ */
+ for (;;) {
+ stream = clnt_stream_access(proxy_stream);
+ errno = 0;
+ if (attr_print(stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_STR, MAIL_ATTR_REQ, PROXY_REQ_OPEN,
+ ATTR_TYPE_STR, MAIL_ATTR_TABLE, dict_proxy->dict.name,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, dict_proxy->in_flags,
+ ATTR_TYPE_END) != 0
+ || attr_scan(stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &server_flags,
+ ATTR_TYPE_END) != 2) {
+ if (msg_verbose || (errno != EPIPE && errno != ENOENT))
+ msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname);
+ } else {
+ if (msg_verbose)
+ msg_info("%s: connect to map=%s status=%d server_flags=0%o",
+ myname, dict_proxy->dict.name, status, server_flags);
+ switch (status) {
+ case PROXY_STAT_BAD:
+ msg_fatal("%s open failed for table \"%s\": invalid request",
+ MAIL_SERVICE_PROXYMAP, dict_proxy->dict.name);
+ case PROXY_STAT_DENY:
+ msg_fatal("%s service is not configured for table \"%s\"",
+ MAIL_SERVICE_PROXYMAP, dict_proxy->dict.name);
+ case PROXY_STAT_OK:
+ dict_proxy->dict.flags = dict_proxy->in_flags | server_flags;
+ return (DICT_DEBUG (&dict_proxy->dict));
+ default:
+ msg_warn("%s open failed for table \"%s\": unexpected status %d",
+ MAIL_SERVICE_PROXYMAP, dict_proxy->dict.name, status);
+ }
+ }
+ clnt_stream_recover(proxy_stream);
+ sleep(1); /* XXX make configurable */
+ }
+}
--- /dev/null
+#ifndef _DICT_PROXY_H_INCLUDED_
+#define _DICT_PROXY_H_INCLUDED_
+
+/*++
+/* NAME
+/* dict_proxy 3h
+/* SUMMARY
+/* dictionary manager interface to PROXY maps
+/* SYNOPSIS
+/* #include <dict_proxy.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * Utility library.
+ */
+#include <dict.h>
+
+ /*
+ * External interface.
+ */
+#define DICT_TYPE_PROXY "proxy"
+
+extern DICT *dict_proxy_open(const char *, int, int);
+
+ /*
+ * Protocol interface.
+ */
+#define PROXY_REQ_OPEN "open"
+#define PROXY_REQ_LOOKUP "lookup"
+
+#define PROXY_STAT_OK 0 /* operation succeeded */
+#define PROXY_STAT_NOKEY 1 /* requested key not found */
+#define PROXY_STAT_RETRY 2 /* try lookup again later */
+#define PROXY_STAT_BAD 3 /* invalid request parameter */
+#define PROXY_STAT_DENY 4 /* table not approved for proxying */
+
+/* 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
--- /dev/null
+/*++
+/* NAME
+/* mail_dict 3
+/* SUMMARY
+/* register application-specific dictionaries
+/* SYNOPSIS
+/* #include <mail_dict.h>
+/*
+/* void mail_dict_init()
+/* DESCRIPTION
+/* This module registers dictionary types that depend on higher-level
+/* Postfix-specific interfaces and protocols.
+/* 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 <sys_defs.h>
+
+/* Utility library. */
+
+#include <dict.h>
+#include <msg.h>
+
+/* Global library. */
+
+#include <dict_proxy.h>
+#include <mail_dict.h>
+
+typedef struct {
+ char *type;
+ struct DICT *(*open) (const char *, int, int);
+} DICT_OPEN_INFO;
+
+static DICT_OPEN_INFO dict_open_info[] = {
+ DICT_TYPE_PROXY, dict_proxy_open,
+ /* XXX LDAP and MYSQL etc. should go here, too. */
+ 0,
+};
+
+/* mail_dict_init - dictionaries that depend on Postfix-specific interfaces */
+
+void mail_dict_init(void)
+{
+ DICT_OPEN_INFO *dp;
+
+ for (dp = dict_open_info; dp->type; dp++)
+ dict_open_register(dp->type, dp->open);
+}
--- /dev/null
+/*++
+/* NAME
+/* mail_dict 3h
+/* SUMMARY
+/* register application-specific dictionaries
+/* SYNOPSIS
+/* #include <mail_dict.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+extern void mail_dict_init(void);
+
+/* 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
+/*--*/
#define VAR_DEST_CON_LIMIT "default_destination_concurrency_limit"
#define _DEST_CON_LIMIT "_destination_concurrency_limit"
-#define DEF_DEST_CON_LIMIT 10
+#define DEF_DEST_CON_LIMIT 20
extern int var_dest_con_limit;
#define VAR_LOCAL_CON_LIMIT "local" _DEST_CON_LIMIT
* Heuristic to reject unknown local recipients at the SMTP port.
*/
#define VAR_LOCAL_RCPT_MAPS "local_recipient_maps"
-#define DEF_LOCAL_RCPT_MAPS "unix:passwd.byname $alias_maps"
+#define DEF_LOCAL_RCPT_MAPS "proxy:unix:passwd.byname $alias_maps"
extern char *var_local_rcpt_maps;
#define VAR_LOCAL_RCPT_CODE "unknown_local_recipient_reject_code"
#define DEF_LOCAL_RCPT_CODE 550
extern int var_local_rcpt_code;
+ /*
+ * List of pre-approved maps that are OK to open with the proxymap service.
+ */
+#define VAR_PROXY_READ_MAPS "proxy_read_maps"
+#define DEF_PROXY_READ_MAPS "$" VAR_LOCAL_RCPT_MAPS \
+ " $" VAR_MYDEST \
+ " $" VAR_VIRT_ALIAS_MAPS \
+ " $" VAR_VIRT_ALIAS_DOMS \
+ " $" VAR_VIRT_MAILBOX_MAPS \
+ " $" VAR_VIRT_MAILBOX_DOMS \
+ " $" VAR_RELAY_RCPT_MAPS \
+ " $" VAR_RELAY_DOMAINS \
+ " $" VAR_CANONICAL_MAPS \
+ " $" VAR_SEND_CANON_MAPS \
+ " $" VAR_RCPT_CANON_MAPS \
+ " $" VAR_RELOCATED_MAPS \
+ " $" VAR_TRANSPORT_MAPS
+extern char *var_proxy_read_maps;
+
/*
* Other.
*/
#define MAIL_SERVICE_ERROR "error"
#define MAIL_SERVICE_FLUSH "flush"
#define MAIL_SERVICE_RELAY "relay"
+#define MAIL_SERVICE_PROXYMAP "proxymap"
/*
* Well-known socket or FIFO directories. The main difference is in file
#define MAIL_ATTR_ADDR "address"
#define MAIL_ATTR_TRANSPORT "transport"
#define MAIL_ATTR_NEXTHOP "nexthop"
+#define MAIL_ATTR_TABLE "table"
+#define MAIL_ATTR_KEY "key"
+#define MAIL_ATTR_VALUE "value"
/*
* Suffixes for sender_name, sender_domain etc.
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20021222"
+#define MAIL_RELEASE_DATE "20030112"
#define VAR_MAIL_VERSION "mail_version"
-#define DEF_MAIL_VERSION "2.0.0"
+#define DEF_MAIL_VERSION "2.0.1"
extern char *var_mail_version;
/*
/* named dictionaries.
/* The result is a handle that must be specified along with all
/* other virtual8_maps_xxx() operations.
-/* See dict_open(3) for a description of flags. virtual8_maps_create()
-/* implicitly sets the DICT_FLAG_NO_REGSUB flag in order to disable
-/* regular expression substitution into the lookup result.
+/* See dict_open(3) for a description of flags.
/*
/* virtual8_maps_find() searches the specified list of dictionaries
/* in the specified order for the named key. The result is in
* External interface.
*/
#define virtual8_maps_create(title, map_names, flags) \
- maps_create((title), (map_names), (flags) | DICT_FLAG_NO_REGSUB)
+ maps_create((title), (map_names), (flags))
extern const char *virtual8_maps_find(MAPS *, const char *);
#define virtual8_maps_free(maps) maps_free((maps))
set_file_limit(var_mailbox_limit);
}
alias_maps = maps_create("aliases", var_alias_maps,
- DICT_FLAG_LOCK | DICT_FLAG_NO_REGSUB);
+ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
}
/* main - pass control to the single-threaded skeleton */
multi_server.o: ../../include/debug_process.h
multi_server.o: ../../include/mail_params.h
multi_server.o: ../../include/mail_conf.h
+multi_server.o: ../../include/mail_dict.h
multi_server.o: ../../include/timed_ipc.h
multi_server.o: ../../include/resolve_local.h
multi_server.o: mail_flow.h
single_server.o: ../../include/mail_task.h
single_server.o: ../../include/debug_process.h
single_server.o: ../../include/mail_conf.h
+single_server.o: ../../include/mail_dict.h
single_server.o: ../../include/timed_ipc.h
single_server.o: ../../include/resolve_local.h
single_server.o: mail_flow.h
trigger_server.o: ../../include/mail_task.h
trigger_server.o: ../../include/debug_process.h
trigger_server.o: ../../include/mail_conf.h
+trigger_server.o: ../../include/mail_dict.h
trigger_server.o: ../../include/resolve_local.h
trigger_server.o: mail_flow.h
trigger_server.o: master_proto.h
mymalloc(sizeof(*MASTER_INET_ADDRLIST(serv)));
inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
+ inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
} else if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
MASTER_INET_ADDRLIST(serv) = 0; /* wild-card */
serv->listen_fd_count = 1;
} else {
MASTER_INET_ADDRLIST(serv) = own_inet_addr_list(); /* virtual */
+ inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
}
MASTER_INET_PORT(serv) = mystrdup(port);
/* The var_idle_limit variable limits the time that a service
/* receives no client connection requests before it commits suicide.
/* This value is taken from the global \fBmain.cf\fR configuration
-/* file. Setting \fBvar_use_limit\fR to zero disables the idle limit.
+/* file. Setting \fBvar_idle_limit\fR to zero disables the idle limit.
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8).
/* SEE ALSO
#include <debug_process.h>
#include <mail_params.h>
#include <mail_conf.h>
+#include <mail_dict.h>
#include <timed_ipc.h>
#include <resolve_local.h>
#include <mail_flow.h>
*/
mail_conf_suck();
+ /*
+ * Register dictionaries that use higher-level interfaces and protocols.
+ */
+ mail_dict_init();
+
/*
* Pick up policy settings from master process. Shut up error messages to
* stderr, because no-one is going to see them.
/*
* Run pre-jail initialization.
*/
+ if (chdir(var_queue_dir) < 0)
+ msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
if (pre_init)
pre_init(multi_server_name, multi_server_argv);
/*
* Optionally, restrict the damage that this process can do.
*/
- if (chdir(var_queue_dir) < 0)
- msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
resolve_local_init();
chroot_uid(root_dir, user_name);
#include <mail_task.h>
#include <debug_process.h>
#include <mail_conf.h>
+#include <mail_dict.h>
#include <timed_ipc.h>
#include <resolve_local.h>
#include <mail_flow.h>
*/
mail_conf_suck();
+ /*
+ * Register dictionaries that use higher-level interfaces and protocols.
+ */
+ mail_dict_init();
+
/*
* Pick up policy settings from master process. Shut up error messages to
* stderr, because no-one is going to see them.
/*
* Run pre-jail initialization.
*/
+ if (chdir(var_queue_dir) < 0)
+ msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
if (pre_init)
pre_init(single_server_name, single_server_argv);
/*
* Optionally, restrict the damage that this process can do.
*/
- if (chdir(var_queue_dir) < 0)
- msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
resolve_local_init();
chroot_uid(root_dir, user_name);
#include <mail_task.h>
#include <debug_process.h>
#include <mail_conf.h>
+#include <mail_dict.h>
#include <resolve_local.h>
#include <mail_flow.h>
*/
mail_conf_suck();
+ /*
+ * Register dictionaries that use higher-level interfaces and protocols.
+ */
+ mail_dict_init();
+
/*
* Pick up policy settings from master process. Shut up error messages to
* stderr, because no-one is going to see them.
/*
* Run pre-jail initialization.
*/
+ if (chdir(var_queue_dir) < 0)
+ msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
if (pre_init)
pre_init(trigger_server_name, trigger_server_argv);
/*
* Optionally, restrict the damage that this process can do.
*/
- if (chdir(var_queue_dir) < 0)
- msg_fatal("chdir(\"%s\"): %m", var_queue_dir);
resolve_local_init();
chroot_uid(root_dir, user_name);
postalias.o: ../../include/tok822.h
postalias.o: ../../include/resolve_clnt.h
postalias.o: ../../include/mail_conf.h
+postalias.o: ../../include/mail_dict.h
postalias.o: ../../include/mail_params.h
postalias.o: ../../include/mkmap.h
postalias.o: ../../include/dict.h
#include <tok822.h>
#include <mail_conf.h>
+#include <mail_dict.h>
#include <mail_params.h>
#include <mkmap.h>
}
}
mail_conf_read();
+ mail_dict_init();
/*
* Use the map type specified by the user, or fall back to a default
postconf.o: ../../include/myflock.h
postconf.o: ../../include/mynetworks.h
postconf.o: ../../include/mail_conf.h
+postconf.o: ../../include/mail_dict.h
postconf.o: ../../include/mail_proto.h
postconf.o: ../../include/iostuff.h
postconf.o: ../../include/attr.h
/* stale lock files that were left behind after abnormal termination.
/* .RE
/* .IP \fB-m\fR
-/* List the names of all supported lookup table types.
+/* List the names of all supported lookup table types. Postfix
+/* lookup tables are specified as \fItype\fB:\fIname\fR, where
+/* \fItype\fR is one of the types listed below. The table \fIname\fR
+/* syntax depends on the lookup table type.
/* .RS
/* .IP \fBbtree\fR
/* A sorted, balanced tree structure.
/* .IP "\fBpcre\fR (read-only)"
/* A lookup table based on Perl Compatible Regular Expressions. The
/* file format is described in \fBpcre_table\fR(5).
+/* .IP "\fBproxy\fR (read-only)"
+/* A lookup table that is implemented via the Postfix
+/* \fBproxymap\fR(8) service. The table name syntax is
+/* \fItype\fB:\fIname\fR.
/* .IP "\fBregexp\fR (read-only)"
/* A lookup table based on regular expressions. The file format is
/* described in \fBregexp_table\fR(5).
#include <mynetworks.h>
#include <mail_conf.h>
+#include <mail_dict.h>
#include <mail_proto.h>
#include <mail_version.h>
#include <mail_params.h>
* If showing map types, show them and exit
*/
if (mode & SHOW_MAPS) {
+ mail_dict_init();
show_maps();
}
postmap.o: ../../include/vstring_vstream.h
postmap.o: ../../include/set_eugid.h
postmap.o: ../../include/mail_conf.h
+postmap.o: ../../include/mail_dict.h
postmap.o: ../../include/mail_params.h
postmap.o: ../../include/mkmap.h
postmap.o: ../../include/dict.h
/* Global library. */
#include <mail_conf.h>
+#include <mail_dict.h>
#include <mail_params.h>
#include <mkmap.h>
}
}
mail_conf_read();
+ mail_dict_init();
/*
* Use the map type specified by the user, or fall back to a default
/* \fBpostqueue\fR [\fB-c \fIconfig_dir\fR] \fB-s \fIsite\fR
/* DESCRIPTION
/* The \fBpostqueue\fR program implements the Postfix user interface
-/* for queue management. It implements all the operations that are
+/* for queue management. It implements operations that are
/* traditionally available via the \fBsendmail\fR(1) command.
+/* See the \fBpostsuper\fR(1) command for queue operations
+/* that require super-user privileges such as deleting a message
+/* from the queue or changing the status of a message.
/*
/* The following options are recognized:
/* .IP "\fB-c \fIconfig_dir\fR"
/* specifies the domains that Postfix accepts in the SMTP \fBETRN\fR
/* request and in the \fBsendmail -qR\fR command.
/* SEE ALSO
-/* sendmail(8) sendmail-compatible user interface
+/* sendmail(1) sendmail-compatible user interface
+/* postsuper(1) privileged queue operations
/* qmgr(8) queue manager
/* showq(8) list mail queue
/* flush(8) fast flush service
/* DESCRIPTION
/* The \fBpostsuper\fR command does maintenance jobs on the Postfix
/* queue. Use of the command is restricted to the superuser.
+/* See the \fBpostqueue\fR command for unprivileged queue operations
+/* such as listing or flushing the mail queue.
/*
/* By default, \fBpostsuper\fR performs the operations requested with the
/* \fB-s\fR and \fB-p\fR command-line options on all Postfix queue
/* .IP \fBhash_queue_names\fR
/* The names of queues that are organized into multiple levels of
/* subdirectories.
+/* SEE ALSO
+/* sendmail(1) sendmail-compatible user interface
+/* postqueue(1) unprivileged queue operations
/* LICENSE
/* .ad
/* .fi
--- /dev/null
+../../.indent.pro
\ No newline at end of file
--- /dev/null
+SHELL = /bin/sh
+SRCS = proxymap.c
+OBJS = proxymap.o
+HDRS =
+TESTSRC =
+WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
+ -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
+ -Wunused
+DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
+CFLAGS = $(DEBUG) $(OPT) $(DEFS)
+TESTPROG=
+PROG = proxymap
+INC_DIR = ../../include
+LIBS = ../../lib/libmaster.a ../../lib/libglobal.a ../../lib/libutil.a
+
+.c.o:; $(CC) $(CFLAGS) -c $*.c
+
+$(PROG): $(OBJS) $(LIBS)
+ $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
+
+Makefile: Makefile.in
+ (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+
+test: $(TESTPROG)
+
+tests: test
+
+update: ../../libexec/$(PROG)
+
+../../libexec/$(PROG): $(PROG)
+ cp $(PROG) ../../libexec
+
+printfck: $(OBJS) $(PROG)
+ rm -rf printfck
+ mkdir printfck
+ sed '1,/^# do not edit/!d' Makefile >printfck/Makefile
+ set -e; for i in *.c; do printfck -f .printfck $$i >printfck/$$i; done
+ cd printfck; make "INC_DIR=../../../include" `cd ..; ls *.o`
+
+lint:
+ lint $(DEFS) $(SRCS) $(LINTFIX)
+
+clean:
+ rm -f *.o *core $(PROG) $(TESTPROG) junk
+ rm -rf printfck
+
+tidy: clean
+
+depend: $(MAKES)
+ (sed '1,/^# do not edit/!d' Makefile.in; \
+ set -e; for i in [a-z][a-z0-9]*.c; do \
+ $(CC) -E $(DEFS) $(INCL) $$i | sed -n -e '/^# *1 *"\([^"]*\)".*/{' \
+ -e 's//'`echo $$i|sed 's/c$$/o/'`': \1/' -e 'p' -e '}'; \
+ done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in
+ @$(EXPORT) make -f Makefile.in Makefile 1>&2
+
+# do not edit below this line - it is generated by 'make depend'
+proxymap.o: proxymap.c
+proxymap.o: ../../include/sys_defs.h
+proxymap.o: ../../include/msg.h
+proxymap.o: ../../include/mymalloc.h
+proxymap.o: ../../include/vstring.h
+proxymap.o: ../../include/vbuf.h
+proxymap.o: ../../include/htable.h
+proxymap.o: ../../include/stringops.h
+proxymap.o: ../../include/dict.h
+proxymap.o: ../../include/vstream.h
+proxymap.o: ../../include/argv.h
+proxymap.o: ../../include/mail_conf.h
+proxymap.o: ../../include/mail_params.h
+proxymap.o: ../../include/mail_proto.h
+proxymap.o: ../../include/iostuff.h
+proxymap.o: ../../include/attr.h
+proxymap.o: ../../include/dict_proxy.h
+proxymap.o: ../../include/mail_server.h
--- /dev/null
+/*++
+/* NAME
+/* proxymap 8
+/* SUMMARY
+/* Postfix lookup table proxy server
+/* SYNOPSIS
+/* \fBproxymap\fR [generic Postfix daemon options]
+/* DESCRIPTION
+/* The \fBproxymap\fR server provides read-only table
+/* lookup service to Postfix client processes. The purpose
+/* of the service is:
+/* .IP \(bu
+/* To overcome chroot restrictions. For example, a chrooted SMTP
+/* server needs access to the system passwd file in order to
+/* reject mail for non-existent local addresses, but it is not
+/* practical to maintain a copy of the passwd file in the chroot
+/* jail. The solution:
+/* .sp
+/* local_recipient_maps =
+/* .ti +4
+/* proxy:unix:passwd.byname $alias_maps
+/* .IP \(bu
+/* To consolidate the number of open lookup tables by sharing
+/* one open table among multiple processes. For example, making
+/* mysql connections from every Postfix daemon process results
+/* in "too many connections" errors. The solution:
+/* .sp
+/* virtual_alias_maps =
+/* .ti +4
+/* proxy:mysql:/etc/postfix/virtual.cf
+/* .sp
+/* The total number of connections is limited by the number of
+/* proxymap server server processes.
+/* .PP
+/* The proxymap server implements the following requests:
+/* .IP "\fBPROXY_REQ_OPEN\fI maptype:mapname flags\fR"
+/* Open the table with type \fImaptype\fR and name \fImapname\fR,
+/* as controlled by \fIflags\fR.
+/* The reply is the request completion status code (below) and the
+/* map type dependent flags.
+/* .IP "\fBPROXY_REQ_LOOKUP\fI maptype:mapname flags key\fR"
+/* Look up the data stored under the requested key.
+/* The reply is the request completion status code (below) and
+/* the lookup result value.
+/* The \fImaptype:mapname\fR and \fIflags\fR are the same
+/* as with the \fBPROXY_REQ_OPEN\fR request.
+/* .PP
+/* There is no close command, nor are tables implicitly closed
+/* when a client disconnects. One of the purposes of the proxymap
+/* server is to share tables among multiple client processes.
+/*
+/* The request completion status code is one of:
+/* .IP \fBPROXY_STAT_OK\fR
+/* The specified table was opened, or the requested entry was found.
+/* .IP \fBPROXY_STAT_NOKEY\fR
+/* The requested table entry was not found.
+/* .IP \fBPROXY_STAT_BAD\fR
+/* The request was rejected (bad request parameter value).
+/* .IP \fBPROXY_STAT_RETRY\fR
+/* The lookup request could not be completed.
+/* .IP \fBPROXY_STAT_DENY\fR
+/* The specified table was not approved for access via the
+/* proxymap service.
+/* SERVER PROCESS MANAGEMENT
+/* .ad
+/* .fi
+/* The proxymap servers run under control by the Postfix master
+/* server. Each server can handle multiple simultaneous connections.
+/* When all servers are busy while a client connects, the master
+/* creates a new proxymap server process, provided that the proxymap
+/* server process limit is not exceeded.
+/* Each proxymap server terminates after serving
+/* at least \fB$max_use\fR clients or after \fB$max_idle\fR seconds
+/* of idle time.
+/* SECURITY
+/* .ad
+/* .fi
+/* The proxymap server opens only tables that are approved via the
+/* \fBproxy_read_maps\fR configuration parameter, does not talk to
+/* users, and can run at fixed low privilege, chrooted or not.
+/*
+/* The proxymap server is not a trusted daemon process, and must
+/* not be used to look up sensitive information such as user or
+/* group IDs, mailbox file/directory names or external commands.
+/* DIAGNOSTICS
+/* Problems and transactions are logged to \fBsyslogd\fR(8).
+/* BUGS
+/* The proxymap server provides service to multiple clients,
+/* and must therefore not be used for tables that have high-latency
+/* lookups.
+/* CONFIGURATION PARAMETERS
+/* .ad
+/* .fi
+/* The following main.cf parameters are especially relevant
+/* to this program. Use the \fBpostfix reload\fR command
+/* after a configuration change.
+/* .IP \fBproxy_read_maps\fR
+/* A list of zero or more parameter values that may contain
+/* references to Postfix lookup tables. Only table references
+/* that begin with \fBproxy:\fR are approved for read-only
+/* access via the proxymap server.
+/* SEE ALSO
+/* dict_proxy(3) proxy map client
+/* 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 <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <htable.h>
+#include <stringops.h>
+#include <dict.h>
+
+/* Global library. */
+
+#include <mail_conf.h>
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <dict_proxy.h>
+
+/* Server skeleton. */
+
+#include <mail_server.h>
+
+/* Application-specific. */
+
+ /*
+ * XXX All but the last are needed here so that $name expansion dependencies
+ * aren't too broken. The fix is to gather all parameter default settings in
+ * one place.
+ */
+char *var_local_rcpt_maps;
+char *var_virt_alias_maps;
+char *var_virt_alias_doms;
+char *var_virt_mbox_maps;
+char *var_virt_mbox_doms;
+char *var_relay_rcpt_maps;
+char *var_relay_domains;
+char *var_canonical_maps;
+char *var_send_canon_maps;
+char *var_rcpt_canon_maps;
+char *var_relocatedmaps;
+char *var_transport_maps;
+char *var_proxy_read_maps;
+
+ /*
+ * The pre-approved, pre-parsed list of maps.
+ */
+static HTABLE *proxy_read_maps;
+
+ /*
+ * Shared and static to reduce memory allocation overhead.
+ */
+static VSTRING *request;
+static VSTRING *request_map;
+static VSTRING *request_key;
+static VSTRING *map_type_name_flags;
+
+ /*
+ * Silly little macros.
+ */
+#define STR(x) vstring_str(x)
+#define VSTREQ(x,y) (strcmp(STR(x),y) == 0)
+
+/* proxy_map_find - look up or open table */
+
+static DICT *proxy_map_find(const char *map_type_name, int request_flags,
+ int *statp)
+{
+ DICT *dict;
+
+#define PROXY_COLON DICT_TYPE_PROXY ":"
+#define PROXY_COLON_LEN (sizeof(PROXY_COLON) - 1)
+#define READ_OPEN_FLAGS O_RDONLY
+
+ /*
+ * Canonicalize the map name. If the map is not on the approved list,
+ * deny the request.
+ */
+#define PROXY_MAP_FIND_ERROR_RETURN(x) { *statp = (x); return (0); }
+
+ while (strncmp(map_type_name, PROXY_COLON, PROXY_COLON_LEN) == 0)
+ map_type_name += PROXY_COLON_LEN;
+ if (strchr(map_type_name, ':') == 0)
+ PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_BAD);
+ if (htable_locate(proxy_read_maps, map_type_name) == 0) {
+ msg_warn("request for unapproved table: \"%s\"", map_type_name);
+ msg_warn("to approve this table for %s access, list %s:%s in %s:%s",
+ MAIL_SERVICE_PROXYMAP, DICT_TYPE_PROXY, map_type_name,
+ MAIN_CONF_FILE, VAR_PROXY_READ_MAPS);
+ PROXY_MAP_FIND_ERROR_RETURN(PROXY_STAT_DENY);
+ }
+
+ /*
+ * Open one instance of a map for each combination of name+flags.
+ */
+ vstring_sprintf(map_type_name_flags, "%s:%o",
+ map_type_name, request_flags);
+ if ((dict = dict_handle(STR(map_type_name_flags))) == 0)
+ dict = dict_open(map_type_name, READ_OPEN_FLAGS, request_flags);
+ if (dict == 0)
+ msg_panic("proxy_map_find: dict_open null result");
+ dict_register(STR(map_type_name_flags), dict);
+ return (dict);
+}
+
+/* proxymap_lookup_service - remote lookup service */
+
+static void proxymap_lookup_service(VSTREAM *client_stream)
+{
+ int request_flags;
+ DICT *dict;
+ const char *reply_value;
+ int reply_status;
+
+ /*
+ * Process the request.
+ */
+ if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_STR, MAIL_ATTR_TABLE, request_map,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request_flags,
+ ATTR_TYPE_STR, MAIL_ATTR_KEY, request_key,
+ ATTR_TYPE_END) != 3) {
+ reply_status = PROXY_STAT_BAD;
+ reply_value = "";
+ } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ &reply_status)) == 0) {
+ reply_value = "";
+ } else if ((reply_value = dict_get(dict, STR(request_key))) != 0) {
+ reply_status = PROXY_STAT_OK;
+ } else if (dict_errno == 0) {
+ reply_status = PROXY_STAT_NOKEY;
+ reply_value = "";
+ } else {
+ reply_status = PROXY_STAT_RETRY;
+ reply_value = "";
+ }
+
+ /*
+ * Respond to the client.
+ */
+ attr_print(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status,
+ ATTR_TYPE_STR, MAIL_ATTR_VALUE, reply_value,
+ ATTR_TYPE_END);
+}
+
+/* proxymap_open_service - open remote lookup table */
+
+static void proxymap_open_service(VSTREAM *client_stream)
+{
+ int request_flags;
+ DICT *dict;
+ int reply_status;
+ int reply_flags;
+
+ /*
+ * Process the request.
+ */
+ if (attr_scan(client_stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_STR, MAIL_ATTR_TABLE, request_map,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request_flags,
+ ATTR_TYPE_END) != 2) {
+ reply_status = PROXY_STAT_BAD;
+ reply_flags = 0;
+ } else if ((dict = proxy_map_find(STR(request_map), request_flags,
+ &reply_status)) == 0) {
+ reply_flags = 0;
+ } else {
+ reply_status = PROXY_STAT_OK;
+ reply_flags = dict->flags;
+ }
+
+ /*
+ * Respond to the client.
+ */
+ attr_print(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, reply_flags,
+ ATTR_TYPE_END);
+}
+
+/* proxymap_service - perform service for client */
+
+static void proxymap_service(VSTREAM *client_stream, char *unused_service,
+ char **argv)
+{
+
+ /*
+ * Sanity check. This service takes no command-line arguments.
+ */
+ if (argv[0])
+ msg_fatal("unexpected command-line argument: %s", argv[0]);
+
+ /*
+ * This routine runs whenever a client connects to the socket dedicated
+ * to the proxymap service. All connection-management stuff is handled by
+ * the common code in multi_server.c.
+ */
+ if (attr_scan(client_stream,
+ ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
+ ATTR_TYPE_STR, MAIL_ATTR_REQ, request,
+ ATTR_TYPE_END) == 1) {
+ if (VSTREQ(request, PROXY_REQ_LOOKUP)) {
+ proxymap_lookup_service(client_stream);
+ } else if (VSTREQ(request, PROXY_REQ_OPEN)) {
+ proxymap_open_service(client_stream);
+ } else {
+ msg_warn("unrecognized request: \"%s\", ignored", STR(request));
+ attr_print(client_stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_NUM, MAIL_ATTR_STATUS, PROXY_STAT_BAD,
+ ATTR_TYPE_END);
+ }
+ }
+ vstream_fflush(client_stream);
+}
+
+/* post_jail_init - initialization after privilege drop */
+
+static void post_jail_init(char *unused_name, char **unused_argv)
+{
+ const char *sep = " \t\r\n";
+ char *saved_filter;
+ char *bp;
+ char *type_name;
+
+ /*
+ * Pre-allocate buffers.
+ */
+ request = vstring_alloc(10);
+ request_map = vstring_alloc(10);
+ request_key = vstring_alloc(10);
+ map_type_name_flags = vstring_alloc(10);
+
+ /*
+ * Prepare the pre-approved list of proxied tables.
+ */
+ saved_filter = bp = mystrdup(var_proxy_read_maps);
+ proxy_read_maps = htable_create(13);
+ while ((type_name = mystrtok(&bp, sep)) != 0) {
+ if (strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN))
+ continue;
+ do {
+ type_name += PROXY_COLON_LEN;
+ } while (!strncmp(type_name, PROXY_COLON, PROXY_COLON_LEN));
+ if (strchr(type_name, ':') != 0
+ && htable_locate(proxy_read_maps, type_name) == 0)
+ (void) htable_enter(proxy_read_maps, type_name, (char *) 0);
+ }
+ myfree(saved_filter);
+}
+
+/* pre_accept - see if tables have changed */
+
+static void pre_accept(char *unused_name, char **unused_argv)
+{
+ if (dict_changed()) {
+ msg_info("some lookup table has changed -- restarting");
+ exit(0);
+ }
+}
+
+/* main - pass control to the multi-threaded skeleton */
+
+int main(int argc, char **argv)
+{
+ static CONFIG_STR_TABLE str_table[] = {
+ VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0,
+ VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0,
+ VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 0, 0,
+ VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mbox_maps, 0, 0,
+ VAR_VIRT_MAILBOX_DOMS, DEF_VIRT_MAILBOX_DOMS, &var_virt_mbox_doms, 0, 0,
+ VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0,
+ VAR_RELAY_DOMAINS, DEF_RELAY_DOMAINS, &var_relay_domains, 0, 0,
+ VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0,
+ VAR_SEND_CANON_MAPS, DEF_SEND_CANON_MAPS, &var_send_canon_maps, 0, 0,
+ VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0,
+ VAR_RELOCATED_MAPS, DEF_RELOCATED_MAPS, &var_relocatedmaps, 0, 0,
+ VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
+ VAR_PROXY_READ_MAPS, DEF_PROXY_READ_MAPS, &var_proxy_read_maps, 0, 0,
+ 0,
+ };
+
+ multi_server_main(argc, argv, proxymap_service,
+ MAIL_SERVER_STR_TABLE, str_table,
+ MAIL_SERVER_POST_INIT, post_jail_init,
+ MAIL_SERVER_PRE_ACCEPT, pre_accept,
+ 0);
+}
smtpd_check.o: ../../include/mail_proto.h
smtpd_check.o: ../../include/iostuff.h
smtpd_check.o: ../../include/attr.h
+smtpd_check.o: ../../include/mail_addr.h
smtpd_check.o: smtpd.h
smtpd_check.o: ../../include/mail_stream.h
smtpd_check.o: smtpd_sasl_glue.h
#include <record.h>
#include <rec_type.h>
#include <mail_proto.h>
+#include <mail_addr.h>
/* Application-specific. */
msg_warn("access map %s entry %s has FILTER entry without value",
table, datum);
return (SMTPD_CHECK_DUNNO);
+ } else if (strchr(cmd_text, ':') == 0) {
+ msg_warn("access map %s entry %s requires transport:destination",
+ table, datum);
+ return (SMTPD_CHECK_DUNNO);
} else {
vstring_sprintf(error_text, "<%s>: %s triggers FILTER %s",
reply_name, reply_class, cmd_text);
* local delivery, because the virtual delivery agent requires
* user@domain style addresses in its user database.
*/
+#define MATCH_LEFT(l, r, n) (strncasecmp((l), (r), (n)) == 0 && (r)[n] == '@')
+
if ((reply->flags & RESOLVE_CLASS_LOCAL)
&& *var_local_rcpt_maps
+ && !MATCH_LEFT(var_double_bounce_sender, CONST_STR(reply->recipient),
+ strlen(var_double_bounce_sender))
+ && !MATCH_LEFT(MAIL_ADDR_POSTMASTER, CONST_STR(reply->recipient),
+ strlen(MAIL_ADDR_POSTMASTER))
&& NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient)))
return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown%s",
* Reject mail to unknown addresses in virtual mailbox domains.
*/
if ((reply->flags & RESOLVE_CLASS_VIRTUAL)
+ && *var_virt_mailbox_maps
&& NOMATCHV8(virt_mailbox_maps, CONST_STR(reply->recipient)))
return (smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown%s",
*/
if (virt_alias_doms
&& string_list_match(virt_alias_doms, rcpt_domain)) {
- if (var_helpful_warnings
- && virt_mailbox_doms
- && string_list_match(virt_mailbox_doms, rcpt_domain))
- msg_warn("do not list domain %s in BOTH %s and %s",
- rcpt_domain, VAR_VIRT_ALIAS_DOMS,
- VAR_VIRT_MAILBOX_DOMS);
+ if (var_helpful_warnings) {
+ if (virt_mailbox_doms
+ && string_list_match(virt_mailbox_doms, rcpt_domain))
+ msg_warn("do not list domain %s in BOTH %s and %s",
+ rcpt_domain, VAR_VIRT_ALIAS_DOMS,
+ VAR_VIRT_MAILBOX_DOMS);
+ }
vstring_strcpy(channel, MAIL_SERVICE_ERROR);
vstring_sprintf(nexthop, "User unknown%s",
var_show_unk_rcpt_table ?
/*
* Fall back to the wild-card entry.
*/
+ if (transport_errno)
+ transport_wildcard_init();
if (transport_errno) {
dict_errno = transport_errno;
RETURN_FREE(NOTFOUND);
/* .fi
/* By default, Postfix uses one of the following delivery methods.
/* This may be overruled with the optional transport(5) table.
-/* .IP \(bu
-/* The recipient domain matches \fB$mydestination\fR or
-/* \fB$inet_interfaces\fR. The transport and optional nexthop
+/* The default delivery method is selected by matching the
+/* recipient address domain against one of the following:
+/* .IP \fB$mydestination\fR
+/* .IP \fB$inet_interfaces\fR
+/* The transport and optional nexthop
/* are specified with \fB$local_transport\fR.
/* The default nexthop is the recipient domain.
-/* .IP \(bu
-/* The recipient domain matches \fB$virtual_mailbox_domains\fR.
+/* .IP \fB$virtual_alias_domains\fR
+/* The recipient address is undeliverable (user unknown).
+/* By definition, all known addresses in a virtual alias domain
+/* are aliased to other addresses.
+/* .IP \fB$virtual_mailbox_domains\fR
/* The transport and optional nexthop are specified with
/* \fB$virtual_transport\fR.
/* The default nexthop is the recipient domain.
-/* .IP \(bu
-/* The recipient domain matches \fB$relay_domains\fR. The
-/* transport and optional nexthop are specified with
+/* .IP \fB$relay_domains\fR
+/* The transport and optional nexthop are specified with
/* \fB$relay_transport\fR. This overrides the optional nexthop
/* information that is specified with \fB$relayhost\fR.
/* The default nexthop is the recipient domain.
-/* .IP \(bu
-/* All other destinations. the transport and optional nexthop are
-/* specified with \fB$relay_transport\fR.
+/* .IP "none of the above"
+/* The transport and optional nexthop are specified with
+/* \fB$default_transport\fR.
/* This overrides the optional nexthop information that is specified
/* with \fB$relayhost\fR.
/* The default nexthop is the recipient domain.
+/* SERVER PROCESS MANAGEMENT
+/* .ad
+/* .fi
+/* The trivial-rewrite servers run under control by the Postfix master
+/* server. Each server can handle multiple simultaneous connections.
+/* When all servers are busy while a client connects, the master
+/* creates a new server process, provided that the trivial-rewrite
+/* server process limit is not exceeded.
+/* Each trivial-rewrite server terminates after
+/* serving at least \fB$max_use\fR clients of after \fB$max_idle\fR
+/* seconds of idle time.
/* STANDARDS
/* .ad
/* .fi
#define DICT_FLAG_DEBUG (1<<9) /* log access */
#define DICT_FLAG_FOLD_KEY (1<<10) /* lowercase the lookup key */
#define DICT_FLAG_NO_REGSUB (1<<11) /* no lhs->rhs regexp substitution */
+#define DICT_FLAG_NO_PROXY (1<<12) /* no proxy mapping */
+
+#define DICT_FLAG_PARANOID (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY)
extern int dict_unknown_allowed;
extern int dict_errno;
/* .IP DICT_FLAG_NO_REGSUB
/* Disallow regular expression substitution from left-hand side data
/* into the right-hand side.
+/* .IP DICT_FLAG_NO_PROXY
+/* Disallow access through the \fBproxymap\fR service.
+/* .IP DICT_FLAG_PARANOID
+/* A combination of all the paranoia flags: DICT_FLAG_NO_REGSUB
+/* and DICT_FLAG_NO_PROXY.
/* .PP
/* Specify DICT_FLAG_NONE for no special processing.
/*
* allocation gives the application a chance to override the default
* buffering policy.
*/
- if (bp->data == 0)
+ if (bp->data == 0) {
vstream_buf_alloc(bp, VSTREAM_BUFSIZE);
+ if (bp->flags & VSTREAM_FLAG_DOUBLE)
+ VSTREAM_SAVE_STATE(stream, read_buf, read_fd);
+ }
/*
* If the stream is double-buffered and the write buffer is not empty,
*/
if (bp->data == 0) {
vstream_buf_alloc(bp, VSTREAM_BUFSIZE);
+ if (bp->flags & VSTREAM_FLAG_DOUBLE)
+ VSTREAM_SAVE_STATE(stream, write_buf, write_fd);
} else if (bp->cnt <= 0) {
if (VSTREAM_FFLUSH_SOME(stream))
return (VSTREAM_EOF);
/* For security reasons, regular expression maps are allowed but
/* regular expression substitution of $1 etc. is disallowed,
/* because that would open a security hole.
+/*
+/* For security reasons, proxied table lookup is not allowed,
+/* because that would open a security hole.
/* .IP \fBvirtual_mailbox_domains\fR
/* The list of domains that should be delivered via the Postfix virtual
/* delivery agent. This uses the same syntax as the \fBmydestination\fR
/* For security reasons, regular expression maps are allowed but
/* regular expression substitution of $1 etc. is disallowed,
/* because that would open a security hole.
+/*
+/* For security reasons, proxied table lookup is not allowed,
+/* because that would open a security hole.
/* .IP \fBvirtual_gid_maps\fR
/* Recipients are looked up in these maps to determine the group ID to be
/* used when writing to the target mailbox.
/* For security reasons, regular expression maps are allowed but
/* regular expression substitution of $1 etc. is disallowed,
/* because that would open a security hole.
+/*
+/* For security reasons, proxied table lookup is not allowed,
+/* because that would open a security hole.
/* .SH "Locking controls"
/* .ad
/* .fi
virtual_mailbox_maps =
virtual8_maps_create(VAR_VIRT_MAILBOX_MAPS, var_virt_mailbox_maps,
- DICT_FLAG_LOCK);
+ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_uid_maps =
virtual8_maps_create(VAR_VIRT_UID_MAPS, var_virt_uid_maps,
- DICT_FLAG_LOCK);
+ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_gid_maps =
virtual8_maps_create(VAR_VIRT_GID_MAPS, var_virt_gid_maps,
- DICT_FLAG_LOCK);
+ DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
virtual_mbox_lock_mask = mbox_lock_mask(var_virt_mailbox_lock);
}