From f90b3d19a4fdac529a40937cd3deb65737657cf4 Mon Sep 17 00:00:00 2001 From: Wietse Venema Date: Thu, 9 Sep 1999 00:00:00 -0500 Subject: [PATCH] snapshot-19990909 --- postfix/.indent.pro | 1 + postfix/HISTORY | 37 ++ postfix/INSTALL.sh | 2 +- postfix/RELEASE_NOTES | 50 +- postfix/bounce/.indent.pro | 1 + postfix/cleanup/.indent.pro | 1 + postfix/conf/sample-smtpd.cf | 2 + postfix/dns/.indent.pro | 1 + postfix/error/.indent.pro | 1 + postfix/fsstone/.indent.pro | 1 + postfix/global/.indent.pro | 1 + postfix/global/mail_params.h | 6 + postfix/global/mail_version.h | 2 +- postfix/global/resolve_clnt.c | 33 ++ postfix/global/rewrite_clnt.c | 37 +- postfix/html/smtpd.8.html | 48 +- postfix/html/uce.html | 41 +- postfix/local/.indent.pro | 1 + postfix/man/man8/smtpd.8 | 4 + postfix/master/.indent.pro | 1 + postfix/pickup/.indent.pro | 1 + postfix/pipe/.indent.pro | 1 + postfix/postalias/.indent.pro | 1 + postfix/postcat/.indent.pro | 1 + postfix/postconf/.indent.pro | 1 + postfix/postdrop/.indent.pro | 1 + postfix/postfix/.indent.pro | 1 + postfix/postkick/.indent.pro | 1 + postfix/postlock/.indent.pro | 1 + postfix/postlock/postlock.c | 2 +- postfix/postlog/.indent.pro | 1 + postfix/postmap/.indent.pro | 1 + postfix/postsuper/.indent.pro | 1 + postfix/qmgr/.indent.pro | 1 + postfix/sendmail/.indent.pro | 1 + postfix/showq/.indent.pro | 1 + postfix/smtp/.indent.pro | 1 + postfix/smtpd/.indent.pro | 1 + postfix/smtpd/smtpd.c | 6 + postfix/smtpd/smtpd.h | 1 + postfix/smtpd/smtpd_check.c | 687 +++++++++++++++++----------- postfix/smtpd/smtpd_check.in | 1 - postfix/smtpd/smtpd_check.ref | 20 - postfix/smtpd/smtpd_state.c | 1 + postfix/smtpstone/.indent.pro | 1 + postfix/trivial-rewrite/.indent.pro | 1 + postfix/util/.indent.pro | 1 + 47 files changed, 663 insertions(+), 346 deletions(-) diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/HISTORY b/postfix/HISTORY index 9a0eecf8d..99f4fa1d7 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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 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. diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index 6945c7c56..fb3bd2c62 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -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 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 6b58ef79d..8e45a4401 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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 a name containing "*" because it could be abused. See the LDAP_README file for how to restore previous behavior. diff --git a/postfix/bounce/.indent.pro b/postfix/bounce/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/bounce/.indent.pro +++ b/postfix/bounce/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/cleanup/.indent.pro b/postfix/cleanup/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/cleanup/.indent.pro +++ b/postfix/cleanup/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index f2989510c..7e6224538 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -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. # diff --git a/postfix/dns/.indent.pro b/postfix/dns/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/dns/.indent.pro +++ b/postfix/dns/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/error/.indent.pro b/postfix/error/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/error/.indent.pro +++ b/postfix/error/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/fsstone/.indent.pro b/postfix/fsstone/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/fsstone/.indent.pro +++ b/postfix/fsstone/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/global/.indent.pro b/postfix/global/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/global/.indent.pro +++ b/postfix/global/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index 204fb0140..32a95a91a 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -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. */ diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index aca279b43..f96a226a3 100644 --- a/postfix/global/mail_version.h +++ b/postfix/global/mail_version.h @@ -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 diff --git a/postfix/global/resolve_clnt.c b/postfix/global/resolve_clnt.c index ae47df04b..f8978da7b 100644 --- a/postfix/global/resolve_clnt.c +++ b/postfix/global/resolve_clnt.c @@ -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 */ diff --git a/postfix/global/rewrite_clnt.c b/postfix/global/rewrite_clnt.c index cfbec3c50..f301304e1 100644 --- a/postfix/global/rewrite_clnt.c +++ b/postfix/global/rewrite_clnt.c @@ -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 */ diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 354870d1b..d4dbafc10 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -203,46 +203,52 @@ SMTPD(8) SMTPD(8) SMTPD(8) SMTPD(8) + restriction_classes + 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. + maps_rbl_domains - List of DNS domains that publish the addresses of + List of DNS domains that publish the addresses of blacklisted hosts. relay_domains - Restrict what domains or networks this mail system + Restrict what domains or networks this mail system will relay mail from or to. UCE control responses access_map_reject_code - Server response when a client violates an access + Server response when a client violates an access database restriction. invalid_hostname_reject_code - Server response when a client violates the + Server response when a client violates the reject_invalid_hostname restriction. maps_rbl_reject_code - Server response when a client violates the + Server response when a client violates the maps_rbl_domains restriction. reject_code - Response code when the client matches a reject + Response code when the client matches a reject restriction. relay_domains_reject_code - Server response when a client attempts to violate + Server response when a client attempts to violate the mail relay policy. unknown_address_reject_code - Server response when a client violates the + Server response when a client violates the reject_unknown_address restriction. unknown_client_reject_code - Server response when a client without address to - name mapping violates the reject_unknown_clients + Server response when a client without address to + name mapping violates the reject_unknown_clients restriction. unknown_hostname_reject_code - Server response when a client violates the + Server response when a client violates the reject_unknown_hostname restriction. SEE ALSO @@ -250,13 +256,7 @@ SMTPD(8) SMTPD(8) master(8) process manager syslogd(8) system logging -LICENSE - The Secure Mailer license must be distributed with this - software. -AUTHOR(S) - Wietse Venema - IBM T.J. Watson Research @@ -269,6 +269,13 @@ SMTPD(8) SMTPD(8) SMTPD(8) SMTPD(8) +LICENSE + The Secure Mailer license must be distributed with this + software. + +AUTHOR(S) + Wietse Venema + IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA @@ -311,13 +318,6 @@ SMTPD(8) SMTPD(8) - - - - - - - diff --git a/postfix/html/uce.html b/postfix/html/uce.html index 6e113edfe..1ccc8558c 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -191,9 +191,10 @@ href="access.5.html">access database for the client name, parent domains, client address, or networks obtained by stripping least significant octets. Reject the request if the result is REJECT or "[45]XX text". Permit the request if the result -is anything else. The access_map_reject_code parameter -specifies the response code for REJECT results (default: -554). +is OK or RELAY. Otherwise, treat the result as another +list of UCE restrictions. The access_map_reject_code +parameter specifies the response code for REJECT results +(default: 554).

@@ -338,7 +339,8 @@ response code to rejected requests (default: 504). href="access.5.html">access database for the HELO hostname or parent domains in the specified table. Reject the request if the result is REJECT or "[45]XX text". Permit -the request when the result is anything else. The +the request when the result is OK or RELAY. Otherwise, +treat the result as another list of UCE restrictions. The access_map_reject_code parameter specifies the response code for REJECT results (default: 554). @@ -429,9 +431,10 @@ is always 450 in case of a temporary DNS error. href="access.5.html">access database for the sender mail address, parent domain, or localpart@. Reject the request if the result is REJECT or "[45]XX text". Permit the -request if the result is anything else. The access_map_reject_code - parameter specifies the result code for rejected requests -(default: 554). +request if the result is OK or RELAY. Otherwise, +treat the result as another list of UCE restrictions. The +access_map_reject_code parameter specifies the result code +for rejected requests (default: 554).

@@ -568,9 +571,10 @@ $inet_interfaces. href="access.5.html">access database for the resolved destination address, parent domain, or localpart@. Reject the request if the result is REJECT or "[45]XX text". -Permit the request if the result is anything else. The -access_map_reject_code parameter specifies the result code -for rejected requests (default: 554). +Permit the request if the result is OK or RELAY. +Otherwise, treat the result as another list of UCE restrictions. +The access_map_reject_code parameter specifies the result +code for rejected requests (default: 554).

@@ -593,6 +597,16 @@ response code to rejected requests (default: 504).

+

permit_address_map maptype:mapname
+Permit the request when the recipient address matches the named +table. Table lookup is done as with the virtual and canonical tables. This also produces +useful results with the aliases and +unix:passwd.byname maps. + +

+

reject_unknown_sender_domain
reject_non_fqdn_sender @@ -691,9 +705,10 @@ address. href="access.5.html">access database for the domain specified in the ETRN command, or its parent domains. Reject the request if the result is REJECT or "[45]XX text". Permit -the request if the result is anything else. The access_map_reject_code - parameter specifies the result code for rejected requests -(default: 554). +the request if the result is OK or RELAY. Otherwise, +treat the result as another list of UCE restrictions. The +access_map_reject_code parameter specifies the result code +for rejected requests (default: 554).

diff --git a/postfix/local/.indent.pro b/postfix/local/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/local/.indent.pro +++ b/postfix/local/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 9ff7a6df7..58050d44f 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -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. diff --git a/postfix/master/.indent.pro b/postfix/master/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/master/.indent.pro +++ b/postfix/master/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/pickup/.indent.pro b/postfix/pickup/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/pickup/.indent.pro +++ b/postfix/pickup/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/pipe/.indent.pro b/postfix/pipe/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/pipe/.indent.pro +++ b/postfix/pipe/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postalias/.indent.pro b/postfix/postalias/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postalias/.indent.pro +++ b/postfix/postalias/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postcat/.indent.pro b/postfix/postcat/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postcat/.indent.pro +++ b/postfix/postcat/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postconf/.indent.pro b/postfix/postconf/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postconf/.indent.pro +++ b/postfix/postconf/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postdrop/.indent.pro b/postfix/postdrop/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postdrop/.indent.pro +++ b/postfix/postdrop/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postfix/.indent.pro b/postfix/postfix/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postfix/.indent.pro +++ b/postfix/postfix/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postkick/.indent.pro b/postfix/postkick/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postkick/.indent.pro +++ b/postfix/postkick/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postlock/.indent.pro b/postfix/postlock/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postlock/.indent.pro +++ b/postfix/postlock/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postlock/postlock.c b/postfix/postlock/postlock.c index 0caa2b0cc..ea9ec6aa6 100644 --- a/postfix/postlock/postlock.c +++ b/postfix/postlock/postlock.c @@ -86,7 +86,6 @@ #include #include #include -#include /* Utility library. */ @@ -102,6 +101,7 @@ #include #include #include +#include /* Application-specific. */ diff --git a/postfix/postlog/.indent.pro b/postfix/postlog/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postlog/.indent.pro +++ b/postfix/postlog/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postmap/.indent.pro b/postfix/postmap/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postmap/.indent.pro +++ b/postfix/postmap/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postsuper/.indent.pro b/postfix/postsuper/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/postsuper/.indent.pro +++ b/postfix/postsuper/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/qmgr/.indent.pro b/postfix/qmgr/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/qmgr/.indent.pro +++ b/postfix/qmgr/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/sendmail/.indent.pro b/postfix/sendmail/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/sendmail/.indent.pro +++ b/postfix/sendmail/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/showq/.indent.pro b/postfix/showq/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/showq/.indent.pro +++ b/postfix/showq/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtp/.indent.pro b/postfix/smtp/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/smtp/.indent.pro +++ b/postfix/smtp/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtpd/.indent.pro b/postfix/smtpd/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/smtpd/.indent.pro +++ b/postfix/smtpd/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index 84d740024..5f2f5a0c3 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -131,6 +131,10 @@ /* .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, }; diff --git a/postfix/smtpd/smtpd.h b/postfix/smtpd/smtpd.h index 5d6623fe9..4e72a0880 100644 --- a/postfix/smtpd/smtpd.h +++ b/postfix/smtpd/smtpd.h @@ -47,6 +47,7 @@ typedef struct SMTPD_STATE { char *reason; char *sender; char *recipient; + char *etrn_name; char *protocol; char *where; } SMTPD_STATE; diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 3460f3843..1cdd34ba5 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -135,6 +135,13 @@ /* 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: @@ -246,6 +253,7 @@ #include #include #include +#include /* DNS library. */ @@ -261,6 +269,9 @@ #include #include #include +#include +#include +#include /* 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. */ - return (SMTPD_CHECK_OK); + 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. + */ + 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); - } - - /* - * 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); - } - - /* - * 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, - state->helo_name, SMTPD_NAME_HELO); - else - *status = reject_invalid_hostaddr(state, state->helo_name, - state->helo_name, SMTPD_NAME_HELO); + 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); } - 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, - state->helo_name, SMTPD_NAME_HELO); - else - *status = reject_invalid_hostaddr(state, state->helo_name, - state->helo_name, SMTPD_NAME_HELO); + + /* + * 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); } - 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, + + /* + * 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, + state->helo_name, SMTPD_NAME_HELO); + } + } 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, + state->helo_name, SMTPD_NAME_HELO); + } + } 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; } diff --git a/postfix/smtpd/smtpd_check.in b/postfix/smtpd/smtpd_check.in index a395b94e6..02e11e9e9 100644 --- a/postfix/smtpd/smtpd_check.in +++ b/postfix/smtpd/smtpd_check.in @@ -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] diff --git a/postfix/smtpd/smtpd_check.ref b/postfix/smtpd/smtpd_check.ref index febc154f1..9c7727171 100644 --- a/postfix/smtpd/smtpd_check.ref +++ b/postfix/smtpd/smtpd_check.ref @@ -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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 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= 501 <1.2.3.4.5.>: Helo command rejected: invalid ip address diff --git a/postfix/smtpd/smtpd_state.c b/postfix/smtpd/smtpd_state.c index a60ee4ca2..531b4db6a 100644 --- a/postfix/smtpd/smtpd_state.c +++ b/postfix/smtpd/smtpd_state.c @@ -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; diff --git a/postfix/smtpstone/.indent.pro b/postfix/smtpstone/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/smtpstone/.indent.pro +++ b/postfix/smtpstone/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/trivial-rewrite/.indent.pro b/postfix/trivial-rewrite/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/trivial-rewrite/.indent.pro +++ b/postfix/trivial-rewrite/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/util/.indent.pro b/postfix/util/.indent.pro index 1817f82e0..b65f4ec24 100644 --- a/postfix/util/.indent.pro +++ b/postfix/util/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR