From: Wietse Venema Date: Fri, 3 Jan 2003 05:00:00 +0000 (-0500) Subject: postfix-2.0.0-20030103 X-Git-Tag: v2.1-RC1-20040331~89 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55978ec179edee3c412c4043d2969eaa03d4d094;p=thirdparty%2Fpostfix.git postfix-2.0.0-20030103 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 16ca497d1..132e9b83f 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -46,6 +46,7 @@ -TDICT_PCRE_PRESCAN_CONTEXT -TDICT_PCRE_REGEXP -TDICT_PCRE_RULE +-TDICT_PROXY -TDICT_REGEXP -TDICT_REGEXP_EXPAND_CONTEXT -TDICT_REGEXP_IF_RULE diff --git a/postfix/HISTORY b/postfix/HISTORY index f29e2f7e2..9f25df299 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7628,6 +7628,27 @@ Apologies for any names omitted. advanced content filtering example. Files: FILTER_README, RELEASE_NOTES-2.0. +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. + + Feature: proxymap server for Postfix table lookups. This + helps to consolidate the number of open lookup tables (such + as MYSQL or LDAP), or to overcome chroot restrictions + (example: specify proxy:unix:passwd.byname to avoid the + need for a copy of the UNIX passwd file in chroot jails). + Files: global/dict_proxy.[hc], proxymap/proxymap.c + + Cleanup: multiservers such as trivial-rewrite and the new + proxymap server now enforce the max_use total client number + limit more agressively, by not accepting new connections + after the limit is reached. Based on a patch by Victor + Duchovni, Morgan Stanley. File: master/multi_server.c. + Open problems: Med: do not postpone rejected "MAIL FROM" size information, diff --git a/postfix/Makefile.in b/postfix/Makefile.in index 882c8206f..62fb6d362 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -7,7 +7,7 @@ DIRS = src/util src/global src/dns src/master src/postfix src/smtpstone \ 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/verify \ - src/virtual + src/virtual src/proxymap MANDIRS = proto man html default: update diff --git a/postfix/conf/post-install b/postfix/conf/post-install index 9b176f7f8..d13c8e079 100644 --- a/postfix/conf/post-install +++ b/postfix/conf/post-install @@ -567,6 +567,15 @@ EOF $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 <$@ +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 >$@ diff --git a/postfix/html/backstage.html b/postfix/html/backstage.html index 99ab2a1bd..fc98461bf 100644 --- a/postfix/html/backstage.html +++ b/postfix/html/backstage.html @@ -73,6 +73,14 @@ UCE restrictions.

+

  • The proxymap 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. + +

    +

  • The spawn 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, diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 0367e4f51..b13c0357d 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -54,73 +54,81 @@ POSTCONF(1) POSTCONF(1) were left behind after abnormal termination. -m List the names of all supported lookup table types. + Postfix lookup tables are specified as type:name, + where type is one of the types listed below. The + table name syntax depends on the lookup table type. - btree A sorted, balanced tree structure. This is - available only on systems with support for + btree A sorted, balanced tree structure. This is + available only on systems with support for Berkeley DB databases. dbm 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. environ 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. hash 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. ldap (read-only) - Perform lookups using the LDAP protocol. + Perform lookups using the LDAP protocol. This is described in an LDAP_README file. mysql (read-only) - Perform lookups using the MYSQL protocol. + Perform lookups using the MYSQL protocol. This is described in a MYSQL_README file. pcre (read-only) A lookup table based on Perl Compatible Reg- - ular Expressions. The file format is + ular Expressions. The file format is described in pcre_table(5). + proxy (read-only) + A lookup table that is implemented via the + Postfix proxymap(8) service. The table name + syntax is type:name. + regexp (read-only) A lookup table based on regular expressions. - The file format is described in reg- + The file format is described in reg- exp_table(5). static (read-only) - A table that always returns its name as - lookup result. For example, static:foobar - always returns the string foobar as lookup + A table that always returns its name as + lookup result. For example, static:foobar + always returns the string foobar as lookup result. unix (read-only) - A limited way to query the UNIX authentica- + A limited way to query the UNIX authentica- tion database. The following tables are implemented: unix:passwd.byname - The table is the UNIX password - 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. unix:group.byname - 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. -n Print non-default parameter settings only. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS @@ -131,7 +139,7 @@ POSTCONF(1) POSTCONF(1) Directory with Postfix configuration files. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/proxymap.8.html b/postfix/html/proxymap.8.html new file mode 100644 index 000000000..bc96ab220 --- /dev/null +++ b/postfix/html/proxymap.8.html @@ -0,0 +1,115 @@ +
    +PROXYMAP(8)                                           PROXYMAP(8)
    +
    +NAME
    +       proxymap - Postfix lookup table proxy server
    +
    +SYNOPSIS
    +       proxymap [generic Postfix daemon options]
    +
    +DESCRIPTION
    +       The  proxymap  server provides read-only table lookup ser-
    +       vice to Postfix client processes. The purpose of the  ser-
    +       vice is:
    +
    +       o      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:
    +
    +              local_recipient_maps =
    +                  proxy:unix:passwd.byname $alias_maps
    +
    +       o      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:
    +
    +              virtual_alias_maps =
    +                  proxy:mysql:/etc/postfix/virtual.cf
    +
    +PROXYMAP SERVICES
    +       The proxymap server implements the following requests:
    +
    +       PROXY_REQ_OPEN maptype:mapname flags
    +              Open  the table with type maptype and name mapname,
    +              as controlled by flags.  The reply is  the  request
    +              completion  status  code and the map type dependent
    +              flags.
    +
    +       PROXY_REQ_LOOKUP maptype:mapname flags key
    +              Look up the data stored under  the  requested  key.
    +              The reply is the request completion status code and
    +              the lookup result value.  The  maptype:mapname  and
    +              flags  are  the  same  as  with  the PROXY_REQ_OPEN
    +              request.
    +
    +       There is no close command. This does not seem to be useful
    +       because  tables  are  meant to be shared among client pro-
    +       cesses.
    +
    +       The request completion status code is one of:
    +
    +       PROXY_STAT_OK
    +              The requested table or lookup key was found.
    +
    +       PROXY_STAT_FAIL
    +              The requested table or lookup key does not exist.
    +
    +       PROXY_STAT_BAD
    +              The request was  rejected  (bad  request  parameter
    +              value).
    +
    +       PROXY_STAT_RETRY
    +              The request was not completed.
    +
    +MASTER INTERFACE
    +       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  $max_use  clients  or after $max_idle seconds of idle
    +       time.
    +
    +SECURITY
    +       The proxymap server is not  security-sensitive.  It  opens
    +       only tables that are approved via the proxymap_filter con-
    +       figuration parameter, does not talk to users, and can  run
    +       at fixed low privilege, chrooted or not.
    +
    +DIAGNOSTICS
    +       Problems and transactions are logged to syslogd(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
    +       The  following  main.cf parameters are especially relevant
    +       to this program. Use the postfix reload  command  after  a
    +       configuration change.
    +
    +       proxymap_filter
    +              A  list  of  zero or more parameter values that may
    +              contain Postfix lookup table references. Only table
    +              references  that begin with proxy: are approved for
    +              access via the proxymap server.
    +
    +SEE ALSO
    +       dict_proxy(3) proxy map client
    +
    +LICENSE
    +       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
    +
    +                                                      PROXYMAP(8)
    +
    diff --git a/postfix/html/trivial-rewrite.8.html b/postfix/html/trivial-rewrite.8.html index fcb9f67ea..97ce29da9 100644 --- a/postfix/html/trivial-rewrite.8.html +++ b/postfix/html/trivial-rewrite.8.html @@ -37,6 +37,14 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8) The envelope recipient address that is passed on to nexthop. + trivial-rewrite 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 $max_use clients or + after $max_idle seconds of idle time. + DEFAULT DELIVERY METHODS By default, Postfix uses one of the following delivery methods. This may be overruled with the optional trans- diff --git a/postfix/html/verify.8.html b/postfix/html/verify.8.html index f86eeb0db..b0f67a1f2 100644 --- a/postfix/html/verify.8.html +++ b/postfix/html/verify.8.html @@ -39,14 +39,14 @@ VERIFY(8) VERIFY(8) The server reply status is one of: - VRFYSTAT_OK + VRFY_STAT_OK The request completed normally. - VRFYSTAT_BAD + VRFY_STAT_BAD The server rejected the request (bad request name, bad request parameter value). - VRFYSTAT_FAIL + VRFY_STAT_FAIL The request failed. The recipient status is one of: diff --git a/postfix/html/virtual.8.html b/postfix/html/virtual.8.html index 925526715..e350dcb3f 100644 --- a/postfix/html/virtual.8.html +++ b/postfix/html/virtual.8.html @@ -141,37 +141,43 @@ VIRTUAL(8) VIRTUAL(8) 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. + virtual_mailbox_domains - 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 mydestination configuration parameter. virtual_minimum_uid - Specifies a minimum uid that will be accepted as a - return from a virtual_owner_maps or vir- - tual_uid_maps 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 virtual_owner_maps or vir- + tual_uid_maps lookup. Returned values less than + this will be rejected, and the message will be deferred. virtual_uid_maps 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 (user+foo@domain.tld) is ignored. - In a lookup table, specify a left-hand side of - @domain.tld to match any user in the specified - domain that does not have a specific + In a lookup table, specify a left-hand side of + @domain.tld to match any user in the specified + domain that does not have a specific user@domain.tld 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. + virtual_gid_maps Recipients are looked up in these maps to determine the group ID to be used when writing to the target @@ -190,63 +196,66 @@ VIRTUAL(8) VIRTUAL(8) 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. + Locking controls virtual_mailbox_lock - How to lock UNIX-style mailboxes: one or more of - flock, fcntl or dotlock. The dotlock method - requires that the recipient UID or GID has write + How to lock UNIX-style mailboxes: one or more of + flock, fcntl or dotlock. The dotlock method + requires that the recipient UID or GID has write access to the parent directory of the mailbox file. - This setting is ignored with maildir style deliv- + This setting is ignored with maildir style deliv- ery, because such deliveries are safe without explicit locks. - Use the command postconf -l to find out what lock- + Use the command postconf -l to find out what lock- ing methods are available on your system. deliver_lock_attempts - 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. deliver_lock_delay 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. stale_lock_time - 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). Resource controls virtual_destination_concurrency_limit Limit the number of parallel deliveries to the same domain via the virtual delivery agent. The default limit is taken from the default_destination_concur- - rency_limit parameter. The limit is enforced by + rency_limit parameter. The limit is enforced by the Postfix queue manager. virtual_destination_recipient_limit Limit the number of recipients per message delivery - via the virtual delivery agent. The default limit - is taken from the default_destination_recipi- - ent_limit parameter. The limit is enforced by the + via the virtual delivery agent. The default limit + is taken from the default_destination_recipi- + ent_limit parameter. The limit is enforced by the Postfix queue manager. virtual_mailbox_limit - 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. HISTORY - 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 Delivered-To: header appears in the qmail system by + The Delivered-To: header appears in the qmail system by Daniel Bernstein. - The maildir structure appears in the qmail system by + The maildir structure appears in the qmail system by Daniel Bernstein. SEE ALSO @@ -257,7 +266,7 @@ VIRTUAL(8) VIRTUAL(8) qmgr(8) queue manager LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/Makefile.in b/postfix/man/Makefile.in index 3a54be60c..91ede1d16 100644 --- a/postfix/man/Makefile.in +++ b/postfix/man/Makefile.in @@ -6,7 +6,7 @@ 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/verify.8 man8/trace.8 + man8/verify.8 man8/trace.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 \ @@ -65,6 +65,9 @@ man8/pickup.8: ../src/pickup/pickup.c 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 $? >$@ diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 74d20a49a..4a7fab8e3 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -53,7 +53,10 @@ The application is expected to remove its own lock file, as well as 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. @@ -79,6 +82,10 @@ in a MYSQL_README file. .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). diff --git a/postfix/man/man8/proxymap.8 b/postfix/man/man8/proxymap.8 new file mode 100644 index 000000000..533ef958d --- /dev/null +++ b/postfix/man/man8/proxymap.8 @@ -0,0 +1,126 @@ +.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. +The solution is to specify: +.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: +.sp +virtual_alias_maps = +.ti +4 +proxy:mysql:/etc/postfix/virtual.cf +.SH PROXYMAP SERVICES +.na +.nf +.ad +.fi +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 +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 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. This does not seem to be useful +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. +.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 +.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 \fB$max_use\fR clients +or 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. +.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 \fBproxymap_filter\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. +.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 diff --git a/postfix/man/man8/trivial-rewrite.8 b/postfix/man/man8/trivial-rewrite.8 index 4320f7f2d..bd56ad96f 100644 --- a/postfix/man/man8/trivial-rewrite.8 +++ b/postfix/man/man8/trivial-rewrite.8 @@ -32,6 +32,14 @@ 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 diff --git a/postfix/man/man8/verify.8 b/postfix/man/man8/verify.8 index 6eb33a196..2e6979947 100644 --- a/postfix/man/man8/verify.8 +++ b/postfix/man/man8/verify.8 @@ -40,12 +40,12 @@ If the status is unknown, a probe is sent and a default status is returned. .PP The server reply status is one of: -.IP \fBVRFYSTAT_OK\fR +.IP \fBVRFY_STAT_OK\fR The request completed normally. -.IP \fBVRFYSTAT_BAD\fR +.IP \fBVRFY_STAT_BAD\fR The server rejected the request (bad request name, bad request parameter value). -.IP \fBVRFYSTAT_FAIL\fR +.IP \fBVRFY_STAT_FAIL\fR The request failed. .PP The recipient status is one of: diff --git a/postfix/man/man8/virtual.8 b/postfix/man/man8/virtual.8 index f74a6d228..c7517bc24 100644 --- a/postfix/man/man8/virtual.8 +++ b/postfix/man/man8/virtual.8 @@ -157,6 +157,9 @@ to this path. 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 @@ -180,6 +183,9 @@ specific \fIuser@domain.tld\fR entry. 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. @@ -194,6 +200,9 @@ specific \fIuser@domain.tld\fR entry. 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 diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index ecbc01be9..be5d77bb4 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -44,9 +44,11 @@ exec sed ' s/[]*canonical[]*(5)/&<\/a>/ s/[]*etrn[]*(5)/&<\/a>/ s/[]*pcre[]*_[]*table[]*(5)/&<\/a>/ + s/[]*proxymap[]*(8)/&<\/a>/ s/[]*reg[-]*\n*[ ]*exp[]*_[]*table[]*(5)/&<\/a>/ s/[]*relocated[]*(5)/&<\/a>/ s/[]*trans[-]*\n*[ ]*port[]*(5)/&<\/a>/ + s/[]*verify[]*(8)/&<\/a>/ s/[]*virtual[]*(5)/&<\/a>/ s/[]*virtual[]*(8)/&<\/a>/ s/\(\)\([]*[a-z0-9-]*[-]*\)\(\n *\)\([]*[a-z0-9-]*[]*([0-9])\)\(<\/a>\)/\1\2\5\3\1\4\5/ diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 319924c46..c88e30bdf 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -21,7 +21,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.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 verify_clnt.c \ - trace.c log_adhoc.c verify.c + trace.c log_adhoc.c verify.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 \ @@ -44,7 +44,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.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 verify_clnt.o \ - trace.o log_adhoc.o verify.o + trace.o log_adhoc.o verify.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 \ @@ -63,7 +63,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.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 verify_clnt.h \ - trace.h log_adhoc.h verify.h + trace.h log_adhoc.h verify.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 \ @@ -514,6 +514,22 @@ deliver_request.o: ../../include/attr.h 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 @@ -743,6 +759,15 @@ mail_date.o: ../../include/msg.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 diff --git a/postfix/src/global/clnt_stream.c b/postfix/src/global/clnt_stream.c index 7b9cb3df4..7c182372a 100644 --- a/postfix/src/global/clnt_stream.c +++ b/postfix/src/global/clnt_stream.c @@ -6,10 +6,11 @@ /* SYNOPSIS /* #include /* -/* CLNT_STREAM *clnt_stream_create(class, service, timeout) +/* CLNT_STREAM *clnt_stream_create(class, service, timeout, ttl) /* const char *class; /* const char *service; /* int timeout; +/* int ttl; /* /* VSTREAM *clnt_stream_access(clnt_stream) /* CLNT_STREAM *clnt_stream; @@ -22,6 +23,7 @@ /* DESCRIPTION /* This module maintains local IPC client endpoints that automatically /* disconnect after a being idle for a configurable amount of time, +/* that disconnect after a configurable time to live, /* and that transparently handle most server-initiated disconnects. /* Server disconnect is detected by read-selecting the client endpoint. /* The code assumes that the server has disconnected when the endpoint @@ -36,6 +38,17 @@ /* that happened in the middle of an I/O operation. /* /* clnt_stream_free() destroys of the specified client endpoint. +/* +/* Arguments: +/* .IP class +/* The service class, private or public. +/* .IP service +/* The service endpoint name. The name is limited to local IPC +/* over sockets or equivalent. +/* .IP timeout +/* Idle time after which the client disconnects. +/* .IP ttl +/* Time to live after which the client disconnects. /* DIAGNOSTICS /* Warnings: communication failure. Fatal error: mail system is down, /* out of memory. @@ -79,6 +92,7 @@ struct CLNT_STREAM { VSTREAM *vstream; /* buffered I/O */ int timeout; /* time before client disconnect */ + int ttl; /* time before client disconnect */ char *class; /* server class */ char *service; /* server name */ }; @@ -101,6 +115,20 @@ static void clnt_stream_event(int unused_event, char *context) clnt_stream_close(clnt_stream); } +/* clnt_stream_ttl_event - server-initiated disconnect or client-side timeout */ + +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. + */ + clnt_stream_event(event, context); +} + /* clnt_stream_open - connect to service */ static void clnt_stream_open(CLNT_STREAM *clnt_stream) @@ -116,6 +144,10 @@ static void clnt_stream_open(CLNT_STREAM *clnt_stream) * Schedule a read event so that we can clean up when the remote side * disconnects, and schedule a timer event so that we can cleanup an idle * connection. Note that both events are handled by the same routine. + * + * Finally, schedule an event to force disconnection even when the + * connection is not idle. This is to prevent one client from clinging on + * to a server forever. */ clnt_stream->vstream = mail_connect_wait(clnt_stream->class, clnt_stream->service); @@ -124,6 +156,8 @@ static void clnt_stream_open(CLNT_STREAM *clnt_stream) (char *) clnt_stream); event_request_timer(clnt_stream_event, (char *) clnt_stream, clnt_stream->timeout); + event_request_timer(clnt_stream_ttl_event, (char *) clnt_stream, + clnt_stream->ttl); } /* clnt_stream_close - disconnect from service */ @@ -144,6 +178,7 @@ static void clnt_stream_close(CLNT_STREAM *clnt_stream) msg_info("%s stream disconnect", clnt_stream->service); event_disable_readwrite(vstream_fileno(clnt_stream->vstream)); event_cancel_timer(clnt_stream_event, (char *) clnt_stream); + event_cancel_timer(clnt_stream_ttl_event, (char *) clnt_stream); (void) vstream_fclose(clnt_stream->vstream); clnt_stream->vstream = 0; } @@ -167,6 +202,8 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream) /* * Open a stream or restart the idle timer. + * + * Important! Do not restart the TTL timer! */ if (clnt_stream->vstream == 0) { clnt_stream_open(clnt_stream); @@ -180,7 +217,7 @@ VSTREAM *clnt_stream_access(CLNT_STREAM *clnt_stream) /* clnt_stream_create - create client stream connection */ CLNT_STREAM *clnt_stream_create(const char *class, const char *service, - int timeout) + int timeout, int ttl) { CLNT_STREAM *clnt_stream; @@ -190,6 +227,7 @@ CLNT_STREAM *clnt_stream_create(const char *class, const char *service, clnt_stream = (CLNT_STREAM *) mymalloc(sizeof(*clnt_stream)); clnt_stream->vstream = 0; clnt_stream->timeout = timeout; + clnt_stream->ttl = ttl; clnt_stream->class = mystrdup(class); clnt_stream->service = mystrdup(service); return (clnt_stream); diff --git a/postfix/src/global/clnt_stream.h b/postfix/src/global/clnt_stream.h index a3d480a17..0d3ee4775 100644 --- a/postfix/src/global/clnt_stream.h +++ b/postfix/src/global/clnt_stream.h @@ -21,7 +21,7 @@ */ typedef struct CLNT_STREAM CLNT_STREAM; -extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int); +extern CLNT_STREAM *clnt_stream_create(const char *, const char *, int, int); extern VSTREAM *clnt_stream_access(CLNT_STREAM *); extern void clnt_stream_recover(CLNT_STREAM *); extern void clnt_stream_free(CLNT_STREAM *); diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c new file mode 100644 index 000000000..626eb9a3e --- /dev/null +++ b/postfix/src/global/dict_proxy.c @@ -0,0 +1,237 @@ +/*++ +/* NAME +/* dict_proxy 3 +/* SUMMARY +/* generic dictionary proxy client +/* SYNOPSIS +/* #include +/* +/* 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. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include +#include +#include + +/* Application-specific. */ + +typedef struct { + DICT dict; /* generic members */ + int in_flags; /* caller-specified flags */ + CLNT_STREAM *client; /* server handle */ + 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 the same 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 + || 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", VSTREAM_PATH(stream), myname); + } 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) { + return (STR(dict_proxy->result)); + } else if (status == PROXY_STAT_FAIL) { + return (0); + } else if (status == 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); + } + } + 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 (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. + */ + 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(var_queue_dir, F_OK) == 0) + prefix = kludge = concatenate(var_queue_dir, "/", + MAIL_CLASS_PRIVATE, (char *) 0); + else + prefix = MAIL_CLASS_PRIVATE; + proxy_stream = clnt_stream_create(prefix, + MAIL_SERVICE_PROXYMAP, + var_ipc_idle_limit, + var_ipc_ttl_limit); + if (kludge) + myfree(kludge); + } + + /* + * Establish initial contact and finalize the flags. + */ + 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 (status == PROXY_STAT_OK) { + 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); + } + clnt_stream_recover(proxy_stream); + sleep(1); /* XXX make configurable */ + } + return (DICT_DEBUG (&dict_proxy->dict)); +} diff --git a/postfix/src/global/dict_proxy.h b/postfix/src/global/dict_proxy.h new file mode 100644 index 000000000..50932b0c4 --- /dev/null +++ b/postfix/src/global/dict_proxy.h @@ -0,0 +1,48 @@ +#ifndef _DICT_PROXY_H_INCLUDED_ +#define _DICT_PROXY_H_INCLUDED_ + +/*++ +/* NAME +/* dict_proxy 3h +/* SUMMARY +/* dictionary manager interface to PROXY maps +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * 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 +#define PROXY_STAT_FAIL 1 +#define PROXY_STAT_BAD 2 +#define PROXY_STAT_RETRY 3 + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif diff --git a/postfix/src/global/mail_dict.c b/postfix/src/global/mail_dict.c new file mode 100644 index 000000000..a576f5894 --- /dev/null +++ b/postfix/src/global/mail_dict.c @@ -0,0 +1,57 @@ +/*++ +/* NAME +/* mail_dict 3 +/* SUMMARY +/* register application-specific dictionaries +/* SYNOPSIS +/* #include +/* +/* 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 + +/* Utility library. */ + +#include +#include + +/* Global library. */ + +#include +#include + +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); +} diff --git a/postfix/src/global/mail_dict.h b/postfix/src/global/mail_dict.h new file mode 100644 index 000000000..62ad8810a --- /dev/null +++ b/postfix/src/global/mail_dict.h @@ -0,0 +1,25 @@ +/*++ +/* NAME +/* mail_dict 3h +/* SUMMARY +/* register application-specific dictionaries +/* SYNOPSIS +/* #include +/* 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 +/*--*/ diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 6d8389974..8c2463b80 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -47,6 +47,7 @@ /* char *var_mail_release; /* char *var_mail_version; /* int var_ipc_idle_limit; +/* int var_ipc_ttl_limit; /* char *var_db_type; /* char *var_hash_queue_names; /* int var_hash_queue_depth; @@ -205,6 +206,7 @@ int var_message_limit; char *var_mail_release; char *var_mail_version; int var_ipc_idle_limit; +int var_ipc_ttl_limit; char *var_db_type; char *var_hash_queue_names; int var_hash_queue_depth; @@ -505,6 +507,7 @@ void mail_params_init() VAR_MAX_IDLE, DEF_MAX_IDLE, &var_idle_limit, 1, 0, VAR_IPC_TIMEOUT, DEF_IPC_TIMEOUT, &var_ipc_timeout, 1, 0, VAR_IPC_IDLE, DEF_IPC_IDLE, &var_ipc_idle_limit, 1, 0, + VAR_IPC_TTL, DEF_IPC_TTL, &var_ipc_ttl_limit, 1, 0, VAR_TRIGGER_TIMEOUT, DEF_TRIGGER_TIMEOUT, &var_trigger_timeout, 1, 0, VAR_FORK_DELAY, DEF_FORK_DELAY, &var_fork_delay, 1, 0, VAR_FLOCK_DELAY, DEF_FLOCK_DELAY, &var_flock_delay, 1, 0, diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 9c004ec7f..554e94a03 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -653,12 +653,21 @@ extern int var_idle_limit; /* * Any subsystem: default amount of time a mail subsystem keeps an internal - * IPC connection before closing it. + * IPC connection before closing it because it is idle for too much time. */ #define VAR_IPC_IDLE "ipc_idle" #define DEF_IPC_IDLE "100s" extern int var_ipc_idle_limit; + /* + * Any subsystem: default amount of time a mail subsystem keeps an internal + * IPC connection before closing it because the connection has existed for + * too much time. + */ +#define VAR_IPC_TTL "ipc_ttl" +#define DEF_IPC_TTL "1000s" +extern int var_ipc_ttl_limit; + /* * Any front-end subsystem: avoid running out of memory when someone sends * infinitely-long requests or replies. @@ -1313,13 +1322,32 @@ extern char *var_smtpd_exp_filter; * 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 $" VAR_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_PROXYMAP_FILTER "proxymap_filter" +#define DEF_PROXYMAP_FILTER "$" 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_proxymap_filter; + /* * Other. */ diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 2b55f5cf8..7cb0dd4c6 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -52,6 +52,7 @@ #define MAIL_SERVICE_VERIFY "verify" #define MAIL_SERVICE_TRACE "trace" #define MAIL_SERVICE_RELAY "relay" +#define MAIL_SERVICE_PROXYMAP "proxymap" /* * Well-known socket or FIFO directories. The main difference is in file @@ -111,6 +112,9 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_TRACE_FLAGS "trace_flags" #define MAIL_ATTR_ADDR_STATUS "recipient_status" #define MAIL_ATTR_ACTION "action" +#define MAIL_ATTR_TABLE "table" +#define MAIL_ATTR_KEY "key" +#define MAIL_ATTR_VALUE "value" /* * Suffixes for sender_name, sender_domain etc. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 6186cb532..8c770247e 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20030101" +#define MAIL_RELEASE_DATE "20030103" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "2.0.0-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/maps.c b/postfix/src/global/maps.c index 82edbb0cc..c9f6a05c4 100644 --- a/postfix/src/global/maps.c +++ b/postfix/src/global/maps.c @@ -11,11 +11,6 @@ /* const char *map_names; /* int flags; /* -/* MAPS *maps_append(maps, map_name, dict_handle) -/* MAPS *maps; -/* const char *map_name; -/* DICT *dict_handle; -/* /* const char *maps_find(maps, key, flags) /* MAPS *maps; /* const char *key; @@ -37,10 +32,6 @@ /* other maps_xxx() operations. /* See dict_open(3) for a description of flags. /* -/* maps_append() appends a dictionary to an existing handle -/* under the given name. If dict_handle is a null pointer, -/* the named dictionary is opened on the fly. -/* /* maps_find() searches the specified list of dictionaries /* in the specified order for the named key. The result is in /* memory that is overwritten upon each call. @@ -115,11 +106,14 @@ MAPS *maps_create(const char *title, const char *map_names, int flags) { + const char *myname = "maps_create"; char *temp; char *bufp; static char sep[] = " \t,\r\n"; MAPS *maps; char *map_type_name; + VSTRING *map_type_name_flags; + DICT *dict; /* * Initialize. @@ -127,7 +121,6 @@ MAPS *maps_create(const char *title, const char *map_names, int flags) maps = (MAPS *) mymalloc(sizeof(*maps)); maps->title = mystrdup(title); maps->argv = argv_alloc(2); - maps->flags = flags; /* * For each specified type:name pair, either register a new dictionary, @@ -135,32 +128,24 @@ MAPS *maps_create(const char *title, const char *map_names, int flags) */ if (*map_names) { bufp = temp = mystrdup(map_names); - while ((map_type_name = mystrtok(&bufp, sep)) != 0) - maps_append(maps, map_type_name, dict_handle(map_type_name)); + map_type_name_flags = vstring_alloc(10); + + while ((map_type_name = mystrtok(&bufp, sep)) != 0) { + vstring_sprintf(map_type_name_flags, "%s:%o", map_type_name, flags); + if ((dict = dict_handle(vstring_str(map_type_name_flags))) == 0) + dict = dict_open(map_type_name, O_RDONLY, flags); + if ((dict->flags & flags) != flags) + msg_panic("%s: map %s has flags 0%o, want flags 0%o", + myname, map_type_name, dict->flags, flags); + dict_register(vstring_str(map_type_name_flags), dict); + argv_add(maps->argv, vstring_str(map_type_name_flags), ARGV_END); + } myfree(temp); + vstring_free(map_type_name_flags); } return (maps); } -/* maps_append - append dictionary */ - -MAPS *maps_append(MAPS *maps, const char *map_type_name, DICT *dict) -{ - char *myname = "maps_append"; - - if (msg_verbose) - msg_info("%s: %s", myname, map_type_name); - if (dict == 0) - dict = dict_open(map_type_name, O_RDONLY, maps->flags); - if ((dict->flags & maps->flags) != maps->flags) - msg_warn("%s: map %s has flags 0%o, want flags 0%o", - myname, map_type_name, dict->flags, maps->flags); - dict_register(map_type_name, dict); - argv_add(maps->argv, map_type_name, ARGV_END); - argv_terminate(maps->argv); - return (maps); -} - /* maps_find - search a list of dictionaries */ const char *maps_find(MAPS *maps, const char *name, int flags) diff --git a/postfix/src/global/maps.h b/postfix/src/global/maps.h index d6be6b1aa..015811f69 100644 --- a/postfix/src/global/maps.h +++ b/postfix/src/global/maps.h @@ -22,11 +22,9 @@ typedef struct MAPS { char *title; struct ARGV *argv; - int flags; } MAPS; extern MAPS *maps_create(const char *, const char *, int); -extern MAPS *maps_append(MAPS *, const char *, DICT *); extern const char *maps_find(MAPS *, const char *, int); extern MAPS *maps_free(MAPS *); diff --git a/postfix/src/global/resolve_clnt.c b/postfix/src/global/resolve_clnt.c index 4d739609f..41cd78584 100644 --- a/postfix/src/global/resolve_clnt.c +++ b/postfix/src/global/resolve_clnt.c @@ -178,7 +178,9 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply) */ if (rewrite_clnt_stream == 0) rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, - var_rewrite_service, var_ipc_idle_limit); + var_rewrite_service, + var_ipc_idle_limit, + var_ipc_ttl_limit); for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); diff --git a/postfix/src/global/rewrite_clnt.c b/postfix/src/global/rewrite_clnt.c index 8e07dba78..ce7850d9e 100644 --- a/postfix/src/global/rewrite_clnt.c +++ b/postfix/src/global/rewrite_clnt.c @@ -119,7 +119,9 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result) */ if (rewrite_clnt_stream == 0) rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, - var_rewrite_service, var_ipc_idle_limit); + var_rewrite_service, + var_ipc_idle_limit, + var_ipc_ttl_limit); for (;;) { stream = clnt_stream_access(rewrite_clnt_stream); diff --git a/postfix/src/global/verify_clnt.c b/postfix/src/global/verify_clnt.c index 31532a357..878df8f9e 100644 --- a/postfix/src/global/verify_clnt.c +++ b/postfix/src/global/verify_clnt.c @@ -96,7 +96,7 @@ static void verify_clnt_init(void) if (vrfy_clnt != 0) msg_panic("verify_clnt_init: multiple initialization"); vrfy_clnt = clnt_stream_create(MAIL_CLASS_PRIVATE, var_verify_service, - var_ipc_idle_limit); + var_ipc_idle_limit, var_ipc_ttl_limit); } /* verify_clnt_query - request address verification status */ diff --git a/postfix/src/global/virtual8_maps.c b/postfix/src/global/virtual8_maps.c index 332cc8e04..c911737ec 100644 --- a/postfix/src/global/virtual8_maps.c +++ b/postfix/src/global/virtual8_maps.c @@ -30,7 +30,9 @@ /* 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. +/* 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. /* /* virtual8_maps_find() searches the specified list of dictionaries /* in the specified order for the named key. The result is in diff --git a/postfix/src/global/virtual8_maps.h b/postfix/src/global/virtual8_maps.h index 4261413b8..2cf89f6c8 100644 --- a/postfix/src/global/virtual8_maps.h +++ b/postfix/src/global/virtual8_maps.h @@ -20,7 +20,8 @@ * 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) | DICT_FLAG_NO_REGSUB | DICT_FLAG_NO_PROXY) extern const char *virtual8_maps_find(MAPS *, const char *); #define virtual8_maps_free(maps) maps_free((maps)) diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index b0615286d..7b4584547 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -696,8 +696,10 @@ 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 | DICT_FLAG_NO_REGSUB); + DICT_FLAG_LOCK | INSECURE_DICT_FLAGS); } /* main - pass control to the single-threaded skeleton */ diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index cf646935e..eeb2ce986 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -242,6 +242,7 @@ multi_server.o: ../../include/mail_task.h 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 @@ -270,6 +271,7 @@ single_server.o: ../../include/mail_params.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 @@ -298,6 +300,7 @@ trigger_server.o: ../../include/mail_params.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 diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 4275c0c65..9fdbd657b 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -111,10 +111,14 @@ /* This value is taken from the global \fBmain.cf\fR configuration /* file. Setting \fBvar_use_limit\fR to zero disables the client limit. /* +/* When the use count reaches the use limit, the process no longer +/* accepts new connections. Once all existing clients disconnect the +/* process terminates. +/* /* 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 @@ -173,6 +177,7 @@ #include #include #include +#include #include #include #include @@ -236,7 +241,6 @@ void multi_server_disconnect(VSTREAM *stream) event_disable_readwrite(vstream_fileno(stream)); (void) vstream_fclose(stream); client_count--; - use_count++; } /* multi_server_execute - in case (char *) != (struct *) */ @@ -254,10 +258,10 @@ static void multi_server_execute(int unused_event, char *context) * Do not bother the application when the client disconnected. */ if (peekfd(vstream_fileno(stream)) > 0) { - if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0) + if (var_use_limit >= 0 && master_notify(var_pid, MASTER_STAT_TAKEN) < 0) multi_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); multi_server_service(stream, multi_server_name, multi_server_argv); - if (master_notify(var_pid, MASTER_STAT_AVAIL) < 0) + if (var_use_limit >= 0 && master_notify(var_pid, MASTER_STAT_AVAIL) < 0) multi_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); } else { multi_server_disconnect(stream); @@ -287,6 +291,7 @@ static void multi_server_wakeup(int fd) non_blocking(fd, BLOCKING); close_on_exec(fd, CLOSE_ON_EXEC); client_count++; + use_count++; stream = vstream_fdopen(fd, O_RDWR); tmp = concatenate(multi_server_name, " socket", (char *) 0); vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); @@ -436,6 +441,11 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) */ 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. @@ -672,7 +682,43 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) /* * The event loop, at last. */ - while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) { + for (;;) { + + /* + * When the use count reaches the use limit, notify the master daemon + * that we are no longer listening, close the listen sockets, and + * dispose of the accept lock if any. A use_limit < 0 indicates that + * the client limit was reached. + */ + if (var_use_limit > 0 && use_count >= var_use_limit) { + if (msg_verbose) + msg_info("use limit reached -- closing listen socket"); + if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0) + multi_server_abort(EVENT_NULL_TYPE, EVENT_NULL_CONTEXT); + for (fd = MASTER_LISTEN_FD; fd < MASTER_LISTEN_FD + socket_count; fd++) { + event_disable_readwrite(fd); + (void) close(fd); + } + if (multi_server_lock != 0) { + (void) vstream_fclose(multi_server_lock); + multi_server_lock = 0; + } + var_use_limit = -1; + } + + /* + * Terminate if the client limit was reached and no connections remain. + */ + if (var_use_limit < 0 && client_count == 0) { + if (msg_verbose) + msg_info("all clients disconnected -- exiting"); + break; + } + + /* + * Grab the optional accept lock, do some optional idle processing, + * and wait for the next event. + */ if (multi_server_lock != 0) { watchdog_stop(watchdog); if (myflock(vstream_fileno(multi_server_lock), INTERNAL_LOCK, diff --git a/postfix/src/master/single_server.c b/postfix/src/master/single_server.c index 077d8cc70..9e269e98d 100644 --- a/postfix/src/master/single_server.c +++ b/postfix/src/master/single_server.c @@ -167,6 +167,7 @@ #include #include #include +#include #include #include #include @@ -392,6 +393,11 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) */ 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. diff --git a/postfix/src/master/trigger_server.c b/postfix/src/master/trigger_server.c index 08d42bf18..685973a07 100644 --- a/postfix/src/master/trigger_server.c +++ b/postfix/src/master/trigger_server.c @@ -175,6 +175,7 @@ #include #include #include +#include #include #include @@ -388,6 +389,11 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. */ 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. diff --git a/postfix/src/postalias/Makefile.in b/postfix/src/postalias/Makefile.in index 465ba2c38..acb8e86b9 100644 --- a/postfix/src/postalias/Makefile.in +++ b/postfix/src/postalias/Makefile.in @@ -95,6 +95,7 @@ postalias.o: ../../include/set_eugid.h 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 diff --git a/postfix/src/postalias/postalias.c b/postfix/src/postalias/postalias.c index cadb61a7f..4a88d6e25 100644 --- a/postfix/src/postalias/postalias.c +++ b/postfix/src/postalias/postalias.c @@ -169,6 +169,7 @@ #include #include +#include #include #include @@ -587,6 +588,7 @@ int main(int argc, char **argv) } } mail_conf_read(); + mail_dict_init(); /* * Use the map type specified by the user, or fall back to a default diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index 7732636b8..198be229e 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -88,6 +88,7 @@ postconf.o: ../../include/vstring_vstream.h 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 diff --git a/postfix/src/postconf/postconf.c b/postfix/src/postconf/postconf.c index 662c66b1d..91854d522 100644 --- a/postfix/src/postconf/postconf.c +++ b/postfix/src/postconf/postconf.c @@ -47,7 +47,10 @@ /* 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. @@ -73,6 +76,10 @@ /* .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). @@ -156,6 +163,7 @@ #include #include +#include #include #include #include @@ -921,6 +929,7 @@ int main(int argc, char **argv) * If showing map types, show them and exit */ if (mode & SHOW_MAPS) { + mail_dict_init(); show_maps(); } diff --git a/postfix/src/postmap/Makefile.in b/postfix/src/postmap/Makefile.in index 66ebf9f74..5dbb4ccfe 100644 --- a/postfix/src/postmap/Makefile.in +++ b/postfix/src/postmap/Makefile.in @@ -93,6 +93,7 @@ postmap.o: ../../include/split_at.h 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 diff --git a/postfix/src/postmap/postmap.c b/postfix/src/postmap/postmap.c index 0d7ad8400..cd3d6887e 100644 --- a/postfix/src/postmap/postmap.c +++ b/postfix/src/postmap/postmap.c @@ -181,6 +181,7 @@ /* Global library. */ #include +#include #include #include @@ -537,6 +538,7 @@ int main(int argc, char **argv) } } mail_conf_read(); + mail_dict_init(); /* * Use the map type specified by the user, or fall back to a default diff --git a/postfix/src/proxymap/.indent.pro b/postfix/src/proxymap/.indent.pro new file mode 120000 index 000000000..5c837eca6 --- /dev/null +++ b/postfix/src/proxymap/.indent.pro @@ -0,0 +1 @@ +../../.indent.pro \ No newline at end of file diff --git a/postfix/src/proxymap/Makefile.in b/postfix/src/proxymap/Makefile.in new file mode 100644 index 000000000..5ee7d59d8 --- /dev/null +++ b/postfix/src/proxymap/Makefile.in @@ -0,0 +1,73 @@ +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/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 diff --git a/postfix/src/proxymap/proxymap.c b/postfix/src/proxymap/proxymap.c new file mode 100644 index 000000000..d29507529 --- /dev/null +++ b/postfix/src/proxymap/proxymap.c @@ -0,0 +1,361 @@ +/*++ +/* 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. +/* The solution is to specify: +/* .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: +/* .sp +/* virtual_alias_maps = +/* .ti +4 +/* proxy:mysql:/etc/postfix/virtual.cf +/* PROXYMAP SERVICES +/* .ad +/* .fi +/* 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 +/* 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 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. This does not seem to be useful +/* 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. +/* .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 +/* .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 \fB$max_use\fR clients +/* or 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. +/* 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 \fBproxymap_filter\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. +/* 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 +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include +#include + +/* Global library. */ + +#include +#include +#include +#include + +/* Server skeleton. */ + +#include + +/* 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_proxymap_filter; + + /* + * The pre-approved, pre-parsed list of maps. + */ +static HTABLE *proxymap_filter; + + /* + * Shared and static to reduce memory allocation overhead. + */ +static VSTRING *request; +static VSTRING *map_type_name_flags; +static VSTRING *map_type_name; +static VSTRING *key; + + /* + * 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 dict_flags) +{ + DICT *dict; + +#define PROXY_COLON DICT_TYPE_PROXY ":" +#define PROXY_COLON_LEN (sizeof(PROXY_COLON) - 1) +#define OPEN_FLAGS O_RDONLY + + /* + * Canonicalize the map name. If the map is not on the approved list, + * deny the request. + */ + 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); + return (0); + } + + /* + * 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); + if ((dict = dict_handle(STR(map_type_name_flags))) == 0) + dict = dict_open(map_type_name, OPEN_FLAGS, dict_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 status = PROXY_STAT_BAD; + DICT *dict; + const char *value = ""; + int dict_flags; + + 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 = ""; + } + } + + /* + * 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_END); +} + +/* proxymap_open_service - open remote lookup table */ + +static void proxymap_open_service(VSTREAM *client_stream) +{ + int dict_flags; + DICT *dict; + int status = PROXY_STAT_BAD; + int flags = 0; + + 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; + } + + /* + * 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_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 address verification 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; + + request = vstring_alloc(10); + map_type_name = 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); + 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); + } + myfree(saved_filter); +} + +/* 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_PROXYMAP_FILTER, DEF_PROXYMAP_FILTER, &var_proxymap_filter, 0, 0, + 0, + }; + + multi_server_main(argc, argv, proxymap_service, + MAIL_SERVER_STR_TABLE, str_table, + MAIL_SERVER_POST_INIT, post_jail_init, + 0); +} diff --git a/postfix/src/trivial-rewrite/trivial-rewrite.c b/postfix/src/trivial-rewrite/trivial-rewrite.c index 6e89221ad..b69f482b0 100644 --- a/postfix/src/trivial-rewrite/trivial-rewrite.c +++ b/postfix/src/trivial-rewrite/trivial-rewrite.c @@ -26,6 +26,14 @@ /* .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 diff --git a/postfix/src/util/dict.h b/postfix/src/util/dict.h index 16071a692..546420dd2 100644 --- a/postfix/src/util/dict.h +++ b/postfix/src/util/dict.h @@ -58,7 +58,9 @@ 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 */ extern int dict_unknown_allowed; extern int dict_errno; diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c index cc8e59530..02d83a02c 100644 --- a/postfix/src/verify/verify.c +++ b/postfix/src/verify/verify.c @@ -34,12 +34,12 @@ /* returned. /* .PP /* The server reply status is one of: -/* .IP \fBVRFYSTAT_OK\fR +/* .IP \fBVRFY_STAT_OK\fR /* The request completed normally. -/* .IP \fBVRFYSTAT_BAD\fR +/* .IP \fBVRFY_STAT_BAD\fR /* The server rejected the request (bad request name, bad /* request parameter value). -/* .IP \fBVRFYSTAT_FAIL\fR +/* .IP \fBVRFY_STAT_FAIL\fR /* The request failed. /* .PP /* The recipient status is one of: @@ -145,7 +145,7 @@ #include #include -/* Single server skeleton. */ +/* Server skeleton. */ #include @@ -490,7 +490,7 @@ static void pre_jail_init(char *unused_name, char **unused_argv) setsid(); } -/* main - pass control to the single-threaded skeleton */ +/* main - pass control to the multi-threaded skeleton */ int main(int argc, char **argv) { diff --git a/postfix/src/virtual/virtual.c b/postfix/src/virtual/virtual.c index 0ae16d2e7..49ed051df 100644 --- a/postfix/src/virtual/virtual.c +++ b/postfix/src/virtual/virtual.c @@ -133,6 +133,9 @@ /* 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 @@ -156,6 +159,9 @@ /* 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. @@ -170,6 +176,9 @@ /* 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