]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.0.0-20030103
authorWietse Venema <wietse@porcupine.org>
Fri, 3 Jan 2003 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:39 +0000 (06:28 +0000)
56 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/Makefile.in
postfix/conf/post-install
postfix/conf/postfix-files
postfix/conf/sample-misc.cf
postfix/html/Makefile.in
postfix/html/backstage.html
postfix/html/postconf.1.html
postfix/html/proxymap.8.html [new file with mode: 0644]
postfix/html/trivial-rewrite.8.html
postfix/html/verify.8.html
postfix/html/virtual.8.html
postfix/man/Makefile.in
postfix/man/man1/postconf.1
postfix/man/man8/proxymap.8 [new file with mode: 0644]
postfix/man/man8/trivial-rewrite.8
postfix/man/man8/verify.8
postfix/man/man8/virtual.8
postfix/mantools/postlink
postfix/src/global/Makefile.in
postfix/src/global/clnt_stream.c
postfix/src/global/clnt_stream.h
postfix/src/global/dict_proxy.c [new file with mode: 0644]
postfix/src/global/dict_proxy.h [new file with mode: 0644]
postfix/src/global/mail_dict.c [new file with mode: 0644]
postfix/src/global/mail_dict.h [new file with mode: 0644]
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_proto.h
postfix/src/global/mail_version.h
postfix/src/global/maps.c
postfix/src/global/maps.h
postfix/src/global/resolve_clnt.c
postfix/src/global/rewrite_clnt.c
postfix/src/global/verify_clnt.c
postfix/src/global/virtual8_maps.c
postfix/src/global/virtual8_maps.h
postfix/src/local/local.c
postfix/src/master/Makefile.in
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/postalias/Makefile.in
postfix/src/postalias/postalias.c
postfix/src/postconf/Makefile.in
postfix/src/postconf/postconf.c
postfix/src/postmap/Makefile.in
postfix/src/postmap/postmap.c
postfix/src/proxymap/.indent.pro [new symlink]
postfix/src/proxymap/Makefile.in [new file with mode: 0644]
postfix/src/proxymap/proxymap.c [new file with mode: 0644]
postfix/src/trivial-rewrite/trivial-rewrite.c
postfix/src/util/dict.h
postfix/src/verify/verify.c
postfix/src/virtual/virtual.c

index 16ca497d1ef6f3fe22df2848fe45f408b44988c9..132e9b83f99610f21450d3331097e5c451047e59 100644 (file)
@@ -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
index f29e2f7e22b395970a64e6d2cd0cdcaf96f39c0b..9f25df299281b73c91180bbaad72fa5f077a95af 100644 (file)
@@ -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,
index 882c8206f54b804209a8fe37df534d5ba6fa8c0e..62fb6d362084dd9432b7066b4616ee1de15eb75a 100644 (file)
@@ -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
index 9b176f7f8868c8790d86d69f8589961d480ecc8d..d13c8e079b7abe5a8faf45bb18f81942248899c2 100644 (file)
@@ -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 <<EOF || exit 1
+proxymap  unix -       -       n       -       -       proxymap
+EOF
+    }
+
 }
 
 # A reminder if this is the first time Postfix is being installed.
index 64d38d24aa383f7827183c1c09eb0069534e03a2..cf30047b12ff1085f543072db013a153ea6df38b 100644 (file)
@@ -64,6 +64,7 @@ $daemon_directory/master:f:root:-:755
 $daemon_directory/nqmgr:f:root:-:755
 $daemon_directory/pickup:f:root:-:755
 $daemon_directory/pipe:f:root:-:755
+$daemon_directory/proxymap:f:root:-:755
 $daemon_directory/qmgr:f:root:-:755
 $daemon_directory/qmqpd:f:root:-:755
 $daemon_directory/showq:f:root:-:755
@@ -135,6 +136,7 @@ $manpage_directory/man8/master.8:f:root:-:644
 $manpage_directory/man8/nqmgr.8:f:root:-:644
 $manpage_directory/man8/pickup.8:f:root:-:644
 $manpage_directory/man8/pipe.8:f:root:-:644
+$manpage_directory/man8/proxymap.8:f:root:-:644
 $manpage_directory/man8/qmgr.8:f:root:-:644
 $manpage_directory/man8/qmqpd.8:f:root:-:644
 $manpage_directory/man8/showq.8:f:root:-:644
index 6d671287c83e8eacf6bb929ab4d564ab9016c82c..18792e312f22b826d68418e539eed4ff91baeb6f 100644 (file)
@@ -143,14 +143,25 @@ inet_interfaces = all
 # The ipc_idle parameter bounds the idle time for internal communication
 # channels after which a client disconnects voluntarily. The purpose
 # is to allow servers to terminate voluntarily after they become
-# idle. Currently this is used by the address resolving and rewriting
-# clients.
+# idle. This is used, for example, by the address resolving and
+# rewriting clients.
 #
 # Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
 # The default time unit is s (seconds).
 #
 ipc_idle = 100s
 
+# The ipc_ttl parameter bounds the active time for internal communication
+# channels after which a client disconnects voluntarily. The purpose
+# is to allow servers to terminate voluntarily after reaching their
+# client limit.  This is used, for example, by the address resolving
+# and rewriting clients.
+#
+# Time units: s (seconds), m (minutes), h (hours), d (days), w (weeks).
+# The default time unit is s (seconds).
+#
+ipc_ttl = 1000s
+
 # The ipc_timeout parameter specifies a timeout for I/O on internal
 # communication channels.  The purpose is to break out of deadlock
 # situations. If the timeout is exceeded the software aborts with a
index 4ed7cb70bb44f2d13d3a08c11b2b4e00beab5bbd..26e257d2676fec9a0bba7c50869abc5bb57c1f56 100644 (file)
@@ -6,7 +6,7 @@ DAEMONS =  bounce.8.html cleanup.8.html defer.8.html error.8.html local.8.html \
        lmtp.8.html master.8.html pickup.8.html pipe.8.html qmgr.8.html \
        showq.8.html smtp.8.html smtpd.8.html trivial-rewrite.8.html \
        nqmgr.8.html spawn.8.html flush.8.html virtual.8.html qmqpd.8.html \
-       trace.8.html verify.8.html
+       trace.8.html verify.8.html proxymap.8.html
 COMMANDS= mailq.1.html newaliases.1.html postalias.1.html postcat.1.html \
        postconf.1.html postfix.1.html postkick.1.html postlock.1.html \
        postlog.1.html postdrop.1.html postmap.1.html sendmail.1.html \
@@ -76,6 +76,10 @@ pipe.8.html: ../src/pipe/pipe.c
        PATH=../mantools:$$PATH; \
        srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
 
+proxymap.8.html: ../src/proxymap/proxymap.c
+       PATH=../mantools:$$PATH; \
+       srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
+
 qmgr.8.html: ../src/qmgr/qmgr.c
        PATH=../mantools:$$PATH; \
        srctoman $? | $(AWK) | nroff -man | uniq | man2html | postlink >$@
index 99ab2a1bdfc5678e191bd8e9fb0ea9ef76c77d84..fc98461bf8799b2e2ed3b451e60c1364ec009db0 100644 (file)
@@ -73,6 +73,14 @@ UCE restrictions.
 
 <p>
 
+<li>The <a href="proxymap.8.html">proxymap</a> daemon provides
+read-only lookup service to Postfix client processes. The purpose
+is to overcome chroot restrictions, and to consolidate the number
+of open lookup tables by sharing one open table among multiple
+processes.
+
+<p>
+
 <li>The <a href="spawn.8.html">spawn</a> daemon listens on a TCP
 port, UNIX-domain socket or FIFO, and runs non-Postfix commands on
 request, with the socket or FIFO connected to the standard input,
index 0367e4f510cad18cbaee844c15a4c6d3137ae653..b13c0357d33190419d1401682027ba40b5f8d350 100644 (file)
@@ -54,73 +54,81 @@ POSTCONF(1)                                           POSTCONF(1)
                      were left behind after abnormal termination.
 
        <b>-m</b>     List the names of all supported lookup table types.
+              Postfix lookup tables are specified  as  <i>type</i><b>:</b><i>name</i>,
+              where  <i>type</i>  is  one of the types listed below. The
+              table <i>name</i> syntax depends on the lookup table type.
 
-              <b>btree</b>  A sorted, balanced tree structure.  This  is
-                     available  only  on systems with support for
+              <b>btree</b>  A  sorted, balanced tree structure.  This is
+                     available only on systems with  support  for
                      Berkeley DB databases.
 
               <b>dbm</b>    An indexed file type based on hashing.  This
-                     is  available  only  on systems with support
+                     is available only on  systems  with  support
                      for DBM databases.
 
               <b>environ</b>
                      The  UNIX  process  environment  array.  The
-                     lookup  key is the variable name. Originally
-                     implemented for testing,  someone  may  find
+                     lookup key is the variable name.  Originally
+                     implemented  for  testing,  someone may find
                      this useful someday.
 
               <b>hash</b>   An indexed file type based on hashing.  This
-                     is available only on  systems  with  support
+                     is  available  only  on systems with support
                      for Berkeley DB databases.
 
               <b>ldap</b> (read-only)
-                     Perform  lookups  using  the  LDAP protocol.
+                     Perform lookups  using  the  LDAP  protocol.
                      This is described in an LDAP_README file.
 
               <b>mysql</b> (read-only)
-                     Perform lookups using  the  MYSQL  protocol.
+                     Perform  lookups  using  the MYSQL protocol.
                      This is described in a MYSQL_README file.
 
               <b>pcre</b> (read-only)
                      A lookup table based on Perl Compatible Reg-
-                     ular  Expressions.  The   file   format   is
+                     ular   Expressions.   The   file  format  is
                      described in <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
 
+              <b>proxy</b> (read-only)
+                     A lookup table that is implemented  via  the
+                     Postfix  <a href="verify.8.html"><b>proxymap</b>(8)</a> service. The table name
+                     syntax is <i>type</i><b>:</b><i>name</i>.
+
               <b>regexp</b> (read-only)
                      A lookup table based on regular expressions.
-                     The  file  format  is  described   in   <a href="regexp_table.5.html"><b>reg-</b>
+                     The   file   format  is  described  in  <a href="regexp_table.5.html"><b>reg-</b>
                      <b>exp</b><i>_</i><b>table</b>(5)</a>.
 
               <b>static</b> (read-only)
-                     A  table  that  always  returns  its name as
-                     lookup result.  For  example,  <b>static:foobar</b>
-                     always  returns  the string <b>foobar</b> as lookup
+                     A table that  always  returns  its  name  as
+                     lookup  result.  For  example, <b>static:foobar</b>
+                     always returns the string <b>foobar</b>  as  lookup
                      result.
 
               <b>unix</b> (read-only)
-                     A limited way to query the UNIX  authentica-
+                     A  limited way to query the UNIX authentica-
                      tion  database.  The  following  tables  are
                      implemented:
 
                      <b>unix:passwd.byname</b>
-                             The  table  is  the  UNIX   password
-                             database.  The  key is a login name.
-                             The result is a password file  entry
+                             The   table  is  the  UNIX  password
+                             database. The key is a  login  name.
+                             The  result is a password file entry
                              in passwd(5) format.
 
                      <b>unix:group.byname</b>
-                             The   table   is   the   UNIX  group
-                             database. The key is a  group  name.
-                             The  result is a group file entry in
+                             The  table   is   the   UNIX   group
+                             database.  The  key is a group name.
+                             The result is a group file entry  in
                              group(5) format.
 
-       Other table types may exist depending on how  Postfix  was
+       Other  table  types may exist depending on how Postfix was
        built.
 
        <b>-n</b>     Print non-default parameter settings only.
 
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
-              tiple <b>-v</b> options  make  the  software  increasingly
+              tiple  <b>-v</b>  options  make  the software increasingly
               verbose.
 
 <b>DIAGNOSTICS</b>
@@ -131,7 +139,7 @@ POSTCONF(1)                                           POSTCONF(1)
               Directory with Postfix configuration files.
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
diff --git a/postfix/html/proxymap.8.html b/postfix/html/proxymap.8.html
new file mode 100644 (file)
index 0000000..bc96ab2
--- /dev/null
@@ -0,0 +1,115 @@
+<html> <head> </head> <body> <pre>
+PROXYMAP(8)                                           PROXYMAP(8)
+
+<b>NAME</b>
+       proxymap - Postfix lookup table proxy server
+
+<b>SYNOPSIS</b>
+       <b>proxymap</b> [generic Postfix daemon options]
+
+<b>DESCRIPTION</b>
+       The  <b>proxymap</b>  server provides read-only table lookup ser-
+       vice to Postfix client processes. The purpose of the  ser-
+       vice is:
+
+       <b>o</b>      To  overcome  chroot  restrictions.  For example, a
+              chrooted SMTP server needs  access  to  the  system
+              passwd  file  in order to reject mail for non-exis-
+              tent local addresses.  The solution is to specify:
+
+              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:
+
+              virtual_alias_maps =
+                  proxy:mysql:/etc/postfix/virtual.cf
+
+<b>PROXYMAP</b> <b>SERVICES</b>
+       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.
+
+       <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.
+
+       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:
+
+       <b>PROXY</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
+              The requested table or lookup key 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>BAD</b>
+              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.
+
+<b>MASTER</b> <b>INTERFACE</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.
+
+<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.
+
+<b>DIAGNOSTICS</b>
+       Problems and transactions are logged to <b>syslogd</b>(8).
+
+<b>BUGS</b>
+       The  proxymap server provides service to multiple clients,
+       and must therefore not be used for tables that have  high-
+       latency lookups.
+
+<b>CONFIGURATION</b> <b>PARAMETERS</b>
+       The  following  main.cf parameters are especially relevant
+       to this program. Use the <b>postfix</b> <b>reload</b>  command  after  a
+       configuration change.
+
+       <b>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>SEE</b> <b>ALSO</b>
+       dict_proxy(3) proxy map client
+
+<b>LICENSE</b>
+       The Secure Mailer license must be  distributed  with  this
+       software.
+
+<b>AUTHOR(S)</b>
+       Wietse Venema
+       IBM T.J. Watson Research
+       P.O. Box 704
+       Yorktown Heights, NY 10598, USA
+
+                                                      PROXYMAP(8)
+</pre> </body> </html>
index fcb9f67eaebe41e98ff00450fa8f0b91cce2af60..97ce29da96e0cc3c688169c3f25a369c05e86bc5 100644 (file)
@@ -37,6 +37,14 @@ 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>
index f86eeb0db3a3e1e4731384a5855f27adf18e1848..b0f67a1f2cb4db8e871fe105e60352b1fbf5babb 100644 (file)
@@ -39,14 +39,14 @@ VERIFY(8)                                               VERIFY(8)
 
        The server reply status is one of:
 
-       <b>VRFYSTAT</b><i>_</i><b>OK</b>
+       <b>VRFY</b><i>_</i><b>STAT</b><i>_</i><b>OK</b>
               The request completed normally.
 
-       <b>VRFYSTAT</b><i>_</i><b>BAD</b>
+       <b>VRFY</b><i>_</i><b>STAT</b><i>_</i><b>BAD</b>
               The server rejected the request (bad request  name,
               bad request parameter value).
 
-       <b>VRFYSTAT</b><i>_</i><b>FAIL</b>
+       <b>VRFY</b><i>_</i><b>STAT</b><i>_</i><b>FAIL</b>
               The request failed.
 
        The recipient status is one of:
index 925526715c21ca652fc53e8786f4709e1b7dcefa..e350dcb3f45653eaeb6c059849c3a0e8aaa23666 100644 (file)
@@ -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.
+
        <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>
-              The  list  of  domains that should be delivered via
-              the Postfix virtual delivery agent. This  uses  the
+              The list of domains that should  be  delivered  via
+              the  Postfix  virtual delivery agent. This uses the
               same  syntax  as  the  <b>mydestination</b>  configuration
               parameter.
 
        <b>virtual</b><i>_</i><b>minimum</b><i>_</i><b>uid</b>
-              Specifies a minimum uid that will be accepted as  a
-              return    from   a   <b>virtual</b><i>_</i><b>owner</b><i>_</i><b>maps</b>   or   <b>vir-</b>
-              <b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b> lookup.  Returned  values  less  than
-              this  will  be  rejected,  and  the message will be
+              Specifies  a minimum uid that will be accepted as a
+              return   from   a   <b>virtual</b><i>_</i><b>owner</b><i>_</i><b>maps</b>   or    <b>vir-</b>
+              <b>tual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>  lookup.   Returned  values less than
+              this will be rejected,  and  the  message  will  be
               deferred.
 
        <b>virtual</b><i>_</i><b>uid</b><i>_</i><b>maps</b>
               Recipients are looked up in these maps to determine
-              the  user  ID to be used when writing to the target
+              the user ID to be used when writing to  the  target
               mailbox.
 
-              While searching a lookup table, an  address  exten-
+              While  searching  a lookup table, an address exten-
               sion (<i>user+foo@domain.tld</i>) is ignored.
 
-              In  a  lookup  table,  specify  a left-hand side of
-              <i>@domain.tld</i> to match  any  user  in  the  specified
-              domain    that    does    not   have   a   specific
+              In a lookup table,  specify  a  left-hand  side  of
+              <i>@domain.tld</i>  to  match  any  user  in the specified
+              domain   that   does   not    have    a    specific
               <i>user@domain.tld</i> entry.
 
-              For security reasons, regular expression  maps  are
-              allowed  but  regular expression substitution of $1
+              For  security  reasons, regular expression maps are
+              allowed but regular expression substitution  of  $1
               etc. is disallowed, because that would open a secu-
               rity hole.
 
+              For security reasons, proxied table lookup  is  not
+              allowed, because that would open a security hole.
+
        <b>virtual</b><i>_</i><b>gid</b><i>_</i><b>maps</b>
               Recipients are looked up in these maps to determine
               the group ID to be used when writing to the  target
@@ -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.
+
 <b>Locking</b> <b>controls</b>
        <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>lock</b>
-              How to lock UNIX-style mailboxes: one  or  more  of
-              <b>flock</b>,   <b>fcntl</b>   or  <b>dotlock</b>.  The  <b>dotlock</b>  method
-              requires that the recipient UID or  GID  has  write
+              How  to  lock  UNIX-style mailboxes: one or more of
+              <b>flock</b>,  <b>fcntl</b>  or  <b>dotlock</b>.  The   <b>dotlock</b>   method
+              requires  that  the  recipient UID or GID has write
               access to the parent directory of the mailbox file.
 
-              This setting is ignored with <b>maildir</b>  style  deliv-
+              This  setting  is ignored with <b>maildir</b> style deliv-
               ery,  because  such  deliveries  are  safe  without
               explicit locks.
 
-              Use the command <b>postconf</b> <b>-l</b> to find out what  lock-
+              Use  the command <b>postconf</b> <b>-l</b> to find out what lock-
               ing methods are available on your system.
 
        <b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
-              Limit  the  number of attempts to acquire an exclu-
+              Limit the number of attempts to acquire  an  exclu-
               sive lock on a UNIX-style mailbox file.
 
        <b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
               Time (default: seconds) between successive attempts
-              to  acquire an exclusive lock on a UNIX-style mail-
-              box file. The actual delay is slightly  randomized.
+              to acquire an exclusive lock on a UNIX-style  mail-
+              box  file. The actual delay is slightly randomized.
 
        <b>stale</b><i>_</i><b>lock</b><i>_</i><b>time</b>
-              Limit  the  time  after  which  a stale lockfile is
-              removed (applicable to UNIX-style mailboxes  only).
+              Limit the time after  which  a  stale  lockfile  is
+              removed  (applicable to UNIX-style mailboxes only).
 
 <b>Resource</b> <b>controls</b>
        <b>virtual</b><i>_</i><b>destination</b><i>_</i><b>concurrency</b><i>_</i><b>limit</b>
               Limit the number of parallel deliveries to the same
               domain via the <b>virtual</b> delivery agent.  The default
               limit is taken from the <b>default</b><i>_</i><b>destination</b><i>_</i><b>concur-</b>
-              <b>rency</b><i>_</i><b>limit</b> parameter.  The limit  is  enforced  by
+              <b>rency</b><i>_</i><b>limit</b>  parameter.   The  limit is enforced by
               the Postfix queue manager.
 
        <b>virtual</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
               Limit the number of recipients per message delivery
-              via the <b>virtual</b> delivery agent.  The default  limit
-              is   taken   from  the  <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
-              <b>ent</b><i>_</i><b>limit</b> parameter.  The limit is enforced by  the
+              via  the <b>virtual</b> delivery agent.  The default limit
+              is  taken  from   the   <b>default</b><i>_</i><b>destination</b><i>_</i><b>recipi-</b>
+              <b>ent</b><i>_</i><b>limit</b>  parameter.  The limit is enforced by the
               Postfix queue manager.
 
        <b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>limit</b>
-              The  maximal  size in bytes of a mailbox or maildir
+              The maximal size in bytes of a mailbox  or  maildir
               file.  Set to zero to disable the limit.
 
 <b>HISTORY</b>
-       This agent was  originally  based  on  the  Postfix  local
+       This  agent  was  originally  based  on  the Postfix local
        delivery agent. Modifications mainly consisted of removing
-       code that either was not applicable or that was  not  safe
-       in  this  context: aliases, ~user/.forward files, delivery
+       code  that  either was not applicable or that was not safe
+       in this context: aliases, ~user/.forward  files,  delivery
        to "|command" or to /file/name.
 
-       The <b>Delivered-To:</b> header appears in the  <b>qmail</b>  system  by
+       The  <b>Delivered-To:</b>  header  appears in the <b>qmail</b> system by
        Daniel Bernstein.
 
-       The  <b>maildir</b>  structure  appears  in  the  <b>qmail</b> system by
+       The <b>maildir</b> structure  appears  in  the  <b>qmail</b>  system  by
        Daniel Bernstein.
 
 <b>SEE</b> <b>ALSO</b>
@@ -257,7 +266,7 @@ VIRTUAL(8)                                             VIRTUAL(8)
        <a href="qmgr.8.html">qmgr(8)</a> queue manager
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 3a54be60c289b4260291fba44cd78341a747e90f..91ede1d16d295fc8a570297672e5543e725997ed 100644 (file)
@@ -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 $? >$@
 
index 74d20a49a29114ba2af530c4e5f4bc1940621b06..4a7fab8e3972d6b9af9eba222db2dfbb054b8eee 100644 (file)
@@ -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 (file)
index 0000000..533ef95
--- /dev/null
@@ -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
index 4320f7f2db0cc1e8c5c4919613c6845211c9aa55..bd56ad96fe7be8349b0a2b8e88db33f889531579 100644 (file)
@@ -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
index 6eb33a1960f2d20fc7fcecffbe92d9859f19edf3..2e69799471468eeeb8d031b10cebfc286e596384 100644 (file)
@@ -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:
index f74a6d228e142cfad46b47f59a4818739b4283f0..c7517bc24aec9c4f7b2c820afc9ef75740b39e42 100644 (file)
@@ -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
index ecbc01be93e4bb1c43fb1c82baa61c5bead74196..be5d77bb43da83ccb8d7cab2b0b0f0620d9cfcaa 100755 (executable)
@@ -44,9 +44,11 @@ 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>]*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>/
+       s/[<bB>]*verify[</bB>]*(8)/<a href="verify.8.html">&<\/a>/
        s/[<bB>]*virtual[</bB>]*(5)/<a href="virtual.5.html">&<\/a>/
        s/[<bB>]*virtual[</bB>]*(8)/<a href="virtual.8.html">&<\/a>/
        s/\(<a href="[^"]*">\)\([<bB>]*[a-z0-9-]*[-</bB>]*\)\(\n *\)\([<bB>]*[a-z0-9-]*[</bB>]*([0-9])\)\(<\/a>\)/\1\2\5\3\1\4\5/
index 319924c464c98ef0ec6579a5a824c11d05aa6610..c88e30bdf8b9f4c9b87e85ad2464182508f52766 100644 (file)
@@ -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
index 7b9cb3df4b6665b454a9e85d5addbc879c587539..7c182372a81a4c98c8b419387cd12e9556fce6ee 100644 (file)
@@ -6,10 +6,11 @@
 /* SYNOPSIS
 /*     #include <clnt_stream.h>
 /*
-/*     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
 /*     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);
index a3d480a1707857c22b51292c691923af029ad20a..0d3ee4775882a0833e664ea4322798e927af53c2 100644 (file)
@@ -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 (file)
index 0000000..626eb9a
--- /dev/null
@@ -0,0 +1,237 @@
+/*++
+/* NAME
+/*     dict_proxy 3
+/* SUMMARY
+/*     generic dictionary proxy client
+/* SYNOPSIS
+/*     #include <dict_proxy.h>
+/*
+/*     DICT    *dict_proxy_open(map, open_flags, dict_flags)
+/*     const char *map;
+/*     int     dummy;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_proxy_open() relays read-only operations through
+/*     the Postfix proxymap server.
+/*
+/*     The \fIopen_flags\fR argument must specify O_RDONLY.
+/*
+/*     The connection to the Postfix proxymap server is automatically
+/*     closed after $ipc_idle seconds of idle time.
+/* SECURITY
+/*      The proxy map server is not meant to be a trusted process. Proxy
+/*     maps must not be used to look up security sensitive information
+/*     such as user/group IDs, output files, or external commands.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/*     clnt_stream(3) client endpoint connection management
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory, unimplemented operation,
+/*     bad request parameter.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <stringops.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <attr.h>
+#include <dict.h>
+
+/* Global library. */
+
+#include <mail_proto.h>
+#include <mail_params.h>
+#include <clnt_stream.h>
+#include <dict_proxy.h>
+
+/* Application-specific. */
+
+typedef struct {
+    DICT    dict;                      /* generic members */
+    int     in_flags;                  /* caller-specified flags */
+    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 (file)
index 0000000..50932b0
--- /dev/null
@@ -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 <dict_proxy.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+#define DICT_TYPE_PROXY        "proxy"
+
+extern DICT *dict_proxy_open(const char *, int, int);
+
+ /*
+  * Protocol interface.
+  */
+#define PROXY_REQ_OPEN         "open"
+#define PROXY_REQ_LOOKUP       "lookup"
+
+#define PROXY_STAT_OK          0
+#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 (file)
index 0000000..a576f58
--- /dev/null
@@ -0,0 +1,57 @@
+/*++
+/* NAME
+/*     mail_dict 3
+/* SUMMARY
+/*     register application-specific dictionaries
+/* SYNOPSIS
+/*     #include <mail_dict.h>
+/*
+/*     void    mail_dict_init()
+/* DESCRIPTION
+/*     This module registers dictionary types that depend on higher-level
+/*     Postfix-specific interfaces and protocols.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <dict.h>
+#include <msg.h>
+
+/* Global library. */
+
+#include <dict_proxy.h>
+#include <mail_dict.h>
+
+typedef struct {
+    char   *type;
+    struct DICT *(*open) (const char *, int, int);
+} DICT_OPEN_INFO;
+
+static DICT_OPEN_INFO dict_open_info[] = {
+    DICT_TYPE_PROXY, dict_proxy_open,
+    /* XXX LDAP and MYSQL etc. should go here, too. */
+    0,
+};
+
+/* mail_dict_init - dictionaries that depend on Postfix-specific interfaces */
+
+void    mail_dict_init(void)
+{
+    DICT_OPEN_INFO *dp;
+
+    for (dp = dict_open_info; dp->type; dp++)
+       dict_open_register(dp->type, dp->open);
+}
diff --git a/postfix/src/global/mail_dict.h b/postfix/src/global/mail_dict.h
new file mode 100644 (file)
index 0000000..62ad881
--- /dev/null
@@ -0,0 +1,25 @@
+/*++
+/* NAME
+/*     mail_dict 3h
+/* SUMMARY
+/*     register application-specific dictionaries
+/* SYNOPSIS
+/*     #include <mail_dict.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * External interface.
+  */
+extern void mail_dict_init(void);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
index 6d8389974c54aaed4a2c9357722b48c4c58aa3f4..8c2463b804dda201dbd610182d51a449b4e33c1f 100644 (file)
@@ -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,
index 9c004ec7f80732112933ac6e0d9d64fb82159857..554e94a03f95179201761b7f4cd994e771878b76 100644 (file)
@@ -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.
   */
index 2b55f5cf8e89fbbe2f881a7d13b072ce0031432f..7cb0dd4c69e0fff634b5562c99e300b5ed876ae7 100644 (file)
@@ -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.
index 6186cb5323fc123ce33667d6b3912763b66dcfc2..8c770247ecad3e64d087ee51f13692e902a537b7 100644 (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      "20030101"
+#define MAIL_RELEASE_DATE      "20030103"
 
 #define VAR_MAIL_VERSION       "mail_version"
 #define DEF_MAIL_VERSION       "2.0.0-" MAIL_RELEASE_DATE
index 82edbb0ccb66c195aa9fe39a145478f5dddeb554..c9f6a05c4a84ef7777fadcdcb380ace76f5a4cd2 100644 (file)
 /*     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;
 /*     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.
 
 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)
index d6be6b1aab076b555a367e2a470efff6bb62a890..015811f699ebc7e1363b9f8e86ef38e77d111103 100644 (file)
 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 *);
 
index 4d739609f2899e00efdd2bbfa613b8d959507bee..41cd78584fd11aab43bce6b6c235f972e6d86e83 100644 (file)
@@ -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);
index 8e07dba78548981f0308075c785622ed88a47ad4..ce7850d9ee2298d6e0384449f39537175ea6d011 100644 (file)
@@ -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);
index 31532a35792399a91bb2e2c5fc4c403ed7b82e86..878df8f9e1d66d6e3174fa38b15181d59e5d30c6 100644 (file)
@@ -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 */
index 332cc8e04fa9c27a49b5c8f331f5b237e5f1a507..c911737ec58ea08c2aef63155db6013ac9492662 100644 (file)
@@ -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
index 4261413b870cb017ce8ead81c4b976d19a71b4c0..2cf89f6c84ec207ce70d5763823c76ce6e020b79 100644 (file)
@@ -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))
 
index b0615286d33d594dbed4b0ba0b9f08bc4ce96b6b..7b45845474ae701ee915ad674e935797fe587cbe 100644 (file)
@@ -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 */
index cf646935e72269dea04e1fb6bb70832542499a5b..eeb2ce986dd059f3690fd21ed27b83b768a68d0d 100644 (file)
@@ -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
index 4275c0c65682a543d54cb946f161052f07e6d626..9fdbd657b45acd507d47d4e4dc76901a083c8a7e 100644 (file)
 /*     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
 #include <debug_process.h>
 #include <mail_params.h>
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <timed_ipc.h>
 #include <resolve_local.h>
 #include <mail_flow.h>
@@ -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,
index 077d8cc702cdc065a9b9a74e70ec06be3488e24d..9e269e98d88fdac5cccaf345961de36d71dffaf3 100644 (file)
 #include <mail_task.h>
 #include <debug_process.h>
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <timed_ipc.h>
 #include <resolve_local.h>
 #include <mail_flow.h>
@@ -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.
index 08d42bf18cca43caee3d9ecaf7651b56123c7150..685973a07e279d367a632f179e74308c16a06841 100644 (file)
 #include <mail_task.h>
 #include <debug_process.h>
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <resolve_local.h>
 #include <mail_flow.h>
 
@@ -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.
index 465ba2c3819c24d93fdc2fa6c909a84fcc8238d5..acb8e86b9823428541d13bd4a692645e678abac7 100644 (file)
@@ -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
index cadb61a7fd4e5d0a272b4d691ef44852d72d7c01..4a88d6e25d6c47de6879f101679cf556599fcd13 100644 (file)
 
 #include <tok822.h>
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <mail_params.h>
 #include <mkmap.h>
 
@@ -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
index 7732636b8967d609fba76e813fa725eca93b401b..198be229e750908fff0cba8e4d6ff5ace7b3aa8a 100644 (file)
@@ -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
index 662c66b1d6ccc2a44de73b6c6c922690170ccfcf..91854d52223132d34719941662f1dac6c97facba 100644 (file)
 /*     stale lock files that were left behind after abnormal termination.
 /* .RE
 /* .IP \fB-m\fR
-/*     List the names of all supported lookup table types.
+/*     List the names of all supported lookup table types. Postfix
+/*     lookup tables are specified as \fItype\fB:\fIname\fR, where
+/*     \fItype\fR is one of the types listed below. The table \fIname\fR
+/*     syntax depends on the lookup table type.
 /* .RS
 /* .IP \fBbtree\fR
 /*     A sorted, balanced tree structure.
 /* .IP "\fBpcre\fR (read-only)"
 /*     A lookup table based on Perl Compatible Regular Expressions. The
 /*     file format is described in \fBpcre_table\fR(5).
+/* .IP "\fBproxy\fR (read-only)"
+/*     A lookup table that is implemented via the Postfix
+/*     \fBproxymap\fR(8) service. The table name syntax is
+/*     \fItype\fB:\fIname\fR.
 /* .IP "\fBregexp\fR (read-only)"
 /*     A lookup table based on regular expressions. The file format is
 /*     described in \fBregexp_table\fR(5).
 
 #include <mynetworks.h>
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <mail_proto.h>
 #include <mail_version.h>
 #include <mail_params.h>
@@ -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();
     }
 
index 66ebf9f744bccf73b26c28235a0b1bc37045aa41..5dbb4ccfe3b535485f180a3d1c1b003a04a5c9a8 100644 (file)
@@ -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
index 0d7ad8400cd8c9ab321bcb3121b3337c2171b213..cd3d6887e0079487f8edc4c4f63bbc125564f8e5 100644 (file)
 /* Global library. */
 
 #include <mail_conf.h>
+#include <mail_dict.h>
 #include <mail_params.h>
 #include <mkmap.h>
 
@@ -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 (symlink)
index 0000000..5c837ec
--- /dev/null
@@ -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 (file)
index 0000000..5ee7d59
--- /dev/null
@@ -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 (file)
index 0000000..d295075
--- /dev/null
@@ -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 <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mymalloc.h>
+#include <vstring.h>
+#include <htable.h>
+#include <stringops.h>
+#include <dict.h>
+
+/* Global library. */
+
+#include <mail_conf.h>
+#include <mail_params.h>
+#include <mail_proto.h>
+#include <dict_proxy.h>
+
+/* Server skeleton. */
+
+#include <mail_server.h>
+
+/* Application-specific. */
+
+ /*
+  * XXX All but the last are needed here so that $name expansion dependencies
+  * aren't too broken. The fix is to gather all parameter default settings in
+  * one place.
+  */
+char   *var_local_rcpt_maps;
+char   *var_virt_alias_maps;
+char   *var_virt_alias_doms;
+char   *var_virt_mbox_maps;
+char   *var_virt_mbox_doms;
+char   *var_relay_rcpt_maps;
+char   *var_relay_domains;
+char   *var_canonical_maps;
+char   *var_send_canon_maps;
+char   *var_rcpt_canon_maps;
+char   *var_relocatedmaps;
+char   *var_transport_maps;
+char   *var_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);
+}
index 6e89221adcee4a8eb63bd30126e1ad9124852695..b69f482b04d61b8c089c1232f6410dc4af4d62ca 100644 (file)
 /* .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
index 16071a69217b6205f821e7a34cce8f61ef09052b..546420dd2a9a11f1401c0629240103214b2e0989 100644 (file)
@@ -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;
index cc8e5953040d46ea0c6e83ce7ff6da15d616c48e..02d83a02c2209800645c546e3deb63771973607a 100644 (file)
 /*     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:
 #include <post_mail.h>
 #include <verify_clnt.h>
 
-/* Single server skeleton. */
+/* Server skeleton. */
 
 #include <mail_server.h>
 
@@ -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)
 {
index 0ae16d2e7e551144f5c4973bc36684b787b641c8..49ed051dfbcc520d866a418518ffd287b2f34673 100644 (file)
 /*     For security reasons, regular expression maps are allowed but
 /*     regular expression substitution of $1 etc. is disallowed,
 /*     because that would open a security hole.
+/*
+/*     For security reasons, proxied table lookup is not allowed,
+/*     because that would open a security hole.
 /* .IP \fBvirtual_mailbox_domains\fR
 /*     The list of domains that should be delivered via the Postfix virtual
 /*     delivery agent. This uses the same syntax as the \fBmydestination\fR
 /*     For security reasons, regular expression maps are allowed but
 /*     regular expression substitution of $1 etc. is disallowed,
 /*     because that would open a security hole.
+/*
+/*     For security reasons, proxied table lookup is not allowed,
+/*     because that would open a security hole.
 /* .IP \fBvirtual_gid_maps\fR
 /*     Recipients are looked up in these maps to determine the group ID to be
 /*     used when writing to the target mailbox.
 /*     For security reasons, regular expression maps are allowed but
 /*     regular expression substitution of $1 etc. is disallowed,
 /*     because that would open a security hole.
+/*
+/*     For security reasons, proxied table lookup is not allowed,
+/*     because that would open a security hole.
 /* .SH "Locking controls"
 /* .ad
 /* .fi