2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

postfix-2.0.0-20030104

This commit is contained in:
Wietse Venema 2003-01-04 00:00:00 -05:00 committed by Viktor Dukhovni
parent 55978ec179
commit 1eed3b4cde
30 changed files with 529 additions and 326 deletions

View File

@ -7630,11 +7630,8 @@ Apologies for any names omitted.
20030102
Workaround: use different client instances when the same
map is opened with different flags. This silences warnings
from maps_append() when the same map is opened by
virtual_alias_maps and by virtual_mailbox_maps. File:
global/maps.c.
Cleanup: use different client instances when the same map
is opened with different flags. File: global/maps.c.
Feature: proxymap server for Postfix table lookups. This
helps to consolidate the number of open lookup tables (such
@ -7649,6 +7646,25 @@ Apologies for any names omitted.
after the limit is reached. Based on a patch by Victor
Duchovni, Morgan Stanley. File: master/multi_server.c.
20030103
Cleanup: client stream endpoints not only have an idle time
limit ($ipc_idle) before a connection is closed, they now
also have a time to live ($ipc_ttl) to prevent connections
from becoming too persistent. This allows multi-servers
such as trivial-rewrite or the proxymap server to refresh
more frequently on busy systems. File: global/clnt_stream.c.
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.
Open problems:
Med: do not postpone rejected "MAIL FROM" size information,

View File

@ -22,6 +22,37 @@ snapshot release). Patches change the patchlevel and the release
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
Incompatible changes with Postfix snapshot 2.0.0-20030104
=========================================================
This release adds the new proxymap service (table lookup via a
proxy process) to the the master.cf file. If you get warnings about
problems connecting to the proxymap service, then you did not
properly upgrade Postfix.
Major changes with Postfix snapshot 2.0.0-20030104
==================================================
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).
Multi-server daemons (servers that accept simultaneous connections
from multiple clients) will now stop accepting new connections
after serving $max_use clients. This allows multi-server daemons
to automatically restart even on busy mail systems.
Clients of multi-server daemons such as trivial-rewrite and the
new proxymap service now automatically disconnect after $ipc_ttl
seconds of activity (default: 1000s). This allows multi-server
daemons to automatically restart even on busy mail mail systems.
Incompatible changes with Postfix snapshot 1.1.11-trace-20021119
================================================================

View File

@ -175,18 +175,20 @@ mail_owner = postfix
# 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:passwd.byname $alias_maps
#local_recipient_maps =
# The unknown_local_recipient_reject_code specifies the SMTP server

View File

@ -11,6 +11,10 @@
# 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".

View File

@ -236,7 +236,7 @@ max_use = 100
# 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.

View File

@ -4,6 +4,65 @@
# 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: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
#

View File

@ -674,7 +674,7 @@ to send mail only to <i>user@domain.com</i>.
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.
@ -2090,7 +2090,7 @@ you use the default Postfix local delivery agent:
<pre>
/etc/postfix/main.cf:
local_recipient_maps = $alias_maps, unix:passwd.byname
local_recipient_maps = $alias_maps, proxy:unix:passwd.byname
</pre>
<p>
@ -2107,10 +2107,12 @@ To stop Postfix from rejecting local mail incorrectly:
<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>
@ -2313,21 +2315,30 @@ database" mean?</h3></a>
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 the 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>

View File

@ -91,7 +91,7 @@ POSTCONF(1) POSTCONF(1)
<b>proxy</b> (read-only)
A lookup table that is implemented via the
Postfix <a href="verify.8.html"><b>proxymap</b>(8)</a> service. The table name
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)

View File

@ -15,34 +15,39 @@ PROXYMAP(8) PROXYMAP(8)
<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. The solution is to specify:
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, to avoid problems due to "too many
connections" to, e.g., mysql servers, specify:
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
<b>PROXYMAP</b> <b>SERVICES</b>
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 and the map type dependent
flags.
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 and
the lookup result value. The <i>maptype: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.
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. This does not seem to be useful
because tables are meant to be shared among client pro-
@ -51,52 +56,63 @@ PROXYMAP(8) PROXYMAP(8)
The request completion status code is one of:
<b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
The requested table or lookup key was found.
The specified table was opened, or the requested
entry was found.
<b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>FAIL</b>
The requested table or lookup key does not exist.
<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
The request was rejected (bad request parameter
value).
<b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>RETRY</b>
The request was not completed.
The lookup request could not be completed.
<b>MASTER</b> <b>INTERFACE</b>
<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 <b>$max</b><i>_</i><b>use</b> clients or after <b>$max</b><i>_</i><b>idle</b> seconds of idle
time.
not exceeded. Each proxymap server stops accepting new
connections after serving <b>$max</b><i>_</i><b>use</b> clients or terminates
after <b>$max</b><i>_</i><b>idle</b> seconds of idle time.
<b>SECURITY</b>
The proxymap server is not security-sensitive. It opens
only tables that are approved via the <b>proxymap</b><i>_</i><b>filter</b> con-
figuration parameter, does not talk to users, and can run
at fixed low privilege, chrooted or not.
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-
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
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>proxymap</b><i>_</i><b>filter</b>
A list of zero or more parameter values that may
contain Postfix lookup table references. Only table
references that begin with <b>proxy:</b> are approved for
access via the proxymap server.
<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

View File

@ -37,14 +37,6 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
The envelope recipient address that is
passed on to <i>nexthop</i>.
<b>trivial-rewrite</b> servers run under control by the Postfix
master server. Each server can handle multiple simultane-
ous connections. When all servers are busy while a client
connects, a new server process is created, provided that
the trivial-rewrite server process limit is not exceeded.
Each server terminates after serving <b>$max</b><i>_</i><b>use</b> clients or
after <b>$max</b><i>_</i><b>idle</b> seconds of idle time.
<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>
@ -83,14 +75,24 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<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 stops accepting
new connections after serving <b>$max</b><i>_</i><b>use</b> clients or termi-
nates 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
None. The command does not interact with the outside
world.
<b>SECURITY</b>
The <b>trivial-rewrite</b> daemon is not security sensitive. By
default, this daemon does not talk to remote or local
users. It can run at a fixed low privilege in a chrooted
The <b>trivial-rewrite</b> daemon is not security sensitive. By
default, this daemon does not talk to remote or local
users. It can run at a fixed low privilege in a chrooted
environment.
<b>DIAGNOSTICS</b>
@ -98,21 +100,21 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b>BUGS</b>
<b>CONFIGURATION</b> <b>PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant
to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values. Use the <b>postfix</b> <b>reload</b>
The following <b>main.cf</b> parameters are especially relevant
to this program. See the Postfix <b>main.cf</b> file for syntax
details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change.
<b>Miscellaneous</b>
<b>empty</b><i>_</i><b>address</b><i>_</i><b>recipient</b>
The recipient that is substituted for the null
The recipient that is substituted for the null
address.
<b>inet</b><i>_</i><b>interfaces</b>
The network interfaces that this mail system
receives mail on. This information is used to
determine if <i>user</i>@[<i>net.work.addr.ess</i>] is local or
remote. Mail for local users is given to the
The network interfaces that this mail system
receives mail on. This information is used to
determine if <i>user</i>@[<i>net.work.addr.ess</i>] is local or
remote. Mail for local users is given to the
<b>$local</b><i>_</i><b>transport</b>.
<b>mydestination</b>
@ -121,7 +123,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>
List of simulated virtual domains (domains with all
recipients aliased to some other local or remote
recipients aliased to some other local or remote
domain).
<b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>
@ -134,10 +136,10 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b>resolve</b><i>_</i><b>unquoted</b><i>_</i><b>address</b>
When resolving an address, do not quote the address
localpart as per <a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a>, so that additional <b>@</b>, <b>%</b>
or <b>!</b> characters remain visible. This is techni-
localpart as per <a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a>, so that additional <b>@</b>, <b>%</b>
or <b>!</b> characters remain visible. This is techni-
cally incorrect, but allows us to stop relay
attacks when forwarding mail to a Sendmail primary
attacks when forwarding mail to a Sendmail primary
MX host.
<b>relocated</b><i>_</i><b>maps</b>
@ -163,50 +165,50 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<b>Routing</b>
<b>local</b><i>_</i><b>transport</b>
Where to deliver mail for destinations that match
<b>$mydestination</b> or <b>$inet</b><i>_</i><b>interfaces</b>. The default
Where to deliver mail for destinations that match
<b>$mydestination</b> or <b>$inet</b><i>_</i><b>interfaces</b>. The default
transport is <b>local:$myhostname</b>.
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>virtual</b><i>_</i><b>transport</b>
Where to deliver mail for non-local domains that
match <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>. The default trans-
port is <b>virtual</b>.
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>virtual</b><i>_</i><b>transport</b>
Where to deliver mail for non-local domains that
match <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>. The default trans-
port is <b>virtual</b>.
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>relay</b><i>_</i><b>transport</b>
Where to deliver mail for non-local domains that
match <b>$relay</b><i>_</i><b>domains</b>. The default transport is
Where to deliver mail for non-local domains that
match <b>$relay</b><i>_</i><b>domains</b>. The default transport is
<b>relay</b> (which normally is a clone of the <b>smtp</b> trans-
port).
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>default</b><i>_</i><b>transport</b>
Where to deliver all other non-local mail. The
Where to deliver all other non-local mail. The
default transport is <b>smtp</b>.
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
List of Postfix features that use <i>domain.tld</i> pat-
terns to match <i>sub.domain.tld</i> (as opposed to
List of Postfix features that use <i>domain.tld</i> pat-
terns to match <i>sub.domain.tld</i> (as opposed to
requiring <i>.domain.tld</i> patterns).
<b>relayhost</b>
The default host to send non-local mail to when no
host is specified with <b>$relay</b><i>_</i><b>transport</b> or
<b>$default</b><i>_</i><b>transport</b>, and when the recipient address
The default host to send non-local mail to when no
host is specified with <b>$relay</b><i>_</i><b>transport</b> or
<b>$default</b><i>_</i><b>transport</b>, and when the recipient address
does not match the optional the <a href="transport.5.html"><b>transport</b>(5)</a> table.
<b>transport</b><i>_</i><b>maps</b>
List of tables with <i>recipient</i> or <i>domain</i> to (<i>trans-</i>
List of tables with <i>recipient</i> or <i>domain</i> to (<i>trans-</i>
<i>port,</i> <i>nexthop</i>) mappings.
<b>SEE</b> <b>ALSO</b>
@ -216,7 +218,7 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
<a href="relocated.5.html">relocated(5)</a> format of the "user has moved" table
<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>

View File

@ -18,35 +18,35 @@ 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.
The solution is to specify:
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, to avoid
problems due to "too many connections" to, e.g., mysql servers,
specify:
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
.SH PROXYMAP SERVICES
.na
.nf
.ad
.fi
.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 and the
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 and
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.
@ -56,14 +56,17 @@ because tables are meant to be shared among client processes.
The request completion status code is one of:
.IP \fBPROXY_STAT_OK\fR
The requested table or lookup key was found.
.IP \fBPROXY_STAT_FAIL\fR
The requested table or lookup key does not exist.
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 request was not completed.
.SH MASTER INTERFACE
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
@ -73,17 +76,21 @@ 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 \fB$max_use\fR clients
or after \fB$max_idle\fR seconds of idle time.
Each proxymap server stops accepting new connections after serving
\fB$max_use\fR clients or terminates after \fB$max_idle\fR seconds
of idle time.
.SH SECURITY
.na
.nf
.ad
.fi
The proxymap server is not security-sensitive. It opens only
tables that are approved via the \fBproxymap_filter\fR
configuration parameter, does not talk to users, and
can run at fixed low privilege, chrooted or not.
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
@ -102,11 +109,11 @@ lookups.
The following main.cf parameters are especially relevant
to this program. Use the \fBpostfix reload\fR command
after a configuration change.
.IP \fBproxymap_filter\fR
.IP \fBproxy_read_maps\fR
A list of zero or more parameter values that may contain
Postfix lookup table references. Only table references that
begin with \fBproxy:\fR are approved for access via the
proxymap server.
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

View File

@ -32,14 +32,6 @@ The host to send to and optional delivery method information.
.IP \fIrecipient\fR
The envelope recipient address that is passed on to \fInexthop\fR.
.RE
.PP
\fBtrivial-rewrite\fR 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, a new server
process is created, provided that the trivial-rewrite server
process limit is not exceeded.
Each server terminates after serving \fB$max_use\fR clients
or after \fB$max_idle\fR seconds of idle time.
.SH DEFAULT DELIVERY METHODS
.na
.nf
@ -73,6 +65,19 @@ The transport and optional nexthop are specified with
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 stops accepting new connections after
serving \fB$max_use\fR clients or terminates after \fB$max_idle\fR
seconds of idle time.
.SH STANDARDS
.na
.nf

View File

@ -44,7 +44,7 @@ exec sed '
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="verify.8.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>/

View File

@ -48,7 +48,7 @@
/* .IP timeout
/* Idle time after which the client disconnects.
/* .IP ttl
/* Time to live after which the client disconnects.
/* Upper bound on the time that a connection is allowed to persist.
/* DIAGNOSTICS
/* Warnings: communication failure. Fatal error: mail system is down,
/* out of memory.
@ -121,10 +121,16 @@ static void clnt_stream_ttl_event(int event, char *context)
{
/*
* XXX This function is needed only because the event_request_timer()
* function cannot distinguish requests with the same callback routine.
* The fix is obvious: specify a request ID along with the callback
* routine, but there is too much code that would have to be changed.
* XXX This function is needed only because event_request_timer() cannot
* distinguish between requests that specify the same call-back routine
* and call-back context. The fix is obvious: specify a request ID along
* with the call-back routine, but there is too much code that would have
* to be changed.
*
* XXX Should we be concerned that an overly agressive optimizer will
* eliminate this function and replace calls to clnt_stream_ttl_event()
* by direct calls to clnt_stream_event()? It should not, because there
* exists code that takes the address of both functions.
*/
clnt_stream_event(event, context);
}

View File

@ -17,7 +17,8 @@
/* 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.
/* closed after $ipc_idle seconds of idle time, or after $ipc_ttl
/* seconds of activity.
/* 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
@ -27,7 +28,7 @@
/* clnt_stream(3) client endpoint connection management
/* DIAGNOSTICS
/* Fatal errors: out of memory, unimplemented operation,
/* bad request parameter.
/* bad request parameter, map not approved for proxy access.
/* LICENSE
/* .ad
/* .fi
@ -78,8 +79,7 @@ typedef struct {
#define VSTREQ(v,s) (strcmp(STR(v),s) == 0)
/*
* All proxied maps within the same process share the same query/reply
* socket.
* All proxied maps within a process share the same query/reply socket.
*/
static CLNT_STREAM *proxy_stream;
@ -115,25 +115,31 @@ static const char *dict_proxy_lookup(DICT *dict, const char *key)
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", VSTREAM_PATH(stream), myname);
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));
if (status == PROXY_STAT_OK) {
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));
} else if (status == PROXY_STAT_FAIL) {
case PROXY_STAT_NOKEY:
return (0);
} else if (status == PROXY_STAT_RETRY) {
case PROXY_STAT_RETRY:
dict_errno = DICT_ERR_RETRY;
return (0);
} else if (status == PROXY_STAT_BAD) {
msg_fatal("%s: %s lookup %s failed: bad request",
myname, dict->name, key);
} else {
msg_warn("%s: %s lookup %s failed with unknown status %d",
myname, dict->name, key, status);
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);
@ -166,10 +172,10 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
/*
* 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);
if (dict_flags & DICT_FLAG_NO_PROXY)
msg_fatal("%s: proxy map is not allowed for this map type", map);
/*
* Local initialization.
@ -201,7 +207,9 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
}
/*
* Establish initial contact and finalize the flags.
* Establish initial contact and get the map type specific flags.
*
* XXX Should retrieve flags from local instance.
*/
for (;;) {
stream = clnt_stream_access(proxy_stream);
@ -217,21 +225,26 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags)
ATTR_TYPE_END) != 2) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: service %s: %m", VSTREAM_PATH(stream), myname);
} else if (status == PROXY_STAT_OK) {
} 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);
dict_proxy->dict.flags = dict_proxy->in_flags | server_flags;
break;
} else if (status == PROXY_STAT_BAD) {
msg_fatal("%s: %s connection request failed: bad request",
myname, dict_proxy->dict.name);
} else {
msg_warn("%s: %s connection request failed with status %d",
myname, dict_proxy->dict.name, status);
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 */
}
return (DICT_DEBUG (&dict_proxy->dict));
}

View File

@ -29,10 +29,11 @@ extern DICT *dict_proxy_open(const char *, int, int);
#define PROXY_REQ_OPEN "open"
#define PROXY_REQ_LOOKUP "lookup"
#define PROXY_STAT_OK 0
#define PROXY_STAT_FAIL 1
#define PROXY_STAT_BAD 2
#define PROXY_STAT_RETRY 3
#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

View File

@ -1332,8 +1332,8 @@ extern int var_local_rcpt_code;
/*
* List of pre-approved maps that are OK to open with the proxymap service.
*/
#define VAR_PROXYMAP_FILTER "proxymap_filter"
#define DEF_PROXYMAP_FILTER "$" VAR_LOCAL_RCPT_MAPS \
#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 \
@ -1346,7 +1346,7 @@ extern int var_local_rcpt_code;
" $" VAR_RCPT_CANON_MAPS \
" $" VAR_RELOCATED_MAPS \
" $" VAR_TRANSPORT_MAPS
extern char *var_proxymap_filter;
extern char *var_proxy_read_maps;
/*
* Other.

View File

@ -20,7 +20,7 @@
* 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 "20030103"
#define MAIL_RELEASE_DATE "20030104"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.0-" MAIL_RELEASE_DATE

View File

@ -184,22 +184,20 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, RESOLVE_ADDR,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
ATTR_TYPE_END)
|| vstream_fflush(stream)) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad write: %m", myname);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_END) != 0
|| attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_TRANSPORT, reply->transport,
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags,
ATTR_TYPE_END) != 4) {
ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, reply->nexthop,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, reply->recipient,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &reply->flags,
ATTR_TYPE_END) != 4) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad read: %m", myname);
msg_warn("problem talking to service %s: %m",
var_rewrite_service);
} else {
if (msg_verbose)
msg_info("%s: `%s' -> t=`%s' h=`%s' r=`%s'",
@ -212,7 +210,7 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
else
break;
}
sleep(10); /* XXX make configurable */
sleep(1); /* XXX make configurable */
clnt_stream_recover(rewrite_clnt_stream);
}

View File

@ -125,26 +125,25 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, REWRITE_ADDR,
ATTR_TYPE_STR, MAIL_ATTR_RULE, rule,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
ATTR_TYPE_END),
vstream_fflush(stream)) {
ATTR_TYPE_END) != 0
|| attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
ATTR_TYPE_END) != 1) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad write: %m", myname);
} else if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, result,
ATTR_TYPE_END) != 1) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("%s: bad read: %m", myname);
msg_warn("problem talking to service %s: %m",
var_rewrite_service);
} else {
if (msg_verbose)
msg_info("rewrite_clnt: %s: %s -> %s",
rule, addr, vstring_str(result));
break;
}
sleep(10); /* XXX make configurable */
sleep(1); /* XXX make configurable */
clnt_stream_recover(rewrite_clnt_stream);
}

View File

@ -117,24 +117,19 @@ int verify_clnt_query(const char *addr, int *addr_status, VSTRING *why)
*/
for (;;) {
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_QUERY,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT)) {
msg_warn("service %s: bad write: %m", var_verify_service);
sleep(10); /* XXX make configurable */
}
} else if (attr_scan(stream, ATTR_FLAG_MISSING,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status,
ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
ATTR_TYPE_END) != 3) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT)) {
msg_warn("service %s: bad read: %m", var_verify_service);
sleep(10); /* XXX make configurable */
}
|| attr_scan(stream, ATTR_FLAG_MISSING,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status,
ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, why,
ATTR_TYPE_END) != 3) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
var_verify_service);
} else {
break;
}
@ -181,25 +176,19 @@ int verify_clnt_vupdate(const char *addr, int addr_status,
vstring_vsprintf(text, format, ap);
for (;;) {
stream = clnt_stream_access(vrfy_clnt);
errno = 0;
if (attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_STR, MAIL_ATTR_REQ, VRFY_REQ_UPDATE,
ATTR_TYPE_STR, MAIL_ATTR_ADDR, addr,
ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, addr_status,
ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(text),
ATTR_TYPE_END) != 0
|| vstream_fflush(stream)) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT)) {
msg_warn("service %s: bad write: %m", var_verify_service);
msg_warn("service %s: bad write: %m", var_verify_service);
sleep(10); /* XXX make configurable */
}
} else if (attr_scan(stream, ATTR_FLAG_MISSING,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status,
ATTR_TYPE_END) != 1) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT)) {
msg_warn("service %s: bad read: %m", var_verify_service);
sleep(10); /* XXX make configurable */
}
|| attr_scan(stream, ATTR_FLAG_MISSING,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &request_status,
ATTR_TYPE_END) != 1) {
if (msg_verbose || (errno != EPIPE && errno != ENOENT))
msg_warn("problem talking to service %s: %m",
var_verify_service);
} else {
break;
}

View File

@ -28,11 +28,7 @@
/* 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, and
/* implicitly sets the DICT_FLAG_NO_PROXY flag in order to disable
/* lookup of sensitive information via an untrusted process.
/* 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

View File

@ -20,8 +20,7 @@
* External interface.
*/
#define virtual8_maps_create(title, map_names, flags) \
maps_create((title), (map_names), \
(flags) | DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY)
maps_create((title), (map_names), (flags))
extern const char *virtual8_maps_find(MAPS *, const char *);
#define virtual8_maps_free(maps) maps_free((maps))

View File

@ -696,10 +696,8 @@ static void pre_init(char *unused_name, char **unused_argv)
VAR_MAILBOX_LIMIT, VAR_MESSAGE_LIMIT);
set_file_limit(var_mailbox_limit);
}
#define INSECURE_DICT_FLAGS (DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY)
alias_maps = maps_create("aliases", var_alias_maps,
DICT_FLAG_LOCK | INSECURE_DICT_FLAGS);
DICT_FLAG_LOCK | DICT_FLAG_PARANOID);
}
/* main - pass control to the single-threaded skeleton */

View File

@ -12,33 +12,35 @@
/* .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.
/* The solution is to specify:
/* 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, to avoid
/* problems due to "too many connections" to, e.g., mysql servers,
/* specify:
/* 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
/* PROXYMAP SERVICES
/* .ad
/* .fi
/* .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 and the
/* 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 and
/* 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.
@ -48,30 +50,37 @@
/*
/* The request completion status code is one of:
/* .IP \fBPROXY_STAT_OK\fR
/* The requested table or lookup key was found.
/* .IP \fBPROXY_STAT_FAIL\fR
/* The requested table or lookup key does not exist.
/* 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 request was not completed.
/* MASTER INTERFACE
/* 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
/* creates a new proxymap server process, provided that the proxymap
/* server process limit is not exceeded.
/* Each proxymap server terminates after serving \fB$max_use\fR clients
/* or after \fB$max_idle\fR seconds of idle time.
/* Each proxymap server stops accepting new connections after serving
/* \fB$max_use\fR clients or terminates after \fB$max_idle\fR seconds
/* of idle time.
/* SECURITY
/* .ad
/* .fi
/* The proxymap server is not security-sensitive. It opens only
/* tables that are approved via the \fBproxymap_filter\fR
/* configuration parameter, does not talk to users, and
/* can run at fixed low privilege, chrooted or not.
/* 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
@ -84,11 +93,11 @@
/* The following main.cf parameters are especially relevant
/* to this program. Use the \fBpostfix reload\fR command
/* after a configuration change.
/* .IP \fBproxymap_filter\fR
/* .IP \fBproxy_read_maps\fR
/* A list of zero or more parameter values that may contain
/* Postfix lookup table references. Only table references that
/* begin with \fBproxy:\fR are approved for access via the
/* proxymap server.
/* 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
@ -148,20 +157,20 @@ char *var_send_canon_maps;
char *var_rcpt_canon_maps;
char *var_relocatedmaps;
char *var_transport_maps;
char *var_proxymap_filter;
char *var_proxy_read_maps;
/*
* The pre-approved, pre-parsed list of maps.
*/
static HTABLE *proxymap_filter;
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;
static VSTRING *map_type_name;
static VSTRING *key;
/*
* Silly little macros.
@ -171,13 +180,13 @@ static VSTRING *key;
/* proxy_map_find - look up or open table */
static DICT *proxy_map_find(const char *map_type_name, int dict_flags)
static DICT *proxy_map_find(const char *map_type_name, int request_flags)
{
DICT *dict;
#define PROXY_COLON DICT_TYPE_PROXY ":"
#define PROXY_COLON_LEN (sizeof(PROXY_COLON) - 1)
#define OPEN_FLAGS O_RDONLY
#define READ_OPEN_FLAGS O_RDONLY
/*
* Canonicalize the map name. If the map is not on the approved list,
@ -185,8 +194,10 @@ static DICT *proxy_map_find(const char *map_type_name, int dict_flags)
*/
while (strncmp(map_type_name, PROXY_COLON, PROXY_COLON_LEN) == 0)
map_type_name += PROXY_COLON_LEN;
if (htable_locate(proxymap_filter, map_type_name) == 0) {
msg_warn("request for unapproved map: %s", map_type_name);
if (htable_locate(proxy_read_maps, map_type_name) == 0) {
msg_warn("request for unapproved table: \"%s\"", map_type_name);
msg_warn("to approve a table for %s access, specify it in %s with %s",
MAIL_SERVICE_PROXYMAP, MAIN_CONF_FILE, VAR_PROXY_READ_MAPS);
return (0);
}
@ -194,9 +205,9 @@ static DICT *proxy_map_find(const char *map_type_name, int dict_flags)
* Open one instance of a map for each combination of name+flags.
*/
vstring_sprintf(map_type_name_flags, "%s:%o",
map_type_name, dict_flags);
map_type_name, request_flags);
if ((dict = dict_handle(STR(map_type_name_flags))) == 0)
dict = dict_open(map_type_name, OPEN_FLAGS, dict_flags);
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);
@ -207,35 +218,40 @@ static DICT *proxy_map_find(const char *map_type_name, int dict_flags)
static void proxymap_lookup_service(VSTREAM *client_stream)
{
int status = PROXY_STAT_BAD;
int request_flags;
DICT *dict;
const char *value = "";
int dict_flags;
const char *reply_value;
int reply_status;
/*
* Process the request.
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_TABLE, map_type_name,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &dict_flags,
ATTR_TYPE_STR, MAIL_ATTR_KEY, key,
ATTR_TYPE_END) == 3
&& (dict = proxy_map_find(STR(map_type_name), dict_flags)) != 0) {
if ((value = dict_get(dict, STR(key))) != 0) {
status = PROXY_STAT_OK;
} else if (dict_errno == 0) {
status = PROXY_STAT_FAIL;
value = "";
} else {
status = PROXY_STAT_RETRY;
value = "";
}
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)) == 0) {
reply_status = PROXY_STAT_DENY;
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, status,
ATTR_TYPE_STR, MAIL_ATTR_VALUE, value,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status,
ATTR_TYPE_STR, MAIL_ATTR_VALUE, reply_value,
ATTR_TYPE_END);
}
@ -243,27 +259,34 @@ static void proxymap_lookup_service(VSTREAM *client_stream)
static void proxymap_open_service(VSTREAM *client_stream)
{
int dict_flags;
int request_flags;
DICT *dict;
int status = PROXY_STAT_BAD;
int flags = 0;
int reply_status;
int reply_flags;
/*
* Process the request.
*/
if (attr_scan(client_stream, ATTR_FLAG_STRICT,
ATTR_TYPE_STR, MAIL_ATTR_TABLE, map_type_name,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &dict_flags,
ATTR_TYPE_END) == 2
&& (dict = proxy_map_find(STR(map_type_name), dict_flags)) != 0) {
status = PROXY_STAT_OK;
flags = dict->flags;
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)) == 0) {
reply_status = PROXY_STAT_DENY;
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, status,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, reply_status,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, reply_flags,
ATTR_TYPE_END);
}
@ -311,28 +334,41 @@ static void post_jail_init(char *unused_name, char **unused_argv)
char *bp;
char *type_name;
/*
* Pre-allocate buffers.
*/
request = vstring_alloc(10);
map_type_name = vstring_alloc(10);
request_map = vstring_alloc(10);
request_key = vstring_alloc(10);
map_type_name_flags = vstring_alloc(10);
key = vstring_alloc(10);
/*
* Prepare the pre-approved list of proxied tables.
*/
saved_filter = bp = mystrdup(var_proxymap_filter);
proxymap_filter = htable_create(13);
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 (htable_find(proxymap_filter, type_name) == 0)
(void) htable_enter(proxymap_filter, type_name, (char *) 0);
if (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)
@ -350,12 +386,13 @@ int main(int argc, char **argv)
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_PROXYMAP_FILTER, DEF_PROXYMAP_FILTER, &var_proxymap_filter, 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);
}

View File

@ -26,14 +26,6 @@
/* .IP \fIrecipient\fR
/* The envelope recipient address that is passed on to \fInexthop\fR.
/* .RE
/* .PP
/* \fBtrivial-rewrite\fR 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, a new server
/* process is created, provided that the trivial-rewrite server
/* process limit is not exceeded.
/* Each server terminates after serving \fB$max_use\fR clients
/* or after \fB$max_idle\fR seconds of idle time.
/* DEFAULT DELIVERY METHODS
/* .ad
/* .fi
@ -65,6 +57,17 @@
/* 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 stops accepting new connections after
/* serving \fB$max_use\fR clients or terminates after \fB$max_idle\fR
/* seconds of idle time.
/* STANDARDS
/* .ad
/* .fi

View File

@ -58,10 +58,11 @@ extern DICT *dict_debug(DICT *);
#define DICT_FLAG_SYNC_UPDATE (1<<8) /* if file, sync updates */
#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;

View File

@ -84,6 +84,11 @@
/* .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.
/*

View File

@ -640,8 +640,11 @@ static int vstream_buf_get_ready(VBUF *bp)
* 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,
@ -724,6 +727,8 @@ static int vstream_buf_put_ready(VBUF *bp)
*/
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);

View File

@ -413,15 +413,15 @@ static void post_init(char *unused_name, char **unused_argv)
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);
}