From: Wietse Venema Date: Sat, 20 Nov 1999 05:00:00 +0000 (-0500) Subject: snapshot-19991120 X-Git-Tag: v20010228~88 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=37aa8480727bb5309b8094566faf1741f5c8fd84;p=thirdparty%2Fpostfix.git snapshot-19991120 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 9acf0f127..1c0e4895b 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -3226,11 +3226,11 @@ Apologies for any names omitted. 19991116 Code cleanup: a new "local_transports" configuration - parameter explicitly lists all transports that deliver - mail locally. The first name listed there is the default - local transport. This is the end of the "empty next-hop - hostname" hack to indicate that a destination is local. - Files: trivial-rewrite/resolve.c, global/local_transport.[hc] + parameter explicitly lists all transports that deliver mail + locally. The first name listed there is the default local + transport. This is the end of the "empty next-hop hostname" + hack to indicate that a destination is local. Files: + trivial-rewrite/resolve.c, global/local_transport.[hc] Feature: "postconf -m" shows what lookup table types are available. Code by Scott Cotton, Internet Consultants @@ -3243,6 +3243,8 @@ Apologies for any names omitted. 19991117 + Portability: SunOS 4 has no SA_RESTART. File: util/watchdog.c. + Feature: on systems with h_errno, the "reject_unknown_client" restriction now distinguishes between soft errors (always reply with 450) and hard errors (use the user-specified @@ -3256,3 +3258,25 @@ Apologies for any names omitted. Robustness: postconf no longer aborts when it can't figure out the local domain name; it prints a warning instead. This allows you to use "postconf -e" to fix the problem. + +19991118 + + Bugfix: the RFC822 address parser would misparse a leading + \ as an atom all by itself. Problem reported by Keith + Stevenson @ louisville.edu. File: global/tok822_parse.c. + +19991119 + + Bugfix: tiny memory leak in pipe_command() when fork() + fails. File: global/pipe_command.c. + +19991120 + + Bugfix: reversed test for all-numerical results in SMTPD + access maps. File: smtpd/smtpd_check.c. + +19991121 + + Robustness: INSTALL.sh no longer uses postmap for sanity checks. + + Feature: INSTALL.sh now has an install_root option. diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index 9cebaaec8..50f4b83a0 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -6,31 +6,6 @@ PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc umask 022 -# Default settings, edit to taste or change interactively. Once this -# script has run it saves settings to $config_directory/install.cf. - -config_directory=/etc/postfix -daemon_directory=/usr/libexec/postfix -command_directory=/usr/sbin -queue_directory=/var/spool/postfix -sendmail_path=/usr/sbin/sendmail -newaliases_path=/usr/bin/newaliases -mailq_path=/usr/bin/mailq -mail_owner=postfix -setgid=no -manpages=no - -# Load defaults from existing installation. - -test -f $config_directory/main.cf && { - for name in daemon_directory command_directory queue_directory mail_owner - do - eval "$name=\"\`bin/postconf -h $name || kill \$\$\`\"" - done -} - -test -f $config_directory/install.cf && . $config_directory/install.cf - cat </dev/null 2>&1 || { + rm -f junk || exit 1 cp $2 junk || exit 1 mv -f junk $3 || exit 1 chmod $1 $3 || exit 1 @@ -73,6 +51,7 @@ compare_or_replace() { compare_or_symlink() { cmp $1 $2 >/dev/null 2>&1 || { + rm -f junk || exit 1 ln -s $1 junk || exit 1 mv -f junk $2 || exit 1 } @@ -92,6 +71,44 @@ case `echo -n` in *) n=; c='\c';; esac +# Default settings, edit to taste or change interactively. Once this +# script has run it saves settings to $config_directory/install.cf. + +config_directory=/etc/postfix +daemon_directory=/usr/libexec/postfix +command_directory=/usr/sbin +queue_directory=/var/spool/postfix +sendmail_path=/usr/sbin/sendmail +newaliases_path=/usr/bin/newaliases +mailq_path=/usr/bin/mailq +mail_owner=postfix +setgid=no +manpages=no + +while : +do + echo $n "install_root: [/] $c" + read ans + case $ans in +""|/|no) install_root=; break;; + /*) install_root=$ans; break;; + *) echo "install_root should be an absolute path name" 1>&2; exit 1;; + esac +done + +# Load defaults from existing installation. + +CONFIG_DIRECTORY=$install_root$config_directory + +test -f $CONFIG_DIRECTORY/main.cf && { + for name in daemon_directory command_directory queue_directory mail_owner + do + eval "$name=\"\`bin/postconf -c $CONFIG_DIRECTORY -h $name || kill \$\$\`\"" + done +} + +test -f $CONFIG_DIRECTORY/install.cf && . $CONFIG_DIRECTORY/install.cf + for name in config_directory daemon_directory command_directory \ queue_directory sendmail_path newaliases_path mailq_path mail_owner \ setgid manpages @@ -109,6 +126,26 @@ done # Sanity checks +rm -f foobar- +touch foobar- + +chown $mail_owner foobar- >/dev/null 2>&1 || { + echo "Error: $mail_owner needs an entry in the passwd file" 1>&2 + echo "Remember, $mail_owner must have a dedicated user id and group id." 1>&2 + exit 1 +} + +case $setgid in +no) ;; + *) chgrp "$setgid" foobar- >/dev/null 2>&1 || { + echo "Error: $setgid needs an entry in the group file" 1>&2 + echo "Remember, $setgid must have a dedicated group id." 1>&2 + exit 1 + } +esac + +rm -f foobar- + for path in $config_directory $daemon_directory $command_directory \ $queue_directory $sendmail_path $newaliases_path $mailq_path $manpages do @@ -121,37 +158,54 @@ done # Create any missing directories. -test -d $config_directory || mkdir -p $config_directory || exit 1 -test -d $daemon_directory || mkdir -p $daemon_directory || exit 1 -test -d $command_directory || mkdir -p $command_directory || exit 1 -test -d $queue_directory || mkdir -p $queue_directory || exit 1 +CONFIG_DIRECTORY=$install_root$config_directory +DAEMON_DIRECTORY=$install_root$daemon_directory +COMMAND_DIRECTORY=$install_root$command_directory +QUEUE_DIRECTORY=$install_root$queue_directory +SENDMAIL_PATH=$install_root$sendmail_path +NEWALIASES_PATH=$install_root$newaliases_path +MAILQ_PATH=$install_root$mailq_path +MANPAGES=$install_root$manpages + +case $install_root in + /?*) test -d $install_root || mkdir -p $install_root || exit 1 +esac + +test -d $CONFIG_DIRECTORY || mkdir -p $CONFIG_DIRECTORY || exit 1 +test -d $DAEMON_DIRECTORY || mkdir -p $DAEMON_DIRECTORY || exit 1 +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/[^/]*[/]*$//'` +done # Install files. Be careful to not copy over running programs. for file in `ls libexec` do - compare_or_replace a+x,go-w libexec/$file $daemon_directory/$file || exit 1 + compare_or_replace a+x,go-w libexec/$file $DAEMON_DIRECTORY/$file || exit 1 done for file in `ls bin | grep '^post'` do - compare_or_replace a+x,go-w bin/$file $command_directory/$file || exit 1 + compare_or_replace a+x,go-w bin/$file $COMMAND_DIRECTORY/$file || exit 1 done test -f bin/sendmail && { - compare_or_replace a+x,go-w bin/sendmail $sendmail_path || exit 1 - compare_or_symlink $sendmail_path $newaliases_path - compare_or_symlink $sendmail_path $mailq_path + compare_or_replace a+x,go-w bin/sendmail $SENDMAIL_PATH || exit 1 + compare_or_symlink $sendmail_path $NEWALIASES_PATH + compare_or_symlink $sendmail_path $MAILQ_PATH } -compare_or_replace a+r,go-w conf/LICENSE $config_directory/LICENSE || exit 1 +compare_or_replace a+r,go-w conf/LICENSE $CONFIG_DIRECTORY/LICENSE || exit 1 -test -f $config_directory/main.cf || { - cp conf/* $config_directory || exit 1 - chmod a+r,go-w $config_directory/* || exit 1 +test -f $CONFIG_DIRECTORY/main.cf || { + cp conf/* $CONFIG_DIRECTORY || exit 1 + chmod a+r,go-w $CONFIG_DIRECTORY/* || exit 1 echo "Warning: you still need to edit myorigin/mydestination in" 1>&2 - echo "$config_directory/main.cf. See also html/faq.html for dialup" 1>&2 + echo "$CONFIG_DIRECTORY/main.cf. See also html/faq.html for dialup" 1>&2 echo "sites or for sites inside a firewalled network." 1>&2 echo "" 1>&2 echo "BTW, Edit your alias database and be sure to set up aliases" 1>&2 @@ -173,32 +227,32 @@ for name in config_directory sendmail_path newaliases_path mailq_path \ do eval echo $name=\$$name done) >junk || exit 1 -compare_or_move a+x,go-w junk $config_directory/install.cf || exit 1 +compare_or_move a+x,go-w junk $CONFIG_DIRECTORY/install.cf || exit 1 rm -f junk # Use set-gid privileges instead of writable maildrop (optional). -test -d $queue_directory/maildrop || { - mkdir -p $queue_directory/maildrop || exit 1 - chown $owner $queue_directory/maildrop || exit 1 +test -d $QUEUE_DIRECTORY/maildrop || { + mkdir -p $QUEUE_DIRECTORY/maildrop || exit 1 + chown $mail_owner $QUEUE_DIRECTORY/maildrop || exit 1 } case $setgid in no) - chmod 1733 $queue_directory/maildrop || exit 1 - chmod g-s $command_directory/postdrop || exit 1 + chmod 1733 $QUEUE_DIRECTORY/maildrop || exit 1 + chmod g-s $COMMAND_DIRECTORY/postdrop || exit 1 postfix_script=conf/postfix-script-nosgid ;; *) - chgrp $setgid $command_directory/postdrop || exit 1 - chmod g+s $command_directory/postdrop || exit 1 - chgrp $setgid $queue_directory/maildrop || exit 1 - chmod 1730 $queue_directory/maildrop || exit 1 + chgrp $setgid $COMMAND_DIRECTORY/postdrop || exit 1 + chmod g+s $COMMAND_DIRECTORY/postdrop || exit 1 + chgrp $setgid $QUEUE_DIRECTORY/maildrop || exit 1 + chmod 1730 $QUEUE_DIRECTORY/maildrop || exit 1 postfix_script=conf/postfix-script-sgid ;; esac -compare_or_replace a+x,go-w $postfix_script $config_directory/postfix-script || +compare_or_replace a+x,go-w $postfix_script $CONFIG_DIRECTORY/postfix-script || exit 1 # Install manual pages (optional). We just clobber whatever is there. @@ -208,13 +262,13 @@ no) ;; *) ( cd man || exit 1 for dir in man? - do mkdir -p $manpages/$dir || exit 1 + do mkdir -p $MANPAGES/$dir || exit 1 done for file in man?/* do - rm -f $manpages/$file - cp $file $manpages/$file || exit 1 - chmod 644 $manpages/$file || exit 1 + rm -f $MANPAGES/$file + cp $file $MANPAGES/$file || exit 1 + chmod 644 $MANPAGES/$file || exit 1 done ) esac diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index dee14e3e5..533cb6197 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,62 +1,55 @@ -Incompatible changes with snapshot XXXXXXXX +Incompatible changes with snapshot 19991120 =========================================== +- 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. + - Recipient addresses may no longer begin with `-'. In order to reinstate the old behavior, specify "allow_min_user = yes" in main.cf. -- You can not longer use virtual, canonical or aliases tables as +- 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. +instead. The loss is compensated for (see below). -Major changes with snapshot XXXXXXXX +Major changes with snapshot 19991120 ==================================== -- Per-client/helo/sender/recipient UCE restrictions: you can now -specify arbitrary restrictions on the right-hand side of SMTPD -access tables. The only anomalies in this scheme are (1) header -checks are the same for every message, and (2) you must use a -restriction class (see below) in order to specify a lookup table -on the right-hand side of an access table. - -- 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 +- The Postfix SMTP server now understands a wider range of illegal +address formats in MAIL FROM and RCPT TO commands. In order to +disable those forms, specify "strict_rfc821_envelopes = yes". -Then use "restrictive" or "permissive" on the right-hand side of -your per-client/helo/sender/recipient SMTPD access tables. +- Per-client/helo/sender/recipient UCE restrictions (fully-recursive +UCE restriction parser). See the RESTRICTION_CLASS file for details. -- Reject mail for non-existent local accounts. You can now use -passwd/canonical/virtual/aliases tables for SMTPD access control. - -For example, a non-relaying site would specify in main.cf: +- Block mail for non-existent users at the SMTP port. On a non-relay +host, use the following to reject mail for non-existent users and +for non-local destinations. smtpd_recipient_restrictions = - permit_recipient_map unix:passwd.byname - permit_recipient_map hash:/etc/canonical + 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 -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. +- "postconf -e name=value..." edits the main.cf file. This is +easier and safer than editing the main.cf file by hand. The edits +are done on a temporary copy that is renamed into place. + +- "postconf -m" displays all supported lookup table types (Scott +Cotton). -For a relaying site, a good configuration with permit_recipient_map -still needs to be found. Something that permits relaying to all -sites except $mydestination. +- It is now relatively safe to configure 550 status codes for the +main.cf unknown_address_reject_code or unknown_client_reject_code +parameters. The SMTP server now always sends a 450 (try again) +reply code when an UCE restriction fails due to a soft DNS error. -Unfortunately, permit_recipient_map does not combine well with -permit_mynetworks, because permit_mynetworks accepts mail for -non-existent local recipients. +- The RBL checks now show the content of TXT records (Simon J Mudd). -Unfortunately, permit_recipient_map does not combine well with -check_relay_domains, because check_relay_domains either rejects -mail, or accepts mail regardless of whether a recipient exists. +- New "permit_auth_destination" UCE restriction for finer-grained +control (Jesper Skriver). Incompatible changes with postfix-19990906 ========================================== diff --git a/postfix/RESTRICTION_CLASS b/postfix/RESTRICTION_CLASS new file mode 100644 index 000000000..22f3d324c --- /dev/null +++ b/postfix/RESTRICTION_CLASS @@ -0,0 +1,24 @@ +Per client/helo/sender/recipient UCE restrictions +================================================= + +The Postfix SMTP server allows you to specify UCE restrictions on +the right-hand side of SMTPD access tables, so that you can have +different UCE restrictions for different clients or users. + +The only anomalies in this scheme are that (1) message header checks +are still the same for every message, and (2) you must use a +restriction class name (see below) if you want to specify a lookup +table on the right-hand side of an access table (this is because +Postfix needs to open those tables ahead of time). + +Restriction classes allow you to give easy-to-remember names to +groups of UCE restrictions (such as permissive, restrictive, and +so on). For example in main.cf: + + smtpd_restriction_classes = restrictive, permissive + restrictive = reject_unknown_sender reject_unknown_client ... + permissive = permit + +With this in place, you can use "restrictive" or "permissive" on +the right-hand side of your per-client/helo/sender/recipient SMTPD +access tables. diff --git a/postfix/aux/rmail/rmail b/postfix/aux/rmail/rmail new file mode 100755 index 000000000..44c999ee7 --- /dev/null +++ b/postfix/aux/rmail/rmail @@ -0,0 +1,8 @@ +#!/bin/sh + +# Dummy UUCP rmail command for postfix/qmail systems + +SENDMAIL="/usr/sbin/sendmail" +IFS=" " read junk from junk + +exec $SENDMAIL -f "$from" -- "$@" diff --git a/postfix/conf/master.cf b/postfix/conf/master.cf index 454a4f713..39ef93f26 100644 --- a/postfix/conf/master.cf +++ b/postfix/conf/master.cf @@ -71,5 +71,5 @@ uucp unix - n n - - pipe ifmail unix - n n - - pipe flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient) bsmtp unix - n n - - pipe - flags=F user=foo argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient + flags=F. user=foo argv=/usr/local/sbin/bsmtp -f $sender $nexthop $recipient diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index b5cb64508..b5551e634 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -210,6 +210,7 @@ smtpd_sender_restrictions = # 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/dns_lookup.c b/postfix/dns/dns_lookup.c index 19e809dd2..fab7144a8 100644 --- a/postfix/dns/dns_lookup.c +++ b/postfix/dns/dns_lookup.c @@ -165,10 +165,7 @@ static int dns_query(const char *name, int type, int flags, * only if the name server told us so. */ len = res_search((char *) name, C_IN, type, reply->buf, sizeof(reply->buf)); - reply_header = (HEADER *) reply->buf; if (len < 0) { - if (reply_header->rcode == SERVFAIL) - h_errno = NO_RECOVERY; if (why) vstring_sprintf(why, "Name service error for domain %s: %s", name, dns_strerror(h_errno)); @@ -194,6 +191,7 @@ static int dns_query(const char *name, int type, int flags, */ if ((reply->end = reply->buf + len) > reply->buf + sizeof(reply->buf)) reply->end = reply->buf + sizeof(reply->buf); + reply_header = (HEADER *) reply->buf; reply->query_start = reply->buf + sizeof(HEADER); reply->answer_start = 0; reply->query_count = ntohs(reply_header->qdcount); @@ -247,7 +245,7 @@ static int dns_get_fixed(unsigned char *pos, DNS_FIXED *fixed) static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos, char *rr_name, DNS_FIXED *fixed) { - unsigned char temp[DNS_NAME_LEN]; + char temp[DNS_NAME_LEN]; int data_len; unsigned pref = 0; unsigned char *src; @@ -255,6 +253,7 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos, int ch; #define MIN2(a, b) ((unsigned)(a) < (unsigned)(b) ? (a) : (b)) +#define UC(x) ((unsigned char *) (x)) if (pos + fixed->length > reply->end) return (0); @@ -296,7 +295,7 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos, break; case T_TXT: data_len = MIN2(fixed->length + 1, sizeof(temp)); - for (src = pos, dst = temp; dst < temp + data_len - 1; /* void */ ) { + for (src = pos, dst = UC(temp); dst < UC(temp) + data_len - 1; /* */ ) { ch = *src++; *dst++ = (ISPRINT(ch) ? ch : ' '); } diff --git a/postfix/global/local_transport.c b/postfix/global/local_transport.c index c555f3f57..76783dd82 100644 --- a/postfix/global/local_transport.c +++ b/postfix/global/local_transport.c @@ -8,20 +8,26 @@ /* /* const char *def_local_transport() /* -/* int local_transport(transport) +/* int match_def_local_transport(transport) +/* const char *transport; +/* +/* int match_any_local_transport(transport) /* const char *transport; /* DESCRIPTION /* This module uses the information kept in the "local_transports" /* configuration parameter, which lists the name of the default -/* local transport, followed by zero or more other transports that -/* deliver locally. +/* local transport, followed by the names of zero or more other +/* transports that deliver locally. /* /* def_local_transport() returns the name of the default local -/* transport, that is, the first transport name specified with +/* transport, that is, the first transport name specified with /* the "local_transports" configuration parameter. /* -/* local_transport() determines if the named transport is listed -/* in the "local_transports" configuration parameter. +/* match_def_local_transport() determines if the named transport is +/* identical to the default local transport. +/* +/* match_any_local_transport() determines if the named transport is +/* listed in the "local_transports" configuration parameter. /* SEE ALSO /* resolve_local(3), see if address resolves locally. /* LICENSE @@ -78,7 +84,7 @@ static void local_transport_init(void) /* * Sanity check. */ - if (!local_transport(local_transport_name)) + if (!match_any_local_transport(local_transport_name)) msg_panic("%s: unable to intialize", myname); } @@ -99,9 +105,27 @@ const char *def_local_transport(void) return (local_transport_name); } -/* local_transport - match address against list of local destinations */ +/* match_def_local_transport - match against default local transport */ + +int match_def_local_transport(const char *transport) +{ + + /* + * Initialize on the fly. + */ + if (local_transport_list == 0) + local_transport_init(); + + /* + * Compare the transport against the list of transports that are listed + * as delivering locally. + */ + return (strcmp(transport, local_transport_name) == 0); +} + +/* match_any_local_transport - match against list of local transports */ -int local_transport(const char *transport) +int match_any_local_transport(const char *transport) { /* @@ -127,7 +151,7 @@ int main(int argc, char **argv) if (argc != 2) msg_fatal("usage: %s transport", argv[0]); mail_conf_read(); - vstream_printf("%s\n", local_transport(argv[1]) ? "yes" : "no"); + vstream_printf("%s\n", match_any_local_transport(argv[1]) ? "yes" : "no"); vstream_fflush(VSTREAM_OUT); } diff --git a/postfix/global/local_transport.h b/postfix/global/local_transport.h index d3defdaa3..a1070c092 100644 --- a/postfix/global/local_transport.h +++ b/postfix/global/local_transport.h @@ -15,7 +15,8 @@ * External interface. */ extern const char *def_local_transport(void); -extern int local_transport(const char *); +extern int match_def_local_transport(const char *); +extern int match_any_local_transport(const char *); /* LICENSE /* .ad diff --git a/postfix/global/mail_addr_map.c b/postfix/global/mail_addr_map.c index 508251f8b..5146eb080 100644 --- a/postfix/global/mail_addr_map.c +++ b/postfix/global/mail_addr_map.c @@ -163,7 +163,7 @@ int main(int argc, char **argv) msg_fatal("chdir %s: %m", var_queue_dir); path = maps_create(argv[0], argv[1], DICT_FLAG_LOCK); while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { - if ((result = mail_addr_map(path, STR(buffer))) != 0) + if ((result = mail_addr_map(path, STR(buffer), 1)) != 0) argv_free(result); } vstring_free(buffer); diff --git a/postfix/global/mail_params.c b/postfix/global/mail_params.c index 7f65ef3dd..3a3c09779 100644 --- a/postfix/global/mail_params.c +++ b/postfix/global/mail_params.c @@ -168,10 +168,16 @@ char *var_local_transports; static const char *check_myhostname(void) { - const char *name; + static const char *name; const char *dot; const char *domain; + /* + * Use cached result. + */ + if (name) + return (name); + /* * If the local machine name is not in FQDN form, try to append the * contents of $mydomain. diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index 042b353f9..a0d539550 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-19991117" +#define DEF_MAIL_VERSION "Snapshot-19991120" extern char *var_mail_version; /* LICENSE diff --git a/postfix/global/pipe_command.c b/postfix/global/pipe_command.c index f697a19e0..da1b37b7b 100644 --- a/postfix/global/pipe_command.c +++ b/postfix/global/pipe_command.c @@ -335,8 +335,6 @@ int pipe_command(VSTREAM *src, VSTRING *why,...) */ if (pipe(cmd_in_pipe) < 0 || pipe(cmd_out_pipe) < 0) msg_fatal("%s: pipe: %m", myname); - cmd_in_stream = vstream_fdopen(cmd_in_pipe[1], O_WRONLY); - cmd_out_stream = vstream_fdopen(cmd_out_pipe[0], O_RDONLY); non_blocking(cmd_out_pipe[1], NON_BLOCKING); /* @@ -412,6 +410,9 @@ int pipe_command(VSTREAM *src, VSTRING *why,...) close(cmd_in_pipe[0]); close(cmd_out_pipe[1]); + cmd_in_stream = vstream_fdopen(cmd_in_pipe[1], O_WRONLY); + cmd_out_stream = vstream_fdopen(cmd_out_pipe[0], O_RDONLY); + /* * Give the command a limited amount of time to run, by enforcing * timeouts on all I/O from and to it. diff --git a/postfix/global/tok822_parse.c b/postfix/global/tok822_parse.c index 798c096a5..cd745cf96 100644 --- a/postfix/global/tok822_parse.c +++ b/postfix/global/tok822_parse.c @@ -324,11 +324,11 @@ TOK822 *tok822_scan(const char *str, TOK822 **tailp) } else if (ch == '"') { tp = tok822_alloc(TOK822_QSTRING, (char *) 0); COLLECT_SKIP_LAST(tp, str, ch, ch != '"'); - } else if (strchr(tok822_opchar, ch)) { + } else if (ch != '\\' && strchr(tok822_opchar, ch)) { tp = tok822_alloc(ch, (char *) 0); } else { tp = tok822_alloc(TOK822_ATOM, (char *) 0); - VSTRING_ADDCH(tp->vstr, ch); + str -= 1; /* \ may be first */ COLLECT(tp, str, ch, !ISSPACE(ch) && !strchr(tok822_opchar, ch)); tok822_quote_atom(tp); } diff --git a/postfix/html/postconf.1.html b/postfix/html/postconf.1.html index 72b218602..1455eec38 100644 --- a/postfix/html/postconf.1.html +++ b/postfix/html/postconf.1.html @@ -9,12 +9,15 @@ POSTCONF(1) POSTCONF(1) postconf - Postfix configuration utility SYNOPSIS - postconf [-c config_dir] [-d] [-h] [-n] [-v] [parameter - ...] + postconf [-dhmnv] [-c config_dir] [parameter ...] + + postconf [-ev] [-c config_dir] [parameter=value ...] DESCRIPTION - The postconf command prints the actual value of parameter - (all known parameters by default), one parameter per line. + The postconf command prints the actual value of parameter + (all known parameters by default), one parameter per line, + changes its value, or prints other information about the + Postfix mail system. Options: @@ -25,20 +28,28 @@ POSTCONF(1) POSTCONF(1) -d Print default parameter settings instead of actual settings. + -e Edit the main.cf configuration file. The file is + copied to a temporary file then renamed into place. + Parameters and values are specified on the command + line. Use quotes in order to protect shell + metacharacters and whitespace. + -h Show parameter values only, not the ``name = '' label that normally precedes the value. + -m List the names of all supported lookup table types. + -n Print non-default parameter settings only. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. DIAGNOSTICS Problems are reported to the standard error stream. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) @@ -51,17 +62,6 @@ POSTCONF(1) POSTCONF(1) - - - - - - - - - - - 1 diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index d4dbafc10..8de52584e 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -73,6 +73,12 @@ SMTPD(8) SMTPD(8) command after a configuration change. +Compatibility controls + strict_rfc821_envelopes + Disallow non-RFC 821 style addresses in envelopes. + For example, allow RFC822-style address forms with + comments, like Sendmail does. + Miscellaneous always_bcc Address to send a copy of each message that enters @@ -119,12 +125,6 @@ SMTPD(8) SMTPD(8) smtpd_recipient_limit Restrict the number of recipients that the SMTP - server accepts per message delivery. - - smtpd_timeout - Limit the time to send a server response and to - receive a client request. - @@ -137,6 +137,12 @@ SMTPD(8) SMTPD(8) SMTPD(8) SMTPD(8) + server accepts per message delivery. + + smtpd_timeout + Limit the time to send a server response and to + receive a client request. + Resource controls line_length_limit Limit the amount of memory in bytes used for the @@ -186,12 +192,6 @@ SMTPD(8) SMTPD(8) Restrict what recipient addresses are allowed in RCPT TO commands. - smtpd_etrn_restrictions - Restrict what domain names can be used in ETRN com- - mands, and what clients may issue ETRN commands. - - - 3 @@ -203,6 +203,10 @@ SMTPD(8) SMTPD(8) SMTPD(8) SMTPD(8) + smtpd_etrn_restrictions + Restrict what domain names can be used in ETRN com- + mands, and what clients may issue ETRN commands. + restriction_classes Declares the name of zero or more parameters that contain a list of UCE restrictions. The names of @@ -253,10 +257,6 @@ SMTPD(8) SMTPD(8) SEE ALSO cleanup(8) message canonicalization - master(8) process manager - syslogd(8) system logging - - @@ -269,6 +269,9 @@ SMTPD(8) SMTPD(8) SMTPD(8) SMTPD(8) + master(8) process manager + syslogd(8) system logging + LICENSE The Secure Mailer license must be distributed with this software. @@ -319,9 +322,6 @@ SMTPD(8) SMTPD(8) - - - diff --git a/postfix/html/uce.html b/postfix/html/uce.html index fdabb0c01..7b74063db 100644 --- a/postfix/html/uce.html +++ b/postfix/html/uce.html @@ -191,10 +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 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). +is OK or RELAY or all-numerical. 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).

@@ -339,10 +339,10 @@ 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 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). +the request when the result is OK or RELAY or +all-numerical. 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).

@@ -431,10 +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 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). +request if the result is OK or RELAY or all-numerical. +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).

@@ -579,12 +579,12 @@ $inet_interfaces.

maptype:mapname
Search the named 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 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). +address, parent domain, or localpart@. Reject the request if the +result is REJECT or "[45]XX text". Permit the +request if the result is OK or RELAY or all-numerical. +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).

@@ -715,10 +715,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 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). +the request if the result is OK or RELAY or +all-numerical. 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/resolve.c b/postfix/local/resolve.c index 2aa44a1eb..e8b93fc64 100644 --- a/postfix/local/resolve.c +++ b/postfix/local/resolve.c @@ -139,7 +139,7 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr * ugly code to force local recursive alias expansions on a host with no * authority over the local domain, but that code was just too unclean. */ - if (local_transport(STR(reply.transport))) { + if (match_def_local_transport(STR(reply.transport))) { status = deliver_recipient(state, usr_attr); } else { status = deliver_indirect(state); diff --git a/postfix/man/man1/postconf.1 b/postfix/man/man1/postconf.1 index 2e5bb2e0b..df036eb3c 100644 --- a/postfix/man/man1/postconf.1 +++ b/postfix/man/man1/postconf.1 @@ -9,23 +9,34 @@ Postfix configuration utility .na .nf .fi -\fBpostconf\fR [\fB-c \fIconfig_dir\fR] [\fB-d\fR] [\fB-h\fR] -[\fB-n\fR] [\fB-v\fR] [\fIparameter ...\fR] +\fBpostconf\fR [\fB-dhmnv\fR] [\fB-c \fIconfig_dir\fR] +[\fIparameter ...\fR] + +\fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] +[\fIparameter=value ...\fR] .SH DESCRIPTION .ad .fi The \fBpostconf\fR command prints the actual value of \fIparameter\fR (all known parameters by default), one -parameter per line. +parameter per line, changes its value, or prints other +information about the Postfix mail system. Options: .IP "\fB-c \fIconfig_dir\fR" The \fBmain.cf\fR configuration file is in the named directory. .IP \fB-d\fR Print default parameter settings instead of actual settings. +.IP \fB-e\fR +Edit the \fBmain.cf\fR configuration file. The file is copied +to a temporary file then renamed into place. Parameters and +values are specified on the command line. Use quotes in order +to protect shell metacharacters and whitespace. .IP \fB-h\fR Show parameter values only, not the ``name = '' label that normally precedes the value. +.IP \fB-m\fR +List the names of all supported lookup table types. .IP \fB-n\fR Print non-default parameter settings only. .IP \fB-v\fR diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 58050d44f..6396131a1 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -68,6 +68,12 @@ The following \fBmain.cf\fR parameters are especially relevant to this program. See the Postfix \fBmain.cf\fR file for syntax details and for default values. Use the \fBpostfix reload\fR command after a configuration change. +.SH "Compatibility controls" +.ad +.fi +.IP \fBstrict_rfc821_envelopes\fR +Disallow non-RFC 821 style addresses in envelopes. For example, +allow RFC822-style address forms with comments, like Sendmail does. .SH Miscellaneous .ad .fi diff --git a/postfix/postconf/postconf.c b/postfix/postconf/postconf.c index dce3e75d7..064a5c698 100644 --- a/postfix/postconf/postconf.c +++ b/postfix/postconf/postconf.c @@ -5,7 +5,7 @@ /* Postfix configuration utility /* SYNOPSIS /* .fi -/* \fBpostconf\fR [\fB-dhnv\fR] [\fB-c \fIconfig_dir\fR] +/* \fBpostconf\fR [\fB-dhmnv\fR] [\fB-c \fIconfig_dir\fR] /* [\fIparameter ...\fR] /* /* \fBpostconf\fR [\fB-ev\fR] [\fB-c \fIconfig_dir\fR] @@ -175,10 +175,16 @@ static int mode = SHOW_NAME; static const char *check_myhostname(void) { - const char *name; + static const char *name; const char *dot; const char *domain; + /* + * Use cached result. + */ + if (name) + return (name); + /* * If the local machine name is not in FQDN form, try to append the * contents of $mydomain. @@ -697,7 +703,7 @@ int main(int argc, char **argv) /* * Edit main.cf. */ - if (mode & EDIT_MAIN) { + else if (mode & EDIT_MAIN) { edit_parameters(argc - optind, argv + optind); } diff --git a/postfix/qmgr/qmgr_message.c b/postfix/qmgr/qmgr_message.c index c3ba5e8e9..a6a89b430 100644 --- a/postfix/qmgr/qmgr_message.c +++ b/postfix/qmgr/qmgr_message.c @@ -477,7 +477,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) /* * Bounce mail to non-existent users in virtual domains. */ - if (!local_transport(STR(reply.transport)) + if (!match_def_local_transport(STR(reply.transport)) && qmgr_virtual != 0 && (at = strrchr(recipient->address, '@')) != 0) { domain = lowercase(mystrdup(at + 1)); @@ -516,7 +516,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * job requires knowledge of local aliases. Yuck! I don't want to * duplicate delivery-agent specific knowledge in the queue manager. */ - if (local_transport(STR(reply.transport))) { + if (match_def_local_transport(STR(reply.transport))) { vstring_strcpy(reply.nexthop, STR(reply.recipient)); (void) split_at_right(STR(reply.nexthop), '@'); #if 0 diff --git a/postfix/smtp/smtp_connect.c b/postfix/smtp/smtp_connect.c index ac011a2db..50ce89135 100644 --- a/postfix/smtp/smtp_connect.c +++ b/postfix/smtp/smtp_connect.c @@ -277,8 +277,7 @@ SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why) session->best = (addr->pref == addr_list->pref); break; } - msg_info("%s; address %s port %d", vstring_str(why), - inet_ntoa(*((struct in_addr *) addr->data)), ntohs(port)); + msg_info("%s (port %d)", vstring_str(why), ntohs(port)); } dns_rr_free(addr_list); return (session); diff --git a/postfix/smtpd/Makefile.in b/postfix/smtpd/Makefile.in index f253df571..bfbc0e7a9 100644 --- a/postfix/smtpd/Makefile.in +++ b/postfix/smtpd/Makefile.in @@ -66,7 +66,7 @@ depend: $(MAKES) done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in @make -f Makefile.in Makefile -tests: smtpd_check_test smtpd_check_test2 smtpd_token_test +tests: smtpd_check_test smtpd_check_test2 smtpd_check_test3 smtpd_token_test smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref ../postmap/postmap smtpd_check_access @@ -80,6 +80,12 @@ smtpd_check_test2: smtpd_check smtpd_check.in2 smtpd_check.ref2 diff smtpd_check.ref2 smtpd_check.tmp rm -f smtpd_check.tmp smtpd_check_access.* +smtpd_check_test3: smtpd_check smtpd_check.in3 smtpd_check.ref3 + ../postmap/postmap smtpd_check_access + ./smtpd_check smtpd_check.tmp 2>&1 + diff smtpd_check.ref3 smtpd_check.tmp + rm -f smtpd_check.tmp smtpd_check_access.* + smtpd_token_test: smtpd_token smtpd_token.in smtpd_token.ref ./smtpd_token smtpd_token.tmp 2>&1 diff smtpd_token.ref smtpd_token.tmp diff --git a/postfix/smtpd/smtpd.h b/postfix/smtpd/smtpd.h index cf934f141..32b7dec7b 100644 --- a/postfix/smtpd/smtpd.h +++ b/postfix/smtpd/smtpd.h @@ -51,6 +51,7 @@ typedef struct SMTPD_STATE { char *etrn_name; char *protocol; char *where; + int recursion; } SMTPD_STATE; extern void smtpd_state_init(SMTPD_STATE *, VSTREAM *); diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 48eaac71a..03a8a92f4 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -305,19 +305,19 @@ static VSTRING *error_text; /* * 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_rest_classes; static HTABLE *smtpd_rcpt_maps; @@ -433,7 +433,7 @@ void smtpd_check_init(void) /* 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 +486,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 +504,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 +537,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 +574,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 +610,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 +646,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 +668,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 +690,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"; @@ -715,7 +715,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient, * Permit if destination is local. XXX This must be generalized for * per-domain user tables and for non-UNIX local delivery agents. */ - if (local_transport(STR(reply.transport)) + if (match_any_local_transport(STR(reply.transport)) || (domain = strrchr(STR(reply.recipient), '@')) == 0) return (SMTPD_CHECK_OK); domain += 1; @@ -754,7 +754,7 @@ static int permit_auth_destination(char *recipient) * Permit if destination is local. XXX This must be generalized for * per-domain user tables and for non-UNIX local delivery agents. */ - if (local_transport(STR(reply.transport)) + if (match_any_local_transport(STR(reply.transport)) || (domain = strrchr(STR(reply.recipient), '@')) == 0) return (SMTPD_CHECK_OK); domain += 1; @@ -773,7 +773,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; @@ -791,7 +791,7 @@ static int reject_unauth_destination(SMTPD_STATE *state, char *recipient) * Pass if destination is local. XXX This must be generalized for * per-domain user tables and for non-UNIX local delivery agents. */ - if (local_transport(STR(reply.transport)) + if (match_any_local_transport(STR(reply.transport)) || (domain = strrchr(STR(reply.recipient), '@')) == 0) return (SMTPD_CHECK_DUNNO); domain += 1; @@ -812,7 +812,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,10 +872,11 @@ 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; + DNS_RR *mx_list; DNS_RR *mx; int dns_status; @@ -893,7 +894,7 @@ static int permit_mx_backup(SMTPD_STATE *unused_state, const char *recipient) * If the destination is local, it is acceptable, because we are * supposedly MX for our own address. */ - if (local_transport(STR(reply.transport)) + if (match_any_local_transport(STR(reply.transport)) || (domain = strrchr(STR(reply.recipient), '@')) == 0) return (SMTPD_CHECK_OK); domain += 1; @@ -956,7 +957,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"; @@ -1009,7 +1010,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"; @@ -1027,7 +1028,7 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr, /* * Skip local destinations and non-DNS forms. */ - if (local_transport(STR(reply.transport)) + if (match_any_local_transport(STR(reply.transport)) || (domain = strrchr(STR(reply.recipient), '@')) == 0) return (SMTPD_CHECK_DUNNO); domain += 1; @@ -1048,8 +1049,9 @@ static int permit_rcpt_map(char *table, char *reply_name) { char *myname = "permit_rcpt_map"; char *domain; - MAPS *map; - DICT *dict; + + MAPS *map; + DICT *dict; if (msg_verbose) msg_info("%s: %s %s", myname, table, reply_name); @@ -1067,7 +1069,7 @@ static int permit_rcpt_map(char *table, char *reply_name) return (SMTPD_CHECK_DUNNO); domain += 1; if (domain[0] == '#' || domain[0] == '[') - if (!local_transport(STR(reply.transport))) + if (!match_any_local_transport(STR(reply.transport))) return (SMTPD_CHECK_DUNNO); /* @@ -1075,6 +1077,10 @@ static int permit_rcpt_map(char *table, char *reply_name) * 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) @@ -1093,14 +1099,14 @@ static int permit_rcpt_map(char *table, char *reply_name) /* 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) @@ -1124,7 +1130,7 @@ static int check_table_result(SMTPD_STATE *state, char *table, * All-numeric result probably means OK - some out-of-band authentication * mechanism uses this as time stamp. */ - if (value[strcspn(value, "0123456789")] == 0) + if (*value && value[strspn(value, "0123456789")] == 0) return (SMTPD_CHECK_OK); /* @@ -1161,6 +1167,19 @@ static int check_table_result(SMTPD_STATE *state, char *table, msg_warn("define a restriction class and specify its name instead"); longjmp(smtpd_check_buf, -1); } + + /* + * Don't get carried away with recursion. + */ + if (state->recursion++ > 100) { + msg_warn("SMTPD access map %s entry %s causes unreasonable recursion", + table, value); + longjmp(smtpd_check_buf, -1); + } + + /* + * Recursively evaluate the restrictions given in the right-hand side. + */ restrictions = argv_split(value, " \t\r\n,"); status = generic_checks(state, restrictions, reply_name, reply_class, def_acl); @@ -1170,7 +1189,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"; @@ -1200,7 +1219,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) @@ -1240,7 +1259,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) @@ -1277,7 +1296,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) @@ -1313,7 +1332,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) { @@ -1373,7 +1392,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, "."); @@ -1469,7 +1488,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"; @@ -1671,7 +1690,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; @@ -1684,6 +1703,7 @@ char *smtpd_check_client(SMTPD_STATE *state) /* * Apply restrictions in the order as specified. */ + state->recursion = 0; status = setjmp(smtpd_check_buf); if (status == 0 && client_restrctions->argc) status = generic_checks(state, client_restrctions, state->namaddr, @@ -1694,7 +1714,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; @@ -1729,6 +1749,7 @@ char *smtpd_check_helo(SMTPD_STATE *state, char *helohost) /* * Apply restrictions in the order as specified. */ + state->recursion = 0; status = setjmp(smtpd_check_buf); if (status == 0 && helo_restrctions->argc) status = generic_checks(state, helo_restrctions, state->helo_name, @@ -1739,7 +1760,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; @@ -1764,6 +1785,7 @@ char *smtpd_check_mail(SMTPD_STATE *state, char *sender) /* * Apply restrictions in the order as specified. */ + state->recursion = 0; status = setjmp(smtpd_check_buf); if (status == 0 && mail_restrctions->argc) status = generic_checks(state, mail_restrctions, sender, @@ -1774,7 +1796,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; @@ -1809,6 +1831,7 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient) /* * Apply restrictions in the order as specified. */ + state->recursion = 0; status = setjmp(smtpd_check_buf); if (status == 0 && rcpt_restrctions->argc) status = generic_checks(state, rcpt_restrctions, @@ -1819,7 +1842,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; @@ -1853,6 +1876,7 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) /* * Apply restrictions in the order as specified. */ + state->recursion = 0; status = setjmp(smtpd_check_buf); if (status == 0 && etrn_restrctions->argc) status = generic_checks(state, etrn_restrctions, domain, @@ -1863,7 +1887,7 @@ char *smtpd_check_etrn(SMTPD_STATE *state, char *domain) /* 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; @@ -1939,7 +1963,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, @@ -1984,7 +2008,7 @@ typedef struct { char *name; int defval; int *target; -} INT_TABLE; +} INT_TABLE; int var_unk_client_code; int var_bad_name_code; @@ -2072,9 +2096,29 @@ static int rest_update(char **argv) return (0); } +/* rest_class - (re)define a restriction class */ + +static void rest_class(char *class) +{ + char *cp = class; + char *name; + HTABLE_INFO *entry; + + if (smtpd_rest_classes == 0) + smtpd_rest_classes = htable_create(1); + + if ((name = mystrtok(&cp, " \t\r\n,")) == 0) + msg_panic("rest_class: null class name"); + if ((entry = htable_locate(smtpd_rest_classes, name)) != 0) + argv_free((ARGV *) entry->value); + else + entry = htable_enter(smtpd_rest_classes, name, (char *) 0); + entry->value = (char *) smtpd_check_parse(cp); +} + /* 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); @@ -2083,7 +2127,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"); @@ -2094,7 +2138,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"); @@ -2107,7 +2151,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) { } @@ -2206,6 +2250,11 @@ main(int argc, char **argv) resp = 0; break; } + if (strcasecmp(args->argv[0], "restriction_class") == 0) { + rest_class(args->argv[1]); + resp = 0; + break; + } if (int_update(args->argv) || string_update(args->argv) || rest_update(args->argv)) { @@ -2244,6 +2293,7 @@ main(int argc, char **argv) helo_restrictions \n\ sender_restrictions \n\ recipient_restrictions \n\ + restriction_class name,\n\ \n\ Note: no address rewriting \n"; break; diff --git a/postfix/smtpd/smtpd_check.in b/postfix/smtpd/smtpd_check.in index 02e11e9e9..fd827324b 100644 --- a/postfix/smtpd/smtpd_check.in +++ b/postfix/smtpd/smtpd_check.in @@ -9,7 +9,7 @@ relay_domains porcupine.org # # Test the client restrictions. # -client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access +client_restrictions permit_mynetworks,reject_unknown_client,dbm:./smtpd_check_access client unknown 131.155.210.17 client unknown 168.100.189.13 client random.bad.domain 123.123.123.123 @@ -21,14 +21,14 @@ client_restrictions permit_mynetworks # # Test the helo restrictions # -helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,hash:./smtpd_check_access +helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,dbm:./smtpd_check_access client unknown 131.155.210.17 helo foo. client foo 123.123.123.123 helo foo. helo foo helo spike.porcupine.org -helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access +helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access helo random.bad.domain helo friend.bad.domain helo_restrictions reject_invalid_hostname,reject_unknown_hostname @@ -48,7 +48,7 @@ mail foo@watson.ibm.com sender_restrictions reject_unknown_address mail foo@watson.ibm.com mail foo@bad.domain -sender_restrictions hash:./smtpd_check_access +sender_restrictions dbm:./smtpd_check_access mail bad-sender@any.domain mail bad-sender@good.domain mail reject@this.address @@ -75,7 +75,7 @@ rcpt foo@porcupine.org client foo 123.123.123.123 rcpt foo@watson.ibm.com rcpt foo@porcupine.org -recipient_restrictions hash:./smtpd_check_access +recipient_restrictions dbm:./smtpd_check_access mail bad-sender@any.domain mail bad-sender@good.domain mail reject@this.address @@ -94,16 +94,16 @@ client foo 127.0.0.2 recipient_restrictions check_relay_domains client foo 131.155.210.17 rcpt foo@watson.ibm.com -recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains +recipient_restrictions check_client_access,dbm:./smtpd_check_access,check_relay_domains client foo 131.155.210.17 rcpt foo@porcupine.org -helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access -recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains +helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access +recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_relay_domains helo bad.domain rcpt foo@porcupine.org helo 131.155.210.17 rcpt foo@porcupine.org -recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains +recipient_restrictions check_sender_access,dbm:./smtpd_check_access,check_relay_domains mail foo@bad.domain rcpt foo@porcupine.org mail foo@friend.bad.domain @@ -123,7 +123,7 @@ rcpt wietse@porcupine.org client_restrictions permit helo_restrictions permit sender_restrictions permit -recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_sender_access,hash:./smtpd_check_access +recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_sender_access,dbm:./smtpd_check_access helo bad.domain mail foo@good.domain rcpt foo@porcupine.org diff --git a/postfix/smtpd/smtpd_check.in2 b/postfix/smtpd/smtpd_check.in2 index 0eaf8c02b..9dbfd36f7 100644 --- a/postfix/smtpd/smtpd_check.in2 +++ b/postfix/smtpd/smtpd_check.in2 @@ -9,7 +9,7 @@ relay_domains porcupine.org # # Test the client restrictions. # -client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access +client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,dbm:./smtpd_check_access client unknown 131.155.210.17 client unknown 168.100.189.13 client random.bad.domain 123.123.123.123 @@ -21,14 +21,14 @@ client_restrictions permit_mynetworks # # Test the helo restrictions # -helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,hash:./smtpd_check_access +helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,dbm:./smtpd_check_access client unknown 131.155.210.17 helo foo. client foo 123.123.123.123 helo foo. helo foo helo spike.porcupine.org -helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access +helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,dbm:./smtpd_check_access helo random.bad.domain helo friend.bad.domain # @@ -44,7 +44,7 @@ mail foo@watson.ibm.com sender_restrictions reject_unknown_address mail foo@watson.ibm.com mail foo@bad.domain -sender_restrictions check_sender_access,hash:./smtpd_check_access +sender_restrictions check_sender_access,dbm:./smtpd_check_access mail bad-sender@any.domain mail bad-sender@good.domain mail reject@this.address @@ -71,7 +71,7 @@ rcpt foo@porcupine.org client foo 123.123.123.123 rcpt foo@watson.ibm.com rcpt foo@porcupine.org -recipient_restrictions check_recipient_access,hash:./smtpd_check_access +recipient_restrictions check_recipient_access,dbm:./smtpd_check_access mail bad-sender@any.domain mail bad-sender@good.domain mail reject@this.address diff --git a/postfix/smtpd/smtpd_check.ref b/postfix/smtpd/smtpd_check.ref index 1ed6fca90..6e9e1b351 100644 --- a/postfix/smtpd/smtpd_check.ref +++ b/postfix/smtpd/smtpd_check.ref @@ -12,7 +12,7 @@ OK >>> # >>> # Test the client restrictions. >>> # ->>> client_restrictions permit_mynetworks,reject_unknown_client,hash:./smtpd_check_access +>>> client_restrictions permit_mynetworks,reject_unknown_client,dbm:./smtpd_check_access OK >>> client unknown 131.155.210.17 ./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] @@ -37,7 +37,7 @@ OK >>> # >>> # Test the helo restrictions >>> # ->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,hash:./smtpd_check_access +>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,dbm:./smtpd_check_access OK >>> client unknown 131.155.210.17 OK @@ -54,7 +54,7 @@ OK 450 : Helo command rejected: Host not found >>> helo spike.porcupine.org OK ->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access +>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access OK >>> helo random.bad.domain ./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 : Helo command rejected: match bad.domain @@ -96,7 +96,7 @@ OK >>> mail foo@bad.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 : Sender address rejected: Domain not found; from= 450 : Sender address rejected: Domain not found ->>> sender_restrictions hash:./smtpd_check_access +>>> sender_restrictions dbm:./smtpd_check_access OK >>> mail bad-sender@any.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@; from= @@ -156,7 +156,7 @@ OK 554 : Recipient address rejected: Relay access denied >>> rcpt foo@porcupine.org OK ->>> recipient_restrictions hash:./smtpd_check_access +>>> recipient_restrictions dbm:./smtpd_check_access OK >>> mail bad-sender@any.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@; from= @@ -194,15 +194,15 @@ OK >>> rcpt foo@watson.ibm.com ./smtpd_check: reject: RCPT from foo[131.155.210.17]: 554 : Recipient address rejected: Relay access denied; from= to= 554 : Recipient address rejected: Relay access denied ->>> recipient_restrictions check_client_access,hash:./smtpd_check_access,check_relay_domains +>>> recipient_restrictions check_client_access,dbm:./smtpd_check_access,check_relay_domains OK >>> client foo 131.155.210.17 OK >>> rcpt foo@porcupine.org OK ->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,hash:./smtpd_check_access +>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,dbm:./smtpd_check_access OK ->>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_relay_domains +>>> recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_relay_domains OK >>> helo bad.domain ./smtpd_check: reject: HELO from foo[131.155.210.17]: 554 : Helo command rejected: match bad.domain; from= @@ -215,7 +215,7 @@ OK OK >>> rcpt foo@porcupine.org OK ->>> recipient_restrictions check_sender_access,hash:./smtpd_check_access,check_relay_domains +>>> recipient_restrictions check_sender_access,dbm:./smtpd_check_access,check_relay_domains OK >>> mail foo@bad.domain ./smtpd_check: reject: MAIL from foo[131.155.210.17]: 554 : Sender address rejected: match bad.domain; from= @@ -252,7 +252,7 @@ OK OK >>> sender_restrictions permit OK ->>> recipient_restrictions check_helo_access,hash:./smtpd_check_access,check_sender_access,hash:./smtpd_check_access +>>> recipient_restrictions check_helo_access,dbm:./smtpd_check_access,check_sender_access,dbm:./smtpd_check_access OK >>> helo bad.domain OK diff --git a/postfix/smtpd/smtpd_check.ref2 b/postfix/smtpd/smtpd_check.ref2 index 55143b69c..17573ff4e 100644 --- a/postfix/smtpd/smtpd_check.ref2 +++ b/postfix/smtpd/smtpd_check.ref2 @@ -12,7 +12,7 @@ OK >>> # >>> # Test the client restrictions. >>> # ->>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,hash:./smtpd_check_access +>>> client_restrictions permit_mynetworks,reject_unknown_client,check_client_access,dbm:./smtpd_check_access OK >>> client unknown 131.155.210.17 ./smtpd_check: reject: CONNECT from unknown[131.155.210.17]: 450 Client host rejected: cannot find your hostname, [131.155.210.17] @@ -37,7 +37,7 @@ OK >>> # >>> # Test the helo restrictions >>> # ->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,hash:./smtpd_check_access +>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,reject_unknown_hostname,check_helo_access,dbm:./smtpd_check_access OK >>> client unknown 131.155.210.17 OK @@ -54,7 +54,7 @@ OK 450 : Helo command rejected: Host not found >>> helo spike.porcupine.org OK ->>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,hash:./smtpd_check_access +>>> helo_restrictions permit_mynetworks,reject_unknown_client,reject_invalid_hostname,check_helo_access,dbm:./smtpd_check_access OK >>> helo random.bad.domain ./smtpd_check: reject: HELO from foo[123.123.123.123]: 554 : Helo command rejected: match bad.domain @@ -86,7 +86,7 @@ OK >>> mail foo@bad.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 450 : Sender address rejected: Domain not found; from= 450 : Sender address rejected: Domain not found ->>> sender_restrictions check_sender_access,hash:./smtpd_check_access +>>> sender_restrictions check_sender_access,dbm:./smtpd_check_access OK >>> mail bad-sender@any.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@; from= @@ -146,7 +146,7 @@ OK 554 : Recipient address rejected: Relay access denied >>> rcpt foo@porcupine.org OK ->>> recipient_restrictions check_recipient_access,hash:./smtpd_check_access +>>> recipient_restrictions check_recipient_access,dbm:./smtpd_check_access OK >>> mail bad-sender@any.domain ./smtpd_check: reject: MAIL from foo[123.123.123.123]: 554 : Sender address rejected: match bad-sender@; from= diff --git a/postfix/smtpd/smtpd_check_access b/postfix/smtpd/smtpd_check_access index b03f3a50d..f7f6e42d7 100644 --- a/postfix/smtpd/smtpd_check_access +++ b/postfix/smtpd/smtpd_check_access @@ -5,3 +5,6 @@ bad-sender@good.domain OK 131.155.210 554 match 131.155.210 131.155.210.17 OK reject@this.address 554 match reject@this.address +open_user@some.site open +strict_user@some.site strict +auth_client 123456 diff --git a/postfix/smtpd/smtpd_peer.c b/postfix/smtpd/smtpd_peer.c index 059e250f2..23a44a853 100644 --- a/postfix/smtpd/smtpd_peer.c +++ b/postfix/smtpd/smtpd_peer.c @@ -36,7 +36,7 @@ /* error (no address->name mapping or no name->address mapping). /* .IP 5 /* The name lookup or verification failed with an unrecoverable -/* error (no address->name mapping, bad hostname syntax, no +/* error (no address->name mapping, bad hostname syntax, no /* name->address mapping, client address not listed for hostname). /* .RE /* .PP @@ -58,12 +58,30 @@ #include #include #include +#include /* strerror() */ +#include #include #include + /* + * Older systems don't have h_errno. Even modern systems don't have + * hstrerror(). + */ #ifdef NO_HERRNO + static int h_errno = TRY_AGAIN; -define hstrerror(x) "Host not found" + +#define HSTRERROR(err) "Host not found" + +#else + +#define HSTRERROR(err) (\ + err == TRY_AGAIN ? "Host not found, try again" : \ + err == HOST_NOT_FOUND ? "Host not found" : \ + err == NO_DATA ? "Host name has no address" : \ + err == NO_RECOVERY ? "Name server failure" : \ + strerror(errno) \ + ) #endif /* Utility library. */ @@ -82,7 +100,7 @@ define hstrerror(x) "Host not found" /* smtpd_peer_init - initialize peer information */ -void smtpd_peer_init(SMTPD_STATE *state) +void smtpd_peer_init(SMTPD_STATE * state) { struct sockaddr_in sin; SOCKADDR_SIZE len = sizeof(sin); @@ -90,93 +108,97 @@ void smtpd_peer_init(SMTPD_STATE *state) int i; /* - * If it's not networked assume local. + * Look up the peer address information. */ if (getpeername(vstream_fileno(state->client), - (struct sockaddr *) & sin, &len) < 0) - sin.sin_family = AF_UNSPEC; - - switch (sin.sin_family) { + (struct sockaddr *) & sin, &len) >= 0) { + errno = 0; + } - /* - * If it's not Internet, assume the client is local, and avoid using - * the naming service because that can hang when the machine is - * disconnected. - */ - default: - state->name = mystrdup("localhost"); - state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */ - state->peer_code = 2; - break; + /* + * If peer went away, give up. + */ + if (errno == ECONNRESET || errno == ECONNABORTED) { + msg_info("errno %d %m", errno); + state->name = mystrdup("unknown"); + state->addr = mystrdup("unknown"); + state->peer_code = 5; + } - /* - * Look up and "verify" the client hostname. - */ - case AF_INET: + /* + * Look up and "verify" the client hostname. + */ + else if (errno == 0 && sin.sin_family == AF_INET) { state->addr = mystrdup(inet_ntoa(sin.sin_addr)); hp = gethostbyaddr((char *) &(sin.sin_addr), sizeof(sin.sin_addr), AF_INET); if (hp == 0) { state->name = mystrdup("unknown"); state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5); - break; - } - if (!valid_hostname(hp->h_name)) { + } else if (!valid_hostname(hp->h_name)) { state->name = mystrdup("unknown"); state->peer_code = 5; - break; - } - state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */ - state->peer_code = 2; + } else { + state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */ + state->peer_code = 2; + + /* + * Reject the hostname if it does not list the peer address. + */ +#define REJECT_PEER_NAME(state, code) { \ + myfree(state->name); \ + state->name = mystrdup("unknown"); \ + state->peer_code = 5; \ + } - /* - * Reject the hostname if it does not list the peer address. - */ - hp = gethostbyname(state->name); /* clobbers hp->name!! */ - if (hp == 0) { - msg_warn("hostname %s verification failed: %s", - state->name, hstrerror(h_errno)); - myfree(state->name); - state->name = mystrdup("unknown"); - state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5); - break; - } - if (hp->h_length != sizeof(sin.sin_addr)) { - msg_warn("hostname %s verification failed: bad address size %d", - state->name, hp->h_length); - myfree(state->name); - state->name = mystrdup("unknown"); - state->peer_code = 5; - break; + hp = gethostbyname(state->name); /* clobbers hp->name!! */ + if (hp == 0) { + msg_warn("%s: hostname %s verification failed: %s", + state->addr, state->name, HSTRERROR(h_errno)); + REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5)); + } else if (hp->h_length != sizeof(sin.sin_addr)) { + msg_warn("%s: hostname %s verification failed: bad address size %d", + state->addr, state->name, hp->h_length); + REJECT_PEER_NAME(state, 5); + } else { + for (i = 0; /* void */ ; i++) { + if (hp->h_addr_list[i] == 0) { + msg_warn("%s: address not listed for hostname %s", + state->addr, state->name); + REJECT_PEER_NAME(state, 5); + break; + } + if (memcmp(hp->h_addr_list[i], + (char *) &sin.sin_addr, + sizeof(sin.sin_addr)) == 0) + break; /* keep peer name */ + } + } } - for (i = 0; hp->h_addr_list[i]; i++) { - if (memcmp(hp->h_addr_list[i], - (char *) &sin.sin_addr, - sizeof(sin.sin_addr)) == 0) - break; - } - if (hp->h_addr_list[i] == 0) { - msg_warn("address %s not listed for name %s", - state->addr, state->name); - myfree(state->name); - state->name = mystrdup("unknown"); - state->peer_code = 5; - break; - } - break; } + + /* + * If it's not Internet, assume the client is local, and avoid using the + * naming service because that can hang when the machine is disconnected. + */ + else { + state->name = mystrdup("localhost"); + state->addr = mystrdup("127.0.0.1"); /* XXX bogus. */ + state->peer_code = 2; + } + + /* + * Do the name[addr] formatting for pretty reports. + */ state->namaddr = concatenate(state->name, "[", state->addr, "]", (char *) 0); } /* smtpd_peer_reset - destroy peer information */ -void smtpd_peer_reset(SMTPD_STATE *state) +void smtpd_peer_reset(SMTPD_STATE * state) { - if (state->name) - myfree(state->name); - if (state->addr) - myfree(state->addr); - if (state->namaddr) - myfree(state->namaddr); + myfree(state->name); + myfree(state->addr); + myfree(state->namaddr); } diff --git a/postfix/smtpd/smtpd_state.c b/postfix/smtpd/smtpd_state.c index 6199b7583..a14b64216 100644 --- a/postfix/smtpd/smtpd_state.c +++ b/postfix/smtpd/smtpd_state.c @@ -85,6 +85,7 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream) state->etrn_name = 0; state->protocol = "SMTP"; state->where = SMTPD_AFTER_CONNECT; + state->recursion = 0; /* * Initialize peer information.