]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.9-20111219
authorWietse Venema <wietse@porcupine.org>
Mon, 19 Dec 2011 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:37:48 +0000 (06:37 +0000)
52 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/README_FILES/DATABASE_README
postfix/RELEASE_NOTES
postfix/WISHLIST
postfix/html/DATABASE_README.html
postfix/html/postconf.1.html
postfix/html/qmqpd.8.html
postfix/man/man1/postconf.1
postfix/man/man8/qmqpd.8
postfix/proto/DATABASE_README.html
postfix/src/dns/dns_rr_eq_sa.ref
postfix/src/dns/dns_rr_to_pa.ref
postfix/src/dns/dns_rr_to_sa.ref
postfix/src/dns/dns_sa_to_rr.ref
postfix/src/flush/flush.c
postfix/src/global/Makefile.in
postfix/src/global/addr_match_list.c
postfix/src/global/addr_match_list.h
postfix/src/global/debug_peer.c
postfix/src/global/dict_memcache.c
postfix/src/global/domain_list.c
postfix/src/global/domain_list.h
postfix/src/global/flush_clnt.c
postfix/src/global/mail_version.h
postfix/src/global/namadr_list.c
postfix/src/global/namadr_list.h
postfix/src/global/namadr_list.in
postfix/src/global/namadr_list.ref
postfix/src/global/server_acl.c
postfix/src/global/server_acl.in [new file with mode: 0644]
postfix/src/global/server_acl.ref [new file with mode: 0644]
postfix/src/global/string_list.c
postfix/src/global/string_list.h
postfix/src/postconf/postconf.c
postfix/src/qmqpd/qmqpd.c
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.h
postfix/src/trivial-rewrite/resolve.c
postfix/src/util/Makefile.in
postfix/src/util/dict_fail.c [new file with mode: 0644]
postfix/src/util/dict_fail.h [new file with mode: 0644]
postfix/src/util/dict_open.c
postfix/src/util/dict_regexp.ref
postfix/src/util/dict_static.c
postfix/src/util/dict_test.c
postfix/src/util/match_list.c
postfix/src/util/match_list.h
postfix/src/util/match_ops.c
postfix/src/util/match_ops.h
postfix/src/util/myaddrinfo.ref

index d2e1c26f5ef75f30009a54cc232aa5c6d0895d82..097a67a2cfa475a95fa47f9ced5c47a30109e80a 100644 (file)
@@ -69,6 +69,7 @@
 -TDICT_DBM
 -TDICT_DEBUG
 -TDICT_ENV
+-TDICT_FAIL
 -TDICT_HT
 -TDICT_LDAP
 -TDICT_MC
 -TMASTER_STATUS
 -TMASTER_STR_WATCH
 -TMATCH_LIST
+-TMATCH_OPS
 -TMBLOCK
 -TMBOX
 -TMILTER
index 6afc09ae0f948d36d328e0278f8faf2da652bbf7..ea798e67636e994bf535c4ebc9ccb8fe1ea7a0e7 100644 (file)
@@ -17372,3 +17372,33 @@ Apologies for any names omitted.
        Incompatibility: the Postfix SMTP server now always checks
        the smtpd_sender_login_maps table, even without having
        "smtpd_sasl_auth_enable = yes" in main.cf.
+
+20111219
+
+       Cleanup: the match_list-based primitives now provide an
+       option to return an error result instead of terminating the
+       process with a fatal error.  Files: util/match_ops.[hc],
+       util/match_list.c, global/addr_list_match.c, domain_list.c,
+       string_list.c, namadr_list.c.
+
+       Cleanup: a "fail:" database type that reliably fails all
+       requests. The lookup table name specifies the internal error
+       result code. having this table facilitates a systematic
+       review of all Postfix table lookup error handling.
+
+       Cleanup: trivial-rewrite now "catches" errors with implicit
+       database lookups in virtual_alias_domains, relay_domains,
+       virtual_mailbox_domains, just like it already caught explicit
+       database lookup errors. This means there are fewer occasions
+       where trivial-rewrite clients will appear to hang. File:
+       trivial-rewrite/resolve.c.
+
+       Cleanup: a broken relay_domains table would cause many
+       Postfix processes to terminate with fatal error. Postfix
+       now logs a warning instead. File: global/flush_clnt.c.
+
+       Cleanup: the Postfix SMTP server now "catches" some of the
+       errors with implicit database lookups in mynetworks and TLS
+       client certificate tables, and reports "server configuration
+       error" instead of terminating with a fatal error. This is
+       work in progress. Files: smtpd/smtpd.c, smtpd/smtpd_check.c.
index dcd3952944603a5b6897714aea913bf2d773e987..4353752c62add1096d477fc41d425b7c9e567397 100644 (file)
@@ -198,6 +198,10 @@ To find out what database types your Postfix system supports, use the "p\bpo\bos\bs
     e\ben\bnv\bvi\bir\bro\bon\bn
         The UNIX process environment array. The lookup key is the variable
         name. The lookup table name in "environ:table" is ignored.
+    f\bfa\bai\bil\bl (read-write)
+        A table that reliably fails all requests. The lookup table name
+        provides the internal error result code. This table exists to simplify
+        Postfix error tests.
     h\bha\bas\bsh\bh
         An indexed file type based on hashing. This is available only on
         systems with support for Berkeley DB databases. Database files are
index ab67e1f7513b953fdfaa7528ff9067fac6fbcd06..ae73b501599b68c5f881b1f63dc8fff132511250 100644 (file)
@@ -14,14 +14,14 @@ specifies the release date of a stable release or snapshot release.
 If you upgrade from Postfix 2.7 or earlier, read RELEASE_NOTES-2.8
 before proceeding.
 
-Incompatible changes with snapshot 201112XX
+Incompatible changes with snapshot 20111218
 ===========================================
 
 To support external SASL authentication, the Postfix SMTP server
 now always checks the smtpd_sender_login_maps table, even without
 having "smtpd_sasl_auth_enable = yes" in main.cf.
 
-Major changes with snapshot 201112XX
+Major changes with snapshot 20111218
 ====================================
 
 Support for external SASL authentication via the XCLIENT command.
index c38f721db1736bda5ac47f533b9a94f1b9edc107..4162c84ab9720c00d1a79f1ef70c105b39a21ce0 100644 (file)
@@ -7,6 +7,9 @@ Wish list:
        limits on attribute string length in IPC protocols. 10-20KB
        seems OK. We could start with limits enabled only in proxymap.
 
+       move flush_init() etc. from defer service clients to the
+       bounce daemon?
+
        Either make all void dict_* operations return an error code,
        or require that they reset dict_errno on entry, either exit
        with a fatal error or set dict_errno on error.
index f394976c51a14dcb3d26f3cd9c7a59aaa3172ac3..1beb1c89805bb05e354db27f81de77d7c2950e2a 100644 (file)
@@ -292,6 +292,12 @@ the ".dir" or ".pag" suffix.  </dd>
 variable name. The lookup table name in "environ:table" is ignored.
 </dd>
 
+<dt> <b>fail</b> (read-write) </dt>
+
+<dd> A table that reliably fails all requests. The lookup table
+name provides the internal error result code. This table exists to
+simplify Postfix error tests. </dd>
+
 <dt> <b>hash</b> </dt>
 
 <dd> An indexed file type based on hashing.  This is available only
index cf4086fc7802d0cea9a378e3f2e662f39ff364e5..63d1483e5842edf7dddaa08a4a059ce6a6867871 100644 (file)
@@ -181,8 +181,13 @@ POSTCONF(1)                                                        POSTCONF(1)
                      implemented  for  testing,  someone may find
                      this useful someday.
 
+              <b>fail</b>   A table that reliably  fails  all  requests.
+                     The  lookup table name provides the internal
+                     error result code. This table exists to sim-
+                     plify Postfix error tests.
+
               <b>hash</b>   An indexed file type based on hashing.  This
-                     is  available  on  systems  with support for
+                     is available on  systems  with  support  for
                      Berkeley DB databases.
 
               <b>internal</b>
@@ -190,7 +195,7 @@ POSTCONF(1)                                                        POSTCONF(1)
                      tent are lost when a process terminates.
 
               <b>ldap</b> (read-only)
-                     Perform  lookups  using  the  LDAP protocol.
+                     Perform lookups  using  the  LDAP  protocol.
                      This is described in <a href="ldap_table.5.html"><b>ldap_table</b>(5)</a>.
 
               <b>memcache</b> (read-write)
@@ -198,126 +203,126 @@ POSTCONF(1)                                                        POSTCONF(1)
                      This is described in <a href="memcache_table.5.html"><b>memcache_table</b>(5)</a>.
 
               <b>mysql</b> (read-only)
-                     Perform  lookups  using  the MYSQL protocol.
+                     Perform lookups using  the  MYSQL  protocol.
                      This is described in <a href="mysql_table.5.html"><b>mysql_table</b>(5)</a>.
 
               <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_table</b>(5)</a>.
 
               <b>pgsql</b> (read-only)
-                     Perform lookups using the PostgreSQL  proto-
+                     Perform  lookups using the PostgreSQL proto-
                      col. This is described in <a href="pgsql_table.5.html"><b>pgsql_table</b>(5)</a>.
 
               <b>proxy</b> (read-only)
-                     A  lookup  table that is implemented via the
-                     Postfix <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table  name
+                     A lookup table that is implemented  via  the
+                     Postfix  <a href="proxymap.8.html"><b>proxymap</b>(8)</a> service. The table name
                      syntax is <i>type</i><b>:</b><i>name</i>.
 
               <b>regexp</b> (read-only)
                      A lookup table based on regular expressions.
-                     The file format is described  in  <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
+                     The  file  format is described in <a href="regexp_table.5.html"><b>regexp_ta-</b></a>
                      <a href="regexp_table.5.html"><b>ble</b>(5)</a>.
 
               <b>sdbm</b>   An indexed file type based on hashing.  This
-                     is available on  systems  with  support  for
+                     is  available  on  systems  with support for
                      SDBM databases.
 
               <b>sqlite</b> (read-only)
-                     Perform  lookups from SQLite database files.
+                     Perform lookups from SQLite database  files.
                      This is described in <a href="sqlite_table.5.html"><b>sqlite_table</b>(5)</a>.
 
               <b>static</b> (read-only)
-                     A table that  always  returns  its  name  as
-                     lookup  result.  For  example, <b><a href="DATABASE_README.html#types">static</a>:foobar</b>
-                     always returns the string <b>foobar</b>  as  lookup
+                     A  table  that  always  returns  its name as
+                     lookup result.  For  example,  <b><a href="DATABASE_README.html#types">static</a>:foobar</b>
+                     always  returns  the string <b>foobar</b> as lookup
                      result.
 
               <b>tcp</b> (read-only)
                      Perform lookups using a simple request-reply
-                     protocol that is described in  <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
+                     protocol  that is described in <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.
 
               <b>texthash</b> (read-only)
-                     Produces  similar  results  as  hash: files,
+                     Produces similar  results  as  hash:  files,
                      except  that  you  don't  need  to  run  the
-                     <a href="postmap.1.html"><b>postmap</b>(1)</a>  command  before  you can use the
-                     file, and that it does  not  detect  changes
+                     <a href="postmap.1.html"><b>postmap</b>(1)</a> command before you  can  use  the
+                     file,  and  that  it does not detect changes
                      after the file is read.
 
               <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 data-
-                            base. The key is a login  name.   The
-                            result  is  a  password file entry in
+                            The table is the UNIX password  data-
+                            base.  The  key is a login name.  The
+                            result is a password  file  entry  in
                             <b>passwd</b>(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  <b>group</b>(5)
+                            The key is a group name.  The  result
+                            is  a  group  file  entry in <b>group</b>(5)
                             format.
 
-              Other  table types may exist depending on how Post-
+              Other table types may exist depending on how  Post-
               fix was built.
 
-       <b>-M</b>     Show <a href="master.5.html"><b>master.cf</b></a> file  contents  instead  of  <a href="postconf.5.html"><b>main.cf</b></a>
-              file  contents.  Specify <b>-Mf</b> to fold long lines for
+       <b>-M</b>     Show  <a href="master.5.html"><b>master.cf</b></a>  file  contents  instead of <a href="postconf.5.html"><b>main.cf</b></a>
+              file contents.  Specify <b>-Mf</b> to fold long lines  for
               human readability.
 
               If <i>service ...</i> is specified, only the matching ser-
-              vices  will  be  output. For example, "<b>postconf -Mf</b>
-              <b>inet</b>" will output all services that listen  on  the
+              vices will be output. For  example,  "<b>postconf  -Mf</b>
+              <b>inet</b>"  will  output all services that listen on the
               network.
 
-              Specify  zero  or  more arguments, each with a <i>ser-</i>
-              <i>vice-type</i> name (<b>inet</b>, <b>unix</b>, <b>fifo</b>, or <b>pass</b>) or  with
-              a  <i>service-name.service-type</i>  pair,  where <i>service-</i>
+              Specify zero or more arguments, each  with  a  <i>ser-</i>
+              <i>vice-type</i>  name (<b>inet</b>, <b>unix</b>, <b>fifo</b>, or <b>pass</b>) or with
+              a <i>service-name.service-type</i>  pair,  where  <i>service-</i>
               <i>name</i> is the first field of a <a href="master.5.html">master.cf</a> entry.
 
-              This feature is  available  with  Postfix  2.9  and
+              This  feature  is  available  with  Postfix 2.9 and
               later.
 
-       <b>-n</b>     Print  <a href="postconf.5.html"><b>main.cf</b></a>  parameter settings that are explic-
-              itly specified in <a href="postconf.5.html"><b>main.cf</b></a>.   Specify  <b>-nf</b>  to  fold
-              long  lines  for human readability (Postfix 2.9 and
+       <b>-n</b>     Print <a href="postconf.5.html"><b>main.cf</b></a> parameter settings that  are  explic-
+              itly  specified  in  <a href="postconf.5.html"><b>main.cf</b></a>.   Specify <b>-nf</b> to fold
+              long lines for human readability (Postfix  2.9  and
               later).
 
        <b>-t</b> [<i>template</i><b>_</b><i>file</i>]
-              Display the templates for text that appears at  the
-              beginning  of  delivery  status  notification (DSN)
+              Display  the templates for text that appears at the
+              beginning of  delivery  status  notification  (DSN)
               messages, without expanding $<b>name</b> expressions.
 
-              To override the built-in templates, specify a  tem-
-              plate  file name at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a> com-
-              mand line, or specify a file name in  <a href="postconf.5.html"><b>main.cf</b></a>  with
+              To  override the built-in templates, specify a tem-
+              plate file name at the end of the <a href="postconf.1.html"><b>postconf</b>(1)</a>  com-
+              mand  line,  or specify a file name in <a href="postconf.5.html"><b>main.cf</b></a> with
               the <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a></b> parameter.
 
               To force selection of the built-in templates, spec-
-              ify an empty template file name on the  <a href="postconf.1.html"><b>postconf</b>(1)</a>
+              ify  an empty template file name on the <a href="postconf.1.html"><b>postconf</b>(1)</a>
               command line (in shell language: "").
 
-              This  feature  is  available  with  Postfix 2.3 and
+              This feature is  available  with  Postfix  2.3  and
               later.
 
        <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>-#</b>     Edit the <a href="postconf.5.html"><b>main.cf</b></a> configuration  file,  and  comment
+       <b>-#</b>     Edit  the  <a href="postconf.5.html"><b>main.cf</b></a>  configuration file, and comment
               out the parameters given on the <a href="postconf.1.html"><b>postconf</b>(1)</a> command
-              line, so that  those  parameters  revert  to  their
-              default  values.  The file is copied to a temporary
-              file then renamed into place.  Specify  a  list  of
+              line,  so  that  those  parameters  revert to their
+              default values.  The file is copied to a  temporary
+              file  then  renamed  into place.  Specify a list of
               parameter names, not <i>name</i>=<i>value</i> pairs.  There is no
-              <a href="postconf.1.html"><b>postconf</b>(1)</a> command to perform the  reverse  opera-
+              <a href="postconf.1.html"><b>postconf</b>(1)</a>  command  to perform the reverse opera-
               tion.
 
-              This  feature  is  available  with  Postfix 2.6 and
+              This feature is  available  with  Postfix  2.6  and
               later.
 
 <b>DIAGNOSTICS</b>
@@ -328,18 +333,18 @@ POSTCONF(1)                                                        POSTCONF(1)
               Directory with Postfix configuration files.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <a href="postconf.5.html"><b>main.cf</b></a> parameters are  especially  relevant
+       The  following  <a href="postconf.5.html"><b>main.cf</b></a> parameters are especially relevant
        to this program.
 
-       The  text  below  provides  only  a parameter summary. See
+       The text below provides  only  a  parameter  summary.  See
        <a href="postconf.5.html"><b>postconf</b>(5)</a> for more details including examples.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#bounce_template_file">bounce_template_file</a> (empty)</b>
-              Pathname  of  a configuration file with bounce mes-
+              Pathname of a configuration file with  bounce  mes-
               sage templates.
 
 <b>FILES</b>
@@ -355,7 +360,7 @@ POSTCONF(1)                                                        POSTCONF(1)
        <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
 
 <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 94eac6a42e56512b8216ac9a8d518be50c4928a7..47f1c0fbc041355f36ff89d672f5bf18625a74e2 100644 (file)
@@ -95,17 +95,17 @@ QMQPD(8)                                                              QMQPD(8)
 
 <b>TARPIT CONTROLS</b>
        <b><a href="postconf.5.html#qmqpd_error_delay">qmqpd_error_delay</a> (1s)</b>
-              How  long the QMQP server will pause before sending
-              a negative reply to the client.
+              How  long the Postfix QMQP server will pause before
+              sending a negative reply to the remote QMQP client.
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  <a href="postconf.5.html">main.cf</a>  and
+              The  default  location  of  the Postfix <a href="postconf.5.html">main.cf</a> and
               <a href="master.5.html">master.cf</a> configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How  much time a Postfix daemon process may take to
-              handle a request  before  it  is  terminated  by  a
+              How much time a Postfix daemon process may take  to
+              handle  a  request  before  it  is  terminated by a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
@@ -113,48 +113,48 @@ QMQPD(8)                                                              QMQPD(8)
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time  that  an  idle  Postfix
-              daemon  process  waits  for  an incoming connection
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits  for  an  incoming  connection
               before terminating voluntarily.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of incoming connections  that  a
-              Postfix  daemon  process will service before termi-
+              The  maximal  number of incoming connections that a
+              Postfix daemon process will service  before  termi-
               nating voluntarily.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The process ID  of  a  Postfix  command  or  daemon
+              The  process  ID  of  a  Postfix  command or daemon
               process.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The  process  name  of  a Postfix command or daemon
+              The process name of a  Postfix  command  or  daemon
               process.
 
        <b><a href="postconf.5.html#qmqpd_authorized_clients">qmqpd_authorized_clients</a> (empty)</b>
-              What clients are allowed to  connect  to  the  QMQP
-              server port.
+              What  remote QMQP clients are allowed to connect to
+              the Postfix QMQP server port.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The  location of the Postfix top-level queue direc-
+              The location of the Postfix top-level queue  direc-
               tory.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (see 'postconf -d' output)</b>
-              The mail system  name  that  is  prepended  to  the
-              process  name  in  syslog  records, so that "smtpd"
+              The  mail  system  name  that  is  prepended to the
+              process name in syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
        <b><a href="postconf.5.html#verp_delimiter_filter">verp_delimiter_filter</a> (-=+)</b>
-              The characters Postfix accepts  as  VERP  delimiter
-              characters  on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command line
+              The  characters  Postfix  accepts as VERP delimiter
+              characters on the Postfix <a href="sendmail.1.html"><b>sendmail</b>(1)</a> command  line
               and in SMTP commands.
 
        Available in Postfix version 2.5 and later:
 
        <b><a href="postconf.5.html#qmqpd_client_port_logging">qmqpd_client_port_logging</a> (no)</b>
-              Enable logging of the remote QMQP  client  port  in
+              Enable  logging  of  the remote QMQP client port in
               addition to the hostname and IP address.
 
 <b>SEE ALSO</b>
@@ -167,7 +167,7 @@ QMQPD(8)                                                              QMQPD(8)
        <a href="QMQP_README.html">QMQP_README</a>, Postfix ezmlm-idx howto.
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>HISTORY</b>
index c2a83503fd69f9679471f319d5ac0ae3467f430c..3711f8dd2f9f3dc6d83edb4f2e1e2433e049340e 100644 (file)
@@ -171,6 +171,10 @@ This is available on systems with support for DBM databases.
 The UNIX process environment array. The lookup key is the variable
 name. Originally implemented for testing, someone may find this
 useful someday.
+.IP \fBfail\fR
+A table that reliably fails all requests. The lookup table
+name provides the internal error result code. This table
+exists to simplify Postfix error tests.
 .IP \fBhash\fR
 An indexed file type based on hashing.
 This is available on systems with support for Berkeley DB
index ca193b2057aa1e3fda170efed7e6b813a26e61e2..758a5dcab367e8f5cc4e8febd53b9836695cfcba 100644 (file)
@@ -102,8 +102,8 @@ the sender.
 .ad
 .fi
 .IP "\fBqmqpd_error_delay (1s)\fR"
-How long the QMQP server will pause before sending a negative reply
-to the client.
+How long the Postfix QMQP server will pause before sending a negative
+reply to the remote QMQP client.
 .SH "MISCELLANEOUS CONTROLS"
 .na
 .nf
@@ -129,7 +129,8 @@ The process ID of a Postfix command or daemon process.
 .IP "\fBprocess_name (read-only)\fR"
 The process name of a Postfix command or daemon process.
 .IP "\fBqmqpd_authorized_clients (empty)\fR"
-What clients are allowed to connect to the QMQP server port.
+What remote QMQP clients are allowed to connect to the Postfix QMQP
+server port.
 .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
 The location of the Postfix top-level queue directory.
 .IP "\fBsyslog_facility (mail)\fR"
index 1b0237b3771deeb714c7844a0e9d0d4b6b1a7747..ca1627c74eab984f6d2ced6ce9955c0714e57c10 100644 (file)
@@ -292,6 +292,12 @@ the ".dir" or ".pag" suffix.  </dd>
 variable name. The lookup table name in "environ:table" is ignored.
 </dd>
 
+<dt> <b>fail</b> (read-write) </dt>
+
+<dd> A table that reliably fails all requests. The lookup table
+name provides the internal error result code. This table exists to
+simplify Postfix error tests. </dd>
+
 <dt> <b>hash</b> </dt>
 
 <dd> An indexed file type based on hashing.  This is available only
index 389164ff83f0981d019a185b9841acf64fed88a3..e633274a3d8dd2777dc6c1dfcb42ce3ec5c0e0d9 100644 (file)
@@ -1,22 +1,22 @@
-2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.2
+2604:8d00:189::2 =?= 168.100.189.2
 tested by function: no
 tested by macro:    no
 168.100.189.2 =?= 168.100.189.2
 tested by function: yes
 tested by macro:    yes
-2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.3
+2604:8d00:189::2 =?= 168.100.189.3
 tested by function: no
 tested by macro:    no
 168.100.189.2 =?= 168.100.189.3
 tested by function: no
 tested by macro:    no
-2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7
-tested by function: yes
-tested by macro:    yes
+2604:8d00:189::2 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7
+tested by function: no
+tested by macro:    no
 168.100.189.2 =?= 2001:240:587:0:2d0:b7ff:fe88:2ca7
 tested by function: no
 tested by macro:    no
-2001:240:587:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f
+2604:8d00:189::2 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f
 tested by function: no
 tested by macro:    no
 168.100.189.2 =?= 2001:240:587:0:2d0:b7ff:febe:ca9f
index 742c95a0f0467a8fc8915d44322b12b3e7001315..86c022d56a6aecc8832bf4ef2761f113d1e9948a 100644 (file)
@@ -1,2 +1,2 @@
 spike.porcupine.org -> 168.100.189.2
-spike.porcupine.org -> 2001:240:587:0:2d0:b7ff:fe88:2ca7
+spike.porcupine.org -> 2604:8d00:189::2
index b9f0c4eebd5ab573ff06abfda675d458c3c553a8..217b9a25308d6c7a889cbe790a3461fa7b8a82dc 100644 (file)
@@ -1,2 +1,2 @@
 spike.porcupine.org 25 -> 168.100.189.2 25
-spike.porcupine.org 25 -> 2001:240:587:0:2d0:b7ff:fe88:2ca7 25
+spike.porcupine.org 25 -> 2604:8d00:189::2 25
index e2f24ce772da88a998d4ac8e8fced0fdb10fa4a7..0b67b74e23388b89459aa4ebbf8c23749267483e 100644 (file)
@@ -1,2 +1,2 @@
-spike.porcupine.org -> 2001:240:587:0:2d0:b7ff:fe88:2ca7
+spike.porcupine.org -> 2604:8d00:189::2
 spike.porcupine.org -> 168.100.189.2
index 53a2c8f44a6a07c66d81c0043961a8306ca49120..a87a0f18c664a55050fd73e0c5afa3d6f933abd3 100644 (file)
@@ -280,7 +280,7 @@ static VSTRING *flush_site_to_path(VSTRING *path, const char *site)
 
 static int flush_policy_ok(const char *site)
 {
-    return (domain_list_match(flush_domains, site));
+    return (domain_list_match(flush_domains, site) > 0);
 }
 
 /* flush_add_service - append queue ID to per-site fast flush logfile */
@@ -810,7 +810,8 @@ static void flush_service(VSTREAM *client_stream, char *unused_service,
 
 static void pre_jail_init(char *unused_name, char **unused_argv)
 {
-    flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS),
+    flush_domains = domain_list_init(MATCH_FLAG_RETURN
+                                  | match_parent_style(VAR_FFLUSH_DOMAINS),
                                     var_fflush_domains);
 }
 
index 586d056460d759486e40a2b8dccd3e8f43f0c4ff..379d0e50fff77cd1b8c13a14858e2f1561e5ec0a 100644 (file)
@@ -308,7 +308,7 @@ server_acl: server_acl.c $(LIB) $(LIBS)
 tests: tok822_test mime_tests strip_addr_test tok822_limit_test \
        xtext_test scache_multi_test ehlo_mask_test \
        namadr_list_test mail_conf_time_test header_body_checks_tests \
-       mail_version_test
+       mail_version_test server_acl_test
 
 mime_tests: mime_test mime_nest mime_8bit mime_dom mime_trunc mime_cvt \
        mime_cvt2 mime_cvt3 mime_garb1 mime_garb2 mime_garb3 mime_garb4
@@ -405,6 +405,11 @@ mail_version_test: mail_version mail_version.in mail_version.ref
        diff  mail_version.ref mail_version.tmp
        rm -f mail_version.tmp
 
+server_acl_test: server_acl server_acl.in server_acl.ref
+       ./server_acl <server_acl.in >server_acl.tmp 2>&1
+       diff  server_acl.ref server_acl.tmp
+       rm -f server_acl.tmp
+
 # Requires: Postfix running, root privileges
 
 rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
index 7ba1166bbdc76d12e6d4b6e1b99414cfee051df6..ad1a249e319c7259ba2ba0e41fe40648f59a6bb3 100644 (file)
 /*     The matching process is case insensitive.
 /*
 /*     addr_match_list_init() performs initializations. The first
-/*     argument is MATCH_FLAG_NONE for future extension.
+/*     argument is the bit-wise OR of zero or more of the following:
+/* .IP MATCH_FLAG_RETURN
+/*      Request that addr_match_list_match() returns a negative result
+/*      (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a fatal
+/*      error.
+/* .PP
+/*     Specify MATCH_FLAG_NONE to request none of the above.
 /*     The second argument is a list of patterns, or the absolute
 /*     pathname of a file with patterns.
 /*
@@ -93,6 +99,7 @@ int     main(int argc, char **argv)
     ADDR_MATCH_LIST *list;
     char   *addr;
     int     ch;
+    int     rc;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
@@ -107,20 +114,21 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
-    list = addr_match_list_init(MATCH_FLAG_PARENT, argv[optind]);
+    list = addr_match_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     addr = argv[optind + 1];
     if (strcmp(addr, "-") == 0) {
        VSTRING *buf = vstring_alloc(100);
 
-       while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF)
+       while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) {
+           rc = addr_match_list_match(list, vstring_str(buf));
            vstream_printf("%s: %s\n", vstring_str(buf),
-                          addr_match_list_match(list, vstring_str(buf)) ?
-                          "YES" : "NO");
+                          rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR");
+       }
        vstring_free(buf);
     } else {
+       rc = addr_match_list_match(list, addr);
        vstream_printf("%s: %s\n", addr,
-                      addr_match_list_match(list, addr) ?
-                      "YES" : "NO");
+                      rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR");
     }
     vstream_fflush(VSTREAM_OUT);
     addr_match_list_free(list);
index d27c672b3f8e679af81035336a5849ec9e246a51..67c7e2316d81861c9fabc6b1f5a068c3b64d7ab5 100644 (file)
@@ -15,7 +15,6 @@
   * Utility library.
   */
 #include <match_list.h>
-#include <match_ops.h>
 
  /*
   * External interface.
index 97b42bd4e6e6c9553982c6471765ea533340ca55..bdd623bebf6013a68d85f028f14da30bab993799 100644 (file)
@@ -99,7 +99,8 @@ void    debug_peer_init(void)
      */
     if (*var_debug_peer_list)
        debug_peer_list =
-           namadr_list_init(match_parent_style(VAR_DEBUG_PEER_LIST),
+           namadr_list_init(MATCH_FLAG_RETURN
+                            | match_parent_style(VAR_DEBUG_PEER_LIST),
                             var_debug_peer_list);
 }
 
@@ -113,7 +114,7 @@ int     debug_peer_check(const char *name, const char *addr)
      */
     if (debug_peer_list != 0
        && saved_level == UNUSED_SAVED_LEVEL
-       && namadr_list_match(debug_peer_list, name, addr) != 0) {
+       && namadr_list_match(debug_peer_list, name, addr) > 0) {
        saved_level = msg_verbose;
        msg_verbose += var_debug_peer_level;
        return (1);
index 3fc6101c0d643474e77b538dedc010490d4fbcd6..9e64d1e1d48898c08f858e870a21a4b1ee818a6e 100644 (file)
@@ -152,27 +152,24 @@ static void dict_memcache_set(DICT_MC *dict_mc, const char *value, int ttl)
        if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
            if (errno == ECONNREFUSED)
                break;
+       } else if (memcache_printf(fp, "set %s %d %d %ld",
+               STR(dict_mc->key_buf), dict_mc->mc_flags, ttl, data_len) < 0
+                  || memcache_fwrite(fp, value, strlen(value)) < 0
+                  || memcache_get(fp, dict_mc->clnt_buf,
+                                  dict_mc->max_line) < 0) {
+           if (count > 0)
+               msg_warn(errno ? "database %s:%s: I/O error: %m" :
+                        "database %s:%s: I/O error",
+                        DICT_TYPE_MEMCACHE, dict_mc->dict.name);
+       } else if (strcmp(STR(dict_mc->clnt_buf), "STORED") != 0) {
+           if (count > 0)
+               msg_warn("database %s:%s: update failed: %.30s",
+                        DICT_TYPE_MEMCACHE, dict_mc->dict.name,
+                        STR(dict_mc->clnt_buf));
        } else {
-           if (memcache_printf(fp, "set %s %d %d %ld",
-                               STR(dict_mc->key_buf), dict_mc->mc_flags,
-                               ttl, data_len) < 0
-               || memcache_fwrite(fp, value, strlen(value)) < 0
-               || memcache_get(fp, dict_mc->clnt_buf,
-                               dict_mc->max_line) < 0) {
-               if (count > 0)
-                   msg_warn(errno ? "database %s:%s: I/O error: %m" :
-                            "database %s:%s: I/O error",
-                            DICT_TYPE_MEMCACHE, dict_mc->dict.name);
-           } else if (strcmp(STR(dict_mc->clnt_buf), "STORED") != 0) {
-               if (count > 0)
-                   msg_warn("database %s:%s: update failed: %.30s",
-                            DICT_TYPE_MEMCACHE, dict_mc->dict.name,
-                            STR(dict_mc->clnt_buf));
-           } else {
-               /* Victory! */
-               dict_mc->mc_errno = 0;
-               break;
-           }
+           /* Victory! */
+           dict_mc->mc_errno = 0;
+           break;
        }
        auto_clnt_recover(dict_mc->clnt);
     }
@@ -195,36 +192,34 @@ static const char *dict_memcache_get(DICT_MC *dict_mc)
        if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
            if (errno == ECONNREFUSED)
                break;
-       } else {
-           if (memcache_printf(fp, "get %s", STR(dict_mc->key_buf)) < 0
+       } else if (memcache_printf(fp, "get %s", STR(dict_mc->key_buf)) < 0
            || memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) {
-               if (count > 0)
-                   msg_warn(errno ? "database %s:%s: I/O error: %m" :
-                            "database %s:%s: I/O error",
-                            DICT_TYPE_MEMCACHE, dict_mc->dict.name);
-           } else if (strcmp(STR(dict_mc->clnt_buf), "END") == 0) {
-               /* Not found. */
-               dict_mc->mc_errno = 0;
-               break;
-           } else if (sscanf(STR(dict_mc->clnt_buf),
-                             "VALUE %*s %*s %ld", &todo) != 1
-                      || todo < 0 || todo > dict_mc->max_data) {
-               if (count > 0)
-                   msg_warn("%s: unexpected memcache server reply: %.30s",
-                            dict_mc->dict.name, STR(dict_mc->clnt_buf));
-           } else if (memcache_fread(fp, dict_mc->res_buf, todo) < 0) {
-               if (count > 0)
-                   msg_warn("%s: EOF receiving memcache server reply",
-                            dict_mc->dict.name);
-           } else {
-               /* Victory! */
-               retval = STR(dict_mc->res_buf);
-               dict_mc->mc_errno = 0;
-               if (memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0
-                   || strcmp(STR(dict_mc->clnt_buf), "END") != 0)
-                   auto_clnt_recover(dict_mc->clnt);
-               break;
-           }
+           if (count > 0)
+               msg_warn(errno ? "database %s:%s: I/O error: %m" :
+                        "database %s:%s: I/O error",
+                        DICT_TYPE_MEMCACHE, dict_mc->dict.name);
+       } else if (strcmp(STR(dict_mc->clnt_buf), "END") == 0) {
+           /* Not found. */
+           dict_mc->mc_errno = 0;
+           break;
+       } else if (sscanf(STR(dict_mc->clnt_buf),
+                         "VALUE %*s %*s %ld", &todo) != 1
+                  || todo < 0 || todo > dict_mc->max_data) {
+           if (count > 0)
+               msg_warn("%s: unexpected memcache server reply: %.30s",
+                        dict_mc->dict.name, STR(dict_mc->clnt_buf));
+       } else if (memcache_fread(fp, dict_mc->res_buf, todo) < 0) {
+           if (count > 0)
+               msg_warn("%s: EOF receiving memcache server reply",
+                        dict_mc->dict.name);
+       } else {
+           /* Victory! */
+           retval = STR(dict_mc->res_buf);
+           dict_mc->mc_errno = 0;
+           if (memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0
+               || strcmp(STR(dict_mc->clnt_buf), "END") != 0)
+               auto_clnt_recover(dict_mc->clnt);
+           break;
        }
        auto_clnt_recover(dict_mc->clnt);
     }
@@ -246,30 +241,27 @@ static int dict_memcache_del(DICT_MC *dict_mc)
        if ((fp = auto_clnt_access(dict_mc->clnt)) == 0) {
            if (errno == ECONNREFUSED)
                break;
+       } else if (memcache_printf(fp, "delete %s", STR(dict_mc->key_buf)) < 0
+           || memcache_get(fp, dict_mc->clnt_buf, dict_mc->max_line) < 0) {
+           if (count > 0)
+               msg_warn(errno ? "database %s:%s: I/O error: %m" :
+                        "database %s:%s: I/O error",
+                        DICT_TYPE_MEMCACHE, dict_mc->dict.name);
+       } else if (strcmp(STR(dict_mc->clnt_buf), "DELETED") == 0) {
+           /* Victory! */
+           dict_mc->mc_errno = 0;
+           retval = 0;
+           break;
+       } else if (strcmp(STR(dict_mc->clnt_buf), "NOT_FOUND") == 0) {
+           /* Not found! */
+           dict_mc->mc_errno = 0;
+           retval = 1;
+           break;
        } else {
-           if (memcache_printf(fp, "delete %s", STR(dict_mc->key_buf)) < 0
-               || memcache_get(fp, dict_mc->clnt_buf,
-                               dict_mc->max_line) < 0) {
-               if (count > 0)
-                   msg_warn(errno ? "database %s:%s: I/O error: %m" :
-                            "database %s:%s: I/O error",
-                            DICT_TYPE_MEMCACHE, dict_mc->dict.name);
-           } else if (strcmp(STR(dict_mc->clnt_buf), "DELETED") == 0) {
-               /* Victory! */
-               dict_mc->mc_errno = 0;
-               retval = 0;
-               break;
-           } else if (strcmp(STR(dict_mc->clnt_buf), "NOT_FOUND") == 0) {
-               /* Not found! */
-               dict_mc->mc_errno = 0;
-               retval = 1;
-               break;
-           } else {
-               if (count > 0)
-                   msg_warn("database %s:%s: delete failed: %.30s",
-                            DICT_TYPE_MEMCACHE, dict_mc->dict.name,
-                            STR(dict_mc->clnt_buf));
-           }
+           if (count > 0)
+               msg_warn("database %s:%s: delete failed: %.30s",
+                        DICT_TYPE_MEMCACHE, dict_mc->dict.name,
+                        STR(dict_mc->clnt_buf));
        }
        auto_clnt_recover(dict_mc->clnt);
     }
index 9535ac223f4f4c4b9efbcaa4df92811a621a323f..57c3c1d66143f0bac64e5a8751c13a0e0051401a 100644 (file)
 /*
 /*     domain_list_init() performs initializations. The first argument
 /*     is the bit-wise OR of zero or more of the following:
-/* .RS
 /* .IP MATCH_FLAG_PARENT
 /*      The hostname pattern foo.com matches itself and any name below
 /*      the domain foo.com. If this flag is cleared, foo.com matches itself
 /*     only, and .foo.com matches any name below the domain foo.com.
-/* .RE
+/* .IP MATCH_FLAG_RETURN
+/*     Request that domain_list_match() returns a negative result
+/*     (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a
+/*     fatal error.
+/* .PP
 /*     Specify MATCH_FLAG_NONE to request none of the above.
 /*     The second argument is a list of domain patterns, or the name of
 /*     a file containing domain patterns.
@@ -96,6 +99,7 @@ int     main(int argc, char **argv)
     DOMAIN_LIST *list;
     char   *host;
     int     ch;
+    int     rc;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
@@ -110,10 +114,11 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
-    list = domain_list_init(MATCH_FLAG_PARENT, argv[optind]);
+    list = domain_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     host = argv[optind + 1];
-    vstream_printf("%s: %s\n", host, domain_list_match(list, host) ?
-                  "YES" : "NO");
+    rc = domain_list_match(list, host);
+    vstream_printf("%s: %s\n", host,
+                  rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR");
     vstream_fflush(VSTREAM_OUT);
     domain_list_free(list);
     return (0);
index 23f60c78950a1693adb9f8f021a82f8d3bc1a3f1..8612219d9cd8ca65477fcc221fc062820aa1c3c2 100644 (file)
@@ -15,7 +15,6 @@
   * Utility library.
   */
 #include <match_list.h>
-#include <match_ops.h>
 
  /*
   * External interface.
index 043754f9b5667d4fcc9e1aee9140020931bda418..d7a51f9fec4163192d68a6cd88a125a8437684f0 100644 (file)
@@ -103,7 +103,8 @@ static DOMAIN_LIST *flush_domains;
 
 void    flush_init(void)
 {
-    flush_domains = domain_list_init(match_parent_style(VAR_FFLUSH_DOMAINS),
+    flush_domains = domain_list_init(MATCH_FLAG_RETURN
+                                  | match_parent_style(VAR_FFLUSH_DOMAINS),
                                     var_fflush_domains);
 }
 
@@ -165,6 +166,7 @@ int     flush_send_site(const char *site)
 {
     const char *myname = "flush_send_site";
     int     status;
+    int     rc;
 
     if (msg_verbose)
        msg_info("%s: site %s", myname, site);
@@ -175,13 +177,15 @@ int     flush_send_site(const char *site)
      */
     if (flush_domains == 0)
        msg_panic("missing flush client initialization");
-    if (domain_list_match(flush_domains, site) == 0)
+    if ((rc = domain_list_match(flush_domains, site)) == 0)
        status = FLUSH_STAT_DENY;
-    else
+    else if (rc > 0)
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
                          ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_SEND_SITE,
                                     ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                                     ATTR_TYPE_END);
+    else
+       status = FLUSH_STAT_FAIL;
 
     if (msg_verbose)
        msg_info("%s: site %s status %d", myname, site, status);
@@ -219,6 +223,7 @@ int     flush_add(const char *site, const char *queue_id)
 {
     const char *myname = "flush_add";
     int     status;
+    int     rc;
 
     if (msg_verbose)
        msg_info("%s: site %s id %s", myname, site, queue_id);
@@ -229,14 +234,16 @@ int     flush_add(const char *site, const char *queue_id)
      */
     if (flush_domains == 0)
        msg_panic("missing flush client initialization");
-    if (domain_list_match(flush_domains, site) == 0)
+    if ((rc = domain_list_match(flush_domains, site)) == 0)
        status = FLUSH_STAT_DENY;
-    else
+    else if (rc > 0)
        status = mail_command_client(MAIL_CLASS_PUBLIC, var_flush_service,
                                ATTR_TYPE_STR, MAIL_ATTR_REQ, FLUSH_REQ_ADD,
                                     ATTR_TYPE_STR, MAIL_ATTR_SITE, site,
                                 ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
                                     ATTR_TYPE_END);
+    else
+       status = FLUSH_STAT_FAIL;
 
     if (msg_verbose)
        msg_info("%s: site %s id %s status %d", myname, site, queue_id,
index a4e1808e147a3c81274410c03d30eca6778bf309..3812da471e5c386082c330facc7c79a727ba2150 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20111218"
+#define MAIL_RELEASE_DATE      "20111219"
 #define MAIL_VERSION_NUMBER    "2.9"
 
 #ifdef SNAPSHOT
index 883b64a8f35cbbd49c56bbc8f2c3f74770c56d86..9dfc87f39ce1ec2dc1fc18874654bda889ae6f99 100644 (file)
 /*     namadr_list_init() performs initializations. The first
 /*     argument is the bit-wise OR of zero or more of the
 /*     following:
-/* .RS
 /* .IP MATCH_FLAG_PARENT
 /*     The hostname pattern foo.com matches itself and any name below
 /*     the domain foo.com. If this flag is cleared, foo.com matches itself
 /*     only, and .foo.com matches any name below the domain foo.com.
-/* .RE
+/* .IP MATCH_FLAG_RETURN
+/*     Request that namadr_list_match() returns a negative result
+/*     (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a
+/*     fatal error.
+/* .PP
 /*     Specify MATCH_FLAG_NONE to request none of the above.
 /*     The second argument is a list of patterns, or the absolute
 /*     pathname of a file with patterns.
@@ -103,6 +106,7 @@ int     main(int argc, char **argv)
     char   *host;
     char   *addr;
     int     ch;
+    int     rc;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
@@ -117,12 +121,12 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 3)
        usage(argv[0]);
-    list = namadr_list_init(MATCH_FLAG_PARENT, argv[optind]);
+    list = namadr_list_init(MATCH_FLAG_PARENT | MATCH_FLAG_RETURN, argv[optind]);
     host = argv[optind + 1];
     addr = argv[optind + 2];
+    rc = namadr_list_match(list, host, addr);
     vstream_printf("%s/%s: %s\n", host, addr,
-                  namadr_list_match(list, host, addr) ?
-                  "YES" : "NO");
+                  rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR");
     vstream_fflush(VSTREAM_OUT);
     namadr_list_free(list);
     return (0);
index 9bf90d7684d5866e0d395d858ee079279a3176fe..b2322edf86305e977e512647294045600a33756d 100644 (file)
@@ -15,7 +15,6 @@
   * Utility library.
   */
 #include <match_list.h>
-#include <match_ops.h>
 
  /*
   * External interface.
index 2eaeea3154f83165a7ab062b9140d9dcd9d4ab29..c1cd8f2c4cd1fb00f261031aebd8b68eb7c303b2 100644 (file)
@@ -1,4 +1,6 @@
 ./namadr_list 168.100.189.0/28 dummy 168.100.189.2
+./namadr_list '!168.100.189.2 168.100.189.0/28' dummy 168.100.189.2
+./namadr_list '!168.100.189.2 168.100.189.0/28' dummy 168.100.189.3
 ./namadr_list 168.100.189.0/28 dummy 168.100.189.16
 ./namadr_list 168.100.189.0/98 dummy 168.100.189.16
 ./namadr_list 168.100.589.0/28 dummy 168.100.189.16
@@ -35,3 +37,5 @@ env foo=x ./namadr_list !environ:junk foo 168.100.189.3
 env foo=x ./namadr_list !environ:junk bar 168.100.189.3
 env foo=x ./namadr_list !!environ:junk foo 168.100.189.3
 env foo=x ./namadr_list !!environ:junk bar 168.100.189.3
+./namadr_list fail:1 bar 168.100.189.3
+./namadr_list !fail:1 bar 168.100.189.3
index 5c2fffbc1710608d840f17c19b2ca85c234bc4b3..a7b8646194efa77beddf83d64afee9249ad20170 100644 (file)
@@ -1,12 +1,17 @@
 dummy/168.100.189.2: YES
+dummy/168.100.189.2: NO
+dummy/168.100.189.3: YES
 dummy/168.100.189.16: NO
-./namadr_list: fatal: bad net/mask pattern: "168.100.189.0/98"
-./namadr_list: fatal: bad net/mask pattern: "168.100.589.0/28"
+./namadr_list: warning: bad net/mask pattern: "168.100.189.0/98"
+dummy/168.100.189.16: ERROR
+./namadr_list: warning: bad net/mask pattern: "168.100.589.0/28"
+dummy/168.100.189.16: ERROR
 dummy/168.100.989.16: NO
 ./namadr_list: fatal: unsupported dictionary type: 2001
 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES
 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO
-./namadr_list: fatal: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
+./namadr_list: warning: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: ERROR
 dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: YES
 dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: NO
 dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: YES
@@ -24,12 +29,18 @@ foo/168.100.189.3: YES
 bar/168.100.189.3: NO
 baz/168.100.189.3: YES
 x.x.x/127.0.0.1: NO
-./namadr_list: fatal: bad net/mask pattern: "be/be"
+./namadr_list: warning: bad net/mask pattern: "be/be"
+x.x.x/127.0.0.1: ERROR
 x.x.x/127.0.0.1: NO
-./namadr_list: fatal: bad address pattern: "be:be"
+./namadr_list: warning: bad address pattern: "be:be"
+x.x.x/::1: ERROR
 foo/168.100.189.3: YES
 bar/168.100.189.3: NO
 foo/168.100.189.3: NO
 bar/168.100.189.3: NO
 foo/168.100.189.3: YES
 bar/168.100.189.3: NO
+./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem
+bar/168.100.189.3: ERROR
+./namadr_list: warning: fail:1(0,lock|fold_fix): table lookup problem
+bar/168.100.189.3: ERROR
index f4a78fb6abf7fb3386dd2df4db7ebb7947ec5c3c..03b602dab2ade8f2568b5acf5bf62428a4178f04 100644 (file)
@@ -98,7 +98,8 @@ void    server_acl_pre_jail_init(const char *mynetworks, const char *origin)
 {
     if (server_acl_mynetworks)
        addr_match_list_free(server_acl_mynetworks);
-    server_acl_mynetworks = addr_match_list_init(match_parent_style(origin),
+    server_acl_mynetworks = 
+       addr_match_list_init(MATCH_FLAG_RETURN | match_parent_style(origin),
                                                 mynetworks);
 }
 
@@ -158,6 +159,7 @@ int     server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl,
     int     ret;
     ARGV    fake_argv;
     const char *fake_args[2];
+    int     rc;
 
     for (cpp = intern_acl->argv; (acl = *cpp) != 0; cpp++) {
        if (msg_verbose)
@@ -168,8 +170,14 @@ int     server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl,
        } else if (STREQ(acl, SERVER_ACL_NAME_PERMIT)) {
            return (SERVER_ACL_ACT_PERMIT);
        } else if (STREQ(acl, SERVER_ACL_NAME_WL_MYNETWORKS)) {
-           if (addr_match_list_match(server_acl_mynetworks, client_addr))
+           rc = addr_match_list_match(server_acl_mynetworks, client_addr);
+           if (rc > 0)
                return (SERVER_ACL_ACT_PERMIT);
+           if (rc < 0) {
+               msg_warn("%s: %s: mynetworks lookup error -- ignoring the "
+                        "remainder of this access list", origin, acl);
+               return (SERVER_ACL_ACT_ERROR);
+           }
        } else if (strchr(acl, ':') != 0) {
            if ((dict = dict_handle(acl)) == 0)
                msg_panic("%s: unexpected dictionary: %s", myname, acl);
@@ -189,8 +197,8 @@ int     server_acl_eval(const char *client_addr, SERVER_ACL * intern_acl,
                if (ret != SERVER_ACL_ACT_DUNNO)
                    return (ret);
            } else if (dict_errno != 0) {
-               msg_warn("%s: table lookup error -- ignoring the remainder "
-                        "of this access list", acl);
+               msg_warn("%s: %s: table lookup error -- ignoring the remainder "
+                        "of this access list", origin, acl);
                return (SERVER_ACL_ACT_ERROR);
            }
        } else if (STREQ(acl, SERVER_ACL_NAME_DUNNO)) {
diff --git a/postfix/src/global/server_acl.in b/postfix/src/global/server_acl.in
new file mode 100644 (file)
index 0000000..a12001a
--- /dev/null
@@ -0,0 +1,10 @@
+mynetworks=168.100.189.0/27
+server_acl=permit_mynetworks,reject
+address=168.100.189.2
+mynetworks=!168.100.189.2,168.100.189.0/27
+address=168.100.189.2
+address=168.100.189.3
+mynetworks=fail:1
+address=168.100.189.4
+server_acl=fail:1,reject
+address=168.100.189.2
diff --git a/postfix/src/global/server_acl.ref b/postfix/src/global/server_acl.ref
new file mode 100644 (file)
index 0000000..7b72f76
--- /dev/null
@@ -0,0 +1,18 @@
+> mynetworks=168.100.189.0/27
+> server_acl=permit_mynetworks,reject
+> address=168.100.189.2
+168.100.189.2: permit
+> mynetworks=!168.100.189.2,168.100.189.0/27
+> address=168.100.189.2
+168.100.189.2: reject
+> address=168.100.189.3
+168.100.189.3: permit
+> mynetworks=fail:1
+> address=168.100.189.4
+unknown: warning: fail:1(0,lock|fold_fix): table lookup problem
+unknown: warning: server_acl: permit_mynetworks: mynetworks lookup error -- ignoring the remainder of this access list
+168.100.189.4: error
+> server_acl=fail:1,reject
+> address=168.100.189.2
+unknown: warning: server_acl: fail:1: table lookup error -- ignoring the remainder of this access list
+168.100.189.2: error
index bdb6fc4fb7867784a80dc6dd7b3eea1f70481a1d..9de5a5429ce596423057bfa307d73f6baffe9253 100644 (file)
 /*     In order to reverse the result, precede a pattern with an
 /*     exclamation point (!).
 /*
-/*     string_list_init() performs initializations. The flags argument
-/*     is ignored; pattern_list specifies a list of string patterns.
+/*     string_list_init() performs initializations. The first argument
+/*     is a bit-wise OR of zero or more of following:
+/* .IP MATCH_FLAG_RETURN
+/*      Request that string_list_match() returns a negative result
+/*      (MATCH_ERR_TEMP or MATCH_ERR_PERM), instead of raising a fatal
+/*      error.
+/* .PP
+/*     Specify MATCH_FLAG_NONE to request none of the above.
+/*     The second argument specifies a list of string patterns.
 /*
 /*     string_list_match() matches the specified string against the
 /*     compiled pattern list.
@@ -85,6 +92,7 @@ int     main(int argc, char **argv)
     STRING_LIST *list;
     char   *string;
     int     ch;
+    int     rc;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
@@ -99,10 +107,11 @@ int     main(int argc, char **argv)
     }
     if (argc != optind + 2)
        usage(argv[0]);
-    list = string_list_init(MATCH_FLAG_NONE, argv[optind]);
+    list = string_list_init(MATCH_FLAG_NONE | MATCH_FLAG_RETURN, argv[optind]);
     string = argv[optind + 1];
-    vstream_printf("%s: %s\n", string, string_list_match(list, string) ?
-                  "YES" : "NO");
+    rc = string_list_match(list, string);
+    vstream_printf("%s: %s\n", string,
+                  rc > 0 ? "YES" : rc == 0 ? "NO" : "ERROR");
     vstream_fflush(VSTREAM_OUT);
     string_list_free(list);
     return (0);
index daa9541d2f56f1b6ed6bbd11ff811682b85cb0d6..0a96bacfeb017bd11cb706fd1e914a6ec1840f9c 100644 (file)
@@ -15,7 +15,6 @@
   * Utility library.
   */
 #include <match_list.h>
-#include <match_ops.h>
 
  /*
   * External interface.
index eea582ac605c1bc6457a1ffe844a14e0e4be7a9c..d742557b200cc68922c4fa5f29245ff072770a8f 100644 (file)
 /*     The UNIX process environment array. The lookup key is the variable
 /*     name. Originally implemented for testing, someone may find this
 /*     useful someday.
+/* .IP \fBfail\fR
+/*     A table that reliably fails all requests. The lookup table
+/*     name provides the internal error result code. This table
+/*     exists to simplify Postfix error tests.
 /* .IP \fBhash\fR
 /*     An indexed file type based on hashing.
 /*     This is available on systems with support for Berkeley DB
index 4c5c6cfa8ad330ff9d507e7576ead5714fc561e2..f7145fade2b94973a94e7629c01676913d2f082b 100644 (file)
@@ -80,8 +80,8 @@
 /* .ad
 /* .fi
 /* .IP "\fBqmqpd_error_delay (1s)\fR"
-/*     How long the QMQP server will pause before sending a negative reply
-/*     to the client.
+/*     How long the Postfix QMQP server will pause before sending a negative
+/*     reply to the remote QMQP client.
 /* MISCELLANEOUS CONTROLS
 /* .ad
 /* .fi
 /* .IP "\fBprocess_name (read-only)\fR"
 /*     The process name of a Postfix command or daemon process.
 /* .IP "\fBqmqpd_authorized_clients (empty)\fR"
-/*     What clients are allowed to connect to the QMQP server port.
+/*     What remote QMQP clients are allowed to connect to the Postfix QMQP
+/*     server port.
 /* .IP "\fBqueue_directory (see 'postconf -d' output)\fR"
 /*     The location of the Postfix top-level queue directory.
 /* .IP "\fBsyslog_facility (mail)\fR"
@@ -648,6 +649,7 @@ static void qmqpd_receive(QMQPD_STATE *state)
 static void qmqpd_proto(QMQPD_STATE *state)
 {
     int     status;
+    int     rc;
 
     netstring_setup(state->client, var_qmqpd_timeout);
 
@@ -685,12 +687,17 @@ static void qmqpd_proto(QMQPD_STATE *state)
        /*
         * See if we want to talk to this client at all.
         */
-       if (namadr_list_match(qmqpd_clients, state->name, state->addr) == 0) {
+       rc = namadr_list_match(qmqpd_clients, state->name, state->addr);
+       if (rc > 0) {
+           qmqpd_receive(state);
+       } else if (rc == 0) {
            qmqpd_reply(state, DONT_LOG, QMQPD_STAT_HARD,
                        "Error: %s is not authorized to use this service",
                        state->namaddr);
-       } else
-           qmqpd_receive(state);
+       } else {
+           qmqpd_reply(state, DONT_LOG, QMQPD_STAT_RETRY,
+                       "Error: server configuration error");
+       }
        break;
     }
 
@@ -760,7 +767,8 @@ static void pre_jail_init(char *unused_name, char **unused_argv)
 {
     debug_peer_init();
     qmqpd_clients =
-       namadr_list_init(match_parent_style(VAR_QMQPD_CLIENTS),
+       namadr_list_init(MATCH_FLAG_RETURN
+                        | match_parent_style(VAR_QMQPD_CLIENTS),
                         var_qmqpd_clients);
 }
 
index d42fefbf5dd9634cdac7582c4487e07fd197d8cc..59415c85f994aa3cf54c03c38441c465ddcf0b94 100644 (file)
@@ -1757,7 +1757,6 @@ static int mail_open_stream(SMTPD_STATE *state)
      * feature.
      */
     if (state->proxy_mail) {
-       smtpd_check_rewrite(state);
        if (smtpd_proxy_create(state, smtpd_proxy_opts, var_smtpd_proxy_filt,
                               var_smtpd_proxy_tmout, var_smtpd_proxy_ehlo,
                               state->proxy_mail) != 0) {
@@ -1780,7 +1779,6 @@ static int mail_open_stream(SMTPD_STATE *state)
     else if (SMTPD_STAND_ALONE(state) == 0) {
        int     cleanup_flags;
 
-       smtpd_check_rewrite(state);
        cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL,
                                             smtpd_input_transp_mask)
            | CLEANUP_FLAG_SMTP_REPLY;
@@ -2297,6 +2295,13 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            return (-1);
        }
     }
+    err = smtpd_check_rewrite(state);
+    if (err != 0) {
+       /* XXX Reset access map side effects. */
+       mail_reset(state);
+       smtpd_chat_reply(state, "%s", err);
+       return (-1);
+    }
 
     /*
      * Check the queue file space, if applicable. The optional before-filter
index f53741f825bf607b10e22ae11b78dcfe000fe1e0..b23c3c168e2860db33cc163ad378730f00f4419e 100644 (file)
@@ -256,6 +256,7 @@ static jmp_buf smtpd_check_buf;
  /*
   * Results of restrictions.
   */
+#define SMTPD_CHECK_ERROR      (-1)    /* server error */
 #define SMTPD_CHECK_DUNNO      0       /* indifferent */
 #define SMTPD_CHECK_OK         1       /* explicitly permit */
 #define SMTPD_CHECK_REJECT     2       /* explicitly reject */
@@ -4101,7 +4102,7 @@ int     smtpd_check_addr(const char *addr)
 
 /* smtpd_check_rewrite - choose address qualification context */
 
-void    smtpd_check_rewrite(SMTPD_STATE *state)
+char   *smtpd_check_rewrite(SMTPD_STATE *state)
 {
     const char *myname = "smtpd_check_rewrite";
     int     status;
@@ -4131,11 +4132,12 @@ void    smtpd_check_rewrite(SMTPD_STATE *state)
            if ((dict = dict_handle(*cpp)) == 0)
                msg_panic("%s: dictionary not found: %s", myname, *cpp);
            dict_errno = 0;
-           /* for now, dict errors are fatal */
            if (dict_get(dict, state->addr) != 0)
                status = SMTPD_CHECK_OK;
-           else if (dict_errno != 0)
-               msg_fatal("%s: table lookup error", *cpp);
+           else if (dict_errno != 0) {
+               msg_warn("%s: %s: lookup error", VAR_LOC_RWR_CLIENTS, *cpp);
+               status = SMTPD_CHECK_ERROR;
+           }
        } else if (strcasecmp(name, PERMIT_SASL_AUTH) == 0) {
 #ifdef USE_SASL_AUTH
            if (smtpd_sasl_is_active(state))
@@ -4144,29 +4146,32 @@ void    smtpd_check_rewrite(SMTPD_STATE *state)
 #endif
        } else if (strcasecmp(name, PERMIT_TLS_ALL_CLIENTCERTS) == 0) {
            status = permit_tls_clientcerts(state, 1);
-           /* for now, dict errors are fatal */
 #ifdef USE_TLS
            if (dict_errno != 0)
-               msg_fatal("%s: table lookup error", var_smtpd_relay_ccerts);
+               status = SMTPD_CHECK_ERROR;
 #endif
        } else if (strcasecmp(name, PERMIT_TLS_CLIENTCERTS) == 0) {
            status = permit_tls_clientcerts(state, 0);
-           /* for now, dict errors are fatal */
 #ifdef USE_TLS
            if (dict_errno != 0)
-               msg_fatal("%s: table lookup error", var_smtpd_relay_ccerts);
+               status = SMTPD_CHECK_ERROR;
 #endif
        } else {
            msg_warn("parameter %s: invalid request: %s",
                     VAR_LOC_RWR_CLIENTS, name);
            continue;
        }
+       if (status < 0) {
+           state->error_mask |= MAIL_ERROR_RESOURCE;
+           return ("451 4.3.5 Server configuration error");
+       }
        if (status == SMTPD_CHECK_OK) {
            state->rewrite_context = MAIL_ATTR_RWR_LOCAL;
-           return;
+           return (0);
        }
     }
     state->rewrite_context = MAIL_ATTR_RWR_REMOTE;
+    return (0);
 }
 
 /* smtpd_check_client - validate client name or address */
@@ -5170,6 +5175,15 @@ int     permit_sasl_auth(SMTPD_STATE *state, int ifyes, int ifnot)
     return (ifnot);
 }
 
+/* smtpd_sasl_state_init - the real deal */
+
+void    smtpd_sasl_state_init(SMTPD_STATE *state)
+{
+    state->sasl_username = 0;
+    state->sasl_method = 0;
+    state->sasl_sender = 0;
+}
+
 #endif
 
 /* verify_clnt_query - stub */
index 9bdd255c7089c640ec22f6eed0cb1fb2bf4d1cdb..b76a4990f4bbfbe6b0a8227fb71104fc953aa84e 100644 (file)
@@ -14,7 +14,7 @@
   */
 extern void smtpd_check_init(void);
 extern int smtpd_check_addr(const char *);
-extern void smtpd_check_rewrite(SMTPD_STATE *);
+extern char *smtpd_check_rewrite(SMTPD_STATE *);
 extern char *smtpd_check_client(SMTPD_STATE *);
 extern char *smtpd_check_helo(SMTPD_STATE *, char *);
 extern char *smtpd_check_mail(SMTPD_STATE *, char *);
index f9d29a86ebdaf401e1398718fbf23406afa7ec5f..2ed3955612ed699847708571507060b40a59086d 100644 (file)
@@ -155,6 +155,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
     const char *relay;
     const char *xport;
     const char *sender_key;
+    int     rc;
 
     *flags = 0;
     vstring_strcpy(channel, "CHANNEL NOT UPDATED");
@@ -431,15 +432,15 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
         * Virtual alias domain.
         */
        if (virt_alias_doms
-           && string_list_match(virt_alias_doms, rcpt_domain)) {
+           && (rc = string_list_match(virt_alias_doms, rcpt_domain)) > 0) {
            if (var_helpful_warnings) {
                if (virt_mailbox_doms
-                   && string_list_match(virt_mailbox_doms, rcpt_domain))
+                   && string_list_match(virt_mailbox_doms, rcpt_domain) > 0)
                    msg_warn("do not list domain %s in BOTH %s and %s",
                             rcpt_domain, VAR_VIRT_ALIAS_DOMS,
                             VAR_VIRT_MAILBOX_DOMS);
                if (relay_domains
-                   && domain_list_match(relay_domains, rcpt_domain))
+                   && domain_list_match(relay_domains, rcpt_domain) > 0)
                    msg_warn("do not list domain %s in BOTH %s and %s",
                             rcpt_domain, VAR_VIRT_ALIAS_DOMS,
                             VAR_RELAY_DOMAINS);
@@ -454,7 +455,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
                            var_show_unk_rcpt_table ?
                            " in virtual alias table" : "");
            *flags |= RESOLVE_CLASS_ALIAS;
-       } else if (dict_errno != 0) {
+       } else if (dict_errno != 0 || rc < 0) {
            msg_warn("%s lookup failure", VAR_VIRT_ALIAS_DOMS);
            *flags |= RESOLVE_FLAG_FAIL;
            FREE_MEMORY_AND_RETURN;
@@ -464,10 +465,10 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
         * Virtual mailbox domain.
         */
        else if (virt_mailbox_doms
-                && string_list_match(virt_mailbox_doms, rcpt_domain)) {
+        && (rc = string_list_match(virt_mailbox_doms, rcpt_domain)) > 0) {
            if (var_helpful_warnings) {
                if (relay_domains
-                   && domain_list_match(relay_domains, rcpt_domain))
+                   && domain_list_match(relay_domains, rcpt_domain) > 0)
                    msg_warn("do not list domain %s in BOTH %s and %s",
                             rcpt_domain, VAR_VIRT_MAILBOX_DOMS,
                             VAR_RELAY_DOMAINS);
@@ -476,7 +477,7 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
            vstring_strcpy(nexthop, rcpt_domain);
            blame = rp->virt_transport_name;
            *flags |= RESOLVE_CLASS_VIRTUAL;
-       } else if (dict_errno != 0) {
+       } else if (dict_errno != 0 || rc < 0) {
            msg_warn("%s lookup failure", VAR_VIRT_MAILBOX_DOMS);
            *flags |= RESOLVE_FLAG_FAIL;
            FREE_MEMORY_AND_RETURN;
@@ -486,11 +487,11 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
             * Off-host relay destination.
             */
            if (relay_domains
-               && domain_list_match(relay_domains, rcpt_domain)) {
+            && (rc = domain_list_match(relay_domains, rcpt_domain)) > 0) {
                vstring_strcpy(channel, RES_PARAM_VALUE(rp->relay_transport));
                blame = rp->relay_transport_name;
                *flags |= RESOLVE_CLASS_RELAY;
-           } else if (dict_errno != 0) {
+           } else if (dict_errno != 0 || rc < 0) {
                msg_warn("%s lookup failure", VAR_RELAY_DOMAINS);
                *flags |= RESOLVE_FLAG_FAIL;
                FREE_MEMORY_AND_RETURN;
@@ -560,11 +561,11 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr,
     else {
        if (var_helpful_warnings) {
            if (virt_alias_doms
-               && string_list_match(virt_alias_doms, rcpt_domain))
+               && string_list_match(virt_alias_doms, rcpt_domain) > 0)
                msg_warn("do not list domain %s in BOTH %s and %s",
                         rcpt_domain, VAR_MYDEST, VAR_VIRT_ALIAS_DOMS);
            if (virt_mailbox_doms
-               && string_list_match(virt_mailbox_doms, rcpt_domain))
+               && string_list_match(virt_mailbox_doms, rcpt_domain) > 0)
                msg_warn("do not list domain %s in BOTH %s and %s",
                         rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS);
        }
@@ -739,15 +740,16 @@ void    resolve_init(void)
 
     if (*var_virt_alias_doms)
        virt_alias_doms =
-           string_list_init(MATCH_FLAG_NONE, var_virt_alias_doms);
+           string_list_init(MATCH_FLAG_RETURN, var_virt_alias_doms);
 
     if (*var_virt_mailbox_doms)
        virt_mailbox_doms =
-           string_list_init(MATCH_FLAG_NONE, var_virt_mailbox_doms);
+           string_list_init(MATCH_FLAG_RETURN, var_virt_mailbox_doms);
 
     if (*var_relay_domains)
        relay_domains =
-           domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
+           domain_list_init(MATCH_FLAG_RETURN 
+                            | match_parent_style(VAR_RELAY_DOMAINS),
                             var_relay_domains);
 
     if (*var_relocated_maps)
index 7ecf8b319c7f46b7abe46b69fadaa30b7ba533a1..3687fe12db699fc94868044077b1c9e54be761a5 100644 (file)
@@ -33,7 +33,8 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        allascii.c load_file.c killme_after.c vstream_tweak.c \
        unix_pass_listen.c unix_pass_trigger.c edit_file.c inet_windowsize.c \
        unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \
-       ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c
+       ip_match.c nbbio.c stream_pass_connect.c base32_code.c dict_test.c \
+       dict_fail.c
 OBJS   = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
        attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -68,7 +69,8 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        allascii.o load_file.o killme_after.o vstream_tweak.o \
        unix_pass_listen.o unix_pass_trigger.o edit_file.o inet_windowsize.o \
        unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \
-       ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o
+       ip_match.o nbbio.o stream_pass_connect.o base32_code.o dict_test.o \
+       dict_fail.o
 HDRS   = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        chroot_uid.h cidr_match.h clean_env.h connect.h ctable.h dict.h \
        dict_cdb.h dict_cidr.h dict_db.h dict_dbm.h dict_env.h dict_ht.h \
@@ -88,8 +90,8 @@ HDRS  = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        stringops.h sys_defs.h timed_connect.h timed_wait.h trigger.h \
        username.h valid_hostname.h vbuf.h vbuf_print.h vstream.h vstring.h \
        vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \
-       edit_file.h dict_cache.h dict_thash.h \
-       ip_match.h nbbio.h base32_code.h
+       edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \
+       dict_fail.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
 DEFS   = -I. -D$(SYSTYPE)
@@ -908,6 +910,16 @@ dict_env.o: sys_defs.h
 dict_env.o: vbuf.h
 dict_env.o: vstream.h
 dict_env.o: vstring.h
+dict_fail.o: argv.h
+dict_fail.o: dict.h
+dict_fail.o: dict_fail.c
+dict_fail.o: dict_fail.h
+dict_fail.o: msg.h
+dict_fail.o: mymalloc.h
+dict_fail.o: sys_defs.h
+dict_fail.o: vbuf.h
+dict_fail.o: vstream.h
+dict_fail.o: vstring.h
 dict_ht.o: argv.h
 dict_ht.o: dict.h
 dict_ht.o: dict_ht.c
@@ -950,6 +962,7 @@ dict_open.o: dict_cidr.h
 dict_open.o: dict_db.h
 dict_open.o: dict_dbm.h
 dict_open.o: dict_env.h
+dict_open.o: dict_fail.h
 dict_open.o: dict_ht.h
 dict_open.o: dict_ni.h
 dict_open.o: dict_nis.h
diff --git a/postfix/src/util/dict_fail.c b/postfix/src/util/dict_fail.c
new file mode 100644 (file)
index 0000000..197f61e
--- /dev/null
@@ -0,0 +1,114 @@
+/*++
+/* NAME
+/*     dict_fail 3
+/* SUMMARY
+/*     dictionary manager interface to 'always fail' table
+/* SYNOPSIS
+/*     #include <dict_fail.h>
+/*
+/*     DICT    *dict_fail_open(name, name, dict_flags)
+/*     const char *name;
+/*     int     dummy;
+/*     int     dict_flags;
+/* DESCRIPTION
+/*     dict_fail_open() implements a dummy dictionary that fails
+/*     all operations. The name specifies the dict_errno value.
+/* SEE ALSO
+/*     dict(3) generic dictionary manager
+/* 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 <stdlib.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <msg.h>
+#include <dict.h>
+#include <dict_fail.h>
+
+/* Application-specific. */
+
+typedef struct {
+    DICT    dict;                      /* generic members */
+    int     dict_errno;                        /* fixed error result */
+} DICT_FAIL;
+
+/* dict_fail_sequence - fail lookup */
+
+static int dict_fail_sequence(DICT *dict, int unused_func,
+                                      const char **key, const char **value)
+{
+    DICT_FAIL *dp = (DICT_FAIL *) dict;
+
+    dict_errno = dp->dict_errno;
+    return (1);
+}
+
+/* dict_fail_update - fail lookup */
+
+static void dict_fail_update(DICT *dict, const char *unused_name,
+                                    const char *unused_value)
+{
+    DICT_FAIL *dp = (DICT_FAIL *) dict;
+
+    dict_errno = dp->dict_errno;
+}
+
+/* dict_fail_lookup - fail lookup */
+
+static const char *dict_fail_lookup(DICT *dict, const char *unused_name)
+{
+    DICT_FAIL *dp = (DICT_FAIL *) dict;
+
+    dict_errno = dp->dict_errno;
+    return (0);
+}
+
+/* dict_fail_delete - fail delete */
+
+static int dict_fail_delete(DICT *dict, const char *unused_name)
+{
+    DICT_FAIL *dp = (DICT_FAIL *) dict;
+
+    dict_errno = dp->dict_errno;
+    return (-1);
+}
+
+/* dict_fail_close - close fail dictionary */
+
+static void dict_fail_close(DICT *dict)
+{
+    dict_free(dict);
+}
+
+/* dict_fail_open - make association with fail variable */
+
+DICT   *dict_fail_open(const char *name, int open_flags, int dict_flags)
+{
+    DICT_FAIL *dp;
+
+    dp = (DICT_FAIL *) dict_alloc(DICT_TYPE_FAIL, name, sizeof(*dp));
+    dp->dict.lookup = dict_fail_lookup;
+    if (open_flags & O_RDWR) {
+       dp->dict.update = dict_fail_update;
+       dp->dict.delete = dict_fail_delete;
+    }
+    dp->dict.sequence = dict_fail_sequence;
+    dp->dict.close = dict_fail_close;
+    dp->dict.flags = dict_flags | DICT_FLAG_PATTERN;
+    dp->dict_errno = atoi(name);
+    dp->dict.owner.status = DICT_OWNER_TRUSTED;
+    return (DICT_DEBUG (&dp->dict));
+}
diff --git a/postfix/src/util/dict_fail.h b/postfix/src/util/dict_fail.h
new file mode 100644 (file)
index 0000000..b42a31b
--- /dev/null
@@ -0,0 +1,35 @@
+#ifndef _DICT_FAIL_H_INCLUDED_
+#define _DICT_FAIL_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_fail 3h
+/* SUMMARY
+/*     dictionary manager interface to 'always fail' table
+/* SYNOPSIS
+/*     #include <dict_fail.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <dict.h>
+
+ /*
+  * External interface.
+  */
+#define DICT_TYPE_FAIL "fail"
+
+extern DICT *dict_fail_open(const char *, int, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     jeffm
+/*     ghostgun.com
+/*--*/
+
+#endif
index d5ae3d5a0ba6a10a6ab2dcc6575901c25c851952..76d946be42095b57298d521fa6910439ad543903 100644 (file)
 #include <dict_cidr.h>
 #include <dict_ht.h>
 #include <dict_thash.h>
+#include <dict_fail.h>
 #include <stringops.h>
 #include <split_at.h>
 #include <htable.h>
@@ -260,6 +261,7 @@ static const DICT_OPEN_INFO dict_open_info[] = {
     DICT_TYPE_STATIC, dict_static_open,
     DICT_TYPE_CIDR, dict_cidr_open,
     DICT_TYPE_THASH, dict_thash_open,
+    DICT_TYPE_FAIL, dict_fail_open,
     0,
 };
 
index 62d05f8d666739705fc658677c4a50f9cdc7653e..589300dc218862f1da0d14a79afaaa01ed896416 100644 (file)
@@ -1,4 +1,5 @@
-./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF
+./dict_open: warning: regexp map dict_regexp.map, line 1: ignoring extra text after IF statement: "fodder"
+./dict_open: warning: regexp map dict_regexp.map, line 1: do not prepend whitespace to statements between IF and ENDIF
 ./dict_open: warning: regexp map dict_regexp.map, line 5: ignoring extra text after ENDIF
 ./dict_open: warning: regexp map dict_regexp.map, line 9: using empty replacement string
 ./dict_open: warning: regexp map dict_regexp.map, line 10: out of range replacement index "5": skipping this rule
index 7c9cabcb6e3375cd00c1ed9c49dd2e2fe5680f3a..723a24dcf4a60c20ef17d89374de6378cf8044e1 100644 (file)
@@ -6,7 +6,7 @@
 /* SYNOPSIS
 /*     #include <dict_static.h>
 /*
-/*     DICT    *dict_static_open(name, dummy, dict_flags)
+/*     DICT    *dict_static_open(name, name, dict_flags)
 /*     const char *name;
 /*     int     dummy;
 /*     int     dict_flags;
@@ -14,8 +14,6 @@
 /*     dict_static_open() implements a dummy dictionary that returns
 /*     as lookup result the dictionary name, regardless of the lookup
 /*     key value.
-/*
-/*     The \fIdummy\fR argument is ignored.
 /* SEE ALSO
 /*     dict(3) generic dictionary manager
 /* LICENSE
index eb8d2cb59814901fd0c363601b3c8132226e0890..b2f57dfa900ad4c48fe9b640d5d245d7d3748fea 100644 (file)
@@ -43,6 +43,7 @@ void    dict_test(int argc, char **argv)
     int     ch;
     int     dict_flags = DICT_FLAG_LOCK | DICT_FLAG_DUP_REPLACE;
     int     n;
+    int     rc;
 
     signal(SIGPIPE, SIG_IGN);
 
@@ -98,15 +99,16 @@ void    dict_test(int argc, char **argv)
        if (strcmp(cmd, "verbose") == 0 && !key) {
            msg_verbose++;
        } else if (strcmp(cmd, "del") == 0 && key && !value) {
-           if (dict_del(dict, key))
+           if ((rc = dict_del(dict, key)) > 0)
                vstream_printf("%s: not found\n", key);
+           else if (rc < 0)
+               vstream_printf("%s: error\n", key);
            else
                vstream_printf("%s: deleted\n", key);
        } else if (strcmp(cmd, "get") == 0 && key && !value) {
            if ((value = dict_get(dict, key)) == 0) {
-               vstream_printf("%s: %s\n", key,
-                              dict_errno == DICT_ERR_RETRY ?
-                              "soft error" : "not found");
+               vstream_printf("%s: %s\n", key, dict_errno ?
+                              "error" : "not found");
            } else {
                vstream_printf("%s=%s\n", key, value);
            }
@@ -115,23 +117,21 @@ void    dict_test(int argc, char **argv)
            dict_errno = 0;
            dict_put(dict, key, value);
            if (dict_errno)
-               vstream_printf("%s: soft error\n", key);
+               vstream_printf("%s: error\n", key);
            else
                vstream_printf("%s=%s\n", key, value);
        } else if (strcmp(cmd, "first") == 0 && !key && !value) {
            if (dict_seq(dict, DICT_SEQ_FUN_FIRST, &key, &value) == 0)
                vstream_printf("%s=%s\n", key, value);
            else
-               vstream_printf("%s\n",
-                              dict_errno == DICT_ERR_RETRY ?
-                              "soft error" : "not found");
+               vstream_printf("%s\n", dict_errno ?
+                              "error" : "not found");
        } else if (strcmp(cmd, "next") == 0 && !key && !value) {
            if (dict_seq(dict, DICT_SEQ_FUN_NEXT, &key, &value) == 0)
                vstream_printf("%s=%s\n", key, value);
            else
-               vstream_printf("%s\n",
-                              dict_errno == DICT_ERR_RETRY ?
-                              "soft error" : "not found");
+               vstream_printf("%s\n", dict_errno ?
+                              "error" : "not found");
        } else if (strcmp(cmd, "flags") == 0 && !key && !value) {
            vstream_printf("dict flags %s\n",
                           dict_flags_str(dict->flags));
index 7832e95eacdcd04c89ce63d97bf3a793ffdd570a..b63ac5ccf0897c06fabe63d868ed974b00a0a170 100644 (file)
@@ -35,6 +35,9 @@
 /*     The hostname pattern foo.com matches any name within the domain
 /*     foo.com. If this flag is cleared, foo.com matches itself
 /*     only, and .foo.com matches any name below the domain foo.com.
+/* .IP MATCH_FLAG_RETURN
+/*     Return a negative result (MATCH_ERR_TEMP or MATCH_ERR_FAIL)
+/*     instead of raising a fatal run-time error.
 /* .RE
 /*     Specify MATCH_FLAG_NONE to request none of the above.
 /*     The pattern_list argument specifies a list of patterns.  The third
@@ -118,7 +121,7 @@ static ARGV *match_list_parse(ARGV *list, char *string, int init_match)
     while ((start = mystrtok(&bp, delim)) != 0) {
        if (*start == '#') {
            msg_warn("%s: comment at end of line is not supported: %s %s",
-                     myname, start, bp);
+                    myname, start, bp);
            break;
        }
        for (match = init_match, item = start; *item == '!'; item++)
@@ -188,7 +191,7 @@ MATCH_LIST *match_list_init(int flags, const char *patterns, int match_count,...
 
 /* match_list_match - match strings against pattern list */
 
-int     match_list_match(MATCH_LIST * list,...)
+int     match_list_match(MATCH_LIST *list,...)
 {
     const char *myname = "match_list_match";
     char  **cpp;
@@ -196,6 +199,7 @@ int     match_list_match(MATCH_LIST * list,...)
     int     match;
     int     i;
     va_list ap;
+    int     rc;
 
     /*
      * Iterate over all patterns in the list, stop at the first match.
@@ -209,8 +213,11 @@ int     match_list_match(MATCH_LIST * list,...)
        for (match = 1; *pat == '!'; pat++)
            match = !match;
        for (i = 0; i < list->match_count; i++)
-           if (list->match_func[i] (list->flags, list->match_args[i], pat))
+           if ((rc = list->match_func[i] (list->flags,
+                                           list->match_args[i], pat)) > 0)
                return (match);
+           else if (rc < 0)
+               return (rc);
     }
     if (msg_verbose)
        for (i = 0; i < list->match_count; i++)
@@ -220,7 +227,7 @@ int     match_list_match(MATCH_LIST * list,...)
 
 /* match_list_free - release storage */
 
-void    match_list_free(MATCH_LIST * list)
+void    match_list_free(MATCH_LIST *list)
 {
     argv_free(list->patterns);
     myfree((char *) list->match_func);
index 910ae713bf2698557427bc266344f3d73499dbd7..cbbc71a36848c9050f736ec7c5adf9e20146a00d 100644 (file)
 /* DESCRIPTION
 /* .nf
 
+ /*
+  * Utility library.
+  */
+#include <match_ops.h>
+
  /*
   * External interface.
   */
index 5832266b1f7dca3ecc08b37aced62f4a4933f400..d1cf850533d2e7a747e7057ba1662dca96178733 100644 (file)
@@ -37,6 +37,9 @@
 /*     The hostname pattern foo.com matches itself and any name below
 /*     the domain foo.com. If this flag is cleared, foo.com matches itself
 /*     only, and .foo.com matches any name below the domain foo.com.
+/* .IP MATCH_FLAG_RETURN
+/*     Return MATCH_ERR_TEMP or MATCH_ERR_PERM, instead of raising
+/*     a fatal run-time error.
 /* .RE
 /*     Specify MATCH_FLAG_NONE to request none of the above.
 /*
 #define MATCH_DICTIONARY(pattern) \
     ((pattern)[0] != '[' && strchr((pattern), ':') != 0)
 
+/* match_error - return or raise fatal error */
+
+static int match_error(int flags, int err_val, const char *fmt,...)
+{
+    VSTRING *buf = vstring_alloc(100);
+    va_list ap;
+
+    /*
+     * In case arguments get swapped after some code change.
+     */
+    if (err_val >= 0)
+       msg_panic("match_error: bad error value: %d", err_val);
+
+    /*
+     * Report, and maybe return.
+     */
+    va_start(ap, fmt);
+    vstring_vsprintf(buf, fmt, ap);
+    va_end(ap);
+    if (flags & MATCH_FLAG_RETURN) {
+       msg_warn("%s", vstring_str(buf));
+    } else {
+       msg_fatal("%s", vstring_str(buf));
+    }
+    vstring_free(buf);
+    return (err_val);
+}
+
 /* match_string - match a string literal */
 
-int     match_string(int unused_flags, const char *string, const char *pattern)
+int     match_string(int flags, const char *string, const char *pattern)
 {
     const char *myname = "match_string";
     int     match;
@@ -99,7 +130,8 @@ int     match_string(int unused_flags, const char *string, const char *pattern)
        if (match != 0)
            return (1);
        if (dict_errno != 0)
-           msg_fatal("%s: table lookup problem", pattern);
+           return (match_error(flags, MATCH_ERR_TEMP,
+                               "%s: table lookup problem", pattern));
        return (0);
     }
 
@@ -149,7 +181,8 @@ int     match_hostname(int flags, const char *name, const char *pattern)
                if (match != 0)
                    break;
                if (dict_errno != 0)
-                   msg_fatal("%s: table lookup problem", pattern);
+                   return (match_error(flags, MATCH_ERR_TEMP,
+                                     "%s: table lookup problem", pattern));
            }
            if ((next = strchr(entry + 1, '.')) == 0)
                break;
@@ -185,7 +218,7 @@ int     match_hostname(int flags, const char *name, const char *pattern)
 
 /* match_hostaddr - match host by address */
 
-int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
+int     match_hostaddr(int flags, const char *addr, const char *pattern)
 {
     const char *myname = "match_hostaddr";
     char   *saved_patt;
@@ -208,7 +241,8 @@ int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
        if (dict_lookup(pattern, addr) != 0)
            return (1);
        if (dict_errno != 0)
-           msg_fatal("%s: table lookup problem", pattern);
+           return (match_error(flags, MATCH_ERR_TEMP,
+                               "%s: table lookup problem", pattern));
        return (0);
     }
 
@@ -260,8 +294,9 @@ int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
      * everything into to binary form, and to do the comparison there.
      */
     saved_patt = mystrdup(pattern);
-    if ((err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0)) != 0)
-       msg_fatal("%s", vstring_str(err));
+    err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0);
     myfree(saved_patt);
+    if (err != 0)
+       return (match_error(flags, MATCH_ERR_PERM, "%s", vstring_str(err)));
     return (cidr_match_execute(&match_info, addr) != 0);
 }
index e147f7b50dd1308df426e14d5143c8cf20d50a3d..e8c8142f597593ff66aa80d7d60e592d91d02de3 100644 (file)
 
 #define MATCH_FLAG_NONE                0
 #define MATCH_FLAG_PARENT      (1<<0)
-#define MATCH_FLAG_ALL         (MATCH_FLAG_PARENT)
+#define MATCH_FLAG_RETURN      (1<<1)
+#define MATCH_FLAG_ALL         (MATCH_FLAG_PARENT | MATCH_FLAG_RETURN)
+
+#define MATCH_ERR_TEMP         (-1)    /* temporary error, e.g., database */
+#define MATCH_ERR_PERM         (-2)    /* permanent error, e.g., syntax */
 
 extern int match_string(int, const char *, const char *);
 extern int match_hostname(int, const char *, const char *);
index bc736010136b8d1060138fbe202aaef550f0d6e7..f0da580cbddc601145e20493a2fffff225bbed96 100644 (file)
@@ -1,6 +1,6 @@
 ./myaddrinfo: === hostname belly.porcupine.org ===
-./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2001:240:587:0:250:56ff:fe10:bd03
-./myaddrinfo: 2001:240:587:0:250:56ff:fe10:bd03 -> belly.porcupine.org
+./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2604:8d00:189::6
+./myaddrinfo: 2604:8d00:189::6 -> belly.porcupine.org
 ./myaddrinfo: belly.porcupine.org -> family=2 sock=1 proto=6 168.100.189.6
 ./myaddrinfo: 168.100.189.6 -> belly.porcupine.org
 ./myaddrinfo: === host address 168.100.189.2 ===