diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/HISTORY b/postfix/HISTORY index 38eadf654..1f20a1617 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -3369,3 +3369,44 @@ Apologies for any names omitted. Bugfix: address rewriting would panic on a lone \ at the end of a line where an address was expected. Jason Hoos @ thwack.net. File: global/rewrite_clnt.c. + +19991215 + + Bugfix: the strict RFC821 envelope address check should + not be applied to VRFY commands. File: smtpd/smtpd.c. + + Cleanup: permit_recipient_maps is gone, because that could + only be used inside UCE restrictions. + +19991216 + + Feature: allow an empty inet_interfaces parameter, just + like an empty mydestination parameter. It's needed for a + true null client that delivers no mail locally at all. + + Feature: "disable_vrfy_command = yes" disables some forms + of address harvesting used by spammers. + + Workaround: added the alias map parameter definition to + the smtpd code. This is a symptom of a general problem + with parameters that have non-empty default values: unless + a program explicitly defines such a parameter, the parameter + defaults to the empty string when used in other parameters. + There's also a problem with evaluation order. + + Feature: the SMTP server rejects mail for unknown users in + virtual domains that are defined by Postfix virtual domain + files. File: smtpd/smtpd_check.c. + + Feature: reject mail for unknown local users at the SMTP + port. The local_recipient_maps configuration parameter + specifies maps with all addresses that are local with + respect to $mydestination or $inet_interfaces. Example: + "local_recipient_maps = $alias_maps unix:passwd.byname". + This feature is disabled by default. You may have to copy + the passwd file into the chroot jail. File: smtpd/smtpd_check.c. + + Feature: the sendmail -f option now understands '' + and even understands address forms with RFC 822-style + comments. + diff --git a/postfix/INSTALL b/postfix/INSTALL index 99f3df5b6..55c951e3b 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -108,7 +108,10 @@ directory of the source tree and type: To build with a non-default compiler, you need to specify the name of the compiler: - % make makefiles CC=/opt/SUNWspro/bin/cc + % make makefiles CC=/opt/SUNWspro/bin/cc (Solaris) + % make + + % make makefiles CC="/opt/ansic/bin/cc -Ae" (HP-UX) % make % make makefiles CC="purify cc" diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index d62a80cd2..afc31fb56 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -199,7 +199,8 @@ test -d $COMMAND_DIRECTORY || mkdir -p $COMMAND_DIRECTORY || exit 1 test -d $QUEUE_DIRECTORY || mkdir -p $QUEUE_DIRECTORY || exit 1 for path in $SENDMAIL_PATH $NEWALIASES_PATH $MAILQ_PATH do - mkdir -p `echo $path|sed 's/[^/]*[/]*$//'` + dir=`echo $path|sed 's/[^/]*[/]*$//'` + test -d $dir || mkdir -p $dir || exit 1 done # Install files. Be careful to not copy over running programs. @@ -285,7 +286,7 @@ no) ;; *) ( cd man || exit 1 for dir in man? - do mkdir -p $MANPAGES/$dir || exit 1 + do test -d $MANPAGES/$dir || mkdir -p $MANPAGES/$dir || exit 1 done for file in man?/* do diff --git a/postfix/Makefile.in b/postfix/Makefile.in index bd00a6d4f..043ee7736 100644 --- a/postfix/Makefile.in +++ b/postfix/Makefile.in @@ -17,7 +17,7 @@ makefiles Makefiles: update printfck: set -e; for i in $(DIRS); do \ - (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@) || exit 1; \ + (set -e; echo "[$$i]"; cd $$i; $(MAKE) $(OPTS) $@ MAKELEVEL=) || exit 1; \ done printfck: update diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 4aad6c272..8efe894a3 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,6 +1,11 @@ -Incompatible changes with snapshot 19991211 +Incompatible changes with snapshot 19991216 =========================================== +- The experimental permit_recipient_map feature is gone. It was +never part of an official release. It is replaced by a +"local_recipient_map" parameter that allows the SMTP server to +reject mail for unknown local users (see below). + - In an SMTPD access map, an all-numeric right-hand side now means OK. This is for better cooperation with out-of-band authentication mechanisms such as POP before SMTP etc. @@ -13,8 +18,8 @@ reinstate the old behavior, specify "allow_min_user = yes" in main.cf. - You can no longer use virtual, canonical or aliases tables as -SMTPD access control tables. Use the permit_recipient_map feature -instead. The loss is compensated for (see below). +SMTPD access control tables. Use the local_recipient_maps feature +instead. - transport_maps entries override mydestination. For every $mydestination domain that matches a transport map entry, or a @@ -22,13 +27,27 @@ parent domain of a transport map entry, you must now add a corresponding "domain.name local:" entry in your transport_maps. See the html/faq.html sections for firewalls and intranets. -Major changes with snapshot 19991211 +Major changes with snapshot 19991216 ==================================== - Updated LDAP client code (John Hensley). - Updated mysql client code (Scott Cotton). +- The SMTP server now rejects mail for unknown users in virtual +domains that are defined by Postfix virtual maps. + +- The SMTP server optionally rejects mail for unknown local users. +Use "local_recipient_maps = $alias_maps, unix:passwd.byname" if +your local mail is delivered by a UNIX-style local delivery agent. +See example in conf/main.cf. + +- Use "disable_vrfy_command = yes" to disable the SMTP VRFY command. +This prevents some forms of address harvesting. + +- The sendmail "-f" option now understands and even understands +forms with RFC 822-style comments. + - New "qmgr_fudge_factor" parameter allows you to balance mailing list performance against response time for one-to-one mail. The fudge factor controls what percentage of delivery resources Postfix @@ -50,26 +69,12 @@ regardless of what main.cf specifies. - The Postfix SMTP server now understands a wider range of illegal address forms in MAIL FROM and RCPT TO commands. In order to disable -those forms, specify "strict_rfc821_envelopes = yes". +illegal forms, specify "strict_rfc821_envelopes = yes". This also +disables support for MAIL FROM and RCPT TO addresses without <>. - Per-client/helo/sender/recipient UCE restrictions (fully-recursive UCE restriction parser). See the RESTRICTION_CLASS file for details. -- Block mail for most non-existent users at the SMTP port. Example: -a non-relaying host could use the following to reject mail for -non-existent local users and for all non-local destinations. - - smtpd_recipient_restrictions = - reject_unknown_sender_domain - permit_recipient_map unix:passwd.byname - permit_recipient_map hash:/etc/postfix/canonical - permit_recipient_map hash:/etc/postfix/virtual - permit_recipient_map hash:/etc/aliases - reject - -I haven't figured out yet how to use this easily on hosts that must -relay mail for other systems. - - Use "postmap -q key" or "postalias -q key" for testing Postfix lookup tables or alias files. diff --git a/postfix/bounce/.indent.pro b/postfix/bounce/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/bounce/.indent.pro +++ b/postfix/bounce/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/cleanup/.indent.pro b/postfix/cleanup/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/cleanup/.indent.pro +++ b/postfix/cleanup/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 6fbc69cb0..a8e2ef965 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -116,6 +116,21 @@ mail_owner = postfix #mydestination = $myhostname, localhost.$mydomain, $mydomain, # mail.$mydomain, www.$mydomain, ftp.$mydomain +# REJECTING UNKNOWN LOCAL USERS +# +# The local_recipient_maps parameter specifies optional lookup tables +# with all users that are local with respect to $mydestination and +# $inet_interfaces. If this parameter is defined, then the SMTP server +# will reject mail for unknown local users. +# +# The local_recipient_maps parameter accepts tables with bare usernames +# such as unix:passwd.byname and alias maps. +# +# Beware: if the Postfix SMTP server runs chrooted, you may have to +# copy the passwd database into the jail. This is system dependent. +# +#local_recipient_maps = $alias_maps unix:passwd.byname + # INTERNET VERSUS INTRANET # # The relayhost parameter specifies the default host to send mail to diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index 9c37a82c3..1f5b13618 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -8,6 +8,12 @@ # MISCELLANEOUS # +# The disable_vrfy_command parameter allows you to disable the SMTP +# VRFY command. This stops some techniques used by spammers to harvest +# email addresses. +# +#disable_vrfy_command = no + # The smtpd_banner parameter specifies the text that follows the 220 # status code in the SMTP greeting banner. Some people like to see # the mail version advertised. By default, Postfix shows no version. @@ -208,9 +214,6 @@ 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_recipient_map maptype:mapname: permit if the recipient matches -# the table. Matching is as with virtual/canonical tables. -# You can also use unix:passwd.byname or alias maps. # 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 6819c7dca..dec6edcbf 100644 --- a/postfix/dns/.indent.pro +++ b/postfix/dns/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/error/.indent.pro b/postfix/error/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/error/.indent.pro +++ b/postfix/error/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/fsstone/.indent.pro b/postfix/fsstone/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/fsstone/.indent.pro +++ b/postfix/fsstone/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/global/.indent.pro b/postfix/global/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/global/.indent.pro +++ b/postfix/global/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/global/mail_params.c b/postfix/global/mail_params.c index 3a3c09779..9cd1100fc 100644 --- a/postfix/global/mail_params.c +++ b/postfix/global/mail_params.c @@ -261,7 +261,7 @@ void mail_params_init() VAR_COMMAND_DIR, DEF_COMMAND_DIR, &var_command_dir, 1, 0, VAR_QUEUE_DIR, DEF_QUEUE_DIR, &var_queue_dir, 1, 0, VAR_PID_DIR, DEF_PID_DIR, &var_pid_dir, 1, 0, - VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 1, 0, + VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces, 0, 0, VAR_DOUBLE_BOUNCE, DEF_DOUBLE_BOUNCE, &var_double_bounce_sender, 1, 0, VAR_DEFAULT_PRIVS, DEF_DEFAULT_PRIVS, &var_default_privs, 1, 0, VAR_ALIAS_DB_MAP, DEF_ALIAS_DB_MAP, &var_alias_db_map, 1, 0, diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index f43ee6051..608843944 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -222,6 +222,13 @@ extern char *var_always_bcc; #define DEF_STRICT_RFC821_ENV 0 extern bool var_strict_rfc821_env; + /* + * Standards violation: disable VRFY. + */ +#define VAR_DISABLE_VRFY_CMD "disable_vrfy_command" +#define DEF_DISABLE_VRFY_CMD 0 +extern bool var_disable_vrfy_cmd; + /* * trivial rewrite/resolve service: mapping tables. */ @@ -819,7 +826,12 @@ extern int var_smtpd_delay_reject; #define REJECT_UNAUTH_PIPE "reject_unauth_pipelining" -#define PERMIT_RCPT_MAP "permit_recipient_map" + /* + * Heuristic to reject most unknown recipients at the SMTP port. + */ +#define VAR_LOCAL_RCPT_MAPS "local_recipient_maps" +#define DEF_LOCAL_RCPT_MAPS "" +extern char *var_local_rcpt_maps; /* * Other. diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 1753babd0..e20640c22 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 "Snapshot-19991211" +#define DEF_MAIL_VERSION "Snapshot-19991216" extern char *var_mail_version; /* LICENSE diff --git a/postfix/local/.indent.pro b/postfix/local/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/local/.indent.pro +++ b/postfix/local/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/master/.indent.pro b/postfix/master/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/master/.indent.pro +++ b/postfix/master/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/pickup/.indent.pro b/postfix/pickup/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/pickup/.indent.pro +++ b/postfix/pickup/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/pipe/.indent.pro b/postfix/pipe/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/pipe/.indent.pro +++ b/postfix/pipe/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postalias/.indent.pro b/postfix/postalias/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postalias/.indent.pro +++ b/postfix/postalias/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postcat/.indent.pro b/postfix/postcat/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postcat/.indent.pro +++ b/postfix/postcat/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postconf/.indent.pro b/postfix/postconf/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postconf/.indent.pro +++ b/postfix/postconf/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postdrop/.indent.pro b/postfix/postdrop/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postdrop/.indent.pro +++ b/postfix/postdrop/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postfix/.indent.pro b/postfix/postfix/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postfix/.indent.pro +++ b/postfix/postfix/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postkick/.indent.pro b/postfix/postkick/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postkick/.indent.pro +++ b/postfix/postkick/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postlock/.indent.pro b/postfix/postlock/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postlock/.indent.pro +++ b/postfix/postlock/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postlog/.indent.pro b/postfix/postlog/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postlog/.indent.pro +++ b/postfix/postlog/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postmap/.indent.pro b/postfix/postmap/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postmap/.indent.pro +++ b/postfix/postmap/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/postsuper/.indent.pro b/postfix/postsuper/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/postsuper/.indent.pro +++ b/postfix/postsuper/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/qmgr/.indent.pro b/postfix/qmgr/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/qmgr/.indent.pro +++ b/postfix/qmgr/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/qmgr/qmgr_message.c b/postfix/qmgr/qmgr_message.c index fec5692a5..e3bb63f28 100644 --- a/postfix/qmgr/qmgr_message.c +++ b/postfix/qmgr/qmgr_message.c @@ -487,9 +487,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) /* * Bounce mail to non-existent users in virtual domains. */ - if (!match_def_local_transport(STR(reply.transport)) - && qmgr_virtual != 0 - && (at = strrchr(recipient->address, '@')) != 0) { + if (qmgr_virtual != 0 + && (at = strrchr(recipient->address, '@')) != 0 + && !resolve_local(at + 1)) { domain = lowercase(mystrdup(at + 1)); junk = maps_find(qmgr_virtual, domain, 0); myfree(domain); diff --git a/postfix/sendmail/.indent.pro b/postfix/sendmail/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/sendmail/.indent.pro +++ b/postfix/sendmail/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/sendmail/sendmail.c b/postfix/sendmail/sendmail.c index 13d13e450..90e27bcf1 100644 --- a/postfix/sendmail/sendmail.c +++ b/postfix/sendmail/sendmail.c @@ -311,6 +311,7 @@ static void enqueue(const char *sender, const char *full_name, char **recipients uid_t uid = getuid(); int status; struct stat st; + int naddr; /* * Initialize. @@ -323,10 +324,20 @@ static void enqueue(const char *sender, const char *full_name, char **recipients * pickup would not be able to run chrooted, and it may not be desirable * to use login names at all. */ - if (sender == 0) + if (sender != 0) { + tree = tok822_parse(sender); + for (naddr = 0, tp = tree; tp != 0; tp = tp->next) + if (tp->type == TOK822_ADDR) + naddr++, tok822_internalize(buf, tp->head, TOK822_STR_DEFL); + tok822_free_tree(tree); + saved_sender = mystrdup(STR(buf)); + if (naddr > 1) + msg_warn("-f option specified malformed sender: %s", sender); + } else { if ((sender = username()) == 0) msg_fatal("unable to find out your login name"); - saved_sender = mystrdup(sender); + saved_sender = mystrdup(sender); + } /* * Open the queue file. Save the queue file name, so the run-time error diff --git a/postfix/showq/.indent.pro b/postfix/showq/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/showq/.indent.pro +++ b/postfix/showq/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtp/.indent.pro b/postfix/smtp/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/smtp/.indent.pro +++ b/postfix/smtp/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtpd/.indent.pro b/postfix/smtpd/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/smtpd/.indent.pro +++ b/postfix/smtpd/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index d3e41b482..55fa74132 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -79,6 +79,10 @@ /* Limit the number of \fBReceived:\fR message headers. /* .IP \fBnotify_classes\fR /* List of error classes. Of special interest are: +/* .IP \fBlocal_recipient_maps\fR +/* List of maps with user names that are local to \fB$myorigin\fR +/* or \fB$inet_interfaces\fR. If this parameter is defined, +/* then the SMTP server rejects mail for unknown local users. /* .RS /* .IP \fBpolicy\fR /* When a client violates any policy, mail a transcript of the @@ -290,6 +294,12 @@ char *var_error_rcpt; int var_smtpd_delay_reject; char *var_rest_classes; int var_strict_rfc821_env; +bool var_disable_vrfy_cmd; +char *var_canonical_maps; +char *var_rcpt_canon_maps; +char *var_virtual_maps; +char *var_alias_maps; +char *var_local_rcpt_maps; /* * Global state, for stand-alone mode queue file cleanup. When this is @@ -442,7 +452,7 @@ static void mail_open_stream(SMTPD_STATE *state) /* extract_addr - extract address from rubble */ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg, - int allow_empty_addr) + int allow_empty_addr, int strict_rfc821) { char *myname = "extract_addr"; TOK822 *tree; @@ -501,7 +511,7 @@ static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg, * Report trouble. Log a warning only if we are going to sleep+reject. */ if (naddr != 1 - || (var_strict_rfc821_env && (non_addr || *STR(arg->vstrval) != '<'))) { + || (strict_rfc821 && (non_addr || *STR(arg->vstrval) != '<'))) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, STR(arg->vstrval)); err = "501 Bad address syntax"; @@ -562,7 +572,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "501 Bad address syntax"); return (-1); } - if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR)) != 0) { + if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "%s", err); return (-1); @@ -669,7 +679,7 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "501 Bad address syntax"); return (-1); } - if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR)) != 0) { + if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR, var_strict_rfc821_env)) != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "%s", err); return (-1); @@ -684,6 +694,10 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "%s", err); return (-1); } + if ((err = smtpd_check_rcptmap(state, argv[2].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } /* * Store the recipient. Remember the first one. @@ -929,6 +943,13 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) * stop doing recipient restriction checks and lose the opportunity to * say "user unknown" at the SMTP port. */ +#define SLOPPY 0 + + if (var_disable_vrfy_cmd) { + state->error_mask |= MAIL_ERROR_POLICY; + smtpd_chat_reply(state, "502 VRFY command is disabled"); + return (-1); + } if (argc < 2) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 Syntax: VRFY address"); @@ -936,22 +957,21 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } if (argc > 2) collapse_args(argc - 1, argv + 1); - if ((err = extract_addr(state, argv + 1, REJECT_EMPTY_ADDR)) != 0) { + if ((err = extract_addr(state, argv + 1, REJECT_EMPTY_ADDR, SLOPPY)) != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "%s", err); return (-1); } - if (SMTPD_STAND_ALONE(state) == 0) - err = smtpd_check_rcpt(state, argv[1].strval); - - /* - * End untokenize. - */ - if (err != 0) { + if (SMTPD_STAND_ALONE(state) == 0 + && (err = smtpd_check_rcpt(state, argv[1].strval)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } - smtpd_chat_reply(state, "252 Send mail to find out"); + if ((err = smtpd_check_rcptmap(state, argv[1].strval)) != 0) { + smtpd_chat_reply(state, "%s", err); + return (-1); + } + smtpd_chat_reply(state, "250 <%s>", argv[1].strval); return (0); } @@ -1027,7 +1047,7 @@ static int quit_cmd(SMTPD_STATE *state, int unused_argc, SMTPD_TOKEN *unused_arg typedef struct SMTPD_CMD { char *name; int (*action) (SMTPD_STATE *, int, SMTPD_TOKEN *); -} SMTPD_CMD; +} SMTPD_CMD; static SMTPD_CMD smtpd_cmd_table[] = { "HELO", helo_cmd, @@ -1304,6 +1324,7 @@ int main(int argc, char **argv) VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required, VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject, VAR_STRICT_RFC821_ENV, DEF_STRICT_RFC821_ENV, &var_strict_rfc821_env, + VAR_DISABLE_VRFY_CMD, DEF_DISABLE_VRFY_CMD, &var_disable_vrfy_cmd, 0, }; static CONFIG_STR_TABLE str_table[] = { @@ -1320,6 +1341,11 @@ int main(int argc, char **argv) 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, + VAR_LOCAL_RCPT_MAPS, DEF_LOCAL_RCPT_MAPS, &var_local_rcpt_maps, 0, 0, + VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0, + VAR_RCPT_CANON_MAPS, DEF_RCPT_CANON_MAPS, &var_rcpt_canon_maps, 0, 0, + VAR_VIRTUAL_MAPS, DEF_VIRTUAL_MAPS, &var_virtual_maps, 0, 0, + VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps, 0, 0, 0, }; diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 03a8a92f4..e1c275ba0 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -138,10 +138,6 @@ /* 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_recipient_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. @@ -302,24 +298,30 @@ static RESOLVE_REPLY reply; static VSTRING *query; static VSTRING *error_text; + /* + * Pre-opened SMTP recipient maps. + */ +static MAPS *local_rcpt_maps; +static MAPS *rcpt_canon_maps; +static MAPS *canonical_maps; +static MAPS *virtual_maps; + /* * Pre-opened access control lists. */ -static DOMAIN_LIST *relay_domains; -static NAMADR_LIST *mynetworks; +static DOMAIN_LIST *relay_domains; +static NAMADR_LIST *mynetworks; /* * Pre-parsed restriction lists. */ -static ARGV *client_restrctions; +static ARGV *client_restrctions; static ARGV *helo_restrctions; static ARGV *mail_restrctions; static ARGV *rcpt_restrctions; static ARGV *etrn_restrctions; -static HTABLE *smtpd_rest_classes; - -static HTABLE *smtpd_rcpt_maps; +static HTABLE *smtpd_rest_classes; /* * The routine that recursively applies restrictions. @@ -383,6 +385,18 @@ void smtpd_check_init(void) mynetworks = namadr_list_init(var_mynetworks); relay_domains = domain_list_init(var_relay_domains); + /* + * Pre-parse and pre-open the recipient maps. + */ + local_rcpt_maps = maps_create(VAR_LOCAL_RCPT_MAPS, var_local_rcpt_maps, + DICT_FLAG_LOCK); + rcpt_canon_maps = maps_create(VAR_RCPT_CANON_MAPS, var_rcpt_canon_maps, + DICT_FLAG_LOCK); + canonical_maps = maps_create(VAR_CANONICAL_MAPS, var_canonical_maps, + DICT_FLAG_LOCK); + virtual_maps = maps_create(VAR_VIRTUAL_MAPS, var_virtual_maps, + DICT_FLAG_LOCK); + /* * Reply is used as a cache for resolved addresses, and error_text is * used for returning error responses. @@ -424,16 +438,11 @@ void smtpd_check_init(void) htable_enter("check_relay_domains", smtpd_check_parse("permit_mydomain reject_unauth_destination")); #endif - - /* - * Other one-off initializations. - */ - smtpd_rcpt_maps = htable_create(1); } /* smtpd_check_reject - do the boring things that must be done */ -static int smtpd_check_reject(SMTPD_STATE * state, int error_class, +static int smtpd_check_reject(SMTPD_STATE *state, int error_class, char *format,...) { va_list ap; @@ -486,7 +495,7 @@ static int smtpd_check_reject(SMTPD_STATE * state, int error_class, /* reject_unknown_client - fail if client hostname is unknown */ -static int reject_unknown_client(SMTPD_STATE * state) +static int reject_unknown_client(SMTPD_STATE *state) { char *myname = "reject_unknown_client"; @@ -504,7 +513,7 @@ static int reject_unknown_client(SMTPD_STATE * state) /* permit_mynetworks - succeed if client is in a trusted network */ -static int permit_mynetworks(SMTPD_STATE * state) +static int permit_mynetworks(SMTPD_STATE *state) { char *myname = "permit_mynetworks"; @@ -537,7 +546,7 @@ static char *dup_if_truncate(char *name) /* reject_invalid_hostaddr - fail if host address is incorrect */ -static int reject_invalid_hostaddr(SMTPD_STATE * state, char *addr, +static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr, char *reply_name, char *reply_class) { char *myname = "reject_invalid_hostaddr"; @@ -574,7 +583,7 @@ static int reject_invalid_hostaddr(SMTPD_STATE * state, char *addr, /* reject_invalid_hostname - fail if host/domain syntax is incorrect */ -static int reject_invalid_hostname(SMTPD_STATE * state, char *name, +static int reject_invalid_hostname(SMTPD_STATE *state, char *name, char *reply_name, char *reply_class) { char *myname = "reject_invalid_hostname"; @@ -610,7 +619,7 @@ static int reject_invalid_hostname(SMTPD_STATE * state, char *name, /* reject_non_fqdn_hostname - fail if host name is not in fqdn form */ -static int reject_non_fqdn_hostname(SMTPD_STATE * state, char *name, +static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name, char *reply_name, char *reply_class) { char *myname = "reject_non_fqdn_hostname"; @@ -646,7 +655,7 @@ static int reject_non_fqdn_hostname(SMTPD_STATE * state, char *name, /* reject_unknown_hostname - fail if name has no A or MX record */ -static int reject_unknown_hostname(SMTPD_STATE * state, char *name, +static int reject_unknown_hostname(SMTPD_STATE *state, char *name, char *reply_name, char *reply_class) { char *myname = "reject_unknown_hostname"; @@ -668,7 +677,7 @@ static int reject_unknown_hostname(SMTPD_STATE * state, char *name, /* reject_unknown_mailhost - fail if name has no A or MX record */ -static int reject_unknown_mailhost(SMTPD_STATE * state, char *name, +static int reject_unknown_mailhost(SMTPD_STATE *state, char *name, char *reply_name, char *reply_class) { char *myname = "reject_unknown_mailhost"; @@ -690,7 +699,7 @@ static int reject_unknown_mailhost(SMTPD_STATE * state, char *name, /* check_relay_domains - OK/FAIL for message relaying */ -static int check_relay_domains(SMTPD_STATE * state, char *recipient, +static int check_relay_domains(SMTPD_STATE *state, char *recipient, char *reply_name, char *reply_class) { char *myname = "check_relay_domains"; @@ -773,7 +782,7 @@ static int permit_auth_destination(char *recipient) /* reject_unauth_destination - FAIL for message relaying */ -static int reject_unauth_destination(SMTPD_STATE * state, char *recipient) +static int reject_unauth_destination(SMTPD_STATE *state, char *recipient) { char *myname = "reject_unauth_destination"; char *domain; @@ -812,7 +821,7 @@ static int reject_unauth_destination(SMTPD_STATE * state, char *recipient) /* reject_unauth_pipelining - reject improper use of SMTP command pipelining */ -static int reject_unauth_pipelining(SMTPD_STATE * state) +static int reject_unauth_pipelining(SMTPD_STATE *state) { char *myname = "reject_unauth_pipelining"; @@ -872,7 +881,7 @@ static int has_my_addr(char *host) /* permit_mx_backup - permit use of me as MX backup for recipient domain */ -static int permit_mx_backup(SMTPD_STATE * unused_state, const char *recipient) +static int permit_mx_backup(SMTPD_STATE *unused_state, const char *recipient) { char *myname = "permit_mx_backup"; char *domain; @@ -957,7 +966,7 @@ static int permit_mx_backup(SMTPD_STATE * unused_state, const char *recipient) /* reject_non_fqdn_address - fail if address is not in fqdn form */ -static int reject_non_fqdn_address(SMTPD_STATE * state, char *addr, +static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr, char *reply_name, char *reply_class) { char *myname = "reject_non_fqdn_address"; @@ -1010,7 +1019,7 @@ static int reject_non_fqdn_address(SMTPD_STATE * state, char *addr, /* reject_unknown_address - fail if address does not resolve */ -static int reject_unknown_address(SMTPD_STATE * state, char *addr, +static int reject_unknown_address(SMTPD_STATE *state, char *addr, char *reply_name, char *reply_class) { char *myname = "reject_unknown_address"; @@ -1043,70 +1052,16 @@ static int reject_unknown_address(SMTPD_STATE * state, char *addr, return (reject_unknown_mailhost(state, domain, reply_name, reply_class)); } -/* permit_rcpt_map - permit if recipient address matches rewriting table */ - -static int permit_rcpt_map(char *table, char *reply_name) -{ - char *myname = "permit_rcpt_map"; - char *domain; - - MAPS *map; - DICT *dict; - - 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 (!match_any_local_transport(STR(reply.transport))) - return (SMTPD_CHECK_DUNNO); - - /* - * Look up the name in the specified table, using the usual magic of - * canonical and virtual maps. Be sure this map was declared in a main.cf - * restriction or restriction class. The maps must be opened before the - * process enters a chroot jail. - * - * XXX What follows is a kludge to wrap up the recipient map in a form - * usable by mail_addr_find(). Perhaps we should have a mail_addr_find() - * interface that will search just one map instead of a list of maps. - */ - if ((map = (MAPS *) htable_find(smtpd_rcpt_maps, table)) == 0) { - if ((dict = dict_handle(table)) == 0) - msg_panic("%s: dictionary not found: %s", myname, table); - map = maps_create("rcpt_map", "", DICT_FLAG_LOCK); - maps_append(map, table, dict); - htable_enter(smtpd_rcpt_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, +static int check_table_result(SMTPD_STATE *state, char *table, const char *value, const char *datum, char *reply_name, char *reply_class, char *def_acl) { char *myname = "check_table_result"; int code; - ARGV *restrictions; + ARGV *restrictions; int status; if (msg_verbose) @@ -1189,7 +1144,7 @@ static int check_table_result(SMTPD_STATE * state, char *table, /* check_access - table lookup without substring magic */ -static int check_access(SMTPD_STATE * state, char *table, char *name, int flags, +static int check_access(SMTPD_STATE *state, char *table, char *name, int flags, char *reply_name, char *reply_class, char *def_acl) { char *myname = "check_access"; @@ -1219,7 +1174,7 @@ static int check_access(SMTPD_STATE * state, char *table, char *name, int flags, /* check_domain_access - domainname-based table lookup */ -static int check_domain_access(SMTPD_STATE * state, char *table, +static int check_domain_access(SMTPD_STATE *state, char *table, char *domain, int flags, char *reply_name, char *reply_class, char *def_acl) @@ -1259,7 +1214,7 @@ static int check_domain_access(SMTPD_STATE * state, char *table, /* check_addr_access - address-based table lookup */ -static int check_addr_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 *def_acl) @@ -1296,7 +1251,7 @@ static int check_addr_access(SMTPD_STATE * state, char *table, /* check_namadr_access - OK/FAIL based on host name/address lookup */ -static int check_namadr_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 *def_acl) @@ -1332,7 +1287,7 @@ 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, +static int check_mail_access(SMTPD_STATE *state, char *table, char *addr, char *reply_name, char *reply_class, char *def_acl) { @@ -1392,7 +1347,7 @@ static int check_mail_access(SMTPD_STATE * state, char *table, char *addr, /* reject_maps_rbl - reject if client address in real-time blackhole list */ -static int reject_maps_rbl(SMTPD_STATE * state) +static int reject_maps_rbl(SMTPD_STATE *state) { char *myname = "reject_maps_rbl"; ARGV *octets = argv_split(state->addr, "."); @@ -1488,7 +1443,7 @@ static int is_map_command(char *name, char *command, char ***argp) /* generic_checks - generic restrictions */ -static int generic_checks(SMTPD_STATE * state, ARGV *restrictions, +static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, char *reply_name, char *reply_class, char *def_acl) { char *myname = "generic_checks"; @@ -1646,9 +1601,6 @@ static int generic_checks(SMTPD_STATE * state, ARGV *restrictions, if (state->recipient) status = reject_non_fqdn_address(state, state->recipient, state->recipient, SMTPD_NAME_RECIPIENT); - } else if (is_map_command(name, PERMIT_RCPT_MAP, &cpp)) { - if (state->recipient) - status = permit_rcpt_map(*cpp, state->recipient); } /* @@ -1690,7 +1642,7 @@ static int generic_checks(SMTPD_STATE * state, ARGV *restrictions, /* smtpd_check_client - validate client name or address */ -char *smtpd_check_client(SMTPD_STATE * state) +char *smtpd_check_client(SMTPD_STATE *state) { int status; @@ -1714,7 +1666,7 @@ char *smtpd_check_client(SMTPD_STATE * state) /* smtpd_check_helo - validate HELO hostname */ -char *smtpd_check_helo(SMTPD_STATE * state, char *helohost) +char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) { int status; char *saved_helo; @@ -1760,7 +1712,7 @@ char *smtpd_check_helo(SMTPD_STATE * state, char *helohost) /* smtpd_check_mail - validate sender address, driver */ -char *smtpd_check_mail(SMTPD_STATE * state, char *sender) +char *smtpd_check_mail(SMTPD_STATE *state, char *sender) { int status; char *saved_sender; @@ -1796,7 +1748,7 @@ char *smtpd_check_mail(SMTPD_STATE * state, char *sender) /* smtpd_check_rcpt - validate recipient address, driver */ -char *smtpd_check_rcpt(SMTPD_STATE * state, char *recipient) +char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) { int status; char *saved_recipient; @@ -1842,7 +1794,7 @@ char *smtpd_check_rcpt(SMTPD_STATE * state, char *recipient) /* smtpd_check_etrn - validate ETRN request */ -char *smtpd_check_etrn(SMTPD_STATE * state, char *domain) +char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) { int status; char *saved_etrn_name; @@ -1885,9 +1837,78 @@ char *smtpd_check_etrn(SMTPD_STATE * state, char *domain) SMTPD_CHECK_ETRN_RETURN(status == SMTPD_CHECK_REJECT ? STR(error_text) : 0); } +/* smtpd_check_rcptmap - permit if recipient address matches lookup table */ + +char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient) +{ + char *myname = "smtpd_check_rcptmap"; + char *saved_recipient; + char *domain; + + /* + * XXX This module does a lot of unnecessary guessing. The SMTP server + * (and presumably, pickup daemon) should run the envelopes through a + * rewriting service that does all the canonical and virtual mapping. + */ + if (msg_verbose) + msg_info("%s: %s", myname, 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. + */ + SMTPD_CHECK_PUSH(saved_recipient, state->recipient, recipient); + + /* + * Resolve the address. + */ + canon_addr_internal(query, recipient); + resolve_clnt_query(STR(query), &reply); + + /* + * Skip non-DNS forms. Skip non-local numerical forms. + */ + if ((domain = strrchr(STR(reply.recipient), '@')) == 0) + SMTPD_CHECK_RCPT_RETURN(0); + domain += 1; + if (domain[0] == '#' || domain[0] == '[') + if (!resolve_local(domain)) + SMTPD_CHECK_RCPT_RETURN(0); + + /* + * Reject mail to unknown addresses in domains that match $mydestination + * or $inet_interfaces (Postfix local). Reject mail to unknown addresses + * in Postfix virtual domains (Postfix virtual). Accept mail to other + * domains. Toss any extension information found by the lookup routines. + */ +#define NOP ((char **) 0) + + if (resolve_local(domain)) { + if (*var_local_rcpt_maps + && !mail_addr_find(rcpt_canon_maps, STR(reply.recipient), NOP) + && !mail_addr_find(canonical_maps, STR(reply.recipient), NOP) + && !mail_addr_find(local_rcpt_maps, STR(reply.recipient), NOP)) { + (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, + "550 <%s>: User unknown", recipient); + SMTPD_CHECK_RCPT_RETURN(STR(error_text)); + } + } else { + if (*var_virtual_maps + && !mail_addr_find(rcpt_canon_maps, STR(reply.recipient), NOP) + && !mail_addr_find(canonical_maps, STR(reply.recipient), NOP) + && !mail_addr_find(virtual_maps, STR(reply.recipient), NOP) + && maps_find(virtual_maps, domain, 0)) { + (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, + "550 <%s>: User unknown", recipient); + SMTPD_CHECK_RCPT_RETURN(STR(error_text)); + } + } + SMTPD_CHECK_RCPT_RETURN(0); +} + /* smtpd_check_size - check optional SIZE parameter value */ -char *smtpd_check_size(SMTPD_STATE * state, off_t size) +char *smtpd_check_size(SMTPD_STATE *state, off_t size) { char *myname = "smtpd_check_size"; struct fsspace fsbuf; @@ -1963,7 +1984,7 @@ typedef struct { char *name; char *defval; char **target; -} STRING_TABLE; +} STRING_TABLE; static STRING_TABLE string_table[] = { VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, @@ -2008,7 +2029,7 @@ typedef struct { char *name; int defval; int *target; -} INT_TABLE; +} INT_TABLE; int var_unk_client_code; int var_bad_name_code; @@ -2118,7 +2139,7 @@ static void rest_class(char *class) /* resolve_clnt_init - initialize reply */ -void resolve_clnt_init(RESOLVE_REPLY * reply) +void resolve_clnt_init(RESOLVE_REPLY *reply) { reply->transport = vstring_alloc(100); reply->nexthop = vstring_alloc(100); @@ -2127,7 +2148,7 @@ void resolve_clnt_init(RESOLVE_REPLY * reply) /* canon_addr_internal - stub */ -VSTRING *canon_addr_internal(VSTRING * result, const char *addr) +VSTRING *canon_addr_internal(VSTRING *result, const char *addr) { if (addr == STR(result)) msg_panic("canon_addr_internal: result clobbers input"); @@ -2138,7 +2159,7 @@ VSTRING *canon_addr_internal(VSTRING * result, const char *addr) /* resolve_clnt_query - stub */ -void resolve_clnt_query(const char *addr, RESOLVE_REPLY * reply) +void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply) { if (addr == STR(reply->recipient)) msg_panic("resolve_clnt_query: result clobbers input"); @@ -2151,7 +2172,7 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY * reply) /* smtpd_chat_reset - stub */ -void smtpd_chat_reset(SMTPD_STATE * unused_state) +void smtpd_chat_reset(SMTPD_STATE *unused_state) { } diff --git a/postfix/smtpd/smtpd_check.h b/postfix/smtpd/smtpd_check.h index 74f013b09..00f923a8f 100644 --- a/postfix/smtpd/smtpd_check.h +++ b/postfix/smtpd/smtpd_check.h @@ -16,6 +16,7 @@ extern void smtpd_check_init(void); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); extern char *smtpd_check_mail(SMTPD_STATE *, char *); +extern char *smtpd_check_rcptmap(SMTPD_STATE *, char *); extern char *smtpd_check_size(SMTPD_STATE *, off_t); extern char *smtpd_check_rcpt(SMTPD_STATE *, char *); extern char *smtpd_check_etrn(SMTPD_STATE *, char *); diff --git a/postfix/smtpstone/.indent.pro b/postfix/smtpstone/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/smtpstone/.indent.pro +++ b/postfix/smtpstone/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/trivial-rewrite/.indent.pro b/postfix/trivial-rewrite/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/trivial-rewrite/.indent.pro +++ b/postfix/trivial-rewrite/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR diff --git a/postfix/util/.indent.pro b/postfix/util/.indent.pro index 6819c7dca..dec6edcbf 100644 --- a/postfix/util/.indent.pro +++ b/postfix/util/.indent.pro @@ -87,6 +87,7 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE +-TSMTPD_CMD -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR