]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-19990909
authorWietse Venema <wietse@porcupine.org>
Thu, 9 Sep 1999 05:00:00 +0000 (00:00 -0500)
committerWietse Venema <wietse@porcupine.org>
Thu, 17 Jan 2013 23:09:45 +0000 (18:09 -0500)
47 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/INSTALL.sh
postfix/RELEASE_NOTES
postfix/bounce/.indent.pro
postfix/cleanup/.indent.pro
postfix/conf/sample-smtpd.cf
postfix/dns/.indent.pro
postfix/error/.indent.pro
postfix/fsstone/.indent.pro
postfix/global/.indent.pro
postfix/global/mail_params.h
postfix/global/mail_version.h
postfix/global/resolve_clnt.c
postfix/global/rewrite_clnt.c
postfix/html/smtpd.8.html
postfix/html/uce.html
postfix/local/.indent.pro
postfix/man/man8/smtpd.8
postfix/master/.indent.pro
postfix/pickup/.indent.pro
postfix/pipe/.indent.pro
postfix/postalias/.indent.pro
postfix/postcat/.indent.pro
postfix/postconf/.indent.pro
postfix/postdrop/.indent.pro
postfix/postfix/.indent.pro
postfix/postkick/.indent.pro
postfix/postlock/.indent.pro
postfix/postlock/postlock.c
postfix/postlog/.indent.pro
postfix/postmap/.indent.pro
postfix/postsuper/.indent.pro
postfix/qmgr/.indent.pro
postfix/sendmail/.indent.pro
postfix/showq/.indent.pro
postfix/smtp/.indent.pro
postfix/smtpd/.indent.pro
postfix/smtpd/smtpd.c
postfix/smtpd/smtpd.h
postfix/smtpd/smtpd_check.c
postfix/smtpd/smtpd_check.in
postfix/smtpd/smtpd_check.ref
postfix/smtpd/smtpd_state.c
postfix/smtpstone/.indent.pro
postfix/trivial-rewrite/.indent.pro
postfix/util/.indent.pro

index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 9a0eecf8d697d121cf758b5461ece34fbef09e46..99f4fa1d79de206ea305574eba1dd11e9827cdf2 100644 (file)
@@ -3039,3 +3039,40 @@ Apologies for any names omitted.
        and for upgrading Postfix. It replaces files instead of
        overwriting them, and leaves existing configuration and
        queue files intact.
+
+19990907
+
+       Bugfix: reject_non_fqdn_sender used the wrong test to see
+       if a sender address was given and could dump core. This
+       must have been broken ever since the UCE tests were moved
+       to the RCPT TO stage in 19990510.
+
+       Bugfix: check_sender_access was recognized as a valid
+       restriction name only if a sender had been specified.
+
+19990908
+
+       Portability: Unixware has <sysexits.h> only after sendmail
+       is installed. Changed postlock.c to use global/sys_exists.h.
+
+19990909
+
+       Performance: added one-entry cache to the address rewriting
+       client and to the address resolving client. This is because
+       UCE restrictions tend to produce the same query repeatedly.
+
+       Feature: the UCE restrictions are now fully recursive so
+       you can have per-client/helo/sender/recipient restrictions.
+       Instead of OK, REJECT or [45]xx, you can specify a sequence
+       of restrictions on the right-hand side of an SMTPD access
+       table. This means you can no longer use canonical/virtual/alias
+       maps as SMTPD access tables. But the loss is compensated for.
+
+       Feature: restriction classes, essentially a short-hand for
+       restriction lists.  These short hands are useful mostly on
+       the right-hand side of SMTPD access tables.
+
+       Feature: "permit_address_map maptype:mapname" permits a
+       recipient address when it matches the specified table.
+       Lookups are done just as with canonical/virtual maps.  With
+       this, you can also use passwd/aliases as SMTPD access maps.
index 6945c7c56c0626ac0d738b40f61fae6436e27ae9..fb3bd2c6228c696a4e515ea2347a1461379d96b9 100644 (file)
@@ -174,7 +174,7 @@ rm -f junk
 
 # Install files. Be careful to not copy over running programs.
 
-for file in `ls libexec`
+for file in `ls libexec | grep '^[a-z]'`
 do
     compare_or_replace a+x,go-w libexec/$file $daemon_directory/$file || exit 1
 done
index 6b58ef79d0ae2b9993d85ff0d063ac4ae1229a08..8e45a440133223a2d6c2a93fc7c0932d9e0582ea 100644 (file)
@@ -1,3 +1,51 @@
+Incompatible changes with snapshot 19990909
+===========================================
+
+- You can not longer use virtual, canonical or aliases tables as
+SMTPD access control tables. Use the permit_address_map feature
+instead. The loss is compensated for.
+
+Major changes with snapshot 19990909
+====================================
+
+- Per-client/helo/sender/recipient UCE restrictions: you can now
+specify arbitrary restrictions on the right-hand side of SMTPD
+access tables.  The only anomaly in this scheme is that header
+checks are the same for every message.
+
+- Restriction classes allow you to conveniently group restrictions
+under one name. This is great for per-client/helo/sender/recipient
+UCE restrictions.  For example in main.cf:
+
+    smtpd_restriction_classes = restrictive, permissive
+    restrictive = reject_unknown_sender reject_unknown_client ...
+    permissive = permit
+
+Then use "restrictive" or "restrictive" on the right-hand side of
+your per-client/helo/sender/recipient SMTPD access tables.
+
+- Reject mail for non-existent local accounts. You can now use
+passwd/canonical/virtual/aliases tables for SMTPD access control.
+For example, specify in main.cf:
+
+    relay_domains = $mydestination other domains...
+    smtpd_recipient_restrictions =
+       reject_unauth_destination
+       permit_address_map unix:passwd.byname
+       permit_address_map hash:/etc/canonical
+       permit_address_map hash:/etc/postfix/virtual
+       permit_address_map hash:/etc/aliases
+       reject
+
+That should stop a lot of the mail to non-existent recipients.  It
+won't stop mail to broken aliases or to users with broken .forward
+files, though.
+
+Unfortunately, permit_address_map does not combine well with
+check_relay_domains, because that restriction ALWAYS permits mail
+for local destinations. Instead of check_relay_domains, use some
+combination of permit_mynetworks and reject_unauth_destination.
+
 Incompatible changes with postfix-19990906
 ==========================================
 
@@ -7,7 +55,7 @@ files while delivering to files specified in aliases/forward/include
 files. This is a no-op when the recipient lacks directory write
 permission.
 
-- The LDAP client code no longer looks up name containing "*"
+- The LDAP client code no longer looks up name containing "*"
 because it could be abused.  See the LDAP_README file for how to
 restore previous behavior.
 
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index f2989510c9d4706cf9c28ed0f2834f030d5d34ce..7e622453888db7f7fc660d77845a5ee1b4ce8776 100644 (file)
@@ -203,6 +203,8 @@ smtpd_sender_restrictions =
 #   reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form
 #   reject_non_fqdn_sender: reject sender address that is not in FQDN form
 #   reject_non_fqdn_recipient: reject recipient address that is not in FQDN form
+#   permit_address_map maptype:mapname: permit if the recipient address matches
+#                  the table. Matching is as with virtual/canonical tables.
 #   reject: reject the request. Place this at the end of a restriction.
 #   permit: permit the request. Place this at the end of a restriction.
 #
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 204fb01404e9dc257bf179af2c4649ee86dd4100..32a95a91af4440c0ab07339098869b67a1d84e7b 100644 (file)
@@ -718,6 +718,10 @@ extern char *var_rcpt_checks;
 #define DEF_ETRN_CHECKS                ""
 extern char *var_etrn_checks;
 
+#define VAR_REST_CLASSES       "smtpd_restriction_classes"
+#define DEF_REST_CLASSES       ""
+extern char *var_rest_classes;
+
  /*
   * Names of specific restrictions, and the corresponding configuration
   * parameters that control the status codes sent in response to rejected
@@ -795,6 +799,8 @@ extern int var_smtpd_delay_reject;
 
 #define REJECT_UNAUTH_PIPE     "reject_unauth_pipelining"
 
+#define PERMIT_ADDR_MAP                "permit_address_map"
+
  /*
   * Other.
   */
index aca279b43fbc8394232e6d9c104867a270b5da14..f96a226a381ee9f9a867d1ea4f25caa2e01abd7a 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Postfix-19990906"
+#define DEF_MAIL_VERSION       "Snapshot-19990909"
 extern char *var_mail_version;
 
 /* LICENSE
index ae47df04bcd5538e0396fa7cb404f4addf0ed6c2..f8978da7b3856230c1937b02a81dcdbf66d74025 100644 (file)
@@ -80,6 +80,9 @@
   */
 extern CLNT_STREAM *rewrite_clnt_stream;
 
+static VSTRING *last_addr;
+static RESOLVE_REPLY last_reply;
+
 /* resolve_clnt_init - initialize reply */
 
 void    resolve_clnt_init(RESOLVE_REPLY *reply)
@@ -96,6 +99,14 @@ void    resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
     char   *myname = "resolve_clnt_query";
     VSTREAM *stream;
 
+    /*
+     * One-entry cache.
+     */
+    if (last_addr == 0) {
+       last_addr = vstring_alloc(100);
+       resolve_clnt_init(&last_reply);
+    }
+
     /*
      * Sanity check. The result must not clobber the input because we may
      * have to retransmit the request.
@@ -105,6 +116,20 @@ void    resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
     if (addr == STR(reply->recipient))
        msg_panic("%s: result clobbers input", myname);
 
+    /*
+     * Peek at the cache.
+     */
+    if (strcmp(addr, STR(last_addr)) == 0) {
+       vstring_strcpy(reply->transport, STR(last_reply.transport));
+       vstring_strcpy(reply->nexthop, STR(last_reply.nexthop));
+       vstring_strcpy(reply->recipient, STR(last_reply.recipient));
+       if (msg_verbose)
+           msg_info("%s: cached: `%s' -> t=`%s' h=`%s' r=`%s'",
+                    myname, addr, STR(reply->transport),
+                    STR(reply->nexthop), STR(reply->recipient));
+       return;
+    }
+
     /*
      * Keep trying until we get a complete response. The resolve service is
      * CPU bound; making the client asynchronous would just complicate the
@@ -139,6 +164,14 @@ void    resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
        sleep(10);                              /* XXX make configurable */
        clnt_stream_recover(rewrite_clnt_stream);
     }
+
+    /*
+     * Update the cache.
+     */
+    vstring_strcpy(last_addr, addr);
+    vstring_strcpy(last_reply.transport, STR(reply->transport));
+    vstring_strcpy(last_reply.nexthop, STR(reply->nexthop));
+    vstring_strcpy(last_reply.recipient, STR(reply->recipient));
 }
 
 /* resolve_clnt_free - destroy reply */
index cfbec3c502144f83c0c6770d24afd6eae407d716..f301304e1e6efb4cfc9753a4b70bb0cfb9e25d33 100644 (file)
@@ -71,6 +71,9 @@
   */
 CLNT_STREAM *rewrite_clnt_stream = 0;
 
+VSTRING *last_addr;
+VSTRING *last_result;
+
 /* rewrite_clnt - rewrite address to (transport, next hop, recipient) */
 
 VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
@@ -78,6 +81,14 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
     char   *myname = "rewrite_clnt";
     VSTREAM *stream;
 
+    /*
+     * One-entry cache.
+     */
+    if (last_addr == 0) {
+       last_addr = vstring_alloc(100);
+       last_result = vstring_alloc(100);
+    }
+
     /*
      * Sanity check. An address must be in externalized form. The result must
      * not clobber the input, because we may have to retransmit the query.
@@ -89,6 +100,17 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
     if (addr == STR(result))
        msg_panic("rewrite_clnt: result clobbers input");
 
+    /*
+     * Peek at the cache.
+     */
+    if (strcmp(addr, STR(last_addr)) == 0) {
+       vstring_strcpy(result, STR(last_result));
+       if (msg_verbose)
+           msg_info("rewrite_clnt: cached: %s: %s -> %s",
+                    rule, addr, vstring_str(result));
+       return (result);
+    }
+
     /*
      * Keep trying until we get a complete response. The rewrite service is
      * CPU bound and making the client asynchronous would just complicate the
@@ -111,16 +133,19 @@ VSTRING *rewrite_clnt(const char *rule, const char *addr, VSTRING *result)
            if (msg_verbose)
                msg_info("rewrite_clnt: %s: %s -> %s",
                         rule, addr, vstring_str(result));
-#if 0
-           if (addr[0] != 0 && STR(result)[0] == 0)
-               msg_warn("%s: null result for: <%s>", myname, addr);
-           else
-#endif
-               return (result);
+           break;
        }
        sleep(10);                              /* XXX make configurable */
        clnt_stream_recover(rewrite_clnt_stream);
     }
+
+    /*
+     * Update the cache.
+     */
+    vstring_strcpy(last_addr, addr);
+    vstring_strcpy(last_result, STR(result));
+
+    return (result);
 }
 
 /* rewrite_clnt_internal - rewrite from/to internal form */
index 354870d1b9262a606634477151cb3fb2bf25a4a2..d4dbafc105f24ebb5e6c82b851cc11ba27533acb 100644 (file)
@@ -203,46 +203,52 @@ SMTPD(8)                                                 SMTPD(8)
 SMTPD(8)                                                 SMTPD(8)
 
 
+       <b>restriction</b><i>_</i><b>classes</b>
+              Declares  the  name of zero or more parameters that
+              contain a list of UCE restrictions.  The  names  of
+              these  parameters  can  then be used instead of the
+              restriction lists that they represent.
+
        <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b>
-              List  of  DNS domains that publish the addresses of
+              List of DNS domains that publish the  addresses  of
               blacklisted hosts.
 
        <b>relay</b><i>_</i><b>domains</b>
-              Restrict what domains or networks this mail  system
+              Restrict  what domains or networks this mail system
               will relay mail from or to.
 
 <b>UCE</b> <b>control</b> <b>responses</b>
        <b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server  response  when  a client violates an access
+              Server response when a client  violates  an  access
               database restriction.
 
        <b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server  response  when  a   client   violates   the
+              Server   response   when   a  client  violates  the
               <b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction.
 
        <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server   response   when   a  client  violates  the
+              Server  response  when  a   client   violates   the
               <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> restriction.
 
        <b>reject</b><i>_</i><b>code</b>
-              Response code when  the  client  matches  a  <b>reject</b>
+              Response  code  when  the  client  matches a <b>reject</b>
               restriction.
 
        <b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server  response  when a client attempts to violate
+              Server response when a client attempts  to  violate
               the mail relay policy.
 
        <b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server  response  when  a   client   violates   the
+              Server   response   when   a  client  violates  the
               <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction.
 
        <b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server  response  when  a client without address to
-              name mapping  violates  the  <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
+              Server response when a client  without  address  to
+              name  mapping  violates  the <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>clients</b>
               restriction.
 
        <b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
-              Server   response   when   a  client  violates  the
+              Server  response  when  a   client   violates   the
               <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
 
 <b>SEE</b> <b>ALSO</b>
@@ -250,13 +256,7 @@ SMTPD(8)                                                 SMTPD(8)
        <a href="master.8.html">master(8)</a> process manager
        syslogd(8) system logging
 
-<b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
-       software.
 
-<b>AUTHOR(S)</b>
-       Wietse Venema
-       IBM T.J. Watson Research
 
 
 
@@ -269,6 +269,13 @@ SMTPD(8)                                                 SMTPD(8)
 SMTPD(8)                                                 SMTPD(8)
 
 
+<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
 
@@ -311,13 +318,6 @@ SMTPD(8)                                                 SMTPD(8)
 
 
 
-
-
-
-
-
-
-
 
 
 
index 6e113edfe170c8443da5a3a89b066736647a0948..1ccc8558c3838e0da28779d75863618b1bae5f42 100644 (file)
@@ -191,9 +191,10 @@ href="access.5.html">access database</a> for the client name, parent
 domains, client address, or networks obtained by stripping least
 significant octets.  Reject the request if the result is <b>REJECT</b>
 or "[<b>45</b>]<i>XX text</i>". Permit the request if the result
-is anything else.  The <b>access_map_reject_code</b> parameter
-specifies the response code for <b>REJECT</b> results (default:
-<b>554</b>).
+is <b>OK</b> or <b>RELAY</b>. Otherwise, treat the result as another
+list of UCE restrictions.  The <b>access_map_reject_code</b>
+parameter specifies the response code for <b>REJECT</b> results
+(default:  <b>554</b>).
 
 <p>
 
@@ -338,7 +339,8 @@ response code to rejected requests (default:  <b>504</b>).
 href="access.5.html">access database</a> for the <b>HELO</b> hostname
 or parent domains in the specified table.  Reject the request if
 the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit
-the request when the result is anything else.  The
+the request when the result is <b>OK</b> or <b>RELAY</b>. Otherwise,
+treat the result as another list of UCE restrictions.  The
 <b>access_map_reject_code </b> parameter specifies the response
 code for <b>REJECT</b> results (default:  <b>554</b>).
 
@@ -429,9 +431,10 @@ is always <b>450</b> in case of a temporary DNS error.
 href="access.5.html">access database</a> for the sender mail address,
 parent domain, or <i>localpart</i>@. Reject the request if the
 result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>". Permit the
-request if the result is anything else.  The <b>access_map_reject_code
-</b> parameter specifies the result code for rejected requests
-(default: <b>554</b>).
+request if the result is <b>OK</b> or <b>RELAY</b>. Otherwise,
+treat the result as another list of UCE restrictions.  The
+<b>access_map_reject_code </b> parameter specifies the result code
+for rejected requests (default: <b>554</b>).
 
 <p>
 
@@ -568,9 +571,10 @@ $inet_interfaces</a>.
 href="access.5.html">access database</a> for the resolved destination
 address, parent domain, or <i>localpart</i>@. Reject the request
 if the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>".
-Permit the request if the result is anything else.  The
-<b>access_map_reject_code </b> parameter specifies the result code
-for rejected requests (default: <b>554</b>).
+Permit the request if the result is <b>OK</b> or <b>RELAY</b>.
+Otherwise, treat the result as another list of UCE restrictions.
+The <b>access_map_reject_code </b> parameter specifies the result
+code for rejected requests (default: <b>554</b>).
 
 <p>
 
@@ -593,6 +597,16 @@ response code to rejected requests (default:  <b>504</b>).
 
 <p>
 
+<dt> <b>permit_address_map</b> <i>maptype</i>:<i>mapname</i> <dd>
+Permit the request when the recipient address matches the named
+table. Table lookup is done as with the <a
+href="virtual.5.html">virtual</a> and <a
+href="canonical.5.html">canonical</a> tables. This also produces
+useful results with the <a href="aliases.5.html">aliases</a> and
+<b>unix:passwd.byname</b> maps.
+
+<p>
+
 <dt> <b><a href="#reject_unknown_sender_domain">reject_unknown_sender_domain</a></b>
 
 <dt> <b><a href="#reject_non_fqdn_sender">reject_non_fqdn_sender</a></b>
@@ -691,9 +705,10 @@ address.
 href="access.5.html">access database</a> for the domain specified
 in the ETRN command, or its parent domains. Reject the request if
 the result is <b>REJECT</b> or "[<b>45</b>]<i>XX text</i>".  Permit
-the request if the result is anything else.  The <b>access_map_reject_code
-</b> parameter specifies the result code for rejected requests
-(default: <b>554</b>).
+the request if the result is <b>OK</b> or <b>RELAY</b>. Otherwise,
+treat the result as another list of UCE restrictions.  The
+<b>access_map_reject_code </b> parameter specifies the result code
+for rejected requests (default: <b>554</b>).
 
 <p>
 
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 9ff7a6df7da05c703591cb24cbb6501e72d36a0b..58050d44f93f60de35305f0ddb38587d9d50bd7a 100644 (file)
@@ -147,6 +147,10 @@ Restrict what recipient addresses are allowed in \fBRCPT TO\fR commands.
 .IP \fBsmtpd_etrn_restrictions\fR
 Restrict what domain names can be used in \fBETRN\fR commands,
 and what clients may issue \fBETRN\fR commands.
+.IP \fBrestriction_classes\fR
+Declares the name of zero or more parameters that contain a
+list of UCE restrictions. The names of these parameters can
+then be used instead of the restriction lists that they represent.
 .IP \fBmaps_rbl_domains\fR
 List of DNS domains that publish the addresses of blacklisted
 hosts.
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 0caa2b0cca3e88d688e68a1fcc5f33a62848cc87..ea9ec6aa61e13de1242953e77e5e41380e8cd9f9 100644 (file)
@@ -86,7 +86,6 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <errno.h>
-#include <sysexits.h>
 
 /* Utility library. */
 
 #include <dot_lockfile.h>
 #include <deliver_flock.h>
 #include <mail_conf.h>
+#include <sys_exits.h>
 
 /* Application-specific. */
 
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 84d7400246c26b08c8eba4abc472d3634645242a..5f2f5a0c31a9ae99ea18bf1ba0b6910c349cf871 100644 (file)
 /* .IP \fBsmtpd_etrn_restrictions\fR
 /*     Restrict what domain names can be used in \fBETRN\fR commands,
 /*     and what clients may issue \fBETRN\fR commands.
+/* .IP \fBrestriction_classes\fR
+/*     Declares the name of zero or more parameters that contain a
+/*     list of UCE restrictions. The names of these parameters can
+/*     then be used instead of the restriction lists that they represent.
 /* .IP \fBmaps_rbl_domains\fR
 /*     List of DNS domains that publish the addresses of blacklisted
 /*     hosts.
@@ -278,6 +282,7 @@ int     var_non_fqdn_code;
 char   *var_always_bcc;
 char   *var_error_rcpt;
 int     var_smtpd_delay_reject;
+char   *var_rest_classes;
 
  /*
   * Global state, for stand-alone mode queue file cleanup. When this is
@@ -1178,6 +1183,7 @@ int     main(int argc, char **argv)
        VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0,
        VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
        VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
+       VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0,
        0,
     };
 
index 5d6623fe9dac9eec19c7bb5ba1c8480c2502e783..4e72a08803c1e6529fbbb0b1aa36ca54a4e1acc7 100644 (file)
@@ -47,6 +47,7 @@ typedef struct SMTPD_STATE {
     char   *reason;
     char   *sender;
     char   *recipient;
+    char   *etrn_name;
     char   *protocol;
     char   *where;
 } SMTPD_STATE;
index 3460f3843a621198c9710e9773cd1fb06c7bf105..1cdd34ba5f2c5ee91cda4ac039a6a698df8c4400 100644 (file)
 /*     Allow the request when the local mail system is mail exchanger
 /*     for the recipient domain (this includes the case where the local
 /*     system is the final destination).
+/* .IP permit_address_map maptype:mapname
+/*     Permit the request when the recipient address matches the named
+/*     table. Lookups are done in the same way as with virtual and 
+/*     canonical maps.
+/* .IP restriction_classes
+/*     Defines a list of parameter names, each parameter being a list
+/*     of restrictions that can be used anywhere a restriction is legal.
 /* .PP
 /*     smtpd_check_client() validates the client host name or address.
 /*     Relevant configuration parameters:
 #include <argv.h>
 #include <mymalloc.h>
 #include <dict.h>
+#include <htable.h>
 
 /* DNS library. */
 
 #include <mail_error.h>
 #include <resolve_local.h>
 #include <own_inet_addr.h>
+#include <mail_conf.h>
+#include <maps.h>
+#include <mail_addr_find.h>
 
 /* Application-specific. */
 
@@ -302,6 +313,15 @@ static ARGV *mail_restrctions;
 static ARGV *rcpt_restrctions;
 static ARGV *etrn_restrctions;
 
+static HTABLE *smtpd_rest_classes;
+
+static HTABLE *smtpd_addr_maps;
+
+ /*
+  * The routine that recursively applies restrictions.
+  */
+static int generic_checks(SMTPD_STATE *, ARGV *, char *, char *, char *);
+
  /*
   * Reject context.
   */
@@ -318,7 +338,7 @@ static ARGV *etrn_restrctions;
 
 /* smtpd_check_parse - pre-parse restrictions */
 
-static ARGV *smtpd_check_parse(char *checks)
+static ARGV *smtpd_check_parse(const char *checks)
 {
     char   *saved_checks = mystrdup(checks);
     ARGV   *argv = argv_alloc(1);
@@ -348,6 +368,10 @@ static ARGV *smtpd_check_parse(char *checks)
 
 void    smtpd_check_init(void)
 {
+    char   *saved_classes;
+    const char *name;
+    const char *value;
+    char   *cp;
 
     /*
      * Pre-open access control lists before going to jail.
@@ -372,6 +396,35 @@ void    smtpd_check_init(void)
     mail_restrctions = smtpd_check_parse(var_mail_checks);
     rcpt_restrctions = smtpd_check_parse(var_rcpt_checks);
     etrn_restrctions = smtpd_check_parse(var_etrn_checks);
+
+    /*
+     * Parse the pre-defined restriction classes.
+     */
+    smtpd_rest_classes = htable_create(1);
+    if (*var_rest_classes) {
+       cp = saved_classes = mystrdup(var_rest_classes);
+       while ((name = mystrtok(&cp, " \t\r\n,")) != 0) {
+           if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
+               msg_fatal("restriction class `%s' needs a definition", name);
+           htable_enter(smtpd_rest_classes, name,
+                        (char *) smtpd_check_parse(value));
+       }
+       myfree(saved_classes);
+    }
+
+    /*
+     * This is the place to specify definitions for complex restrictions
+     * such as check_relay_domains in terms of more elementary restrictions.
+     */
+#if 0
+    htable_enter("check_relay_domains",
+           smtpd_check_parse("permit_mydomain reject_unauth_destination"));
+#endif
+
+    /*
+     * Other one-off initializations.
+     */
+    smtpd_addr_maps = htable_create(1);
 }
 
 /* smtpd_check_reject - do the boring things that must be done */
@@ -946,14 +999,61 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
     return (reject_unknown_mailhost(state, domain, reply_name, reply_class));
 }
 
+/* permit_addr_map - permit if address matches rewriting table */
+
+static int permit_addr_map(SMTPD_STATE *state, char *table,
+                                  char *reply_name, char *reply_class)
+{
+    char   *myname = "permit_addr_map";
+    char   *domain;
+    MAPS   *map;
+
+    if (msg_verbose)
+       msg_info("%s: %s %s", myname, table, reply_name);
+
+    /*
+     * Resolve the address.
+     */
+    canon_addr_internal(query, reply_name);
+    resolve_clnt_query(STR(query), &reply);
+
+    /*
+     * Skip non-DNS forms. Skip non-local numerical forms.
+     */
+    if ((domain = strrchr(STR(reply.recipient), '@')) == 0)
+       return (SMTPD_CHECK_DUNNO);
+    domain += 1;
+    if (domain[0] == '#' || domain[0] == '[')
+       if (STR(reply.nexthop)[0] != 0)
+           return (SMTPD_CHECK_DUNNO);
+
+    /*
+     * Look up the name in the specified table, using the usual magic of
+     * canonical and virtual maps.
+     */
+    if ((map = (MAPS *) htable_find(smtpd_addr_maps, table)) == 0) {
+       map = maps_create("addr_map", table, DICT_FLAG_LOCK);
+       htable_enter(smtpd_addr_maps, table, (char *) map);
+    }
+#define TOSS_THE_EXTENSION ((char **) 0)
+
+    if (mail_addr_find(map, STR(reply.recipient), TOSS_THE_EXTENSION) != 0)
+       return (SMTPD_CHECK_OK);
+
+    return (SMTPD_CHECK_DUNNO);
+}
+
 /* check_table_result - translate table lookup result into pass/reject */
 
 static int check_table_result(SMTPD_STATE *state, char *table,
                                      const char *value, const char *datum,
-                                     char *reply_name, char *reply_class)
+                                     char *reply_name, char *reply_class,
+                                     char *def_acl)
 {
     char   *myname = "check_table_result";
     int     code;
+    ARGV   *restrictions;
+    int     status;
 
     if (msg_verbose)
        msg_info("%s: %s %s %s", myname, table, value, datum);
@@ -986,15 +1086,25 @@ static int check_table_result(SMTPD_STATE *state, char *table,
     }
 
     /*
-     * OK or RELAY or whatever means YES.
+     * OK or RELAY means YES.
+     */
+    if (strcasecmp(value, "OK") == 0 || strcasecmp(value, "RELAY") == 0)
+       return (SMTPD_CHECK_OK);
+
+    /*
+     * XXX Don't use passwd files or address rewriting maps as access tables.
      */
-    return (SMTPD_CHECK_OK);
+    restrictions = argv_split(value, " \t\r\n,");
+    status = generic_checks(state, restrictions, reply_name,
+                           reply_class, def_acl);
+    argv_free(restrictions);
+    return (status);
 }
 
 /* check_access - table lookup without substring magic */
 
 static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
-                               char *reply_name, char *reply_class)
+                        char *reply_name, char *reply_class, char *def_acl)
 {
     char   *myname = "check_access";
     char   *low_name = lowercase(mystrdup(name));
@@ -1013,7 +1123,8 @@ static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
     if (flags == 0 || (flags & dict->flags) != 0) {
        if ((value = dict_get(dict, low_name)) != 0)
            CHK_ACCESS_RETURN(check_table_result(state, table, value, name,
-                                                reply_name, reply_class));
+                                                reply_name, reply_class,
+                                                def_acl));
        if (dict_errno != 0)
            msg_fatal("%s: table lookup problem", table);
     }
@@ -1024,7 +1135,8 @@ static int check_access(SMTPD_STATE *state, char *table, char *name, int flags,
 
 static int check_domain_access(SMTPD_STATE *state, char *table,
                                       char *domain, int flags,
-                                      char *reply_name, char *reply_class)
+                                      char *reply_name, char *reply_class,
+                                      char *def_acl)
 {
     char   *myname = "check_domain_access";
     char   *low_domain = lowercase(mystrdup(domain));
@@ -1047,7 +1159,8 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
        if (flags == 0 || (flags & dict->flags) != 0) {
            if ((value = dict_get(dict, name)) != 0)
                CHK_DOMAIN_RETURN(check_table_result(state, table, value,
-                                         domain, reply_name, reply_class));
+                                           domain, reply_name, reply_class,
+                                                    def_acl));
            if (dict_errno != 0)
                msg_fatal("%s: table lookup problem", table);
        }
@@ -1060,7 +1173,8 @@ static int check_domain_access(SMTPD_STATE *state, char *table,
 
 static int check_addr_access(SMTPD_STATE *state, char *table,
                                     char *address, int flags,
-                                    char *reply_name, char *reply_class)
+                                    char *reply_name, char *reply_class,
+                                    char *def_acl)
 {
     char   *myname = "check_addr_access";
     char   *addr;
@@ -1081,7 +1195,8 @@ static int check_addr_access(SMTPD_STATE *state, char *table,
        if (flags == 0 || (flags & dict->flags) != 0) {
            if ((value = dict_get(dict, addr)) != 0)
                return (check_table_result(state, table, value, address,
-                                          reply_name, reply_class));
+                                          reply_name, reply_class,
+                                          def_acl));
            if (dict_errno != 0)
                msg_fatal("%s: table lookup problem", table);
        }
@@ -1095,7 +1210,8 @@ static int check_addr_access(SMTPD_STATE *state, char *table,
 
 static int check_namadr_access(SMTPD_STATE *state, char *table,
                                       char *name, char *addr, int flags,
-                                      char *reply_name, char *reply_class)
+                                      char *reply_name, char *reply_class,
+                                      char *def_acl)
 {
     char   *myname = "check_namadr_access";
     int     status;
@@ -1108,14 +1224,16 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
      * wildcard may pre-empt a more specific address table entry.
      */
     if ((status = check_domain_access(state, table, name, flags,
-                                     reply_name, reply_class)) != 0)
+                                     reply_name, reply_class,
+                                     def_acl)) != 0)
        return (status);
 
     /*
      * Look up the network address, or parent networks thereof.
      */
     if ((status = check_addr_access(state, table, addr, flags,
-                                   reply_name, reply_class)) != 0)
+                                   reply_name, reply_class,
+                                   def_acl)) != 0)
        return (status);
 
     /*
@@ -1127,7 +1245,8 @@ static int check_namadr_access(SMTPD_STATE *state, char *table,
 /* check_mail_access - OK/FAIL based on mail address lookup */
 
 static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
-                                    char *reply_name, char *reply_class)
+                                    char *reply_name, char *reply_class,
+                                    char *def_acl)
 {
     char   *myname = "check_mail_access";
     char   *ratsign;
@@ -1156,14 +1275,14 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
      * Look up the full address.
      */
     if ((status = check_access(state, table, STR(reply.recipient), FULL,
-                              reply_name, reply_class)) != 0)
+                              reply_name, reply_class, def_acl)) != 0)
        return (status);
 
     /*
      * Look up the domain name, or parent domains thereof.
      */
     if ((status = check_domain_access(state, table, ratsign + 1, PARTIAL,
-                                     reply_name, reply_class)) != 0)
+                                   reply_name, reply_class, def_acl)) != 0)
        return (status);
 
     /*
@@ -1172,7 +1291,7 @@ static int check_mail_access(SMTPD_STATE *state, char *table, char *addr,
     local_at = mystrndup(STR(reply.recipient),
                         ratsign - STR(reply.recipient) + 1);
     status = check_access(state, table, local_at, PARTIAL,
-                         reply_name, reply_class);
+                         reply_name, reply_class, def_acl);
     myfree(local_at);
     if (status != 0)
        return (status);
@@ -1267,170 +1386,226 @@ static int is_map_command(char *name, char *command, char ***argp)
 
 /* generic_checks - generic restrictions */
 
-static int generic_checks(SMTPD_STATE *state, char *name,
-                                 char ***cpp, int *status,
-                                 char *reply_name, char *reply_class)
+static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
+                        char *reply_name, char *reply_class, char *def_acl)
 {
+    char   *myname = "generic_checks";
+    char  **cpp;
+    char   *name;
+    int     status;
+    ARGV   *list;
 
-    /*
-     * Generic restrictions.
-     */
-    if (strcasecmp(name, PERMIT_ALL) == 0) {
-       *status = SMTPD_CHECK_OK;
-       if ((*cpp)[1] != 0)
-           msg_warn("restriction `%s' after `%s' is ignored",
-                    (*cpp)[1], PERMIT_ALL);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_ALL) == 0) {
-       *status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
-                                    "%d <%s>: %s rejected: Access denied",
+    status = setjmp(smtpd_check_buf);
+    if (status != 0)
+       return (0);
+
+    if (msg_verbose)
+       msg_info("%s: START", myname);
+
+    for (cpp = restrictions->argv; (name = *cpp) != 0; cpp++) {
+
+       if (msg_verbose)
+           msg_info("%s: name=%s", myname, name);
+
+       /*
+        * Spoof the is_map_command() routine, so that we do not have to make
+        * special cases for the implicit short-hand access map notation.
+        */
+       if (strchr(name, ':') != 0) {
+           name = def_acl;
+           cpp -= 1;
+       }
+
+       /*
+        * Generic restrictions.
+        */
+       if (strcasecmp(name, PERMIT_ALL) == 0) {
+           status = SMTPD_CHECK_OK;
+           if (cpp[1] != 0)
+               msg_warn("restriction `%s' after `%s' is ignored",
+                        cpp[1], PERMIT_ALL);
+       } else if (strcasecmp(name, REJECT_ALL) == 0) {
+           status = smtpd_check_reject(state, MAIL_ERROR_POLICY,
+                                     "%d <%s>: %s rejected: Access denied",
                                  var_reject_code, reply_name, reply_class);
-       if ((*cpp)[1] != 0)
-           msg_warn("restriction `%s' after `%s' is ignored",
-                    (*cpp)[1], REJECT_ALL);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) {
-       *status = reject_unauth_pipelining(state);
-       return (1);
-    }
+           if (cpp[1] != 0)
+               msg_warn("restriction `%s' after `%s' is ignored",
+                        cpp[1], REJECT_ALL);
+       } else if (strcasecmp(name, REJECT_UNAUTH_PIPE) == 0) {
+           status = reject_unauth_pipelining(state);
+       }
 
-    /*
-     * Client name/address restrictions.
-     */
-    if (strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
-       *status = reject_unknown_client(state);
-       return (1);
-    }
-    if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
-       *status = permit_mynetworks(state);
-       return (1);
-    }
-    if (is_map_command(name, CHECK_CLIENT_ACL, cpp)) {
-       *status = check_namadr_access(state, **cpp, state->name, state->addr,
-                                  FULL, state->namaddr, SMTPD_NAME_CLIENT);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
-       *status = reject_maps_rbl(state);
-       return (1);
-    }
+       /*
+        * Client name/address restrictions.
+        */
+       else if (strcasecmp(name, REJECT_UNKNOWN_CLIENT) == 0) {
+           status = reject_unknown_client(state);
+       } else if (strcasecmp(name, PERMIT_MYNETWORKS) == 0) {
+           status = permit_mynetworks(state);
+       } else if (is_map_command(name, CHECK_CLIENT_ACL, &cpp)) {
+           status = check_namadr_access(state, *cpp, state->name, state->addr,
+                                        FULL, state->namaddr,
+                                        SMTPD_NAME_CLIENT, def_acl);
+       } else if (strcasecmp(name, REJECT_MAPS_RBL) == 0) {
+           status = reject_maps_rbl(state);
+       }
 
-    /*
-     * HELO/EHLO parameter restrictions.
-     */
-    if (is_map_command(name, CHECK_HELO_ACL, cpp) && state->helo_name) {
-       if (state->helo_name)
-           *status = check_domain_access(state, **cpp, state->helo_name, FULL,
-                                         state->helo_name, SMTPD_NAME_HELO);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
-       if (state->helo_name) {
-           if (*state->helo_name != '[')
-               *status = reject_invalid_hostname(state, state->helo_name,
+       /*
+        * HELO/EHLO parameter restrictions.
+        */
+       else if (is_map_command(name, CHECK_HELO_ACL, &cpp)) {
+           if (state->helo_name)
+               status = check_domain_access(state, *cpp, state->helo_name,
+                                            FULL, state->helo_name,
+                                            SMTPD_NAME_HELO, def_acl);
+       } else if (strcasecmp(name, REJECT_INVALID_HOSTNAME) == 0) {
+           if (state->helo_name) {
+               if (*state->helo_name != '[')
+                   status = reject_invalid_hostname(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
-           else
-               *status = reject_invalid_hostaddr(state, state->helo_name,
+               else
+                   status = reject_invalid_hostaddr(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
-       }
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
-       if (state->helo_name) {
-           if (*state->helo_name != '[')
-               *status = reject_unknown_hostname(state, state->helo_name,
+           }
+       } else if (strcasecmp(name, REJECT_UNKNOWN_HOSTNAME) == 0) {
+           if (state->helo_name) {
+               if (*state->helo_name != '[')
+                   status = reject_unknown_hostname(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
-           else
-               *status = reject_invalid_hostaddr(state, state->helo_name,
+               else
+                   status = reject_invalid_hostaddr(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
-       }
-       return (1);
-    }
-    if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
-       if (state->helo_name) {
-           if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
-             && (*status = reject_invalid_hostaddr(state, state->helo_name,
+           }
+       } else if (strcasecmp(name, PERMIT_NAKED_IP_ADDR) == 0) {
+           if (state->helo_name) {
+               if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
+               && (status = reject_invalid_hostaddr(state, state->helo_name,
                                   state->helo_name, SMTPD_NAME_HELO)) == 0)
-               *status = SMTPD_CHECK_OK;
-       }
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
-       if (state->helo_name) {
-           if (*state->helo_name != '[')
-               *status = reject_non_fqdn_hostname(state, state->helo_name,
+                   status = SMTPD_CHECK_OK;
+           }
+       } else if (strcasecmp(name, REJECT_NON_FQDN_HOSTNAME) == 0) {
+           if (state->helo_name) {
+               if (*state->helo_name != '[')
+                   status = reject_non_fqdn_hostname(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
-           else
-               *status = reject_invalid_hostaddr(state, state->helo_name,
+               else
+                   status = reject_invalid_hostaddr(state, state->helo_name,
                                         state->helo_name, SMTPD_NAME_HELO);
+           }
        }
-       return (1);
-    }
 
-    /*
-     * Sender mail address restrictions.
-     */
-    if (is_map_command(name, CHECK_SENDER_ACL, cpp) && state->sender) {
-       if (state->sender)
-           *status = check_mail_access(state, **cpp, state->sender,
-                                       state->sender, SMTPD_NAME_SENDER);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
-       if (state->sender)
-           *status = reject_unknown_address(state, state->sender,
+       /*
+        * Sender mail address restrictions.
+        */
+       else if (is_map_command(name, CHECK_SENDER_ACL, &cpp)) {
+           if (state->sender)
+               status = check_mail_access(state, *cpp, state->sender,
+                                          state->sender,
+                                          SMTPD_NAME_SENDER, def_acl);
+       } else if (strcasecmp(name, REJECT_UNKNOWN_ADDRESS) == 0) {
+           if (state->sender)
+               status = reject_unknown_address(state, state->sender,
                                          state->sender, SMTPD_NAME_SENDER);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) {
-       if (state->sender)
-           *status = reject_unknown_address(state, state->sender,
+       } else if (strcasecmp(name, REJECT_UNKNOWN_SENDDOM) == 0) {
+           if (state->sender)
+               status = reject_unknown_address(state, state->sender,
                                          state->sender, SMTPD_NAME_SENDER);
-       return (1);
-    }
-    if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
-       if (*state->sender)
-           *status = reject_non_fqdn_address(state, state->sender,
+       } else if (strcasecmp(name, REJECT_NON_FQDN_SENDER) == 0) {
+           if (state->sender && *state->sender)
+               status = reject_non_fqdn_address(state, state->sender,
                                          state->sender, SMTPD_NAME_SENDER);
-       return (1);
+       }
+
+       /*
+        * Recipient mail address restrictions.
+        */
+       else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
+           if (state->recipient)
+               status = check_mail_access(state, *cpp, state->recipient,
+                                          state->recipient,
+                                          SMTPD_NAME_RECIPIENT, def_acl);
+       } else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
+           if (state->recipient)
+               status = permit_mx_backup(state, state->recipient);
+       } else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) {
+           if (state->recipient)
+               status = reject_unauth_destination(state, state->recipient);
+       } else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
+           if (state->recipient)
+               status = check_relay_domains(state, state->recipient,
+                                   state->recipient, SMTPD_NAME_RECIPIENT);
+           if (cpp[1] != 0)
+               msg_warn("restriction `%s' after `%s' is ignored",
+                        cpp[1], CHECK_RELAY_DOMAINS);
+       } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
+           if (state->recipient)
+               status = reject_unknown_address(state, state->recipient,
+                                   state->recipient, SMTPD_NAME_RECIPIENT);
+       } else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
+           if (state->recipient)
+               status = reject_non_fqdn_address(state, state->recipient,
+                                   state->recipient, SMTPD_NAME_RECIPIENT);
+       } else if (is_map_command(name, PERMIT_ADDR_MAP, &cpp)) {
+           if (state->recipient)
+               status = permit_addr_map(state, *cpp,
+                                   state->recipient, SMTPD_NAME_RECIPIENT);
+       }
+
+       /*
+        * ETRN domain name restrictions.
+        */
+       else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
+           if (state->etrn_name)
+               status = check_domain_access(state, *cpp, state->etrn_name,
+                                            FULL, state->etrn_name,
+                                            SMTPD_NAME_ETRN, def_acl);
+       }
+
+       /*
+        * User-defined restriction class.
+        */
+       else if ((list = (ARGV *) htable_find(smtpd_rest_classes, name)) != 0) {
+           status = generic_checks(state, list, reply_name,
+                                   reply_class, def_acl);
+       }
+
+       /*
+        * Error: undefined restriction name.
+        */
+       else {
+           msg_warn("unknown smtpd restriction: \"%s\"", name);
+           break;
+       }
+       if (msg_verbose)
+           msg_info("%s: name=%s status=%d", myname, name, status);
+
+       if (status != 0)
+           break;
     }
-    return (0);
+    if (msg_verbose && name == 0)
+       msg_info("%s: END", myname);
+
+    return (status);
 }
 
 /* smtpd_check_client - validate client name or address */
 
 char   *smtpd_check_client(SMTPD_STATE *state)
 {
-    char  **cpp;
-    char   *name;
     int     status;
 
     /*
      * Initialize.
      */
-    if (state->name == 0 && state->addr == 0)
-       return (0);
-    status = setjmp(smtpd_check_buf);
-    if (status != 0)
+    if (state->name == 0 || state->addr == 0)
        return (0);
 
     /*
      * Apply restrictions in the order as specified.
      */
-    for (cpp = client_restrctions->argv; (name = *cpp) != 0; cpp++) {
-       if (strchr(name, ':') != 0) {
-           status = check_namadr_access(state, name, state->name, state->addr,
-                                  FULL, state->namaddr, SMTPD_NAME_CLIENT);
-       } else if (generic_checks(state, name, &cpp, &status,
-                                 state->namaddr, SMTPD_NAME_CLIENT) == 0) {
-           msg_warn("unknown %s check: \"%s\"", VAR_CLIENT_CHECKS, name);
-           break;
-       }
-       if (status != 0)
-           break;
-    }
+    status = generic_checks(state, client_restrctions, state->namaddr,
+                           SMTPD_NAME_CLIENT, CHECK_CLIENT_ACL);
+
     return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
@@ -1438,90 +1613,84 @@ char   *smtpd_check_client(SMTPD_STATE *state)
 
 char   *smtpd_check_helo(SMTPD_STATE *state, char *helohost)
 {
-    char  **cpp;
-    char   *name;
     int     status;
-    char   *saved_helo = state->helo_name;
+    char   *saved_helo;
 
     /*
      * Initialize.
      */
     if (helohost == 0)
        return (0);
-    status = setjmp(smtpd_check_buf);
-    if (status != 0)
-       return (0);
 
     /*
-     * Apply restrictions in the order as specified. Minor kluge so that we
-     * can delegate work to the generic routine.
+     * Minor kluge so that we can delegate work to the generic routine and so
+     * that we can syslog the recipient with the reject messages.
      */
-    state->helo_name = mystrdup(helohost);
-    for (cpp = helo_restrctions->argv; (name = *cpp) != 0; cpp++) {
-       if (strchr(name, ':') != 0) {
-           status = check_domain_access(state, name, helohost, FULL,
-                                        helohost, SMTPD_NAME_HELO);
-       } else if (generic_checks(state, name, &cpp, &status,
-                                 helohost, SMTPD_NAME_HELO) == 0) {
-           msg_warn("unknown %s check: \"%s\"", VAR_HELO_CHECKS, name);
-           break;
-       }
-       if (status != 0)
-           break;
+#define SMTPD_CHECK_PUSH(backup, current, new) { \
+       backup = current; \
+       current = mystrdup(new); \
     }
-    myfree(state->helo_name);
-    state->helo_name = saved_helo;
-    return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
+
+#define SMTPD_CHECK_POP(current, backup) { \
+       myfree(current); \
+       current = backup; \
+    }
+
+    SMTPD_CHECK_PUSH(saved_helo, state->helo_name, helohost);
+
+#define SMTPD_CHECK_HELO_RETURN(x) { \
+       SMTPD_CHECK_POP(state->helo_name, saved_helo); \
+       return (x); \
+    }
+
+    /*
+     * Apply restrictions in the order as specified.
+     */
+    status = generic_checks(state, helo_restrctions, state->helo_name,
+                           SMTPD_NAME_HELO, CHECK_HELO_ACL);
+
+    SMTPD_CHECK_HELO_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
-/* smtpd_check_mail - validate sender address */
+/* smtpd_check_mail - validate sender address, driver */
 
 char   *smtpd_check_mail(SMTPD_STATE *state, char *sender)
 {
-    char  **cpp;
-    char   *name;
     int     status;
-    char   *saved_sender = state->sender;
+    char   *saved_sender;
 
     /*
      * Initialize.
      */
     if (sender == 0)
        return (0);
-    status = setjmp(smtpd_check_buf);
-    if (status != 0)
-       return (0);
 
     /*
-     * Apply restrictions in the order as specified. Minor kluge so that we
-     * can delegate work to the generic routine.
+     * Minor kluge so that we can delegate work to the generic routine and so
+     * that we can syslog the recipient with the reject messages.
      */
-    state->sender = mystrdup(sender);
-    for (cpp = mail_restrctions->argv; (name = *cpp) != 0; cpp++) {
-       if (strchr(name, ':') != 0) {
-           status = check_mail_access(state, name, sender,
-                                      sender, SMTPD_NAME_SENDER);
-       } else if (generic_checks(state, name, &cpp, &status,
-                                 sender, SMTPD_NAME_SENDER) == 0) {
-           msg_warn("unknown %s check: \"%s\"", VAR_MAIL_CHECKS, name);
-           return (0);
-       }
-       if (status != 0)
-           break;
+    SMTPD_CHECK_PUSH(saved_sender, state->sender, sender);
+
+#define SMTPD_CHECK_MAIL_RETURN(x) { \
+       SMTPD_CHECK_POP(state->sender, saved_sender); \
+       return (x); \
     }
-    myfree(state->sender);
-    state->sender = saved_sender;
-    return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
+
+    /*
+     * Apply restrictions in the order as specified.
+     */
+    status = generic_checks(state, mail_restrctions, sender,
+                           SMTPD_NAME_SENDER, CHECK_SENDER_ACL);
+
+    SMTPD_CHECK_MAIL_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
-/* smtpd_check_rcpt - validate recipient address */
+/* smtpd_check_rcpt - validate recipient address, driver */
 
 char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
 {
-    char  **cpp;
-    char   *name;
     int     status;
-    char   *saved_recipient = state->recipient;
+    char   *saved_recipient;
     char   *err;
 
     /*
@@ -1534,11 +1703,10 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
      * Minor kluge so that we can delegate work to the generic routine and so
      * that we can syslog the recipient with the reject messages.
      */
-    state->recipient = mystrdup(recipient);
+    SMTPD_CHECK_PUSH(saved_recipient, state->recipient, recipient);
 
 #define SMTPD_CHECK_RCPT_RETURN(x) { \
-       myfree(state->recipient); \
-       state->recipient = saved_recipient; \
+       SMTPD_CHECK_POP(state->recipient, saved_recipient); \
        return (x); \
     }
 
@@ -1551,47 +1719,12 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
            || (err = smtpd_check_mail(state, state->sender)) != 0)
            SMTPD_CHECK_RCPT_RETURN(err);
 
-    /*
-     * More initialization.
-     */
-    status = setjmp(smtpd_check_buf);
-    if (status != 0)
-       SMTPD_CHECK_RCPT_RETURN(0);
-
     /*
      * Apply restrictions in the order as specified.
      */
-    for (cpp = rcpt_restrctions->argv; (name = *cpp) != 0; cpp++) {
-       if (strchr(name, ':') != 0) {
-           status = check_mail_access(state, name, recipient,
-                                      recipient, SMTPD_NAME_RECIPIENT);
-       } else if (is_map_command(name, CHECK_RECIP_ACL, &cpp)) {
-           status = check_mail_access(state, *cpp, recipient,
-                                      recipient, SMTPD_NAME_RECIPIENT);
-       } else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
-           status = permit_mx_backup(state, recipient);
-       } else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) {
-           status = reject_unauth_destination(state, recipient);
-       } else if (strcasecmp(name, CHECK_RELAY_DOMAINS) == 0) {
-           status = check_relay_domains(state, recipient,
-                                        recipient, SMTPD_NAME_RECIPIENT);
-           if (cpp[1] != 0)
-               msg_warn("restriction `%s' after `%s' is ignored",
-                        cpp[1], CHECK_RELAY_DOMAINS);
-       } else if (strcasecmp(name, REJECT_UNKNOWN_RCPTDOM) == 0) {
-           status = reject_unknown_address(state, recipient,
-                                           recipient, SMTPD_NAME_RECIPIENT);
-       } else if (strcasecmp(name, REJECT_NON_FQDN_RCPT) == 0) {
-           status = reject_non_fqdn_address(state, recipient,
-                                          recipient, SMTPD_NAME_RECIPIENT);
-       } else if (generic_checks(state, name, &cpp, &status,
-                                 recipient, SMTPD_NAME_RECIPIENT) == 0) {
-           msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
-           break;
-       }
-       if (status != 0)
-           break;
-    }
+    status = generic_checks(state, rcpt_restrctions,
+                         recipient, SMTPD_NAME_RECIPIENT, CHECK_RECIP_ACL);
+
     SMTPD_CHECK_RCPT_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
@@ -1599,47 +1732,42 @@ char   *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
 
 char   *smtpd_check_etrn(SMTPD_STATE *state, char *domain)
 {
-    char  **cpp;
-    char   *name;
     int     status;
+    char   *saved_etrn_name;
     char   *err;
 
+    /*
+     * Initialize.
+     */
+    if (domain == 0)
+       return (0);
+
+    /*
+     * Minor kluge so that we can delegate work to the generic routine and so
+     * that we can syslog the recipient with the reject messages.
+     */
+    SMTPD_CHECK_PUSH(saved_etrn_name, state->etrn_name, domain);
+
+#define SMTPD_CHECK_ETRN_RETURN(x) { \
+       SMTPD_CHECK_POP(state->etrn_name, saved_etrn_name); \
+       return (x); \
+    }
+
     /*
      * Apply delayed restrictions.
      */
     if (var_smtpd_delay_reject)
        if ((err = smtpd_check_client(state)) != 0
            || (err = smtpd_check_helo(state, state->helo_name)) != 0)
-           return (err);
-
-    /*
-     * Initialize.
-     */
-    if (domain == 0)
-       return (0);
-    status = setjmp(smtpd_check_buf);
-    if (status != 0)
-       return (0);
+           SMTPD_CHECK_ETRN_RETURN(err);
 
     /*
      * Apply restrictions in the order as specified.
      */
-    for (cpp = etrn_restrctions->argv; (name = *cpp) != 0; cpp++) {
-       if (strchr(name, ':') != 0) {
-           status = check_domain_access(state, name, domain, FULL,
-                                        domain, SMTPD_NAME_ETRN);
-       } else if (is_map_command(name, CHECK_ETRN_ACL, &cpp)) {
-           status = check_domain_access(state, *cpp, domain, FULL,
-                                        domain, SMTPD_NAME_ETRN);
-       } else if (generic_checks(state, name, &cpp, &status,
-                                 domain, SMTPD_NAME_ETRN) == 0) {
-           msg_warn("unknown %s check: \"%s\"", VAR_RCPT_CHECKS, name);
-           break;
-       }
-       if (status != 0)
-           break;
-    }
-    return (status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
+    status = generic_checks(state, etrn_restrctions, domain,
+                           SMTPD_NAME_ETRN, CHECK_ETRN_ACL);
+
+    SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0);
 }
 
 /* smtpd_check_size - check optional SIZE parameter value */
@@ -1661,6 +1789,7 @@ char   *smtpd_check_size(SMTPD_STATE *state, off_t size)
        return (STR(error_text));
     }
     fsspace(".", &fsbuf);
+
     if (msg_verbose)
        msg_info("%s: blocks %lu avail %lu min_free %lu size %lu",
                 myname,
@@ -1713,6 +1842,7 @@ char   *var_notify_classes = "";
 char   *var_maps_rbl_domains;
 char   *var_mydest;
 char   *var_inet_interfaces;
+char   *var_rest_classes;
 
 typedef struct {
     char   *name;
@@ -1724,6 +1854,7 @@ static STRING_TABLE string_table[] = {
     VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains,
     VAR_MYDEST, DEF_MYDEST, &var_mydest,
     VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces,
+    VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes,
     0,
 };
 
@@ -1822,9 +1953,9 @@ static int int_update(char **argv)
 typedef struct {
     char   *name;
     ARGV  **target;
-}       REST_TABLE;
+} SMTPD_REST_TABLE;
 
-static REST_TABLE rest_table[] = {
+static SMTPD_REST_TABLE smtpd_rest_table[] = {
     "client_restrictions", &client_restrctions,
     "helo_restrictions", &helo_restrctions,
     "sender_restrictions", &mail_restrctions,
@@ -1833,13 +1964,13 @@ static REST_TABLE rest_table[] = {
     0,
 };
 
-/* rest_update - update restriction */
+/* smtpd_rest_update - update restriction */
 
-static int rest_update(char **argv)
+static int smtpd_rest_update(char **argv)
 {
-    REST_TABLE *rp;
+    SMTPD_REST_TABLE *rp;
 
-    for (rp = rest_table; rp->name; rp++) {
+    for (rp = smtpd_rest_table; rp->name; rp++) {
        if (strcasecmp(rp->name, argv[0]) == 0) {
            argv_free(rp->target[0]);
            rp->target[0] = smtpd_check_parse(argv[1]);
@@ -1980,7 +2111,7 @@ main(int argc, char **argv)
            }
            if (int_update(args->argv)
                || string_update(args->argv)
-               || rest_update(args->argv)) {
+               || smtpd_rest_update(args->argv)) {
                resp = 0;
                break;
            }
index a395b94e64f8cebd97fe3f15caef1128fc3e01a6..02e11e9e9e568fbce9b7e91509caf97151ec6cdc 100644 (file)
@@ -150,7 +150,6 @@ rcpt foo
 #
 # Numerical HELO checks
 #
-msg_verbose 1
 helo_restrictions permit_naked_ip_address,reject_non_fqdn_hostname
 helo [1.2.3.4]
 helo [321.255.255.255]
index febc154f1d6bfe0a344ce3aab9544002d620018b..9c7727171ef5116e465ae0100524d16e4323f523 100644 (file)
@@ -307,93 +307,73 @@ OK
 >>> #
 >>> # Numerical HELO checks
 >>> #
->>> msg_verbose 1
-OK
 >>> helo_restrictions permit_naked_ip_address,reject_non_fqdn_hostname
 OK
 >>> helo [1.2.3.4]
-./smtpd_check: reject_invalid_hostaddr: [1.2.3.4]
 OK
 >>> helo [321.255.255.255]
-./smtpd_check: reject_invalid_hostaddr: [321.255.255.255]
 ./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[321.255.255.255]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[321.255.255.255]>: Helo command rejected: invalid ip address
 >>> helo [0.255.255.255]
-./smtpd_check: reject_invalid_hostaddr: [0.255.255.255]
 ./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[0.255.255.255]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[0.255.255.255]>: Helo command rejected: invalid ip address
 >>> helo [1.2.3.321]
-./smtpd_check: reject_invalid_hostaddr: [1.2.3.321]
 ./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.321]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[1.2.3.321]>: Helo command rejected: invalid ip address
 >>> helo [1.2.3]
-./smtpd_check: reject_invalid_hostaddr: [1.2.3]
 ./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[1.2.3]>: Helo command rejected: invalid ip address
 >>> helo [1.2.3.4.5]
-./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5]
 ./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[1.2.3.4.5]>: Helo command rejected: invalid ip address
 >>> helo [1..2.3.4]
-./smtpd_check: reject_invalid_hostaddr: [1..2.3.4]
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1..2.3.4]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[1..2.3.4]>: Helo command rejected: invalid ip address
 >>> helo [.1.2.3.4]
-./smtpd_check: reject_invalid_hostaddr: [.1.2.3.4]
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[.1.2.3.4]>: Helo command rejected: invalid ip address
 >>> helo [1.2.3.4.5.]
-./smtpd_check: reject_invalid_hostaddr: [1.2.3.4.5.]
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address; from=<foo>
 501 <[1.2.3.4.5.]>: Helo command rejected: invalid ip address
 >>> helo 1.2.3.4
-./smtpd_check: reject_invalid_hostaddr: 1.2.3.4
 OK
 >>> helo 321.255.255.255
-./smtpd_check: reject_invalid_hostaddr: 321.255.255.255
 ./smtpd_check: warning: valid_hostaddr: invalid octet value: 321.255.255.255
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <321.255.255.255>: Helo command rejected: invalid ip address; from=<foo>
 501 <321.255.255.255>: Helo command rejected: invalid ip address
 >>> helo 0.255.255.255
-./smtpd_check: reject_invalid_hostaddr: 0.255.255.255
 ./smtpd_check: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <0.255.255.255>: Helo command rejected: invalid ip address; from=<foo>
 501 <0.255.255.255>: Helo command rejected: invalid ip address
 >>> helo 1.2.3.321
-./smtpd_check: reject_invalid_hostaddr: 1.2.3.321
 ./smtpd_check: warning: valid_hostaddr: invalid octet value: 1.2.3.321
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.321>: Helo command rejected: invalid ip address; from=<foo>
 501 <1.2.3.321>: Helo command rejected: invalid ip address
 >>> helo 1.2.3
-./smtpd_check: reject_invalid_hostaddr: 1.2.3
 ./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3>: Helo command rejected: invalid ip address; from=<foo>
 501 <1.2.3>: Helo command rejected: invalid ip address
 >>> helo 1.2.3.4.5
-./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5
 ./smtpd_check: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5>: Helo command rejected: invalid ip address; from=<foo>
 501 <1.2.3.4.5>: Helo command rejected: invalid ip address
 >>> helo 1..2.3.4
-./smtpd_check: reject_invalid_hostaddr: 1..2.3.4
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: 1..2.3.4
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1..2.3.4>: Helo command rejected: invalid ip address; from=<foo>
 501 <1..2.3.4>: Helo command rejected: invalid ip address
 >>> helo .1.2.3.4
-./smtpd_check: reject_invalid_hostaddr: .1.2.3.4
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: .1.2.3.4
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <.1.2.3.4>: Helo command rejected: invalid ip address; from=<foo>
 501 <.1.2.3.4>: Helo command rejected: invalid ip address
 >>> helo 1.2.3.4.5.
-./smtpd_check: reject_invalid_hostaddr: 1.2.3.4.5.
 ./smtpd_check: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
 ./smtpd_check: reject: HELO from foo[131.155.210.17]: 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address; from=<foo>
 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address
index a60ee4ca2ea29a9b673aac5208b175b3084fc83c..531b4db6acc9449e31e145d50f2a7b4c20780ef6 100644 (file)
@@ -95,6 +95,7 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream,
     state->reason = 0;
     state->sender = 0;
     state->recipient = 0;
+    state->etrn_name = 0;
     state->protocol = "SMTP";
     state->where = SMTPD_AFTER_CONNECT;
 
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR
index 1817f82e0e554f3d090b62ce511111c0c203d343..b65f4ec2434c41cc91fa8bdb535e382d249f7794 100644 (file)
@@ -87,6 +87,7 @@
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
+-TSMTPD_REST_TABLE
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTP_ADDR