From: Wietse Venema Date: Wed, 10 Nov 1999 05:00:00 +0000 (-0500) Subject: snapshot-19991110 X-Git-Tag: v20010228~92 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b37fc863cd3f871307cc3544a38f4e42df0fe35;p=thirdparty%2Fpostfix.git snapshot-19991110 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/0README b/postfix/0README index b09fc9247..083ebe270 100644 --- a/postfix/0README +++ b/postfix/0README @@ -151,6 +151,7 @@ Test programs: Miscellaneous: + auxiliary/ Auxiliary software etc. bin/ Postfix command executables conf/ Sample configuration files include/ Installed include files diff --git a/postfix/HISTORY b/postfix/HISTORY index 4a63ed474..2f8367cb2 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -3053,7 +3053,7 @@ Apologies for any names omitted. 19990908 Portability: Unixware has only after sendmail - is installed. Changed postlock.c to use global/sys_exists.h. + is installed. Changed postlock.c to use global/sys_exits.h. 19990909 @@ -3091,6 +3091,87 @@ Apologies for any names omitted. File: smtpd/smtpd_access.c. Cleanup: removed spurious sender address checks for <>. + File: smtpd/smtpd_check.c. Cleanup: the smtp client now consistently logs host[address] for all connection attempts. + +19990919 + + Feature: in an SMTPD access map, an all-numeric right-hand + side now means OK, for better cooperation with out-of-band + authentication mechanisms. + +19990922 + + Security: recipient addresses must not start with '-', in + order to protect external commands. The old behavior is + re-instated when main.cf specifies: "allow_min_user = + yes". Credits to Mads Kiilerich @ Kiilerich.com. File: + qmgr/qmgr_message.c. + + Bugfix: after 19990831, the queue manager would throw away + defer logs after deferring mail to known-to-be-dead hosts + or message transports. This means that in some cases, mailq + would not show why mail is delayed, and that delayed mail + could be sent back with recipients missing from the error + report. Reported by Giulio Orsero @ tiscalinet.it. + +19990923 + + Bugfix: the above bugfix broke bounces of mail with bad + address syntax and relocated users. Problem diagnosed by + Dick Porter @ acm.org. + + Documentation: added DO NOT EDIT THIS FILE. EDIT MAIN.CF + INSTEAD notices to the sample-xxx.cf files. + +19991007 + + Compatibility: ignore the sendmail -U (initial user + submission) option. Thomas Quinot @ cuivre.fr.eu.org. + +19991103 + + Code cleanup: don't send postmaster notifications when an + SMTP client sends a DATA command while no recipients were + accepted. This can happen when a pipelined client runs + into an UCE block. File: smtpd/smtpd.c. + +19991104 + + Robustness: do not apply UCE header checks to mail that is + generated by Postfix (bounces, forwarded mail etc.). Files: + smtpd/smtpd.c, pickup/pickup.c, cleanup/cleanup_message.c. + + Robustness: new generic watchdog module that can deal with + clocks that jump occasionally. Files: util/watchdog.c, + master/master.c, master/{single,multi,trigger}_server.c. + This hopefully ends the false watchdog alarms that happen + when clocks are set or when laptops are resumed. + + Code cleanup: BSMTP requires dot quoting as per RFC 821. + Based on code by Florian Lohoff @ rfc822.org. Files: + global/mail_copy.[hc], pipe/pipe.c. + +19991105 + + Bugfix: the crufty code in inet_addr_local() did not find + IP aliases. File: util/inet_addr_local.c. + + Portability: the INSTALL.sh utility did not find users or + groups in NIS or Netinfo tables. The script no longer + searches the /etc/passwd and /etc/group files. Instead it + now queries the unix:passwd.byname and unix:group.byname + maps. For this, a -q (query) option was added to postmap + (and to postalias, for symmetry). Files: util/dict_unix.c, + postalias/postalias.c, postmap/postmap.c, INSTALL.sh. + + Bugfix: LDAP lookup timeout settings were ignored. Patch + by John Hensley. File: util/dict_ldap.c. + +19991110 + + Code cleanup: greatly simplified the SMTPD command parser + and somewhat simplified the code that groks RFC 822-style + address syntax in MAIL FROM and RCPT TO commands. diff --git a/postfix/INSTALL.sh b/postfix/INSTALL.sh index fb3bd2c62..0b740f319 100644 --- a/postfix/INSTALL.sh +++ b/postfix/INSTALL.sh @@ -28,9 +28,9 @@ your changes interactively. command_directory - directory with Postfix administrative commands. queue_directory - directory with Postfix queues. - sendmail_path - full pathname of the sendmail command. - newaliases_path - full pathname of the newaliases command. - mailq_path - full pathname of the mailq command. + sendmail_path - full pathname of the Postfix sendmail command. + newaliases_path - full pathname of the Postfix newaliases command. + mailq_path - full pathname of the Postfix mailq command. owner - owner of Postfix queue files. @@ -138,7 +138,7 @@ do esac done -grep "^$owner:" /etc/passwd >/dev/null || { +bin/postmap -c ./conf -q "$owner" unix:passwd.byname >/dev/null || { echo "$owner needs an entry in the passwd file" 1>&2 echo "Remember, $owner must have a dedicated user id and group id." 1>&2 exit 1 @@ -146,7 +146,7 @@ grep "^$owner:" /etc/passwd >/dev/null || { case $setgid in no) ;; - *) grep "^$setgid:" /etc/group >/dev/null || { + *) bin/postmap -c ./conf -q "$setgid" unix:group.byname >/dev/null || { echo "$setgid needs an entry in the group file" 1>&2 echo "Remember, $setgid must have a dedicated group id." 1>&2 exit 1 @@ -174,7 +174,7 @@ rm -f junk # Install files. Be careful to not copy over running programs. -for file in `ls libexec | grep '^[a-z]'` +for file in `ls libexec` do compare_or_replace a+x,go-w libexec/$file $daemon_directory/$file || exit 1 done @@ -199,7 +199,7 @@ test -f $config_directory/main.cf || { s;^daemon_directory .*;daemon_directory = $daemon_directory; s;^command_directory .*;command_directory = $command_directory; s;^queue_directory .*;queue_directory = $queue_directory; - s;^mail_owner .*;mail_owner = $mail_owner; + s;^mail_owner .*;mail_owner = $owner; " conf/main.cf >$config_directory/main.cf || exit 1 echo "Warning: you still need to edit myorigin/mydestination in" 1>&2 diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index f1792aba7..dee14e3e5 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -1,11 +1,15 @@ -Incompatible changes with snapshot 19990911 +Incompatible changes with snapshot XXXXXXXX =========================================== +- 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 SMTPD access control tables. Use the permit_recipient_map feature instead. The loss is compensated for. -Major changes with snapshot 19990911 +Major changes with snapshot XXXXXXXX ==================================== - Per-client/helo/sender/recipient UCE restrictions: you can now @@ -23,7 +27,7 @@ UCE restrictions. For example in main.cf: restrictive = reject_unknown_sender reject_unknown_client ... permissive = permit -Then use "restrictive" or "restrictive" on the right-hand side of +Then use "restrictive" or "permissive" on the right-hand side of your per-client/helo/sender/recipient SMTPD access tables. - Reject mail for non-existent local accounts. You can now use @@ -51,8 +55,8 @@ permit_mynetworks, because permit_mynetworks accepts mail for non-existent local recipients. Unfortunately, permit_recipient_map does not combine well with -check_relay_domains, because check_relay_domains permits either -rejects mail, or accepts mail for non-existent local recipients. +check_relay_domains, because check_relay_domains either rejects +mail, or accepts mail regardless of whether a recipient exists. Incompatible changes with postfix-19990906 ========================================== diff --git a/postfix/aux/rmail/rmail b/postfix/auxiliary/rmail/rmail similarity index 100% rename from postfix/aux/rmail/rmail rename to postfix/auxiliary/rmail/rmail diff --git a/postfix/bounce/.indent.pro b/postfix/bounce/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/bounce/.indent.pro +++ b/postfix/bounce/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/cleanup/.indent.pro b/postfix/cleanup/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/cleanup/.indent.pro +++ b/postfix/cleanup/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/cleanup/cleanup_message.c b/postfix/cleanup/cleanup_message.c index 2a862e54c..25c55bcf9 100644 --- a/postfix/cleanup/cleanup_message.c +++ b/postfix/cleanup/cleanup_message.c @@ -234,7 +234,7 @@ static void cleanup_header(void) if (msg_verbose) msg_info("%s: '%s'", myname, vstring_str(cleanup_header_buf)); - if (cleanup_header_checks) { + if ((cleanup_flags & CLEANUP_FLAG_FILTER) && cleanup_header_checks) { char *header = vstring_str(cleanup_header_buf); const char *value; diff --git a/postfix/conf/sample-aliases.cf b/postfix/conf/sample-aliases.cf index b75c94261..80dd4a6e8 100644 --- a/postfix/conf/sample-aliases.cf +++ b/postfix/conf/sample-aliases.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control alias database lookups. # diff --git a/postfix/conf/sample-canonical.cf b/postfix/conf/sample-canonical.cf index 65c8fdd84..1e3b0a57c 100644 --- a/postfix/conf/sample-canonical.cf +++ b/postfix/conf/sample-canonical.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control canonical address map lookups. diff --git a/postfix/conf/sample-debug.cf b/postfix/conf/sample-debug.cf index 056e22fbf..c8a8e97a6 100644 --- a/postfix/conf/sample-debug.cf +++ b/postfix/conf/sample-debug.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control debugging features. diff --git a/postfix/conf/sample-ldap.cf b/postfix/conf/sample-ldap.cf index f68aee6a5..0acb8682e 100644 --- a/postfix/conf/sample-ldap.cf +++ b/postfix/conf/sample-ldap.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control LDAP lookups. Source code for LDAP # lookup is available separately from http://www.postfix.org/ diff --git a/postfix/conf/sample-local.cf b/postfix/conf/sample-local.cf index b07c1c9d6..2cb6ff6d4 100644 --- a/postfix/conf/sample-local.cf +++ b/postfix/conf/sample-local.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control local delivery. # diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index f7a990529..99d809c66 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings for miscellaneous Postfix # configuration parameters. diff --git a/postfix/conf/sample-rate.cf b/postfix/conf/sample-rate.cf index e95094dcd..28ccc19b2 100644 --- a/postfix/conf/sample-rate.cf +++ b/postfix/conf/sample-rate.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix parameters that # control delivery rates. diff --git a/postfix/conf/sample-relocated.cf b/postfix/conf/sample-relocated.cf index aeea31ad0..1c83ca538 100644 --- a/postfix/conf/sample-relocated.cf +++ b/postfix/conf/sample-relocated.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control relocated database lookups. diff --git a/postfix/conf/sample-resource.cf b/postfix/conf/sample-resource.cf index 846355cdc..aecc31200 100644 --- a/postfix/conf/sample-resource.cf +++ b/postfix/conf/sample-resource.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of general Postfix resource # control parameters. # diff --git a/postfix/conf/sample-rewrite.cf b/postfix/conf/sample-rewrite.cf index 16ab6da8e..5b5f3a584 100644 --- a/postfix/conf/sample-rewrite.cf +++ b/postfix/conf/sample-rewrite.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control address rewriting. diff --git a/postfix/conf/sample-smtp.cf b/postfix/conf/sample-smtp.cf index 882f7394d..084c0ad6d 100644 --- a/postfix/conf/sample-smtp.cf +++ b/postfix/conf/sample-smtp.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control the SMTP client program. diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index 1e2fd83a9..521e9c45a 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration parameters # that control the SMTP server program. diff --git a/postfix/conf/sample-transport.cf b/postfix/conf/sample-transport.cf index 0600dc30c..8ecd2b56b 100644 --- a/postfix/conf/sample-transport.cf +++ b/postfix/conf/sample-transport.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control the optional transport table lookups. diff --git a/postfix/conf/sample-virtual.cf b/postfix/conf/sample-virtual.cf index bfea4df49..3bebaab00 100644 --- a/postfix/conf/sample-virtual.cf +++ b/postfix/conf/sample-virtual.cf @@ -1,3 +1,6 @@ +# DO NOT EDIT THIS FILE. EDIT THE MAIN.CF FILE INSTEAD. THE STUFF +# HERE JUST SERVES AS AN EXAMPLE. +# # This file contains example settings of Postfix configuration # parameters that control virtual database lookups. diff --git a/postfix/dns/.indent.pro b/postfix/dns/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/dns/.indent.pro +++ b/postfix/dns/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/dns/dns_lookup.c b/postfix/dns/dns_lookup.c index 865e6c640..90344cd52 100644 --- a/postfix/dns/dns_lookup.c +++ b/postfix/dns/dns_lookup.c @@ -163,7 +163,10 @@ 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)); @@ -189,7 +192,6 @@ 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); diff --git a/postfix/error/.indent.pro b/postfix/error/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/error/.indent.pro +++ b/postfix/error/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/fsstone/.indent.pro b/postfix/fsstone/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/fsstone/.indent.pro +++ b/postfix/fsstone/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/global/.indent.pro b/postfix/global/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/global/.indent.pro +++ b/postfix/global/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/global/bounce.h b/postfix/global/bounce.h index d7cf2f1d9..c1316b26c 100644 --- a/postfix/global/bounce.h +++ b/postfix/global/bounce.h @@ -39,6 +39,7 @@ extern int bounce_flush(int, const char *, const char *, const char *); #define BOUNCE_FLAG_NONE 0 /* no flags up */ #define BOUNCE_FLAG_CLEAN (1<<0) /* remove log on error */ #define BOUNCE_FLAG_COPY (1<<1) /* postmaster notice */ +#define BOUNCE_FLAG_VERP (1<<2) /* personalized bounce */ /* * Backwards compatibility. diff --git a/postfix/global/mail_copy.c b/postfix/global/mail_copy.c index 4116270d4..e91bf8bf5 100644 --- a/postfix/global/mail_copy.c +++ b/postfix/global/mail_copy.c @@ -33,7 +33,9 @@ /* The binary OR of zero or more of the following: /* .RS /* .IP MAIL_COPY_QUOTE -/* prepend a `>' character to lines beginning with `From '. +/* Prepend a `>' character to lines beginning with `From '. +/* .IP MAIL_COPY_DOT +/* Prepend a `.' character to lines beginning with `.'. /* .IP MAIL_COPY_TOFILE /* On systems that support this, use fsync() to flush the /* data to stable storage, and truncate the destination @@ -166,6 +168,8 @@ int mail_copy(const char *sender, const char *delivered, bp = vstring_str(buf); if ((flags & MAIL_COPY_QUOTE) && *bp == 'F' && !strncmp(bp, "From ", 5)) VSTREAM_PUTC('>', dst); + if ((flags & MAIL_COPY_DOT) && *bp == '.') + VSTREAM_PUTC('.', dst); if (VSTRING_LEN(buf) && VSTREAM_FWRITE_BUF(dst, buf) != VSTRING_LEN(buf)) break; if (type == REC_TYPE_NORM && VSTREAM_PUTC('\n', dst) == VSTREAM_EOF) diff --git a/postfix/global/mail_copy.h b/postfix/global/mail_copy.h index ffa9682f0..a121b90e1 100644 --- a/postfix/global/mail_copy.h +++ b/postfix/global/mail_copy.h @@ -28,7 +28,10 @@ extern int mail_copy(const char *, const char *, VSTREAM *, VSTREAM *, #define MAIL_COPY_FROM (1<<2) /* prepend From_ */ #define MAIL_COPY_DELIVERED (1<<3) /* prepend Delivered-To: */ #define MAIL_COPY_RETURN_PATH (1<<4) /* prepend Return-Path: */ -#define MAIL_COPY_MBOX (~0) /* all turned on */ +#define MAIL_COPY_DOT (1<<5) /* escape dots - needed for bsmtp */ +#define MAIL_COPY_MBOX (MAIL_COPY_FROM | MAIL_COPY_QUOTE | \ + MAIL_COPY_TOFILE | MAIL_COPY_DELIVERED | \ + MAIL_COPY_RETURN_PATH) #define MAIL_COPY_NONE 0 /* all turned off */ /* LICENSE diff --git a/postfix/global/mail_params.h b/postfix/global/mail_params.h index 1bdc983be..6561a2d36 100644 --- a/postfix/global/mail_params.h +++ b/postfix/global/mail_params.h @@ -207,6 +207,13 @@ extern char *var_db_type; #define DEF_ALWAYS_BCC "" extern char *var_always_bcc; + /* + * Standards violation: permit RFC 822-style addresses in SMTP commands. + */ +#define VAR_ALLOW_RFC822_ENV "allow_rfc822_envelopes" +#define DEF_ALLOW_RFC822_ENV 1 +extern bool var_allow_rfc822_envelopes; + /* * trivial rewrite/resolve service: mapping tables. */ @@ -833,6 +840,13 @@ extern bool var_soft_bounce; #define DEF_OWNREQ_SPECIAL 1 extern bool var_ownreq_special; + /* + * Allow/disallow recipient addresses starting with `-'. + */ +#define VAR_ALLOW_MIN_USER "allow_min_user" +#define DEF_ALLOW_MIN_USER 0 +extern bool var_allow_min_user; + extern void mail_params_init(void); /* LICENSE diff --git a/postfix/global/mail_version.h b/postfix/global/mail_version.h index fff99cabf..287086ab2 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-19990912" +#define DEF_MAIL_VERSION "Snapshot-19991110" extern char *var_mail_version; /* LICENSE diff --git a/postfix/global/rewrite_clnt.c b/postfix/global/rewrite_clnt.c index f301304e1..0b03fb64f 100644 --- a/postfix/global/rewrite_clnt.c +++ b/postfix/global/rewrite_clnt.c @@ -71,8 +71,8 @@ */ CLNT_STREAM *rewrite_clnt_stream = 0; -VSTRING *last_addr; -VSTRING *last_result; +static VSTRING *last_addr; +static VSTRING *last_result; /* rewrite_clnt - rewrite address to (transport, next hop, recipient) */ diff --git a/postfix/html/faq.html b/postfix/html/faq.html index 087b577df..57096651d 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -56,8 +56,12 @@
  • Mail fails with timeout or lost connection +

    +

  • Undefined symbols: ___dn_expand, ___res_init etc. +
  • Undefined symbols: dbm_pagfno, dbm_dirfno etc. +
  • Using DB libraries on Solaris etc. @@ -1047,6 +1051,31 @@ Fix: use the right include files. For example:
    +

    Undefined symbols: dbm_pagfno, dbm_dirfno etc.

    + +Question: When I build Postfix I get the following errors: + +

    + +

    +    Undefined                       first referenced
    +     symbol                             in file
    +       dbm_pagfno                          ../lib/libutil.a(dict_dbm.o)
    +       dbm_dirfno                          ../lib/libutil.a(dict_dbm.o)
    +
    + +

    + +Answer: instead of using /usr/include/ndbm.h, you're building +Postfix with some incompatible third-party ndbm.h include file, +typically something in /usr/local/include. + +

    + +Fix: get rid of the third-party ndbm.h include file. + +


    +

    Using DB libraries on Solaris etc.

    The old dbm UNIX database has severe limitations when you @@ -1092,8 +1121,8 @@ include directory and of the object library.

    -One problem: older DB versions install a file /usr/include/ndbm.h -that is incompatible with the one in /usr/include. Be sure +One problem: older DB versions install a file /usr/local/include/ndbm.h +that is incompatible with /usr/include/ndbm.h. Be sure to get rid of the bogus file, or the linker will fail to find dbm_dirfno. diff --git a/postfix/html/index.html b/postfix/html/index.html index 9282ad42d..6482cfbde 100644 --- a/postfix/html/index.html +++ b/postfix/html/index.html @@ -28,10 +28,10 @@ First of all, thank you for your interest in the Postfix project.

    -What is Postfix? It is Wietse Venema's attempt to provide an -alternative to the widely-used Sendmail program. Sendmail is -responsible for an estimated 70% of all e-mail delivered on the +What is Postfix? It is Wietse +Venema's attempt to provide an alternative to the widely-used +Sendmail program. Sendmail +is responsible for an estimated 70% of all e-mail delivered on the Internet. With an estimated 100 million users, that's billions of messages daily. A stunning number. diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html index 2e9f14f62..eb63c2a48 100644 --- a/postfix/html/pipe.8.html +++ b/postfix/html/pipe.8.html @@ -30,7 +30,7 @@ PIPE(8) PIPE(8) file at the end of a service definition. The syntax is as follows: - flags=FR> (optional) + flags=FR.> (optional) Optional message processing flags. By default, a message is copied unchanged. @@ -43,7 +43,10 @@ PIPE(8) PIPE(8) R Prepend a Return-Path: message header with the envelope sender address. - > Prepend > to lines starting with "From ". + . Prepend . to lines starting with ".". This + is needed by, for example, BSMTP software. + + > Prepend > to lines starting with "From ". This is expected by, for example, UUCP soft- ware. @@ -51,15 +54,12 @@ PIPE(8) PIPE(8) user=username:groupname The external command is executed with the rights of - the specified username. The software refuses to - execute commands with root privileges, or with the - privileges of the mail system owner. If groupname - is specified, the corresponding group ID is used + the specified username. The software refuses to + execute commands with root privileges, or with the + privileges of the mail system owner. If groupname + is specified, the corresponding group ID is used instead of the group ID of of username. - argv=command... (required) - The command to be executed. This must be specified - 1 @@ -71,31 +71,33 @@ PIPE(8) PIPE(8) PIPE(8) PIPE(8) + argv=command... (required) + The command to be executed. This must be specified as the last command attribute. The command is exe- cuted directly, i.e. without interpretation of - shell meta characters by a shell command inter- + shell meta characters by a shell command inter- preter. In the command argument vector, the following macros are recognized and replaced with correspond- - ing information from the Postfix queue manager + ing information from the Postfix queue manager delivery request: ${extension} - This macro expands to the extension part of - a recipient address. For example, with an + This macro expands to the extension part of + a recipient address. For example, with an address user+foo@domain the extension is - foo. A command-line argument that contains - ${extension} expands into as many command- + foo. A command-line argument that contains + ${extension} expands into as many command- line arguments as there are recipients. ${mailbox} - This macro expands to the complete local - part of a recipient address. For example, - with an address user+foo@domain the mailbox - is user+foo. A command-line argument that - contains ${mailbox} expands into as many - command-line arguments as there are recipi- + This macro expands to the complete local + part of a recipient address. For example, + with an address user+foo@domain the mailbox + is user+foo. A command-line argument that + contains ${mailbox} expands into as many + command-line arguments as there are recipi- ents. ${nexthop} @@ -103,28 +105,26 @@ PIPE(8) PIPE(8) ${recipient} This macro expands to the complete recipient - address. A command-line argument that con- + address. A command-line argument that con- tains ${recipient} expands into as many com- mand-line arguments as there are recipients. ${sender} - This macro expands to the envelope sender + This macro expands to the envelope sender address. ${user} This macro expands to the username part of a - recipient address. For example, with an + recipient address. For example, with an address user+foo@domain the username part is user. A command-line argument that contains - ${user} expands into as many command-line + ${user} expands into as many command-line arguments as there are recipients. - In addition to the form ${name}, the forms $name and - $(name) are also recognized. Specify $$ where a single $ + In addition to the form ${name}, the forms $name and + $(name) are also recognized. Specify $$ where a single $ is wanted. -DIAGNOSTICS - Command exit status codes are expected to follow the @@ -137,60 +137,60 @@ PIPE(8) PIPE(8) PIPE(8) PIPE(8) - conventions defined in <sysexits.h>. +DIAGNOSTICS + Command exit status codes are expected to follow the con- + ventions defined in <sysexits.h>. - Problems and transactions are logged to syslogd(8). Cor- - rupted message files are marked so that the queue manager + Problems and transactions are logged to syslogd(8). Cor- + rupted message files are marked so that the queue manager can move them to the corrupt queue for further inspection. SECURITY - This program needs a dual personality 1) to access the - private Postfix queue and IPC mechanisms, and 2) to exe- + This program needs a dual personality 1) to access the + private Postfix queue and IPC mechanisms, and 2) to exe- cute external commands as the specified user. It is there- fore security sensitive. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax - details and for default values. Use the postfix reload + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax + details and for default values. Use the postfix reload command after a configuration change. Miscellaneous mail_owner - The process privileges used while not running an + The process privileges used while not running an external command. Resource controls - In the text below, transport is the first field in a mas- + In the text below, transport is the first field in a mas- ter.cf entry. transport_destination_concurrency_limit Limit the number of parallel deliveries to the same - destination, for delivery via the named transport. - The default limit is taken from the default_desti- - nation_concurrency_limit parameter. The limit is + destination, for delivery via the named transport. + The default limit is taken from the default_desti- + nation_concurrency_limit parameter. The limit is enforced by the Postfix queue manager. transport_destination_recipient_limit - Limit the number of recipients per message deliv- - ery, for delivery via the named transport. The - default limit is taken from the default_destina- - tion_recipient_limit parameter. The limit is + Limit the number of recipients per message deliv- + ery, for delivery via the named transport. The + default limit is taken from the default_destina- + tion_recipient_limit parameter. The limit is enforced by the Postfix queue manager. transport_time_limit - Limit the time for delivery to external command, - for delivery via the named transport. The default - limit is taken from the command_time_limit parame- - ter. The limit is enforced by the Postfix queue + Limit the time for delivery to external command, + for delivery via the named transport. The default + limit is taken from the command_time_limit parame- + ter. The limit is enforced by the Postfix queue manager. SEE ALSO bounce(8) non-delivery status reports master(8) process manager qmgr(8) queue manager - syslogd(8) system logging - @@ -203,8 +203,10 @@ PIPE(8) PIPE(8) PIPE(8) PIPE(8) + syslogd(8) system logging + LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) @@ -255,8 +257,6 @@ PIPE(8) PIPE(8) - - diff --git a/postfix/html/postalias.1.html b/postfix/html/postalias.1.html index 051f475e8..4e25fad1f 100644 --- a/postfix/html/postalias.1.html +++ b/postfix/html/postalias.1.html @@ -9,15 +9,15 @@ POSTALIAS(1) POSTALIAS(1) postalias - Postfix alias database maintenance SYNOPSIS - postalias [-c config_dir] [-i] [-v] [-w] + postalias [-ivw] [-c config_dir] [-q key] [file_type:]file_name ... DESCRIPTION - The postalias command creates a new Postfix alias - database, or updates an existing one. The input and output - file formats are expected to be compatible with Sendmail - version 8, and are expected to be suitable for the use as - NIS alias maps. + The postalias command creates or queries one or more Post- + fix alias databases, or updates an existing one. The input + and output file formats are expected to be compatible with + Sendmail version 8, and are expected to be suitable for + the use as NIS alias maps. While a database update is in progress, signal delivery is postponed, and an exclusive, advisory, lock is placed on @@ -35,8 +35,13 @@ POSTALIAS(1) POSTALIAS(1) default, postalias creates a new database from the entries in file_name. + -q key Search the specified maps for key and print the + first value found on the standard output stream. + The exit status is non-zero if the requested infor- + mation was not found. + -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. -w Do not warn about duplicate entries; silently @@ -47,19 +52,14 @@ POSTALIAS(1) POSTALIAS(1) file_type The type of database to be produced. - btree The output is a btree file, named - file_name.db. This is available only on - systems with support for db databases. - - dbm The output consists of two files, named - file_name.pag and file_name.dir. This is - available only on systems with support for - dbm databases. - - hash The output is a hashed file, named + btree The output is a btree file, named file_name.db. This is available only on systems with support for db databases. + dbm The output consists of two files, named + file_name.pag and file_name.dir. This is + available only on systems with support for + 1 @@ -71,17 +71,23 @@ POSTALIAS(1) POSTALIAS(1) POSTALIAS(1) POSTALIAS(1) - When no file_type is specified, the software uses - the database type specified via the database_type - configuration parameter. The default value for + dbm databases. + + hash The output is a hashed file, named + file_name.db. This is available only on + systems with support for db databases. + + When no file_type is specified, the software uses + the database type specified via the database_type + configuration parameter. The default value for this parameter depends on the host environment. file_name - The name of the alias database source file when + The name of the alias database source file when rebuilding a database. DIAGNOSTICS - Problems are logged to the standard error stream. No out- + Problems are logged to the standard error stream. No out- put means no problems were detected. Duplicate entries are skipped and are flagged with a warning. @@ -93,12 +99,12 @@ POSTALIAS(1) POSTALIAS(1) Enable verbose logging for debugging purposes. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax details and for default values. database_type - Default alias database type. On many UNIX systems, + Default alias database type. On many UNIX systems, the default type is either dbm or hash. STANDARDS @@ -109,7 +115,7 @@ POSTALIAS(1) POSTALIAS(1) sendmail(1) mail posting and compatibility interface. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) @@ -122,12 +128,6 @@ POSTALIAS(1) POSTALIAS(1) - - - - - - 2 diff --git a/postfix/html/postmap.1.html b/postfix/html/postmap.1.html index 34f88ded0..263a52fbd 100644 --- a/postfix/html/postmap.1.html +++ b/postfix/html/postmap.1.html @@ -9,13 +9,13 @@ POSTMAP(1) POSTMAP(1) postmap - Postfix lookup table management SYNOPSIS - postmap [-c config_dir] [-i] [-v] [-w] - [file_type:]file_name + postmap [-ivw] [-c config_dir] [-q key] + [file_type:]file_name ... DESCRIPTION - The postmap command creates a new Postfix lookup table, or - updates an existing one. The input and output formats are - expected to be compatible with: + The postmap command creates or queries one or more Postfix + lookup tables, or updates an existing one. The input and + output file formats are expected to be compatible with: makemap file_type file_name < file_name @@ -54,11 +54,11 @@ POSTMAP(1) POSTMAP(1) default, postmap creates a new database from the entries in file_name. - -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly - verbose. + -q key Search the specified maps for key and print the + first value found on the standard output stream. + The exit status is non-zero if the requested infor- + mation was not found. - B-w Do not warn about duplicate entries; silently @@ -71,6 +71,11 @@ POSTMAP(1) POSTMAP(1) POSTMAP(1) POSTMAP(1) + -v Enable verbose logging for debugging purposes. Mul- + tiple -v options make the software increasingly + verbose. + + -w Do not warn about duplicate entries; silently ignore them. Arguments: @@ -78,25 +83,25 @@ POSTMAP(1) POSTMAP(1) file_type The type of database to be produced. - btree The output file is a btree file, named - file_name.db. This is available only on + btree The output file is a btree file, named + file_name.db. This is available only on systems with support for db databases. - dbm The output consists of two files, named - file_name.pag and file_name.dir. This is - available only on systems with support for + dbm The output consists of two files, named + file_name.pag and file_name.dir. This is + available only on systems with support for dbm databases. - hash The output file is a hashed file, named - file_name.db. This is available only on + hash The output file is a hashed file, named + file_name.db. This is available only on systems with support for db databases. - When no file_type is specified, the software uses - the database type specified via the database_type + When no file_type is specified, the software uses + the database type specified via the database_type configuration parameter. file_name - The name of the lookup table source file when + The name of the lookup table source file when rebuilding a database. DIAGNOSTICS @@ -113,19 +118,14 @@ POSTMAP(1) POSTMAP(1) CONFIGURATION PARAMETERS database_type - Default output database type. On many UNIX sys- - tems, the default database type is either hash or + Default output database type. On many UNIX sys- + tems, the default database type is either hash or dbm. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. -AUTHOR(S) - Wietse Venema - IBM T.J. Watson Research - P.O. Box 704 - 2 @@ -137,6 +137,10 @@ POSTMAP(1) POSTMAP(1) POSTMAP(1) POSTMAP(1) +AUTHOR(S) + Wietse Venema + IBM T.J. Watson Research + P.O. Box 704 Yorktown Heights, NY 10598, USA @@ -185,10 +189,6 @@ POSTMAP(1) POSTMAP(1) - - - - diff --git a/postfix/html/sendmail.1.html b/postfix/html/sendmail.1.html index 77c41d3c6..f3d9963ee 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -100,6 +100,9 @@ SENDMAIL(1) SENDMAIL(1) Log mailer traffic. Use the debug_peer_list and debug_peer_level configuration parameters instead. + -U (ignored) + Initial user submission. + -bd Go into daemon mode. This mode of operation is implemented by executing the postfix start command. @@ -121,9 +124,6 @@ SENDMAIL(1) SENDMAIL(1) address where delivery problems are sent to, unless the message contains an Errors-To: message header. - -h hop_count (ignored) - Hop count limit. Use the hopcount_limit configura- - tion parameter instead. @@ -137,6 +137,10 @@ SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) + -h hop_count (ignored) + Hop count limit. Use the hopcount_limit configura- + tion parameter instead. + -i (ignored) Lines beginning with "." get special treatment only with -bs. @@ -187,10 +191,6 @@ SENDMAIL(1) SENDMAIL(1) SECURITY By design, this program is not set-user (or group) id. - However, it must handle data from untrusted users or - untrusted machines. Thus, the usual precautions need to - be taken against malicious inputs. - @@ -203,6 +203,10 @@ SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) + However, it must handle data from untrusted users or + untrusted machines. Thus, the usual precautions need to + be taken against malicious inputs. + DIAGNOSTICS Problems are logged to syslogd(8) and to the standard error stream. @@ -252,11 +256,7 @@ SENDMAIL(1) SENDMAIL(1) debug_peer_list List of domain or network patterns. When a remote - host matches a pattern, increase the verbose log- - ging level by the amount specified in the - debug_peer_level parameter. - - + host matches a pattern, increase the verbose @@ -269,6 +269,9 @@ SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) SENDMAIL(1) + logging level by the amount specified in the + debug_peer_level parameter. + fork_attempts Number of attempts to fork() a process before giv- ing up. @@ -320,13 +323,76 @@ SENDMAIL(1) SENDMAIL(1) Wietse Venema IBM T.J. Watson Research P.O. Box 704 + + + + 5 + + + + + +SENDMAIL(1) SENDMAIL(1) + + Yorktown Heights, NY 10598, USA - 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 6 diff --git a/postfix/local/.indent.pro b/postfix/local/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/local/.indent.pro +++ b/postfix/local/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/local/local.h b/postfix/local/local.h index 0332cebc0..b24376f71 100644 --- a/postfix/local/local.h +++ b/postfix/local/local.h @@ -125,12 +125,14 @@ typedef struct LOCAL_STATE { #define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp #define MSG_LOG_STATE(m, p) \ - msg_info("%s[%d]: local %s recip %s exten %s deliver %s", m, \ + msg_info("%s[%d]: local %s recip %s exten %s deliver %s exp_from %s", \ + m, \ p.level, \ p.msg_attr.local ? p.msg_attr.local : "" , \ p.msg_attr.recipient ? p.msg_attr.recipient : "", \ p.msg_attr.extension ? p.msg_attr.extension : "", \ - p.msg_attr.delivered ? p.msg_attr.delivered : "") + p.msg_attr.delivered ? p.msg_attr.delivered : "", \ + p.msg_attr.exp_from ? p.msg_attr.exp_from : "") /* * "inner" nodes of the delivery graph. diff --git a/postfix/man/man1/postalias.1 b/postfix/man/man1/postalias.1 index 63c092ea0..5315b5d22 100644 --- a/postfix/man/man1/postalias.1 +++ b/postfix/man/man1/postalias.1 @@ -9,15 +9,15 @@ Postfix alias database maintenance .na .nf .fi -\fBpostalias\fR [\fB-c \fIconfig_dir\fR] [\fB-i\fR] [\fB-v\fR] -[\fB-w\fR] [\fIfile_type\fR:]\fIfile_name\fR ... +\fBpostalias\fR [\fB-ivw\fR] [\fB-c \fIconfig_dir\fR] [\fB-q \fIkey\fR] +[\fIfile_type\fR:]\fIfile_name\fR ... .SH DESCRIPTION .ad .fi -The \fBpostalias\fR command creates a new Postfix alias database, -or updates an existing one. The input and output file formats -are expected to be compatible with Sendmail version 8, and are -expected to be suitable for the use as NIS alias maps. +The \fBpostalias\fR command creates or queries one or more Postfix +alias databases, or updates an existing one. The input and output +file formats are expected to be compatible with Sendmail version 8, +and are expected to be suitable for the use as NIS alias maps. While a database update is in progress, signal delivery is postponed, and an exclusive, advisory, lock is placed on the @@ -31,6 +31,10 @@ Read the \fBmain.cf\fR configuration file in the named directory. Incremental mode. Read entries from standard input and do not truncate an existing database. By default, \fBpostalias\fR creates a new database from the entries in \fBfile_name\fR. +.IP "\fB-q \fIkey\fR" +Search the specified maps for \fIkey\fR and print the first value +found on the standard output stream. The exit status is non-zero +if the requested information was not found. .IP \fB-v\fR Enable verbose logging for debugging purposes. Multiple \fB-v\fR options make the software increasingly verbose. diff --git a/postfix/man/man1/postmap.1 b/postfix/man/man1/postmap.1 index 45f95d7f0..f23c330d1 100644 --- a/postfix/man/man1/postmap.1 +++ b/postfix/man/man1/postmap.1 @@ -9,14 +9,14 @@ Postfix lookup table management .na .nf .fi -\fBpostmap\fR [\fB-c \fIconfig_dir\fR] [\fB-i\fR] [\fB-v\fR] -[\fB-w\fR] [\fIfile_type\fR:]\fIfile_name\fR +\fBpostmap\fR [\fB-ivw\fR] [\fB-c \fIconfig_dir\fR] [\fB-q \fIkey\fR] +[\fIfile_type\fR:]\fIfile_name\fR ... .SH DESCRIPTION .ad .fi -The \fBpostmap\fR command creates a new Postfix lookup table, -or updates an existing one. The input and output formats are -expected to be compatible with: +The \fBpostmap\fR command creates or queries one or more Postfix +lookup tables, or updates an existing one. The input and output +file formats are expected to be compatible with: .ti +4 \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR @@ -50,10 +50,14 @@ Read the \fBmain.cf\fR configuration file in the named directory. Incremental mode. Read entries from standard input and do not truncate an existing database. By default, \fBpostmap\fR creates a new database from the entries in \fBfile_name\fR. +.IP "\fB-q \fIkey\fR" +Search the specified maps for \fIkey\fR and print the first value +found on the standard output stream. The exit status is non-zero +if the requested information was not found. .IP \fB-v\fR Enable verbose logging for debugging purposes. Multiple \fB-v\fR options make the software increasingly verbose. -.IP \f\B-w\fR +.IP \fB-w\fR Do not warn about duplicate entries; silently ignore them. .PP Arguments: diff --git a/postfix/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index 9c57eb740..3a3becd2d 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -76,6 +76,8 @@ configuration parameter instead. .IP "\fB-X \fIlog_file\fR (ignored)" Log mailer traffic. Use the \fBdebug_peer_list\fR and \fBdebug_peer_level\fR configuration parameters instead. +.IP "\fB-U\fR (ignored)" +Initial user submission. .IP \fB-bd\fR Go into daemon mode. This mode of operation is implemented by executing the \fBpostfix start\fR command. diff --git a/postfix/man/man8/pipe.8 b/postfix/man/man8/pipe.8 index f602d935b..18215d1d6 100644 --- a/postfix/man/man8/pipe.8 +++ b/postfix/man/man8/pipe.8 @@ -30,7 +30,7 @@ to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate. .fi The external command attributes are given in the \fBmaster.cf\fR file at the end of a service definition. The syntax is as follows: -.IP "\fBflags=FR>\fR (optional)" +.IP "\fBflags=FR.>\fR (optional)" Optional message processing flags. By default, a message is copied unchanged. .RS @@ -42,6 +42,9 @@ flag also causes an empty line to be appended to the message. .IP \fBR\fR Prepend a \fBReturn-Path:\fR message header with the envelope sender address. +.IP \fB.\fR +Prepend \fB.\fR to lines starting with "\fB.\fR". This is needed +by, for example, \fBBSMTP\fR software. .IP \fB>\fR Prepend \fB>\fR to lines starting with "\fBFrom \fR". This is expected by, for example, \fBUUCP\fR software. diff --git a/postfix/master/.indent.pro b/postfix/master/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/master/.indent.pro +++ b/postfix/master/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/master/Makefile.in b/postfix/master/Makefile.in index 9f9c4285a..a499576de 100644 --- a/postfix/master/Makefile.in +++ b/postfix/master/Makefile.in @@ -90,6 +90,7 @@ master.o: ../include/iostuff.h master.o: ../include/vstream.h master.o: ../include/stringops.h master.o: ../include/myflock.h +master.o: ../include/watchdog.h master.o: ../include/mail_params.h master.o: ../include/debug_process.h master.o: ../include/mail_task.h @@ -202,6 +203,7 @@ multi_server.o: ../include/stringops.h multi_server.o: ../include/sane_accept.h multi_server.o: ../include/myflock.h multi_server.o: ../include/safe_open.h +multi_server.o: ../include/watchdog.h multi_server.o: ../include/mail_task.h multi_server.o: ../include/debug_process.h multi_server.o: ../include/mail_params.h @@ -227,6 +229,7 @@ single_server.o: ../include/sane_accept.h single_server.o: ../include/myflock.h single_server.o: ../include/safe_open.h single_server.o: ../include/listen.h +single_server.o: ../include/watchdog.h single_server.o: ../include/mail_params.h single_server.o: ../include/mail_task.h single_server.o: ../include/debug_process.h @@ -252,6 +255,7 @@ trigger_server.o: ../include/sane_accept.h trigger_server.o: ../include/myflock.h trigger_server.o: ../include/safe_open.h trigger_server.o: ../include/listen.h +trigger_server.o: ../include/watchdog.h trigger_server.o: ../include/mail_params.h trigger_server.o: ../include/mail_task.h trigger_server.o: ../include/debug_process.h diff --git a/postfix/master/master.c b/postfix/master/master.c index c245fc460..ecc70bf18 100644 --- a/postfix/master/master.c +++ b/postfix/master/master.c @@ -142,6 +142,7 @@ #include #include #include +#include /* Global library. */ @@ -155,19 +156,6 @@ #include "master.h" -/* master_watchdog - something got stuck */ - -static NORETURN master_watchdog(int unused_sig) -{ - - /* - * This runs as a signal handler. We should not do anything that could - * involve memory managent, but exiting without explanation would be - * worse. - */ - msg_fatal("watchdog timer"); -} - int main(int argc, char **argv) { static VSTREAM *lock_fp; @@ -180,6 +168,7 @@ int main(int argc, char **argv) int test_lock = 0; int fd_limit = open_limit(0); VSTRING *why; + WATCHDOG *watchdog; /* * Initialize. @@ -332,13 +321,13 @@ int main(int argc, char **argv) * multiple things at the same time, it really is all a single thread, so * that there are no concurrency conflicts within the master process. */ - signal(SIGALRM, master_watchdog); + watchdog = watchdog_create(1000, (WATCHDOG_FN) 0, (char *) 0); for (;;) { #ifdef HAS_VOLATILE_LOCKS if (myflock(vstream_fileno(lock_fp), MYFLOCK_EXCLUSIVE) < 0) msg_fatal("refresh exclusive lock: %m"); #endif - alarm(1000); /* same as trigger servers */ + watchdog_start(watchdog); /* same as trigger servers */ event_loop(-1); if (master_gotsighup) { msg_info("reload configuration"); diff --git a/postfix/master/multi_server.c b/postfix/master/multi_server.c index 68a6fcda9..2af61dc9d 100644 --- a/postfix/master/multi_server.c +++ b/postfix/master/multi_server.c @@ -144,6 +144,7 @@ #include #include #include +#include /* Global library. */ @@ -185,19 +186,6 @@ static NORETURN multi_server_exit(void) exit(0); } -/* multi_server_watchdog - something got stuck */ - -static NORETURN multi_server_watchdog(int unused_sig) -{ - - /* - * This runs as a signal handler. We should not do anything that could - * involve memory managent, but exiting without explanation would be - * worse. - */ - msg_fatal("watchdog timer"); -} - /* multi_server_abort - terminate after abnormal master exit */ static void multi_server_abort(int unused_event, char *unused_context) @@ -274,12 +262,6 @@ static void multi_server_accept_local(int unused_event, char *context) int time_left = -1; int fd; - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, multi_server_watchdog); - alarm(var_daemon_timeout); - /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -314,12 +296,6 @@ static void multi_server_accept_inet(int unused_event, char *context) int time_left = -1; int fd; - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, multi_server_watchdog); - alarm(var_daemon_timeout); - /* * Be prepared for accept() to fail because some other process already * got the connection (the number of processes competing for clients is @@ -369,6 +345,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) char *lock_path; VSTRING *why; int alone = 0; + WATCHDOG *watchdog; /* * Process environment options as early as we can. @@ -585,11 +562,19 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...) } event_enable_read(MASTER_STATUS_FD, multi_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0); + + /* + * The event loop, at last. + */ while (var_use_limit == 0 || use_count < var_use_limit || client_count > 0) { + if (multi_server_lock != 0) { + watchdog_stop(watchdog); + if (myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0) + msg_fatal("select lock: %m"); + } + watchdog_start(watchdog); delay = loop ? loop(multi_server_name, multi_server_argv) : -1; - if (multi_server_lock != 0 - && myflock(vstream_fileno(multi_server_lock), MYFLOCK_EXCLUSIVE) < 0) - msg_fatal("select lock: %m"); event_loop(delay); } multi_server_exit(); diff --git a/postfix/master/single_server.c b/postfix/master/single_server.c index 744afc420..15e500e41 100644 --- a/postfix/master/single_server.c +++ b/postfix/master/single_server.c @@ -135,6 +135,7 @@ #include #include #include +#include /* Global library. */ @@ -175,19 +176,6 @@ static NORETURN single_server_exit(void) exit(0); } -/* single_server_watchdog - something got stuck */ - -static NORETURN single_server_watchdog(int unused_sig) -{ - - /* - * This runs as a signal handler. We should not do anything that could - * involve memory managent, but exiting without explanation would be - * worse. - */ - msg_fatal("watchdog timer"); -} - /* single_server_abort - terminate after abnormal master exit */ static void single_server_abort(int unused_event, char *unused_context) @@ -245,12 +233,6 @@ static void single_server_accept_local(int unused_event, char *context) int time_left = -1; int fd; - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, single_server_watchdog); - alarm(var_daemon_timeout); - /* * Be prepared for accept() to fail because some other process already * got the connection. We use select() + accept(), instead of simply @@ -284,12 +266,6 @@ static void single_server_accept_inet(int unused_event, char *context) int time_left = -1; int fd; - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, single_server_watchdog); - alarm(var_daemon_timeout); - /* * Be prepared for accept() to fail because some other process already * got the connection. We use select() + accept(), instead of simply @@ -338,6 +314,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) char *lock_path; VSTRING *why; int alone = 0; + WATCHDOG *watchdog; /* * Process environment options as early as we can. @@ -554,11 +531,19 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...) } event_enable_read(MASTER_STATUS_FD, single_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + watchdog = watchdog_create(var_daemon_timeout, (WATCHDOG_FN) 0, (char *) 0); + + /* + * The event loop, at last. + */ while (var_use_limit == 0 || use_count < var_use_limit) { + if (single_server_lock != 0) { + watchdog_stop(watchdog); + if (myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0) + msg_fatal("select lock: %m"); + } + watchdog_start(watchdog); delay = loop ? loop(single_server_name, single_server_argv) : -1; - if (single_server_lock != 0 - && myflock(vstream_fileno(single_server_lock), MYFLOCK_EXCLUSIVE) < 0) - msg_fatal("select lock: %m"); event_loop(delay); } single_server_exit(); diff --git a/postfix/master/trigger_server.c b/postfix/master/trigger_server.c index 791c101ea..7c777319c 100644 --- a/postfix/master/trigger_server.c +++ b/postfix/master/trigger_server.c @@ -143,6 +143,7 @@ #include #include #include +#include /* Global library. */ @@ -182,19 +183,6 @@ static NORETURN trigger_server_exit(void) exit(0); } -/* trigger_server_watchdog - something got stuck */ - -static NORETURN trigger_server_watchdog(int unused_sig) -{ - - /* - * This runs as a signal handler. We should not do anything that could - * involve memory managent, but exiting without explanation would be - * worse. - */ - msg_fatal("watchdog timer"); -} - /* trigger_server_abort - terminate after abnormal master exit */ static void trigger_server_abort(int unused_event, char *unused_context) @@ -249,12 +237,6 @@ static void trigger_server_accept_fifo(int unused_event, char *context) if (msg_verbose) msg_info("%s: trigger arrived", myname); - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, trigger_server_watchdog); - alarm(1000); - /* * Read whatever the other side wrote into the FIFO. The FIFO read end is * non-blocking so we won't get stuck when multiple processes wake up. @@ -277,12 +259,6 @@ static void trigger_server_accept_local(int unused_event, char *context) if (msg_verbose) msg_info("%s: trigger arrived", myname); - /* - * Some buggy systems cause Postfix to lock up. - */ - signal(SIGALRM, trigger_server_watchdog); - alarm(1000); - /* * Read a message from a socket. Be prepared for accept() to fail because * some other process already got the connection. The socket is @@ -339,6 +315,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. char *lock_path; VSTRING *why; int alone = 0; + WATCHDOG *watchdog; /* * Process environment options as early as we can. @@ -566,11 +543,19 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,.. } event_enable_read(MASTER_STATUS_FD, trigger_server_abort, (char *) 0); close_on_exec(MASTER_STATUS_FD, CLOSE_ON_EXEC); + watchdog = watchdog_create(1000, (WATCHDOG_FN) 0, (char *) 0); + + /* + * The event loop, at last. + */ while (var_use_limit == 0 || use_count < var_use_limit) { + if (trigger_server_lock != 0) { + watchdog_stop(watchdog); + if (myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0) + msg_fatal("select lock: %m"); + } + watchdog_start(watchdog); delay = loop ? loop(trigger_server_name, trigger_server_argv) : -1; - if (trigger_server_lock != 0 - && myflock(vstream_fileno(trigger_server_lock), MYFLOCK_EXCLUSIVE) < 0) - msg_fatal("select lock: %m"); event_loop(delay); } trigger_server_exit(); diff --git a/postfix/pickup/.indent.pro b/postfix/pickup/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/pickup/.indent.pro +++ b/postfix/pickup/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/pickup/pickup.c b/postfix/pickup/pickup.c index cbcd8ec54..1c76dd2cb 100644 --- a/postfix/pickup/pickup.c +++ b/postfix/pickup/pickup.c @@ -140,7 +140,7 @@ static int file_read_error(PICKUP_INFO *info, int type) static int cleanup_service_error(PICKUP_INFO *info, int status) { msg_warn("%s: %s", info->path, cleanup_strerror(status)); - return (status == CLEANUP_STAT_BAD ? + return ((status & CLEANUP_STAT_BAD) ? REMOVE_MESSAGE_FILE : KEEP_MESSAGE_FILE); } @@ -345,10 +345,12 @@ static int pickup_file(PICKUP_INFO *info) * easier to implement the many possible error exits without forgetting * to close files, or to release memory. */ +#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER) + buf = vstring_alloc(100); cleanup = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP); if (mail_scan(cleanup, "%s", buf) != 1 - || mail_print(cleanup, "%d", CLEANUP_FLAG_BOUNCE) != 0) { + || mail_print(cleanup, "%d", PICKUP_CLEANUP_FLAGS) != 0) { status = KEEP_MESSAGE_FILE; } else { info->id = mystrdup(vstring_str(buf)); diff --git a/postfix/pipe/.indent.pro b/postfix/pipe/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/pipe/.indent.pro +++ b/postfix/pipe/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/pipe/pipe.c b/postfix/pipe/pipe.c index ed9f8af8a..134d76ea3 100644 --- a/postfix/pipe/pipe.c +++ b/postfix/pipe/pipe.c @@ -22,7 +22,7 @@ /* .fi /* The external command attributes are given in the \fBmaster.cf\fR /* file at the end of a service definition. The syntax is as follows: -/* .IP "\fBflags=FR>\fR (optional)" +/* .IP "\fBflags=FR.>\fR (optional)" /* Optional message processing flags. By default, a message is /* copied unchanged. /* .RS @@ -34,6 +34,9 @@ /* .IP \fBR\fR /* Prepend a \fBReturn-Path:\fR message header with the envelope sender /* address. +/* .IP \fB.\fR +/* Prepend \fB.\fR to lines starting with "\fB.\fR". This is needed +/* by, for example, \fBBSMTP\fR software. /* .IP \fB>\fR /* Prepend \fB>\fR to lines starting with "\fBFrom \fR". This is expected /* by, for example, \fBUUCP\fR software. @@ -430,6 +433,9 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv) case 'F': attr->flags |= MAIL_COPY_FROM; break; + case '.': + attr->flags |= MAIL_COPY_DOT; + break; case '>': attr->flags |= MAIL_COPY_QUOTE; break; diff --git a/postfix/postalias/.indent.pro b/postfix/postalias/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postalias/.indent.pro +++ b/postfix/postalias/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postalias/postalias.c b/postfix/postalias/postalias.c index 96de6a610..93b8d5fe9 100644 --- a/postfix/postalias/postalias.c +++ b/postfix/postalias/postalias.c @@ -5,13 +5,13 @@ /* Postfix alias database maintenance /* SYNOPSIS /* .fi -/* \fBpostalias\fR [\fB-c \fIconfig_dir\fR] [\fB-i\fR] [\fB-v\fR] -/* [\fB-w\fR] [\fIfile_type\fR:]\fIfile_name\fR ... +/* \fBpostalias\fR [\fB-ivw\fR] [\fB-c \fIconfig_dir\fR] [\fB-q \fIkey\fR] +/* [\fIfile_type\fR:]\fIfile_name\fR ... /* DESCRIPTION -/* The \fBpostalias\fR command creates a new Postfix alias database, -/* or updates an existing one. The input and output file formats -/* are expected to be compatible with Sendmail version 8, and are -/* expected to be suitable for the use as NIS alias maps. +/* The \fBpostalias\fR command creates or queries one or more Postfix +/* alias databases, or updates an existing one. The input and output +/* file formats are expected to be compatible with Sendmail version 8, +/* and are expected to be suitable for the use as NIS alias maps. /* /* While a database update is in progress, signal delivery is /* postponed, and an exclusive, advisory, lock is placed on the @@ -25,6 +25,10 @@ /* Incremental mode. Read entries from standard input and do not /* truncate an existing database. By default, \fBpostalias\fR creates /* a new database from the entries in \fBfile_name\fR. +/* .IP "\fB-q \fIkey\fR" +/* Search the specified maps for \fIkey\fR and print the first value +/* found on the standard output stream. The exit status is non-zero +/* if the requested information was not found. /* .IP \fB-v\fR /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR /* options make the software increasingly verbose. @@ -272,11 +276,28 @@ static void postalias(char *map_type, char *path_name, vstream_fclose(source_fp); } +/* postalias_query - query a map and print the result to stdout */ + +static int postalias_query(const char *map_type, const char *map_name, + const char *key) +{ + DICT *dict; + const char *value; + + dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + if ((value = dict_get(dict, key)) != 0) { + vstream_printf("%s\n", value); + vstream_fflush(VSTREAM_OUT); + } + dict_close(dict); + return (value != 0); +} + /* usage - explain */ static NORETURN usage(char *myname) { - msg_fatal("usage: %s [-c config_dir] [-i] [-v] [-w] [output_type:]file...", + msg_fatal("usage: %s [-ivw] [-c config_dir] [-q key] [map_type:]file...", myname); } @@ -289,6 +310,8 @@ int main(int argc, char **argv) struct stat st; int open_flags = O_RDWR | O_CREAT | O_TRUNC; int dict_flags = DICT_FLAG_DUP_WARN; + char *query = 0; + int found; /* * Be consistent with file permissions. @@ -323,7 +346,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) { + while ((ch = GETOPT(argc, argv, "c:iq:vw")) > 0) { switch (ch) { default: usage(argv[0]); @@ -335,6 +358,9 @@ int main(int argc, char **argv) case 'i': open_flags &= ~O_TRUNC; break; + case 'q': + query = optarg; + break; case 'v': msg_verbose++; break; @@ -350,15 +376,31 @@ int main(int argc, char **argv) * Use the map type specified by the user, or fall back to a default * database type. */ - if (optind + 1 > argc) - usage(argv[0]); - while (optind < argc) { - if ((path_name = split_at(argv[optind], ':')) != 0) { - postalias(argv[optind], path_name, open_flags, dict_flags); - } else { - postalias(var_db_type, argv[optind], open_flags, dict_flags); + if (query == 0) { /* create/update map(s) */ + if (optind + 1 > argc) + usage(argv[0]); + while (optind < argc) { + if ((path_name = split_at(argv[optind], ':')) != 0) { + postalias(argv[optind], path_name, open_flags, dict_flags); + } else { + postalias(var_db_type, argv[optind], open_flags, dict_flags); + } + optind++; + } + exit(0); + } else { /* query map(s) */ + if (optind + 1 > argc) + usage(argv[0]); + while (optind < argc) { + if ((path_name = split_at(argv[optind], ':')) != 0) { + found = postalias_query(argv[optind], path_name, query); + } else { + found = postalias_query(var_db_type, argv[optind], query); + } + if (found) + exit(0); + optind++; } - optind++; + exit(1); } - exit(0); } diff --git a/postfix/postcat/.indent.pro b/postfix/postcat/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postcat/.indent.pro +++ b/postfix/postcat/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postconf/.indent.pro b/postfix/postconf/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postconf/.indent.pro +++ b/postfix/postconf/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postdrop/.indent.pro b/postfix/postdrop/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postdrop/.indent.pro +++ b/postfix/postdrop/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postfix/.indent.pro b/postfix/postfix/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postfix/.indent.pro +++ b/postfix/postfix/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postkick/.indent.pro b/postfix/postkick/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postkick/.indent.pro +++ b/postfix/postkick/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postlock/.indent.pro b/postfix/postlock/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postlock/.indent.pro +++ b/postfix/postlock/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postlock/Makefile.in b/postfix/postlock/Makefile.in index 6117bc9e7..c2ee45d3c 100644 --- a/postfix/postlock/Makefile.in +++ b/postfix/postlock/Makefile.in @@ -65,3 +65,4 @@ postlock.o: ../include/mail_params.h postlock.o: ../include/dot_lockfile.h postlock.o: ../include/deliver_flock.h postlock.o: ../include/mail_conf.h +postlock.o: ../include/sys_exits.h diff --git a/postfix/postlog/.indent.pro b/postfix/postlog/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postlog/.indent.pro +++ b/postfix/postlog/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postmap/.indent.pro b/postfix/postmap/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postmap/.indent.pro +++ b/postfix/postmap/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/postmap/postmap.c b/postfix/postmap/postmap.c index f44c232ab..af6a2b7c6 100644 --- a/postfix/postmap/postmap.c +++ b/postfix/postmap/postmap.c @@ -5,12 +5,12 @@ /* Postfix lookup table management /* SYNOPSIS /* .fi -/* \fBpostmap\fR [\fB-c \fIconfig_dir\fR] [\fB-i\fR] [\fB-v\fR] -/* [\fB-w\fR] [\fIfile_type\fR:]\fIfile_name\fR +/* \fBpostmap\fR [\fB-ivw\fR] [\fB-c \fIconfig_dir\fR] [\fB-q \fIkey\fR] +/* [\fIfile_type\fR:]\fIfile_name\fR ... /* DESCRIPTION -/* The \fBpostmap\fR command creates a new Postfix lookup table, -/* or updates an existing one. The input and output formats are -/* expected to be compatible with: +/* The \fBpostmap\fR command creates or queries one or more Postfix +/* lookup tables, or updates an existing one. The input and output +/* file formats are expected to be compatible with: /* /* .ti +4 /* \fBmakemap \fIfile_type\fR \fIfile_name\fR < \fIfile_name\fR @@ -44,10 +44,14 @@ /* Incremental mode. Read entries from standard input and do not /* truncate an existing database. By default, \fBpostmap\fR creates /* a new database from the entries in \fBfile_name\fR. +/* .IP "\fB-q \fIkey\fR" +/* Search the specified maps for \fIkey\fR and print the first value +/* found on the standard output stream. The exit status is non-zero +/* if the requested information was not found. /* .IP \fB-v\fR /* Enable verbose logging for debugging purposes. Multiple \fB-v\fR /* options make the software increasingly verbose. -/* .IP \f\B-w\fR +/* .IP \fB-w\fR /* Do not warn about duplicate entries; silently ignore them. /* .PP /* Arguments: @@ -226,11 +230,28 @@ static void postmap(char *map_type, char *path_name, vstream_fclose(source_fp); } +/* postmap_query - query a map and print the result to stdout */ + +static int postmap_query(const char *map_type, const char *map_name, + const char *key) +{ + DICT *dict; + const char *value; + + dict = dict_open3(map_type, map_name, O_RDONLY, DICT_FLAG_LOCK); + if ((value = dict_get(dict, key)) != 0) { + vstream_printf("%s\n", value); + vstream_fflush(VSTREAM_OUT); + } + dict_close(dict); + return (value != 0); +} + /* usage - explain */ static NORETURN usage(char *myname) { - msg_fatal("usage: %s [-c config_dir] [-i] [-v] [-w] [output_type:]file...", + msg_fatal("usage: %s [-ivw] [-c config_dir] [-q key] [map_type:]file...", myname); } @@ -243,6 +264,8 @@ int main(int argc, char **argv) struct stat st; int open_flags = O_RDWR | O_CREAT | O_TRUNC; int dict_flags = DICT_FLAG_DUP_WARN; + char *query = 0; + int found; /* * Be consistent with file permissions. @@ -277,7 +300,7 @@ int main(int argc, char **argv) /* * Parse JCL. */ - while ((ch = GETOPT(argc, argv, "c:ivw")) > 0) { + while ((ch = GETOPT(argc, argv, "c:iq:vw")) > 0) { switch (ch) { default: usage(argv[0]); @@ -289,6 +312,9 @@ int main(int argc, char **argv) case 'i': open_flags &= ~O_TRUNC; break; + case 'q': + query = optarg; + break; case 'v': msg_verbose++; break; @@ -304,15 +330,31 @@ int main(int argc, char **argv) * Use the map type specified by the user, or fall back to a default * database type. */ - if (optind + 1 > argc) - usage(argv[0]); - while (optind < argc) { - if ((path_name = split_at(argv[optind], ':')) != 0) { - postmap(argv[optind], path_name, open_flags, dict_flags); - } else { - postmap(var_db_type, argv[optind], open_flags, dict_flags); + if (query == 0) { /* create/update map(s) */ + if (optind + 1 > argc) + usage(argv[0]); + while (optind < argc) { + if ((path_name = split_at(argv[optind], ':')) != 0) { + postmap(argv[optind], path_name, open_flags, dict_flags); + } else { + postmap(var_db_type, argv[optind], open_flags, dict_flags); + } + optind++; + } + exit(0); + } else { /* query map(s) */ + if (optind + 1 > argc) + usage(argv[0]); + while (optind < argc) { + if ((path_name = split_at(argv[optind], ':')) != 0) { + found = postmap_query(argv[optind], path_name, query); + } else { + found = postmap_query(var_db_type, argv[optind], query); + } + if (found) + exit(0); + optind++; } - optind++; + exit(1); } - exit(0); } diff --git a/postfix/postsuper/.indent.pro b/postfix/postsuper/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/postsuper/.indent.pro +++ b/postfix/postsuper/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/qmgr/.indent.pro b/postfix/qmgr/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/qmgr/.indent.pro +++ b/postfix/qmgr/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/qmgr/qmgr.c b/postfix/qmgr/qmgr.c index 7bfd25ff5..2259cd1f7 100644 --- a/postfix/qmgr/qmgr.c +++ b/postfix/qmgr/qmgr.c @@ -266,6 +266,7 @@ int var_dest_rcpt_limit; char *var_relocated_maps; char *var_virtual_maps; char *var_defer_xports; +bool var_allow_min_user; static QMGR_SCAN *qmgr_incoming; static QMGR_SCAN *qmgr_deferred; @@ -460,6 +461,10 @@ int main(int argc, char **argv) VAR_DEST_RCPT_LIMIT, DEF_DEST_RCPT_LIMIT, &var_dest_rcpt_limit, 0, 0, 0, }; + static CONFIG_BOOL_TABLE bool_table[] = { + VAR_ALLOW_MIN_USER, DEF_ALLOW_MIN_USER, &var_allow_min_user, + 0, + }; /* * Use the trigger service skeleton, because no-one else should be diff --git a/postfix/qmgr/qmgr_active.c b/postfix/qmgr/qmgr_active.c index 257dbc4aa..5fe689029 100644 --- a/postfix/qmgr/qmgr_active.c +++ b/postfix/qmgr/qmgr_active.c @@ -220,14 +220,6 @@ void qmgr_active_feed(QMGR_SCAN *scan_info, const char *queue_id) qmgr_active_defer(MAIL_QUEUE_ACTIVE, queue_id, var_min_backoff_time); } else { - /* - * Reset the defer log. Leave the bounce log alone; if it is still - * around, something did not send it previously. - */ - if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT) - msg_fatal("%s: %s: remove %s %s: %m", myname, - queue_id, MAIL_QUEUE_DEFER, queue_id); - /* * Special case if all recipients were already delivered. Send any * bounces and clean up. diff --git a/postfix/qmgr/qmgr_message.c b/postfix/qmgr/qmgr_message.c index e47527a62..a5bfaff2c 100644 --- a/postfix/qmgr/qmgr_message.c +++ b/postfix/qmgr/qmgr_message.c @@ -489,6 +489,24 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) } } + /* + * Bounce recipient addresses that start with `-'. External commands + * may misinterpret such addresses as command-line options. + * + * In theory I could say people should always carefully set up their + * master.cf pipe mailer entries with `--' before the first + * non-option argument, but mistakes will happen regardless. + * + * Therefore the protection is put in place here, in the queue manager, + * where it cannot be bypassed. + */ + if (var_allow_min_user == 0 && recipient->address[0] == '-') { + qmgr_bounce_recipient(message, recipient, + "invalid recipient syntax: \"%s\"", + recipient->address); + continue; + } + /* * Queues are identified by the transport name and by the next-hop * hostname. When the destination is local (no next hop), derive the @@ -682,6 +700,17 @@ QMGR_MESSAGE *qmgr_message_alloc(const char *queue_name, const char *queue_id, qmgr_message_free(message); return (0); } else { + + /* + * Reset the defer log. This code should not be here, but we must + * reset the defer log *after* acquiring the exclusive lock on the + * queue file and *before* resolving new recipients. Since all those + * operations are encapsulated so nicely by this routine, the defer + * log reset has to be done here as well. + */ + if (mail_queue_remove(MAIL_QUEUE_DEFER, queue_id) && errno != ENOENT) + msg_fatal("%s: %s: remove %s %s: %m", myname, + queue_id, MAIL_QUEUE_DEFER, queue_id); qmgr_message_sort(message); qmgr_message_resolve(message); qmgr_message_sort(message); diff --git a/postfix/sendmail/.indent.pro b/postfix/sendmail/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/sendmail/.indent.pro +++ b/postfix/sendmail/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/sendmail/sendmail.c b/postfix/sendmail/sendmail.c index dc100b778..13d13e450 100644 --- a/postfix/sendmail/sendmail.c +++ b/postfix/sendmail/sendmail.c @@ -70,6 +70,8 @@ /* .IP "\fB-X \fIlog_file\fR (ignored)" /* Log mailer traffic. Use the \fBdebug_peer_list\fR and /* \fBdebug_peer_level\fR configuration parameters instead. +/* .IP "\fB-U\fR (ignored)" +/* Initial user submission. /* .IP \fB-bd\fR /* Go into daemon mode. This mode of operation is implemented by /* executing the \fBpostfix start\fR command. @@ -660,7 +662,7 @@ int main(int argc, char **argv) optind++; continue; } - if ((c = GETOPT(argc, argv, "B:C:F:IN:R:X:b:ce:f:h:imno:p:r:q:tvx")) <= 0) + if ((c = GETOPT(argc, argv, "B:C:F:IN:R:UX:b:ce:f:h:imno:p:r:q:tvx")) <= 0) break; switch (c) { default: diff --git a/postfix/showq/.indent.pro b/postfix/showq/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/showq/.indent.pro +++ b/postfix/showq/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/smtp/.indent.pro b/postfix/smtp/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/smtp/.indent.pro +++ b/postfix/smtp/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/smtpd/.indent.pro b/postfix/smtpd/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/smtpd/.indent.pro +++ b/postfix/smtpd/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/smtpd/Makefile.in b/postfix/smtpd/Makefile.in index a39502921..2fa6b677a 100644 --- a/postfix/smtpd/Makefile.in +++ b/postfix/smtpd/Makefile.in @@ -56,9 +56,6 @@ clean: tidy: clean -smtpd_token_test: smtpd_token_test.c smtpd_token.o $(LIBS) - $(CC) $(CFLAGS) -DTEST -o $@ $@.c smtpd_token.o $(LIBS) $(SYSLIBS) - depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -67,7 +64,7 @@ depend: $(MAKES) done) | grep -v '[.][o][:][ ][/]' >$$$$ && mv $$$$ Makefile.in @make -f Makefile.in Makefile -tests: smtpd_check_test smtpd_check_test2 +tests: smtpd_check_test smtpd_check_test2 smtpd_token_test smtpd_check_test: smtpd_check smtpd_check.in smtpd_check.ref ../postmap/postmap smtpd_check_access @@ -81,6 +78,11 @@ 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_token_test: smtpd_token smtpd_token.in smtpd_token.ref + ./smtpd_token smtpd_token.tmp 2>&1 + diff smtpd_token.ref smtpd_token.tmp + rm -f smtpd_token.tmp + # do not edit below this line - it is generated by 'make depend' smtpd.o: smtpd.c smtpd.o: ../include/sys_defs.h @@ -111,6 +113,8 @@ smtpd.o: ../include/name_mask.h smtpd.o: ../include/mail_flush.h smtpd.o: ../include/mail_stream.h smtpd.o: ../include/mail_queue.h +smtpd.o: ../include/tok822.h +smtpd.o: ../include/resolve_clnt.h smtpd.o: ../include/mail_server.h smtpd.o: smtpd_token.h smtpd.o: smtpd.h @@ -154,6 +158,7 @@ smtpd_check.o: ../include/argv.h smtpd_check.o: ../include/mymalloc.h smtpd_check.o: ../include/dict.h smtpd_check.o: ../include/vstream.h +smtpd_check.o: ../include/htable.h smtpd_check.o: ../include/dns.h smtpd_check.o: ../include/namadr_list.h smtpd_check.o: ../include/domain_list.h @@ -164,6 +169,9 @@ smtpd_check.o: ../include/mail_error.h smtpd_check.o: ../include/name_mask.h smtpd_check.o: ../include/resolve_local.h smtpd_check.o: ../include/own_inet_addr.h +smtpd_check.o: ../include/mail_conf.h +smtpd_check.o: ../include/maps.h +smtpd_check.o: ../include/mail_addr_find.h smtpd_check.o: smtpd.h smtpd_check.o: ../include/mail_stream.h smtpd_check.o: smtpd_check.h diff --git a/postfix/smtpd/smtpd.c b/postfix/smtpd/smtpd.c index 5f2f5a0c3..32468aa8d 100644 --- a/postfix/smtpd/smtpd.c +++ b/postfix/smtpd/smtpd.c @@ -232,6 +232,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -392,7 +393,7 @@ static void mail_open_stream(SMTPD_STATE *state) state->dest = mail_stream_service(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP); if (state->dest == 0 - || mail_print(state->dest->stream, "%d", CLEANUP_FLAG_NONE) != 0) + || mail_print(state->dest->stream, "%d", CLEANUP_FLAG_FILTER) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP); } @@ -424,6 +425,50 @@ static void mail_open_stream(SMTPD_STATE *state) state->queue_id = mystrdup(state->dest->id); } +/* extract_addr - extract address from rubble */ + +static VSTRING *extract_addr(SMTPD_STATE *state, VSTRING *buf) +{ + char *myname = "extract_addr"; + TOK822 *tree; + TOK822 *tp; + int naddr; + int non_addr; + + /* + * Some mailers send RFC822-style address forms (with comments and such) + * in SMTP envelopes. We cannot blame users for this: the blame is with + * programmers violating the RFC, and with sendmail for being permissive. + * + * Extract the address from any surrounding junk. XXX Because of this, the + * SMTP command tokenizer must leave the address in externalized (quoted) + * form. + */ +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + + if (msg_verbose) + msg_info("%s: input: %s", myname, STR(buf)); + tree = tok822_parse(STR(buf)); + for (naddr = non_addr = 0, tp = tree; tp != 0; tp = tp->next) { + if (tp->type == TOK822_ADDR) { + if (++naddr == 1) + tok822_internalize(buf, tp->head, TOK822_STR_DEFL); + else if (naddr == 2) + msg_warn("Multiple addresses from %s in %s command: %s", + state->namaddr, state->where, STR(buf)); + } else if (tp->type != '<' && tp->type != '>') { + if (++non_addr == 1) + msg_warn("Non-RFC 821 syntax from %s in %s command: %s", + state->namaddr, state->where, STR(buf)); + } + } + tok822_free_tree(tree); + if (msg_verbose) + msg_info("%s: result: %s", myname, STR(buf)); + return (buf); +} + /* mail_cmd - process MAIL command */ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) @@ -447,14 +492,14 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 Error: nested MAIL command"); return (-1); } - if (argc < 4 - || strcasecmp(argv[1].strval, "from") != 0 - || strcmp(argv[2].strval, ":") != 0) { + if (argc < 3 + || strcasecmp(argv[1].strval, "from:") != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 Syntax: MAIL FROM:

    "); return (-1); } - for (narg = 4; narg < argc; narg++) { + argv[2].strval = STR(extract_addr(state, argv[2].vstrval)); + for (narg = 3; narg < argc; narg++) { arg = argv[narg].strval; if (strcasecmp(arg, "BODY=8BITMIME") == 0 || strcasecmp(arg, "BODY=7BIT") == 0) { @@ -471,7 +516,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) state->time = time((time_t *) 0); if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_delay_reject == 0 - && (err = smtpd_check_mail(state, argv[3].strval)) != 0) { + && (err = smtpd_check_mail(state, argv[2].strval)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } @@ -491,8 +536,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) */ rec_fprintf(state->cleanup, REC_TYPE_TIME, "%ld", (long) time((time_t *) 0)); - rec_fputs(state->cleanup, REC_TYPE_FROM, argv[3].strval); - state->sender = mystrdup(argv[3].strval); + rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval); + state->sender = mystrdup(argv[2].strval); smtpd_chat_reply(state, "250 Ok"); return (0); } @@ -545,20 +590,20 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "503 Error: need MAIL command"); return (-1); } - if (argc != 4 - || strcasecmp(argv[1].strval, "to") != 0 - || strcmp(argv[2].strval, ":") != 0) { + if (argc != 3 + || strcasecmp(argv[1].strval, "to:") != 0) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 Syntax: RCPT TO:
    "); return (-1); } + argv[2].strval = STR(extract_addr(state, argv[2].vstrval)); if (var_smtpd_rcpt_limit && state->rcpt_count >= var_smtpd_rcpt_limit) { state->error_mask |= MAIL_ERROR_POLICY; smtpd_chat_reply(state, "452 Error: too many recipients"); return (-1); } if (SMTPD_STAND_ALONE(state) == 0 - && (err = smtpd_check_rcpt(state, argv[3].strval)) != 0) { + && (err = smtpd_check_rcpt(state, argv[2].strval)) != 0) { smtpd_chat_reply(state, "%s", err); return (-1); } @@ -568,8 +613,8 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) */ state->rcpt_count++; if (state->recipient == 0) - state->recipient = mystrdup(argv[3].strval); - rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[3].strval); + state->recipient = mystrdup(argv[2].strval); + rec_fputs(state->cleanup, REC_TYPE_RCPT, argv[2].strval); smtpd_chat_reply(state, "250 Ok"); return (0); } @@ -596,10 +641,13 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) int first = 1; /* - * Sanity checks. + * Sanity checks. With ESMTP command pipelining the client can send DATA + * before all recipients are rejected, so don't report that as a protocol + * error. */ if (state->rcpt_count == 0) { - state->error_mask |= MAIL_ERROR_PROTOCOL; + if (state->cleanup == 0) + state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "503 Error: need RCPT command"); return (-1); } diff --git a/postfix/smtpd/smtpd_check.c b/postfix/smtpd/smtpd_check.c index 9ef699771..4cc27582e 100644 --- a/postfix/smtpd/smtpd_check.c +++ b/postfix/smtpd/smtpd_check.c @@ -1077,6 +1077,13 @@ static int check_table_result(SMTPD_STATE *state, char *table, "%d <%s>: %s rejected: Access denied", var_access_map_code, reply_name, reply_class)); + /* + * All-numeric result probably means OK - some out-of-band authentication + * mechanism uses this as time stamp. + */ + if (value[strcspn(value, "0123456789")] == 0) + return (SMTPD_CHECK_OK); + /* * 4xx or 5xx means NO as well. smtpd_check_reject() will validate the * response status code. diff --git a/postfix/smtpd/smtpd_token.c b/postfix/smtpd/smtpd_token.c index 846cfc403..7de161fa6 100644 --- a/postfix/smtpd/smtpd_token.c +++ b/postfix/smtpd/smtpd_token.c @@ -7,8 +7,10 @@ /* #include /* /* typedef struct { - int tokval; - char *strval; +/* .in +4 +/* char *strval; +/* /* other stuff... */ +/* .in -4 /* } SMTPD_TOKEN; /* /* int smtpd_token(str, argvp) @@ -20,8 +22,6 @@ /* via the function return value. /* /* Token types: -/* .IP SMTPD_TOK_ADDR -/* The token is of the form , not including the angle brackets. /* .IP SMTPD_TOK_OTHER /* The token is something else. /* .IP SMTPD_TOK_ERROR @@ -29,8 +29,9 @@ /* BUGS /* This tokenizer understands just enough to tokenize SMTPD commands. /* It understands backslash escapes, white space, quoted strings, -/* and addresses (including quoted text) enclosed by < and >. Any -/* other sequence of characters is lumped together as one token. +/* and addresses (including quoted text) enclosed by < and >. +/* The input is broken up into tokens by whitespace, except for +/* whitespace that is protected by quites etc. /* LICENSE /* .ad /* .fi @@ -47,6 +48,7 @@ #include #include #include +#include /* Utility library. */ @@ -57,45 +59,43 @@ #include "smtpd_token.h" - /* - * Macros to make complex code more readable. - */ -#define COLLECT(cp,vp,c,cond) { \ - while ((c = *cp) != 0) { \ - if (c == '\\') { \ - cp++; \ - if ((c = *cp) == 0) \ - break; \ - } else if (!(cond)) { \ - break; \ - } \ - cp++; \ - VSTRING_ADDCH(vp, c); \ - } \ - } - /* smtp_quoted - read until closing quote */ -static char *smtp_quoted(char *cp, SMTPD_TOKEN *arg, int last) +static char *smtp_quoted(char *cp, SMTPD_TOKEN *arg, int start, int last) { + static VSTRING *stack; int c; - while ((c = *cp) != 0) { + if (stack == 0) + stack = vstring_alloc(1); + VSTRING_RESET(stack); + VSTRING_ADDCH(stack, last); + + VSTRING_ADDCH(arg->vstrval, start); + for (;;) { + if ((c = *cp) == 0) + break; cp++; - if (c == '\\') { /* parse escape sequence */ - if ((c = *cp) == 0) - break; /* end of input, punt */ - cp++; - VSTRING_ADDCH(arg->vstrval, c); /* store escaped character */ - } else if (c == last) { - return (cp); /* closing quote */ - } else if (c == '"') { - cp = smtp_quoted(cp, arg, c); /* recurse */ + VSTRING_ADDCH(arg->vstrval, c); + if (c == vstring_end(stack)[-1]) { /* closing quote etc. */ + vstring_truncate(stack, VSTRING_LEN(stack) - 1); + if (VSTRING_LEN(stack) == 0) + break; } else { - VSTRING_ADDCH(arg->vstrval, c); /* store character */ + if (c == '\\') { /* parse escape sequence */ + if ((c = *cp) == 0) + break; + cp++; + VSTRING_ADDCH(arg->vstrval, c); + } else if (c == '"') { + VSTRING_ADDCH(stack, '"'); /* highest precedence */ + } else if (c == '(' && vstring_end(stack)[-1] != '"') { + VSTRING_ADDCH(stack, ')'); /* medium precedence */ + } else if (c == '<' && vstring_end(stack)[-1] == '>') { + VSTRING_ADDCH(stack, '>'); /* lowest precedence */ + } } } - arg->tokval = SMTPD_TOK_ERROR; /* missing end */ return (cp); } @@ -103,45 +103,43 @@ static char *smtp_quoted(char *cp, SMTPD_TOKEN *arg, int last) static char *smtp_next_token(char *cp, SMTPD_TOKEN *arg) { - char *special = "<[\">]:"; int c; VSTRING_RESET(arg->vstrval); - arg->tokval = SMTPD_TOK_OTHER; - for (;;) { - if ((c = *cp++) == 0) { - return (0); - } else if (ISSPACE(c)) { /* whitespace, skip */ - while (ISSPACE(*cp)) +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) +#define STREQ(x,y,l) ((x)[0] == (x)[0] && strncasecmp((x), (y), (l)) == 0) + + while ((c = *cp) != 0) { + cp++; + if (ISSPACE(c)) { /* whitespace, skip */ + while (*cp && ISSPACE(*cp)) cp++; - continue; + if (LEN(arg->vstrval) > 0) /* end of token */ + break; } else if (c == '<') { /* */ - arg->tokval = SMTPD_TOK_ADDR; - cp = smtp_quoted(cp, arg, '>'); - break; - } else if (c == '[') { /* [stuff], keep [] */ - VSTRING_ADDCH(arg->vstrval, c); - cp = smtp_quoted(cp, arg, ']'); - if (cp[-1] == ']') - VSTRING_ADDCH(arg->vstrval, ']'); - break; - } else if (c == '"') { /* string */ - cp = smtp_quoted(cp, arg, c); - break; - } else if (ISCNTRL(c) || strchr(special, c)) { + cp = smtp_quoted(cp, arg, c, '>'); + } else if (c == '[') { /* [stuff] */ + cp = smtp_quoted(cp, arg, c, ']'); + } else if (c == '"') { /* "stuff" */ + cp = smtp_quoted(cp, arg, c, c); + } else if (c == ':') { /* this is gross, but... */ VSTRING_ADDCH(arg->vstrval, c); - break; + if (STREQ(STR(arg->vstrval), "to:", LEN(arg->vstrval)) + || STREQ(STR(arg->vstrval), "from:", LEN(arg->vstrval))) + break; } else { /* other */ - if (c == '\\') + if (c == '\\') { if ((c = *cp) == 0) break; + cp++; + } VSTRING_ADDCH(arg->vstrval, c); - COLLECT(cp, arg->vstrval, c, - !ISSPACE(c) && !ISCNTRL(c) && !strchr(special, c)); - break; } } + if (LEN(arg->vstrval) == 0) /* no token found */ + return (0); VSTRING_TERMINATE(arg->vstrval); arg->strval = vstring_str(arg->vstrval); return (cp); @@ -168,7 +166,7 @@ int smtpd_token(char *cp, SMTPD_TOKEN **argvp) if (smtp_argv == 0) smtp_argv = (SMTPD_TOKEN *) mvect_alloc(&mvect, sizeof(*smtp_argv), 1, - smtpd_token_init, (MVECT_FN) 0); + smtpd_token_init, (MVECT_FN) 0); for (n = 0; /* void */ ; n++) { smtp_argv = (SMTPD_TOKEN *) mvect_realloc(&mvect, n + 1); if ((cp = smtp_next_token(cp, smtp_argv + n)) == 0) @@ -196,17 +194,18 @@ main(int unused_argc, char **unused_argv) int i; for (;;) { - vstream_printf("enter SMTPD command: "); + if (isatty(STDIN_FILENO)) + vstream_printf("enter SMTPD command: "); vstream_fflush(VSTREAM_OUT); if (vstring_fgets(vp, VSTREAM_IN) == 0) break; + if (*vstring_str(vp) == '#') + continue; + if (!isatty(STDIN_FILENO)) + vstream_fputs(vstring_str(vp), VSTREAM_OUT); tok_argc = smtpd_token(vstring_str(vp), &tok_argv); - for (i = 0; i < tok_argc; i++) { - vstream_printf("Token type: %s\n", - tok_argv[i].tokval == SMTPD_TOK_ADDR ? - "address" : "other"); + for (i = 0; i < tok_argc; i++) vstream_printf("Token value: %s\n", tok_argv[i].strval); - } } exit(0); } diff --git a/postfix/smtpd/smtpd_token.h b/postfix/smtpd/smtpd_token.h index 88489fa22..841ddb3ce 100644 --- a/postfix/smtpd/smtpd_token.h +++ b/postfix/smtpd/smtpd_token.h @@ -17,7 +17,6 @@ * External interface. */ typedef struct SMTPD_TOKEN { - int tokval; char *strval; VSTRING *vstrval; } SMTPD_TOKEN; diff --git a/postfix/smtpd/smtpd_token.in b/postfix/smtpd/smtpd_token.in new file mode 100644 index 000000000..3ef8f7596 --- /dev/null +++ b/postfix/smtpd/smtpd_token.in @@ -0,0 +1,9 @@ +mail from: +mail from:<"wietse venema"@porcupine.org> +mail from:wietse@porcupine.org +mail from: +mail from:<"wietse venema"@porcupine.org ("wietse ) venema")> +mail from:<"wietse venema" > +mail from:<"wietse venema"@porcupine.org ( ("wietse ) venema") )> +mail from:"wietse venema"@porcupine.org +mail from:wietse\ venema@porcupine.org diff --git a/postfix/smtpd/smtpd_token.ref b/postfix/smtpd/smtpd_token.ref new file mode 100644 index 000000000..5d962fbf6 --- /dev/null +++ b/postfix/smtpd/smtpd_token.ref @@ -0,0 +1,36 @@ +mail from: +Token value: mail +Token value: from: +Token value: +mail from:<"wietse venema"@porcupine.org> +Token value: mail +Token value: from: +Token value: <"wietse venema"@porcupine.org> +mail from:wietse@porcupine.org +Token value: mail +Token value: from: +Token value: wietse@porcupine.org +mail from: +Token value: mail +Token value: from: +Token value: +mail from:<"wietse venema"@porcupine.org ("wietse ) venema")> +Token value: mail +Token value: from: +Token value: <"wietse venema"@porcupine.org ("wietse ) venema")> +mail from:<"wietse venema" > +Token value: mail +Token value: from: +Token value: <"wietse venema" > +mail from:<"wietse venema"@porcupine.org ( ("wietse ) venema") )> +Token value: mail +Token value: from: +Token value: <"wietse venema"@porcupine.org ( ("wietse ) venema") )> +mail from:"wietse venema"@porcupine.org +Token value: mail +Token value: from: +Token value: "wietse venema"@porcupine.org +mail from:wietse\ venema@porcupine.org +Token value: mail +Token value: from: +Token value: wietse venema@porcupine.org diff --git a/postfix/smtpstone/.indent.pro b/postfix/smtpstone/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/smtpstone/.indent.pro +++ b/postfix/smtpstone/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/trivial-rewrite/.indent.pro b/postfix/trivial-rewrite/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/trivial-rewrite/.indent.pro +++ b/postfix/trivial-rewrite/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/util/.indent.pro b/postfix/util/.indent.pro index b65f4ec24..6819c7dca 100644 --- a/postfix/util/.indent.pro +++ b/postfix/util/.indent.pro @@ -87,7 +87,6 @@ -TSINGLE_SERVER -TSINK_COMMAND -TSINK_STATE --TSMTPD_REST_TABLE -TSMTPD_STATE -TSMTPD_TOKEN -TSMTP_ADDR @@ -106,4 +105,5 @@ -TVSTREAM_POPEN_ARGS -TVSTRING -TWAIT_STATUS_T +-TWATCHDOG -TWATCH_FD diff --git a/postfix/util/Makefile.in b/postfix/util/Makefile.in index 22a134351..e7656653b 100644 --- a/postfix/util/Makefile.in +++ b/postfix/util/Makefile.in @@ -20,7 +20,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \ vstream.c vstream_popen.c vstring.c vstring_vstream.c writable.c \ write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \ stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \ - clean_env.c + clean_env.c watchdog.c OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \ dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ @@ -42,7 +42,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ vstream.o vstream_popen.o vstring.o vstring_vstream.o writable.o \ write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \ stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \ - clean_env.o + clean_env.o watchdog.o HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \ dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \ @@ -56,7 +56,8 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ sigdelay.h split_at.h stat_as.h stringops.h sys_defs.h \ timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \ vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \ - dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h + dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \ + watchdog.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ @@ -71,7 +72,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ fifo_rdonly_bug fifo_rdwr_bug fifo_trigger fsspace fullname \ inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \ mystrtok peer_name sigdelay translit valid_hostname vstream_popen \ - vstring vstring_vstream doze select_bug stream_test mac_expand + vstring vstring_vstream doze select_bug stream_test mac_expand \ + watchdog LIB_DIR = ../lib INC_DIR = ../include @@ -240,6 +242,11 @@ mac_expand: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +watchdog: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + depend: $(MAKES) (sed '1,/^# do not edit/!d' Makefile.in; \ set -e; for i in [a-z][a-z0-9]*.c; do \ @@ -852,6 +859,11 @@ vstring_vstream.o: vstring.h vstring_vstream.o: vbuf.h vstring_vstream.o: vstream.h vstring_vstream.o: vstring_vstream.h +watchdog.o: watchdog.c +watchdog.o: sys_defs.h +watchdog.o: msg.h +watchdog.o: mymalloc.h +watchdog.o: watchdog.h writable.o: writable.c writable.o: sys_defs.h writable.o: msg.h diff --git a/postfix/util/dict_ldap.c b/postfix/util/dict_ldap.c index 069bcf723..8ebdeb096 100644 --- a/postfix/util/dict_ldap.c +++ b/postfix/util/dict_ldap.c @@ -399,7 +399,7 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags) /* get configured value of "ldapsource_timeout"; default to 10 */ vstring_sprintf(config_param, "%s_timeout", ldapsource); - dict_ldap->timeout = get_mail_conf_int(config_param, 10, 0, 0); + dict_ldap->timeout = get_mail_conf_int(vstring_str(config_param), 10, 0, 0); if (msg_verbose) msg_info("%s: %s is %d", myname, vstring_str(config_param), dict_ldap->timeout); diff --git a/postfix/util/dict_unix.c b/postfix/util/dict_unix.c index 89a9d7204..20d9a4540 100644 --- a/postfix/util/dict_unix.c +++ b/postfix/util/dict_unix.c @@ -19,6 +19,9 @@ /* .IP passwd.byname /* The table is the UNIX password database. The key is a login name. /* The result is a password file entry in passwd(5) format. +/* .IP group.byname +/* The table is the UNIX group database. The key is a group name. +/* The result is a group file entry in group(5) format. /* SEE ALSO /* dict(3) generic dictionary manager /* DIAGNOSTICS @@ -37,8 +40,10 @@ /* System library. */ #include "sys_defs.h" +#include #include #include +#include /* Utility library. */ @@ -76,6 +81,33 @@ static const char *dict_unix_getpwnam(DICT *unused_dict, const char *key) } } +/* dict_unix_getgrnam - find group table entry */ + +static const char *dict_unix_getgrnam(DICT *unused_dict, const char *key) +{ + struct group *grp; + static VSTRING *buf; + char **cpp; + + dict_errno = 0; + + if ((grp = getgrnam(key)) == 0) { + return (0); + } else { + if (buf == 0) + buf = vstring_alloc(10); + vstring_sprintf(buf, "%s:%s:%d:", + grp->gr_name, grp->gr_passwd, grp->gr_gid); + for (cpp = grp->gr_mem; *cpp; cpp++) { + vstring_strcat(buf, *cpp); + if (cpp[1]) + VSTRING_ADDCH(buf, ','); + } + VSTRING_TERMINATE(buf); + return (vstring_str(buf)); + } +} + /* dict_unix_update - add or update table entry */ static void dict_unix_update(DICT *dict, const char *unused_name, const char *unused_value) @@ -106,6 +138,7 @@ DICT *dict_unix_open(const char *map, int unused_flags, int dict_flags) }; static struct dict_unix_lookup dict_unix_lookup[] = { "passwd.byname", dict_unix_getpwnam, + "group.byname", dict_unix_getgrnam, 0, }; struct dict_unix_lookup *lp; diff --git a/postfix/util/inet_addr_local.c b/postfix/util/inet_addr_local.c index 3acc2b3b9..9a53d8d6f 100644 --- a/postfix/util/inet_addr_local.c +++ b/postfix/util/inet_addr_local.c @@ -72,12 +72,12 @@ int inet_addr_local(INET_ADDR_LIST *addr_list) { char *myname = "inet_addr_local"; struct ifconf ifc; - struct ifreq ifreq; struct ifreq *ifr; struct ifreq *the_end; int sock; VSTRING *buf = vstring_alloc(1024); int initial_count = addr_list->used; + struct in_addr addr; if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) msg_fatal("%s: socket: %m", myname); @@ -109,20 +109,18 @@ int inet_addr_local(INET_ADDR_LIST *addr_list) } /* - * Get the IP address of each active IP network interface. + * Get the address of each IP network interface. According to BIND we + * must include interfaces that are down because the machine may still + * receive packets for that address (yes, via some other interface). + * Having no way to verify this claim on every machine, I will give them + * the benefit of the doubt. */ the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); for (ifr = ifc.ifc_req; ifr < the_end;) { if (ifr->ifr_addr.sa_family == AF_INET) { /* IP interface */ - ifreq = *ifr; - if (ioctl(sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) - msg_fatal("%s: ioctl SIOCGIFFLAGS: %m", myname); - if (ifreq.ifr_flags & IFF_UP) { /* active interface */ - if (ioctl(sock, SIOCGIFADDR, (char *) &ifreq) < 0) - msg_fatal("%s: ioctl SIOCGIFADDR: %m", myname); - inet_addr_list_append(addr_list, - &(((struct sockaddr_in *) & ifreq.ifr_addr)->sin_addr)); - } + addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr; + if (addr.s_addr != INADDR_ANY) /* has IP address */ + inet_addr_list_append(addr_list, &addr); } ifr = NEXT_INTERFACE(ifr); } diff --git a/postfix/util/timed_wait.c b/postfix/util/timed_wait.c index 6e8293fb2..73f395fec 100644 --- a/postfix/util/timed_wait.c +++ b/postfix/util/timed_wait.c @@ -83,6 +83,7 @@ int timed_waitpid(pid_t pid, WAIT_STATUS_T *statusp, int options, char *myname = "timed_waitpid"; struct sigaction action; struct sigaction old_action; + int time_left; int wpid; /* @@ -100,7 +101,7 @@ int timed_waitpid(pid_t pid, WAIT_STATUS_T *statusp, int options, if (sigaction(SIGALRM, &action, &old_action) < 0) msg_fatal("%s: sigaction(SIGALRM): %m", myname); timed_wait_expired = 0; - alarm(time_limit); + time_left = alarm(time_limit); /* * Wait for only a limited amount of time. @@ -114,6 +115,8 @@ int timed_waitpid(pid_t pid, WAIT_STATUS_T *statusp, int options, alarm(0); if (sigaction(SIGALRM, &old_action, (struct sigaction *) 0) < 0) msg_fatal("%s: sigaction(SIGALRM): %m", myname); + if (time_left) + alarm(time_left); return (wpid); } diff --git a/postfix/util/watchdog.c b/postfix/util/watchdog.c new file mode 100644 index 000000000..db1e412fa --- /dev/null +++ b/postfix/util/watchdog.c @@ -0,0 +1,228 @@ +/*++ +/* NAME +/* watchdog 3 +/* SUMMARY +/* watchdog timer +/* SYNOPSIS +/* #include +/* +/* WATCHDOG *watchdog_create(timeout, action, context) +/* unsigned timeout; +/* void (*action)(WATCHDOG *watchdog, char *context); +/* char *context; +/* +/* void watchdog_start(watchdog) +/* WATCHDOG *watchdog; +/* +/* void watchdog_stop(watchdog) +/* WATCHDOG *watchdog; +/* +/* void watchdog_destroy(watchdog) +/* WATCHDOG *watchdog; +/* DESCRIPTION +/* This module implements watchdog timers that are based on ugly +/* UNIX alarm timers. The module is designed to survive systems +/* with clocks that jump occasionally. +/* +/* Watchdog timers can be stacked. Only one watchdog timer can be +/* active at a time. Only the last created watchdog timer can be +/* manipulated. Watchdog timers must be destroyed in reverse order +/* of creation. +/* +/* watchdog_create() suspends the current watchdog timer, if any, +/* and instantiates a new watchdog timer. +/* +/* watchdog_start() starts or restarts the watchdog timer. +/* +/* watchdog_stop() stops the watchdog timer. +/* +/* watchdog_destroy() stops the watchdog timer, and resumes the +/* watchdog timer instance that was suspended by watchdog_create(). +/* +/* Arguments: +/* .IP timeout +/* The watchdog time limit. When the watchdog timer runs, the +/* process must invoke watchdog_start(), watchdog_stop() or +/* watchdog_destroy() before the time limit is reached. +/* .IP action +/* A null pointer, or pointer to function that is called when the +/* watchdog alarm goes off. The default action is to terminate +/* the process with a fatal error. +/* .IP context +/* Application context that is passed to the action routine. +/* .IP watchdog +/* Must be a pointer to the most recently created watchdog instance. +/* This argument is checked upon each call. +/* BUGS +/* UNIX alarm timers are not stackable, so there can be at most one +/* watchdog instance active at any given time. +/* SEE ALSO +/* msg(3) diagnostics interface +/* DIAGNOSTICS +/* Fatal errors: memory allocation problem, system call failure. +/* Panics: interface violations. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include +#include +#include + +/* Application-specific. */ + + /* + * Rather than having one timer that goes off when it is too late, we break + * up the time limit into smaller intervals so that we can deal with clocks + * that jump occasionally. + */ +#define WATCHDOG_STEPS 3 + + /* + * UNIX alarms are not stackable, but we can save and restore state, so that + * watchdogs can at least be nested, sort of. + */ +struct WATCHDOG { + unsigned timeout; /* our time resolution */ + WATCHDOG_FN action; /* application routine */ + char *context; /* application context */ + int trip_run; /* number of successive timeouts */ + WATCHDOG *saved_watchdog; /* saved state */ + struct sigaction saved_action; /* saved state */ + unsigned saved_time; /* saved state */ +}; + + /* + * However, only one watchdog instance can be current, and the caller has to + * restore state before a prior watchdog instance can be manipulated. + */ +static WATCHDOG *watchdog_curr; + +/* watchdog_event - handle timeout event */ + +static void watchdog_event(int unused_sig) +{ + char *myname = "watchdog_event"; + WATCHDOG *wp; + + /* + * This routine runs as a signal handler. We should not do anything that + * could involve memory allocation/deallocation, but exiting without + * proper explanation would be unacceptable. + */ + if ((wp = watchdog_curr) == 0) + msg_panic("%s: no instance", myname); + if (msg_verbose) + msg_info("%s: %p %d", myname, (char *) wp, wp->trip_run); + if (++(wp->trip_run) < WATCHDOG_STEPS) { + alarm(wp->timeout); + } else { + if (wp->action) + wp->action(wp, wp->context); + else + msg_fatal("watchdog timeout"); + } +} + +/* watchdog_create - create watchdog instance */ + +WATCHDOG *watchdog_create(unsigned timeout, WATCHDOG_FN action, char *context) +{ + char *myname = "watchdog_create"; + struct sigaction sig_action; + WATCHDOG *wp; + + wp = (WATCHDOG *) mymalloc(sizeof(*wp)); + if ((wp->timeout = timeout / WATCHDOG_STEPS) == 0) + msg_panic("%s: timeout %d is too small", myname, timeout); + wp->action = action; + wp->context = context; + wp->saved_watchdog = watchdog_curr; + wp->saved_time = alarm(0); + sigemptyset(&sig_action.sa_mask); + sig_action.sa_flags = SA_RESTART; + sig_action.sa_handler = watchdog_event; + if (sigaction(SIGALRM, &sig_action, &wp->saved_action) < 0) + msg_fatal("%s: sigaction(SIGALRM): %m", myname); + if (msg_verbose) + msg_info("%s: %p %d", myname, (char *) wp, timeout); + return (watchdog_curr = wp); +} + +/* watchdog_destroy - destroy watchdog instance, restore state */ + +void watchdog_destroy(WATCHDOG *wp) +{ + char *myname = "watchdog_destroy"; + + watchdog_stop(wp); + watchdog_curr = wp->saved_watchdog; + if (sigaction(SIGALRM, &wp->saved_action, (struct sigaction *) 0) < 0) + msg_fatal("%s: sigaction(SIGALRM): %m", myname); + if (wp->saved_time) + alarm(wp->saved_time); + myfree((char *) wp); + if (msg_verbose) + msg_info("%s: %p", myname, (char *) wp); +} + +/* watchdog_start - enable watchdog timer */ + +void watchdog_start(WATCHDOG *wp) +{ + char *myname = "watchdog_start"; + + if (wp != watchdog_curr) + msg_panic("%s: wrong watchdog instance", myname); + wp->trip_run = 0; + alarm(wp->timeout); + if (msg_verbose) + msg_info("%s: %p", myname, (char *) wp); +} + +/* watchdog_stop - disable watchdog timer */ + +void watchdog_stop(WATCHDOG *wp) +{ + char *myname = "watchdog_stop"; + + if (wp != watchdog_curr) + msg_panic("%s: wrong watchdog instance", myname); + alarm(0); + if (msg_verbose) + msg_info("%s: %p", myname, (char *) wp); +} + +#ifdef TEST + +#include + +main(int unused_argc, char **unused_argv) +{ + WATCHDOG *wp; + + msg_verbose = 1; + + wp = watchdog_create(10, (WATCHDOG_FN) 0, (char *) 0); + do { + watchdog_start(wp); + } while (VSTREAM_GETCHAR() != VSTREAM_EOF); + watchdog_destroy(wp); +} + +#endif diff --git a/postfix/util/watchdog.h b/postfix/util/watchdog.h new file mode 100644 index 000000000..926233b69 --- /dev/null +++ b/postfix/util/watchdog.h @@ -0,0 +1,35 @@ +#ifndef _WATCHDOG_H_INCLUDED_ +#define _WATCHDOG_H_INCLUDED_ + +/*++ +/* NAME +/* watchdog 3h +/* SUMMARY +/* watchdog timer +/* SYNOPSIS +/* #include "watchdog.h" + DESCRIPTION + .nf + + /* + * External interface. + */ +typedef struct WATCHDOG WATCHDOG; +typedef void (*WATCHDOG_FN) (WATCHDOG *, char *); +extern WATCHDOG *watchdog_create(unsigned, WATCHDOG_FN, char *); +extern void watchdog_start(WATCHDOG *); +extern void watchdog_stop(WATCHDOG *); +extern void watchdog_destroy(WATCHDOG *); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif