Apply by doing: cd /usr/src patch -p0 < 028_sendmail.patch And then rebuild, install and restart sendmail: cd gnu/usr.sbin/sendmail make obj make depend make make install kill -HUP `sed 1q /var/run/sendmail.pid` Index: gnu/usr.sbin/sendmail/KNOWNBUGS =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/KNOWNBUGS,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/KNOWNBUGS 2000/04/02 19:48:09 1.2 +++ gnu/usr.sbin/sendmail/KNOWNBUGS 2001/01/15 21:08:50 1.3 @@ -1,7 +1,6 @@ K N O W N B U G S I N S E N D M A I L - (for 8.9.3) The following are bugs or deficiencies in sendmail that I am aware of @@ -13,7 +12,21 @@ This list is not guaranteed to be complete. +* Delivery to programs that generate too much output may cause problems + (8.10, 8.11) + If e-mail is delivered to a program which generates too much + output, then sendmail may issue an error: + + timeout waiting for input from local during Draining Input + + Make sure that the program does not generate output beyond a + status message (corresponding to the exit status). This may + require a wrapper around the actual program to redirect output + to /dev/null. + + Such a problem has been reported for bulk_mailer. + * Null bytes are not handled properly in headers. Sendmail should handle full binary data. As it stands, it handles @@ -198,4 +211,4 @@ state. This option and it's use is deprecated and will be removed from a future version of sendmail. -$Revision: 1.2 $, Last updated $Date: 2000/04/02 19:48:09 $ +$Revision: 1.3 $, Last updated $Date: 2001/01/15 21:08:50 $ Index: gnu/usr.sbin/sendmail/LICENSE =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/LICENSE,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/LICENSE 2000/04/02 19:48:09 1.2 +++ gnu/usr.sbin/sendmail/LICENSE 2001/02/28 02:43:48 1.4 @@ -33,7 +33,7 @@ forth as paragraph 6 below, in the documentation and/or other materials provided with the distribution. For the purposes of binary distribution the "Copyright Notice" refers to the following language: - "Copyright (c) 1998-2000 Sendmail, Inc. All rights reserved." + "Copyright (c) 1998-2001 Sendmail, Inc. All rights reserved." 4. Neither the name of Sendmail, Inc. nor the University of California nor the names of their contributors may be used to endorse or promote @@ -76,4 +76,4 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. -$Revision: 1.2 $, Last updated $Date: 2000/04/02 19:48:09 $ +$Revision: 1.4 $, Last updated $Date: 2001/02/28 02:43:48 $ Index: gnu/usr.sbin/sendmail/README =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/README,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- gnu/usr.sbin/sendmail/README 2000/04/07 19:20:25 1.3 +++ gnu/usr.sbin/sendmail/README 2001/01/15 21:08:50 1.4 @@ -47,10 +47,9 @@ You will probably have to tweak this for your environment (for example, some systems put the spool directory into /usr/spool instead of -/var/spool and use /etc/mail for aliases file instead of /etc). If you -set the RunAsUser option in your sendmail.cf, the /var/spool/mqueue -directory will have to be owned by the RunAsUser user. As a general rule, -after you have compiled sendmail, run the command +/var/spool). If you set the RunAsUser option in your sendmail.cf, the +/var/spool/mqueue directory will have to be owned by the RunAsUser user. +As a general rule, after you have compiled sendmail, run the command sendmail -v -bi @@ -90,8 +89,8 @@ delivery. Other files affected by this strengthened security include class -files (i.e. Fw /etc/sendmail.cw), persistent host status files, and -the files specified by the ErrorHeader and HelpFile options. Similar +files (i.e. Fw /etc/mail/local-host-names), persistent host status files, +and the files specified by the ErrorHeader and HelpFile options. Similar DontBlameSendmail flags are available for the class, ErrorHeader, and HelpFile files. @@ -187,6 +186,7 @@ RFC2033 Local Mail Transfer Protocol (LMTP) RFC2034 SMTP Service Extension for Returning Enhanced Error Codes RFC2476 Message Submission + RFC2487 SMTP Service Extension for Secure SMTP over TLS RFC2554 SMTP Service Extension for Authentication Other standards that may be of interest (but which are less directly @@ -200,6 +200,27 @@ RFC1035. ++---------+ +| WARNING | ++---------+ + +Since sendmail 8.11 and later includes hooks to cryptography, the +following information from OpenSSL applies to sendmail as well. + +PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG CRYPTOGRAPHY +SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST COMMUNICATING +TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS ILLEGAL IN SOME +PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE TO YOUR +COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL TECHNICAL +SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR OTHER PEOPLE +YOU ARE STRONGLY ADVISED TO PAY CLOSE ATTENTION TO ANY EXPORT/IMPORT +AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHORS ARE NOT LIABLE FOR +ANY VIOLATIONS YOU MAKE HERE. SO BE CAREFUL, IT IS YOUR RESPONSIBILITY. + +If you use OpenSSL then make sure you read their README file which +contains information about patents etc. + + +-------------------+ | DATABASE ROUTINES | +-------------------+ @@ -364,4 +385,4 @@ test Some test scripts (currently only for compilation aids). vacation Source for the vacation program. NOT PART OF SENDMAIL! -$Revision: 1.3 $, Last updated $Date: 2000/04/07 19:20:25 $ +$Revision: 1.4 $, Last updated $Date: 2001/01/15 21:08:50 $ Index: gnu/usr.sbin/sendmail/RELEASE_NOTES =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/RELEASE_NOTES,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/RELEASE_NOTES 2000/04/07 19:20:26 1.2 +++ gnu/usr.sbin/sendmail/RELEASE_NOTES 2001/05/29 01:31:10 1.5 @@ -1,18 +1,628 @@ SENDMAIL RELEASE NOTES - $Sendmail: RELEASE_NOTES,v 8.561 2000/04/06 23:51:49 gshapiro Exp $ + $Sendmail: RELEASE_NOTES,v 8.561.2.5.2.235 2001/05/27 21:39:16 gshapiro Exp $ This listing shows the version of the sendmail binary, the version of the sendmail configuration files, the date of release, and a summary of the changes in that release. +8.11.4/8.11.4 2001/05/28 + Clean up signal handling routines to reduce the chances of heap + corruption and other potential race conditions. + Terminating and restarting the daemon may not be + instantaneous due to this change. Also, non-root users can + no longer send out-of-band signals. Problem reported by + Michal Zalewski of BindView. + If LogLevel is greater than 9 and SASL fails to negotiate an + encryption layer, avoid core dump logging the encryption + strength. Problem noted by Miroslav Zubcic of Crol. + If a server offers "AUTH=" and "AUTH " and the list of mechanisms is + different in those two lines, sendmail might not have + recognized (and used) all of the offered mechanisms. + Fix an IP address lookup problem on Solaris 2.0 - 2.3. Patch + from Kenji Miyake. + This time, really don't use the .. directory when expanding + QueueDirectory wildcards. + If a process is interrupted while closing a map, don't try to close + the same map again while exiting. + Allow local mailers (F=l) to contact remote hosts (e.g., via + LMTP). Problem noted by Norbert Klasen of the University + of Tuebingen. + If Timeout.QueueReturn was set to a value less the time it took + to write a new queue file (e.g., 0 seconds), the bounce + message would be lost. Problem noted by Lorraine L Goff of + Oklahoma State University. + Pass map argument vector into map rewriting engine for the regex + and prog map types. Problem noted by Stephen Gildea of + InTouch Systems, Inc. + When closing an LDAP map due to a temporary error, close all of the + other LDAP maps which share the original map's connection + to the LDAP server. Patch from Victor Duchovni of + Morgan Stanley. + To detect changes of NDBM aliases files check the timestamp of the + .pag file instead of the .dir file. Problem noted by Neil + Rickert of Northern Illinois University. + Don't treat temporary hesiod lookup failures as permanent. Patch + from Werner Wiethege. + If ClientPortOptions is set, make sure to create the outgoing socket + with the family set in that option. Patch from Sean Farley. + Avoid a segmentation fault trying to dereference a NULL pointer + when logging a MaxHopCount exceeded error with an empty + recipient list. Problem noted by Chris Adams of HiWAAY + Internet Services. + Fix DSN for "Too many hops" bounces. Problem noticed by Ulrich + Windl of the Universitaet Regensburg. + Fix DSN for "mail loops back to me" bounces. Problem noticed by + Kari Hurtta of the Finnish Meteorological Institute. + Portability: + OpenBSD has a broken setreuid() implementation. + CONFIG: Undo change from 8.11.1: change 501 SMTP reply code back + to 553 since it is allowed by DRUMS. + CONFIG: Add OSTYPE(freebsd4) for FreeBSD 4.X. + DEVTOOLS: install.sh did not properly handle paths in the source + file name argument. Noted by Kari Hurtta of the Finnish + Meteorological Institute. + DEVTOOLS: Add FAST_PID_RECYCLE to compile time options for OpenBSD + since it generates random process ids. + PRALIASES: Add back adaptive algorithm to deal with different endings + of entries in the database (with/without trailing '\0'). + Patch from John Beck of Sun Microsystems. + New Files: + cf/ostype/freebsd4.m4 + +8.11.3/8.11.3 2001/02/27 + Prevent a segmentation fault when a bogus value was used in the + LDAPDefaultSpec option's -r, -s, or -M flags and if a bogus + option was used. Problem noted by Allan E Johannesen of + Worcester Polytechnic Institute. + Prevent "token too long" message by shortening {currHeader} which + could be too long if the last copied character was a quote. + Problem detected by Jan Krueger of digitalanswers + communications consulting gmbh. + Additional IPv6 check for unspecified addresses. Patch from + Jun-ichiro itojun Hagino of the KAME Project. + Do not ignore the ClientPortOptions setting if DaemonPortOptions + Modifier=b (bind to same interface) is set and the + connection came in from the command line. + Do not bind to the loopback address if DaemonPortOptions + Modifier=b (bind to same interface) is set. Patch from + John Beck of Sun Microsystems. + Properly deal with open failures on non-optional maps used in + check_* rulesets by returning a temporary failure. + Buffered file I/O files were not being properly fsync'ed to disk + when they were committed. + Properly encode '=' for the AUTH= parameter of the MAIL command. + Problem noted by Hadmut Danisch. + Under certain circumstances the macro {server_name} could be set + to the wrong hostname (of a previous connection), which may + cause some rulesets to return wrong results. This would + usually cause mail to be queued up and delivered later on. + Ignore F=z (LMTP) mailer flag if $u is given in the mailer A= + equate. Problem noted by Motonori Nakamura of Kyoto + University. + Work around broken accept() implementations which only partially + fill in the peer address if the socket is closed before + accept() completes. + Return an SMTP "421" temporary failure if the data file can't be + opened where the "354" reply would normally be given. + Prevent a CPU loop in trying to expand a macro which doesn't exist + in a queue run. Problem noted by Gordon Lack of Glaxo + Wellcome. + If delivering via a program and that program exits with EX_TEMPFAIL, + note that fact for the mailq display instead of just showing + "Deferred". Problem noted by Motonori Nakamura of Kyoto + University. + If doing canonification via /etc/hosts, try both the fully + qualified hostname as well as the first portion of the + hostname. Problem noted by David Bremner of the + University of New Brunswick. + Portability: + Fix a compilation problem for mail.local and rmail if SFIO + is in use. Problem noted by Auteria Wally + Winzer Jr. of Champion Nutrition. + IPv6 changes for platforms using KAME. Patch from + Jun-ichiro itojun Hagino of the KAME Project. + OpenBSD 2.7 and higher has srandomdev(3). OpenBSD 2.8 and + higher has BSDI-style login classes. Patch from + Todd C. Miller of Courtesan Consulting. + Unixware 7.1.1 doesn't allow h_errno to be set directly if + sendmail is being compiled with -kthread. Problem + noted by Orion Poplawski of CQG, Inc. + CONTRIB: buildvirtuser: Substitute current domain for $DOMAIN and + current left hand side for $LHS in virtuser files. + DEVTOOLS: Do not pass make targets to recursive Build invocations. + Problem noted by Jeff Bronson of J.D. Bronson, Inc. + MAIL.LOCAL: In LMTP mode, do not return errors regarding problems + storing the temporary message file until after the remote + side has sent the final DATA termination dot. Problem + noted by Allan E Johannesen of Worcester Polytechnic + Institute. + MAIL.LOCAL: If LMTP mode is set, give a temporary error if users + are also specified on the command line. Patch from + Motonori Nakamura of Kyoto University. + PRALIASES: Skip over AliasFile specifications which aren't based on + database files (i.e., only show dbm, hash, and btree). + Renamed Files: + devtools/OS/OSF1.V5.0 => devtools/OS/OSF1.V5.x + +8.11.2/8.11.2 2000/12/29 + Prevent a segmentation fault when trying to set a class in + address test mode due to a negative array index. Audit + other array indexing. This bug is not believed to be + exploitable. Noted by Michal Zalewski of the "Internet for + Schools" project (IdS). + Add an FFR (for future release) to drop privileges when using + address test mode. This will be turned on in 8.12. It can + be enabled by compiling with: + APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_TESTMODE_DROP_PRIVS') + in your devtools/Site/site.config.m4 file. Suggested by + Michal Zalewski of the "Internet for Schools" project (IdS). + Fix potential problem with Cyrus-SASL security layer which may have + caused I/O errors, especially for mechanism DIGEST-MD5. + When QueueSortOrder was set to host, sendmail might not read + enough of the queue file to determine the host, making the + sort sub-optimal. Problem noted by Jeff Earickson of + Colby College. + Don't issue DSNs for addresses which use the NOTIFY parameter (per + RFC 1891) but don't have FAILURE as value. + Initialize Cyrus-SASL library before the SMTP daemon is started. + This implies that every change to SASL related files requires + a restart of the daemon, e.g., Sendmail.conf, new SASL + mechanisms (in form of shared libraries). + Properly set the STARTTLS related macros during a queue run for + a cached connection. Bug reported by Michael Kellen of + NxNetworks, Inc. + Log the server name in relay= for ruleset tls_server instead of the + client name. + Include original length of bad field/header when reporting + MaxMimeHeaderLength problems. Requested by Ulrich Windl of + the Universitat Regensburg. + Fix delivery to set-user-ID files that are expanded from aliases in + DeliveryMode queue. Problem noted by Ric Anderson of the + University of Arizona. + Fix LDAP map -m (match only) flag. Problem noted by Jeff Giuliano + of Collective Technologies. + Avoid using a negative argument for sleep() calls when delaying answers + to EXPN/VRFY commands on systems which respond very slowly. + Problem noted by Mikolaj J. Habryn of Optus Internet + Engineering. + Make sure the F=u flag is set in the default prog mailer + definition. Problem noted by Kari Hurtta of the Finnish + Meteorological Institute. + Fix IPv6 check for unspecified addresses. Patch from + Jun-ichiro itojun Hagino of the KAME Project. + Fix return values for IRIX nsd map. From Kari Hurtta of the Finnish + Meteorological Institute. + Fix parsing of DaemonPortOptions and ClientPortOptions. Read all + of the parameters to find Family= setting before trying to + interpret Addr= and Port=. Problem noted by Valdis + Kletnieks of Virginia Tech. + When delivering to a file directly from an alias, do not call + initgroups(); instead use the DefaultUser group information. + Problem noted by Marc Schaefer of ALPHANET NF. + RunAsUser now overrides the ownership of the control socket, if + created. Otherwise, sendmail can not remove it upon + close. Problem noted by Werner Wiethege. + Fix ConnectionRateThrottle counting as the option is the number of + overall connections, not the number of connections per + socket. A future version may change this to per socket + counting. + Portability: + Clean up libsmdb so it functions properly on platforms + where sizeof(u_int32_t) != sizeof(size_t). Problem + noted by Rein Tollevik of Basefarm AS. + Fix man page formatting for compatibility with Solaris' + whatis. From Stephen Gildea of InTouch Systems, Inc. + UnixWare 7 includes snprintf() support. From Larry + Rosenman. + IPv6 changes for platforms using KAME. Patch from + Jun-ichiro itojun Hagino of the KAME Project. + Avoid a typedef compile conflict with Berkeley DB 3.X and + Solaris 2.5 or earlier. Problem noted by Bob Hughes + of Pacific Access. + Add preliminary support for AIX 5. Contributed by + Valdis Kletnieks of Virginia Tech. + Solaris 9 load average support from Andrew Tucker of Sun + Microsystems. + CONFIG: Reject addresses of the form a!b if FEATURE(`nouucp', `r') + is used. Problem noted by Phil Homewood of Asia Online, + patch from Neil Rickert of Northern Illinois University. + CONFIG: Change the default DNS based blacklist server for + FEATURE(`dnsbl') to blackholes.mail-abuse.org. + CONFIG: Deal correctly with the 'C' flag in {daemon_flags}, i.e., + implicitly assume canonical host names. + CONFIG: Deal with "::" in IPv6 addresses for access_db. Based on + patch by Motonori Nakamura of Kyoto University. + CONFIG: New OSTYPE(`aix5') contributed by Valdis Kletnieks of + Virginia Tech. + CONFIG: Pass the illegal header form through untouched + instead of making it worse. Problem noted by Motonori + Nakamura of Kyoto University. + CONTRIB: Added buildvirtuser (see `perldoc contrib/buildvirtuser`). + CONTRIB: qtool.pl: An empty queue is not an error. Problem noted + by Jan Krueger of digitalanswers communications consulting + gmbh. + CONTRIB: domainmap.m4: Handle domains with '-' in them. From Mark + Roth of the University of Illinois at Urbana-Champaign. + DEVTOOLS: Change the internal devtools OS, REL, and ARCH m4 + variables into bldOS, bldREL, and bldARCH to prevent + namespace collisions. Problem noted by Motonori Nakamura + of Kyoto University. + RMAIL: Undo the 8.11.1 change to use -G when calling sendmail. It + causes some changes in behavior and may break rmail for + installations where sendmail is actually a wrapper to + another MTA. The change will re-appear in a future + version. + SMRSH: Use the vendor supplied directory on HPUX 10.X, HPUX 11.X, + and SunOS 5.8. Requested by Jeff A. Earickson of Colby + College and John Beck of Sun Microsystems. + VACATION: Fix pattern matching for addresses to ignore. + VACATION: Don't reply to addresses of the form owner-* + or *-owner. + New Files: + cf/ostype/aix5.m4 + contrib/buildvirtuser + devtools/OS/AIX.5.0 + +8.11.1/8.11.1 2000/09/27 + Fix SMTP EXPN command output if the address expands to a single + name. Fix from John Beck of Sun Microsystems. + Don't try STARTTLS in the client if the PRNG has not been properly + seeded. This problem only occurs on systems without + /dev/urandom. Problem detected by Jan Krueger of + digitalanswers communications consulting gmbh and + Neil Rickert of Northern Illinois University. + Don't use the . and .. directories when expanding QueueDirectory + wildcards. + Do not try to cache LDAP connections across processes as a parent + process may close the connection before the child process + has completed. Problem noted by Lai Yiu Fai of the Hong + Kong University of Science and Technology and Wolfgang + Hottgenroth of UUNET. + Use Timeout.fileopen to limit the amount of time spent trying to + read the LDAP secret from a file. + Prevent SIGTERM from removing a command line submitted item after + the user submits the message and before the first delivery + attempt completes. Problem noted by Max France of AlphaNet. + Fix from Neil Rickert of Northern Illinois University. + Deal correctly with MaxMessageSize restriction if message size is + greater than 2^31. Problem noted by Tim "Darth Dice" Bosserman + of EarthLink. + Turn off queue checkpointing if CheckpointInterval is set to zero. + Treat an empty home directory (from getpw*() or $HOME) as + non-existent instead of treating it as /. Problem noted by + Todd C. Miller of Courtesan Consulting. + Don't drop duplicate headers when reading a queued item. Problem + noted by Motonori Nakamura of Kyoto University. + Avoid bogus error text when logging the savemail panic "cannot + save rejected email anywhere". Problem noted by Marc G. + Fournier of Acadia University. + If an LDAP search fails because the LDAP server went down, close + the map so subsequent searches reopen the map. If there are + multiple LDAP servers, the down server will be skipped and + one of the others may be able to take over. + Set the ${load_avg} macro to the current load average, not the + previous load average query result. + If a non-optional map used in a check_* ruleset can't be opened, + return a temporary failure to the remote SMTP client + instead of ignoring the map. Problem noted by Allan E + Johannesen of Worcester Polytechnic Institute. + Avoid a race condition when queuing up split envelopes by saving + the split envelopes before the original envelope. + Fix a bug in the PH_MAP code which caused mail to bounce instead of + defer if the PH server could not be contacted. From Mark + Roth of the University of Illinois at Urbana-Champaign. + Prevent QueueSortOrder=Filename from interfering with -qR, -qS, and + ETRN. Problem noted by Erik R. Leo of SoVerNet. + Change error code for unrecognized parameters to the SMTP MAIL and + RCPT commands from 501 to 555 per RFC 1869. Problem + reported to Postfix by Robert Norris of Monash University. + Prevent overwriting the argument of -B on certain OS. Problem + noted by Matteo Gelosa of I.NET S.p.A. + Use the proper routine for freeing memory with Netscape's LDAP + client libraries. Patch from Paul Hilchey of the + University of British Columbia. + Portability: + Move the NETINET6 define to devtools/OS/SunOS.5.{8,9} + instead of defining it in conf.h so users can + override the setting. Suggested by + Henrik Nordstrom of Ericsson. + On HP-UX 10.X and 11.X, use /usr/sbin/sendmail instead of + /usr/lib/sendmail for rmail and vacation. From + Jeff A. Earickson of Colby College. + On HP-UX 11.X, use /usr/sbin instead of /usr/libexec (which + does not exist). From Jeff A. Earickson of Colby + College. + Avoid using the UCB subsystem on NCR MP-RAS 3.x. From + Tom Moore of NCR. + NeXT 3.X and 4.X installs man pages in /usr/man. From + Hisanori Gogota of NTT/InterCommunicationCenter. + Solaris 8 and later include /var/run. The default PID file + location is now /var/run/sendmail.pid. From John + Beck of Sun Microsystems. + SFIO includes snprintf() for those operating systems + which do not. From Todd C. Miller of Courtesan + Consulting. + CONFIG: Use the result of _CERT_REGEX_SUBJECT_ not {cert_subject}. + Problem noted by Kaspar Brand of futureLab AG. + CONFIG: Change 553 SMTP reply code to 501 to avoid problems with + errors in the MAIL address. + CONFIG: Fix FEATURE(nouucp) usage in example .mc files. Problem + noted by Ron Jarrell of Virginia Tech. + CONFIG: Add support for Solaris 8 (and later) as OSTYPE(solaris8). + Contributed by John Beck of Sun Microsystems. + CONFIG: Set confFROM_HEADER such that the mail hub can possibly add + GECOS information for an address. This more closely + matches pre-8.10 nullclient behavior. From Per Hedeland of + Ericsson. + CONFIG: Fix MODIFY_MAILER_FLAGS(): apply the flag modifications for + SMTP to all *smtp* mailers and those for RELAY to the relay + mailer as described in cf/README. + MAIL.LOCAL: Open the mailbox as the recipient not root so quotas + are obeyed. Problem noted by Damian Kuczynski of NIK. + MAKEMAP: Do not change a map's owner to the TrustedUser if using + makemap to 'unmake' the map. + RMAIL: Avoid overflowing the list of recipients being passed to + sendmail. + RMAIL: Invoke sendmail with '-G' to indicate this is a gateway + submission. Problem noted by Kari Hurtta of the Finnish + Meteorological Institute. + VACATION: Read the complete message to avoid "broken pipe" signals. + VACATION: Do not cut off vacation.msg files which have a single + dot as the only character on the line. + New Files: + cf/ostype/solaris8.m4 + +8.11.0/8.11.0 2000/07/19 + SECURITY: If sendmail is installed as a non-root set-user-ID binary + (not the normal case), some operating systems will still + keep a saved-uid of the effective-uid when sendmail tries + to drop all of its privileges. If sendmail needs to drop + these privileges and the operating system doesn't set the + saved-uid as well, exit with an error. Problem noted by + Kari Hurtta of the Finnish Meteorological Institute. + SECURITY: sendmail depends on snprintf() NUL terminating the string + it populates. It is possible that some broken + implementations of snprintf() exist that do not do this. + Systems in this category should compile with + -DSNPRINTF_IS_BROKEN=1. Use test/t_snprintf.c to test your + system and report broken implementations to + sendmail-bugs@sendmail.org and your OS vendor. Problem + noted by Slawomir Piotrowski of TELSAT GP. + Support SMTP Service Extension for Secure SMTP (RFC 2487) (STARTTLS). + Implementation influenced by the example programs of + OpenSSL and the work of Lutz Jaenicke of TU Cottbus. + Add new STARTTLS related options CACERTPath, CACERTFile, + ClientCertFile, ClientKeyFile, DHParameters, RandFile, + ServerCertFile, and ServerKeyFile. These are documented in + cf/README and doc/op/op.*. + New STARTTLS related macros: ${cert_issuer}, ${cert_subject}, + ${tls_version}, ${cipher}, ${cipher_bits}, ${verify}, + ${server_name}, and ${server_addr}. These are documented + in cf/README and doc/op/op.*. + Add support for the Entropy Gathering Daemon (EGD) for better + random data. + New DontBlameSendmail option InsufficientEntropy for systems which + don't properly seed the PRNG for OpenSSL but want to + try to use STARTTLS despite the security problems. + Support the security layer in SMTP AUTH for mechanisms which + support encryption. Based on code contributed by Tim + Martin of CMU. + Add new macro ${auth_ssf} to reflect the SMTP AUTH security + strength factor. + LDAP's -1 (single match only) flag was not honored if the -z + (delimiter) flag was not given. Problem noted by ST Wong of + the Chinese University of Hong Kong. Fix from Mark Adamson + of CMU. + Add more protection from accidentally tripping OpenLDAP 1.X's + ld_errno == LDAP_DECODING_ERROR hack on ldap_next_attribute(). + Suggested by Kurt Zeilenga of OpenLDAP. + Fix the default family selection for DaemonPortOptions. As + documented, unless a family is specified in a + DaemonPortOptions option, "inet" is the default. It is + also the default if no DaemonPortOptions value is set. + Therefore, IPv6 users should configure additional sockets + by adding DaemonPortOptions settings with Family=inet6 if + they wish to also listen on IPv6 interfaces. Problem noted + by Jun-ichiro itojun Hagino of the KAME Project. + Set ${if_family} when setting ${if_addr} and ${if_name} to reflect + the interface information for an outgoing connection. + Not doing so was creating a mismatch between the socket + family and address used in subsequent connections if the + M=b modifier was set in DaemonPortOptions. Problem noted + by John Beck of Sun Microsystems. + If DaemonPortOptions modifier M=b is used, determine the socket + family based on the IP address. ${if_family} is no longer + persistent (i.e., saved in qf files). Patch from John Beck + of Sun Microsystems. + sendmail 8.10 and 8.11 reused the ${if_addr} and ${if_family} + macros for both the incoming interface address/family and + the outgoing interface address/family. In order for M=b + modifier in DaemonPortOptions to work properly, preserve + the incoming information in the queue file for later + delivery attempts. + Use SMTP error code and enhanced status code from check_relay in + responses to commands. Problem noted by Jeff Wasilko of + smoe.org. + Add more vigilance in checking for putc() errors on output streams + to protect from a bug in Solaris 2.6's putc(). Problem + noted by Graeme Hewson of Oracle. + The LDAP map -n option (return attribute names only) wasn't working. + Problem noted by Ajay Matia. + Under certain circumstances, an address could be listed as deferred + but would be bounced back to the sender as failed to be + delivered when it really should have been queued. Problem + noted by Allan E Johannesen of Worcester Polytechnic Institute. + Prevent a segmentation fault in a child SMTP process from getting + the SMTP transaction out of sync. Problem noted by Per + Hedeland of Ericsson. + Turn off RES_DEBUG if SFIO is defined unless SFIO_STDIO_COMPAT + is defined to avoid a core dump due to incompatibilities + between sfio and stdio. Problem noted by Neil Rickert + of Northern Illinois University. + Don't log useless envelope ID on initial connection log. Problem + noted by Kari Hurtta of the Finnish Meteorological Institute. + Convert the free disk space shown in a control socket status query + to kilobyte units. + If TryNullMXList is True and there is a temporary DNS failure + looking up the hostname, requeue the message for a later + attempt. Problem noted by Ari Heikkinen of Pohjois-Savo + Polytechnic. + Under the proper circumstances, failed connections would be recorded + as "Bad file number" instead of "Connection failed" in the + queue file and persistent host status. Problem noted by + Graeme Hewson of Oracle. + Avoid getting into an endless loop if a non-hoststat directory exists + within the hoststatus directory (e.g., lost+found). + Patch from Valdis Kletnieks of Virginia Tech. + Make sure Timeout.queuereturn=now returns a bounce message to the + sender. Problem noted by Per Hedeland of Ericsson. + If a message data file can't be opened at delivery time, panic and + abort the attempt instead of delivering a message that + states "<<< No Message Collected >>>". + Fixup the GID checking code from 8.10.2 as it was overly + restrictive. Problem noted by Mark G. Thomas of Mark + G. Thomas Consulting. + Preserve source port number instead of replacing it with the ident + port number (113). + Document the queue status characters in the mailq man page. + Suggested by Ulrich Windl of the Universitat Regensburg. + Process queued items in which none of the recipient addresses have + host portions (or there are no recipients). Problem noted + by Valdis Kletnieks of Virginia Tech. + If a cached LDAP connection is used for multiple maps, make sure + only the first to open the connection is allowed to close + it so a later map close doesn't break the connection for + other maps. Problem noted by Wolfgang Hottgenroth of UUNET. + Netscape's LDAP libraries do not support Kerberos V4 + authentication. Patch from Rainer Schoepf of the + University of Mainz. + Provide workaround for inconsistent handling of data passed + via callbacks to Cyrus SASL prior to version 1.5.23. + Mention ENHANCEDSTATUSCODES in the SMTP HELP helpfile. Omission + noted by Ulrich Windl of the Universitat Regensburg. + Portability: + Add the ability to read IPv6 interface addresses into class + 'w' under FreeBSD (and possibly others). From Jun + Kuriyama of IMG SRC, Inc. and the FreeBSD Project. + Replace code for finding the number of CPUs on HPUX. + NCRUNIX MP-RAS 3.02 SO_REUSEADDR socket option does not + work properly causing problems if the accept() + fails and the socket needs to be reopened. Patch + from Tom Moore of NCR. + NetBSD uses a .0 extension of formatted man pages. From + Andrew Brown of Crossbar Security. + Return to using the IPv6 AI_DEFAULT flag instead of AI_V4MAPPED + for calls to getipnodebyname(). The Linux + implementation is broken so AI_ADDRCONFIG is stripped + under Linux. From John Beck of Sun Microsystems and + John Kennedy of Cal State University, Chico. + CONFIG: Catch invalid addresses containing a ',' at the wrong place. + Patch from Neil Rickert of Northern Illinois University. + CONFIG: New variables for the new sendmail options: + confCACERT_PATH CACERTPath + confCACERT CACERTFile + confCLIENT_CERT ClientCertFile + confCLIENT_KEY ClientKeyFile + confDH_PARAMETERS DHParameters + confRAND_FILE RandFile + confSERVER_CERT ServerCertFile + confSERVER_KEY ServerKeyFile + CONFIG: Provide basic rulesets for TLS policy control and add new + tags to the access database to support these policies. See + cf/README for more information. + CONFIG: Add TLS information to the Received: header. + CONFIG: Call tls_client ruleset from check_mail in case it wasn't + called due to a STARTTLS command. + CONFIG: If TLS_PERM_ERR is defined, TLS related errors are permanent + instead of temporary. + CONFIG: FEATURE(`relay_hosts_only') didn't work in combination with + the access map and relaying to a domain without using a To: + tag. Problem noted by Mark G. Thomas of Mark G. Thomas + Consulting. + CONFIG: Set confEBINDIR to /usr/sbin to match the devtools entry in + OSTYPE(`linux') and OSTYPE(`mklinux'). From Tim Pierce of + RootsWeb.com. + CONFIG: Make sure FEATURE(`nullclient') doesn't use aliasing and + forwarding to make it as close to the old behavior as + possible. Problem noted by George W. Baltz of the + University of Maryland. + CONFIG: Added OSTYPE(`darwin') for Mac OS X and Darwin users. From + Wilfredo Sanchez of Apple Computer, Inc. + CONFIG: Changed the map names used by FEATURE(`ldap_routing') from + ldap_mailhost and ldap_mailroutingaddress to ldapmh and + ldapmra as underscores in map names cause problems if + underscore is in OperatorChars. Problem noted by Bob Zeitz + of the University of Alberta. + CONFIG: Apply blacklist_recipients also to hosts in class {w}. + Patch from Michael Tratz of Esosoft Corporation. + CONFIG: Use A=TCP ... instead of A=IPC ... in SMTP mailers. + CONTRIB: Add link_hash.sh to create symbolic links to the hash + of X.509 certificates. + CONTRIB: passwd-to-alias.pl: More protection from special characters; + treat special shells as root aliases; skip entries where the + GECOS full name and username match. From Ulrich Windl of the + Universitat Regensburg. + CONTRIB: qtool.pl: Add missing last_modified_time method and fix a + typo. Patch from Graeme Hewson of Oracle. + CONTRIB: re-mqueue.pl: Improve handling of a race between re-mqueue + and sendmail. Patch from Graeme Hewson of Oracle. + CONTRIB: re-mqueue.pl: Don't exit(0) at end so can be called as + subroutine Patch from Graeme Hewson of Oracle. + CONTRIB: Add movemail.pl (move old mail messages between queues by + calling re-mqueue.pl) and movemail.conf (configuration + script for movemail.pl). From Graeme Hewson of Oracle. + CONTRIB: Add cidrexpand (expands CIDR blocks as a preprocessor to + makemap). From Derek J. Balling of Yahoo,Inc. + DEVTOOLS: INSTALL_RAWMAN installation option mistakenly applied any + extension modifications (e.g., MAN8EXT) to the installation + target. Patch from James Ralston of Carnegie Mellon + University. + DEVTOOLS: Add support for SunOS 5.9. + DEVTOOLS: New option confLN contains the command used to create + links. + LIBSMDB: Berkeley DB 2.X and 3.X errors might be lost and not + reported. + MAIL.LOCAL: DG/UX portability. Problem noted by Tim Boyer of + Denman Tire Corporation. + MAIL.LOCAL: Prevent a possible DoS attack when compiled with + -DCONTENTLENGTH. Based on patch from 3APA3A@SECURITY.NNOV.RU. + MAILSTATS: Fix usage statement (-p and -o are optional). + MAKEMAP: Change man page layout as workaround for problem with nroff + and -man on Solaris 7. Patch from Larry Williamson. + RMAIL: AIX 4.3 has snprintf(). Problem noted by David Hayes of + Black Diamond Equipment, Limited. + RMAIL: Prevent a segmentation fault if the incoming message does not + have a From line. + VACATION: Read all of the headers before deciding whether or not + to respond instead of stopping after finding recipient. + Added Files: + cf/ostype/darwin.m4 + contrib/cidrexpand + contrib/link_hash.sh + contrib/movemail.conf + contrib/movemail.pl + devtools/OS/SunOS.5.9 + test/t_snprintf.c + +8.10.2/8.10.2 2000/06/07 + SECURITY: Work around broken Linux setuid() implementation. + On Linux, a normal user process has the ability to subvert + the setuid() call such that it is impossible for a root + process to drop its privileges. Problem noted by Wojciech + Purczynski of elzabsoft.pl. + SECURITY: Add more vigilance around set*uid(), setgid(), setgroups(), + initgroups(), and chroot() calls. + Added Files: + test/t_setuid.c + 8.10.1/8.10.1 2000/04/06 SECURITY: Limit the choice of outgoing (client-side) SMTP Authentication mechanisms to those specified in AuthMechanisms to prevent information leakage. We do not recommend use of PLAIN for outgoing mail as it sends the password in clear text to possibly untrusted servers. See - cf/README's DefAuthInfo section for additional information. + cf/README's DefaultAuthInfo section for additional information. Copy the ident argument for openlog() to avoid problems on some OSs. Based on patch from Rob Bajorek from Webhelp.com. Avoid bogus error message when reporting an alias line as too long. @@ -505,7 +1115,7 @@ "(user=%s)"' and a lookup is done on "*", this would be equivalent to '-k "(user=*)"' -- matching ANY record with a user attribute. Instead, if the LDAP map specification - contains '-k "(user=%0)"' and a lookup is one on "*", this + contains '-k "(user=%0)"' and a lookup is done on "*", this would be equivalent to '-k "(user=\2A)"' -- matching a user with the name "*". New LDAP map flags: "-1" requires a single match to be returned, if @@ -531,7 +1141,7 @@ Ulrich Windl of the Universitat Regensburg. Add new F=% mailer flag to allow for a store and forward configuration. Mailers which have this flag will not attempt - delivery on initial recipient of a message or on queue runs + delivery on initial receipt of a message or on queue runs unless the queued message is selected using one of the -qI/-qR/-qS queue run modifiers or an ETRN request. Code provided by Philip Guenther of Gustavus Adolphus College. @@ -570,9 +1180,8 @@ Macro expand PostmasterCopy and DoubleBounceAddress options. New "ph" map for performing ph queries in rulesets. More information is available at - http://www-wsg.cso.uiuc.edu/sendmail/patches/. - Contributed by Mark Roth of the University of Illinois at - Urbana-Champaign. + http://www-dev.cso.uiuc.edu/sendmail/. Contributed by Mark + Roth of the University of Illinois at Urbana-Champaign. Detect temporary lookup failures in the host map if looking up a bracketed IP address. Problem noted by Kari Hurtta of the Finnish Meteorological Institute. @@ -1251,7 +1860,7 @@ MAILLOCK when compiling. Also requires linking with -lmail. Patch from Neil Rickert of Northern Illinois University. - MAIL.LOCAL: Create a Content-Length; header if CONTENTLENGTH is + MAIL.LOCAL: Create a Content-Length: header if CONTENTLENGTH is defined when compiling. Automatically set for Solaris 2.3 and later. Patch from Neil Rickert of Northern Illinois University. @@ -1266,15 +1875,15 @@ MAIL.LOCAL: Support group writable mail spool files when MAILGID is set to the gid to use (-DMAILGID=6) when compiling. Patch from Neil Rickert of Northern Illinois University. - MAIL.LOCAL: When a mail message includes lines longer than 2046 - characters (in LMTP mode), mail.local will split the - incoming line up into 2046-character output lines - (excluding the newline). If an input line is 2047 - characters long (excluding CR-LF) and the last character is - a '.', mail.local will see it as the end of input, transfer - it to the user mailbox and try to write an `ok' back to - sendmail. If the message was much longer, both sendmail - and mail.local will deadlock waiting for each other to read + MAIL.LOCAL: When a mail message included lines longer than 2046 + characters (in LMTP mode), mail.local split the incoming + line up into 2046-character output lines (excluding the + newline). If an input line was 2047 characters long + (excluding CR-LF) and the last character was a '.', + mail.local saw it as the end of input, transfered it to the + user mailbox and tried to write an `ok' back to sendmail. + If the message was much longer, both sendmail and + mail.local would deadlock waiting for each other to read what they have written. Problem noted by Peter Jeremy of Alcatel Australia Limited. MAIL.LOCAL: New option -b to return a permanent error instead of a @@ -2106,7 +2715,7 @@ CONFIG: new FEATURE(relay_based_on_MX) to allow relaying based on the MX records of the host portion of an incoming recipient. CONFIG: new FEATURE(access_db) which turns on the access database - feature. This database give you the ability to allow + feature. This database gives you the ability to allow or refuse to accept mail from specified domains for administrative reasons. By default, names that are listed as "OK" in the access db are domain names, not host names. @@ -2958,9 +3567,9 @@ first" error message. Problem pointed out by Chris Thomas of UCLA; patch from John Beck of SunSoft. Handle "sendmail -bp -qSfoobar" properly if restrictqrun is set - in PrivacyOptions. The -q shouldn't turn this command off. - Problem noted by Murray Kucherawy of Pacific Bell Internet; - based on a patch from Gregory Neil Shapiro of WPI. + in PrivacyOptions. The -q shouldn't turn this command off. + Problem noted by Murray Kucherawy of Pacific Bell Internet; + based on a patch from Gregory Neil Shapiro of WPI. Don't consider SMTP reply codes 452 or 552 (exceeded storage allocation) in a DATA transaction to be sticky; these can occur because a message is too large, and smaller messages should still go Index: gnu/usr.sbin/sendmail/cf/README =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/README,v retrieving revision 1.3 retrieving revision 1.6 diff -u -r1.3 -r1.6 --- gnu/usr.sbin/sendmail/cf/README 2000/04/07 19:20:28 1.3 +++ gnu/usr.sbin/sendmail/cf/README 2001/05/29 01:31:10 1.6 @@ -6,8 +6,8 @@ 7th Edition version. SunOS's /usr/5bin/m4 or BSD-Net/2's m4 both work. GNU m4 version 1.1 or later also works. Unfortunately, the M4 on BSDI 1.0 doesn't work -- you'll have to use a Net/2 or GNU version. GNU m4 is -available from ftp://ftp.gnu.org/pub/gnu/m4-1.4.tar.gz (check for the -latset version). EXCEPTIONS: DEC's m4 on Digital UNIX 4.x is broken (3.x +available from ftp://ftp.gnu.org/pub/gnu/m4/m4-1.4.tar.gz (check for the +latest version). EXCEPTIONS: DEC's m4 on Digital UNIX 4.x is broken (3.x is fine). Use GNU m4 on this platform. To get started, you may want to look at tcpproto.mc (for TCP-only sites), @@ -54,7 +54,7 @@ divert(-1) # - # Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + # Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -254,12 +254,13 @@ QUEUE_DIR [/var/spool/mqueue] The directory containing queue files. To use multiple queues, supply a value ending with an asterisk. For - example, /var/spool/mqueue/q* will use all of the + example, /var/spool/mqueue/qd* will use all of the directories or symbolic links to directories - beginning with 'q' in /var/spool/mqueue as queue + beginning with 'qd' in /var/spool/mqueue as queue directories. The names 'qf', 'df', and 'xf' are - used as specific subdirectories for the corresponding - queue file types. + reserved as specific subdirectories for the + corresponding queue file types as explained in + doc/op/op.me. STATUS_FILE [/etc/mail/statistics] The file containing status information. LOCAL_MAILER_PATH [/bin/mail] The program used to deliver local mail. @@ -309,13 +310,13 @@ SMTP_MAILER_MAXMSGS [undefined] If defined, the maximum number of messages to deliver in a single connection for the smtp, smtp8, esmtp, or dsmtp mailers. -SMTP_MAILER_ARGS [IPC $h] The arguments passed to the smtp mailer. +SMTP_MAILER_ARGS [TCP $h] The arguments passed to the smtp mailer. About the only reason you would want to change this would be to change the default port. -ESMTP_MAILER_ARGS [IPC $h] The arguments passed to the esmtp mailer. -SMTP8_MAILER_ARGS [IPC $h] The arguments passed to the smtp8 mailer. -DSMTP_MAILER_ARGS [IPC $h] The arguments passed to the dsmtp mailer. -RELAY_MAILER_ARGS [IPC $h] The arguments passed to the relay mailer. +ESMTP_MAILER_ARGS [TCP $h] The arguments passed to the esmtp mailer. +SMTP8_MAILER_ARGS [TCP $h] The arguments passed to the smtp8 mailer. +DSMTP_MAILER_ARGS [TCP $h] The arguments passed to the dsmtp mailer. +RELAY_MAILER_ARGS [TCP $h] The arguments passed to the relay mailer. RELAY_MAILER_MAXMSGS [undefined] If defined, the maximum number of messages to deliver in a single connection for the relay mailer. @@ -426,13 +427,16 @@ of the form node::user will not work. FAX_RELAY The host that will accept mail to the .FAX pseudo-domain. The "fax" mailer overrides this value. -LOCAL_RELAY DEPRECATED. The site that will handle unqualified - names -- that is, names with out an @domain extension. - If not set, they are assumed to belong on this machine. - This allows you to have a central site to store a - company- or department-wide alias database. This - only works at small sites, and only with some user - agents. +LOCAL_RELAY The site that will handle unqualified names -- that + is, names with out an @domain extension. + Normally MAIL_HUB is preferred for this function. + LOCAL_RELAY is mostly useful in conjunction with + FEATURE(stickyhost) -- see the discussion of + stickyhost below. If not set, they are assumed to + belong on this machine. This allows you to have a + central site to store a company- or department-wide + alias database. This only works at small sites, + and only with some user agents. LUSER_RELAY The site that will handle lusers -- that is, apparently local names that aren't local accounts or aliases. To specify a local user instead of a site, set this to @@ -488,7 +492,7 @@ demand delivery, and "relay" for transmission to the RELAY_HOST, LUSER_RELAY, or MAIL_HUB. -uucp The Unix-to-Unix Copy Program mailer. Actually, this +uucp The UNIX-to-UNIX Copy Program mailer. Actually, this defines two mailers, "uucp-old" (a.k.a. "uucp") and "uucp-new" (a.k.a. "suucp"). The latter is for when you know that the UUCP mailer at the other end can handle @@ -513,7 +517,7 @@ fax Facsimile transmission. This is experimental and based on Sam Leffler's HylaFAX software. For more information, - see http://www.vix.com/hylafax/. + see http://www.hylafax.org/. pop Post Office Protocol. @@ -623,8 +627,10 @@ given as parameter. nocanonify Don't pass addresses to $[ ... $] for canonification - by default. It can be changed by setting the - DaemonPortOptions modifiers (M=). That is, + by default, i.e., host/domain names are considered canonical, + except for unqualified names, which must not be used in this + mode (violation of the standard). It can be changed by + setting the DaemonPortOptions modifiers (M=). That is, FEATURE(`nocanonify') will be overridden by setting the 'c' flag. Conversely, if FEATURE(`nocanonify') is not used, it can be emulated by setting the 'C' flag @@ -656,14 +662,22 @@ , will be canonified (and hopefully fully qualified), too. -stickyhost If set, email sent to "user@local.host" are marked - as "sticky" -- that is, the local addresses aren't - matched against UDB and don't go through ruleset 5. - This is used if you want a set up where "user" is - not necessarily the same as "user@local.host", e.g., - to make a distinct domain-wide namespace. Prior to - 8.7 this was the default, and notsticky was used to - turn this off. +stickyhost This feature is sometimes used with LOCAL_RELAY, + although it can be used for a different effect with + MAIL_HUB. + + When used without MAIL_HUB, email sent to + "user@local.host" are marked as "sticky" -- that + is, the local addresses aren't matched against UDB, + don't go through ruleset 5, and are not forwarded to + the LOCAL_RELAY (if defined). + + With MAIL_HUB, mail addressed to "user@local.host" + is forwarded to the mail hub, with the envelope + address still remaining "user@local.host". + Without stickyhost, the envelope would be changed + to "user@mail_hub", in order to protect against + mailing loops. mailertable Include a "mailer table" which can be used to override routing for particular domains (which are not in class {w}, @@ -966,12 +980,13 @@ promiscuous_relay By default, the sendmail configuration files do not permit mail relaying (that is, accepting mail from outside your - domain and sending it to another host outside your domain). - This option sets your site to allow mail relaying from any - site to any site. In general, it is better to control the - relaying more carefully with the access db and class {R}. - Domains can be added to class {R} by the macros RELAY_DOMAIN - or RELAY_DOMAIN_FILE (analogously to MASQUERADE_DOMAIN and + local host (class {w}) and sending it to another host than + your local host). This option sets your site to allow + mail relaying from any site to any site. In almost all + cases, it is better to control relaying more carefully + with the access map, class {R}, or authentication. Domains + can be added to class {R} by the macros RELAY_DOMAIN or + RELAY_DOMAIN_FILE (analogously to MASQUERADE_DOMAIN and MASQUERADE_DOMAIN_FILE, see below). relay_entire_domain @@ -1003,11 +1018,15 @@ FEATURE(`loose_relay_check'). relay_mail_from - Allows relaying if the mail sender is listed as RELAY in the - access map. If an optional argument `domain' is given, the - domain portion of the mail sender is checked too. This - should only be used if absolutely necessary as the sender - address can be easily forged. + Allows relaying if the mail sender is listed as RELAY in + the access map. If an optional argument `domain' is given, + the domain portion of the mail sender is checked too. + This should only be used if absolutely necessary as the + sender address can be easily forged. Use of this feature + requires the "From:" tag be prepended to the key in the + access map; see the discussion of tags and + FEATURE(`relay_mail_from') in the section on ANTI-SPAM + CONFIGURATION CONTROL. relay_local_from Allows relaying if the domain portion of the mail sender @@ -1059,6 +1078,12 @@ described in the anti-spam configuration control section later in this document. +delay_checks The rulesets check_mail and check_relay will not be called + when a client connects or issues a MAIL command, respectively. + Instead, those rulesets will be called by the check_rcpt + ruleset; they will be skipped under certain circumstances. + See "Delay all checks" in "ANTI-SPAM CONFIGURATION CONTROL". + rbl This feature is deprecated! Please use dnsbl instead. Turns on rejection of hosts found in the Realtime Blackhole List. If an argument is provided it is used as the domain @@ -1069,13 +1094,13 @@ dnsbl Turns on rejection of hosts found in an DNS based rejection list. If an argument is provided it is used as the domain in which blocked hosts are listed; otherwise it defaults to - rbl.maps.vix.com. An explanation for an DNS based rejection - list can be found http://maps.vix.com/rbl/. A second argument - can be used to change the default error message of - Mail from $&{client_addr} refused by blackhole site SERVER - where SERVER is replaced by the first argument. This feature - can be included several times to query different DNS based - rejection lists. + blackholes.mail-abuse.org. An explanation for an DNS based + rejection list can be found http://mail-abuse.org/rbl/. A + second argument can be used to change the default error + message of Mail from $&{client_addr} refused by blackhole site + SERVER where SERVER is replaced by the first argument. This + feature can be included several times to query different DNS + based rejection lists. loose_relay_check Normally, if % addressing is used for a recipient, e.g. @@ -1118,15 +1143,6 @@ lists of UUCP hosts they speak with directly. This can get a bit more tricky. For an example of a "complex" site, see cf/ucbvax.mc. -If your host is known by several different names, you need to augment -class {w}. This is a list of names by which you are known, and -anything sent to an address using a host name in this list will be -treated as local mail. You can do this in two ways: either create the -file /etc/mail/local-host-names containing a list of your aliases (one per -line), and use ``FEATURE(`use_cw_file')'' in the .mc file, or add -``LOCAL_DOMAIN(`alias.host.name')''. Be sure you use the fully-qualified -name of the host, rather than a short name. - The SITECONFIG macro allows you to indirectly reference site-dependent configuration information stored in the siteconfig subdirectory. For example, the line @@ -1231,7 +1247,7 @@ On host grasp.insa-lyon.fr (UUCP host name "grasp"), the following summarizes the sender rewriting for various mailers. -Mailer sender rewriting in the envelope +Mailer sender rewriting in the envelope ------ ------ ------------------------- uucp-{old,new} wolf grasp!wolf uucp-dom wolf wolf@grasp.insa-lyon.fr @@ -1569,14 +1585,20 @@ * Access database. * Header checks. -Relaying (transmission of messages from a site outside your domain to -another site outside your domain) is denied by default. Note that -this changed in sendmail 8.9; previous versions allowed relaying by -default. If you want to revert to the old behaviour, you will need -to use FEATURE(`promiscuous_relay'). You can allow certain domains to -relay through your server by adding their domain name or IP address to -class {R} using RELAY_DOMAIN() and RELAY_DOMAIN_FILE() or via the -access database (described below). +Relaying (transmission of messages from a site outside your host (class +{w}) to another site except yours) is denied by default. Note that this +changed in sendmail 8.9; previous versions allowed relaying by default. +If you really want to revert to the old behaviour, you will need to use +FEATURE(`promiscuous_relay'). You can allow certain domains to relay +through your server by adding their domain name or IP address to class +{R} using RELAY_DOMAIN() and RELAY_DOMAIN_FILE() or via the access database +(described below). The file consists (like any other file based class) +of entries listed on separate lines, e.g., + + sendmail.org + 128.32 + 1:2:3:4:5:6:7 + host.mydomain.com If you use @@ -1704,15 +1726,14 @@ REJECT Reject the sender or recipient with a general purpose message. DISCARD Discard the message completely using the - $#discard mailer. For sender addresses it - indicates that you should discard anything - received from the indicated domain. If it - is used for recipients, it affects only - the designated recipients, not the whole - message. - ### any text where ### is an RFC 821 compliant error code - and "any text" is a message to return for - the command. + $#discard mailer. If it is used in check_compat, + it affects only the designated recipient, not + the whole message as it does in all other cases. + This should only be used if really necessary. + ### any text where ### is an RFC 821 compliant error code and + "any text" is a message to return for the command. + The string should be quoted to avoid surprises, + e.g., sendmail may remove spaces otherwise. ERROR:### any text as above, but useful to mark error messages as such. ERROR:D.S.N:### any text @@ -1721,7 +1742,7 @@ For example: - cyberspammer.com 550 We don't accept mail from spammers + cyberspammer.com ERROR:"550 We don't accept mail from spammers" okay.cyberspammer.com OK sendmail.org RELAY 128.32 RELAY @@ -1759,7 +1780,7 @@ You can also use the access database to block sender addresses based on the username portion of the address. For example: - FREE.STEALTH.MAILER@ 550 Spam not accepted + FREE.STEALTH.MAILER@ ERROR:550 Spam not accepted Note that you must include the @ after the username to signify that this database entry is for checking only the username portion of the @@ -1772,9 +1793,9 @@ then you can add entries to the map for local users, hosts in your domains, or addresses in your domain which should not receive mail: - badlocaluser@ 550 Mailbox disabled for this username - host.mydomain.com 550 That host does not accept mail - user@otherhost.mydomain.com 550 Mailbox disabled for this recipient + badlocaluser@ ERROR:550 Mailbox disabled for this username + host.mydomain.com ERROR:550 That host does not accept mail + user@otherhost.mydomain.com ERROR:550 Mailbox disabled for this recipient This would prevent a recipient of badlocaluser@mydomain.com, any user at host.mydomain.com, and the single address @@ -1800,12 +1821,15 @@ This will cause sendmail to reject mail from any site in the Realtime Blackhole List database. You can specify an alternative RBL domain to check by specifying an argument to the FEATURE. -A second argument can be used to change the default error message -Mail from $&{client_addr} refused by blackhole site DOMAIN -where DOMAIN is replaced by the first argument. This FEATURE can -be included several times to query different DNS based rejection -lists, e.g., the dial-up user list (see http://maps.vix.com/dul/). +The default error message is + + Mail from $&{client_addr} refused by blackhole site DOMAIN +where DOMAIN is the first argument of the feature. A second argument +can be used to specify a different text. This FEATURE can be +included several times to query different DNS based rejection lists, +e.g., the dial-up user list (see http://maps.vix.com/dul/). + The features described above make use of the check_relay, check_mail, and check_rcpt rulesets. If you wish to include your own checks, you can put your checks in the rulesets Local_check_relay, @@ -1837,8 +1861,8 @@ access map according to their type. Three tags are available: Connect: connection information (${client_addr}, ${client_name}) - From: sender - To: recipient + From: envelope sender + To: envelope recipient If the required item is looked up in a map, it will be tried first with the corresponding tag in front, then (as fallback to enable @@ -1871,10 +1895,32 @@ respectively. Instead, those rulesets will be called by the check_rcpt ruleset; they will be skipped if a sender has been authenticated using a "trusted" mechanism, i.e., one that is defined via TRUST_AUTH_MECH(). -Moreover, an argument can be specified for this option: - - friend: enable spamfriend test - hater: enable spamhater test +If check_mail returns an error then the RCPT TO command will be rejected +with that error. If it returns some other result starting with $# then +check_relay will be skipped. If the sender address (or a part of it) is +listed in the access map and it has a RHS of OK or RELAY, then check_relay +will be skipped. This has an interesting side effect: if your domain is +my.domain and you have + + my.domain RELAY + +in the access map, then all e-mail with a sender address of + gets through, even if check_relay would reject it +(e.g., based on the hostname or IP address). This allows spammers +to get around DNS based blacklist by faking the sender address. To +avoid this problem you have to use tagged entries: + + To:my.domain RELAY + Connect:my.domain RELAY + +if you need those entries at all (class {R} may take care of them). + +FEATURE(`delay_checks') can take an optional argument: + + FEATURE(`delay_checks', `friend') + enables spamfriend test + FEATURE(`delay_checks', `hater') + enables spamhater test If such an argument is given, the recipient will be looked up in the access map (using the tag To:). If the argument is `friend', then the other @@ -1921,6 +1967,11 @@ H*: $>CheckHdr +Notice: All rules act on tokens as explained in doc/op/op.{me,ps,txt}. +That may cause problems with simple header checks due to the +tokenization. It might be simpler to use a regex map and apply it +to $&{currHeader}. + After all of the headers are read, the check_eoh ruleset will be called for any final header-related checks. The ruleset is called with the number of headers and the size of all of the headers in bytes separated by $|. One @@ -1955,10 +2006,144 @@ # Otherwise, reject the mail R$* $#error $: 553 Header Error -+--------------------------------+ -| SMTP AUTHENTICATION | -+--------------------------------+ ++----------+ +| STARTTLS | ++----------+ + +In this text, cert will be used as an abreviation for X.509 certificate, +DN is the distinguished name of a cert, and CA is a certification authority. + +Macros related to STARTTLS are: + +${cert_issuer} holds the DN of the CA (the cert issuer). +${cert_subject} holds the DN of the cert (called the cert subject). +${tls_version} the TLS/SSL version used for the connection, e.g., TLSv1, + SSLv3, SSLv2. +${cipher} the cipher used for the connection, e.g., EDH-DSS-DES-CBC3-SHA, + EDH-RSA-DES-CBC-SHA, DES-CBC-MD5, DES-CBC3-SHA. +${cipher_bits} the keylength (in bits) of the symmetric encryption algorithm + used for the connection. +${verify} holds the result of the verification of the presented cert. Possible + values are: + OK verification succeeded. + NO no cert presented. + FAIL cert presented but could not be verified, e.g., the signing + CA is missing. + NONE STARTTLS has not been performed. + TEMP temporary error occurred. + PROTOCOL some protocol error occurred. + SOFTWARE STARTTLS handshake failed. +${server_name} the name of the server of the current outgoing SMTP + connection. +${server_addr} the address of the server of the current outgoing SMTP + connection. + +Relaying + +SMTP STARTTLS can allow relaying for senders who have successfully +authenticated themselves. This is done in the ruleset RelayAuth. If the +verification of the cert failed (${verify} != OK), relaying is subject to +the usual rules. Otherwise the DN of the issuer is looked up in the access +map using the tag CERTISSUER. If the resulting value is RELAY, relaying is +allowed. If it is SUBJECT, the DN of the cert subject is looked up next in +the access map. using the tag CERTSUBJECT. If the value is RELAY, relaying +is allowed. + +To make things a bit more flexible (or complicated), the values for +${cert_issuer} and ${cert_subject} can be optionally modified by regular +expressions defined in the m4 variables _CERT_REGEX_ISSUER_ and +_CERT_REGEX_SUBJECT_, respectively. To avoid problems with those macros in +rulesets and map lookups, they are modified as follows: each non-printable +character and the characters '<', '>', '(', ')', '"', '+' are replaced by +their HEX value with a leading '+'. For example: + +/C=US/ST=California/O=endmail.org/OU=private/CN=Darth Mail (Cert)/Email= +darth+cert@endmail.org + +is encoded as: + +/C=US/ST=California/O=endmail.org/OU=private/CN= +Darth+20Mail+20+28Cert+29/Email=darth+2Bcert@endmail.org + +(line breaks have been inserted for readability). + +Of course it is also possible to write a simple rulesets that allows +relaying for everyone who can present a cert that can be verified, e.g., + +LOCAL_RULESETS +SLocal_check_rcpt +R$* $: $&{verify} +ROK $# OK + +Allowing Connections + +The rulesets tls_server and tls_client are used to decide whether an SMTP +connection is accepted (or should continue). + +tls_server is called when sendmail acts as client after a STARTTLS command +(should) have been issued. The parameter is the value of ${verify}. + +tls_client is called when sendmail acts as server, after a STARTTLS command +has been issued, and from check_mail. The parameter is the value of +${verify} and STARTTLS or MAIL, respectively. + +Both rulesets behave the same. If no access map is in use, the connection +will be accepted unless ${verify} is SOFTWARE, in which case the connection +is always aborted. Otherwise, ${client_name} (${server_name}) is looked +up in the access map using the tag TLS_Srv (or TLS_Clt), which is done +with the ruleset LookUpDomain. If no entry is found, ${client_addr} +(${server_addr}) is looked up in the access map (same tag, ruleset +LookUpAddr). If this doesn't result in an entry either, just the tag is +looked up in the access map (included the trailing :). The result of the +lookups is then used to call the ruleset tls_connection, which checks the +requirement specified by the RHS in the access map against the actual +parameters of the current TLS connection, esp. ${verify} and +${cipher_bits}. Legal RHSs in the access map are: + +VERIFY verification must have succeeded +VERIFY:bits verification must have succeeded and ${cipher_bits} must + be greater than or equal bits. +ENCR:bits ${cipher_bits} must be greater than or equal bits. +The RHS can optionally be prefixed by TEMP+ or PERM+ to select a temporary +or permanent error. The default is a temporary error code (403 4.7.0) +unless the macro TLS_PERM_ERR is set during generation of the .cf file. + +If a certain level of encryption is required, then it might also be +possible that this level is provided by the security layer from a SASL +algorithm, e.g., DIGEST-MD5. + +Example: e-mail send to secure.example.com should only use an encrypted +connection. e-mail received from hosts within the laptop.example.com domain +should only be accepted if they have been authenticated. +TLS_Srv:secure.example.com ENCR:112 +TLS_Clt:laptop.example.com PERM+VERIFY:112 + +Notice: requiring that e-mail is sent to a server only encrypted, +e.g., via + +TLS_Srv:secure.domain ENCR:112 + +doesn't necessarily mean that e-mail sent to that domain is encrypted. +If the domain has multiple MX servers, e.g., + +secure.domain. IN MX 10 mail.secure.domain. +secure.domain. IN MX 50 mail.other.domain. + +then mail to user@secure.domain may go unencrypted to mail.other.domain. + + +Received: Header + +The Received: header reveals whether STARTTLS has been used. It contains an +extra line: + +(using ${tls_version} with cipher ${cipher} (${cipher_bits} bits) verified ${verify}) + ++---------------------+ +| SMTP AUTHENTICATION | ++---------------------+ + The macros ${auth_authen}, ${auth_author}, and ${auth_type} can be used in anti-relay rulesets to allow relaying for those users that authenticated themselves. A very simple example is: @@ -1989,6 +2174,12 @@ Per default, relaying is allowed for any user who authenticated via a "trusted" mechanism, i.e., one that is defined via TRUST_AUTH_MECH(`list of mechanisms') +For example: +TRUST_AUTH_MECH(`KERBEROS_V4 DIGEST-MD5') + +If the selected mechanism provides a security layer the number of +bits used for the key of the symmetric cipher is stored in the +macro ${auth_ssf}. +--------------------------------+ | ADDING NEW MAILERS OR RULESETS | @@ -2008,9 +2199,9 @@ #if _FFR_MILTER -+---------------------------+ -| ADDING NEW MAILER FILTERS | -+---------------------------+ ++-------------------------+ +| ADDING NEW MAIL FILTERS | ++-------------------------+ Sendmail supports mail filters to filter incoming SMTP messages according to the "Sendmail Mail Filter API" documentation. These filters can be @@ -2115,6 +2306,24 @@ define(`confDOMAIN_NAME', `$w.$m')dnl ++-----------------------------------+ +| ACCEPTING MAIL FOR MULTIPLE NAMES | ++-----------------------------------+ + +If your host is known by several different names, you need to augment +class {w}. This is a list of names by which your host is known, and +anything sent to an address using a host name in this list will be +treated as local mail. You can do this in two ways: either create the +file /etc/mail/local-host-names containing a list of your aliases (one per +line), and use ``FEATURE(`use_cw_file')'' in the .mc file, or add +``LOCAL_DOMAIN(`alias.host.name')''. Be sure you use the fully-qualified +name of the host, rather than a short name. + +If you want to have different address in different domains, take +a look at the virtusertable feature, which is also explained at +http://www.sendmail.org/virtual-hosting.html + + +--------------------+ | USING MAILERTABLES | +--------------------+ @@ -2134,13 +2343,15 @@ The semantics are simple. Any LHS entry that does not begin with a dot matches the full host name indicated. LHS entries beginning -with a dot match anything ending with that domain name -- that is, -they can be thought of as having a leading "*" wildcard. Matching -is done in order of most-to-least qualified -- for example, even -though ".my.domain" is listed first in the above example, an entry -of "uuhost1.my.domain" will match the second entry since it is -more explicit. Note: e-mail to "user@my.domain" does not match -any entry in the above table. You need to have something like: +with a dot match anything ending with that domain name (including +the leading dot) -- that is, they can be thought of as having a +leading ".+" regular expression pattern for a non-empty sequence of +characters. Matching is done in order of most-to-least qualified +-- for example, even though ".my.domain" is listed first in the +above example, an entry of "uuhost1.my.domain" will match the second +entry since it is more explicit. Note: e-mail to "user@my.domain" +does not match any entry in the above table. You need to have +something like: my.domain esmtp:host.my.domain @@ -2190,7 +2401,7 @@ As a general rule, it is an extremely bad idea to using full names as e-mail addresses, since they are not in any sense unique. For -example, the Unix software-development community has at least two +example, the UNIX software-development community has at least two well-known Peter Deutsches, and at one time Bell Labs had two Stephen R. Bournes with offices along the same hallway. Which one will be forced to suffer the indignity of being Stephen_R_Bourne_2? @@ -2587,7 +2798,7 @@ rejected. If not set or <= 0, there is no limit. confMAX_HEADERS_LENGTH MaxHeadersLength - [undefined] Maximum length of the sum + [32768] Maximum length of the sum of all headers. confMAX_MIME_HEADER_LENGTH MaxMimeHeaderLength [undefined] Maximum length of @@ -2788,7 +2999,7 @@ intersection of this list and the list of available mechanisms as determined by the CYRUS SASL library. -confDEF_AUTH_INFO DefaultAuthInfo [undefined] Filename that contains +confDEF_AUTH_INFO DefaultAuthInfo [undefined] Name of file that contains authentication information for outgoing connections. This file must contain the user id, the @@ -2829,6 +3040,33 @@ maps unless they are specified in the individual map specification ('K' command). +confCACERT_PATH CACERTPath [undefined] Path to directory + with certs of CAs. +confCACERT CACERTFile [undefined] File containing one CA + cert. +confSERVER_CERT ServerCertFile [undefined] File containing the + cert of the server, i.e., this cert + is used when sendmail acts as + server. +confSERVER_KEY ServerKeyFile [undefined] File containing the + private key belonging to the server + cert. +confCLIENT_CERT ClientCertFile [undefined] File containing the + cert of the client, i.e., this cert + is used when sendmail acts as + client. +confCLIENT_KEY ClientKeyFile [undefined] File containing the + private key belonging to the client + cert. +confDH_PARAMETERS DHParameters [undefined] File containing the + DH parameters. +confRAND_FILE RandFile [undefined] File containing random + data (use prefix file:) or the + name of the UNIX socket if EGD is + used (use prefix egd:). STARTTLS + requires this option if the compile + flag HASURANDOM is not set (see + sendmail/README). See also the description of OSTYPE for some parameters that can be tweaked (generally pathnames to mailers). @@ -2863,6 +3101,11 @@ Note that if the first of those DAEMON_OPTIONS lines were omitted, then there would be no listener on the standard SMTP port. +Example 3: To listen on both IPv4 and IPv6 interfaces, use + + DAEMON_OPTIONS(`Name=MTA-v4, Family=inet') + DAEMON_OPTIONS(`Name=MTA-v6, Family=inet6') + A "Message Submission Agent" still uses all of the same rulesets for processing the message (and therefore still allows message rejection via the check_* rulesets). In accordance with the RFC, the MSA will ensure @@ -2870,6 +3113,7 @@ relayed to another MTA. It will also enforce the normal address syntax rules and log error messages. Additionally, by using the M=a modifier you can require authentication before messages are accepted by the MSA. +Notice: Do NOT use the 'a' modifier on a public accessible MTA! Finally, the M=E modifier shown above disables ETRN as required by RFC 2476. @@ -2900,7 +3144,7 @@ site dependent; for example, "CS.Berkeley.EDU.m4" describes hosts in the CS.Berkeley.EDU subdomain. -mailer Descriptions of mailers. These are referenced using +mailer Descriptions of mailers. These are referenced using the MAILER macro in the .mc file. sh Shell files used when building the .cf file from the @@ -3034,4 +3278,4 @@ 8 DNS based blacklists 9 special local rulesets (1 and 2) -$Revision: 1.3 $, Last updated $Date: 2000/04/07 19:20:28 $ +$Revision: 1.6 $, Last updated $Date: 2001/05/29 01:31:10 $ Index: gnu/usr.sbin/sendmail/cf/cf/Makefile =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/cf/Makefile,v retrieving revision 1.6 retrieving revision 1.10 diff -u -r1.6 -r1.10 --- gnu/usr.sbin/sendmail/cf/cf/Makefile 2000/06/18 03:13:08 1.6 +++ gnu/usr.sbin/sendmail/cf/cf/Makefile 2001/05/29 01:31:11 1.10 @@ -1,8 +1,8 @@ -# $OpenBSD: Makefile,v 1.6 2000/06/18 03:13:08 itojun Exp $ +# $OpenBSD: Makefile,v 1.10 2001/05/29 01:31:11 millert Exp $ # # Makefile for configuration files. # -# $Sendmail: Makefile,v 8.40 2000/02/01 22:07:15 gshapiro Exp $ +# $Sendmail: Makefile,v 8.40.8.5 2001/04/12 22:39:52 gshapiro Exp $ # # @@ -26,9 +26,8 @@ $(CHMOD) $(ROMODE) $@ ALL= clientproto.cf openbsd-proto.cf courtesan.cf courtesan-nonet.cf \ - courtesan-lists.cf openbsd-lists.cf gandalf.cf saruman.cf alatar.cf \ - nettan.cf waldorf.cf lucifier.cf elbereth.cf corpse.cf knecht.cf \ - openbsd-proto-IPv4only.cf + courtesan-lists.cf openbsd-lists.cf gandalf.cf alatar.cf \ + nettan.cf waldorf.cf lucifier.cf elbereth.cf corpse.cf knecht.cf all: $(ALL) @@ -37,11 +36,9 @@ depend install: -distribution: openbsd-proto.cf openbsd-proto-IPv4only.cf +distribution: openbsd-proto.cf ${INSTALL} ${INSTALL_COPY} -o root -g wheel -m 644 openbsd-proto.cf \ ${DESTDIR}/etc/mail/sendmail.cf - ${INSTALL} ${INSTALL_COPY} -o root -g wheel -m 644 \ - openbsd-proto-IPv4only.cf ${DESTDIR}/etc/mail/sendmail-IPv4only.cf # this is overkill, but.... M4FILES=\ @@ -113,7 +110,6 @@ ${CFDIR}/ostype/aix4.m4 \ ${CFDIR}/ostype/altos.m4 \ ${CFDIR}/ostype/amdahl-uts.m4 \ - ${CFDIR}/ostype/aux.m4 \ ${CFDIR}/ostype/bsd4.3.m4 \ ${CFDIR}/ostype/bsd4.4.m4 \ ${CFDIR}/ostype/bsdi.m4 \ Index: gnu/usr.sbin/sendmail/cf/cf/knecht.mc =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/cf/knecht.mc,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/cf/cf/knecht.mc 2000/04/02 19:05:51 1.1.1.1 +++ gnu/usr.sbin/sendmail/cf/cf/knecht.mc 2001/02/28 02:43:49 1.3 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998, 1999, 2001 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -17,8 +17,8 @@ # divert(0)dnl -VERSIONID(`$Sendmail: knecht.mc,v 8.37 1999/11/19 05:18:12 gshapiro Exp $') -OSTYPE(bsdi)dnl +VERSIONID(`$Sendmail: knecht.mc,v 8.37.16.3 2001/02/22 22:38:39 ca Exp $') +OSTYPE(bsd4.4)dnl DOMAIN(generic)dnl define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward+$h:$z/.forward')dnl define(`confDEF_USER_ID', `mailnull')dnl @@ -28,10 +28,16 @@ define(`confTO_QUEUEWARN', `8h')dnl define(`confTRUSTED_USERS', `www')dnl define(`confPRIVACY_FLAGS', ``authwarnings,noexpn,novrfy'')dnl +define(`CERT_DIR', `MAIL_SETTINGS_DIR`'certs')dnl +define(`confCACERT_PATH', `CERT_DIR')dnl +define(`confCACERT', `CERT_DIR/CAcert.pem')dnl +define(`confSERVER_CERT', `CERT_DIR/MYcert.pem')dnl +define(`confSERVER_KEY', `CERT_DIR/MYkey.pem')dnl +define(`confCLIENT_CERT', `CERT_DIR/MYcert.pem')dnl +define(`confCLIENT_KEY', `CERT_DIR/MYkey.pem')dnl FEATURE(virtusertable)dnl FEATURE(access_db)dnl FEATURE(local_lmtp)dnl -MODIFY_MAILER_FLAGS(`LOCAL', `+P')dnl MAILER(local)dnl MAILER(smtp)dnl @@ -61,7 +67,7 @@ SCheckMessageId R< $+ @ $+ > $@ OK -R$* $#error $: "553 Header error" +R$* $#error $: "554 Header error" LOCAL_RULESETS SLocal_check_mail Index: gnu/usr.sbin/sendmail/cf/cf/openbsd-proto.mc =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/cf/openbsd-proto.mc,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/cf/cf/openbsd-proto.mc 2000/06/18 00:14:40 1.2 +++ gnu/usr.sbin/sendmail/cf/cf/openbsd-proto.mc 2001/01/16 01:38:37 1.3 @@ -17,13 +17,13 @@ # divert(0)dnl -VERSIONID(`@(#)openbsd-proto.mc $Revision: 1.2 $') +VERSIONID(`@(#)openbsd-proto.mc $Revision: 1.3 $') OSTYPE(openbsd) FEATURE(nouucp, `reject') MAILER(local) MAILER(smtp) DAEMON_OPTIONS(`Family=inet, address=0.0.0.0, Name=MTA')dnl -DAEMON_OPTIONS(`Family=inet6, address=::, Name=MTA6')dnl +DAEMON_OPTIONS(`Family=inet6, address=::, Name=MTA6, M=O')dnl dnl dnl Enforce valid Message-Id to help stop spammers dnl Index: gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 2000/04/02 19:05:52 1.1.1.1 +++ gnu/usr.sbin/sendmail/cf/feature/dnsbl.m4 2001/01/15 21:08:54 1.2 @@ -11,9 +11,9 @@ divert(0) ifdef(`_DNSBL_R_',`dnl',`dnl -VERSIONID(`$Sendmail: dnsbl.m4,v 8.18 1999/08/03 04:30:56 gshapiro Exp $')') +VERSIONID(`$Sendmail: dnsbl.m4,v 8.18.16.1 2000/11/22 01:13:21 ca Exp $')') divert(-1) -define(`_DNSBL_SRV_', `ifelse(len(X`'_ARG_),`1',`rbl.maps.vix.com',_ARG_)')dnl +define(`_DNSBL_SRV_', `ifelse(len(X`'_ARG_),`1',`blackholes.mail-abuse.org',_ARG_)')dnl define(`_DNSBL_MSG_', `ifelse(len(X`'_ARG2_),`1',`"550 Mail from " $`'&{client_addr} " refused by blackhole site '_DNSBL_SRV_`"',`_ARG2_')')dnl divert(8) # DNS based IP address spam list _DNSBL_SRV_ Index: gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 2000/04/02 19:05:53 1.1.1.1 +++ gnu/usr.sbin/sendmail/cf/feature/ldap_routing.m4 2001/01/15 21:08:55 1.2 @@ -10,7 +10,7 @@ # divert(0) -VERSIONID(`$Sendmail: ldap_routing.m4,v 8.5 2000/02/26 01:32:03 gshapiro Exp $') +VERSIONID(`$Sendmail: ldap_routing.m4,v 8.5.4.1 2000/07/15 18:05:05 gshapiro Exp $') divert(-1) # Check first two arguments. If they aren't set, may need to warn in proto.m4 @@ -25,10 +25,10 @@ LOCAL_CONFIG # LDAP routing maps -Kldap_mailhost ifelse(len(X`'_ARG1_), `1', - `ldap -1 -v mailHost -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', - `_ARG1_') +Kldapmh ifelse(len(X`'_ARG1_), `1', + `ldap -1 -v mailHost -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', + `_ARG1_') -Kldap_mailroutingaddress ifelse(len(X`'_ARG2_), `1', - `ldap -1 -v mailRoutingAddress -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', - `_ARG2_') +Kldapmra ifelse(len(X`'_ARG2_), `1', + `ldap -1 -v mailRoutingAddress -k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))', + `_ARG2_') Index: gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/feature/nullclient.m4,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 2000/04/02 19:05:53 1.1.1.1 +++ gnu/usr.sbin/sendmail/cf/feature/nullclient.m4 2001/01/15 21:08:55 1.2 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -22,13 +22,15 @@ # divert(0) -VERSIONID(`$Sendmail: nullclient.m4,v 8.21 1999/08/06 01:48:57 gshapiro Exp $') +VERSIONID(`$Sendmail: nullclient.m4,v 8.21.16.3 2000/09/17 17:04:22 gshapiro Exp $') divert(-1) undefine(`ALIAS_FILE') define(`MAIL_HUB', _NULL_CLIENT_) define(`SMART_HOST', _NULL_CLIENT_) define(`confFORWARD_PATH', `') +ifdef(`confFROM_HEADER',, `define(`confFROM_HEADER', `<$g>')') +define(`_DEF_LOCAL_MAILER_FLAGS', `lsDFM5q') MASQUERADE_AS(_NULL_CLIENT_) FEATURE(`allmasquerade') FEATURE(`masquerade_envelope') Index: gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/m4/cfhead.m4,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 2000/04/07 19:20:30 1.2 +++ gnu/usr.sbin/sendmail/cf/m4/cfhead.m4 2001/05/29 01:31:11 1.5 @@ -1,5 +1,5 @@ # -# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -16,10 +16,11 @@ ##### ##### SENDMAIL CONFIGURATION FILE ##### -define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl +ifdef(`unix', `dnl +ifdef(`TEMPFILE', `dnl', `define(`TEMPFILE', maketemp(/tmp/cfXXXXXX))dnl syscmd(sh _CF_DIR_`'sh/makeinfo.sh _CF_DIR_ > TEMPFILE)dnl include(TEMPFILE)dnl -syscmd(rm -f TEMPFILE)dnl +syscmd(rm -f TEMPFILE)dnl')', `dnl') ##### ###################################################################### ###################################################################### @@ -153,26 +154,28 @@ CONCAT(CY, $'1`), CONCAT(C, $3, $'1`))') sinclude(_CF_DIR_`'siteconfig/$1.m4)') -define(`EXPOSED_USER', `PUSHDIVERT(5)CE$1 +define(`EXPOSED_USER', `PUSHDIVERT(5)C{E}$1 POPDIVERT`'dnl`'') -define(`LOCAL_USER', `PUSHDIVERT(5)CL$1 +ifdef(`_FFR_EXPOSED_USER_FILE', `define(`EXPOSED_USER_FILE', `PUSHDIVERT(5)F{E}$1 +POPDIVERT`'dnl`'')', `dnl') +define(`LOCAL_USER', `PUSHDIVERT(5)C{L}$1 POPDIVERT`'dnl`'') define(`MASQUERADE_AS', `define(`MASQUERADE_NAME', $1)') -define(`MASQUERADE_DOMAIN', `PUSHDIVERT(5)CM$1 +define(`MASQUERADE_DOMAIN', `PUSHDIVERT(5)C{M}$1 POPDIVERT`'dnl`'') -define(`MASQUERADE_EXCEPTION', `PUSHDIVERT(5)CN$1 +define(`MASQUERADE_EXCEPTION', `PUSHDIVERT(5)C{N}$1 POPDIVERT`'dnl`'') -define(`MASQUERADE_DOMAIN_FILE', `PUSHDIVERT(5)FM$1 +define(`MASQUERADE_DOMAIN_FILE', `PUSHDIVERT(5)F{M}$1 POPDIVERT`'dnl`'') -define(`LOCAL_DOMAIN', `PUSHDIVERT(5)Cw$1 +define(`LOCAL_DOMAIN', `PUSHDIVERT(5)C{w}$1 POPDIVERT`'dnl`'') define(`CANONIFY_DOMAIN', `PUSHDIVERT(5)C{Canonify}$1 POPDIVERT`'dnl`'') define(`CANONIFY_DOMAIN_FILE', `PUSHDIVERT(5)F{Canonify}$1 POPDIVERT`'dnl`'') -define(`GENERICS_DOMAIN', `PUSHDIVERT(5)CG$1 +define(`GENERICS_DOMAIN', `PUSHDIVERT(5)C{G}$1 POPDIVERT`'dnl`'') -define(`GENERICS_DOMAIN_FILE', `PUSHDIVERT(5)FG$1 +define(`GENERICS_DOMAIN_FILE', `PUSHDIVERT(5)F{G}$1 POPDIVERT`'dnl`'') define(`LDAPROUTE_DOMAIN', `PUSHDIVERT(5)C{LDAPRoute}$1 POPDIVERT`'dnl`'') @@ -184,9 +187,9 @@ define(`VIRTUSER_DOMAIN_FILE', `PUSHDIVERT(5)F{VirtHost}$1 define(`_VIRTHOSTS_') POPDIVERT`'dnl`'') -define(`RELAY_DOMAIN', `PUSHDIVERT(5)CR$1 +define(`RELAY_DOMAIN', `PUSHDIVERT(5)C{R}$1 POPDIVERT`'dnl`'') -define(`RELAY_DOMAIN_FILE', `PUSHDIVERT(5)FR$1 +define(`RELAY_DOMAIN_FILE', `PUSHDIVERT(5)F{R}$1 POPDIVERT`'dnl`'') define(`TRUST_AUTH_MECH', `PUSHDIVERT(5)C{TrustAuthMech}$1 POPDIVERT`'dnl`'') @@ -212,12 +215,14 @@ define(`_REC_HDR_', `$?sfrom $s $.$?_($?s$|from $.$_)') define(`_REC_END_', `for $u; $|; $.$b') +define(`_REC_TLS_', `(using ${tls_version} with cipher ${cipher} (${cipher_bits} bits) verified ${verify})$.$?u') +define(`_REC_BY_', `$.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}') define(`confRECEIVED_HEADER', `_REC_HDR_ - _REC_AUTH_) - $.by $j ($v/$Z)$?r with $r$. id $i$?u + _REC_AUTH_$?{auth_ssf} (${auth_ssf} bits)$.) + _REC_BY_ + _REC_TLS_ _REC_END_') define(`confSEVEN_BIT_INPUT', `False') -define(`confEIGHT_BIT_HANDLING', `pass8') define(`confALIAS_WAIT', `10') define(`confMIN_FREE_BLOCKS', `100') define(`confBLANK_SUB', `.') @@ -240,9 +245,10 @@ define(`confFORWARD_PATH', `$z/.forward.$w:$z/.forward') define(`confCR_FILE', `-o MAIL_SETTINGS_DIR`'relay-domains') define(`confMILTER_MACROS_CONNECT', ``j, _, {daemon_name}, {if_name}, {if_addr}'') -define(`confMILTER_MACROS_ENVFROM', ``i, {auth_type}, {auth_authen}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr}'') +define(`confMILTER_MACROS_HELO', ``{tls_version}, {cipher}, {cipher_bits}, {cert_subject}, {cert_issuer}'') +define(`confMILTER_MACROS_ENVFROM', ``i, {auth_type}, {auth_authen}, {auth_ssf}, {auth_author}, {mail_mailer}, {mail_host}, {mail_addr}'') define(`confMILTER_MACROS_ENVRCPT', ``{rcpt_mailer}, {rcpt_host}, {rcpt_addr}'') divert(0)dnl -VERSIONID(`$Sendmail: cfhead.m4,v 8.76 2000/03/21 23:56:59 gshapiro Exp $') +VERSIONID(`$Sendmail: cfhead.m4,v 8.76.4.16 2001/03/06 22:56:36 ca Exp $') Index: gnu/usr.sbin/sendmail/cf/m4/proto.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/m4/proto.m4,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/cf/m4/proto.m4 2000/04/07 19:20:30 1.2 +++ gnu/usr.sbin/sendmail/cf/m4/proto.m4 2001/05/29 01:31:11 1.4 @@ -13,7 +13,7 @@ # divert(0) -VERSIONID(`$Sendmail: proto.m4,v 8.446 2000/04/06 06:29:45 gshapiro Exp $') +VERSIONID(`$Sendmail: proto.m4,v 8.446.2.5.2.41 2001/05/23 21:32:16 ca Exp $') MAILER(local)dnl @@ -77,6 +77,7 @@ define(`_U_',ifdef(`_DELAY_CHECKS_',`',`_')) dnl default relaying denied message ifdef(`confRELAY_MSG', `', `define(`confRELAY_MSG', `"550 Relaying denied"')') +define(`CODE553', `553') divert(0)dnl # override file safeties - setting this option compromises system security, @@ -160,11 +161,31 @@ # Resolve map (to check if a host exists in check_mail) Kresolve host -a -T') +ifdef(`_FFR_5_', `# macro storage map +Kmacro macro') + ifdef(`confCR_FILE', `dnl -# Hosts that will permit relaying ($=R) +# Hosts for which relaying is permitted ($=R) FR`'confCR_FILE', `dnl') +define(`TLS_SRV_TAG', `TLS_Srv')dnl +define(`TLS_CLT_TAG', `TLS_Clt')dnl +define(`TLS_TRY_TAG', `Try_TLS')dnl +define(`TLS_OFF_TAG', `Offer_TLS')dnl +dnl this may be useful in other contexts too +ifdef(`_ARITH_MAP_', `', `# arithmetic map +define(`_ARITH_MAP_', `1')dnl +Karith arith') +ifdef(`_ACCESS_TABLE_', `dnl +# possible values for tls_connect in access map +C{tls}VERIFY ENCR', `dnl') +ifdef(`_CERT_REGEX_ISSUER_', `dnl +# extract relevant part from cert issuer +KCERTIssuer regex _CERT_REGEX_ISSUER_', `dnl') +ifdef(`_CERT_REGEX_SUBJECT_', `dnl +# extract relevant part from cert subject +KCERTSubject regex _CERT_REGEX_SUBJECT_', `dnl') # who I send unqualified names to (null means deliver locally) DR`'ifdef(`LOCAL_RELAY', LOCAL_RELAY) @@ -201,7 +222,7 @@ _OPTION(SevenBitInput, `confSEVEN_BIT_INPUT', `False') # 8-bit data handling -_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `adaptive') +_OPTION(EightBitMode, `confEIGHT_BIT_HANDLING', `pass8') # wait for alias file rebuild (default units: minutes) _OPTION(AliasWait, `confALIAS_WAIT', `5m') @@ -297,7 +318,9 @@ `errprint(WARNING: `confDAEMON_OPTIONS' is no longer valid. See cf/README for more information. )'dnl `DAEMON_OPTIONS(`confDAEMON_OPTIONS')') -ifelse(defn(`_DPO_'), `', `O DaemonPortOptions=Name=MTA', `_DPO_') +ifelse(defn(`_DPO_'), `', +`ifdef(`_NETINET6_', `O DaemonPortOptions=Name=MTA-IPv4, Family=inet +O DaemonPortOptions=Name=MTA-IPv6, Family=inet6',`O DaemonPortOptions=Name=MTA')', `_DPO_') ifdef(`_NO_MSA_', `dnl', `O DaemonPortOptions=Port=587, Name=MSA, M=E') # SMTP client options @@ -387,7 +410,7 @@ _OPTION(MaxDaemonChildren, `confMAX_DAEMON_CHILDREN', `12') # maximum number of new connections per second -_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `3') +_OPTION(ConnectionRateThrottle, `confCONNECTION_RATE_THROTTLE', `0') # work recipient factor _OPTION(RecipientFactor, `confWORK_RECIPIENT_FACTOR', `30000') @@ -525,6 +548,22 @@ _OPTION(Milter.macros.envfrom, `confMILTER_MACROS_ENVFROM', `') _OPTION(Milter.macros.envrcpt, `confMILTER_MACROS_ENVRCPT', `')') +# CA directory +_OPTION(CACERTPath, `confCACERT_PATH', `') +# CA file +_OPTION(CACERTFile, `confCACERT', `') +# Server Cert +_OPTION(ServerCertFile, `confSERVER_CERT', `') +# Server private key +_OPTION(ServerKeyFile, `confSERVER_KEY', `') +# Client Cert +_OPTION(ClientCertFile, `confCLIENT_CERT', `') +# Client private key +_OPTION(ClientKeyFile, `confCLIENT_KEY', `') +# DHParameters (only required if DSA/DH is used) +_OPTION(DHParameters, `confDH_PARAMETERS', `') +# Random data source (required for systems without /dev/urandom under OpenSSL) +_OPTION(RandFile, `confRAND_FILE', `') ifdef(`confQUEUE_FILE_MODE', `# queue file mode (qf files) @@ -597,6 +636,7 @@ R$* : $* <@> $: $2 strip colon if marked R$* <@> $: $1 unmark R$* ; $1 strip trailing semi +R$* < $+ :; > $* $@ $2 :; <@> catch R$* < $* ; > $1 < $2 > bogus bracketed semi # null input now results from list:; syntax @@ -741,6 +781,9 @@ R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl dnl _NO_CANONIFY_ is not set: canonify unless: dnl {daemon_flags} contains CC (do not canonify) +dnl but add a trailing dot to qualified hostnames so other rules will work +dnl should we do this for every hostname: even unqualified? +R$* CC $* $| $* < @ $+.$+ > $* $: $3 < @ $4.$5 . > $6 R$* CC $* $| $* $: $3 # pass to name server to make hostname canonical R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4') @@ -768,6 +811,7 @@ ################################################## Sfinal=4 +R$+ :; <@> $@ $1 : handle R$* <@> $@ handle <> and list:; # strip trailing dot off possibly canonical name @@ -824,24 +868,26 @@ SParse0 R<@> $@ <@> special case error msgs -R$* : $* ; <@> $#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses" +R$* : $* ; <@> $#error $@ 5.1.3 $: "CODE553 List:; syntax illegal for recipient addresses" R@ <@ $* > < @ $1 > catch "@@host" bogosity -R<@ $+> $#error $@ 5.1.3 $: "553 User address required" +R<@ $+> $#error $@ 5.1.3 $: "CODE553 User address required" R$* $: <> $1 R<> $* < @ [ $+ ] > $* $1 < @ [ $2 ] > $3 -R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "553 Colon illegal in host name part" +R<> $* <$* : $* > $* $#error $@ 5.1.3 $: "CODE553 Colon illegal in host name part" R<> $* $1 -R$* < @ . $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" -R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "553 Invalid host name" +R$* < @ . $* > $* $#error $@ 5.1.2 $: "CODE553 Invalid host name" +R$* < @ $* .. $* > $* $#error $@ 5.1.2 $: "CODE553 Invalid host name" +dnl comma only allowed before @; this check is not complete +R$* , $~O $* $#error $@ 5.1.2 $: "CODE553 Invalid route address" # now delete the local info -- note $=O to find characters that cause forwarding R$* < @ > $* $@ $>Parse0 $>canonify $1 user@ => user R< @ $=w . > : $* $@ $>Parse0 $>canonify $2 @here:... -> ... R$- < @ $=w . > $: $(dequote $1 $) < @ $2 . > dequote "foo"@here -R< @ $+ > $#error $@ 5.1.3 $: "553 User address required" +R< @ $+ > $#error $@ 5.1.3 $: "CODE553 User address required" R$* $=O $* < @ $=w . > $@ $>Parse0 $>canonify $1 $2 $3 ...@here -> ... R$- $: $(dequote $1 $) < @ *LOCAL* > dequote "foo" -R< @ *LOCAL* > $#error $@ 5.1.3 $: "553 User address required" +R< @ *LOCAL* > $#error $@ 5.1.3 $: "CODE553 User address required" R$* $=O $* < @ *LOCAL* > $@ $>Parse0 $>canonify $1 $2 $3 ...@*LOCAL* -> ... R$* < @ *LOCAL* > $: $1 @@ -890,12 +936,16 @@ R $+ $: $1 R< error : $-.$-.$- : $+ > $* $#error $@ $1.$2.$3 $: $4 R< error : $- $+ > $* $#error $@ $(dequote $1 $) $: $2 -R< $+ > $+ < @ $+ > $: $>Recurse $1', -`dnl') +ifdef(`_NO_VIRTUSER_RECURSION_', +`R< $+ > $+ < @ $+ > $: $>ParseLocal $>Parse0 $>canonify $1', +`R< $+ > $+ < @ $+ > $: $>Recurse $1') +dnl', `dnl') # short circuit local delivery so forwarded email works ifdef(`_MAILER_usenet_', `dnl R$+ . USENET < @ $=w . > $#usenet $@ usenet $: $1 handle usenet specially', `dnl') + + ifdef(`_STICKY_LOCAL_DOMAIN_', `R$+ < @ $=w . > $: < $H > $1 < @ $2 . > first try hub R< $+ > $+ < $+ > $>MailerToTriple < $1 > $2 < $3 > yep .... @@ -966,7 +1016,7 @@ # deal with other remote names ifdef(`_MAILER_smtp_', `R$* < @$* > $* $#_SMTP_ $@ $2 $: $1 < @ $2 > $3 user@host.domain', -`R$* < @$* > $* $#error $@ 5.1.2 $: "553 Unrecognized host name " $2') +`R$* < @$* > $* $#error $@ 5.1.2 $: "CODE553 Unrecognized host name " $2') # handle locally delivered names R$=L $#_LOCAL_ $: @ $1 special local names @@ -982,31 +1032,44 @@ R$+ $| $#$* $#$2 R$+ $| $* $: $1 -# deal with plussed users so aliases work nicely -R$+ + * $#_LOCAL_ $@ $&h $: $1 -R$+ + $* $#_LOCAL_ $@ + $2 $: $1 + * +ifdef(`_FFR_5_', ` +# Preserve host in a macro +R$+ $: $(macro {LocalAddrHost} $) $1 +R$+ @ $+ $: $(macro {LocalAddrHost} $@ @ $2 $) $1') +ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', `', ` +# deal with plussed users so aliases work nicely +R$+ + * $#_LOCAL_ $@ $&h $: $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') +R$+ + $* $#_LOCAL_ $@ + $2 $: $1 + *`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') +') # prepend an empty "forward host" on the front R$+ $: <> $1 ifdef(`LUSER_RELAY', `dnl # send unrecognized local users to a relay host +ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', ` +R< > $+ + $* $: < ? $L > <+ $2> $(user $1 $) look up user+ +R< > $+ $: < ? $L > < > $(user $1 $) look up user +R< ? $* > < $* > $+ <> $: < > $3 $2 found; strip $L +R< ? $* > < $* > $+ $: < $1 > $3 $2 not found', ` R< > $+ $: < $L > $(user $1 $) look up user -R< $* > $+ <> $: < > $2 found; strip $L', +R< $* > $+ <> $: < > $2 found; strip $L')', `dnl') # see if we have a relay or a hub R< > $+ $: < $H > $1 try hub R< > $+ $: < $R > $1 try relay +ifdef(`_PRESERVE_LOCAL_PLUS_DETAIL_', ` +R< > $+ $@ $1', ` R< > $+ $: < > < $1 <> $&h > nope, restore +detail R< > < $+ <> + $* > $: < > < $1 + $2 > check whether +detail R< > < $+ <> $* > $: < > < $1 > else discard R< > < $+ + $* > $* < > < $1 > + $2 $3 find the user part -R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1 strip the extra + +R< > < $+ > + $* $#_LOCAL_ $@ $2 $: @ $1`'ifdef(`_FFR_5_', ` $&{LocalAddrHost}') strip the extra + R< > < $+ > $@ $1 no +detail R$+ $: $1 <> $&h add +detail back in R$+ <> + $* $: $1 + $2 check whether +detail -R$+ <> $* $: $1 else discard +R$+ <> $* $: $1 else discard') R< local : $* > $* $: $>MailerToTriple < local : $1 > $2 no host extension R< error : $* > $* $: $>MailerToTriple < error : $1 > $2 no host extension R< $- : $+ > $+ $: $>MailerToTriple < $1 : $2 > $3 < @ $2 > @@ -1164,8 +1227,7 @@ ifdef(`_LDAP_ROUTING_', `dnl SLDAPExpand # do the LDAP lookups -R<$+><$+> - $: <$(ldap_mailroutingaddress $2 $: $)> <$(ldap_mailhost $2 $: $)> <$1> <$2> +R<$+><$+> $: <$(ldapmra $2 $: $)> <$(ldapmh $2 $: $)> <$1> <$2> # if mailRoutingAddress and local or non-existant mailHost, # return the new mailRoutingAddress @@ -1232,6 +1294,7 @@ dnl lookup IP address (no check is done whether it is an IP number!) R <[$+.$-]> <$+> <$*> <$*> $@ $>LookUpDomain <[$1]> <$3> <$4> <$5> dnl lookup IPv6 address +R <[$+::$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5> R <[$+:$-]> <$+> <$*> <$*> $: $>LookUpDomain <[$1]> <$3> <$4> <$5> dnl not found, but subdomain: try again R <$+.$+> <$+> <$*> <$*> $@ $>LookUpDomain <$2> <$3> <$4> <$5> @@ -1261,7 +1324,8 @@ dnl lookup without tag R <$+> <$+> <$*> <+ $+> $: < $(access $1 $: ? $) > <$1> <$2> <$3> <+ $4> dnl no match; IPv6: remove last part -R <$+:$-> <$+> <$*> <$*> $: $>LookUpAddress <$1> <$3> <$4> <$5> +R <$+::$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> +R <$+:$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> dnl no match; IPv4: remove last part R <$+.$-> <$+> <$*> <$*> $@ $>LookUpAddress <$1> <$3> <$4> <$5> dnl no match: return default @@ -1366,17 +1430,22 @@ R< $* > $* $: $2 ifdef(`_ACCESS_TABLE_', `dnl +dnl workspace: {client_name} $| {client_addr} R$+ $| $+ $: $>LookUpDomain < $1 > < $2 > <+Connect> +dnl workspace: <{client_addr}> R <$+> $: $>LookUpAddress < $1 > < $1 > <+Connect> no: another lookup +dnl workspace: <{client_addr}> R < $+ > $: $1 found nothing -R<$={Accept}> < $* > $@ $1 +dnl workspace: <{client_addr}> +dnl or {client_addr} +R<$={Accept}> < $* > $@ $1 return value of lookup R $* $#error ifdef(`confREJECT_MSG', `$: "confREJECT_MSG"', `$@ 5.7.1 $: "550 Access denied"') R $* $#discard $: discard dnl error tag -R $* $#error $@ $1.$2.$3 $: $4 -R $* $#error $: $1 +R <$*> $#error $@ $1.$2.$3 $: $4 +R <$*> $#error $: $1 dnl generic error from access map -R<$+> $* $#error $: $1', `dnl') +R<$+> <$*> $#error $: $1', `dnl') ifdef(`_RBL_',`dnl # DNS based IP address spam list @@ -1404,6 +1473,14 @@ R< d > $* $@ deferred R< $* > $* $: $2 +# authenticated? +dnl done first: we can require authentication for every mail transaction +dnl workspace: address as given by MAIL FROM: (sender) +R$* $: $1 $| $>"tls_client" $&{verify} $| MAIL +R$* $| $#$+ $#$2 +dnl undo damage: remove result of tls_client call +R$* $| $* $: $1 + dnl workspace: address as given by MAIL FROM: R<> $@ we MUST accept <> (RFC 1123) ifdef(`_ACCEPT_UNQUALIFIED_SENDERS_',`dnl',`dnl @@ -1448,7 +1525,7 @@ dnl or:
dnl or:
(thanks to u in ${daemon_flags}) R $* $: $2 local client: ok -R <$+> $#error $@ 5.5.4 $: "553 Real domain name required" +R <$+> $#error $@ 5.5.4 $: "CODE553 Real domain name required for sender address" dnl remove (happens only if ${client_name} == "" or u in ${daemon_flags}) R $* $: $1') dnl workspace: address (or
) @@ -1498,13 +1575,13 @@ R$* $| $* $: $2 R $* $: < ? $&{client_name} > $1 R $* $@ ...local unqualed ok -R $* $#error $@ 5.5.4 $: "553 Domain name required" +R $* $#error $@ 5.5.4 $: "CODE553 Domain name required for sender address " $&f ...remote is not') # check results R $* $: @ $1 mark address: nothing known about it R $* $@ R $* $#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve" -R $* $#error $@ 5.1.8 $: "501 Domain of sender address " $&f " does not exist" +R $* $#error $@ 5.1.8 $: "CODE553 Domain of sender address " $&f " does not exist" ifdef(`_ACCESS_TABLE_', `dnl R<$={Accept}> $* $# $1 R $* $#discard $: discard @@ -1570,7 +1647,7 @@ R$* $: $1 dnl user is now tagged with @ to be consistent with check_mail dnl and to distinguish users from hosts (com would be host, com@ would be user) -R $+ < @ $=w > $: <> <$1 < @ $2 >> $| +R $+ < @ $=w > $: <> <$1 < @ $2 >> $| R $+ < @ $* > $: <> <$1 < @ $2 >> $| R $+ $: <> <$1> $| dnl $| is used as delimiter, otherwise false matches may occur: > @@ -1596,6 +1673,16 @@ R@ $* $1 remove mark', `dnl')', `dnl') ifdef(`_PROMISCUOUS_RELAY_', `divert(-1)') +# authenticated? +dnl do this unconditionally? this requires to manage CAs carefully +dnl just because someone has a CERT signed by a "trusted" CA +dnl does not mean we want to allow relaying for her, +dnl either use a subroutine or provide something more sophisticated +dnl this could for example check the DN (maybe an access map lookup) +R$* $: $1 $| $>RelayAuth $1 $| $&{verify} client authenticated? +R$* $| $# $+ $# $2 error/ok? +R$* $| $* $: $1 no + # authenticated by a trusted mechanism? R$* $: $1 $| $&{auth_type} dnl empty ${auth_type}? @@ -1605,8 +1692,10 @@ R$* $| $={TrustAuthMech} $# RELAYAUTH dnl undo addition of ${auth_type} R$* $| $* $: $1 +dnl workspace: localpart<@domain> | localpart ifelse(defn(`_NO_UUCP_'), `r', -`R$* ! $* < @ $* > $: $2 < @ BANG_PATH >', `dnl') +`R$* ! $* < @ $* > $: $2 < @ BANG_PATH > +R$* ! $* $: $2 < @ BANG_PATH >', `dnl') # anything terminating locally is ok ifdef(`_RELAY_ENTIRE_DOMAIN_', `dnl R$+ < @ $* $=m > $@ RELAYTO', `dnl') @@ -1615,11 +1704,13 @@ `R$+ < @ $=R > $@ RELAYTO ifdef(`_ACCESS_TABLE_', `dnl R$+ < @ $+ > $: <$(access To:$2 $: ? $)> <$1 < @ $2 >> -R$+ < @ $+ > $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', +dnl workspace: > +R <$+ < @ $+ >> $: <$(access $2 $: ? $)> <$1 < @ $2 >>',`dnl')', `R$+ < @ $* $=R > $@ RELAYTO ifdef(`_ACCESS_TABLE_', `dnl R$+ < @ $+ > $: $>LookUpDomain <$2> <$1 < @ $2 >> <+To>',`dnl')') ifdef(`_ACCESS_TABLE_', `dnl +dnl workspace: > R $* $@ RELAYTO R<$*> <$*> $: $2',`dnl') @@ -1810,8 +1901,11 @@ ### return: or (not found) ###################################################################### +# class with valid marks for SearchList +dnl if A is activated: add it +C{src}E F H U SSearchList -# if it is H: do lookup? +# mark H: lookup domain R<$+> $| <$*> $: <$1> $| <@> $>LookUpDomain <$2> <$3> <$1> R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> dnl A: NOT YET REQUIRED @@ -1819,9 +1913,9 @@ dnl R<$+> $| <@> <$+> <$*> $: <$1> $| <$2> <$3> dnl lookup of the item with tag dnl this applies to F: U: E: -R<$- $-> $| <$-:$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$4 $: $3:$4 $)> <$5> +R<$- $-> $| <$={src}:$+> <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$4 $: $3:$4 $)> <$5> dnl no match, try without tag -R<+ $-> $| <$-:$+> <$*> $: <+ $1> $| <$(access $3 $: $2:$3 $)> <$4> +R<+ $-> $| <$={src}:$+> <$*> $: <+ $1> $| <$(access $3 $: $2:$3 $)> <$4> dnl do we really have to distinguish these cases? dnl probably yes, there might be a + in the domain part (is that allowed?) dnl user+detail lookups: should it be: @@ -1832,13 +1926,12 @@ dnl do not remove the @ from the lookup: dnl it is part of the +detail@ which is omitted for the lookup R<$- $-> $| <$*> $: <$1 $2> $| <$(access $2`'_TAG_DELIM_`'$3@ $: U:$3 + $4$)> <$5> +dnl no match, try without tag R<+ $-> $| <$*> $: <+ $1> $| <$(access $2@ $: U:$2 + $3$)> <$4> -dnl special case for ERROR because this matches the input mark:address -R<$+> $| <> $@ dnl no match, try rest of list -R<$+> $| <$-:$+> <$+> $@ $>SearchList <$1> $| <$4> +R<$+> $| <$={src}:$+> <$+> $@ $>SearchList <$1> $| <$4> dnl no match, list empty: return failure -R<$+> $| <$-:$+> <> $@ +R<$+> $| <$={src}:$+> <> $@ dnl got result, return it R<$+> $| <$+> <$*> $@ <$2> dnl return result from recursive invocation @@ -1862,6 +1955,136 @@ dnl empty ruleset definition so it can be called SLocal_trust_auth +ifdef(`_FFR_TLS_O_T', `dnl +Soffer_tls +R$* $: $>LookUpDomain <$&{client_name}> <> +R$* $: $>LookUpAddress <$&{client_addr}> <> +R$* $: <$(access TLS_OFF_TAG: $: ? $)> +R$* $@ OK +R <> $#error $@ 5.7.1 $: "550 do not offer TLS for " $&{client_name} " ["$&{client_addr}"]" + +Stry_tls +R$* $: $>LookUpDomain <$&{server_name}> <> +R$* $: $>LookUpAddress <$&{server_addr}> <> +R$* $: <$(access TLS_TRY_TAG: $: ? $)> +R$* $@ OK +R$* $#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]" +')dnl + +# is connection with client "good" enough? (done in server) +# input: ${verify} $| (MAIL|STARTTLS) +dnl MAIL: called from check_mail +dnl STARTTLS: called from smtp() after STARTTLS has been accepted +Stls_client +ifdef(`_ACCESS_TABLE_', `dnl +dnl ignore second arg for now +dnl maybe use it to distinguish permanent/temporary error? +dnl if MAIL: permanent (STARTTLS has not been offered) +dnl if STARTTLS: temporary (offered but maybe failed) +R$* $| $* $: $1 $| $>LookUpDomain <$&{client_name}> <> +R$* $| $* $: $1 $| $>LookUpAddress <$&{client_addr}> <> +dnl do a default lookup: just TLS_CLT_TAG +R$* $| $* $: $1 $| <$(access TLS_CLT_TAG`'_TAG_DELIM_ $: ? $)> +R$* $@ $>"tls_connection" $1', `dnl +R$* $| $* $@ $>"tls_connection" $1') + +# is connection with server "good" enough? (done in client) +dnl i.e. has the server been authenticated and is encryption active? +dnl called from deliver() after STARTTLS command +# input: ${verify} +Stls_server +ifdef(`_ACCESS_TABLE_', `dnl +R$* $: $1 $| $>LookUpDomain <$&{server_name}> <> +R$* $| $* $: $1 $| $>LookUpAddress <$&{server_addr}> <> +dnl do a default lookup: just TLS_SRV_TAG +R$* $| $* $: $1 $| <$(access TLS_SRV_TAG`'_TAG_DELIM_ $: ? $)> +R$* $@ $>"tls_connection" $1', `dnl +R$* $@ $>"tls_connection" $1') + +Stls_connection +ifdef(`_ACCESS_TABLE_', `dnl +dnl common ruleset for tls_{client|server} +dnl input: $&{verify} $| [<>] +dnl remove optional <> +R$* $| <$*>$* $: $1 $| <$2> +dnl permanent or temporary error? +R$* $| $: $1 $| <503:5.7.0> <$2 $3> +R$* $| $: $1 $| <403:4.7.0> <$2 $3> +dnl default case depends on TLS_PERM_ERR +R$* $| <$={tls} $*> $: $1 $| <$2 $3> +dnl deal with TLS handshake failures: abort +RSOFTWARE $| <$-:$+> $* $#error $@ $2 $: $1 " TLS handshake failed." +dnl no i.e. not requirements in the access map +dnl use default error +RSOFTWARE $| $* $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake failed." +R$* $| <$*> $: <$2> $1 +R$* $| <$*> <$={tls}:$->$* $: <$2> <$3:$4> $1 +dnl some other value in access map: accept +dnl this also allows to override the default case (if used) +R$* $| $* $@ OK +# authentication required: give appropriate error +# other side did authenticate (via STARTTLS) +dnl workspace: <{VERIFY,ENCR}[:BITS]> ${verify} +dnl only verification required and it succeeded +R<$*> OK $@ OK +dnl verification required + some level of encryption +R<$*> OK $: <$1> +dnl just some level of encryption required +R<$*> $* $: <$1> +dnl verification required but ${verify} is not set +R<$-:$+> $#error $@ $2 $: $1 " authentication required" +R<$-:$+> FAIL $#error $@ $2 $: $1 " authentication failed" +R<$-:$+> NO $#error $@ $2 $: $1 " not authenticated" +R<$-:$+> NONE $#error $@ $2 $: $1 " other side does not support STARTTLS" +dnl some other value for ${verify} +R<$-:$+> $+ $#error $@ $2 $: $1 " authentication failure " $4 +dnl some level of encryption required: get the maximum level +R<$*> $: <$1> $>max $&{cipher_bits} : $&{auth_ssf} +dnl compare required bits with actual bits +R<$*> $- $: <$1> <$2:$3> $(arith l $@ $3 $@ $2 $) +R<$-:$+><$-:$-> TRUE $#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3 + +Smax +dnl compute the max of two values separated by : +R: $: 0 +R:$- $: $1 +R$-: $: $1 +R$-:$- $: $(arith l $@ $1 $@ $2 $) : $1 : $2 +RTRUE:$-:$- $: $2 +R$-:$-:$- $: $2', +`dnl use default error +dnl deal with TLS handshake failures: abort +RSOFTWARE $#error $@ ifdef(`TLS_PERM_ERR', `5.7.0', `4.7.0') $: "ifdef(`TLS_PERM_ERR', `503', `403') TLS handshake."') + +SRelayAuth +# authenticated? +dnl we do not allow relaying for anyone who can present a cert +dnl signed by a "trusted" CA. For example, even if we put verisigns +dnl CA in CERTPath so we can authenticate users, we do not allow +dnl them to abuse our server (they might be easier to get hold of, +dnl but anyway). +dnl so here is the trick: if the verification succeeded +dnl we look up the cert issuer in the access map +dnl (maybe after extracting a part with a regular expression) +dnl if this returns RELAY we relay without further questions +dnl if it returns SUBJECT we perform a similar check on the +dnl cert subject. +R$* $| OK $: $1 +R$* $| $* $@ NO not authenticated +ifdef(`_ACCESS_TABLE_', `dnl +ifdef(`_CERT_REGEX_ISSUER_', `dnl +R$* $: $1 $| $(CERTIssuer $&{cert_issuer} $)', +`R$* $: $1 $| $&{cert_issuer}') +R$* $| $+ $: $1 $| $(access CERTISSUER:$2 $) +dnl use $# to stop further checks (delay_check) +R$* $| RELAY $# RELAYCERTISSUER +ifdef(`_CERT_REGEX_SUBJECT_', `dnl +R$* $| SUBJECT $: $1 $| <@> $(CERTSubject $&{cert_subject} $)', +`R$* $| SUBJECT $: $1 $| <@> $&{cert_subject}') +R$* $| <@> $+ $: $1 $| <@> $(access CERTSUBJECT:$2 $) +R$* $| <@> RELAY $# RELAYCERTSUBJECT +R$* $| $* $: $1', `dnl') + undivert(9)dnl LOCAL_RULESETS ifdef(`_FFR_MILTER', ` # @@ -1882,3 +2105,4 @@ ###################################################################### ###################################################################### undivert(7)dnl MAILER_DEFINITIONS + Index: gnu/usr.sbin/sendmail/cf/m4/version.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/m4/version.m4,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/cf/m4/version.m4 2000/04/07 19:20:30 1.2 +++ gnu/usr.sbin/sendmail/cf/m4/version.m4 2001/05/29 01:31:11 1.5 @@ -1,6 +1,6 @@ divert(-1) # -# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -11,8 +11,8 @@ # the sendmail distribution. # # -VERSIONID(`$Sendmail: version.m4,v 8.39 2000/04/06 20:30:53 gshapiro Exp $') +VERSIONID(`$Sendmail: version.m4,v 8.39.4.29 2001/05/27 21:39:20 gshapiro Exp $') # divert(0) # Configuration version number -DZ8.10.1`'ifdef(`confCF_VERSION', `/confCF_VERSION') +DZ8.11.4`'ifdef(`confCF_VERSION', `/confCF_VERSION') Index: gnu/usr.sbin/sendmail/cf/mailer/local.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/mailer/local.m4,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/cf/mailer/local.m4 2000/04/02 19:05:56 1.1.1.1 +++ gnu/usr.sbin/sendmail/cf/mailer/local.m4 2001/01/15 21:08:57 1.2 @@ -1,6 +1,6 @@ PUSHDIVERT(-1) # -# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -27,7 +27,7 @@ ### Local and Program Mailer specification ### ################################################## -VERSIONID(`$Sendmail: local.m4,v 8.50 1999/11/21 19:02:08 ca Exp $') +VERSIONID(`$Sendmail: local.m4,v 8.50.16.2 2000/09/17 17:04:22 gshapiro Exp $') # # Envelope sender rewriting @@ -78,7 +78,7 @@ `dnl') Mlocal, P=LOCAL_MAILER_PATH, F=_MODMF_(CONCAT(_DEF_LOCAL_MAILER_FLAGS, LOCAL_MAILER_FLAGS), `LOCAL'), S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,_OPTINS(`LOCAL_MAILER_EOL', ` E=', `, ') - _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')_OPTINS(`LOCAL_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`LOCAL_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/LOCAL_MAILER_DSN_DIAGNOSTIC_CODE, + _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')_OPTINS(`LOCAL_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`LOCAL_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`LOCAL_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/LOCAL_MAILER_DSN_DIAGNOSTIC_CODE, A=LOCAL_MAILER_ARGS Mprog, P=LOCAL_SHELL_PATH, F=CONCAT(_DEF_LOCAL_SHELL_FLAGS, LOCAL_SHELL_FLAGS), S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=LOCAL_SHELL_DIR, _OPTINS(`LOCAL_MAILER_MAX', `M=', `, ')T=X-Unix/X-Unix/X-Unix, Index: gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/cf/mailer/smtp.m4,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 2000/04/07 19:20:31 1.2 +++ gnu/usr.sbin/sendmail/cf/mailer/smtp.m4 2001/01/15 21:08:57 1.3 @@ -1,6 +1,6 @@ PUSHDIVERT(-1) # -# Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983 Eric P. Allman. All rights reserved. # Copyright (c) 1988, 1993 @@ -14,17 +14,17 @@ _DEFIFNOT(`_DEF_SMTP_MAILER_FLAGS', `mDFMuX') _DEFIFNOT(`SMTP_MAILER_FLAGS',`') _DEFIFNOT(`RELAY_MAILER_FLAGS', `SMTP_MAILER_FLAGS') -ifdef(`SMTP_MAILER_ARGS',, `define(`SMTP_MAILER_ARGS', `IPC $h')') -ifdef(`ESMTP_MAILER_ARGS',, `define(`ESMTP_MAILER_ARGS', `IPC $h')') -ifdef(`SMTP8_MAILER_ARGS',, `define(`SMTP8_MAILER_ARGS', `IPC $h')') -ifdef(`DSMTP_MAILER_ARGS',, `define(`DSMTP_MAILER_ARGS', `IPC $h')') -ifdef(`RELAY_MAILER_ARGS',, `define(`RELAY_MAILER_ARGS', `IPC $h')') +ifdef(`SMTP_MAILER_ARGS',, `define(`SMTP_MAILER_ARGS', `TCP $h')') +ifdef(`ESMTP_MAILER_ARGS',, `define(`ESMTP_MAILER_ARGS', `TCP $h')') +ifdef(`SMTP8_MAILER_ARGS',, `define(`SMTP8_MAILER_ARGS', `TCP $h')') +ifdef(`DSMTP_MAILER_ARGS',, `define(`DSMTP_MAILER_ARGS', `TCP $h')') +ifdef(`RELAY_MAILER_ARGS',, `define(`RELAY_MAILER_ARGS', `TCP $h')') POPDIVERT ##################################### ### SMTP Mailer specification ### ##################################### -VERSIONID(`$Sendmail: smtp.m4,v 8.56 2000/04/03 20:54:55 ca Exp $') +VERSIONID(`$Sendmail: smtp.m4,v 8.56.2.1.2.3 2000/09/25 13:53:27 ca Exp $') # # common sender and masquerading recipient rewriting @@ -101,17 +101,17 @@ R$+ $: $>MasqHdr $1 Msmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, - _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, A=SMTP_MAILER_ARGS -Mesmtp, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, - _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, +Mesmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a', SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, A=ESMTP_MAILER_ARGS -Msmtp8, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `8', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, - _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, +Msmtp8, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `8', SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, A=SMTP8_MAILER_ARGS -Mdsmtp, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a%', SMTP_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, - _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, +Mdsmtp, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a%', SMTP_MAILER_FLAGS), `SMTP'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `EnvToSMTP/HdrFromSMTP', `EnvToSMTP'), E=\r\n, L=990, + _OPTINS(`SMTP_MAILER_MAX', `M=', `, ')_OPTINS(`SMTP_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')_OPTINS(`SMTP_MAILER_CHARSET', `C=', `, ')T=DNS/RFC822/SMTP, A=DSMTP_MAILER_ARGS -Mrelay, P=[IPC], F=CONCAT(_DEF_SMTP_MAILER_FLAGS, `a8', RELAY_MAILER_FLAGS), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `MasqSMTP/MasqRelay', `MasqSMTP'), E=\r\n, L=2040, - _OPTINS(`RELAY_MAILER_CHARSET', `C=', `, ')_OPTINS(`RELAY_MAILER_MAXMSGS', `m=', `, ')T=DNS/RFC822/SMTP, +Mrelay, P=[IPC], F=_MODMF_(CONCAT(_DEF_SMTP_MAILER_FLAGS, `a8', RELAY_MAILER_FLAGS), `RELAY'), S=EnvFromSMTP/HdrFromSMTP, R=ifdef(`_ALL_MASQUERADE_', `MasqSMTP/MasqRelay', `MasqSMTP'), E=\r\n, L=2040, + _OPTINS(`RELAY_MAILER_CHARSET', `C=', `, ')_OPTINS(`RELAY_MAILER_MAXMSGS', `m=', `, ')_OPTINS(`SMTP_MAILER_MAXRCPTS', `r=', `, ')T=DNS/RFC822/SMTP, A=RELAY_MAILER_ARGS Index: gnu/usr.sbin/sendmail/contrib/bitdomain.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/bitdomain.c,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- gnu/usr.sbin/sendmail/contrib/bitdomain.c 2000/04/02 19:05:57 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/bitdomain.c 2001/01/15 20:52:40 1.1.1.2 @@ -51,7 +51,7 @@ { int opt; - while ((opt = getopt(argc, argv, "o:")) != EOF) { + while ((opt = getopt(argc, argv, "o:")) != -1) { switch (opt) { case 'o': if (!freopen(optarg, "w", stdout)) { @@ -187,7 +187,7 @@ case NO_DATA: err = "registered in DNS, but not mailable"; break; - + default: err = "unknown nameserver error"; break; @@ -210,7 +210,7 @@ int hbsize; { register u_char *eom, *ap; - register int n; + register int n; HEADER *hp; querybuf answer; int ancount, qdcount; @@ -406,4 +406,4 @@ } } } - + Index: gnu/usr.sbin/sendmail/contrib/domainmap.m4 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/domainmap.m4,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- gnu/usr.sbin/sendmail/contrib/domainmap.m4 2000/04/02 19:05:57 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/domainmap.m4 2001/01/15 20:52:40 1.1.1.2 @@ -58,7 +58,7 @@ ifdef(`_DOMAIN_MAP_',`',`dnl LOCAL_RULE_0 # do mapping for domains where applicable -R$* $=O $* <@ $={MappedDomain} .> $@ $>97 $1 $2 $3 Strip extraneous routing +R$* $=O $* <@ $={MappedDomain} .> $@ $>Recurse $1 $2 $3 Strip extraneous routing R$+ <@ $={MappedDomain} .> $>DomainMapLookup $1 <@ $2 .> domain mapping LOCAL_RULESETS @@ -69,22 +69,35 @@ SDomainMapLookup R $=L <@ $=w .> $@ $1 <@ $2 .> weed out local users, in case # Cw contains a mapped domain -R $+ <@ $+ .> $1 <@ $2 > strip trailing dot -R $+ <@ $+ . $+ > $1 <@ $(dequote $2 "_" $3 $) > +ifdef(`DOMAINMAP_NO_REGEX',`dnl +R $+ <@ $+> $: $1 <@ $2> <$2> find domain +R $+ <$+> <$+ . $+> $1 <$2> < $(dequote $3 "_" $4 $) > # change "." to "_" -R $+ <@ $+ > $: $1 <@ $(dequote "domain_" $2 $) > +R $+ <$+> <$+ .> $: $1 <$2> < $(dequote "domain_" $3 $) > # prepend "domain_" -R $+ + $+ <@ $*> $1 <@ $3 > <+> $2 handle user+list syntax -R $+ <@ $* > $* $( $2 $1 $: $) $3 +dnl',`dnl +R $+ <@ $+> $: $1 <@ $2> <$2 :NOTDONE:> find domain +R $+ <$+> <$+ . :NOTDONE:> $1 <$2> < $(domainmap_regex $3 $: $3 $) > +# change "." and "-" to "_" +R $+ <$+> <$+> $: $1 <$2> < $(dequote "domain_" $3 $) > +# prepend "domain_" +dnl') +R $+ <$+> <$+> $: $1 <$2> <$3> $1 find user name +R $+ <$+> <$+> $+ + $* $: $1 <$2> <$3> $4 handle user+detail syntax +R $+ <$+> <$+> $+ $: $1 <$2> $( $3 $4 $: $) # do actual domain map lookup -R $* $#error $@ 5.1.1 $: "550 email address lookup in domain map failed" -R $* $* $#error $@ 4.3.0 $: "450 domain map temporarily unavailable" -R $+ @ $+ <+> $+ $1 + $3 @ $2 reset original user+list -R $+ <+> $* $1 paranoid check - remove <+> -R $+ @ $+ . $1 @ $2 strip trailing dot -R $+ @ $+ $@ $>97 $1 @ $2 recanonify -define(`_DOMAIN_MAP_',`1')') +R $+ <$+> $#error $@ 5.1.1 $: "550 email address lookup in domain map failed" +R $+ <@ $+> $* $* $#dsmtp $@ localhost $: $1 @ $2 +# queue it up for later delivery +R $+ + $* <$+> $+ @ $+ $: $1 + $2 <$3> $4 + $2 @ $5 +# reset original user+detail +R $+ <$+> $+ $@ $>Recurse $3 recanonify + +ifdef(`DOMAINMAP_NO_REGEX',`',`dnl +LOCAL_CONFIG +K domainmap_regex regex -a.:NOTDONE: -s1,2 -d_ (.*)[-\.]([^-\.]*)$ +')define(`_DOMAIN_MAP_',`1')') LOCAL_CONFIG C{MappedDomain} _ARG_ -K `domain_'translit(_ARG_, `.', `_') _ARG2_ -T +K `domain_'translit(_ARG_, `.-', `__') _ARG2_ -T Index: gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl 2000/04/02 19:05:57 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/passwd-to-alias.pl 2001/01/15 20:52:41 1.1.1.2 @@ -8,22 +8,23 @@ print "# Generated from passwd by $0\n"; +$wordpat = '([a-zA-Z]+?[a-zA-Z0-9-]*)?[a-zA-Z0-9]'; # 'DB2' while (@a = getpwent) { ($name,$passwd,$uid,$gid,$quota,$comment,$gcos,$dir,$shell) = @a; ($fullname = $gcos) =~ s/,.*$//; - if (!-d $dir || !-x $shell) { - print "$name: root\n"; + if (!-d $dir || !-x $shell || $shell =~ m!/bin/(false|true)$!) { + print "$name: root\n"; # handle pseudo user } $fullname =~ s/\.*[ _]+\.*/./g; - $fullname =~ tr [åäöÅÄÖé] [aaoAAOe]; # 1997-06-15 - if ($fullname =~ /^[a-zA-Z][a-zA-Z-]+(\.[a-zA-Z][a-zA-Z-]+)+$/) { -# if ($fullname =~ /^[a-zA-Z]+(\.[a-zA-Z]+)+$/) { # Kari E. Hurtta + $fullname =~ tr [åäéöüÅÄÖÜ] [aaeouAAOU]; # 1997-06-15 + next if (!$fullname || lc($fullname) eq $name); # avoid nonsense + if ($fullname =~ /^$wordpat(\.$wordpat)*$/o) { # Ulrich Windl print "$fullname: $name\n"; } else { - print "# $fullname: $name\n"; + print "# $fullname: $name\n"; # avoid strange names } }; Index: gnu/usr.sbin/sendmail/contrib/qtool.8 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/qtool.8,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/contrib/qtool.8 2000/04/02 19:05:57 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/qtool.8 2001/01/15 21:09:00 1.2 @@ -6,11 +6,11 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: qtool.8,v 8.9 1999/08/26 00:04:10 cying Exp $ +.\" $Sendmail: qtool.8,v 8.9.16.2 2000/12/15 19:50:41 gshapiro Exp $ .\" -.TH QTOOL 8 "July 12, 1999" +.TH QTOOL 8 "$Date: 2001/01/15 21:09:00 $" .SH NAME -.B qtool +qtool \- manipulate sendmail queues .SH SYNOPSIS .B qtool.pl Index: gnu/usr.sbin/sendmail/contrib/qtool.pl =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/qtool.pl,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/contrib/qtool.pl 2000/04/02 19:05:57 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/qtool.pl 2001/01/15 21:09:00 1.2 @@ -1,9 +1,9 @@ #!/usr/bin/env perl ## -## Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +## Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. ## All rights reserved. ## -## $Sendmail: qtool.pl,v 8.15 1999/08/30 19:18:37 peterh Exp $ +## $Sendmail: qtool.pl,v 8.15.16.4 2000/11/30 07:14:01 gshapiro Exp $ ## use strict; use File::Basename; @@ -133,13 +133,12 @@ if ($result) { print("$result.\n"); + exit; } } if (keys(%sources) == 0) { - print("You must at least specify at least one source.\n"); - usage(); exit; } @@ -164,7 +163,7 @@ print(" -b Bounce the messages specified by source.\n"); print(" -d Delete the messages specified by source.\n"); print(" -e [perl expression] Move only messages for which perl expression returns true.\n"); - print(" -s [seconds] Move only messages older than seconds.\n"); + print(" -s [seconds] Move only messages whose qf file is older than seconds.\n"); } ## @@ -705,6 +704,14 @@ } } +sub last_modified_time +{ + my $self = shift; + my @result; + @result = stat($self->{data_file}->{file_name}); + return $result[9]; +} + sub TIEHASH { my $this = shift; @@ -914,7 +921,7 @@ } @control_files = grep { /^qf.*/ && -f "$control_dir/$_" } readdir(QUEUE_DIR); - closedir(DIR); + closedir(QUEUE_DIR); foreach $file_name (@control_files) { $id = substr($file_name, 2); Index: gnu/usr.sbin/sendmail/contrib/re-mqueue.pl =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/re-mqueue.pl,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- gnu/usr.sbin/sendmail/contrib/re-mqueue.pl 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/re-mqueue.pl 2001/01/15 20:52:41 1.1.1.2 @@ -93,6 +93,17 @@ # Allow zero-length df files (empty message body) # Preserve $! for error messages # +# Updated by Graeme Hewson April 2000 +# +# Improve handling of race between re-mqueue and sendmail +# +# Updated by Graeme Hewson June 2000 +# +# Don't exit(0) at end so can be called as subroutine +# +# NB This program can't handle separate qf/df/xf subdirectories +# as introduced in sendmail 8.10.0. +# use Sys::Syslog; @@ -136,18 +147,17 @@ ($qfile = $dfile) =~ s/^d/q/; ($xfile = $dfile) =~ s/^d/x/; ($mfile = $dfile) =~ s/^df//; - if (! -e $dfile) { - print "$dfile is gone - skipping\n" if ($debug); - next; - } if (! -e $qfile || -z $qfile) { print "$qfile is gone or zero bytes - skipping\n" if ($debug); next; } - $mtime = $now; ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($dfile); + if (! defined $mtime) { + print "$dfile is gone - skipping\n" if ($debug); + next; + } # Compare timestamps if (($mtime + $age) > $now) { @@ -182,6 +192,17 @@ } print "$qfile now flock()ed\n" if ($debug); + # Check df* file again in case sendmail got in + if (! -e $dfile) { + print "$mfile sent - skipping\n" if ($debug); + # qf* file created by ourselves at open? (Almost certainly) + if (-z $qfile) { + unlink($qfile); + } + close(QF); + next; + } + # Show time! Do the link()s if (link("$dfile", "$queueB/$dfile") == 0) { $bang = $!; @@ -235,4 +256,3 @@ &syslog('info', '%s moved to %s', $mfile, $queueB); print "Done with $dfile $qfile\n\n" if ($debug); } -exit 0; Index: gnu/usr.sbin/sendmail/contrib/smcontrol.pl =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/contrib/smcontrol.pl,v retrieving revision 1.1.1.1 retrieving revision 1.1.1.2 diff -u -r1.1.1.1 -r1.1.1.2 --- gnu/usr.sbin/sendmail/contrib/smcontrol.pl 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/contrib/smcontrol.pl 2001/01/15 20:52:41 1.1.1.2 @@ -162,7 +162,7 @@ my $cooked = ""; my $daemonStatus = ""; - if ($raw =~ /^(\d+)\/(\d+)\/(\d+)\/(\d+)$/mg) + if ($raw =~ /^(\d+)\/(\d+)\/(\d+)\/(\d+)/mg) { $cooked .= "Current number of children: $1"; if ($2 > 0) Index: gnu/usr.sbin/sendmail/doc/op/op.me =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/doc/op/op.me,v retrieving revision 1.3 retrieving revision 1.6 diff -u -r1.3 -r1.6 --- gnu/usr.sbin/sendmail/doc/op/op.me 2000/04/07 19:20:32 1.3 +++ gnu/usr.sbin/sendmail/doc/op/op.me 2001/05/29 01:31:11 1.6 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +.\" Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. .\" All rights reserved. .\" Copyright (c) 1983, 1995 Eric P. Allman. All rights reserved. .\" Copyright (c) 1983, 1993 @@ -9,7 +9,7 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: op.me,v 8.317 2000/04/06 21:05:27 gshapiro Exp $ +.\" $Sendmail: op.me,v 8.317.4.64 2001/05/24 16:45:49 ca Exp $ .\" .\" eqn op.me | pic | troff -me .eh 'SMM:08-%''Sendmail Installation and Operation Guide' @@ -32,7 +32,6 @@ \\$1 \\$2. \\$3 .)x .. -.sc .+c .(l C .sz 16 @@ -54,10 +53,10 @@ .de Ve Version \\$2 .. -.Ve $Revision: 1.3 $ +.Ve $Revision: 1.6 $ .rm Ve .sp -For Sendmail Version 8.10 +For Sendmail Version 8.11 .)l .(f Sendmail is a trademark of Sendmail, Inc. @@ -100,12 +99,13 @@ RFC1870 (SMTP SIZE Extension), RFC1891 (SMTP Delivery Status Notifications), RFC1892 (Multipart/Report), -RFC1893 (Mail System Status Codes), +RFC1893 (Enhanced Mail System Status Codes), RFC1894 (Delivery Status Notifications), RFC1985 (SMTP Service Extension for Remote Message Queue Starting), RFC2033 (Local Message Transmission Protocol), RFC2034 (SMTP Service Extension for Returning Enhanced Error Codes), RFC2476 (Message Submission), +RFC2487 (SMTP Service Extension for Secure SMTP over TLS), and RFC2554 (SMTP Service Extension for Authentication). However, since @@ -148,12 +148,6 @@ The appendixes give a brief but detailed explanation of a number of features not described in the rest of the paper. -.bp -.rs -.sp |4i -.ce 2 -This page intentionally left blank; -replace it with a blank sheet for double-sided output. .bp 7 .sh 1 "BASIC INSTALLATION" .pp @@ -265,6 +259,7 @@ .pp (This section is not yet complete. For now, see the file devtools/README for details.) +See sendmail/README for various compilation flags that can be set. .sh 3 "Tweaking the Makefile" .pp .\" .b "XXX This should all be in the Site Configuration File section." @@ -629,7 +624,7 @@ .pp This command is also a link to .i sendmail . -It flushes all information that is stored in the +It flushes expired (Timeout.hoststatus) information that is stored in the .b HostStatusDirectory tree. .sh 3 "/var/spool/mqueue" @@ -649,9 +644,9 @@ To use multiple queues, supply a value ending with an asterisk. For example, -.i /var/spool/mqueue/q* +.i /var/spool/mqueue/qd* will use all of the directories or symbolic links to directories -beginning with `q' in +beginning with `qd' in .i /var/spool/mqueue as queue directories. Do not change the queue directory structure @@ -915,6 +910,10 @@ The message id of the message (from the header). .ip proto The protocol used to receive this message (e.g., ESMTP or UUCP) +.ip daemon +The daemon name from the +.b DaemonPortOptions +setting. .ip relay The machine from which it was received. .lp @@ -929,7 +928,7 @@ whose credentials we use for delivery. .ip delay The total delay between the time this message was received -and the time it was delivered. +and the current delivery attempt. .ip xdelay The amount of time needed in this delivery attempt (normally indicative of the speed of the connection). @@ -937,6 +936,8 @@ The name of the mailer used to deliver to this recipient. .ip relay The name of the host that actually accepted (or rejected) this recipient. +.ip dsn +The enhanced error code (RFC2034) if available. .ip stat The delivery status. .lp @@ -1140,6 +1141,9 @@ the .i purgestat command and is completely safe. +However, +.i purgestat +only removes expired (Timeout.hoststatus) data. The information in these directories can be perused with the .i hoststat @@ -1157,7 +1161,7 @@ .b Timeout.hoststatus option. .pp -The connection information stored on disk may be purged at any time +The connection information stored on disk may be expired at any time with the .i purgestat command or by invoking sendmail with the @@ -1173,7 +1177,8 @@ The implementation of certain system services such as host and user name lookup is controlled by the service switch. -If the host operating system supports such a switch +If the host operating system supports such a switch, +and sendmail knows about it, .i sendmail will use the native version. Ultrix, Solaris, and DEC OSF/1 are examples of such systems\**. @@ -1516,6 +1521,7 @@ .i sendmail redirects mail for that user to the list of addresses listed in the .forward file. +Note that aliases are fully expanded before forward files are referenced. For example, if the home directory for user .q mckusick has a .forward file with contents: @@ -1583,6 +1589,9 @@ The Precedence: header can be used as a crude control of message priority. It tweaks the sort order in the queue and can be configured to change the message timeout values. +The precedence of a message also controls how +delivery status notifications (DSNs) +are processed for that message. .sh 2 "IDENT Protocol Support" .pp .i Sendmail @@ -1824,7 +1833,7 @@ gives up its setuid root permissions when you use this flag, so it is common to use a publicly writable directory (such as /tmp) -as the spool directory (QueueDirectory or Q option) while testing. +as the queue directory (QueueDirectory or Q option) while testing. .sh 2 "Logging Traffic" .pp Many SMTP implementations do not fully implement the protocol. @@ -2033,6 +2042,9 @@ specifies how often a sub-daemon will run the queue. This is typically set to between fifteen minutes and one hour. +If not set, +or set to zero, +the queue will not be run automatically. RFC 1123 section 5.3.1.1 recommends that this be at least 30 minutes. .sh 3 "Read timeouts" .pp @@ -2401,7 +2413,7 @@ .b QueueLA option plus one -exceeds the priority of the message \(em +is less than the priority of the message \(em that is, the message is queued iff: .EQ pri > { bold QueueFactor } over { LA - { bold QueueLA } + 1 } @@ -2443,7 +2455,7 @@ i deliver interactively (synchronously) b deliver in background (asynchronously) q queue only (don't deliver) -d defer delvery attempts (don't deliver) +d defer delivery attempts (don't deliver) .)b There are tradeoffs. Mode @@ -2521,7 +2533,8 @@ Messages being deferred (due to a host being down, etc.). .ip 10 -Database expansion (alias, forward, and userdb lookups). +Database expansion (alias, forward, and userdb lookups) +and authentication information. .ip 11 NIS errors and end of job processing. .ip 12 @@ -2602,6 +2615,8 @@ setuid to that) which will fix the privacy problems but not the functionality issues. +It also introduces problems on some operating systems +if sendmail needs to give up the setuid special privileges. Also, this isn't a guarantee of security: for example, root occasionally sends mail, @@ -2682,7 +2697,7 @@ Assume that the .i chown system call is restricted to root. -Since some versions of Unix permit regular users +Since some versions of UNIX permit regular users to give away their files to other users on some filesystems, .i sendmail often cannot assume that a given file was created by the owner, @@ -2702,6 +2717,25 @@ Allow the file named in the .b ErrorHeader option to be in an unsafe directory. +.ip FileDeliveryToHardLink +Allow delivery to files that are hard links. +.ip FileDeliveryToSymLink +Allow delivery to files that are symbolic links. +.ip ForwardFileInGroupWritableDirPath +Allow +.i \&.forward +files in group writable directories. +.ip ForwardFileInUnsafeDirPath +Allow +.i \&.forward +files in unsafe directories. +.ip ForwardFileInUnsafeDirPathSafe +Allow a +.i \&.forward +file that is in an unsafe directory to include references +to program and files. +.ip GroupWritableAliasFile +Allow group-writable alias files. .ip GroupWritableDirPathSafe Change the definition of .q "unsafe directory" @@ -2710,53 +2744,31 @@ .ip GroupWritableForwardFileSafe Accept group-writable .i \&.forward -files. +files as safe for program and file delivery. .ip GroupWritableIncludeFileSafe Accept group-writable .i :include: -files. -.ip GroupWritableAliasFile -Allow group-writable alias files. +files as safe for program and file delivery. .ip HelpFileInUnsafeDirPath Allow the file named in the .b HelpFile option to be in an unsafe directory. -.ip WorldWritableAliasFile -Accept world-writable alias files. -.ip ForwardFileInGroupWritableDirPath -Allow -.i \&.forward -files in group writable directories. .ip IncludeFileInGroupWritableDirPath Allow .i :include: files in group writable directories. -.ip ForwardFileInUnsafeDirPath -Allow -.i \&.forward -files in unsafe directories. .ip IncludeFileInUnsafeDirPath Allow .i :include: files in unsafe directories. -.ip ForwardFileInUnsafeDirPathSafe -Allow a -.i \&.forward -file that is in an unsafe directory to include references -to program and files. .ip IncludeFileInUnsafeDirPathSafe Allow a .i :include: file that is in an unsafe directory to include references to program and files. -.ip MapInUnsafeDirPath -Allow maps (e.g., -.i hash , -.i btree , -and -.i dbm -files) -in unsafe directories. +.ip InsufficientEntropy +Try to use STARTTLS even if the PRNG for OpenSSL is not properly seeded +despite the security problems. .ip LinkedAliasFileInWritableDir Allow an alias file that is a link in a writable directory. .ip LinkedClassFileInWritableDir @@ -2774,14 +2786,28 @@ .ip LinkedServiceSwitchFileInWritableDir Allow the service switch file to be a link even if the directory is writable. -.ip FileDeliveryToHardLink -Allow delivery to files that are hard links. -.ip FileDeliveryToSymLink -Allow delivery to files that are symbolic links. +.ip MapInUnsafeDirPath +Allow maps (e.g., +.i hash , +.i btree , +and +.i dbm +files) +in unsafe directories. +.ip NonRootSafeAddr +Do not mark file and program deliveries as unsafe +if sendmail is not running with root privileges. .ip RunProgramInUnsafeDirPath Go ahead and run programs that are in writable directories. .ip RunWritableProgram Go ahead and run programs that are group- or world-writable. +.ip TrustStickyBit +Allow group or world writable directories +if the sticky bit is set on the directory. +Do not set this on systems which do not honor +the sticky bit on directories. +.ip WorldWritableAliasFile +Accept world-writable alias files. .ip WriteMapToHardLink Allow writes to maps that are hard links. .ip WriteMapToSymLink @@ -2790,14 +2816,6 @@ Allow the status file to be a hard link. .ip WriteStatsToSymLink Allow the status file to be a symbolic link. -.ip TrustStickyBit -Allow group or world writable directories -if the sticky bit is set on the directory. -Do not set this on systems which do not honor -the sticky bit on directories. -.ip NonRootSafeAddr -Do not mark file and program deliveries as unsafe -if sendmail is not running with root privileges. .sh 2 "Connection Caching" .pp When processing the queue, @@ -3177,6 +3195,10 @@ .b $ \c .i x are performed when the configuration file is read. +A literal +.b $ +can be included using +.b $$ . Expansions of the form .b $& \c .i x @@ -3335,13 +3357,14 @@ .b $# syntax should .i only -be used in ruleset zero -or a subroutine of ruleset zero. +be used in ruleset zero, +a subroutine of ruleset zero, +or rulesets that return decisions (e.g., check_rcpt). It causes evaluation of the ruleset to terminate immediately, and signals to .i sendmail that the address has completely resolved. -The complete syntax is: +The complete syntax for ruleset 0 is: .(b \fB$#\fP\fImailer\fP \fB$@\fP\fIhost\fP \fB$:\fP\fIuser\fP .)b @@ -3467,8 +3490,8 @@ .)c .\} -.el .ie !"\*(.T"" \ -\{\ +.el \{\ +.ie !"\*(.T"" \{\ .PS boxwid = 0.3i boxht = 0.3i @@ -3499,6 +3522,7 @@ .PE .\} .el .sp 2i +.\} .ce Figure 1 \*- Rewriting set semantics .(c @@ -3596,7 +3620,10 @@ .pp The .i check_relay -ruleset is called after a connection is accepted. +ruleset is called after a connection is accepted by the daemon. +It is not called when sendmail is started using the +.b \-bs +option. It is passed .(b client.host.name $| client.host.address @@ -3727,6 +3754,31 @@ .q error mailer the AUTH= parameter is not trusted and hence not passed on to the next relay. +.sh 4 "tls_client" +.pp +The +.i tls_client +ruleset is called when sendmail acts as server, after a STARTTLS command +has been issued, and from +.i check_mail. +The parameter is the value of +.b ${verify} +and STARTTLS or MAIL, respectively. +If the ruleset does resolve to the +.q error +mailer, the appropriate error code is returned to the client. +.sh 4 "tls_server" +.pp +The +.i tls_server +ruleset is called when sendmail acts as client after a STARTTLS command +(should) have been issued. +The parameter is the value of +.b ${verify} . +If the ruleset does resolve to the +.q error +mailer, the connection is aborted +(treated as non-deliverable with a permanent or temporary error). .sh 3 "IPC mailers" .pp Some special processing occurs @@ -3780,6 +3832,8 @@ .pp Macros are named with a single character or with a word in {braces}. +The names ``x'' and ``{x}'' denote the same macro +for every single character ``x''. Single character names may be selected from the entire ASCII set, but user-defined macros should be selected from the set of upper case letters only. @@ -4024,10 +4078,24 @@ .ip ${auth_type} The mechanism used for authentication (only set if successful). +.ip ${auth_ssf} +The keylength (in bits) of the symmetric encryption algorithm +used for the security layer of a SASL mechanism. .ip ${bodytype} The message body type (7BIT or 8BITMIME), as determined from the envelope. +.ip ${cert_issuer} +The DN (distinguished name) of the CA (certificate authority) +that signed the presented certificate (the cert issuer). +.ip ${cert_subject} +The DN of the presented certificate (called the cert subject). +.ip ${cipher} +The cipher suite used for the connection, e.g., EDH-DSS-DES-CBC3-SHA, +EDH-RSA-DES-CBC-SHA, DES-CBC-MD5, DES-CBC3-SHA. +.ip ${cipher_bits} +The keylength (in bits) of the symmetric encryption algorithm +used for a TLS connection. .ip ${client_addr} The IP address of the SMTP client. Defined in the SMTP server only. @@ -4035,8 +4103,9 @@ The host name of the SMTP client. This may be the client's bracketed IP address in the form [ nnn.nnn.nnn.nnn ] if the client's -IP address is not resolvable, or if the resolved -name doesn't match ${client_name}. +IP address is not resolvable, or if it is resolvable +but the IP address of the resolved hostname +doesn't match the original IP address. Defined in the SMTP server only. .ip ${client_port} The port number of the SMTP client. @@ -4116,12 +4185,17 @@ .ip ${if_addr} The IP address of the interface of an incoming connection unless it is in the loopback net. +.ip ${if_family} +The IP family of the interface of an incoming connection +unless it is in the loopback net. .ip ${if_name} The name of the interface of an incoming connection. This macro can be used for SmtpGreetingMessage and HReceived for virtual hosting. For example: -O SmtpGreetingMessage=$?{if_name}${if_name}$|$j$. Sendmail $v/$Z; $b +.(b +O SmtpGreetingMessage=$?{if_name}${if_name}$|$j$. MTA +.)b .ip ${mail_addr} The address part of the resolved triple of the address given for the .sm "SMTP MAIL" @@ -4137,6 +4211,13 @@ .sm "SMTP MAIL" command. Defined in the SMTP server only. +.ip ${msg_size} +The value of the SIZE= parameter, +i.e., usually the size of the message (in an ESMTP dialogue), +before the message has been collected, thereafter +the message size as computed by +.i sendmail +(and can be used in check_compat). .ip ${ntries} The number of delivery attempts. .ip ${opMode} @@ -4168,6 +4249,28 @@ .sm "SMTP RCPT" command. Defined in the SMTP server only. +.ip ${server_addr} +The address of the server of the current outgoing SMTP connection. +.ip ${server_name} +The name of the server of the current outgoing SMTP connection. +.ip ${tls_version} +The TLS/SSL version used for the connection, e.g., TLSv1, SSLv3, SSLv2. +.ip ${verify} +The result of the verification of the presented cert. +Possible values are: +.(b +.ta 9n +OK verification succeeded. +NO no cert presented. +FAIL cert presented but could not be verified, + e.g., the signing CA is missing. +NONE STARTTLS has not been performed. +TEMP temporary error occurred. +PROTOCOL some protocol error occurred. +SOFTWARE STARTTLS handshake failed, + which is a fatal error for this session, + the e-mail will be queued. +.)b .pp There are three types of dates that can be used. The @@ -4408,6 +4511,9 @@ .br .b F \c .i c\|file +.br +.b F \c +.i c\||program .)b The first form defines the class .i c @@ -4434,11 +4540,22 @@ CHucbmonet .)b are equivalent. -The ``F'' form -reads the elements of the class +The ``F'' forms +read the elements of the class .i c from the named -.i file . +.i file +or +.i program . +Each element should be listed on a separate line. +To specify an optional file, use ``-o'' between the class +name and the file name, e.g., +.(b +Fc -o /path/to/file +.)b +If the file can't be used, +.i sendmail +will not complain but silently ignore it. .pp Elements of classes can be accessed in rules using .b $= @@ -5178,12 +5295,18 @@ (as with the other .b check_ * rulesets). +The ruleset receives the header field-body as argument, +i.e., not the header field-name; see also +${hdr_name} and ${currHeader}. The header is treated as a structured field, that is, -comments (in parentheses) are deleted before processing, +text in parentheses is deleted before processing, unless the second form .b $>+ is used. +Note: only one ruleset can be associated with a header; +.i sendmail +will silently ignore multiple entries. .pp For example, the configuration lines: .(b @@ -5271,7 +5394,7 @@ ``\c .i class \c .b : -.i file '' +.i info '' where .i class \c .b : @@ -5286,6 +5409,10 @@ (if .sm NEWDB is specified), +.q btree +(if +.sm NEWDB +is specified), .q dbm (if .sm NDBM @@ -5293,6 +5420,13 @@ .q stab (internal symbol table \*- not normally used unless you have no other database lookup), +.q sequence +(use a sequence of maps +previously declared), +.q ldap +(if +.sm LDAPMAP +is specified), or .q nis (if @@ -5362,6 +5496,14 @@ .i c . Unquoted spaces in addresses are replaced by this character. Defaults to space (i.e., no change is made). +.ip CACERTPath +[no short name] +Path to directory with certificates of CAs. +This directory directory must contain the hashes of each CA certificate +as filenames (or as links to them). +.ip CACERTFile +[no short name] +File containing one CA certificate. .ip CheckAliases [n] Validate the RHS of aliases when rebuilding the alias database. @@ -5373,7 +5515,7 @@ addresses sent. If your system crashes during delivery to a large list, this prevents retransmission to any but the last -.I N +.i N recipients. .ip ClassFactor=\fIfact\fP [z] @@ -5387,6 +5529,10 @@ and subtracted from the priority. Thus, messages with a higher Priority: will be favored. Defaults to 1800. +.ip ClientCertFile +[no short name] +File containing the certificate of the client, i.e., this certificate +is used when sendmail acts as client. .ip ClientPortOptions=\fIoptions\fP [O] Set client SMTP options. @@ -5416,6 +5562,9 @@ If ``h'' is set, the name corresponding to the outgoing interface address (whether chosen via the Connection parameter or the default) is used for the HELO/EHLO command. +.ip ClientKeyFile +[no short name] +File containing the private key belonging to the client certificate. .ip ColonOkInAddr [no short name] If set, colons are acceptable in e-mail addresses @@ -5498,9 +5647,13 @@ and the load average of the machine expressed as an integer. If not set, no control socket will be available. Solaris and pre-4.4BSD kernel users should see the note in sendmail/README . +.ip DHParameters +File with DH parameters for STARTTLS. +This is only required if DSA/DH is used. .ip DaemonPortOptions=\fIoptions\fP [O] Set server SMTP options. +Each instance of DaemonPortOptions leads to an additional incoming socket. The options are .i key=value pairs. @@ -5523,12 +5676,17 @@ .i Addr ess mask may be a numeric address in dot notation or a network name. +The +.i Family +key defaults to INET (IPv4). +IPv6 users who wish to also accept IPv6 connections +should add additional Family=inet6 DaemonPortOptions lines. .i Modifier can be a sequence (without any delimiters) of the following characters: .(b .ta 1i -a require authentication +a always require authentication b bind to interface through which mail has been received c perform hostname canonification (.cf) f require fully qualified hostname (.cf) @@ -5537,7 +5695,7 @@ E disallow ETRN (see RFC 2476) .)b That is, one way to specify a message submission agent (MSA) that -requires authentication is: +always requires authentication is: .(b O DaemonPortOptions=Name=MSA, Port=587, M=Ea .)b @@ -5545,6 +5703,12 @@ effect in the standard configuration file, in which they are available via .b ${daemon_flags} . +Notice: Do +.b not +use the ``a'' modifier on a public accessible MTA! +It should only be used for a MSA that is accessed by authorized +users for initial mail submission. +Users must authenticate to use a MSA which has this option turned on. The flags ``c'' and ``C'' can change the default for hostname canonification in the .i sendmail.cf @@ -5710,6 +5874,7 @@ IncludeFileInUnsafeDirPath IncludeFileInUnsafeDirPathSafe IncludeFileIngroupWritableDirPath +InsufficientEntropy LinkedAliasFileInWritableDir LinkedClassFileInWritableDir LinkedForwardFileInWritableDir @@ -6017,7 +6182,7 @@ .i sendmail will refuse connections when it has more than .i N -children processing incoming mail. +children processing incoming mail or automatic queue runs. This does not limit the number of outgoing connections. If not set, there is no limit to the number of children -- that is, the system load averaging controls this. @@ -6093,7 +6258,7 @@ gives a 452 response to the MAIL command. This invites the sender to try again later. -.ip MinQueueAge=\fPage\fP +.ip MinQueueAge=\fIage\fP [no short name] Don't process any queued jobs that have been in the queue less than the indicated time interval. @@ -6178,6 +6343,7 @@ copies of error messages will be sent to the named .i postmaster . Only the header of the failed message is sent. +Errors resulting from messages with a negative precedence will not be sent. Since most errors are user problems, this is probably not a good idea on large sites, and arguably contains all sorts of privacy violations, @@ -6211,6 +6377,7 @@ nobodyreturn Don't return the body of a message with DSNs goaway Disallow essentially all SMTP status queries authwarnings Put X-Authentication-Warning: headers in messages + and log warnings .)b .(f \**N.B.: @@ -6319,6 +6486,13 @@ Use that form instead of the .q QueueTimeout form. +.ip RandFile +[no short name] +Name of file containing random data or the name of the UNIX socket +if EGD is used. +A (required) prefix "egd:" or "file:" specifies the type. +STARTTLS requires this filename if the compile flag HASURANDOMDEV is not set +(see sendmail/README). .ip ResolverOptions=\fIoptions\fP [I] Set resolver options. @@ -6399,7 +6573,7 @@ .i user Also, all file and program deliveries will be marked unsafe unless the option -.b DontBlameSendmail=NonRootAddrSafe +.b DontBlameSendmail=NonRootSafeAddr is set, in which case the delivery will be done as .i user . @@ -6468,7 +6642,7 @@ .ip SaveFromLine [f] Save -Unix-style +UNIX-style .q From lines at the front of headers. Normally they are assumed redundant @@ -6482,6 +6656,13 @@ will not return the DSN keyword in response to an EHLO and will not do Delivery Status Notification processing as described in RFC1891. +.ip ServerCertFile +[no short name] +File containing the certificate of the server, i.e., this certificate +is used when sendmail acts as server. +.ip ServerKeyFile +[no short name] +File containing the private key belonging to the server certificate. .ip ServiceSwitchFile=\fIfilename\fP [no short name] If your host operating system has a service switch abstraction @@ -6653,13 +6834,13 @@ (very unlikely). .ip UnsafeGroupWrites [no short name] -If set, +If set (default), :include: and .forward files that are group writable are considered .q unsafe , that is, they cannot reference programs or write directly to files. World writable :include: and .forward files -are always unsafe.. +are always unsafe. .ip UseErrorsTo [l] If there is an @@ -7114,7 +7295,7 @@ Mark Roth, roth@uiuc.edu. For more information, consult the web site -.q http://www-wsg.cso.uiuc.edu/sendmail/sendmail-phmap/ . +.q http://www-dev.cso.uiuc.edu/sendmail/ . .ip nsd nsd map for IRIX 6.5 and later. Contributed and supported by Bob Mende of SGI, @@ -7258,6 +7439,14 @@ .(b -s1,3,4 .)b +Notes: to match a +.b $ +in a string, +\\$$ +must be used. +If the pattern contains spaces, they must be replaced +with the blank substitution character, unless it is +space itself. .ip program The arguments on the .b K @@ -7489,6 +7678,10 @@ Set search scope to one of base, one (one level), or sub (subtree). .ip "\-h\fIhost\fP" LDAP server hostname. +Some LDAP libraries allow you to specify multiple, space-separated hosts for +redundancy. +In addition, each of the hosts listed can be followed by a colon and a port +number to override the default LDAP port. .ip "\-b\fIbase\fP" LDAP search base. .ip "\-p\fIport\fP" @@ -7791,6 +7984,14 @@ .ip SASL Compile in support for SASL, a required component for SMTP Authentication support. +.ip STARTTLS +Compile in support for STARTTLS. +.ip EGD +Compile in support for the "Entropy Gathering Daemon" +to provide better random data for TLS. +.ip SFIO +Compile in support for sfio, which is required to enable encryption, +e.g., STARTTLS. .ip TCPWRAPPERS Compile in support for TCP Wrappers. .ip _PATH_SENDMAILCF @@ -7851,6 +8052,7 @@ .ip "MAXMAILERS [25]" The maximum number of mailers that may be defined in the configuration file. +This value is defined in include/sendmail/sendmail.h. .ip "MAXRWSETS [200]" The maximum number of rewriting sets that may be defined. @@ -7911,6 +8113,7 @@ .ip NETINET6\(dg If set, support for IPv6 networking is compiled in. +It must be separately enabled by adding DaemonPortOptions settings. .ip NETISO\(dg If set, support for ISO protocol networking is compiled in @@ -8493,6 +8696,92 @@ .b $] lookups. We now recommend that you create a new keyed map instead. +.sh 2 "Certificates for STARTTLS" +.pp +In this section we assume that +.i sendmail +has been compiled with support for STARTTLS. +When acting as a server, +.i sendmail +requires X.509 certificates to support STARTTLS: +one as certificate for the server (ServerCertFile) +at least one root CA (CACERTFile), +i.e., a certificate that is used to sign other certificates, +and a path to a directory which contains other CAs (CACERTPath). +The file specified via +CACERTFile +can contain several certificates of CAs. +The DNs of these certificates are sent +to the client during the TLS handshake (as part of the +CertificateRequest) as the list of acceptable CAs. +The CACERTPath directory must contain the hashes of each CA certificate +as filenames (or as links to them). +Symbolic links can be generated with the following +two (Bourne) shell commands: +.(b +C=FileName_of_CA_Certificate +ln -s $C `openssl x509 -noout -hash < $C`.0 +.)b +An X.509 certificate is also required for authentication in client mode +(ClientCertFile), however, +.i sendmail +will always use STARTTLS when offered by a server. +The client and server certificates can be identical. +Certificates can be obtained from a certificate authority +or created with the help of OpenSSL. +The required format for certificates and private keys is PEM. +To allow for automatic startup of sendmail, private keys +(ServerKeyFile, ClientKeyFile) +must be stored unencrypted. +The keys are only protected by the permissions of the file system. +Never make a private key available to a third party. +.sh 2 "PRNG for STARTTLS" +.pp +STARTTLS requires a strong pseudo random number generator (PRNG) +to operate properly. +Depending on the TLS library you use, it may be required to explicitly +initialize the PRNG with random data. +OpenSSL makes use of +.b /dev/urandom(4) +if available (this corresponds to the compile flag HASURANDOMDEV). +On systems which lack this support, a random file must be specified in the +.i sendmail.cf +file using the option RandFile. +It is +.b strongly +advised to use the "Entropy Gathering Daemon" EGD +from Brian Warner on those systems to provide useful random data. +In this case, +.i sendmail +must be compiled with the flag EGD, and the +RandFile option must point to the EGD socket. +If neither +.b /dev/urandom(4) +nor EGD are available, you have to make sure +that useful random data is available all the time in RandFile. +If the file hasn't been modified in the last 10 minutes before +it is supposed to be used by +.i sendmail +the content is considered obsolete. +One method for generating this file is: +.(b +openssl rand -out /etc/mail/randfile -rand \c +.i /path/to/file:... \c +256 +.)b +See the OpenSSL documentation for more information. +In this case, the PRNG for TLS is only +seeded with other random data if the +.b DontBlameSendmail +option +.b InsufficientEntropy +is set. +This is most likely not sufficient for certain actions, e.g., +generation of (temporary) keys. +.pp +Please see the OpenSSL documentation or other sources +for further information about certificates, their creation and their usage, +the importance of a good PRNG, and other aspects of TLS. .sh 1 "ACKNOWLEDGEMENTS" .pp I've worked on @@ -8685,7 +8974,7 @@ .i value (for long form option names). These options are described in Section 5.6. -.ip \-M\fIx\|value +.ip \-M\fIx\|value\fP Set macro .i x to the specified @@ -8859,7 +9148,7 @@ .ip N Envelope number .ip PPPPP -First five digits of the process ID +At least five digits of the process ID .pp All files with the same id collectively define one message. If memory-buffered files are available, @@ -8901,6 +9190,11 @@ Defaults to version zero. Must be the first line of the file if present. For 8.10 the version number is 4. +.ip A +The information given by the AUTH= parameter of the +.q "MAIL FROM:" +command or $f@$j +if sendmail has been called directly. .ip H A header definition. There may be any number of these lines. @@ -8982,10 +9276,6 @@ .ip $ A macro definition. The values of certain macros -(as of this writing, only -.b $r -and -.b $s ) are passed through to the queue run phase. .ip B The body type. @@ -9013,26 +9303,31 @@ nothing can replace looking at what your own system generates. .)f .(b -P835771 -T404261372 +V4 +T711358135 +K904446490 +N0 +P2100941 +$_eric@localhost +${daemon_flags} Seric -Ceric:sendmail@vangogh.CS.Berkeley.EDU -Reric@mammoth.Berkeley.EDU -Rbostic@okeeffe.CS.Berkeley.EDU -H?P?Return-path: -HReceived: by vangogh.CS.Berkeley.EDU (5.108/2.7) id AAA06703; +Ceric:100:1000:sendmail@vangogh.CS.Berkeley.EDU +RPFD:eric@mammoth.Berkeley.EDU +RPFD:bostic@okeeffe.CS.Berkeley.EDU +H?P?Return-path: <^g> +H??Received: by vangogh.CS.Berkeley.EDU (5.108/2.7) id AAA06703; Fri, 17 Jul 1992 00:28:55 -0700 -HReceived: from mail.CS.Berkeley.EDU by vangogh.CS.Berkeley.EDU (5.108/2.7) +H??Received: from mail.CS.Berkeley.EDU by vangogh.CS.Berkeley.EDU (5.108/2.7) id AAA06698; Fri, 17 Jul 1992 00:28:54 -0700 -HReceived: from [128.32.31.21] by mail.CS.Berkeley.EDU (5.96/2.5) +H??Received: from [128.32.31.21] by mail.CS.Berkeley.EDU (5.96/2.5) id AA22777; Fri, 17 Jul 1992 03:29:14 -0400 -HReceived: by foo.bar.baz.de (5.57/Ultrix3.0-C) +H??Received: by foo.bar.baz.de (5.57/Ultrix3.0-C) id AA22757; Fri, 17 Jul 1992 09:31:25 GMT H?F?From: eric@foo.bar.baz.de (Eric Allman) H?x?Full-name: Eric Allman -HMessage-id: <9207170931.AA22757@foo.bar.baz.de> -HTo: sendmail@vangogh.CS.Berkeley.EDU -HSubject: this is an example message +H??Message-id: <9207170931.AA22757@foo.bar.baz.de> +H??To: sendmail@vangogh.CS.Berkeley.EDU +H??Subject: this is an example message .)b This shows the person who sent the message, @@ -9130,7 +9425,7 @@ .\".sz 10 .\"Eric Allman .\".sp -.\"Version $Revision: 1.3 $ +.\"Version $Revision: 1.6 $ .\".ce 0 .bp 3 .ce Index: gnu/usr.sbin/sendmail/include/libmilter/mfapi.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/include/libmilter/mfapi.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/include/libmilter/mfapi.h 2000/04/02 19:05:49 1.1.1.1 +++ gnu/usr.sbin/sendmail/include/libmilter/mfapi.h 2001/01/15 21:09:01 1.2 @@ -7,7 +7,7 @@ * the sendmail distribution. * * - * $Sendmail: mfapi.h,v 8.13 2000/02/26 19:13:36 gshapiro Exp $ + * $Sendmail: mfapi.h,v 8.13.4.12 2000/09/09 02:11:48 ca Exp $ */ /* @@ -17,126 +17,75 @@ #ifndef _LIBMILTER_MFAPI_H # define _LIBMILTER_MFAPI_H 1 -/* -** Access common MTA/libmilter constants -*/ +# define LIBMILTER_API extern -# include "libmilter/milter.h" - -/* -** Currently this is a C-fied version of ~eric/public_html/mfapi.html -** It does not (yet) conform with the coding standard... -*/ -/* -** status codes -*/ +# include -/* XXX maybe use enum? */ +#ifndef _SOCK_ADDR +# include +# define _SOCK_ADDR struct sockaddr +#endif /* ! _SOCK_ADDR */ /* -** Continue processing message/connection. +** libmilter functions return one of the following to indicate +** success/failure: */ -#define SMFIS_CONTINUE 0 - -/* -** Reject the message/connection. -** No further routines will be called for this message -** (or connection, if returned from a connection-oriented routine). -*/ +#define MI_SUCCESS 0 +#define MI_FAILURE (-1) -#define SMFIS_REJECT 1 - -/* -** Accept the message, -** but silently discard the message. -** No further routines will be called for this message. -** This is only meaningful from message-oriented routines. -*/ - -#define SMFIS_DISCARD 2 +/* "forward" declarations */ +typedef struct smfi_str SMFICTX; +typedef struct smfi_str *SMFICTX_PTR; -/* -** Accept the message/connection. -** No further routines will be called for this message -** (or connection, if returned from a connection-oriented routine; -** in this case, it causes all messages on this connection -** to be accepted without filtering). -*/ +typedef struct smfiDesc smfiDesc_str; +typedef struct smfiDesc *smfiDesc_ptr; -#define SMFIS_ACCEPT 3 +#define SMFI_VERSION 2 /* version number */ /* -** Return a temporary failure, i.e., -** the corresponding SMTP command will return a 4xx status code. -** In some cases this may prevent further routines from -** being called on this message or connection, -** although in other cases (e.g., when processing an envelope -** recipient) processing of the message will continue. +** What the filter might do -- values to be ORed together for +** smfiDesc.xxfi_flags. */ -#define SMFIS_TEMPFAIL 4 - -/* type to store return value */ -typedef int sfsistat; - -/* for now ... */ -#if SOCKADDRHACK -# ifndef _SOCK_ADDR -# define _SOCK_ADDR struct sockaddr_in -# endif /* !_SOCK_ADDR */ -#else /* SOCKADDRHACK */ -# define NOT_SENDMAIL 1 -# include "sendmail.h" -# define _SOCK_ADDR SOCKADDR -#endif /* SOCKADDRHACK */ - -#include - -#ifndef MI_SUCCESS -# define MI_SUCCESS 0 -#endif /* MI_SUCCESS */ -#ifndef MI_FAILURE -# define MI_FAILURE (-1) -#endif /* MI_FAILURE */ - -/* "forward" declarations */ -typedef struct smfi_str SMFICTX; -typedef struct smfi_str *SMFICTX_PTR; -typedef struct smfiDesc smfiDesc_str; -typedef struct smfiDesc * smfiDesc_ptr; +#define SMFIF_ADDHDRS 0x00000001L /* filter may add headers */ +#define SMFIF_CHGBODY 0x00000002L /* filter may replace body */ +#define SMFIF_MODBODY SMFIF_CHGBODY /* backwards compatible */ +#define SMFIF_ADDRCPT 0x00000004L /* filter may add recipients */ +#define SMFIF_DELRCPT 0x00000008L /* filter may delete recipients */ +#define SMFIF_CHGHDRS 0x00000010L /* filter may change/delete headers */ -# define MAX_MACROS_ENTRIES 4 /* max size of macro pointer array */ +#define SMFI_V1_ACTS 0x0000000FL /* The actions of V1 filter */ +#define SMFI_V2_ACTS 0x0000001FL /* The actions of V2 filter */ +#define SMFI_CURR_ACTS SMFI_V2_ACTS /* The current version */ /* -** context for milter -** implementation hint: -** macros are stored in mac_buf[] as sequence of: -** macro_name \0 macro_value -** (just as read from the MTA) -** mac_ptr is a list of pointers into mac_buf to the beginning of each -** entry, i.e., macro_name, macro_value, ... +** Type which callbacks should return to indicate message status. +** This may take on one of the SMFIS_* values listed below. */ -struct smfi_str -{ - pthread_t ctx_id; /* thread id */ - int ctx_fd; /* filedescriptor */ - int ctx_dbg; /* debug level */ - time_t ctx_timeout; /* timeout */ - int ctx_state; /* state */ - smfiDesc_ptr ctx_smfi; /* filter description */ - char **ctx_mac_ptr[MAX_MACROS_ENTRIES]; - char *ctx_mac_buf[MAX_MACROS_ENTRIES]; - char *ctx_reply; /* reply code */ - void *ctx_privdata; /* private data */ -}; +typedef int sfsistat; /* ** structure describing one milter */ +#if defined(__linux__) && defined(__GNUC__) && defined(__cplusplus) && __GNUC_MINOR__ >= 8 +# define SM__P(X) __PMT(X) +#else /* __linux__ && __GNUC__ && __cplusplus && _GNUC_MINOR__ >= 8 */ +# define SM__P(X) __P(X) +#endif /* __linux__ && __GNUC__ && __cplusplus && _GNUC_MINOR__ >= 8 */ + +/* Some platforms don't define __P -- do it for them here: */ +#ifndef __P +# ifdef __STDC__ +# define __P(X) X +# else /* __STDC__ */ +# define __P(X) () +# endif /* __STDC__ */ +#endif /* __P */ + struct smfiDesc { char *xxfi_name; /* filter name */ @@ -144,64 +93,92 @@ u_long xxfi_flags; /* flags */ /* connection info filter */ - sfsistat (*xxfi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); + sfsistat (*xxfi_connect) SM__P((SMFICTX *, char *, _SOCK_ADDR *)); /* SMTP HELO command filter */ - sfsistat (*xxfi_helo) __P((SMFICTX *, char *)); + sfsistat (*xxfi_helo) SM__P((SMFICTX *, char *)); /* envelope sender filter */ - sfsistat (*xxfi_envfrom) __P((SMFICTX *, char **)); + sfsistat (*xxfi_envfrom) SM__P((SMFICTX *, char **)); /* envelope recipient filter */ - sfsistat (*xxfi_envrcpt) __P((SMFICTX *, char **)); + sfsistat (*xxfi_envrcpt) SM__P((SMFICTX *, char **)); /* header filter */ - sfsistat (*xxfi_header) __P((SMFICTX *, char *, char *)); + sfsistat (*xxfi_header) SM__P((SMFICTX *, char *, char *)); /* end of header */ - sfsistat (*xxfi_eoh) __P((SMFICTX *)); + sfsistat (*xxfi_eoh) SM__P((SMFICTX *)); /* body block */ - sfsistat (*xxfi_body) __P((SMFICTX *, u_char *, size_t)); + sfsistat (*xxfi_body) SM__P((SMFICTX *, u_char *, size_t)); /* end of message */ - sfsistat (*xxfi_eom) __P((SMFICTX *)); + sfsistat (*xxfi_eom) SM__P((SMFICTX *)); /* message aborted */ - sfsistat (*xxfi_abort) __P((SMFICTX *)); + sfsistat (*xxfi_abort) SM__P((SMFICTX *)); /* connection cleanup */ - sfsistat (*xxfi_close) __P((SMFICTX *)); + sfsistat (*xxfi_close) SM__P((SMFICTX *)); }; -#if 0 -simple example what a filter program should do: +LIBMILTER_API int smfi_register __P((struct smfiDesc)); +LIBMILTER_API int smfi_main __P((void)); +LIBMILTER_API int smfi_setdbg __P((int)); +LIBMILTER_API int smfi_settimeout __P((int)); +LIBMILTER_API int smfi_setconn __P((char *)); +LIBMILTER_API int smfi_stop __P((void)); -int -main(argc, argv) - int argc; - char **argv; -{ - struct smfiDesc XxFilterDesc; +/* +** Continue processing message/connection. +*/ - /* fill in elements */ - smfi_register(XxFilterDesc); - smfi_main(); - /* NOTREACHED */ -} -#endif /* 0 */ +#define SMFIS_CONTINUE 0 + +/* +** Reject the message/connection. +** No further routines will be called for this message +** (or connection, if returned from a connection-oriented routine). +*/ -extern int smfi_register __P((smfiDesc_str)); -extern int smfi_main __P((void)); -extern int smfi_setdbg __P((int)); -extern int smfi_settimeout __P((int)); -extern int smfi_setconn __P((char *)); +#define SMFIS_REJECT 1 /* -** Filter Routine Details +** Accept the message, +** but silently discard the message. +** No further routines will be called for this message. +** This is only meaningful from message-oriented routines. +*/ + +#define SMFIS_DISCARD 2 + +/* +** Accept the message/connection. +** No further routines will be called for this message +** (or connection, if returned from a connection-oriented routine; +** in this case, it causes all messages on this connection +** to be accepted without filtering). */ +#define SMFIS_ACCEPT 3 + +/* +** Return a temporary failure, i.e., +** the corresponding SMTP command will return a 4xx status code. +** In some cases this may prevent further routines from +** being called on this message or connection, +** although in other cases (e.g., when processing an envelope +** recipient) processing of the message will continue. +*/ + +#define SMFIS_TEMPFAIL 4 + #if 0 +/* +** Filter Routine Details +*/ + /* connection info filter */ extern sfsistat xxfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); @@ -265,7 +242,6 @@ /* ** xxfi_eoh(ctx) Invoked at end of header */ -#endif /* 0 */ /* body block */ extern sfsistat xxfi_body __P((SMFICTX *, u_char *, size_t)); @@ -304,7 +280,7 @@ ** xxfi_close(ctx) Invoked at end of the connection. This is called on ** close even if the previous mail transaction was aborted. */ - +#endif /* 0 */ /* ** Additional information is passed in to the vendor filter routines using @@ -313,7 +289,7 @@ */ /* Return the value of a symbol. */ -extern char * smfi_getsymval __P((SMFICTX *, char *)); +LIBMILTER_API char * smfi_getsymval __P((SMFICTX *, char *)); /* ** Return the value of a symbol. @@ -327,7 +303,7 @@ ** the MTA for use in SMTP replies may call smfi_setreply before returning. */ -extern int smfi_setreply __P((SMFICTX *, char *, char *, char *)); +LIBMILTER_API int smfi_setreply __P((SMFICTX *, char *, char *, char *)); /* ** Set the specific reply code to be used in response to the active @@ -348,7 +324,7 @@ ** routine other than xxfi_eom. */ -extern int smfi_addheader __P((SMFICTX *, char *, char *)); +LIBMILTER_API int smfi_addheader __P((SMFICTX *, char *, char *)); /* ** Add a header to the message. This header is not passed to other @@ -360,8 +336,21 @@ ** char *headerf; Header field name ** char *headerv; Header field value */ + +LIBMILTER_API int smfi_chgheader __P((SMFICTX *, char *, int, char *)); + +/* +** Change/delete a header in the message. It is not checked for standards +** compliance; the mail filter must ensure that no protocols are violated +** as a result of adding this header. +** +** SMFICTX *ctx; Opaque context structure +** char *headerf; Header field name +** int index; The Nth occurence of header field name +** char *headerv; New header field value (empty for delete header) +*/ -extern int smfi_addrcpt __P((SMFICTX *, char *)); +LIBMILTER_API int smfi_addrcpt __P((SMFICTX *, char *)); /* ** Add a recipient to the envelope @@ -370,7 +359,7 @@ ** char *rcpt; Recipient to be added */ -extern int smfi_delrcpt __P((SMFICTX *, char *)); +LIBMILTER_API int smfi_delrcpt __P((SMFICTX *, char *)); /* ** Delete a recipient from the envelope @@ -381,7 +370,7 @@ ** not be deleted. */ -extern int smfi_replacebody __P((SMFICTX *, u_char *, int)); +LIBMILTER_API int smfi_replacebody __P((SMFICTX *, u_char *, int)); /* ** Replace the body of the message. This routine may be called multiple @@ -405,7 +394,7 @@ ** data using smfi_getpriv. */ -extern int smfi_setpriv __P((SMFICTX *, void *)); +LIBMILTER_API int smfi_setpriv __P((SMFICTX *, void *)); /* ** Set the private data pointer @@ -413,7 +402,8 @@ ** SMFICTX *ctx; Opaque context structure ** void *privatedata; Pointer to private data area */ + +LIBMILTER_API void *smfi_getpriv __P((SMFICTX *)); -extern void *smfi_getpriv __P((SMFICTX *)); #endif /* !_LIBMILTER_MFAPI_H */ Index: gnu/usr.sbin/sendmail/include/libmilter/milter.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/include/libmilter/milter.h,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/include/libmilter/milter.h 2000/04/02 19:05:49 1.1.1.1 +++ gnu/usr.sbin/sendmail/include/libmilter/milter.h 2001/05/29 01:31:12 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -7,7 +7,7 @@ * the sendmail distribution. * * - * $Sendmail: milter.h,v 8.24 1999/11/28 05:54:20 gshapiro Exp $ + * $Sendmail: milter.h,v 8.24.16.9 2001/03/02 21:22:48 geir Exp $ */ /* @@ -17,10 +17,13 @@ #ifndef _LIBMILTER_MILTER_H # define _LIBMILTER_MILTER_H 1 +#include "libmilter/mfapi.h" +#include "sendmail.h" + /* Shared protocol constants */ # define MILTER_LEN_BYTES 4 /* length of 32 bit integer in bytes */ +# define MILTER_OPTLEN (MILTER_LEN_BYTES * 3) /* length of options */ # define MILTER_CHUNK_SIZE 65535 /* body chunk size */ -# define SMFI_VERSION 1 /* version number */ /* address families */ # define SMFIA_UNKNOWN 'U' /* unknown */ @@ -49,22 +52,56 @@ # define SMFIR_REPLBODY 'b' /* replace body (chunk) */ # define SMFIR_CONTINUE 'c' /* continue */ # define SMFIR_DISCARD 'd' /* discard */ +# define SMFIR_CHGHEADER 'm' /* change header */ # define SMFIR_PROGRESS 'p' /* progress */ # define SMFIR_REJECT 'r' /* reject */ # define SMFIR_TEMPFAIL 't' /* tempfail */ # define SMFIR_ADDHEADER 'h' /* add header */ # define SMFIR_REPLYCODE 'y' /* reply code etc */ + +/* What the MTA can send/filter wants in protocol */ +# define SMFIP_NOCONNECT 0x00000001L /* MTA should not send connect info */ +# define SMFIP_NOHELO 0x00000002L /* MTA should not send HELO info */ +# define SMFIP_NOMAIL 0x00000004L /* MTA should not send MAIL info */ +# define SMFIP_NORCPT 0x00000008L /* MTA should not send RCPT info */ +# define SMFIP_NOBODY 0x00000010L /* MTA should not send body */ +# define SMFIP_NOHDRS 0x00000020L /* MTA should not send headers */ +# define SMFIP_NOEOH 0x00000040L /* MTA should not send EOH */ + +# define SMFI_V1_PROT 0x0000003FL /* The protocol of V1 filter */ +# define SMFI_V2_PROT 0x0000007FL /* The protocol of V2 filter */ +# define SMFI_CURR_PROT SMFI_V2_PROT /* The current version */ + +/* socket and thread portability */ +# include +typedef pthread_t sthread_t; +typedef int socket_t; + +# define MAX_MACROS_ENTRIES 4 /* max size of macro pointer array */ + +/* +** context for milter +** implementation hint: +** macros are stored in mac_buf[] as sequence of: +** macro_name \0 macro_value +** (just as read from the MTA) +** mac_ptr is a list of pointers into mac_buf to the beginning of each +** entry, i.e., macro_name, macro_value, ... +*/ -/* values for filter negotiation flags */ -# define SMFIF_MODHDRS 0x00000001L /* filter may add headers */ -# define SMFIF_MODBODY 0x00000002L /* filter may replace body */ -# define SMFIF_ADDRCPT 0x00000004L /* filter may add recipients */ -# define SMFIF_DELRCPT 0x00000008L /* filter may delete recipients */ -# define SMFIF_NOCONNECT 0x00000010L /* MTA should not send connect info */ -# define SMFIF_NOHELO 0x00000020L /* MTA should not send HELO info */ -# define SMFIF_NOMAIL 0x00000040L /* MTA should not send MAIL info */ -# define SMFIF_NORCPT 0x00000080L /* MTA should not send RCPT info */ -# define SMFIF_NOBODY 0x00000100L /* MTA should not send body */ -# define SMFIF_NOHDRS 0x00000200L /* MTA should not send headers */ +struct smfi_str +{ + sthread_t ctx_id; /* thread id */ + socket_t ctx_sd; /* socket descriptor */ + int ctx_dbg; /* debug level */ + time_t ctx_timeout; /* timeout */ + int ctx_state; /* state */ + smfiDesc_ptr ctx_smfi; /* filter description */ + u_long ctx_pflags; /* protocol flags */ + char **ctx_mac_ptr[MAX_MACROS_ENTRIES]; + char *ctx_mac_buf[MAX_MACROS_ENTRIES]; + char *ctx_reply; /* reply code */ + void *ctx_privdata; /* private data */ +}; #endif /* !_LIBMILTER_MILTER_H */ Index: gnu/usr.sbin/sendmail/include/libsmdb/smdb.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/include/libsmdb/smdb.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/include/libsmdb/smdb.h 2000/04/07 19:20:33 1.2 +++ gnu/usr.sbin/sendmail/include/libsmdb/smdb.h 2001/01/15 21:09:01 1.3 @@ -6,7 +6,7 @@ ** forth in the LICENSE file which can be found at the top level of ** the sendmail distribution. ** -** $Sendmail: smdb.h,v 8.29 2000/03/17 07:32:42 gshapiro Exp $ +** $Sendmail: smdb.h,v 8.29.2.1.2.2 2000/10/05 22:23:55 gshapiro Exp $ */ #ifndef _SMDB_H_ @@ -18,6 +18,12 @@ # include "sendmail/cdefs.h" # endif /* __P */ +# ifndef NDBM +# ifndef NEWDB +ERROR NDBM or NEWDB must be defined. +# endif /* ! NEWDB */ +# endif /* ! NDBM */ + # ifdef NDBM # include # endif /* NDBM */ @@ -47,7 +53,7 @@ typedef struct database_struct SMDB_DATABASE; typedef struct cursor_struct SMDB_CURSOR; -typedef union database_entity_union SMDB_DBENT; +typedef struct entry_struct SMDB_DBENT; /* @@ -183,6 +189,7 @@ typedef int (*db_cursor_func) __P((SMDB_DATABASE *db, SMDB_CURSOR **cursor, u_int flags)); +typedef int (*db_lockfd_func) __P((SMDB_DATABASE *db)); struct database_struct { @@ -194,6 +201,7 @@ db_sync_func smdb_sync; db_set_owner_func smdb_set_owner; db_cursor_func smdb_cursor; + db_lockfd_func smdb_lockfd; void *smdb_impl; }; @@ -304,22 +312,12 @@ typedef struct database_user_struct SMDB_USER_INFO; -union database_entity_union +struct entry_struct { -# ifdef NDBM - datum dbm; -# endif /* NDBM */ -# ifdef NEWDB - DBT db; -# endif /* NEWDB */ - struct - { - char *data; - size_t size; - } data; + void *data; + size_t size; }; - typedef char *SMDB_DBTYPE; typedef u_int SMDB_FLAG; @@ -370,4 +368,6 @@ struct stat *)); extern void smdb_print_available_types __P((void)); extern char *smdb_db_definition __P((SMDB_DBTYPE)); +extern int smdb_lock_map __P((SMDB_DATABASE *, int)); +extern int smdb_unlock_map __P((SMDB_DATABASE *)); #endif /* ! _SMDB_H_ */ Index: gnu/usr.sbin/sendmail/include/sendmail/pathnames.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/include/sendmail/pathnames.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/include/sendmail/pathnames.h 2000/04/02 19:05:49 1.1.1.1 +++ gnu/usr.sbin/sendmail/include/sendmail/pathnames.h 2001/01/15 21:09:02 1.2 @@ -9,26 +9,28 @@ * the sendmail distribution. * * - * $Sendmail: pathnames.h,v 8.16 2000/02/01 05:49:50 gshapiro Exp $ + * $Sendmail: pathnames.h,v 8.16.8.8 2000/09/28 21:26:39 gshapiro Exp $ */ -#ifndef _PATH_SENDMAILCF -# if defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) -# define _PATH_SENDMAILCF _PATH_VENDOR_CF -# else /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ -# define _PATH_SENDMAILCF "/etc/mail/sendmail.cf" -# endif /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ -#endif /* ! _PATH_SENDMAILCF */ -#ifndef _PATH_SENDMAILPID -# ifdef BSD4_4 -# define _PATH_SENDMAILPID "/var/run/sendmail.pid" -# else /* BSD4_4 */ -# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" -# endif /* BSD4_4 */ -#endif /* ! _PATH_SENDMAILPID */ +# ifndef _PATH_SENDMAILCF +# if defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) +# define _PATH_SENDMAILCF _PATH_VENDOR_CF +# else /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ +# define _PATH_SENDMAILCF "/etc/mail/sendmail.cf" +# endif /* defined(USE_VENDOR_CF_PATH) && defined(_PATH_VENDOR_CF) */ +# endif /* ! _PATH_SENDMAILCF */ -#ifndef _PATH_HOSTS -# define _PATH_HOSTS "/etc/hosts" -#endif /* ! _PATH_HOSTS */ +# ifndef _PATH_SENDMAILPID +# ifdef BSD4_4 +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" +# else /* BSD4_4 */ +# define _PATH_SENDMAILPID "/etc/mail/sendmail.pid" +# endif /* BSD4_4 */ +# endif /* ! _PATH_SENDMAILPID */ + +# ifndef _PATH_HOSTS +# define _PATH_HOSTS "/etc/hosts" +# endif /* ! _PATH_HOSTS */ + Index: gnu/usr.sbin/sendmail/include/sendmail/sendmail.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/include/sendmail/sendmail.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/include/sendmail/sendmail.h 2000/04/07 19:20:34 1.2 +++ gnu/usr.sbin/sendmail/include/sendmail/sendmail.h 2001/01/15 21:09:02 1.3 @@ -10,14 +10,18 @@ * the sendmail distribution. * * - * $Sendmail: sendmail.h,v 8.34 2000/03/16 22:05:28 gshapiro Exp $ + * $Sendmail: sendmail.h,v 8.34.4.7 2000/10/09 16:15:26 gshapiro Exp $ */ /* ** SENDMAIL.H -- Global definitions for sendmail. */ +#if SFIO +# include +#else /* SFIO */ # include +#endif /* SFIO */ #include #include "conf.h" #include "sendmail/errstring.h" @@ -49,6 +53,9 @@ typedef unsigned int BITMAP256[BITMAPBYTES / sizeof (int)]; +/* properly case and truncate bit */ +#define bitidx(bit) ((unsigned int) (bit) & 0xff) + /* test bit number N */ #define bitnset(bit, map) ((map)[_BITWORD(bit)] & _BITBIT(bit)) @@ -144,9 +151,16 @@ #define DBS_NONROOTSAFEADDR 31 #define DBS_TRUSTSTICKYBIT 32 #define DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH 33 +#define DBS_INSUFFICIENTENTROPY 34 #if _FFR_UNSAFE_SASL -#define DBS_GROUPREADABLESASLFILE 34 +# define DBS_GROUPREADABLESASLFILE 35 #endif /* _FFR_UNSAFE_SASL */ +#if _FFR_UNSAFE_WRITABLE_INCLUDE +# define DBS_GROUPWRITABLEFORWARDFILE 36 +# define DBS_GROUPWRITABLEINCLUDEFILE 37 +# define DBS_WORLDWRITABLEFORWARDFILE 38 +# define DBS_WORLDWRITABLEINCLUDEFILE 39 +#endif /* _FFR_UNSAFE_WRITABLE_INCLUDE */ /* struct defining such things */ struct dbsval @@ -163,11 +177,10 @@ #define dflush() fflush(stdout) #endif /* _FFR_DPRINTF */ -#if !HASSNPRINTF -extern int snprintf __P((char *, size_t, const char *, ...)); -extern int vsnprintf __P((char *, size_t, const char *, va_list)); -#endif /* !HASSNPRINTF */ +extern int sm_snprintf __P((char *, size_t, const char *, ...)); +extern int sm_vsnprintf __P((char *, size_t, const char *, va_list)); extern char *quad_to_string __P((QUAD_T)); extern size_t strlcpy __P((char *, const char *, size_t)); extern size_t strlcat __P((char *, const char *, size_t)); + Index: gnu/usr.sbin/sendmail/libmilter/README =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/README,v retrieving revision 1.3 retrieving revision 1.6 diff -u -r1.3 -r1.6 --- gnu/usr.sbin/sendmail/libmilter/README 2000/04/07 19:20:34 1.3 +++ gnu/usr.sbin/sendmail/libmilter/README 2001/05/29 01:31:12 1.6 @@ -10,7 +10,7 @@ issuing the './Build' command in SRCDIR/libmilter . NOTE: Both libmilter and the callouts in sendmail are marked as an FFR (For -Future Release). If you intend to use them in 8.10.X, you must compiled +Future Release). If you intend to use them in 8.11.X, you must compiled both libmilter and sendmail with -D_FFR_MILTER defined. You can do this by adding the following to your devtools/Site/site.config.m4 file: @@ -18,6 +18,9 @@ APPENDDEF(`conf_sendmail_ENVDEF', `-D_FFR_MILTER=1') APPENDDEF(`conf_libmilter_ENVDEF', `-D_FFR_MILTER=1') +You will also need to define _FFR_MILTER when building your .cf file using +m4. + +-------------------+ | BUILDING A FILTER | +-------------------+ @@ -32,7 +35,8 @@ the sendmail source tree. Modify the compiler include references (-I) and the library locations accordingly. Also, some operating systems may require additional libraries. For example, SunOS 5.X requires '-lresolv --lsocket -lnsl'. +-lsocket -lnsl'. Depending on your OS you may need a library instead +of the option -pthread, e.g., -lpthread. Filters must be thread-safe! Many operating systems now provide support for POSIX threads in the standard C libraries. The compiler flag to link with @@ -40,6 +44,11 @@ the Makefile in your appropriate obj.*/libmilter build subdirectory if you are unsure of the local flag used. +Note that since filters use threads, it may be necessary to alter per +process limits in your filter. For example, you might look at using +setrlimit() to increase the number of open file descriptors if your filter +is going to be busy. + +----------------------------------------+ | SPECIFYING FILTERS IN SENDMAIL CONFIGS | @@ -49,14 +58,14 @@ For example: - Xfilter1, S=unix:/var/run/f1.sock, F=R + Xfilter1, S=local:/var/run/f1.sock, F=R Xfilter2, S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m Xfilter3, S=inet:3333@localhost specifies three filters. Filters can be specified in your .mc file using the following: - INPUT_MAIL_FILTER(`filter1', `S=unix:/var/run/f1.sock, F=R') + INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R') INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=S:1s;R:1s;E:5m') INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') @@ -67,6 +76,9 @@ R Reject connection if filter unavailable T Temporary fail connection if filter unavailable +If neither F=R nor F=T is specified, the message is passed through sendmail +as if the filter were not present. + Finally, you can override the default timeouts used by sendmail when talking to the filters using the T= equate. There are three fields inside of the T= equate: @@ -84,13 +96,18 @@ where 's' is seconds and 'm' is minutes. -Actual sequencing is handled by the InputMailFilters option which is set -automatically according to the order of the INPUT_MAIL_FILTER commands -in your .mc file. Alternatively, you can reset it's value by setting -confINPUT_MAIL_FILTERS in your .mc file. This options causes the three -filters to be called in the same order they were specified. It allows -for possible future filtering on output (although this is not intended -for this release). +Which filters are invoked and their sequencing is handled by the +InputMailFilters option. Note: if InputMailFilters is not defined no filters +will be used. + + O InputMailFilters=filter1, filter2, filter3 + +This is is set automatically according to the order of the +INPUT_MAIL_FILTER commands in your .mc file. Alternatively, you can +reset its value by setting confINPUT_MAIL_FILTERS in your .mc file. +This options causes the three filters to be called in the same order +they were specified. It allows for possible future filtering on output +(although this is not intended for this release). Also note that a filter can be defined without adding it to the input filter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your @@ -99,7 +116,7 @@ To test sendmail with the sample filter, the following might be added (in the appropriate locations) to your .mc file: - INPUT_MAIL_FILTER(`sample', `S=unix:/var/run/f1.sock') + INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock') +------------------+ @@ -115,7 +132,7 @@ consistency with the suggested options for sendmail.cf, this would be the UNIX domain socket located in /var/run/f1.sock. - % ./sample -p unix:/var/run/f1.sock + % ./sample -p local:/var/run/f1.sock If the sample filter returns immediately to a command line, there was either an error with your command or a problem creating the specified socket. @@ -130,7 +147,7 @@ the use of standard SMTP commands. % sendmail -bs -220 test.sendmail.com ESMTP Sendmail 8.10.0.Beta8/8.10.0.Beta8; Mon, 6 Dec 1999 19:34:23 -0800 (PST) +220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST) HELO localhost 250 test.sendmail.com Hello testy@localhost, pleased to meet you MAIL From: @@ -167,10 +184,30 @@ | SOURCE FOR SAMPLE FILTER | +--------------------------+ +Note that the filter below may not be thread safe on some operating +systems. You should check your system man pages for the functions used +below to verify the functions are thread safe. + /* A trivial filter that logs all email to a file. */ +#include +#include +#include +#include +#include +#include + #include "libmilter/mfapi.h" +typedef int bool; + +#ifndef FALSE +# define FALSE 0 +#endif /* ! FALSE*/ +#ifndef TRUE +# define TRUE 1 +#endif /* ! TRUE*/ + struct mlfiPriv { char *mlfi_fname; @@ -187,7 +224,7 @@ char **envfrom; { struct mlfiPriv *priv; - int fd; + int fd = -1; /* allocate some private memory */ priv = malloc(sizeof *priv); @@ -208,6 +245,8 @@ if ((fd = mkstemp(priv->mlfi_fname)) < 0 || (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) { + if (fd >= 0) + (void) close(fd); free(priv->mlfi_fname); free(priv); return SMFIS_TEMPFAIL; @@ -336,7 +375,7 @@ { "SampleFilter", /* filter name */ SMFI_VERSION, /* version code -- do not change */ - SMFIF_MODHDRS, /* flags */ + SMFIF_ADDHDRS, /* flags */ NULL, /* connection info filter */ NULL, /* SMTP HELO command filter */ mlfi_envfrom, /* envelope sender filter */ @@ -355,7 +394,7 @@ int argc; char *argv[]; { - char c; + int c; const char *args = "p:"; /* Process command line options */ @@ -385,4 +424,4 @@ /* eof */ -$Revision: 1.3 $, Last updated $Date: 2000/04/07 19:20:34 $ +$Revision: 1.6 $, Last updated $Date: 2001/05/29 01:31:12 $ Index: gnu/usr.sbin/sendmail/libmilter/comm.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/comm.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libmilter/comm.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/comm.c 2001/01/15 21:09:02 1.2 @@ -9,24 +9,24 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: comm.c,v 8.30 2000/02/11 00:12:29 ca Exp $"; +static char id[] = "@(#)$Sendmail: comm.c,v 8.30.4.6 2000/10/05 22:44:01 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" #define FD_Z FD_ZERO(&readset); \ - FD_SET(fd, &readset); \ + FD_SET((u_int) sd, &readset); \ FD_ZERO(&excset); \ - FD_SET(fd, &excset) + FD_SET((u_int) sd, &excset) /* ** MI_RD_CMD -- read a command ** ** Parameters: -** fd -- file descriptor +** sd -- socket descriptor ** timeout -- maximum time to wait -** cmd -- single character command read from fd +** cmd -- single character command read from sd ** rlen -- pointer to length of result ** name -- name of milter ** @@ -37,8 +37,8 @@ */ char * -mi_rd_cmd(fd, timeout, cmd, rlen, name) - int fd; +mi_rd_cmd(sd, timeout, cmd, rlen, name) + socket_t sd; struct timeval *timeout; char *cmd; size_t *rlen; @@ -55,23 +55,25 @@ *cmd = '\0'; *rlen = 0; - if (fd >= FD_SETSIZE) + + if (sd >= FD_SETSIZE) { smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", - name, fd, FD_SETSIZE); + name, sd, FD_SETSIZE); *cmd = SMFIC_SELECT; return NULL; } + FD_Z; i = 0; - while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) >= 1) + while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) >= 1) { - if (FD_ISSET(fd, &excset)) + if (FD_ISSET(sd, &excset)) { *cmd = SMFIC_SELECT; return NULL; } - if ((len = read(fd, data + i, sizeof data - i)) < 0) + if ((len = MI_SOCK_READ(sd, data + i, sizeof data - i)) < 0) { smi_log(SMI_LOG_ERR, "%s, mi_rd_cmd: read returned %d: %s", @@ -84,7 +86,7 @@ *cmd = SMFIC_EOF; return NULL; } - if (len >= sizeof data - i) + if (len >= (ssize_t) sizeof data - i) break; i += len; FD_Z; @@ -123,15 +125,15 @@ i = 0; FD_Z; - while ((ret = select(fd + 1, &readset, NULL, &excset, timeout)) == 1) + while ((ret = select(sd + 1, &readset, NULL, &excset, timeout)) == 1) { - if (FD_ISSET(fd, &excset)) + if (FD_ISSET(sd, &excset)) { *cmd = SMFIC_SELECT; free(buf); return NULL; } - if ((len = read(fd, buf + i, expl - i)) < 0) + if ((len = MI_SOCK_READ(sd, buf + i, expl - i)) < 0) { smi_log(SMI_LOG_ERR, "%s: mi_rd_cmd: read returned %d: %s", @@ -181,10 +183,10 @@ return NULL; } /* -** MI_WR_CMD -- write a cmd to fd +** MI_WR_CMD -- write a cmd to sd ** ** Parameters: -** fd -- file descriptor +** sd -- socket descriptor ** timeout -- maximum time to wait (currently unused) ** cmd -- single character command to write ** buf -- buffer with further data @@ -195,8 +197,8 @@ */ int -mi_wr_cmd(fd, timeout, cmd, buf, len) - int fd; +mi_wr_cmd(sd, timeout, cmd, buf, len) + socket_t sd; struct timeval *timeout; int cmd; char *buf; @@ -217,17 +219,19 @@ i = 0; sl = MILTER_LEN_BYTES + 1; - do { + do + { FD_ZERO(&wrtset); - FD_SET(fd, &wrtset); - if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + FD_SET((u_int) sd, &wrtset); + if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0) return MI_FAILURE; } while (ret < 0 && errno == EINTR); if (ret < 0) return MI_FAILURE; /* use writev() instead to send the whole stuff at once? */ - while ((l = write(fd, (void *) (data + i), sl - i)) < sl) + while ((l = MI_SOCK_WRITE(sd, (void *) (data + i), + sl - i)) < (ssize_t) sl) { if (l < 0) return MI_FAILURE; @@ -241,15 +245,17 @@ return MI_SUCCESS; i = 0; sl = len; - do { + do + { FD_ZERO(&wrtset); - FD_SET(fd, &wrtset); - if ((ret = select(fd + 1, NULL, &wrtset, NULL, timeout)) == 0) + FD_SET((u_int) sd, &wrtset); + if ((ret = select(sd + 1, NULL, &wrtset, NULL, timeout)) == 0) return MI_FAILURE; } while (ret < 0 && errno == EINTR); if (ret < 0) return MI_FAILURE; - while ((l = write(fd, (void *) (buf + i), sl - i)) < sl) + while ((l = MI_SOCK_WRITE(sd, (void *) (buf + i), + sl - i)) < (ssize_t) sl) { if (l < 0) return MI_FAILURE; Index: gnu/usr.sbin/sendmail/libmilter/engine.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/engine.c,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/libmilter/engine.c 2000/04/07 19:20:34 1.2 +++ gnu/usr.sbin/sendmail/libmilter/engine.c 2001/02/28 02:43:51 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: engine.c,v 8.67 2000/03/27 05:04:16 ca Exp $"; +static char id[] = "@(#)$Sendmail: engine.c,v 8.67.4.17 2001/01/22 19:00:16 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -20,9 +20,6 @@ # include #endif /* NETINET || NETINET6 */ -/* length of options: two 32bit integers */ -#define MILTER_OPTLEN 8 - /* generic argument for functions in the command table */ struct arg_struct { @@ -87,7 +84,7 @@ static int st_rcpt __P((genarg *)); static int st_eoh __P((genarg *)); static int st_quit __P((genarg *)); -static int sendreply __P((sfsistat, int, struct timeval *, SMFICTX_PTR)); +static int sendreply __P((sfsistat, socket_t, struct timeval *, SMFICTX_PTR)); static void fix_stm __P((SMFICTX_PTR)); static bool trans_ok __P((int, int)); static char **dec_argv __P((char *, size_t)); @@ -110,6 +107,9 @@ #define ST_LAST ST_ABRT #define ST_SKIP 15 /* not a state but required for the state table */ +/* in a mail transaction? must be before eom according to spec. */ +#define ST_IN_MAIL(st) ((st) >= ST_MAIL && (st) < ST_ENDM) + /* ** set of next states ** each state (ST_*) corresponds to bit in an int value (1 << state) @@ -122,7 +122,7 @@ #define NX_INIT (MASK(ST_OPTS)) #define NX_OPTS (MASK(ST_CONN)) #define NX_CONN (MASK(ST_HELO) | MASK(ST_MAIL)) -#define NX_HELO (MASK(ST_MAIL)) +#define NX_HELO (MASK(ST_HELO) | MASK(ST_MAIL)) #define NX_MAIL (MASK(ST_RCPT) | MASK(ST_ABRT)) #define NX_RCPT (MASK(ST_HDRS) | MASK(ST_EOHS) | MASK(ST_RCPT) | MASK(ST_ABRT)) #define NX_HDRS (MASK(ST_EOHS) | MASK(ST_HDRS) | MASK(ST_ABRT)) @@ -187,11 +187,13 @@ SMFICTX_PTR ctx; { size_t len; - int i, fd; + int i; + socket_t sd; int ret = MI_SUCCESS; int ncmds = sizeof(cmds) / sizeof(cmdfct); int curstate = ST_INIT; int newstate; + bool call_abort; sfsistat r; char cmd; char *buf = NULL; @@ -199,13 +201,17 @@ struct timeval timeout; int (*f) __P((genarg *)); sfsistat (*fi_abort) __P((SMFICTX *)); + sfsistat (*fi_close) __P((SMFICTX *)); arg.a_ctx = ctx; - fd = ctx->ctx_fd; + sd = ctx->ctx_sd; fi_abort = ctx->ctx_smfi->xxfi_abort; mi_clr_macros(ctx, 0); fix_stm(ctx); - do { + do + { + /* call abort only if in a mail transaction */ + call_abort = ST_IN_MAIL(curstate); timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; if (mi_stop() == MILTER_ABRT) @@ -216,12 +222,12 @@ ret = MI_FAILURE; break; } - if ((buf = mi_rd_cmd(fd, &timeout, &cmd, &len, + if ((buf = mi_rd_cmd(sd, &timeout, &cmd, &len, ctx->ctx_smfi->xxfi_name)) == NULL && cmd < SMFIC_VALIDCMD) { if (ctx->ctx_dbg > 5) - dprintf("[%d] error (%x)\n", + dprintf("[%d] mi_engine: mi_rd_cmd error (%x)\n", (int) ctx->ctx_id, (int) cmd); /* @@ -275,7 +281,9 @@ curstate, MASK(curstate), newstate, MASK(newstate), next_states[curstate]); - if (fi_abort != NULL) + + /* call abort only if in a mail transaction */ + if (fi_abort != NULL && call_abort) (void) (*fi_abort)(ctx); /* @@ -303,12 +311,13 @@ free(buf); buf = NULL; } - if (sendreply(r, fd, &timeout, ctx) != MI_SUCCESS) + if (sendreply(r, sd, &timeout, ctx) != MI_SUCCESS) { ret = MI_FAILURE; break; } + call_abort = ST_IN_MAIL(curstate); if (r == SMFIS_ACCEPT) { /* accept mail, no further actions taken */ @@ -337,16 +346,14 @@ if (ret != MI_SUCCESS) { - if (fi_abort != NULL) + /* call abort only if in a mail transaction */ + if (fi_abort != NULL && call_abort) (void) (*fi_abort)(ctx); } - else - { - sfsistat (*fi_close) __P((SMFICTX *)); - if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) - (void) (*fi_close)(ctx); - } + /* close must always be called */ + if ((fi_close = ctx->ctx_smfi->xxfi_close) != NULL) + (void) (*fi_close)(ctx); if (buf != NULL) free(buf); mi_clr_macros(ctx, 0); @@ -357,7 +364,7 @@ ** ** Parameters: ** r -- reply code -** fd -- file descriptor +** sd -- socket descriptor ** timeout_ptr -- (ptr to) timeout to use for sending ** ctx -- context structure ** @@ -366,24 +373,24 @@ */ static int -sendreply(r, fd, timeout_ptr, ctx) +sendreply(r, sd, timeout_ptr, ctx) sfsistat r; - int fd; + socket_t sd; struct timeval *timeout_ptr; SMFICTX_PTR ctx; { int ret = MI_SUCCESS; - switch(r) + switch (r) { case SMFIS_CONTINUE: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_CONTINUE, NULL, 0); break; case SMFIS_TEMPFAIL: case SMFIS_REJECT: if (ctx->ctx_reply != NULL) { - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_REPLYCODE, + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_REPLYCODE, ctx->ctx_reply, strlen(ctx->ctx_reply) + 1); free(ctx->ctx_reply); @@ -391,15 +398,15 @@ } else { - ret = mi_wr_cmd(fd, timeout_ptr, r == SMFIS_REJECT ? + ret = mi_wr_cmd(sd, timeout_ptr, r == SMFIS_REJECT ? SMFIR_REJECT : SMFIR_TEMPFAIL, NULL, 0); } break; case SMFIS_DISCARD: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_DISCARD, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_DISCARD, NULL, 0); break; case SMFIS_ACCEPT: - ret = mi_wr_cmd(fd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIR_ACCEPT, NULL, 0); break; case _SMFIS_OPTIONS: { @@ -411,7 +418,10 @@ v = htonl(ctx->ctx_smfi->xxfi_flags); (void) memcpy(&(buf[MILTER_LEN_BYTES]), (void *) &v, MILTER_LEN_BYTES); - ret = mi_wr_cmd(fd, timeout_ptr, SMFIC_OPTNEG, buf, + v = htonl(ctx->ctx_pflags); + (void) memcpy(&(buf[MILTER_LEN_BYTES * 2]), (void *) &v, + MILTER_LEN_BYTES); + ret = mi_wr_cmd(sd, timeout_ptr, SMFIC_OPTNEG, buf, MILTER_OPTLEN); } break; @@ -466,15 +476,17 @@ st_optionneg(g) genarg *g; { - mi_int32 i, version; + mi_int32 i, v; if (g == NULL || g->a_ctx->ctx_smfi == NULL) return SMFIS_CONTINUE; mi_clr_macros(g->a_ctx, g->a_idx + 1); - if (g->a_len != MILTER_OPTLEN) + + /* check for minimum length */ + if (g->a_len < MILTER_OPTLEN) { smi_log(SMI_LOG_ERR, - "%s: st_optionneg[%d]: len mismatch %d != %d", + "%s: st_optionneg[%d]: len too short %d < %d", g->a_ctx->ctx_smfi->xxfi_name, (int) g->a_ctx->ctx_id, g->a_len, MILTER_OPTLEN); @@ -483,24 +495,52 @@ (void) memcpy((void *) &i, (void *) &(g->a_buf[0]), MILTER_LEN_BYTES); - version = ntohl(i); - if (version != g->a_ctx->ctx_smfi->xxfi_version) + v = ntohl(i); + if (v < g->a_ctx->ctx_smfi->xxfi_version) { + /* hard failure for now! */ smi_log(SMI_LOG_ERR, - "%s: st_optionneg[%d]: version mismatch %d != %d", + "%s: st_optionneg[%d]: version mismatch MTA: %d < milter: %d", g->a_ctx->ctx_smfi->xxfi_name, - (int) g->a_ctx->ctx_id, (int) version, + (int) g->a_ctx->ctx_id, (int) v, g->a_ctx->ctx_smfi->xxfi_version); return _SMFIS_ABORT; } -#if 0 - /* flags are currently ignored */ (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES]), MILTER_LEN_BYTES); - flags = ntohl(i); -#endif /* 0 */ + v = ntohl(i); + + /* no flags? set to default value for V1 actions */ + if (v == 0) + v = SMFI_V1_ACTS; + i = g->a_ctx->ctx_smfi->xxfi_flags; + if ((v & i) != i) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: 0x%x does not fulfill action requirements 0x%x", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, v, i); + return _SMFIS_ABORT; + } + (void) memcpy((void *) &i, (void *) &(g->a_buf[MILTER_LEN_BYTES * 2]), + MILTER_LEN_BYTES); + v = ntohl(i); + + /* no flags? set to default value for V1 protocol */ + if (v == 0) + v = SMFI_V1_PROT; + i = g->a_ctx->ctx_pflags; + if ((v & i) != i) + { + smi_log(SMI_LOG_ERR, + "%s: st_optionneg[%d]: 0x%x does not fulfill protocol requirements 0x%x", + g->a_ctx->ctx_smfi->xxfi_name, + (int) g->a_ctx->ctx_id, v, i); + return _SMFIS_ABORT; + } + return _SMFIS_OPTIONS; } /* @@ -518,9 +558,9 @@ genarg *g; { size_t l; - int i; + size_t i; char *s, family; - u_short port; + u_short port = 0; _SOCK_ADDR sockaddr; sfsistat (*fi_connect) __P((SMFICTX *, char *, _SOCK_ADDR *)); @@ -569,6 +609,8 @@ return _SMFIS_ABORT; } sockaddr.sa.sa_family = AF_INET; + if (port > 0) + sockaddr.sin.sin_port = port; } else # endif /* NETINET */ @@ -585,6 +627,8 @@ return _SMFIS_ABORT; } sockaddr.sa.sa_family = AF_INET6; + if (port > 0) + sockaddr.sin6.sin6_port = port; } else # endif /* NETINET6 */ @@ -763,7 +807,7 @@ return _SMFIS_FAIL; if ((argv = dec_argv(g->a_buf + 1, g->a_len - 1)) == NULL) return _SMFIS_FAIL; - switch(g->a_buf[0]) + switch (g->a_buf[0]) { case SMFIC_CONNECT: i = CI_CONN; @@ -857,15 +901,15 @@ if ((fi_body = g->a_ctx->ctx_smfi->xxfi_body) != NULL && g->a_len > 0) { - int fd; + socket_t sd; struct timeval timeout; timeout.tv_sec = g->a_ctx->ctx_timeout; timeout.tv_usec = 0; - fd = g->a_ctx->ctx_fd; + sd = g->a_ctx->ctx_sd; r = (*fi_body)(g->a_ctx, (u_char *)g->a_buf, g->a_len); if (r != SMFIS_CONTINUE && - sendreply(r, fd, &timeout, g->a_ctx) != MI_SUCCESS) + sendreply(r, sd, &timeout, g->a_ctx) != MI_SUCCESS) return _SMFIS_ABORT; } } @@ -915,7 +959,8 @@ int s, n; s = old; - do { + do + { /* is this state transition allowed? */ if ((MASK(new) & next_states[s]) != 0) return TRUE; @@ -960,21 +1005,20 @@ if (ctx == NULL || ctx->ctx_smfi == NULL) return; - fl = ctx->ctx_smfi->xxfi_flags; - if (bitset(SMFIF_NOCONNECT, fl)) + fl = ctx->ctx_pflags; + if (bitset(SMFIP_NOCONNECT, fl)) next_states[ST_CONN] |= NX_SKIP; - if (bitset(SMFIF_NOHELO, fl)) + if (bitset(SMFIP_NOHELO, fl)) next_states[ST_HELO] |= NX_SKIP; - if (bitset(SMFIF_NOMAIL, fl)) + if (bitset(SMFIP_NOMAIL, fl)) next_states[ST_MAIL] |= NX_SKIP; - if (bitset(SMFIF_NORCPT, fl)) + if (bitset(SMFIP_NORCPT, fl)) next_states[ST_RCPT] |= NX_SKIP; - if (bitset(SMFIF_NOHDRS, fl)) - { + if (bitset(SMFIP_NOHDRS, fl)) next_states[ST_HDRS] |= NX_SKIP; + if (bitset(SMFIP_NOEOH, fl)) next_states[ST_EOHS] |= NX_SKIP; - } - if (bitset(SMFIF_NOBODY, fl)) + if (bitset(SMFIP_NOBODY, fl)) next_states[ST_BODY] |= NX_SKIP; } /* @@ -1019,7 +1063,7 @@ /* overwrite last entry */ s[elem] = NULL; - return (s); + return s; } /* ** DEC_ARG2 -- split a buffer into two strings @@ -1040,7 +1084,7 @@ char **s1; char **s2; { - int i; + size_t i; *s1 = buf; for (i = 1; i < len && buf[i] != '\0'; i++) Index: gnu/usr.sbin/sendmail/libmilter/handler.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/handler.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libmilter/handler.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/handler.c 2001/01/15 21:09:02 1.2 @@ -9,14 +9,15 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: handler.c,v 8.19 2000/02/11 00:12:29 ca Exp $"; +static char id[] = "@(#)$Sendmail: handler.c,v 8.19.4.3 2000/12/29 19:45:39 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" + /* -** HANDLE_SESSION -- Handle a connected session in it's own context +** HANDLE_SESSION -- Handle a connected session in its own context ** ** Parameters: ** ctx -- context structure @@ -33,7 +34,7 @@ if (ctx == NULL) return MI_FAILURE; - ctx->ctx_id = pthread_self(); + ctx->ctx_id = (sthread_t) sthread_get_id(); /* ** detach so resources are free when the thread returns @@ -42,10 +43,16 @@ if (pthread_detach(ctx->ctx_id) != 0) return MI_FAILURE; ret = mi_engine(ctx); - if (ctx->ctx_fd >= 0) - (void) close(ctx->ctx_fd); + if (ValidSocket(ctx->ctx_sd)) + { + (void) close(ctx->ctx_sd); + ctx->ctx_sd = INVALID_SOCKET; + } if (ctx->ctx_reply != NULL) + { free(ctx->ctx_reply); + ctx->ctx_reply = NULL; + } if (ctx->ctx_privdata != NULL) { smi_log(SMI_LOG_WARN, Index: gnu/usr.sbin/sendmail/libmilter/libmilter.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/libmilter.h,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/libmilter/libmilter.h 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/libmilter.h 2001/05/29 01:31:12 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -8,7 +8,7 @@ */ /* -** MILTER.H -- include file for mail filter library functions +** LIBMILTER.H -- include file for mail filter library functions */ #ifndef _LIBMILTER_H @@ -17,21 +17,40 @@ # define EXTERN # define INIT(x) = x # ifndef lint -static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3 2000/02/26 01:32:13 gshapiro Exp $"; +static char MilterlId[] = "@(#)$Sendmail: libmilter.h,v 8.3.6.14 2001/05/27 14:31:12 ca Exp $"; # endif /* ! lint */ #else /* _DEFINE */ # define EXTERN extern # define INIT(x) #endif /* _DEFINE */ + +#define NOT_SENDMAIL 1 +#define _SOCK_ADDR union bigsockaddr +#include "sendmail.h" + #include "libmilter/milter.h" -#include "libmilter/mfapi.h" #ifndef __P # include "sendmail/cdefs.h" #endif /* ! __P */ #include "sendmail/useful.h" +# define ValidSocket(sd) ((sd) >= 0) +# define INVALID_SOCKET -1 +# define MI_SOCK_READ(s, b, l) (read(s, b, l)) +# define MI_SOCK_WRITE(s, b, l) (write(s, b, l)) + +# define thread_create(ptid,wr,arg) pthread_create(ptid, NULL, wr, arg) +# define sthread_get_id() pthread_self() + +typedef pthread_mutex_t smutex_t; +# define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) +# define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) +# define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) +# define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) +# define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) + #include /* version info */ @@ -39,12 +58,19 @@ #define MILTER_VERSION 100 /* some defaults */ -#define MI_TIMEOUT 1800 /* default timeout for read/write */ +#define MI_TIMEOUT 7210 /* default timeout for read/write */ #define MI_CHK_TIME 5 /* checking whether to terminate */ +#if SOMAXCONN > 20 +# define MI_SOMAXCONN SOMAXCONN +#else /* SOMAXCONN */ +# define MI_SOMAXCONN 20 +#endif /* SOMAXCONN */ + /* maximum number of repeated failures in mi_listener() */ #define MAX_FAILS_M 16 /* malloc() */ #define MAX_FAILS_T 16 /* thread creation */ +#define MAX_FAILS_A 16 /* accept() */ /* internal "commands", i.e., error codes */ #define SMFIC_TIMEOUT ((char) 1) /* timeout */ @@ -65,8 +91,6 @@ #define SMI_LOG_INFO LOG_INFO #define SMI_LOG_DEBUG LOG_DEBUG -#define MI_INVALID_SOCKET (-1) - /* stop? */ #define MILTER_CONT 0 #define MILTER_STOP 1 @@ -75,17 +99,18 @@ /* functions */ extern int mi_handle_session __P((SMFICTX_PTR)); extern int mi_engine __P((SMFICTX_PTR)); -extern int mi_listener __P((char *, int, smfiDesc_ptr, time_t)); +extern int mi_listener __P((char *, int, smfiDesc_ptr, time_t, int)); extern void mi_clr_macros __P((SMFICTX_PTR, int)); extern int mi_stop __P((void)); extern int mi_control_startup __P((char *)); extern void mi_stop_milters __P((int)); extern void mi_clean_signals __P((void)); extern struct hostent *mi_gethostbyname __P((char *, int)); +extern void mi_closener __P((void)); /* communication functions */ -extern char *mi_rd_cmd __P((int, struct timeval *, char *, size_t *, char *)); -extern int mi_wr_cmd __P((int, struct timeval *, int, char *, size_t)); +extern char *mi_rd_cmd __P((socket_t, struct timeval *, char *, size_t *, char *)); +extern int mi_wr_cmd __P((socket_t, struct timeval *, int, char *, size_t)); extern bool mi_sendok __P((SMFICTX_PTR, int)); #endif /* !_LIBMILTER_H */ Index: gnu/usr.sbin/sendmail/libmilter/listener.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/listener.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/libmilter/listener.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/listener.c 2001/05/29 01:31:12 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: listener.c,v 8.38 2000/02/11 00:12:30 ca Exp $"; +static char id[] = "@(#)$Sendmail: listener.c,v 8.38.2.1.2.22 2001/05/16 17:15:58 ca Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -19,10 +19,10 @@ #include "libmilter.h" -#if NETINET || NETINET6 -# include -#endif /* NETINET || NETINET6 */ +# if NETINET || NETINET6 +# include +# endif /* NETINET || NETINET6 */ /* ** MI_MILTEROPEN -- setup socket to listen on ** @@ -30,31 +30,33 @@ ** conn -- connection description ** backlog -- listen backlog ** socksize -- socksize of created socket +** family -- family of created socket +** name -- name for logging ** ** Returns: ** socket upon success, error code otherwise. */ -static int -mi_milteropen(conn, backlog, socksize, name) +static socket_t +mi_milteropen(conn, backlog, socksize, family, name) char *conn; int backlog; SOCKADDR_LEN_T *socksize; + int *family; char *name; { - int sock = 0; + socket_t sock; int sockopt = 1; char *p; char *colon; char *at; - struct hostent *hp = NULL; SOCKADDR addr; if (conn == NULL || conn[0] == '\0') { smi_log(SMI_LOG_ERR, "%s: empty or missing socket information", name); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } (void) memset(&addr, '\0', sizeof addr); @@ -86,7 +88,7 @@ smi_log(SMI_LOG_ERR, "%s: no valid socket protocols available", name); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # endif /* NETINET6 */ # endif /* NETINET */ #endif /* NETUNIX */ @@ -117,7 +119,7 @@ { smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", name, p); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } *colon++ = ':'; } @@ -141,7 +143,7 @@ # else /* NETINET6 */ smi_log(SMI_LOG_ERR, "%s: unknown socket type %s", name, p); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # endif /* NETINET6 */ # endif /* NETINET */ #endif /* NETUNIX */ @@ -162,7 +164,7 @@ errno = EINVAL; smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s too long", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } # if 0 errno = safefile(colon, RunAsUid, RunAsGid, RunAsUserName, sff, @@ -174,7 +176,7 @@ smi_log(SMI_LOG_ERR, "%s: UNIX socket name %s unsafe", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } # endif /* 0 */ @@ -219,13 +221,13 @@ *at = '\0'; if (isascii(*colon) && isdigit(*colon)) - port = htons(atoi(colon)); + port = htons((u_short) atoi(colon)); else { # ifdef NO_GETSERVBYNAME smi_log(SMI_LOG_ERR, "%s: invalid port number %s", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; # else /* NO_GETSERVBYNAME */ register struct servent *sp; @@ -235,7 +237,7 @@ smi_log(SMI_LOG_ERR, "%s: unknown port name %s", name, colon); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } port = sp->s_port; # endif /* NO_GETSERVBYNAME */ @@ -286,7 +288,7 @@ smi_log(SMI_LOG_ERR, "%s: Invalid numeric domain spec \"%s\"", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } } else @@ -294,18 +296,20 @@ smi_log(SMI_LOG_ERR, "%s: Invalid numeric domain spec \"%s\"", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } } else { + struct hostent *hp = NULL; + hp = mi_gethostbyname(at, addr.sa.sa_family); if (hp == NULL) { smi_log(SMI_LOG_ERR, "%s: Unknown host name %s", name, at); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } addr.sa.sa_family = hp->h_addrtype; switch (hp->h_addrtype) @@ -332,8 +336,11 @@ smi_log(SMI_LOG_ERR, "%s: Unknown protocol for %s (%d)", name, at, hp->h_addrtype); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ } } else @@ -356,12 +363,12 @@ #endif /* NETINET || NETINET6 */ sock = socket(addr.sa.sa_family, SOCK_STREAM, 0); - if (sock < 0) + if (!ValidSocket(sock)) { smi_log(SMI_LOG_ERR, "%s: Unable to create new socket: %s", name, strerror(errno)); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *) &sockopt, @@ -370,7 +377,7 @@ smi_log(SMI_LOG_ERR, "%s: Unable to setsockopt: %s", name, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (bind(sock, &addr.sa, *socksize) < 0) @@ -379,7 +386,7 @@ "%s: Unable to bind to port %s: %s", name, conn, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } if (listen(sock, backlog) < 0) @@ -387,9 +394,9 @@ smi_log(SMI_LOG_ERR, "%s: listen call failed: %s", name, strerror(errno)); (void) close(sock); - return MI_INVALID_SOCKET; + return INVALID_SOCKET; } - + *family = addr.sa.sa_family; return sock; } /* @@ -409,8 +416,34 @@ return (void *) mi_handle_session(arg); } +static socket_t listenfd = INVALID_SOCKET; + +static smutex_t L_Mutex; + + /* +** MI_CLOSENER -- close listen socket +** +** Parameters: +** none. +** +** Returns: +** none. +*/ + +void +mi_closener() +{ + (void) smutex_lock(&L_Mutex); + if (ValidSocket(listenfd)) + { + (void) close(listenfd); + listenfd = INVALID_SOCKET; + } + (void) smutex_unlock(&L_Mutex); +} + /* -** MI_MILTER_LISTENER -- Generic listener harness +** MI_LISTENER -- Generic listener harness ** ** Open up listen port ** Wait for connections @@ -427,24 +460,67 @@ ** MI_FAILURE -- Network initialization failed. */ +# if BROKEN_PTHREAD_SLEEP + +/* +** Solaris 2.6, perhaps others, gets an internal threads library panic +** when sleep() is used: +** +** thread_create() failed, returned 11 (EINVAL) +** co_enable, thr_create() returned error = 24 +** libthread panic: co_enable failed (PID: 17793 LWP 1) +** stacktrace: +** ef526b10 +** ef52646c +** ef534cbc +** 156a4 +** 14644 +** 1413c +** 135e0 +** 0 +*/ + +# define MI_SLEEP(s) \ +{ \ + int rs = 0; \ + struct timeval st; \ + \ + st.tv_sec = (s); \ + st.tv_usec = 0; \ + if (st.tv_sec > 0) \ + rs = select(0, NULL, NULL, NULL, &st); \ + if (rs != 0) \ + { \ + smi_log(SMI_LOG_ERR, \ + "MI_SLEEP(): select() returned non-zero result %d, errno = %d", \ + rs, errno); \ + } \ +} +# else /* BROKEN_PTHREAD_SLEEP */ +# define MI_SLEEP(s) sleep((s)) +# endif /* BROKEN_PTHREAD_SLEEP */ + int -mi_listener(conn, dbg, smfi, timeout) +mi_listener(conn, dbg, smfi, timeout, backlog) char *conn; int dbg; smfiDesc_ptr smfi; time_t timeout; + int backlog; { - int connfd = -1; - int listenfd = -1; - int clilen; + socket_t connfd = INVALID_SOCKET; + int family = AF_UNSPEC; int sockopt = 1; int r; int ret = MI_SUCCESS; - int cnt_m = 0; - int cnt_t = 0; - pthread_t thread_id; + int mcnt = 0; + int tcnt = 0; + int acnt = 0; + int save_errno = 0; + sthread_t thread_id; _SOCK_ADDR cliaddr; SOCKADDR_LEN_T socksize; + SOCKADDR_LEN_T clilen; SMFICTX_PTR ctx; fd_set readset, excset; struct timeval chktime; @@ -453,37 +529,56 @@ smi_log(SMI_LOG_DEBUG, "%s: Opening listen socket on conn %s", smfi->xxfi_name, conn); - if ((listenfd = mi_milteropen(conn, SOMAXCONN, &socksize, - smfi->xxfi_name)) < 0) + (void) smutex_init(&L_Mutex); + (void) smutex_lock(&L_Mutex); + listenfd = mi_milteropen(conn, backlog, &socksize, &family, + smfi->xxfi_name); + if (!ValidSocket(listenfd)) { smi_log(SMI_LOG_FATAL, "%s: Unable to create listening socket on conn %s", smfi->xxfi_name, conn); + (void) smutex_unlock(&L_Mutex); return MI_FAILURE; } clilen = socksize; + if (listenfd >= FD_SETSIZE) { smi_log(SMI_LOG_ERR, "%s: fd %d is larger than FD_SETSIZE %d", smfi->xxfi_name, listenfd, FD_SETSIZE); + (void) smutex_unlock(&L_Mutex); return MI_FAILURE; } + (void) smutex_unlock(&L_Mutex); while (mi_stop() == MILTER_CONT) { + (void) smutex_lock(&L_Mutex); + if (!ValidSocket(listenfd)) + { + (void) smutex_unlock(&L_Mutex); + break; + } + /* select on interface ports */ FD_ZERO(&readset); - FD_SET(listenfd, &readset); FD_ZERO(&excset); - FD_SET(listenfd, &excset); + FD_SET((u_int) listenfd, &readset); + FD_SET((u_int) listenfd, &excset); chktime.tv_sec = MI_CHK_TIME; chktime.tv_usec = 0; r = select(listenfd + 1, &readset, NULL, &excset, &chktime); if (r == 0) /* timeout */ + { + (void) smutex_unlock(&L_Mutex); continue; /* just check mi_stop() */ + } if (r < 0) { - if (errno == EINTR) + save_errno = errno; + (void) smutex_unlock(&L_Mutex); + if (save_errno == EINTR) continue; ret = MI_FAILURE; break; @@ -492,17 +587,48 @@ { /* some error: just stop for now... */ ret = MI_FAILURE; + (void) smutex_unlock(&L_Mutex); break; } + memset(&cliaddr, '\0', sizeof cliaddr); connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen); + save_errno = errno; + (void) smutex_unlock(&L_Mutex); - if (connfd < 0) + /* + ** If remote side closes before + ** accept() finishes, sockaddr + ** might not be fully filled in. + */ + + if (ValidSocket(connfd) && + (clilen == 0 || +# ifdef BSD4_4_SOCKADDR + cliaddr.sa.sa_len == 0 || +# endif /* BSD4_4_SOCKADDR */ + cliaddr.sa.sa_family != family)) { + (void) close(connfd); + connfd = INVALID_SOCKET; + save_errno = EINVAL; + } + + if (!ValidSocket(connfd)) + { smi_log(SMI_LOG_ERR, - "%s: accept() returned invalid socket", - smfi->xxfi_name); + "%s: accept() returned invalid socket (%s)", + smfi->xxfi_name, strerror(save_errno)); + if (save_errno == EINTR) + continue; + acnt++; + MI_SLEEP(acnt); + if (acnt >= MAX_FAILS_A) + { + ret = MI_FAILURE; + break; + } continue; } @@ -518,17 +644,19 @@ (void) close(connfd); smi_log(SMI_LOG_ERR, "%s: malloc(ctx) failed", smfi->xxfi_name); - sleep(++cnt_m); - if (cnt_m >= MAX_FAILS_M) + mcnt++; + MI_SLEEP(mcnt); + if (mcnt >= MAX_FAILS_M) { ret = MI_FAILURE; break; } continue; } - cnt_m = 0; + mcnt = 0; + acnt = 0; memset(ctx, '\0', sizeof *ctx); - ctx->ctx_fd = connfd; + ctx->ctx_sd = connfd; ctx->ctx_dbg = dbg; ctx->ctx_timeout = timeout; ctx->ctx_smfi = smfi; @@ -539,41 +667,45 @@ if (smfi->xxfi_close == NULL) #endif /* 0 */ if (smfi->xxfi_connect == NULL) - smfi->xxfi_flags |= SMFIF_NOCONNECT; + ctx->ctx_pflags |= SMFIP_NOCONNECT; if (smfi->xxfi_helo == NULL) - smfi->xxfi_flags |= SMFIF_NOHELO; + ctx->ctx_pflags |= SMFIP_NOHELO; if (smfi->xxfi_envfrom == NULL) - smfi->xxfi_flags |= SMFIF_NOMAIL; + ctx->ctx_pflags |= SMFIP_NOMAIL; if (smfi->xxfi_envrcpt == NULL) - smfi->xxfi_flags |= SMFIF_NORCPT; + ctx->ctx_pflags |= SMFIP_NORCPT; if (smfi->xxfi_header == NULL) - smfi->xxfi_flags |= SMFIF_NOHDRS; + ctx->ctx_pflags |= SMFIP_NOHDRS; + if (smfi->xxfi_eoh == NULL) + ctx->ctx_pflags |= SMFIP_NOEOH; if (smfi->xxfi_body == NULL) - smfi->xxfi_flags |= SMFIF_NOBODY; + ctx->ctx_pflags |= SMFIP_NOBODY; - if ((r = pthread_create(&thread_id, NULL, + if ((r = thread_create(&thread_id, mi_thread_handle_wrapper, (void *) ctx)) != 0) { smi_log(SMI_LOG_ERR, - "%s: pthread_create() failed: %d", + "%s: thread_create() failed: %d", smfi->xxfi_name, r); - sleep(++cnt_t); + tcnt++; + MI_SLEEP(tcnt); (void) close(connfd); free(ctx); - if (cnt_t >= MAX_FAILS_T) + if (tcnt >= MAX_FAILS_T) { ret = MI_FAILURE; break; } continue; } - cnt_t = 0; + tcnt = 0; } if (ret != MI_SUCCESS) mi_stop_milters(MILTER_ABRT); - if (listenfd >= 0) - (void) close(listenfd); + else + mi_closener(); + (void) smutex_destroy(&L_Mutex); return ret; } #endif /* _FFR_MILTER */ Index: gnu/usr.sbin/sendmail/libmilter/main.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/main.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/libmilter/main.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/main.c 2001/05/29 01:31:12 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: main.c,v 8.34 2000/02/11 02:43:45 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: main.c,v 8.34.4.11 2001/05/07 22:06:37 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -18,6 +18,7 @@ #include #include + static smfiDesc_ptr smfi = NULL; /* @@ -42,7 +43,7 @@ if (smfi == NULL) return MI_FAILURE; } - (void)memcpy(smfi, &smfilter, sizeof *smfi); + (void) memcpy(smfi, &smfilter, sizeof *smfi); if (smfilter.xxfi_name == NULL) smfilter.xxfi_name = "Unknown"; @@ -51,12 +52,42 @@ if (smfi->xxfi_name == NULL) return MI_FAILURE; (void) strlcpy(smfi->xxfi_name, smfilter.xxfi_name, len); + + /* compare milter version with hard coded version */ + if (smfi->xxfi_version != SMFI_VERSION) + { + /* hard failure for now! */ + smi_log(SMI_LOG_ERR, + "%s: smfi_register: version mismatch application: %d != milter: %d", + smfi->xxfi_name, smfi->xxfi_version, + (int) SMFI_VERSION); + return MI_FAILURE; + } + + return MI_SUCCESS; +} + + /* +** SMFI_STOP -- stop milter +** +** Parameters: +** none. +** +** Returns: +** success. +*/ + +int +smfi_stop() +{ + mi_stop_milters(MILTER_STOP); return MI_SUCCESS; } static int dbg = 0; static char *conn = NULL; static int timeout = MI_TIMEOUT; +static int backlog= MI_SOMAXCONN; int smfi_setdbg(odbg) @@ -91,14 +122,26 @@ } int +smfi_setbacklog(obacklog) + int obacklog; +{ + if (obacklog <= 0) + return MI_FAILURE; + backlog = obacklog; + return MI_SUCCESS; +} + + +int smfi_main() { + signal(SIGPIPE, SIG_IGN); if (conn == NULL) { smi_log(SMI_LOG_FATAL, "%s: missing connection information", smfi->xxfi_name); - exit(EX_DATAERR); + return MI_FAILURE; } (void) atexit(mi_clean_signals); @@ -107,13 +150,14 @@ smi_log(SMI_LOG_FATAL, "%s: Couldn't start signal thread", smfi->xxfi_name); - exit(EX_OSERR); + return MI_FAILURE; } + /* Startup the listener */ - if (mi_listener(conn, dbg, smfi, timeout) != MI_SUCCESS) - return(MI_FAILURE); + if (mi_listener(conn, dbg, smfi, timeout, backlog) != MI_SUCCESS) + return MI_FAILURE; - return(MI_SUCCESS); + return MI_SUCCESS; } #endif /* _FFR_MILTER */ Index: gnu/usr.sbin/sendmail/libmilter/signal.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/signal.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libmilter/signal.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/signal.c 2001/01/15 21:09:02 1.2 @@ -9,29 +9,21 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: signal.c,v 8.10 2000/02/26 01:32:14 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: signal.c,v 8.10.4.8 2000/11/20 21:15:37 ca Exp $"; #endif /* ! lint */ #if _FFR_MILTER #include "libmilter.h" /* -** thread to handle signals +** thread to handle signals */ -typedef pthread_mutex_t smutex_t; -#define smutex_init(mp) (pthread_mutex_init(mp, NULL) == 0) -#define smutex_destroy(mp) (pthread_mutex_destroy(mp) == 0) -#define smutex_lock(mp) (pthread_mutex_lock(mp) == 0) -#define smutex_unlock(mp) (pthread_mutex_unlock(mp) == 0) -#define smutex_trylock(mp) (pthread_mutex_trylock(mp) == 0) - static smutex_t M_Mutex; static int MilterStop = MILTER_CONT; - -/* + /* ** MI_STOP -- return value of MilterStop ** ** Parameters: @@ -44,11 +36,9 @@ int mi_stop() { - return(MilterStop); + return MilterStop; } - - -/* + /* ** MI_STOP_MILTERS -- set value of MilterStop ** ** Parameters: @@ -65,10 +55,12 @@ (void) smutex_lock(&M_Mutex); if (MilterStop < v) MilterStop = v; + + /* close listen socket */ + mi_closener(); (void) smutex_unlock(&M_Mutex); } - -/* + /* ** MI_CLEAN_SIGNALS -- clean up signal handler thread ** ** Parameters: @@ -83,9 +75,8 @@ { (void) smutex_destroy(&M_Mutex); } - -/* -** MI -- thread to deal with signals + /* +** MI_SIGNAL_THREAD -- thread to deal with signals ** ** Parameters: ** name -- name of milter @@ -147,8 +138,7 @@ } } } - -/* + /* ** MI_SPAWN_SIGNAL_THREAD -- spawn thread to handle signals ** ** Parameters: @@ -162,8 +152,8 @@ mi_spawn_signal_thread(name) char *name; { + sthread_t tid; sigset_t set; - pthread_t tid; /* Mask HUP and KILL signals */ sigemptyset(&set); @@ -177,8 +167,8 @@ "%s: Couldn't mask HUP and KILL signals", name); return MI_FAILURE; } - if (pthread_create(&tid, NULL, mi_signal_thread, (void *)name) - != MI_SUCCESS) + if (thread_create(&tid, mi_signal_thread, + (void *)name) != MI_SUCCESS) { smi_log(SMI_LOG_ERR, "%s: Couldn't start signal thread", name); @@ -186,8 +176,7 @@ } return MI_SUCCESS; } - -/* + /* ** MI_CONTROL_STARTUP -- startup for thread to handle signals ** ** Parameters: Index: gnu/usr.sbin/sendmail/libmilter/sm_gethost.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/sm_gethost.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/libmilter/sm_gethost.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/sm_gethost.c 2001/05/29 01:31:13 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7 2000/01/20 21:51:52 geir Exp $"; +static char id[] = "@(#)$Sendmail: sm_gethost.c,v 8.7.8.10 2001/05/09 20:57:12 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -29,7 +29,7 @@ ** Support IPv6 as well as IPv4. */ -#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 +#if NETINET6 && NEEDSGETIPNODE # ifndef AI_V4MAPPED # define AI_V4MAPPED 0 /* dummy */ @@ -39,7 +39,7 @@ # endif /* ! AI_ALL */ static struct hostent * -mi_getipnodebyname(name, family, flags, err) +getipnodebyname(name, family, flags, err) char *name; int family; int flags; @@ -54,15 +54,29 @@ resv6 = bitset(RES_USE_INET6, _res.options); _res.options |= RES_USE_INET6; } - h_errno = 0; + SM_SET_H_ERRNO(0); h = gethostbyname(name); *err = h_errno; if (family == AF_INET6 && !resv6) _res.options &= ~RES_USE_INET6; return h; } -#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ +# if _FFR_FREEHOSTENT +void +freehostent(h) + struct hostent *h; +{ + /* + ** Stub routine -- if they don't have getipnodeby*(), + ** they probably don't have the free routine either. + */ + + return; +} +# endif /* _FFR_FREEHOSTENT */ +#endif /* NEEDSGETIPNODE && NETINET6 */ + struct hostent * mi_gethostbyname(name, family) char *name; @@ -87,8 +101,8 @@ # endif /* NETINET6 */ # if NETINET6 - h = mi_getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); - h_errno = err; + h = getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); + SM_SET_H_ERRNO(err); # else /* NETINET6 */ h = gethostbyname(name); # endif /* NETINET6 */ Index: gnu/usr.sbin/sendmail/libmilter/smfi.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libmilter/smfi.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libmilter/smfi.c 2000/04/02 19:05:58 1.1.1.1 +++ gnu/usr.sbin/sendmail/libmilter/smfi.c 2001/01/15 21:09:03 1.2 @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smfi.c,v 8.28 2000/02/26 01:32:15 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: smfi.c,v 8.28.4.6 2000/06/28 23:48:56 gshapiro Exp $"; #endif /* ! lint */ #if _FFR_MILTER @@ -40,9 +40,9 @@ char *buf; struct timeval timeout; - if (headerf == NULL || headerv == NULL) + if (headerf == NULL || *headerf == '\0' || headerv == NULL) return MI_FAILURE; - if (!mi_sendok(ctx, SMFIF_MODHDRS)) + if (!mi_sendok(ctx, SMFIF_ADDHDRS)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; @@ -54,10 +54,62 @@ return MI_FAILURE; (void) memcpy(buf, headerf, l1 + 1); (void) memcpy(buf + l1 + 1, headerv, l2 + 1); - r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDHEADER, buf, len); + r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDHEADER, buf, len); free(buf); return r; } + +/* +** SMFI_CHGHEADER -- send a changed header to the MTA +** +** Parameters: +** ctx -- Opaque context structure +** headerf -- Header field name +** hdridx -- Header index value +** headerv -- Header field value +** +** Returns: +** MI_SUCCESS/MI_FAILURE +*/ + +int +smfi_chgheader(ctx, headerf, hdridx, headerv) + SMFICTX *ctx; + char *headerf; + mi_int32 hdridx; + char *headerv; +{ + /* do we want to copy the stuff or have a special mi_wr_cmd call? */ + size_t len, l1, l2; + int r; + mi_int32 v; + char *buf; + struct timeval timeout; + + if (headerf == NULL || *headerf == '\0') + return MI_FAILURE; + if (hdridx < 0) + return MI_FAILURE; + if (!mi_sendok(ctx, SMFIF_CHGHDRS)) + return MI_FAILURE; + timeout.tv_sec = ctx->ctx_timeout; + timeout.tv_usec = 0; + if (headerv == NULL) + headerv = ""; + l1 = strlen(headerf); + l2 = strlen(headerv); + len = l1 + l2 + 2 + MILTER_LEN_BYTES; + buf = malloc(len); + if (buf == NULL) + return MI_FAILURE; + v = htonl(hdridx); + (void) memcpy(&(buf[0]), (void *) &v, MILTER_LEN_BYTES); + (void) memcpy(buf + MILTER_LEN_BYTES, headerf, l1 + 1); + (void) memcpy(buf + MILTER_LEN_BYTES + l1 + 1, headerv, l2 + 1); + r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_CHGHEADER, buf, len); + free(buf); + return r; +} /* ** SMFI_ADDRCPT -- send an additional recipient to the MTA ** @@ -77,14 +129,14 @@ size_t len; struct timeval timeout; - if (rcpt == NULL) + if (rcpt == NULL || *rcpt == '\0') return MI_FAILURE; if (!mi_sendok(ctx, SMFIF_ADDRCPT)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; len = strlen(rcpt) + 1; - return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_ADDRCPT, rcpt, len); + return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_ADDRCPT, rcpt, len); } /* ** SMFI_DELRCPT -- send a recipient to be removed to the MTA @@ -105,14 +157,14 @@ size_t len; struct timeval timeout; - if (rcpt == NULL) + if (rcpt == NULL || *rcpt == '\0') return MI_FAILURE; if (!mi_sendok(ctx, SMFIF_DELRCPT)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; len = strlen(rcpt) + 1; - return mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_DELRCPT, rcpt, len); + return mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_DELRCPT, rcpt, len); } /* ** SMFI_REPLACEBODY -- send a body chunk to the MTA @@ -137,7 +189,7 @@ if (bodyp == NULL && bodylen > 0) return MI_FAILURE; - if (!mi_sendok(ctx, SMFIF_MODBODY)) + if (!mi_sendok(ctx, SMFIF_CHGBODY)) return MI_FAILURE; timeout.tv_sec = ctx->ctx_timeout; timeout.tv_usec = 0; @@ -148,7 +200,7 @@ { len = (bodylen >= MILTER_CHUNK_SIZE) ? MILTER_CHUNK_SIZE : bodylen; - if ((r = mi_wr_cmd(ctx->ctx_fd, &timeout, SMFIR_REPLBODY, + if ((r = mi_wr_cmd(ctx->ctx_sd, &timeout, SMFIR_REPLBODY, (char *) (bodyp + off), len)) != MI_SUCCESS) return r; off += len; @@ -302,10 +354,29 @@ { int i; char **s; + char one[2]; + char braces[4]; if (ctx == NULL || symname == NULL || *symname == '\0') return NULL; + if (strlen(symname) == 3 && symname[0] == '{' && symname[2] == '}') + { + one[0] = symname[1]; + one[1] = '\0'; + } + else + one[0] = '\0'; + if (strlen(symname) == 1) + { + braces[0] = '{'; + braces[1] = *symname; + braces[2] = '}'; + braces[3] = '\0'; + } + else + braces[0] = '\0'; + /* search backwards through the macro array */ for (i = MAX_MACROS_ENTRIES - 1 ; i >= 0; --i) { @@ -315,6 +386,10 @@ while (s != NULL && *s != NULL) { if (strcmp(*s, symname) == 0) + return *++s; + if (one[0] != '\0' && strcmp(*s, one) == 0) + return *++s; + if (braces[0] != '\0' && strcmp(*s, braces) == 0) return *++s; ++s; /* skip over macro value */ ++s; /* points to next macro name */ Index: gnu/usr.sbin/sendmail/libsmdb/smdb.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmdb/smdb.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/libsmdb/smdb.c 2000/04/07 19:20:35 1.2 +++ gnu/usr.sbin/sendmail/libsmdb/smdb.c 2001/01/15 21:09:03 1.3 @@ -8,13 +8,14 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smdb.c,v 8.37 2000/03/17 07:32:43 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: smdb.c,v 8.37.4.2 2000/08/24 17:08:00 gshapiro Exp $"; #endif /* ! lint */ #include #include #include + #include #include @@ -61,7 +62,108 @@ free(database); } + /* +** SMDB_LOCKFILE -- lock a file using flock or (shudder) fcntl locking +** +** Parameters: +** fd -- the file descriptor of the file. +** type -- type of the lock. Bits can be: +** LOCK_EX -- exclusive lock. +** LOCK_NB -- non-blocking. +** +** Returns: +** TRUE if the lock was acquired. +** FALSE otherwise. +*/ + +static bool +smdb_lockfile(fd, type) + int fd; + int type; +{ + int i; + int save_errno; +#if !HASFLOCK + int action; + struct flock lfd; + + memset(&lfd, '\0', sizeof lfd); + if (bitset(LOCK_UN, type)) + lfd.l_type = F_UNLCK; + else if (bitset(LOCK_EX, type)) + lfd.l_type = F_WRLCK; + else + lfd.l_type = F_RDLCK; + + if (bitset(LOCK_NB, type)) + action = F_SETLK; + else + action = F_SETLKW; + + while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) + continue; + if (i >= 0) + { + return TRUE; + } + save_errno = errno; + + /* + ** On SunOS, if you are testing using -oQ/tmp/mqueue or + ** -oA/tmp/aliases or anything like that, and /tmp is mounted + ** as type "tmp" (that is, served from swap space), the + ** previous fcntl will fail with "Invalid argument" errors. + ** Since this is fairly common during testing, we will assume + ** that this indicates that the lock is successfully grabbed. + */ + + if (save_errno == EINVAL) + { + return TRUE; + } + + if (!bitset(LOCK_NB, type) || + (save_errno != EACCES && save_errno != EAGAIN)) + { + int omode = -1; +# ifdef F_GETFL + (void) fcntl(fd, F_GETFL, &omode); + errno = save_errno; +# endif /* F_GETFL */ +# if 0 + syslog(LOG_ERR, "cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", + filename, ext, fd, type, omode, geteuid()); +# endif /* 0 */ + return FALSE; + } +#else /* !HASFLOCK */ + while ((i = flock(fd, type)) < 0 && errno == EINTR) + continue; + if (i >= 0) + { + return TRUE; + } + save_errno = errno; + + if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) + { + int omode = -1; +# ifdef F_GETFL + (void) fcntl(fd, F_GETFL, &omode); + errno = save_errno; +# endif /* F_GETFL */ +# if 0 + syslog(LOG_ERR, "cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", + filename, ext, fd, type, omode, geteuid()); +# endif /* 0 */ + return FALSE; + } +#endif /* !HASFLOCK */ + errno = save_errno; + return FALSE; +} + /* ** SMDB_OPEN_DATABASE -- Opens a database. ** @@ -265,6 +367,59 @@ return SMDBE_OK; } + + /* +** SMDB_LOCK_MAP -- Locks a database. +** +** Parameters: +** database -- database description. +** type -- type of the lock. Bits can be: +** LOCK_EX -- exclusive lock. +** LOCK_NB -- non-blocking. +** +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_lock_map(database, type) + SMDB_DATABASE *database; + int type; +{ + int fd; + + fd = database->smdb_lockfd(database); + if (fd < 0) + return SMDBE_NOT_FOUND; + if (!smdb_lockfile(fd, type)) + return SMDBE_LOCK_NOT_GRANTED; + return SMDBE_OK; +} + + /* +** SMDB_UNLOCK_MAP -- Unlocks a database +** +** Parameters: +** database -- database description. +** +** Returns: +** SMDBE_OK -- Success, otherwise errno. +*/ + +int +smdb_unlock_map(database) + SMDB_DATABASE *database; +{ + int fd; + + fd = database->smdb_lockfd(database); + if (fd < 0) + return SMDBE_NOT_FOUND; + if (!smdb_lockfile(fd, LOCK_UN)) + return SMDBE_LOCK_NOT_HELD; + return SMDBE_OK; +} + /* ** SMDB_SETUP_FILE -- Gets db file ready for use. Index: gnu/usr.sbin/sendmail/libsmdb/smdb1.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmdb/smdb1.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/libsmdb/smdb1.c 2000/04/07 19:20:36 1.2 +++ gnu/usr.sbin/sendmail/libsmdb/smdb1.c 2001/01/15 21:09:03 1.3 @@ -8,7 +8,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smdb1.c,v 8.43 2000/03/17 07:32:43 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: smdb1.c,v 8.43.4.3 2000/10/05 23:06:30 gshapiro Exp $"; #endif /* ! lint */ #include @@ -175,8 +175,12 @@ u_int flags; { DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + DBT dbkey; - return db->del(db, &key->db, flags); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + return db->del(db, &dbkey, flags); } int @@ -194,6 +198,16 @@ } int +smdb1_lockfd(database) + SMDB_DATABASE *database; +{ + SMDB_DB1_DATABASE *db1 = (SMDB_DB1_DATABASE *) database->smdb_impl; + + return db1->smdb1_lock_fd; +} + + +int smdb1_get(database, key, data, flags) SMDB_DATABASE *database; SMDB_DBENT *key; @@ -202,14 +216,22 @@ { int result; DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + DBT dbkey, dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; - result = db->get(db, &key->db, &data->db, flags); + result = db->get(db, &dbkey, &dbdata, flags); if (result != 0) { if (result == 1) return SMDBE_NOT_FOUND; return errno; } + data->data = dbdata.data; + data->size = dbdata.size; return SMDBE_OK; } @@ -221,9 +243,17 @@ u_int flags; { DB *db = ((SMDB_DB1_DATABASE *) database->smdb_impl)->smdb1_db; + DBT dbkey, dbdata; - return db->put(db, &key->db, &data->db, - smdb_put_flags_to_db1_flags(flags)); + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + dbdata.data = data->data; + dbdata.size = data->size; + + return db->put(db, &dbkey, &dbdata, + smdb_put_flags_to_db1_flags(flags)); } int @@ -299,13 +329,21 @@ SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; SMDB_DB1_DATABASE *db1 = db1_cursor->db; DB *db = db1->smdb1_db; + DBT dbkey, dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); db1_flags = smdb_cursor_get_flags_to_smdb1(flags); - result = db->seq(db, &key->db, &value->db, db1_flags); + result = db->seq(db, &dbkey, &dbdata, db1_flags); if (result == -1) return errno; if (result == 1) return SMDBE_LAST_ENTRY; + value->data = dbdata.data; + value->size = dbdata.size; + key->data = dbkey.data; + key->size = dbkey.size; return SMDBE_OK; } @@ -319,8 +357,16 @@ SMDB_DB1_CURSOR *db1_cursor = (SMDB_DB1_CURSOR *) cursor->smdbc_impl; SMDB_DB1_DATABASE *db1 = db1_cursor->db; DB *db = db1->smdb1_db; + DBT dbkey, dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + dbdata.data = value->data; + dbdata.size = value->size; - return db->put(db, &key->db, &value->db, R_CURSOR); + return db->put(db, &dbkey, &dbdata, R_CURSOR); } int @@ -482,6 +528,7 @@ smdb_db->smdb_close = smdb1_close; smdb_db->smdb_del = smdb1_del; smdb_db->smdb_fd = smdb1_fd; + smdb_db->smdb_lockfd = smdb1_lockfd; smdb_db->smdb_get = smdb1_get; smdb_db->smdb_put = smdb1_put; smdb_db->smdb_set_owner = smdb1_set_owner; Index: gnu/usr.sbin/sendmail/libsmdb/smdb2.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmdb/smdb2.c,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/libsmdb/smdb2.c 2000/04/07 19:20:36 1.2 +++ gnu/usr.sbin/sendmail/libsmdb/smdb2.c 2001/02/28 02:43:52 1.4 @@ -1,5 +1,5 @@ /* -** Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. +** Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** By using this file, you agree to the terms and conditions set @@ -8,13 +8,14 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smdb2.c,v 8.53 2000/03/17 07:32:43 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: smdb2.c,v 8.53.2.1.2.7 2001/02/14 04:07:24 gshapiro Exp $"; #endif /* ! lint */ #include #include #include + #include #include @@ -137,7 +138,7 @@ break; default: - result = errno; + result = error; } return result; } @@ -249,8 +250,12 @@ u_int flags; { DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + DBT dbkey; - return db2_error_to_smdb(db->del(db, NULL, &key->db, flags)); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + return db2_error_to_smdb(db->del(db, NULL, &dbkey, flags)); } int @@ -264,15 +269,35 @@ } int +smdb2_lockfd(database) + SMDB_DATABASE *database; +{ + SMDB_DB2_DATABASE *db2 = (SMDB_DB2_DATABASE *) database->smdb_impl; + + return db2->smdb2_lock_fd; +} + + +int smdb2_get(database, key, data, flags) SMDB_DATABASE *database; SMDB_DBENT *key; SMDB_DBENT *data; u_int flags; { + int result; DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + DBT dbkey, dbdata; - return db2_error_to_smdb(db->get(db, NULL, &key->db, &data->db, flags)); + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + + result = db->get(db, NULL, &dbkey, &dbdata, flags); + data->data = dbdata.data; + data->size = dbdata.size; + return db2_error_to_smdb(result); } int @@ -283,8 +308,16 @@ u_int flags; { DB *db = ((SMDB_DB2_DATABASE *) database->smdb_impl)->smdb2_db; + DBT dbkey, dbdata; - return db2_error_to_smdb(db->put(db, NULL, &key->db, &data->db, + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + dbdata.data = data->data; + dbdata.size = data->size; + + return db2_error_to_smdb(db->put(db, NULL, &dbkey, &dbdata, smdb_put_flags_to_db2_flags(flags))); } @@ -326,9 +359,12 @@ smdb2_cursor_close(cursor) SMDB_CURSOR *cursor; { + int ret; DBC *dbc = (DBC *) cursor->smdbc_impl; - return db2_error_to_smdb(dbc->c_close(dbc)); + ret = db2_error_to_smdb(dbc->c_close(dbc)); + free(cursor); + return ret; } int @@ -351,11 +387,19 @@ int db2_flags; int result; DBC *dbc = (DBC *) cursor->smdbc_impl; + DBT dbkey, dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); db2_flags = smdb_cursor_get_flags_to_db2(flags); - result = dbc->c_get(dbc, &key->db, &value->db, db2_flags); + result = dbc->c_get(dbc, &dbkey, &dbdata, db2_flags); if (result == DB_NOTFOUND) return SMDBE_LAST_ENTRY; + key->data = dbkey.data; + key->size = dbkey.size; + value->data = dbdata.data; + value->size = dbdata.size; return db2_error_to_smdb(result); } @@ -367,8 +411,16 @@ SMDB_FLAG flags; { DBC *dbc = (DBC *) cursor->smdbc_impl; + DBT dbkey, dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + memset(&dbkey, '\0', sizeof dbkey); + dbkey.data = key->data; + dbkey.size = key->size; + dbdata.data = value->data; + dbdata.size = value->size; - return db2_error_to_smdb(dbc->c_put(dbc, &key->db, &value->db, 0)); + return db2_error_to_smdb(dbc->c_put(dbc, &dbkey, &dbdata, 0)); } int @@ -620,6 +672,7 @@ smdb_db->smdb_close = smdb2_close; smdb_db->smdb_del = smdb2_del; smdb_db->smdb_fd = smdb2_fd; + smdb_db->smdb_lockfd = smdb2_lockfd; smdb_db->smdb_get = smdb2_get; smdb_db->smdb_put = smdb2_put; smdb_db->smdb_set_owner = smdb2_set_owner; Index: gnu/usr.sbin/sendmail/libsmdb/smndbm.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmdb/smndbm.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/libsmdb/smndbm.c 2000/04/07 19:20:36 1.2 +++ gnu/usr.sbin/sendmail/libsmdb/smndbm.c 2001/01/15 21:09:03 1.3 @@ -8,7 +8,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: smndbm.c,v 8.40 2000/03/19 05:03:30 ca Exp $"; +static char id[] = "@(#)$Sendmail: smndbm.c,v 8.40.4.3 2000/10/05 22:27:50 gshapiro Exp $"; #endif /* ! lint */ #include @@ -124,9 +124,14 @@ { int result; DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + datum dbkey; + memset(&dbkey, '\0', sizeof dbkey); + dbkey.dptr = key->data; + dbkey.dsize = key->size; + errno = 0; - result = dbm_delete(dbm, key->dbm); + result = dbm_delete(dbm, dbkey); if (result != 0) { int save_errno = errno; @@ -157,6 +162,15 @@ } int +smdbm_lockfd(database) + SMDB_DATABASE *database; +{ + SMDB_DBM_DATABASE *db = (SMDB_DBM_DATABASE *) database->smdb_impl; + + return db->smndbm_lock_fd; +} + +int smdbm_get(database, key, data, flags) SMDB_DATABASE *database; SMDB_DBENT *key; @@ -164,10 +178,16 @@ u_int flags; { DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + datum dbkey, dbdata; + + memset(&dbkey, '\0', sizeof dbkey); + memset(&dbdata, '\0', sizeof dbdata); + dbkey.dptr = key->data; + dbkey.dsize = key->size; errno = 0; - data->dbm = dbm_fetch(dbm, key->dbm); - if (data->dbm.dptr == NULL) + dbdata = dbm_fetch(dbm, dbkey); + if (dbdata.dptr == NULL) { int save_errno = errno; @@ -179,7 +199,8 @@ return SMDBE_NOT_FOUND; } - + data->data = dbdata.dptr; + data->size = dbdata.dsize; return SMDBE_OK; } @@ -193,9 +214,17 @@ int result; int save_errno; DBM *dbm = ((SMDB_DBM_DATABASE *) database->smdb_impl)->smndbm_dbm; + datum dbkey, dbdata; + memset(&dbkey, '\0', sizeof dbkey); + memset(&dbdata, '\0', sizeof dbdata); + dbkey.dptr = key->data; + dbkey.dsize = key->size; + dbdata.dptr = data->data; + dbdata.dsize = data->size; + errno = 0; - result = dbm_store(dbm, key->dbm, data->dbm, + result = dbm_store(dbm, dbkey, dbdata, smdb_put_flags_to_ndbm_flags(flags)); switch (result) { @@ -312,6 +341,10 @@ SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; DBM *dbm = db->smndbm_dbm; + datum dbkey, dbdata; + + memset(&dbkey, '\0', sizeof dbkey); + memset(&dbdata, '\0', sizeof dbdata); if (flags == SMDB_CURSOR_GET_RANGE) return SMDBE_UNSUPPORTED; @@ -338,8 +371,8 @@ } errno = 0; - value->dbm = dbm_fetch(dbm, dbm_cursor->smndbmc_current_key); - if (value->dbm.dptr == NULL) + dbdata = dbm_fetch(dbm, dbm_cursor->smndbmc_current_key); + if (dbdata.dptr == NULL) { int save_errno = errno; @@ -351,7 +384,10 @@ return SMDBE_NOT_FOUND; } - key->dbm = dbm_cursor->smndbmc_current_key; + value->data = dbdata.dptr; + value->size = dbdata.dsize; + key->data = dbm_cursor->smndbmc_current_key.dptr; + key->size = dbm_cursor->smndbmc_current_key.dsize; return SMDBE_OK; } @@ -368,9 +404,14 @@ SMDB_DBM_CURSOR *dbm_cursor = (SMDB_DBM_CURSOR *) cursor->smdbc_impl; SMDB_DBM_DATABASE *db = dbm_cursor->smndbmc_db; DBM *dbm = db->smndbm_dbm; + datum dbdata; + + memset(&dbdata, '\0', sizeof dbdata); + dbdata.dptr = value->data; + dbdata.dsize = value->size; errno = 0; - result = dbm_store(dbm, dbm_cursor->smndbmc_current_key, value->dbm, + result = dbm_store(dbm, dbm_cursor->smndbmc_current_key, dbdata, smdb_put_flags_to_ndbm_flags(flags)); switch (result) { @@ -555,6 +596,7 @@ smdb_db->smdb_close = smdbm_close; smdb_db->smdb_del = smdbm_del; smdb_db->smdb_fd = smdbm_fd; + smdb_db->smdb_lockfd = smdbm_lockfd; smdb_db->smdb_get = smdbm_get; smdb_db->smdb_put = smdbm_put; smdb_db->smdb_set_owner = smndbm_set_owner; Index: gnu/usr.sbin/sendmail/libsmutil/lockfile.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmutil/lockfile.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libsmutil/lockfile.c 2000/04/02 19:05:41 1.1.1.1 +++ gnu/usr.sbin/sendmail/libsmutil/lockfile.c 2001/01/15 21:09:04 1.2 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: lockfile.c,v 8.3 1999/08/31 15:38:27 ca Exp $"; +static char id[] = "@(#)$Sendmail: lockfile.c,v 8.3.16.11 2000/11/16 02:54:28 geir Exp $"; #endif /* ! lint */ #include @@ -27,6 +27,7 @@ ** type -- type of the lock. Bits can be: ** LOCK_EX -- exclusive lock. ** LOCK_NB -- non-blocking. +** LOCK_UN -- unlock. ** ** Returns: ** TRUE if the lock was acquired. Index: gnu/usr.sbin/sendmail/libsmutil/safefile.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmutil/safefile.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libsmutil/safefile.c 2000/04/02 19:05:41 1.1.1.1 +++ gnu/usr.sbin/sendmail/libsmutil/safefile.c 2001/01/15 21:09:04 1.2 @@ -12,12 +12,14 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: safefile.c,v 8.81 2000/02/26 01:32:17 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: safefile.c,v 8.81.4.7 2000/09/01 21:09:23 ca Exp $"; #endif /* ! lint */ #include + + /* -** SAFEFILE -- return true if a file exists and is safe for a user. +** SAFEFILE -- return 0 if a file exists and is safe for a user. ** ** Parameters: ** fn -- filename to check. @@ -77,12 +79,12 @@ flags &= ~SFF_SAFEDIRPATH; /* first check to see if the file exists at all */ -#if HASLSTAT +# if HASLSTAT if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st) : stat(fn, st)) < 0) -#else /* HASLSTAT */ +# else /* HASLSTAT */ if (stat(fn, st) < 0) -#endif /* HASLSTAT */ +# endif /* HASLSTAT */ { file_errno = errno; } @@ -96,21 +98,21 @@ ** soon here! */ -#ifdef SUID_ROOT_FILES_OK +# ifdef SUID_ROOT_FILES_OK if (bitset(S_ISUID, st->st_mode)) -#else /* SUID_ROOT_FILES_OK */ +# else /* SUID_ROOT_FILES_OK */ if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0 && st->st_uid != TrustedUid) -#endif /* SUID_ROOT_FILES_OK */ +# endif /* SUID_ROOT_FILES_OK */ { uid = st->st_uid; user = NULL; } -#ifdef SUID_ROOT_FILES_OK +# ifdef SUID_ROOT_FILES_OK if (bitset(S_ISGID, st->st_mode)) -#else /* SUID_ROOT_FILES_OK */ +# else /* SUID_ROOT_FILES_OK */ if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0) -#endif /* SUID_ROOT_FILES_OK */ +# endif /* SUID_ROOT_FILES_OK */ gid = st->st_gid; } @@ -141,7 +143,7 @@ } else { -#if HASLSTAT +# if HASLSTAT /* Need lstat() information if called stat() before */ if (!bitset(SFF_NOSLINK, flags) && lstat(fn, st) < 0) { @@ -150,7 +152,7 @@ dprintf("\t%s\n", errstring(ret)); return ret; } -#endif /* HASLSTAT */ +# endif /* HASLSTAT */ /* directory is writable: disallow links */ flags |= SFF_NOLINK; } @@ -216,7 +218,7 @@ if (stbuf.st_gid == gid) /* EMPTY */ ; -#ifndef NO_GROUP_SET +# ifndef NO_GROUP_SET else if (user != NULL && !DontInitGroups && ((gr != NULL && gr->gr_gid == stbuf.st_gid) || @@ -230,7 +232,7 @@ if (*gp == NULL) md >>= 3; } -#endif /* ! NO_GROUP_SET */ +# endif /* ! NO_GROUP_SET */ else md >>= 3; } @@ -248,7 +250,7 @@ return ret; } -#ifdef S_ISLNK +# ifdef S_ISLNK if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode)) { if (tTd(44, 4)) @@ -256,7 +258,7 @@ (u_long) st->st_mode); return E_SM_NOSLINK; } -#endif /* S_ISLNK */ +# endif /* S_ISLNK */ if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode)) { if (tTd(44, 4)) @@ -328,7 +330,7 @@ if (st->st_gid == gid) /* EMPTY */ ; -#ifndef NO_GROUP_SET +# ifndef NO_GROUP_SET else if (user != NULL && !DontInitGroups && ((gr != NULL && gr->gr_gid == st->st_gid) || (gr = getgrgid(st->st_gid)) != NULL)) @@ -341,7 +343,7 @@ if (*gp == NULL) mode >>= 3; } -#endif /* ! NO_GROUP_SET */ +# endif /* ! NO_GROUP_SET */ else mode >>= 3; } @@ -463,18 +465,18 @@ if (tTd(44, 20)) dprintf("\t[dir %s]\n", s); -#if HASLSTAT +# if HASLSTAT ret = lstat(s, &stbuf); -#else /* HASLSTAT */ +# else /* HASLSTAT */ ret = stat(s, &stbuf); -#endif /* HASLSTAT */ +# endif /* HASLSTAT */ if (ret < 0) { ret = errno; break; } -#ifdef S_ISLNK +# ifdef S_ISLNK /* Follow symlinks */ if (S_ISLNK(stbuf.st_mode)) { @@ -619,7 +621,7 @@ if (stbuf.st_gid == gid && bitset(S_IXGRP, stbuf.st_mode)) continue; -#ifndef NO_GROUP_SET +# ifndef NO_GROUP_SET if (user != NULL && !DontInitGroups && ((gr != NULL && gr->gr_gid == stbuf.st_gid) || (gr = getgrgid(stbuf.st_gid)) != NULL)) @@ -633,7 +635,7 @@ bitset(S_IXGRP, stbuf.st_mode)) continue; } -#endif /* ! NO_GROUP_SET */ +# endif /* ! NO_GROUP_SET */ if (!bitset(S_IXOTH, stbuf.st_mode)) { ret = EACCES; @@ -830,13 +832,13 @@ if (stb->st_mode == ST_MODE_NOFILE) { -#if HASLSTAT && BOGUS_O_EXCL +# if HASLSTAT && BOGUS_O_EXCL /* only necessary if exclusive open follows symbolic links */ if (lstat(fn, stb) < 0 || stb->st_nlink != 1) return TRUE; -#else /* HASLSTAT && BOGUS_O_EXCL */ +# else /* HASLSTAT && BOGUS_O_EXCL */ return FALSE; -#endif /* HASLSTAT && BOGUS_O_EXCL */ +# endif /* HASLSTAT && BOGUS_O_EXCL */ } if (fstat(fd, &sta) < 0) return TRUE; @@ -844,9 +846,9 @@ if (sta.st_nlink != stb->st_nlink || sta.st_dev != stb->st_dev || sta.st_ino != stb->st_ino || -#if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ +# if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */ sta.st_gen != stb->st_gen || -#endif /* HAS_ST_GEN && 0 */ +# endif /* HAS_ST_GEN && 0 */ sta.st_uid != stb->st_uid || sta.st_gid != stb->st_gid) { @@ -868,10 +870,10 @@ dprintf(" ino = %lu/%lu\n", (unsigned long) stb->st_ino, (unsigned long) sta.st_ino); -#if HAS_ST_GEN +# if HAS_ST_GEN dprintf(" gen = %ld/%ld\n", (long) stb->st_gen, (long) sta.st_gen); -#endif /* HAS_ST_GEN */ +# endif /* HAS_ST_GEN */ dprintf(" uid = %ld/%ld\n", (long) stb->st_uid, (long) sta.st_uid); dprintf(" gid = %ld/%ld\n", Index: gnu/usr.sbin/sendmail/libsmutil/snprintf.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmutil/snprintf.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libsmutil/snprintf.c 2000/04/02 19:05:41 1.1.1.1 +++ gnu/usr.sbin/sendmail/libsmutil/snprintf.c 2001/01/15 21:09:04 1.2 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: snprintf.c,v 8.27 1999/10/13 03:27:08 ca Exp $"; +static char id[] = "@(#)$Sendmail: snprintf.c,v 8.27.16.2 2000/09/17 17:04:24 gshapiro Exp $"; #endif /* ! lint */ #include @@ -44,14 +44,20 @@ char *DoprEnd; int SnprfOverflow; -#if !HASSNPRINTF +#if !HASSNPRINTF && !SNPRINTF_IS_BROKEN +# define sm_snprintf snprintf +# ifndef luna2 +# define sm_vsnprintf vsnprintf +extern int vsnprintf __P((char *, size_t, const char *, va_list)); +# endif /* ! luna2 */ +#endif /* !HASSNPRINTF && !SNPRINTF_IS_BROKEN */ /* VARARGS3 */ int # ifdef __STDC__ -snprintf(char *str, size_t count, const char *fmt, ...) +sm_snprintf(char *str, size_t count, const char *fmt, ...) # else /* __STDC__ */ -snprintf(str, count, fmt, va_alist) +sm_snprintf(str, count, fmt, va_alist) char *str; size_t count; const char *fmt; @@ -62,15 +68,13 @@ VA_LOCAL_DECL VA_START(fmt); - len = vsnprintf(str, count, fmt, ap); + len = sm_vsnprintf(str, count, fmt, ap); VA_END; return len; } - -# ifndef luna2 int -vsnprintf(str, count, fmt, args) +sm_vsnprintf(str, count, fmt, args) char *str; size_t count; const char *fmt; @@ -87,9 +91,6 @@ (long) count, shortenstring(str, MAXSHORTSTR)); return strlen(str); } - -# endif /* ! luna2 */ -#endif /* !HASSNPRINTF */ /* * sm_dopr(): poor man's version of doprintf Index: gnu/usr.sbin/sendmail/libsmutil/strl.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/libsmutil/strl.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/libsmutil/strl.c 2000/04/02 19:05:41 1.1.1.1 +++ gnu/usr.sbin/sendmail/libsmutil/strl.c 2001/01/15 21:09:04 1.2 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,7 +9,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: strl.c,v 8.5 1999/12/29 22:13:46 ca Exp $"; +static char id[] = "@(#)$Sendmail: strl.c,v 8.5.14.2 2000/09/17 17:04:24 gshapiro Exp $"; #endif /* ! lint */ #include @@ -77,7 +77,7 @@ o = strlen(dst); if (len < o + 1) - return o + strlen(src); + return o + strlen(src); len -= o + 1; for (i = 0, j = o; i < len && (dst[j] = src[i]) != 0; i++, j++) continue; Index: gnu/usr.sbin/sendmail/mail.local/mail.local.8 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/mail.local/mail.local.8,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/mail.local/mail.local.8 2000/04/02 19:48:32 1.2 +++ gnu/usr.sbin/sendmail/mail.local/mail.local.8 2001/01/15 21:09:04 1.3 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. +.\" Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. .\" All rights reserved. .\" Copyright (c) 1990, 1993 .\" The Regents of the University of California. All rights reserved. @@ -8,15 +8,17 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: mail.local.8,v 8.14 1999/08/26 15:49:20 ca Exp $ +.\" $Sendmail: mail.local.8,v 8.14.14.5 2000/12/29 18:12:16 gshapiro Exp $ .\" -.TH MAIL.LOCAL 8 "$Date: 2000/04/02 19:48:32 $" +.TH MAIL.LOCAL 8 "$Date: 2001/01/15 21:09:04 $" .SH NAME -.B mail.local +mail.local \- store mail in a mailbox .SH SYNOPSIS .B mail.local -.RB [ \-7 "] [" \-d "] [" \-l "] [" \-f +.RB [ \-7 "] [" \-b "] [" \-d "] [" \-l "] [" \-f +.IR from "] " +.RB [ \-r .IR from "] " "user ..." .SH DESCRIPTION .B Mail.local @@ -96,6 +98,12 @@ getservbyname(3), comsat(8), sendmail(8) +.SH WARNING +.B mail.local +escapes only "^From " lines that follow an empty line. +If all lines starting with "From " should be escaped, +use the 'E' flag for the local mailer in the +sendmail.cf file. .SH HISTORY A superset of .B mail.local Index: gnu/usr.sbin/sendmail/mail.local/mail.local.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/mail.local/mail.local.c,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/mail.local/mail.local.c 2000/04/07 19:20:36 1.2 +++ gnu/usr.sbin/sendmail/mail.local/mail.local.c 2001/02/28 02:43:52 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. @@ -12,14 +12,14 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ +"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ All rights reserved.\n\ Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Sendmail: mail.local.c,v 8.143 2000/03/17 07:32:44 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: mail.local.c,v 8.143.4.57 2001/02/11 20:08:20 gshapiro Exp $"; #endif /* ! lint */ /* @@ -31,205 +31,206 @@ ** work on such architectures. */ -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef EX_OK -# undef EX_OK /* unistd.h may have another use for this */ -#endif /* EX_OK */ -#include -#include - -#ifndef __P -# include "sendmail/cdefs.h" -#endif /* ! __P */ -#include "sendmail/useful.h" +/* additional mode for open() */ +# define EXTRA_MODE 0 + +# include +# include +# include +# include +# include + +# include +# include + +# include +# include +# include +# include +# include +# include +# include +# include +# include +# ifdef EX_OK +# undef EX_OK /* unistd.h may have another use for this */ +# endif /* EX_OK */ +# include +# include + +# ifndef __P +# include "sendmail/cdefs.h" +# endif /* ! __P */ +# include "sendmail/useful.h" + extern size_t strlcpy __P((char *, const char *, size_t)); extern size_t strlcat __P((char *, const char *, size_t)); -#if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) -# ifndef HASSTRERROR -# define HASSTRERROR 1 -# endif /* ! HASSTRERROR */ -#endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || - defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ - -#include "sendmail/errstring.h" - - -#ifndef LOCKTO_RM -# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ -#endif /* LOCKTO_RM */ -#ifndef LOCKTO_GLOB -# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ -#endif /* LOCKTO_GLOB */ - -#ifdef __STDC__ -# include -# define REALLOC(ptr, size) realloc(ptr, size) -#else /* __STDC__ */ -# include +# if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# ifndef HASSTRERROR +# define HASSTRERROR 1 +# endif /* ! HASSTRERROR */ +# endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ + +# include "sendmail/errstring.h" + +# ifndef LOCKTO_RM +# define LOCKTO_RM 300 /* timeout for stale lockfile removal */ +# endif /* ! LOCKTO_RM */ +# ifndef LOCKTO_GLOB +# define LOCKTO_GLOB 400 /* global timeout for lockfile creation */ +# endif /* ! LOCKTO_GLOB */ + +# ifdef __STDC__ +# include +# define REALLOC(ptr, size) realloc(ptr, size) +# else /* __STDC__ */ +# include /* define a realloc() which works for NULL pointers */ -# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) -#endif /* __STDC__ */ +# define REALLOC(ptr, size) (((ptr) == NULL) ? malloc(size) : realloc(ptr, size)) +# endif /* __STDC__ */ -#if (defined(sun) && defined(__svr4__)) || defined(__SVR4) -# define USE_LOCKF 1 -# define USE_SETEUID 1 -# define _PATH_MAILDIR "/var/mail" -#endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */ - -#ifdef NCR_MP_RAS3 -# define USE_LOCKF 1 -# define HASSNPRINTF 1 -# define _PATH_MAILDIR "/var/mail" -#endif /* NCR_MP_RAS3 */ - -#if defined(_AIX) -# define USE_LOCKF 1 -# define USE_SETEUID 1 -# define USE_VSYSLOG 0 -#endif /* defined(_AIX) */ - -#if defined(__hpux) -# define USE_LOCKF 1 -# define USE_SETRESUID 1 -# define USE_VSYSLOG 0 -#endif /* defined(__hpux) */ - -#if defined(_CRAY) -# if !defined(MAXPATHLEN) -# define MAXPATHLEN PATHSIZE -# endif /* !defined(MAXPATHLEN) */ -# define USE_VSYSLOG 0 -# define _PATH_MAILDIR "/usr/spool/mail" -#endif /* defined(_CRAY) */ - -#if defined(ultrix) -# define USE_VSYSLOG 0 -#endif /* defined(ultrix) */ - -#if defined(__osf__) -# define USE_VSYSLOG 0 -#endif /* defined(__osf__) */ - -#if defined(NeXT) && !defined(__APPLE__) -# include -# define _PATH_MAILDIR "/usr/spool/mail" -# define S_IRUSR S_IREAD -# define S_IWUSR S_IWRITE -#endif /* defined(NeXT) && !defined(__APPLE__) */ - -#if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) -# include -#endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ +# if (defined(sun) && defined(__svr4__)) || defined(__SVR4) +# define USE_LOCKF 1 +# define USE_SETEUID 1 +# define _PATH_MAILDIR "/var/mail" +# endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */ + +# ifdef NCR_MP_RAS3 +# define USE_LOCKF 1 +# define HASSNPRINTF 1 +# define _PATH_MAILDIR "/var/mail" +# endif /* NCR_MP_RAS3 */ + +# if defined(_AIX) +# define USE_LOCKF 1 +# define USE_SETEUID 1 +# endif /* defined(_AIX) */ + +# if defined(__hpux) +# define USE_LOCKF 1 +# define USE_SETRESUID 1 +# endif /* defined(__hpux) */ + +# ifdef DGUX +# define HASSNPRINTF 1 +# define USE_LOCKF 1 +# endif /* DGUX */ + +# if defined(_CRAY) +# if !defined(MAXPATHLEN) +# define MAXPATHLEN PATHSIZE +# endif /* !defined(MAXPATHLEN) */ +# define _PATH_MAILDIR "/usr/spool/mail" +# endif /* defined(_CRAY) */ + +# if defined(NeXT) && !defined(__APPLE__) +# include +# define _PATH_MAILDIR "/usr/spool/mail" +# define S_IRUSR S_IREAD +# define S_IWUSR S_IWRITE +# endif /* defined(NeXT) && !defined(__APPLE__) */ + +# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6) +# include +# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */ /* * If you don't have flock, you could try using lockf instead. */ -#ifdef USE_LOCKF -# define flock(a, b) lockf(a, b, 0) -# ifdef LOCK_EX -# undef LOCK_EX -# endif /* LOCK_EX */ -# define LOCK_EX F_LOCK -#endif /* USE_LOCKF */ - -#ifndef USE_VSYSLOG -# define USE_VSYSLOG 1 -#endif /* ! USE_VSYSLOG */ - -#ifndef LOCK_EX -# include -#endif /* ! LOCK_EX */ - -#if defined(BSD4_4) || defined(__GLIBC__) -# include -# define _PATH_LOCTMP "/tmp/local.XXXXXX" -#endif /* defined(BSD4_4) || defined(__GLIBC__) */ - -#ifdef BSD4_4 -# define HAS_ST_GEN 1 -#else /* BSD4_4 */ -# ifndef _BSD_VA_LIST_ -# define _BSD_VA_LIST_ va_list -# endif /* ! _BSD_VA_LIST_ */ -#endif /* BSD4_4 */ - -#if defined(BSD4_4) || defined(linux) -# define HASSNPRINTF 1 -#else /* defined(BSD4_4) || defined(linux) */ -# ifndef ultrix +# ifdef USE_LOCKF +# define flock(a, b) lockf(a, b, 0) +# ifdef LOCK_EX +# undef LOCK_EX +# endif /* LOCK_EX */ +# define LOCK_EX F_LOCK +# endif /* USE_LOCKF */ + +# ifndef LOCK_EX +# include +# endif /* ! LOCK_EX */ + +# if defined(BSD4_4) || defined(__GLIBC__) +# include +# define _PATH_LOCTMP "/tmp/local.XXXXXX" +# endif /* defined(BSD4_4) || defined(__GLIBC__) */ + +# ifdef BSD4_4 +# define HAS_ST_GEN 1 +# else /* BSD4_4 */ +# ifndef _BSD_VA_LIST_ +# define _BSD_VA_LIST_ va_list +# endif /* ! _BSD_VA_LIST_ */ +# endif /* BSD4_4 */ + +# if defined(BSD4_4) || defined(linux) +# define HASSNPRINTF 1 +# else /* defined(BSD4_4) || defined(linux) */ +# ifndef ultrix extern FILE *fdopen __P((int, const char *)); -# endif /* ! ultrix */ -#endif /* defined(BSD4_4) || defined(linux) */ +# endif /* ! ultrix */ +# endif /* defined(BSD4_4) || defined(linux) */ -#if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) -# define CONTENTLENGTH 1 /* Needs the Content-Length header */ -#endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ - -#if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) -# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ -#endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ - -#ifdef HPUX11 -# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ -#endif /* HPUX11 */ - -#if _AIX4 >= 40300 -# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ -#endif /* _AIX4 >= 40300 */ +# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) +# define CONTENTLENGTH 1 /* Needs the Content-Length header */ +# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */ + +# if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) +# define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ + +# ifdef HPUX11 +# define HASSNPRINTF 1 /* has snprintf starting in 11.X */ +# endif /* HPUX11 */ + +# if _AIX4 >= 40300 +# define HASSNPRINTF 1 /* has snprintf starting in 4.3 */ +# endif /* _AIX4 >= 40300 */ -#if !HASSNPRINTF +# if !HASSNPRINTF && !SFIO extern int snprintf __P((char *, size_t, const char *, ...)); -# ifndef _CRAY +# ifndef _CRAY extern int vsnprintf __P((char *, size_t, const char *, ...)); -# endif /* ! _CRAY */ -#endif /* !HASSNPRINTF */ +# endif /* ! _CRAY */ +# endif /* !HASSNPRINTF && !SFIO */ /* ** If you don't have setreuid, and you have saved uids, and you have ** a seteuid() call that doesn't try to emulate using setuid(), then ** you can try defining USE_SETEUID. */ -#ifdef USE_SETEUID -# define setreuid(r, e) seteuid(e) -#endif /* USE_SETEUID */ + +# ifdef USE_SETEUID +# define setreuid(r, e) seteuid(e) +# endif /* USE_SETEUID */ /* ** And of course on hpux you have setresuid() */ -#ifdef USE_SETRESUID -# define setreuid(r, e) setresuid(-1, e, -1) -#endif /* USE_SETRESUID */ - -#ifndef _PATH_LOCTMP -# define _PATH_LOCTMP "/tmp/local.XXXXXX" -#endif /* ! _PATH_LOCTMP */ -# ifndef _PATH_MAILDIR -# define _PATH_MAILDIR "/var/spool/mail" -# endif /* ! _PATH_MAILDIR */ - -#ifndef S_ISREG -# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) -#endif /* ! S_ISREG */ + +# ifdef USE_SETRESUID +# define setreuid(r, e) setresuid(-1, e, -1) +# endif /* USE_SETRESUID */ + +# ifndef _PATH_LOCTMP +# define _PATH_LOCTMP "/tmp/local.XXXXXX" +# endif /* ! _PATH_LOCTMP */ +# ifndef _PATH_MAILDIR +# define _PATH_MAILDIR "/var/spool/mail" +# endif /* ! _PATH_MAILDIR */ + +# ifndef S_ISREG +# define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) +# endif /* ! S_ISREG */ + +# ifdef MAILLOCK +# include +# endif /* MAILLOCK */ + +# define U_UID pw->pw_uid +# define U_GID pw->pw_gid #ifndef INADDRSZ # define INADDRSZ 4 /* size of an IPv4 address in bytes */ @@ -239,10 +240,6 @@ # define MAILER_DAEMON "MAILER-DAEMON" #endif /* ! MAILER_DAEMON */ -#ifdef MAILLOCK -# include -#endif /* MAILLOCK */ - #ifdef CONTENTLENGTH char ContentHdr[40] = "Content-Length: "; off_t HeaderLength; @@ -250,19 +247,22 @@ #endif /* CONTENTLENGTH */ bool EightBitMime = TRUE; /* advertise 8BITMIME in LMTP */ +char ErrBuf[10240]; /* error buffer */ int ExitVal = EX_OK; /* sysexits.h error value. */ +bool HoldErrs = FALSE; /* Hold errors in ErrBuf */ bool LMTPMode = FALSE; -bool bouncequota = FALSE; /* permanent error when over quota */ +bool BounceQuota = FALSE; /* permanent error when over quota */ -void deliver __P((int, char *, bool)); +void deliver __P((int, char *)); int e_to_sys __P((int)); void notifybiff __P((char *)); -int store __P((char *, int)); +int store __P((char *, int, bool *)); void usage __P((void)); -void vwarn __P((const char *, _BSD_VA_LIST_)); int lockmbox __P((char *)); void unlockmbox __P((void)); void mailerr __P((const char *, const char *, ...)); +void flush_error __P((void)); + int main(argc, argv) @@ -275,8 +275,8 @@ char *from; extern char *optarg; extern int optind; - extern void dolmtp __P((bool)); + /* make sure we have some open file descriptors */ for (fd = 10; fd < 30; fd++) (void) close(fd); @@ -284,14 +284,14 @@ /* use a reasonable umask */ (void) umask(0077); -#ifdef LOG_MAIL +# ifdef LOG_MAIL openlog("mail.local", 0, LOG_MAIL); -#else /* LOG_MAIL */ +# else /* LOG_MAIL */ openlog("mail.local", 0); -#endif /* LOG_MAIL */ +# endif /* LOG_MAIL */ from = NULL; - while ((ch = getopt(argc, argv, "7bdf:r:l")) != EOF) + while ((ch = getopt(argc, argv, "7bdf:r:l")) != -1) { switch(ch) { @@ -300,7 +300,7 @@ break; case 'b': /* bounce mail when over quota. */ - bouncequota = TRUE; + BounceQuota = TRUE; break; case 'd': /* Backward compatible. */ @@ -310,7 +310,7 @@ case 'r': /* Backward compatible. */ if (from != NULL) { - mailerr(NULL, "multiple -f options"); + mailerr(NULL, "Multiple -f options"); usage(); } from = optarg; @@ -332,8 +332,21 @@ notifybiff(NULL); if (LMTPMode) - dolmtp(bouncequota); + { + extern void dolmtp __P((void)); + + if (argc > 0) + { + mailerr("421", "Users should not be specified in command line if LMTP required"); + exit(EX_TEMPFAIL); + } + + dolmtp(); + /* NOTREACHED */ + exit(EX_OK); + } + /* Non-LMTP from here on out */ if (*argv == '\0') usage(); @@ -342,6 +355,7 @@ ** uid matches, otherwise, use the name from the password file ** corresponding to the uid. */ + uid = getuid(); if (from == NULL && ((from = getlogin()) == NULL || @@ -358,8 +372,17 @@ ** failures. This results in the delivery being reattempted later ** at the expense of repeated failures and multiple deliveries. */ - for (fd = store(from, 0); *argv; ++argv) - deliver(fd, *argv, bouncequota); + + HoldErrs = TRUE; + fd = store(from, 0, NULL); + HoldErrs = FALSE; + if (fd < 0) + { + flush_error(); + exit(ExitVal); + } + for (; *argv != NULL; ++argv) + deliver(fd, *argv); exit(ExitVal); /* NOTREACHED */ return ExitVal; @@ -447,7 +470,7 @@ p = malloc(l); if (p == NULL) { - printf("421 4.3.0 memory exhausted\r\n"); + mailerr("421 4.3.0", "Memory exhausted"); exit(EX_TEMPFAIL); } @@ -460,15 +483,14 @@ char *addr; { if (getpwnam(addr) == NULL) - return "550 5.1.1 user unknown"; + return "550 5.1.1 User unknown"; return NULL; } #define RCPT_GROW 30 void -dolmtp(bouncequota) - bool bouncequota; +dolmtp() { char *return_path = NULL; char **rcpt_addr = NULL; @@ -482,7 +504,10 @@ char myhostname[1024]; char buf[4096]; + memset(myhostname, '\0', sizeof myhostname); (void) gethostname(myhostname, sizeof myhostname - 1); + if (myhostname[0] == '\0') + strlcpy(myhostname, "localhost", sizeof myhostname); printf("220 %s LMTP ready\r\n", myhostname); for (;;) @@ -502,23 +527,37 @@ case 'D': if (strcasecmp(buf, "data") == 0) { + bool inbody = FALSE; + if (rcpt_num == 0) { - printf("503 5.5.1 No recipients\r\n"); + mailerr("503 5.5.1", "No recipients"); continue; } - msgfd = store(return_path, rcpt_num); - if (msgfd == -1) + HoldErrs = TRUE; + msgfd = store(return_path, rcpt_num, &inbody); + HoldErrs = FALSE; + if (msgfd < 0 && !inbody) + { + flush_error(); continue; + } for (i = 0; i < rcpt_num; i++) { + if (msgfd < 0) + { + /* print error for rcpt */ + flush_error(); + continue; + } p = strchr(rcpt_addr[i], '+'); if (p != NULL) - *p++ = '\0'; - deliver(msgfd, rcpt_addr[i], bouncequota); + *p = '\0'; + deliver(msgfd, rcpt_addr[i]); } - (void) close(msgfd); + if (msgfd >= 0) + (void) close(msgfd); goto rset; } goto syntaxerr; @@ -532,7 +571,7 @@ /* check for duplicate per RFC 1651 4.2 */ if (gotlhlo) { - printf("503 %s Duplicate LHLO\r\n", + mailerr("503", "%s Duplicate LHLO", myhostname); continue; } @@ -554,17 +593,19 @@ { if (return_path != NULL) { - printf("503 5.5.1 Nested MAIL command\r\n"); + mailerr("503 5.5.1", + "Nested MAIL command"); continue; } if (strncasecmp(buf+5, "from:", 5) != 0 || ((return_path = parseaddr(buf + 10, FALSE)) == NULL)) { - printf("501 5.5.4 Syntax error in parameters\r\n"); + mailerr("501 5.5.4", + "Syntax error in parameters"); continue; } - printf("250 2.5.0 ok\r\n"); + printf("250 2.5.0 Ok\r\n"); continue; } goto syntaxerr; @@ -575,7 +616,7 @@ case 'N': if (strcasecmp(buf, "noop") == 0) { - printf("250 2.0.0 ok\r\n"); + printf("250 2.0.0 Ok\r\n"); continue; } goto syntaxerr; @@ -586,7 +627,7 @@ case 'Q': if (strcasecmp(buf, "quit") == 0) { - printf("221 2.0.0 bye\r\n"); + printf("221 2.0.0 Bye\r\n"); exit(EX_OK); } goto syntaxerr; @@ -599,19 +640,21 @@ { if (return_path == NULL) { - printf("503 5.5.1 Need MAIL command\r\n"); + mailerr("503 5.5.1", + "Need MAIL command"); continue; } if (rcpt_num >= rcpt_alloc) { rcpt_alloc += RCPT_GROW; rcpt_addr = (char **) - REALLOC((char *)rcpt_addr, + REALLOC((char *) rcpt_addr, rcpt_alloc * sizeof(char **)); if (rcpt_addr == NULL) { - printf("421 4.3.0 memory exhausted\r\n"); + mailerr("421 4.3.0", + "Memory exhausted"); exit(EX_TEMPFAIL); } } @@ -619,24 +662,26 @@ ((rcpt_addr[rcpt_num] = parseaddr(buf + 8, TRUE)) == NULL)) { - printf("501 5.5.4 Syntax error in parameters\r\n"); + mailerr("501 5.5.4", + "Syntax error in parameters"); continue; } - if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL) + err = process_recipient(rcpt_addr[rcpt_num]); + if (err != NULL) { - printf("%s\r\n", err); + mailerr(NULL, "%s", err); continue; } rcpt_num++; - printf("250 2.1.5 ok\r\n"); + printf("250 2.1.5 Ok\r\n"); continue; } else if (strcasecmp(buf, "rset") == 0) { - printf("250 2.0.0 ok\r\n"); + printf("250 2.0.0 Ok\r\n"); rset: - while (rcpt_num) + while (rcpt_num > 0) free(rcpt_addr[--rcpt_num]); if (return_path != NULL) free(return_path); @@ -651,7 +696,7 @@ case 'V': if (strncasecmp(buf, "vrfy ", 5) == 0) { - printf("252 2.3.3 try RCPT to attempt delivery\r\n"); + printf("252 2.3.3 Try RCPT to attempt delivery\r\n"); continue; } goto syntaxerr; @@ -660,7 +705,7 @@ default: syntaxerr: - printf("500 5.5.2 Syntax error\r\n"); + mailerr("500 5.5.2", "Syntax error"); continue; /* NOTREACHED */ break; @@ -669,40 +714,39 @@ } int -store(from, lmtprcpts) +store(from, lmtprcpts, inbody) char *from; int lmtprcpts; + bool *inbody; { FILE *fp = NULL; time_t tval; bool eline; - bool fullline = TRUE; + bool fullline = TRUE; /* current line is terminated */ + bool prevfl; /* previous line was terminated */ char line[2048]; int fd; char tmpbuf[sizeof _PATH_LOCTMP + 1]; + if (inbody != NULL) + *inbody = FALSE; + (void) umask(0077); (void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf); - if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) + if ((fd = mkstemp(tmpbuf)) < 0 || (fp = fdopen(fd, "w+")) == NULL) { - if (lmtprcpts) - { - printf("451 4.3.0 unable to open temporary file\r\n"); - return -1; - } - else - { - mailerr("451 4.3.0", "unable to open temporary file"); - exit(ExitVal); - } + mailerr("451 4.3.0", "Unable to open temporary file"); + return -1; } (void) unlink(tmpbuf); if (LMTPMode) { - printf("354 go ahead\r\n"); + printf("354 Go ahead\r\n"); (void) fflush(stdout); } + if (inbody != NULL) + *inbody = TRUE; (void) time(&tval); (void) fprintf(fp, "From %s %s", from, ctime(&tval)); @@ -713,16 +757,19 @@ #endif /* CONTENTLENGTH */ line[0] = '\0'; - for (eline = TRUE; fgets(line, sizeof(line), stdin); ) + eline = TRUE; + while (fgets(line, sizeof(line), stdin) != (char *) NULL) { size_t line_len = 0; int peek; + + prevfl = fullline; /* preserve state of previous line */ while (line[line_len] != '\n' && line_len < sizeof(line) - 2) line_len++; line_len++; /* Check for dot-stuffing */ - if (fullline && lmtprcpts && line[0] == '.') + if (prevfl && LMTPMode && line[0] == '.') { if (line[1] == '\n' || (line[1] == '\r' && line[2] == '\n')) @@ -731,7 +778,7 @@ line_len--; } - /* Check to see if we have the full line from the fgets() */ + /* Check to see if we have the full line from fgets() */ fullline = FALSE; if (line_len > 0) { @@ -739,12 +786,11 @@ { if (line_len >= 2 && line[line_len - 2] == '\r') - { - (void) strlcpy(line + line_len - 2, - "\n", sizeof line - - line_len + 2); + { + line[line_len - 2] = '\n'; + line[line_len - 1] = '\0'; line_len--; - } + } fullline = TRUE; } else if (line[line_len - 1] == '\r') @@ -764,10 +810,11 @@ fullline = TRUE; #ifdef CONTENTLENGTH - if (line[0] == '\n' && HeaderLength == 0) + if (prevfl && line[0] == '\n' && HeaderLength == 0) { eline = FALSE; - HeaderLength = ftell(fp); + if (fp != NULL) + HeaderLength = ftell(fp); if (HeaderLength <= 0) { /* @@ -779,58 +826,65 @@ } } #else /* CONTENTLENGTH */ - if (line[0] == '\n') + if (prevfl && line[0] == '\n') eline = TRUE; #endif /* CONTENTLENGTH */ else { if (eline && line[0] == 'F' && + fp != NULL && !memcmp(line, "From ", 5)) - (void)putc('>', fp); + (void) putc('>', fp); eline = FALSE; #ifdef CONTENTLENGTH /* discard existing "Content-Length:" headers */ - if (HeaderLength == 0 && + if (prevfl && HeaderLength == 0 && (line[0] == 'C' || line[0] == 'c') && strncasecmp(line, ContentHdr, 15) == 0) - continue; + { + /* + ** be paranoid: clear the line + ** so no "wrong matches" may occur later + */ + line[0] = '\0'; + continue; + } #endif /* CONTENTLENGTH */ } - (void) fwrite(line, sizeof(char), line_len, fp); - if (ferror(fp)) + if (fp != NULL) { - if (lmtprcpts) - { - while (lmtprcpts--) - printf("451 4.3.0 temporary file write error\r\n"); - (void) fclose(fp); - return -1; - } - else + (void) fwrite(line, sizeof(char), line_len, fp); + if (ferror(fp)) { mailerr("451 4.3.0", - "temporary file write error"); + "Temporary file write error"); (void) fclose(fp); - exit(ExitVal); + fp = NULL; + continue; } } } + + /* check if an error occurred */ + if (fp == NULL) + return -1; - if (lmtprcpts) + if (LMTPMode) { /* Got a premature EOF -- toss message and exit */ exit(EX_OK); } /* If message not newline terminated, need an extra. */ - if (strchr(line, '\n') == NULL) + if (fp != NULL && strchr(line, '\n') == NULL) (void) putc('\n', fp); lmtpdot: #ifdef CONTENTLENGTH - BodyLength = ftell(fp); + if (fp != NULL) + BodyLength = ftell(fp); if (HeaderLength == 0 && BodyLength > 0) /* empty body */ { HeaderLength = BodyLength; @@ -847,7 +901,8 @@ snprintf(line, sizeof line, "%s\n", quad_to_string(BodyLength)); else - snprintf(line, sizeof line, "%ld\n", (long) BodyLength); + snprintf(line, sizeof line, "%ld\n", + (long) BodyLength); strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16); } else @@ -855,38 +910,31 @@ #endif /* CONTENTLENGTH */ /* Output a newline; note, empty messages are allowed. */ - (void) putc('\n', fp); + if (fp != NULL) + (void) putc('\n', fp); - if (fflush(fp) == EOF || ferror(fp) != 0) + if (fp == NULL || fflush(fp) == EOF || ferror(fp) != 0) { - if (lmtprcpts) - { - while (lmtprcpts--) - printf("451 4.3.0 temporary file write error\r\n"); + mailerr("451 4.3.0", "Temporary file write error"); + if (fp != NULL) (void) fclose(fp); - return -1; - } - else - { - mailerr("451 4.3.0", "temporary file write error"); - (void) fclose(fp); - exit(ExitVal); - } + return -1; } return fd; } void -deliver(fd, name, bouncequota) +deliver(fd, name) int fd; char *name; - bool bouncequota; { - struct stat fsb, sb; + struct stat fsb; + struct stat sb; struct passwd *pw; char path[MAXPATHLEN]; - int mbfd, nr = 0, nw, off; + int mbfd = -1, nr = 0, nw, off; char *p; + char *errcode; off_t curoff; #ifdef CONTENTLENGTH off_t headerbytes; @@ -900,27 +948,17 @@ ** Disallow delivery to unknown names -- special mailboxes can be ** handled in the sendmail aliases file. */ + if ((pw = getpwnam(name)) == NULL) { - if (ExitVal != EX_TEMPFAIL) - ExitVal = EX_UNAVAILABLE; - if (LMTPMode) - { - if (ExitVal == EX_TEMPFAIL) - printf("451 4.3.0 cannot lookup name: %s\r\n", name); - else - printf("550 5.1.1 unknown name: %s\r\n", name); - } + if (ExitVal == EX_TEMPFAIL) + errcode = "451 4.3.0"; else { - char *errcode = NULL; - - if (ExitVal == EX_TEMPFAIL) - errcode = "451 4.3.0"; - else - errcode = "550 5.1.1"; - mailerr(errcode, "unknown name: %s", name); + ExitVal = EX_UNAVAILABLE; + errcode = "550 5.1.1"; } + mailerr(errcode, "Unknown name: %s", name); return; } endpwent(); @@ -943,8 +981,10 @@ *p = '.'; } + (void) snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name); + /* ** If the mailbox is linked or a symlink, fail. There's an obvious ** race here, that the file was replaced with a symbolic link after @@ -978,16 +1018,13 @@ if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL) { ExitVal = EX_TEMPFAIL; - mailerr("451 4.3.0", - "lockmailbox %s failed; error code %d %s", - p, off, errno > 0 ? errstring(errno) : ""); + errcode = "451 4.3.0"; } else - { - mailerr("551 5.3.0", - "lockmailbox %s failed; error code %d %s", - p, off, errno > 0 ? errstring(errno) : ""); - } + errcode = "551 5.3.0"; + + mailerr(errcode, "lockmailbox %s failed; error code %d %s", + p, off, errno > 0 ? errstring(errno) : ""); return; } @@ -995,7 +1032,7 @@ { int save_errno; int mode = S_IRUSR|S_IWUSR; - gid_t gid = pw->pw_gid; + gid_t gid = U_GID; #ifdef MAILGID (void) umask(0007); @@ -1003,8 +1040,8 @@ mode |= S_IRGRP|S_IWGRP; #endif /* MAILGID */ - mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY, mode); - + mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|EXTRA_MODE, + mode); save_errno = errno; if (lstat(path, &sb) < 0) @@ -1014,36 +1051,61 @@ "%s: lstat: file changed after open", path); goto err1; } - else - sb.st_uid = pw->pw_uid; - if (mbfd == -1) + if (mbfd < 0) { if (save_errno == EEXIST) goto tryagain; + + /* open failed, don't try again */ + mailerr("450 4.2.0", "%s: %s", path, + errstring(save_errno)); + goto err0; } - else if (fchown(mbfd, pw->pw_uid, gid) < 0) + else if (fchown(mbfd, U_UID, gid) < 0) { mailerr("451 4.3.0", "chown %u.%u: %s", - pw->pw_uid, gid, name); + U_UID, gid, name); goto err1; } + else + { + /* + ** open() was successful, now close it so can + ** be opened as the right owner again. + ** Paranoia: reset mbdf since the file descriptor + ** is no longer valid; better safe than sorry. + */ + + sb.st_uid = U_UID; + (void) close(mbfd); + mbfd = -1; + } } else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) { mailerr("550 5.2.0", "%s: irregular file", path); goto err0; } - else if (sb.st_uid != pw->pw_uid) + else if (sb.st_uid != U_UID) { ExitVal = EX_CANTCREAT; mailerr("550 5.2.0", "%s: wrong ownership (%d)", path, sb.st_uid); goto err0; } - else - mbfd = open(path, O_APPEND|O_WRONLY, 0); - if (mbfd == -1) + /* change UID for quota checks */ + if (setreuid(0, U_UID) < 0) + { + mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", + U_UID, errstring(errno), getuid(), geteuid()); + goto err1; + } +#ifdef DEBUG + fprintf(stderr, "new euid = %d\n", geteuid()); +#endif /* DEBUG */ + mbfd = open(path, O_APPEND|O_WRONLY|EXTRA_MODE, 0); + if (mbfd < 0) { mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); goto err0; @@ -1054,9 +1116,9 @@ !S_ISREG(fsb.st_mode) || sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino || -#if HAS_ST_GEN && 0 /* AFS returns random values for st_gen */ +# if HAS_ST_GEN && 0 /* AFS returns random values for st_gen */ sb.st_gen != fsb.st_gen || -#endif /* HAS_ST_GEN && 0 */ +# endif /* HAS_ST_GEN && 0 */ sb.st_uid != fsb.st_uid) { ExitVal = EX_TEMPFAIL; @@ -1074,29 +1136,23 @@ } /* Get the starting offset of the new message for biff. */ - curoff = lseek(mbfd, (off_t)0, SEEK_END); + curoff = lseek(mbfd, (off_t) 0, SEEK_END); if (sizeof curoff > sizeof(long)) - (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n", - name, quad_to_string(curoff)); + (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n", + name, quad_to_string(curoff)); else - (void)snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n", - name, (long) curoff); + (void) snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n", + name, (long) curoff); /* Copy the message into the file. */ - if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) + if (lseek(fd, (off_t) 0, SEEK_SET) == (off_t) -1) { - mailerr("450 4.2.0", "temporary file: %s", + mailerr("450 4.2.0", "Temporary file: %s", errstring(errno)); goto err1; } - if (setreuid(0, pw->pw_uid) < 0) - { - mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)", - pw->pw_uid, errstring(errno), getuid(), geteuid()); - goto err1; - } #ifdef DEBUG - fprintf(stderr, "new euid = %d\n", geteuid()); + fprintf(stderr, "before writing: euid = %d\n", geteuid()); #endif /* DEBUG */ #ifdef CONTENTLENGTH headerbytes = (BodyLength >= 0) ? HeaderLength : -1 ; @@ -1128,13 +1184,12 @@ { if ((nw = write(mbfd, buf + off, nr - off)) < 0) { + errcode = "450 4.2.0"; #ifdef EDQUOT - if (errno == EDQUOT && bouncequota) - mailerr("552 5.2.2", "%s: %s", - path, errstring(errno)); - else + if (errno == EDQUOT && BounceQuota) + errcode = "552 5.2.2"; #endif /* EDQUOT */ - mailerr("450 4.2.0", "%s: %s", + mailerr(errcode, "%s: %s", path, errstring(errno)); goto err3; } @@ -1142,7 +1197,7 @@ } if (nr < 0) { - mailerr("450 4.2.0", "temporary file: %s", + mailerr("450 4.2.0", "Temporary file: %s", errstring(errno)); goto err3; } @@ -1152,20 +1207,13 @@ { mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); err3: - if (setreuid(0, 0) < 0) - { -#if 0 - /* already printed an error above for this recipient */ - (void) e_to_sys(errno); - mailerr("450 4.2.0", "setreuid(0, 0): %s", - errstring(errno)); -#endif /* 0 */ - } + (void) setreuid(0, 0); #ifdef DEBUG fprintf(stderr, "reset euid = %d\n", geteuid()); #endif /* DEBUG */ (void) ftruncate(mbfd, curoff); -err1: (void) close(mbfd); +err1: if (mbfd >= 0) + (void) close(mbfd); err0: unlockmbox(); return; } @@ -1173,12 +1221,12 @@ /* Close and check -- NFS doesn't write until the close. */ if (close(mbfd)) { + errcode = "450 4.2.0"; #ifdef EDQUOT - if (errno == EDQUOT && bouncequota) - mailerr("552 5.2.2", "%s: %s", path, errstring(errno)); - else + if (errno == EDQUOT && BounceQuota) + errcode = "552 5.2.2"; #endif /* EDQUOT */ - mailerr("450 4.2.0", "%s: %s", path, errstring(errno)); + mailerr(errcode, "%s: %s", path, errstring(errno)); (void) truncate(path, curoff); } else @@ -1195,7 +1243,7 @@ #endif /* DEBUG */ unlockmbox(); if (LMTPMode) - printf("250 2.1.5 %s OK\r\n", name); + printf("250 2.1.5 %s Ok\r\n", name); } /* @@ -1212,7 +1260,7 @@ lockmbox(name) char *name; { - int r; + int r = 0; if (Locked) return 0; @@ -1350,7 +1398,7 @@ if (addr.sin_family == AF_UNSPEC) return; - if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) return; len = strlen(msg) + 1; (void) sendto(f, msg, len, 0, (struct sockaddr *) &addr, sizeof(addr)); @@ -1360,7 +1408,7 @@ usage() { ExitVal = EX_USAGE; - mailerr(NULL, "usage: mail.local [-l] [-f from] user ..."); + mailerr(NULL, "usage: mail.local [-7] [-b] [-l] [-f from] user ..."); exit(ExitVal); } @@ -1374,61 +1422,53 @@ va_dcl #endif /* __STDC__ */ { + size_t len = 0; va_list ap; + (void) e_to_sys(errno); + #ifdef __STDC__ va_start(ap, fmt); #else /* __STDC__ */ va_start(ap); #endif /* __STDC__ */ + if (LMTPMode) { if (hdr != NULL) - printf("%s ", hdr); - (void) vprintf(fmt, ap); - (void) printf("\r\n"); - } - else - { - (void) e_to_sys(errno); - vwarn(fmt, ap); + { + snprintf(ErrBuf, sizeof ErrBuf, "%s ", hdr); + len = strlen(ErrBuf); + } } + (void) vsnprintf(&ErrBuf[len], sizeof ErrBuf - len, fmt, ap); + + if (!HoldErrs) + flush_error(); + + /* Log the message to syslog. */ + if (!LMTPMode) + syslog(LOG_ERR, "%s", ErrBuf); } void -vwarn(fmt, ap) - const char *fmt; - _BSD_VA_LIST_ ap; +flush_error() { - /* - ** Log the message to stderr. - ** - ** Don't use LOG_PERROR as an openlog() flag to do this, - ** it's not portable enough. - */ - - if (ExitVal != EX_USAGE) - (void) fprintf(stderr, "mail.local: "); - (void) vfprintf(stderr, fmt, ap); - (void) fprintf(stderr, "\n"); - -#if USE_VSYSLOG - /* Log the message to syslog. */ - vsyslog(LOG_ERR, fmt, ap); -#else /* USE_VSYSLOG */ + if (LMTPMode) + printf("%s\r\n", ErrBuf); + else { - char fmtbuf[10240]; - - (void) vsnprintf(fmtbuf, sizeof fmtbuf, fmt, ap); - syslog(LOG_ERR, "%s", fmtbuf); + if (ExitVal != EX_USAGE) + (void) fprintf(stderr, "mail.local: "); + fprintf(stderr, "%s\n", ErrBuf); } -#endif /* USE_VSYSLOG */ } /* * e_to_sys -- * Guess which errno's are temporary. Gag me. */ + int e_to_sys(num) int num; @@ -1441,7 +1481,7 @@ { #ifdef EDQUOT case EDQUOT: /* Disc quota exceeded */ - if (bouncequota) + if (BounceQuota) { ExitVal = EX_UNAVAILABLE; break; @@ -1582,15 +1622,6 @@ return (_gettemp(path, &fd) ? fd : -1); } -# if 0 -char * -mktemp(path) - char *path; -{ - return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); -} -# endif /* 0 */ - static _gettemp(path, doopen) char *path; @@ -1636,8 +1667,8 @@ { if (doopen) { - if ((*doopen = - open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) + if ((*doopen = open(path, O_CREAT|O_EXCL|O_RDWR, + 0600)) >= 0) return(1); if (errno != EEXIST) return(0); Index: gnu/usr.sbin/sendmail/mailstats/mailstats.8 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/mailstats/mailstats.8,v retrieving revision 1.4 retrieving revision 1.7 diff -u -r1.4 -r1.7 --- gnu/usr.sbin/sendmail/mailstats/mailstats.8 2000/04/06 18:59:28 1.4 +++ gnu/usr.sbin/sendmail/mailstats/mailstats.8 2001/05/29 01:31:13 1.7 @@ -1,4 +1,4 @@ -.\" Copyright (c) 1998 Sendmail, Inc. and its suppliers. +.\" Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. .\" All rights reserved. .\" .\" By using this file, you agree to the terms and conditions set @@ -6,9 +6,9 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: mailstats.8,v 8.16 2000/02/01 05:49:53 gshapiro Exp $ +.\" $Sendmail: mailstats.8,v 8.17.4.6 2001/05/07 22:06:38 gshapiro Exp $ .\" -.Dd April 25, 1996 +.Dd May 7, 2001 .Dt MAILSTATS 1 .Os .Sh NAME @@ -52,11 +52,12 @@ .El .Pp After this display, a line totaling the values for all of the mailers -is displayed, +is displayed (preceded with a +.Dq T ) , separated from the previous information by a line containing only equals .Pq Dq \&= characters. -Another line preceeded with a +Another line preceded with a .Dq C lists the number of connections. .Pp @@ -65,14 +66,12 @@ .It Fl C Read the specified file instead of the default .Nm sendmail -.Dq cf -file. +configuration file. .It Fl f Read the specified statistics file instead of the statistics file specified in the .Nm sendmail -.Dq cf -file. +configuration file. .It Fl p Output information in program-readable mode and clear statistics. .It Fl o Index: gnu/usr.sbin/sendmail/mailstats/mailstats.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/mailstats/mailstats.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/mailstats/mailstats.c 2000/04/02 19:05:42 1.1.1.1 +++ gnu/usr.sbin/sendmail/mailstats/mailstats.c 2001/05/29 01:31:13 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -14,14 +14,14 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers.\n\ +"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ All rights reserved.\n\ Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Sendmail: mailstats.c,v 8.53 1999/10/13 05:43:54 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: mailstats.c,v 8.53.16.13 2001/05/07 22:06:38 gshapiro Exp $"; #endif /* ! lint */ #include @@ -39,8 +39,10 @@ #include #include + #define MNAMELEN 20 /* max length of mailer name */ + int main(argc, argv) int argc; @@ -66,11 +68,12 @@ extern char *optarg; extern int optind; + cfile = _PATH_SENDMAILCF; sfile = NULL; mnames = TRUE; progmode = FALSE; - while ((ch = getopt(argc, argv, "C:f:op")) != EOF) + while ((ch = getopt(argc, argv, "C:f:op")) != -1) { switch (ch) { @@ -93,7 +96,7 @@ case '?': default: usage: - (void) fputs("usage: mailstats [-C cffile] [-f stfile] -o -p\n", + (void) fputs("usage: mailstats [-C cffile] [-f stfile] [-o] [-p]\n", stderr); exit(EX_USAGE); } @@ -202,8 +205,8 @@ exit (EX_OSFILE); } - if ((fd = open(sfile, O_RDONLY)) < 0 || - (i = read(fd, &stats, sizeof stats)) < 0) + fd = open(sfile, O_RDONLY); + if ((fd < 0) || (i = read(fd, &stats, sizeof stats)) < 0) { save_errno = errno; (void) fputs("mailstats: ", stderr); Index: gnu/usr.sbin/sendmail/makemap/makemap.8 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/makemap/makemap.8,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/makemap/makemap.8 2000/04/04 04:50:14 1.2 +++ gnu/usr.sbin/sendmail/makemap/makemap.8 2001/01/17 04:57:56 1.4 @@ -8,9 +8,9 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: makemap.8,v 8.21 1999/07/30 06:15:31 gshapiro Exp $ +.\" $Sendmail: makemap.8,v 8.21.16.5 2000/12/29 18:12:20 gshapiro Exp $ .\" -.Dd November 16, 1992 +.Dd December 29, 2000 .Dt MAKEMAP 8 .Os .Sh NAME @@ -86,7 +86,9 @@ .Ss Flags .Bl -tag -width Fl .It Fl C Ar file -Use the specified sendmail configuration +Use the specified +.Nm +configuration .Ar file for looking up the TrustedUser option. .It Fl N Index: gnu/usr.sbin/sendmail/makemap/makemap.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/makemap/makemap.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/makemap/makemap.c 2000/04/07 19:20:37 1.2 +++ gnu/usr.sbin/sendmail/makemap/makemap.c 2001/01/15 21:09:05 1.3 @@ -21,9 +21,10 @@ #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Sendmail: makemap.c,v 8.135 2000/04/07 17:05:21 ca Exp $"; +static char id[] = "@(#)$Sendmail: makemap.c,v 8.135.4.13 2000/10/05 23:00:50 gshapiro Exp $"; #endif /* ! lint */ + #include #ifndef ISC_UNIX # include @@ -57,6 +58,7 @@ # define ISSEP(c) (isascii(c) && isspace(c)) #endif /* _FFR_DELIM */ + static void usage(progname) char *progname; @@ -132,8 +134,8 @@ if (pw != NULL) (void) strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); else - snprintf(rnamebuf, sizeof rnamebuf, - "Unknown UID %d", (int) RealUid); + (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", + (int) RealUid); RunAsUserName = RealUserName = rnamebuf; user_info.smdbu_id = RunAsUid; user_info.smdbu_group_id = RunAsGid; @@ -142,7 +144,7 @@ #define OPTIONS "C:Nc:t:deflorsuv" - while ((opt = getopt(argc, argv, OPTIONS)) != EOF) + while ((opt = getopt(argc, argv, OPTIONS)) != -1) { switch (opt) { @@ -336,7 +338,7 @@ (void) database->smdb_sync(database, 0); - if (geteuid() == 0 && TrustedUid != 0) + if (!unmake && geteuid() == 0 && TrustedUid != 0) { errno = database->smdb_set_owner(database, TrustedUid, -1); if (errno != SMDBE_OK) @@ -354,7 +356,6 @@ exitstat = EX_OK; if (unmake) { - bool stop; errno = database->smdb_cursor(database, &cursor, 0); if (errno != SMDBE_OK) { @@ -368,20 +369,18 @@ memset(&db_key, '\0', sizeof db_key); memset(&db_val, '\0', sizeof db_val); - for (stop = FALSE, lineno = 0; !stop; lineno++) + for (lineno = 0; ; lineno++) { errno = cursor->smdbc_get(cursor, &db_key, &db_val, SMDB_CURSOR_GET_NEXT); if (errno != SMDBE_OK) - { - stop = TRUE; - } - if (!stop) - printf("%.*s\t%.*s\n", - (int) db_key.data.size, - (char *) db_key.data.data, - (int) db_val.data.size, - (char *)db_val.data.data); + break; + + printf("%.*s\t%.*s\n", + (int) db_key.size, + (char *) db_key.data, + (int) db_val.size, + (char *)db_val.data); } (void) cursor->smdbc_close(cursor); @@ -428,16 +427,16 @@ memset(&db_key, '\0', sizeof db_key); memset(&db_val, '\0', sizeof db_val); - db_key.data.data = ibuf; + db_key.data = ibuf; for (p = ibuf; *p != '\0' && !(ISSEP(*p)); p++) { if (foldcase && isascii(*p) && isupper(*p)) *p = tolower(*p); } - db_key.data.size = p - ibuf; + db_key.size = p - ibuf; if (inclnull) - db_key.data.size++; + db_key.size++; if (*p != '\0') *p++ = '\0'; @@ -448,15 +447,15 @@ fprintf(stderr, "%s: %s: line %d: no RHS for LHS %s\n", progname, mapname, lineno, - (char *) db_key.data.data); + (char *) db_key.data); exitstat = EX_DATAERR; continue; } - db_val.data.data = p; - db_val.data.size = strlen(p); + db_val.data = p; + db_val.size = strlen(p); if (inclnull) - db_val.data.size++; + db_val.size++; /* ** Do the database insert. @@ -465,8 +464,8 @@ if (verbose) { printf("key=`%s', val=`%s'\n", - (char *) db_key.data.data, - (char *) db_val.data.data); + (char *) db_key.data, + (char *) db_val.data); } errno = database->smdb_put(database, &db_key, &db_val, @@ -491,7 +490,7 @@ fprintf(stderr, "%s: %s: line %d: key %s: put error: %s\n", progname, mapname, lineno, - (char *) db_key.data.data, + (char *) db_key.data, errstring(errno)); exitstat = EX_IOERR; } @@ -500,7 +499,7 @@ fprintf(stderr, "%s: %s: line %d: key %s: duplicate key\n", progname, mapname, - lineno, (char *) db_key.data.data); + lineno, (char *) db_key.data); exitstat = EX_DATAERR; } } Index: gnu/usr.sbin/sendmail/praliases/praliases.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/praliases/praliases.c,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/praliases/praliases.c 2000/04/03 02:52:11 1.2 +++ gnu/usr.sbin/sendmail/praliases/praliases.c 2001/05/29 01:31:13 1.5 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,7 +13,7 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ +"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ All rights reserved.\n\ Copyright (c) 1983 Eric P. Allman. All rights reserved.\n\ Copyright (c) 1988, 1993\n\ @@ -21,7 +21,7 @@ #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Sendmail: praliases.c,v 8.59 2000/03/17 07:32:47 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: praliases.c,v 8.59.4.19 2001/02/28 02:37:57 ca Exp $"; #endif /* ! lint */ #include @@ -33,6 +33,7 @@ #endif /* EX_OK */ #include + #ifndef NOT_SENDMAIL # define NOT_SENDMAIL #endif /* ! NOT_SENDMAIL */ @@ -55,6 +56,9 @@ extern void syserr __P((const char *, ...)); +# define DELIMITERS " ,/" +# define PATH_SEPARATOR ':' + int main(argc, argv) int argc; @@ -71,6 +75,7 @@ extern char *optarg; extern int optind; + clrbitmap(DontBlameSendmail); RunAsUid = RealUid = getuid(); RunAsGid = RealGid = getgid(); @@ -82,12 +87,12 @@ snprintf(rnamebuf, sizeof rnamebuf, "%s", pw->pw_name); } else - snprintf(rnamebuf, sizeof rnamebuf, - "Unknown UID %d", (int) RealUid); + (void) snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", + (int) RealUid); RunAsUserName = RealUserName = rnamebuf; cfile = _PATH_SENDMAILCF; - while ((ch = getopt(argc, argv, "C:f:")) != EOF) + while ((ch = getopt(argc, argv, "C:f:")) != -1) { switch ((char)ch) { case 'C': @@ -167,7 +172,7 @@ break; b = p; - p = strpbrk(p, " ,/"); + p = strpbrk(p, DELIMITERS); /* find end of spec */ if (p != NULL) @@ -241,7 +246,7 @@ SMDB_DBPARAMS params; SMDB_USER_INFO user_info; - colon = strchr(filename, ':'); + colon = strchr(filename, PATH_SEPARATOR); if (colon == NULL) { db_name = filename; @@ -259,6 +264,7 @@ { while (isascii(*db_name) && isspace(*db_name)) db_name++; + if (*db_name != '-') break; while (*db_name != '\0' && @@ -266,6 +272,21 @@ db_name++; } + /* Skip non-file based DB types */ + if (db_type != NULL && *db_type != '\0') + { + if (db_type != SMDB_TYPE_DEFAULT && + strcmp(db_type, "hash") != 0 && + strcmp(db_type, "btree") != 0 && + strcmp(db_type, "dbm") != 0) + { + fprintf(stderr, + "praliases: Skipping non-file based alias type %s\n", + db_type); + return; + } + } + if (*db_name == '\0' || (db_type != NULL && *db_type == '\0')) { if (colon != NULL) @@ -310,20 +331,20 @@ { #if 0 /* skip magic @:@ entry */ - if (db_key.data.size == 2 && - db_key.data.data[0] == '@' && - db_key.data.data[1] == '\0' && - db_value.data.size == 2 && - db_value.data.data[0] == '@' && - db_value.data.data[1] == '\0') + if (db_key.size == 2 && + db_key.data[0] == '@' && + db_key.data[1] == '\0' && + db_value.size == 2 && + db_value.data[0] == '@' && + db_value.data[1] == '\0') continue; #endif /* 0 */ printf("%.*s:%.*s\n", - (int) db_key.data.size, - (char *) db_key.data.data, - (int) db_value.data.size, - (char *) db_value.data.data); + (int) db_key.size, + (char *) db_key.data, + (int) db_value.size, + (char *) db_value.data); } if (result != SMDBE_OK && result != SMDBE_LAST_ENTRY) @@ -336,21 +357,29 @@ } else for (; *argv != NULL; ++argv) { + int get_res; + memset(&db_key, '\0', sizeof db_key); memset(&db_value, '\0', sizeof db_value); - db_key.data.data = *argv; - db_key.data.size = strlen(*argv) + 1; - if (database->smdb_get(database, &db_key, - &db_value, 0) == SMDBE_OK) + db_key.data = *argv; + db_key.size = strlen(*argv); + get_res = database->smdb_get(database, &db_key, &db_value, 0); + if (get_res == SMDBE_NOT_FOUND) + { + db_key.size++; + get_res = database->smdb_get(database, &db_key, + &db_value, 0); + } + if (get_res == SMDBE_OK) { printf("%.*s:%.*s\n", - (int) db_key.data.size, - (char *) db_key.data.data, - (int) db_value.data.size, - (char *) db_value.data.data); + (int) db_key.size, + (char *) db_key.data, + (int) db_value.size, + (char *) db_value.data); } else - printf("%s: No such key\n", (char *) db_key.data.data); + printf("%s: No such key\n", (char *) db_key.data); } fatal: Index: gnu/usr.sbin/sendmail/rmail/rmail.8 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/rmail/rmail.8,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- gnu/usr.sbin/sendmail/rmail/rmail.8 2000/04/02 19:48:34 1.2 +++ gnu/usr.sbin/sendmail/rmail/rmail.8 2001/01/15 21:09:06 1.3 @@ -8,14 +8,17 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: rmail.8,v 8.1 1999/06/22 20:41:33 tony Exp $ +.\" $Sendmail: rmail.8,v 8.1.16.2 2000/12/29 18:12:22 gshapiro Exp $ .\" -.TH RMAIL 8 "$Date: 2000/04/02 19:48:34 $" +.TH RMAIL 8 "$Date: 2001/01/15 21:09:06 $" .SH NAME -.B rmail +rmail \- handle remote mail received via uucp .SH SYNOPSIS .B rmail +.RB [ \-D +.IR domain ] +.RB [ \-T ] .I user ... .SH DESCRIPTION @@ -34,6 +37,15 @@ uucp and sendmail. +.SS Flags +.TP +.B \-D +Use the specified +.I domain +instead of the default domain of ``UUCP''. +.TP +.B \-T +Turn on debugging. .SH SEE ALSO uucp(1), mail.local(8), Index: gnu/usr.sbin/sendmail/rmail/rmail.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/rmail/rmail.c,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/rmail/rmail.c 2000/04/07 19:20:37 1.2 +++ gnu/usr.sbin/sendmail/rmail/rmail.c 2001/05/29 01:31:13 1.5 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. @@ -12,14 +12,14 @@ #ifndef lint static char copyright[] = -"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\ +"@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ All rights reserved.\n\ Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* ! lint */ #ifndef lint -static char id[] = "@(#)$Sendmail: rmail.c,v 8.39 2000/03/17 07:32:47 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: rmail.c,v 8.39.4.12 2001/05/07 22:06:39 gshapiro Exp $"; #endif /* ! lint */ /* @@ -89,17 +89,17 @@ # define STDIN_FILENO 0 #endif /* ! STDIN_FILENO */ -#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) +#if defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 || defined(HPUX11) # define HASSNPRINTF 1 -#endif /* defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ +#endif /* defined(BSD4_4) || defined(linux) || SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) || _AIX4 >= 40300 || defined(HPUX11) */ #if defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) # define memmove(d, s, l) (bcopy((s), (d), (l))) #endif /* defined(sun) && !defined(BSD) && !defined(SOLARIS) && !defined(__svr4__) && !defined(__SVR4) */ -#if !HASSNPRINTF +#if !HASSNPRINTF && !SFIO extern int snprintf __P((char *, size_t, const char *, ...)); -#endif /* !HASSNPRINTF */ +#endif /* !HASSNPRINTF && !SFIO */ #if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) # ifndef HASSTRERROR @@ -151,14 +151,14 @@ FILE *fp; char *addrp = NULL, *domain, *p, *t; char *from_path, *from_sys, *from_user; - char *args[100], buf[2048], lbuf[2048]; + char **args, buf[2048], lbuf[2048]; struct stat sb; extern char *optarg; extern int optind; debug = 0; domain = "UUCP"; /* Default "domain". */ - while ((ch = getopt(argc, argv, "D:T")) != EOF) + while ((ch = getopt(argc, argv, "D:T")) != -1) { switch (ch) { @@ -206,7 +206,7 @@ break; } - if (*addrp == '\0') + if (addrp == NULL || *addrp == '\0') err(EX_DATAERR, "corrupted From line: %s", lbuf); /* Use the "remote from" if it exists. */ @@ -310,6 +310,10 @@ offset = (off_t)ftell(stdin); } + + /* Allocate args (with room for sendmail args as well as recipients) */ + args = (char **)xalloc(sizeof(*args) * (10 + argc)); + i = 0; args[i++] = _PATH_SENDMAIL; /* Build sendmail's argument list. */ args[i++] = "-oee"; /* No errors, just status. */ @@ -338,7 +342,7 @@ ** the address (helps to pass addrs like @gw1,@gw2:aa@bb) */ - while (*argv) + while (*argv != NULL) { if (**argv == '-') err(EX_USAGE, "dash precedes argument: %s", *argv); @@ -353,13 +357,18 @@ snprintf(args[i++], len, "<%s>", *argv); } argv++; + argc--; + + /* Paranoia check, argc used for args[] bound */ + if (argc < 0) + err(EX_SOFTWARE, "Argument count mismatch"); } - args[i] = 0; + args[i] = NULL; if (debug) { fprintf(stderr, "Sendmail arguments:\n"); - for (i = 0; args[i]; i++) + for (i = 0; args[i] != NULL; i++) fprintf(stderr, "\t%s\n", args[i]); } Index: gnu/usr.sbin/sendmail/sendmail/Makefile =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/Makefile,v retrieving revision 1.9 retrieving revision 1.12 diff -u -r1.9 -r1.12 --- gnu/usr.sbin/sendmail/sendmail/Makefile 2000/10/09 23:45:00 1.9 +++ gnu/usr.sbin/sendmail/sendmail/Makefile 2001/05/05 22:00:17 1.12 @@ -1,11 +1,22 @@ -# $OpenBSD: Makefile,v 1.9 2000/10/09 23:45:00 millert Exp $ +# $OpenBSD: Makefile,v 1.12 2001/05/05 22:00:17 millert Exp $ PROG= sendmail WANT_LIBWRAP=1 WANT_LIBSMUTIL=1 -# To casue sendmail to drop privs in test mode (-bt) uncomment the following +# For TLS/SSL support +ENVDEF+= -DSTARTTLS -D_FFR_TLS_TOREK +LDADD+= -lssl -lcrypto +DPADD= ${LIBSSL} ${LIBCRYPTO} + +# Work around broken name servers that return SERV_FAIL for AAAA records +ENVDEF+= -D_FFR_WORKAROUND_BROKEN_NAMESERVERS + +# Since we have random PIDs we need to be careful to avoid filename collisions +ENVDEF+= -DFAST_PID_RECYCLE + +# To cause sendmail to drop privs in test mode (-bt) uncomment the following #ENVDEF+= -D_FFR_TESTMODE_DROP_PRIVS SRCS= main.c alias.c arpadate.c bf_torek.c clock.c collect.c \ Index: gnu/usr.sbin/sendmail/sendmail/README =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/README,v retrieving revision 1.3 retrieving revision 1.6 diff -u -r1.3 -r1.6 --- gnu/usr.sbin/sendmail/sendmail/README 2000/04/07 19:20:38 1.3 +++ gnu/usr.sbin/sendmail/sendmail/README 2001/05/29 01:31:13 1.6 @@ -1,4 +1,4 @@ -# Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. +# Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. # All rights reserved. # Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. # Copyright (c) 1988 @@ -9,7 +9,7 @@ # the sendmail distribution. # # -# $Sendmail: README,v 8.263 2000/04/06 20:27:44 gshapiro Exp $ +# $Sendmail: README,v 8.263.2.1.2.35 2001/05/09 20:58:32 gshapiro Exp $ # This directory contains the source files for sendmail(TM). @@ -268,6 +268,7 @@ the stat structure (see stat(2)). HASSRANDOMDEV Define this if your system has the srandomdev(3) function call. +HASURANDOMDEV Define this if your system has /dev/urandom(4). HASSTRERROR Define this if you have the libc strerror(3) function (which should be declared in ), and it should be used instead of sys_errlist. @@ -450,8 +451,18 @@ FAST_PID_RECYCLE Set this if your system can reuse the same PID in the same second. +SO_REUSEADDR_IS_BROKEN + Set this if your system has a setsockopt() SO_REUSEADDR + flag but doesn't pay attention to it when trying to bind a + socket to a recently closed port. +SNPRINTF_IS_BROKEN + Set this if your system has an snprintf() implementation + which does not NUL terminate the string being filled in. + Use test/t_snprintf.c to test your system. +NEEDSGETIPNODE Set this if your system supports IPv6 but doesn't include + the getipnodeby{name,addr}() functions. Set automatically + for Linux's glibc. - +-----------------------+ | COMPILE-TIME FEATURES | +-----------------------+ @@ -508,6 +519,8 @@ in conf.h. You probably want this. NETINET6 Set this to get IPv6 support. Other configuration may be needed in conf.h for your particular operating system. + Also, DaemonPortOptions must be set appropriately for + sendmail to accept IPv6 connections. NETISO Define this to get ISO networking support. NETUNIX Define this to get Unix domain networking support. Defined by default. A few bizarre systems (SCO, ISC, Altos) don't @@ -565,6 +578,26 @@ is sufficient. Any value other than 1 (or 0) will be compared with the actual version found and if there is a mismatch, compilation will fail. +EGD Define this if your system has EGD installed, see + http://www.lothar.com/tech/crypto/ . It should be used to + seed the PRNG for STARTTLS if HASURANDOMDEV is not defined. +STARTTLS Enables SMTP STARTTLS (RFC 2487). This requires OpenSSL + (http://www.OpenSSL.org/) and sfio (see below). + Use OpenSSL 0.9.5a or later (if compatible with this + version), do not use 0.9.3. + See STARTTLS COMPILATION AND CONFIGURATION for further + information. +TLS_NO_RSA Turn off support for RSA algorithms in STARTTLS. +SFIO Uses sfio instead of stdio. sfio is available from AT&T + (http://www.research.att.com/sw/tools/sfio/). If this + compile flag is set, confSTDIO_TYPE must be set to portable. + This compile flag is necessary for STARTTLS; it also + enables the security layer of SASL. The sfio include file + stdio.h must be installed in a subdirectory called sfio, + i.e., if you install sfio in /usr/local, stdio.h should + be in /usr/local/include/sfio, and libsfio.a should be in + /usr/local/lib. Notice: read the sfio section in + OPERATING SYSTEM AND COMPILE QUIRKS. +---------------------+ @@ -598,7 +631,51 @@ wildcard MX records that match your domain. ANYTHING ELSE WILL GIVE YOU HEADACHES! +When attempting to canonify a hostname, some broken name servers will +return SERVFAIL (a temporary failure) on T_AAAA (IPv6) lookups. If you +want to excuse this behavior, compile sendmail with +-D_FFR_WORKAROUND_BROKEN_NAMESERVERS and add WorkAroundBrokenAAAA to your +ResolverOptions setting. However, instead, we recommend catching the +problem and reporting it to the name server administrator so we can rid the +world of broken name servers. + ++----------------------------------------+ +| STARTTLS COMPILATION AND CONFIGURATION | ++----------------------------------------+ + +Please read the docs accompanying the OpenSSL library and sfio. +You have to compile and install both libraries before you can compile +sendmail. See devtools/README how to set the correct compile time +parameters; you should at least set the following variables: + +define(`confSTDIO_TYPE', `portable') +APPENDDEF(`confENVDEF', `-DSFIO') +APPENDDEF(`confLIBS', `-lsfio') +APPENDDEF(`conf_sendmail_ENVDEF', `-DSTARTTLS') +APPENDDEF(`conf_sendmail_LIBS', `-lssl -lcrypto') + +Configuration information can be found in doc/op/op.me (required +certificates) and cf/README (how to tell sendmail about certificates). + +To perform an initial test, connect to your sendmail daemon +(telnet localhost 25) and issue a EHLO localhost and see whether +250-STARTTLS +is in the response. If it isn't, run the daemon with +-O LogLevel=14 +and try again. Then take a look at the logfile and see whether +there are any problems listed about permissions (unsafe files) +or the validity of X.509 certificates. + +Note: sfio must be used in all libraries with which sendmail exchanges +file pointers. That is, libsmutil must be compiled with sfio, which +is accomplished by the above config parameters. Another example is +PH map support. This does not apply to the usual libraries, e.g., +OpenSSL, Berkeley DB, Cyrus SASL. + +Further information can be found via: +http://www.sendmail.org/tips/ + +------------------------------------+ | SASL COMPILATION AND CONFIGURATION | +------------------------------------+ @@ -622,8 +699,8 @@ and try again. Then take a look at the logfile and see whether there are any security related problems listed (unsafe files). -Further information can be found at: -http://www.sendmail.org/~ca/email/auth.html +Further information can be found via: +http://www.sendmail.org/tips/ +-------------------------------------+ @@ -722,7 +799,7 @@ NOTE: The SunOS 4.X linker uses library paths specified during compilation using -L for run-time shared library searches. Therefore, it is vital that relative and unsafe directory paths not - be using when compiling sendmail. + be used when compiling sendmail. SunOS 4.0.2 (Sun 386i) Date: Fri, 25 Aug 1995 11:13:58 +0200 (MET DST) @@ -765,44 +842,6 @@ make sure /opt/SUNWspro/bin/cc is used instead of /usr/ucb/cc (or it might complain about tm_zone). - To the best of my knowledge, Solaris does not have the - gethostbyname problem described above. However, it does - have another one: - - From a correspondent: - - For solaris 2.2, I have - - hosts: files dns - - in /etc/nsswitch.conf and /etc/hosts has to have the fully - qualified host name. I think "files" has to be before "dns" - in /etc/nsswitch.conf during bootup. - - From another correspondent: - - When running sendmail under Solaris, the gethostbyname() - hack in conf.c which should perform proper canonicalization - of host names could fail. Result: the host name is not - canonicalized despite the hack, and you'll have to define $j - and $m in sendmail.cf somewhere. - - The reason could be that /etc/nsswitch.conf is improperly - configured (at least from sendmail's point of view). For - example, the line - - hosts: files nisplus dns - - will make gethostbyname() look in /etc/hosts first, then ask - nisplus, then dns. However, if /etc/hosts does not contain - the full canonicalized hostname, then no amount of - gethostbyname()s will work. - - Solution (or rather, a workaround): Ask nisplus first, then - dns, then local files: - - hosts: nisplus dns [NOTFOUND=return] files - The Solaris "syslog" function is apparently limited to something about 90 characters because of a kernel limitation. If you have source code, you can probably up this number. You can get patches @@ -854,12 +893,6 @@ >> >> here, path 2 would be the first used. -Solaris 2.6 (SunOS 5.6) - If you built sendmail 8.8.1 through 8.8.4 inclusive on a Solaris 2.5 - system, that binary will not run on Solaris 2.6, due to problems with - incompatible snprintf(3s) calls. This problem is fixed in sendmail - 8.8.5. - Solaris 2.5.1 (SunOS 5.5.1) and 2.6 (SunOS 5.6) Apparently Solaris 2.5.1 patch 103663-01 installs a new /usr/include/resolv.h file that defines the __P macro without @@ -894,6 +927,25 @@ to ldap_set_option for LDAP_OPT_REFERRALS in ldapmap_setopts if LDAP support is compiled in sendmail. +Solaris + If you are using dns for hostname resolution on Solaris, make sure + that the 'dns' entry is last on the hosts line in + '/etc/nsswitch.conf'. For example, use: + + hosts: nisplus files dns + + Do not use: + + host: nisplus dns [NOTFOUND=return] files + + Note that 'nisplus' above is an illustration. The same comment + applies no matter what naming services you are using. If you have + anything other than dns last, even after "[NOTFOUND=return]", + sendmail may not be able to determine whether an error was + temporary or permanent. The error returned by the solaris + gethostbyname() is the error for the last lookup used, and other + naming services do not have the same concept of temporary failure. + Ultrix By default, the IDENT protocol is turned off on Ultrix. If you are running Ultrix 4.4 or later, or if you have included patch @@ -990,6 +1042,12 @@ If you are using XFS filesystem, avoid using the -32 ABI switch to the cc compiler if possible. + Broken inet_aton and inet_ntoa on IRIX using gcc: There's + a problem with gcc on IRIX, i.e., gcc can't pass structs + less than 16 bits long unless they are 8 bits; IRIX 6.2 has + some other sized structs. See + http://www.bitmechanic.com/mail-archives/mysql/current/0418.html + IRIX 6.4 The IRIX 6.5.4 version of /bin/m4 does not work properly with sendmail. Either install fw_m4.sw.m4 off the Freeware_May99 CD and @@ -1016,8 +1074,6 @@ in your .cf file. - You may have to use -DNeXT. - BSDI (BSD/386) 1.0, NetBSD 0.9, FreeBSD 1.0 The "m4" from BSDI won't handle the config files properly. I haven't had a chance to test this myself. @@ -1050,9 +1106,11 @@ determined to continue to use your old, buggy version (or as a shortcut to get sendmail working -- I'm sure you have the best intentions to port a modern version of BIND), you can - copy ../contrib/oldbind.compat.c into sendmail and add - oldbind.compat.o to OBJADD in the Makefile. + copy ../contrib/oldbind.compat.c into sendmail and add the + following to devtools/Site/site.config.m4: + APPENDDEF(`confOBJADD', `oldbind.compat.o') + A/UX Date: Tue, 12 Oct 1993 18:28:28 -0400 (EDT) From: "Eric C. Hagberg" @@ -1185,6 +1243,22 @@ implementation in the Linux 2.2.0 kernel and poll()-aware versions of glib (at least up to 2.0.111). + Some pre-glibc distributions of Linux include a syslog.h that does + not work properly with SFIO. You can fix this by adding + "#include " to the SFIO version of stdio.h as the very + first line. + +glibc + glibc 2.2.1 (and possibly other versions) changed the value of + __RES in resolv.h but failed to actually provide the IPv6 API + changes that the change implied. Therefore, compiling with + -DNETINET6 fails. + + Workarounds: + 1) Compile without -DNETINET6 + 2) Build against a real BIND 8.2.2 include/lib tree + 3) Wait for glibc to fix it + AIX 4.X The AIX 4.X linker uses library paths specified during compilation using -L for run-time shared library searches. Therefore, it is @@ -1206,7 +1280,21 @@ gcc -Wl,-rpath /usr/lib -Wl,-rpath /lib -Wl,-rpath /usr/local/lib -AIX 4.2 +AIX 4.3.3 + From: Valdis.Kletnieks@vt.edu + Date: Sun, 02 Jul 2000 03:58:02 -0400 + + Under AIX 4.3.3, after applying bos.adt.include 4.3.3.12 to close the + BIND 8.2.2 security holes, you can no longer build with -DNETINET6 + because they changed the value of __RES in resolv.h but failed to + actually provide the API changes that the change implied. + + Workarounds: + 1) Compile without -DNETINET6 + 2) Build against a real BIND 8.2.2 include/lib tree + 3) Wait for IBM to fix it + +AIX 4.X The AIX m4 implements a different mechanism for ifdef which is inconsistent with other versions of m4. Therefore, it will not work properly with the sendmail Build architecture or m4 @@ -1269,10 +1357,6 @@ about the location of the 'getloadavg' routine if you use the LA_SUBR define. - - Manual pages will format correctly if given the mandoc macros - and used with nroff. I have not tried groff. - RISC/os RISC/os from MIPS is a merged AT&T/Berkeley system. When you compile on that platform you will get duplicate definitions @@ -1367,6 +1451,21 @@ problems. You may want to turn this off if you have problems running sendmail. Reported by Jerry G. DeLapp . +Mac OS X (10.0.X) + From: Mike Zimmerman + From scratch here is what Darwin users need to do to the standard + 10.0.0, 10.0.1 install to get sendmail working. + From http://www.macosx.com/forums/showthread.php?s=6dac0e9e1f3fd118a4870a8a9b559491&threadid=2242: + 1. chmod g-w / /private /private/etc + 2. Properly set HOSTNAME in /etc/hostconfig to your FQDN: + HOSTNAME=-my.domain.com- + 3. Edit /etc/rc.boot: + hostname my.domain.com + domainname domain.com + 4. Edit /System/Library/StartupItems/Sendmail/Sendmail: + Remove the "&" after the sendmail command: + /usr/sbin/sendmail -bd -q1h + GNU getopt I'm told that GNU getopt has a problem in that it gets confused by the double call. Use the version in conf.c instead. @@ -1426,9 +1525,37 @@ cause it to use "HELO hostname" (which Z-mail apparently requires as well. :) +OpenSSL + OpenSSL versions prior to 0.9.6 use a macro named Free which + conflicts with existing macro names on some platforms, such as + AIX. + Do not use 0.9.3, but OpenSSL 0.9.5a or later if compatible with + 0.9.5a. + +sfio + You may run into problems if you use sfio2000 (the body of a + message is lost). Use sfio1999 instead; however, it also has + a bug that can cause sendmail to fail. A patch has been provided + by Petr Lampa of Brno University of Technology, which is given here: + +diff -rc ../../../../sfio/src/lib/sfio/sfputr.c ./sfputr.c +*** ../../../../sfio/src/lib/sfio/sfputr.c Tue May 16 18:25:49 2000 +--- ./sfputr.c Wed Sep 20 09:06:01 2000 +*************** +*** 24,29 **** +--- 24,30 ---- + for(w = 0; (*s || rc >= 0); ) + { SFWPEEK(f,ps,p); + ++ if(p == -1) return -1; /* PL */ + if(p == 0 || (f->flags&SF_WHOLE) ) + { n = strlen(s); + if(p >= (n + (rc < 0 ? 0 : 1)) ) + + PH PH support is provided by Mark Roth . The map is - described at http://www-wsg.cso.uiuc.edu/sendmail/patches/ . + described at http://www-dev.cso.uiuc.edu/sendmail/ . Please contact Mark Roth for support and questions regarding the map. @@ -1504,12 +1631,15 @@ The following list describes the files in this directory: +Build Shell script for building sendmail. +Makefile A convenience for calling ./Build. Makefile.m4 A template for constructing a makefile based on the information in the devtools directory. README This file. TRACEFLAGS My own personal list of the trace flags -- not guaranteed to be particularly up to date. alias.c Does name aliasing in all forms. +aliases.5 Man page describing the format of the aliases file. arpadate.c A subroutine which creates ARPANET standard dates. bf.h Buffered file I/O function declarations. bf_portable.c Stub routines for systems lacking the Torek stdio library. @@ -1533,33 +1663,39 @@ deliver.c Routines to deliver mail. domain.c Routines that interface with DNS (the Domain Name System). -err.c Routines to print error messages. envelope.c Routines to manipulate the envelope structure. +err.c Routines to print error messages. headers.c Routines to process message headers. +helpfile An example helpfile for the SMTP HELP command and -bt mode. macro.c The macro expander. This is used internally to insert information from the configuration file. +mailq.1 Man page for the mailq command. main.c The main routine to sendmail. This file also contains some miscellaneous routines. +makesendmail A convenience for calling ./Build. map.c Support for database maps. mci.c Routines that handle mail connection information caching. +milter.c MTA portions of the mail filter API. mime.c MIME conversion routines. +newaliases.1 Man page for the newaliases command. parseaddr.c The routines which do address parsing. queue.c Routines to implement message queueing. readcf.c The routine that reads the configuration file and translates it to internal form. recipient.c Routines that manipulate the recipient list. -safefile.c Routines to do careful checking of file modes and permissions - when opening or creating files. savemail.c Routines which save the letter on processing errors. +sendmail.8 Man page for the sendmail command. sendmail.h Main header file for sendmail. +sfsasl.c I/O interface between SASL/TLS and the MTA using SFIO. +sfsasl.h Header file for sfsasl.c. shmticklib.c Routines for shared memory counters. -snprintf.c Routines to manipulate strings but prevent buffer overflows. srvrsmtp.c Routines to implement server SMTP. stab.c Routines to manage the symbol table. stats.c Routines to collect and post the statistics. statusd_shm.h Data structure and function declarations for shmticklib.c. sysexits.c List of error messages associated with error codes in sysexits.h. +sysexits.h List of error codes for systems that lack their own. timers.c Routines to provide microtimers. timers.h Data structure and function declarations for timers.h. trace.c The trace package. These routines allow setting and @@ -1568,7 +1704,6 @@ usersmtp.c Routines to implement user SMTP. util.c Some general purpose routines used by sendmail. version.c The version number and information about this - version of sendmail. Theoretically, this gets - modified on every change. + version of sendmail. -(Version $Revision: 1.3 $, last update $Date: 2000/04/07 19:20:38 $ ) +(Version $Revision: 1.6 $, last update $Date: 2001/05/29 01:31:13 $ ) Index: gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/TRACEFLAGS 2001/05/29 01:31:14 1.3 @@ -1,4 +1,4 @@ -# $Sendmail: TRACEFLAGS,v 8.29 1999/11/04 23:31:02 gshapiro Exp $ +# $Sendmail: TRACEFLAGS,v 8.29.16.1 2001/05/03 17:24:00 gshapiro Exp $ 0, 1 main.c main skip background fork 0, 4 main.c main canonical name, UUCP node name, a.k.a.s 0, 15 main.c main print configuration @@ -75,6 +75,7 @@ 62 multiple file descriptor checking 63 queue.c runqueue process watching 64 multiple Milter +67 conf.c signals 80 content length 81 sun remote mode 91 mci.c syslogging of MCI cache information Index: gnu/usr.sbin/sendmail/sendmail/alias.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/alias.c,v retrieving revision 1.2 retrieving revision 1.4 diff -u -r1.2 -r1.4 --- gnu/usr.sbin/sendmail/sendmail/alias.c 2000/04/07 19:20:38 1.2 +++ gnu/usr.sbin/sendmail/sendmail/alias.c 2001/05/29 01:31:14 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,9 +13,12 @@ #include #ifndef lint -static char id[] = "@(#)$Sendmail: alias.c,v 8.142 2000/03/31 05:35:29 ca Exp $"; +static char id[] = "@(#)$Sendmail: alias.c,v 8.142.4.11 2001/05/03 17:24:01 gshapiro Exp $"; #endif /* ! lint */ +# define SEPARATOR ':' +# define ALIAS_SPEC_SEPARATORS " ,/:" + static MAP *AliasFileMap = NULL; /* the actual aliases.files map */ static int NAliasFileMaps; /* the number of entries in AliasFileMap */ @@ -276,9 +279,8 @@ map = &s->s_map; memset(map, '\0', sizeof *map); map->map_mname = s->s_name; - - p = strpbrk(p, " ,/:"); - if (p != NULL && *p == ':') + p = strpbrk(p, ALIAS_SPEC_SEPARATORS); + if (p != NULL && *p == SEPARATOR) { /* map name */ *p++ = '\0'; @@ -403,8 +405,9 @@ dprintf("aliaswait: sleeping for %u seconds\n", sleeptime); + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); (void) sleep(sleeptime); sleeptime *= 2; if (sleeptime > 60) @@ -435,7 +438,8 @@ { #if !_FFR_REMOVE_AUTOREBUILD /* database is out of date */ - if (AutoRebuild && stb.st_ino != 0 && + if (AutoRebuild && + stb.st_ino != 0 && (stb.st_uid == geteuid() || (geteuid() == 0 && stb.st_uid == TrustedUid))) { @@ -446,8 +450,9 @@ SuprErrs = TRUE; if (isopen) { + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } (void) rebuildaliases(map, TRUE); isopen = map->map_class->map_open(map, O_RDONLY); @@ -592,16 +597,17 @@ /* add distinguished entries and close the database */ if (bitset(MF_OPEN, map->map_mflags)) { + map->map_mflags |= MF_CLOSING; map->map_class->map_close(map); - map->map_mflags &= ~(MF_OPEN|MF_WRITABLE); + map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING); } /* restore the old signals */ (void) setsignal(SIGINT, oldsigint); (void) setsignal(SIGQUIT, oldsigquit); -#ifdef SIGTSTP +# ifdef SIGTSTP (void) setsignal(SIGTSTP, oldsigtstp); -#endif /* SIGTSTP */ +# endif /* SIGTSTP */ return success; } /* @@ -729,7 +735,7 @@ register char *nlp; nlp = &p[strlen(p)]; - if (nlp[-1] == '\n') + if (nlp > p && nlp[-1] == '\n') *--nlp = '\0'; if (CheckAliases) @@ -824,21 +830,21 @@ } if (al.q_paddr != NULL) - free(al.q_paddr); + sm_free(al.q_paddr); if (al.q_host != NULL) - free(al.q_host); + sm_free(al.q_host); if (al.q_user != NULL) - free(al.q_user); + sm_free(al.q_user); } CurEnv->e_to = NULL; FileName = NULL; if (Verbose || announcestats) - message("%s: %d aliases, longest %d bytes, %d bytes total", + message("%s: %ld aliases, longest %ld bytes, %ld bytes total", map->map_file, naliases, longest, bytes); if (LogLevel > 7 && logstats) sm_syslog(LOG_INFO, NOQID, - "%s: %d aliases, longest %d bytes, %d bytes total", + "%s: %ld aliases, longest %ld bytes, %ld bytes total", map->map_file, naliases, longest, bytes); } /* @@ -900,12 +906,12 @@ char buf[MAXPATHLEN + 1]; struct stat st; - ep = strchr(pp, ':'); + ep = strchr(pp, SEPARATOR); if (ep != NULL) *ep = '\0'; expand(pp, buf, sizeof buf, e); if (ep != NULL) - *ep++ = ':'; + *ep++ = SEPARATOR; if (buf[0] == '\0') continue; if (tTd(27, 3)) Index: gnu/usr.sbin/sendmail/sendmail/aliases =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/aliases,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- gnu/usr.sbin/sendmail/sendmail/aliases 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/aliases 2001/01/15 21:09:06 1.2 @@ -1,5 +1,5 @@ # -# $Sendmail: aliases,v 8.1 1999/02/06 18:44:07 gshapiro Exp $ +# $Sendmail: aliases,v 8.1.36.1 2000/10/16 20:18:39 gshapiro Exp $ # @(#)aliases 8.2 (Berkeley) 3/5/94 # # Aliases in this file will NOT be expanded in the header from @@ -31,24 +31,3 @@ # trap decode to catch security attacks decode: root - -# OFFICIAL CSRG/BUG ADDRESSES - -# Ftp maintainer. -ftp: ftp-bugs -ftp-bugs: bigbug@cs.berkeley.edu - -# Distribution office. -bsd-dist: bsd-dist@cs.berkeley.edu - -# Fortune maintainer. -fortune: fortune@cs.berkeley.edu - -# Termcap maintainer. -termcap: termcap@cs.berkeley.edu - -# General bug address. -ucb-fixes: bigbug@cs.berkeley.edu -ucb-fixes-request: bigbug@cs.berkeley.edu -bugs: bugs@cs.berkeley.edu -# END OFFICIAL BUG ADDRESSES Index: gnu/usr.sbin/sendmail/sendmail/aliases.5 =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/aliases.5,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- gnu/usr.sbin/sendmail/sendmail/aliases.5 2000/06/11 21:03:39 1.4 +++ gnu/usr.sbin/sendmail/sendmail/aliases.5 2001/01/15 21:09:06 1.5 @@ -9,9 +9,9 @@ .\" the sendmail distribution. .\" .\" -.\" $Sendmail: aliases.5,v 8.15 2000/02/26 01:12:21 ca Exp $ +.\" $Sendmail: aliases.5,v 8.15.4.2 2000/12/14 23:08:15 gshapiro Exp $ .\" -.Dd February 26, 1999 +.Dd December 14, 2000 .Dt ALIASES 5 .Os .Sh NAME @@ -104,8 +104,8 @@ command should be executed each time the aliases file is changed for the change to take effect. .Sh SEE ALSO -.Xr dbopen 3 , .Xr dbm 3 , +.Xr dbopen 3 , .Xr newaliases 8 , .Xr sendmail 8 .Rs Index: gnu/usr.sbin/sendmail/sendmail/arpadate.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/arpadate.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/sendmail/arpadate.c 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/arpadate.c 2001/05/29 01:31:14 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998, 1999, 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: arpadate.c,v 8.23 1999/09/23 19:59:18 ca Exp $"; +static char id[] = "@(#)$Sendmail: arpadate.c,v 8.23.20.2 2001/05/07 22:07:26 gshapiro Exp $"; #endif /* ! lint */ #include @@ -117,11 +117,12 @@ *q++ = *p++; /* - * should really get the timezone from the time in "ud" (which - * is only different if a non-null arg was passed which is different - * from the current time), but for all practical purposes, returning - * the current local zone will do (its all that is ever needed). - */ + ** should really get the timezone from the time in "ud" (which + ** is only different if a non-null arg was passed which is different + ** from the current time), but for all practical purposes, returning + ** the current local zone will do (its all that is ever needed). + */ + gmt = *gmtime(&t); lt = localtime(&t); Index: gnu/usr.sbin/sendmail/sendmail/bf.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/bf.h,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/sendmail/bf.h 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/bf.h 2001/02/28 02:43:53 1.3 @@ -1,12 +1,12 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999, 2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. * - * $Sendmail: bf.h,v 8.5 1999/11/04 19:31:25 ca Exp $ + * $Sendmail: bf.h,v 8.5.16.2 2001/02/14 04:07:27 gshapiro Exp $ * * Contributed by Exactis.com, Inc. * @@ -20,6 +20,7 @@ extern int bfcommit __P((FILE *)); extern int bfrewind __P((FILE *)); extern int bftruncate __P((FILE *)); +extern int bffsync __P((FILE *)); extern int bfclose __P((FILE *)); extern bool bftest __P((FILE *)); Index: gnu/usr.sbin/sendmail/sendmail/bf_portable.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/bf_portable.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/sendmail/bf_portable.c 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/bf_portable.c 2001/05/29 01:31:14 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -11,9 +11,12 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: bf_portable.c,v 8.25 2000/02/26 01:32:25 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: bf_portable.c,v 8.25.4.6 2001/05/03 17:24:01 gshapiro Exp $"; #endif /* ! lint */ +#if SFIO +# include +#endif /* SFIO */ #include #include @@ -22,10 +25,15 @@ #include #include #include +#if !SFIO # include -#ifndef BF_STANDALONE +#endif /* !SFIO */ +#ifdef BF_STANDALONE +# define sm_free free +# define xalloc malloc +#else /* BF_STANDALONE */ # include "sendmail.h" -#endif /* ! BF_STANDALONE */ +#endif /* BF_STANDALONE */ #include "bf_portable.h" #include "bf.h" @@ -90,7 +98,7 @@ } /* Allocate memory */ - bfp = (struct bf *)malloc(sizeof(struct bf)); + bfp = (struct bf *)xalloc(sizeof(struct bf)); if (bfp == NULL) { (void) fclose(retval); @@ -105,10 +113,10 @@ filename, (long) sizeof(struct bf)); l = strlen(filename) + 1; - bfp->bf_filename = (char *)malloc(l); + bfp->bf_filename = (char *)xalloc(l); if (bfp->bf_filename == NULL) { - free(bfp); + sm_free(bfp); (void) fclose(retval); /* don't care about errors */ @@ -120,7 +128,7 @@ /* Fill in the other fields, then add it to the list */ bfp->bf_key = retval; - bfp->bf_committed = 0; + bfp->bf_committed = FALSE; bfp->bf_refcount = 1; bfinsert(bfp); @@ -219,7 +227,6 @@ /* check to see if there is an error on the stream */ err = ferror(fp); - (void) fflush(fp); /* @@ -278,6 +285,47 @@ } /* +** BFFSYNC -- fsync the fd associated with the FILE * +** +** Parameters: +** fp -- FILE * to fsync +** +** Returns: +** 0 on success, -1 on error +** +** Sets errno: +** EINVAL if FILE * not bfcommitted yet. +** any value of errno specified by fsync() +*/ + +int +bffsync(fp) + FILE *fp; +{ + int fd; + struct bf *bfp; + + /* Get associated bf structure */ + bfp = bflookup(fp); + + /* If called on a normal FILE *, noop */ + if (bfp != NULL && !bfp->bf_committed) + fd = -1; + else + fd = fileno(fp); + + if (tTd(58, 10)) + dprintf("bffsync: fd = %d\n", fd); + + if (fd < 0) + { + errno = EINVAL; + return -1; + } + return fsync(fd); +} + + /* ** BFCLOSE -- close a buffered file ** ** Parameters: @@ -333,8 +381,8 @@ if (!bfp->bf_committed) retval = unlink(bfp->bf_filename); - free(bfp->bf_filename); - free(bfp); + sm_free(bfp->bf_filename); + sm_free(bfp); if (tTd(58, 8)) dprintf("bfclose: freed %ld\n", (long) sizeof(struct bf)); Index: gnu/usr.sbin/sendmail/sendmail/bf_torek.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/bf_torek.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/sendmail/bf_torek.c 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/bf_torek.c 2001/05/29 01:31:14 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1999-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -11,9 +11,13 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: bf_torek.c,v 8.19 1999/10/11 23:37:26 ca Exp $"; +static char id[] = "@(#)$Sendmail: bf_torek.c,v 8.19.18.6 2001/05/08 06:52:19 gshapiro Exp $"; #endif /* ! lint */ +#if SFIO + ERROR README: Can not use bf_torek.c with SFIO. +#endif /* SFIO */ + #include #include #include @@ -22,9 +26,12 @@ #include #include #include -#ifndef BF_STANDALONE +#ifdef BF_STANDALONE +# define sm_free free +# define xalloc malloc +#else /* BF_STANDALONE */ # include "sendmail.h" -#endif /* ! BF_STANDALONE */ +#endif /* BF_STANDALONE */ #include "bf_torek.h" #include "bf.h" @@ -86,7 +93,7 @@ } /* Allocate memory */ - bfp = (struct bf *)malloc(sizeof(struct bf)); + bfp = (struct bf *)xalloc(sizeof(struct bf)); if (bfp == NULL) { errno = ENOMEM; @@ -96,10 +103,10 @@ /* A zero bsize is valid, just don't allocate memory */ if (bsize > 0) { - bfp->bf_buf = (char *)malloc(bsize); + bfp->bf_buf = (char *)xalloc(bsize); if (bfp->bf_buf == NULL) { - free(bfp); + sm_free(bfp); errno = ENOMEM; return NULL; } @@ -115,12 +122,12 @@ bfp->bf_bufsize = bsize; bfp->bf_buffilled = 0; l = strlen(filename) + 1; - bfp->bf_filename = (char *)malloc(l); + bfp->bf_filename = (char *)xalloc(l); if (bfp->bf_filename == NULL) { - free(bfp); if (bfp->bf_buf != NULL) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); + sm_free(bfp); errno = ENOMEM; return NULL; } @@ -138,10 +145,10 @@ { /* Just in case free() sets errno */ save_errno = errno; - free(bfp); - free(bfp->bf_filename); + sm_free(bfp->bf_filename); if (bfp->bf_buf != NULL) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); + sm_free(bfp); errno = save_errno; return NULL; } @@ -281,7 +288,7 @@ { /* Don't need buffer anymore; free it */ bfp->bf_bufsize = 0; - free(bfp->bf_buf); + sm_free(bfp->bf_buf); } return 0; } @@ -313,7 +320,6 @@ /* check to see if there is an error on the stream */ err = ferror(fp); - (void) fflush(fp); /* @@ -377,6 +383,51 @@ } /* +** BFFSYNC -- fsync the fd associated with the FILE * +** +** Parameters: +** fp -- FILE * to fsync +** +** Returns: +** 0 on success, -1 on error +** +** Sets errno: +** EINVAL if FILE * not bfcommitted yet. +** any value of errno specified by fsync() +*/ + +int +bffsync(fp) + FILE *fp; +{ + int fd; + struct bf *bfp; + + if (bftest(fp)) + { + /* Get bf structure */ + bfp = (struct bf *)fp->_cookie; + + if (bfp->bf_ondisk && bfp->bf_committed) + fd = bfp->bf_disk_fd; + else + fd = -1; + } + else + fd = fileno(fp); + + if (tTd(58, 10)) + dprintf("bffsync: fd = %d\n", fd); + + if (fd < 0) + { + errno = EINVAL; + return -1; + } + return fsync(fd); +} + + /* ** BFCLOSE -- close a buffered file ** ** Parameters: @@ -481,10 +532,10 @@ /* Need to free the buffer */ if (bfp->bf_bufsize > 0) - free(bfp->bf_buf); + sm_free(bfp->bf_buf); /* Finally, free the structure */ - free(bfp); + sm_free(bfp); return 0; } Index: gnu/usr.sbin/sendmail/sendmail/clock.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/clock.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/sendmail/clock.c 2000/04/02 19:05:43 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/clock.c 2001/05/29 01:31:14 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,7 +12,7 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: clock.c,v 8.52 1999/10/13 22:16:42 ca Exp $"; +static char id[] = "@(#)$Sendmail: clock.c,v 8.52.18.14 2001/05/17 18:12:28 gshapiro Exp $"; #endif /* ! lint */ #include @@ -21,8 +21,10 @@ # define sigmask(s) (1 << ((s) - 1)) #endif /* ! sigmask */ +static SIGFUNC_DECL tick __P((int)); static void endsleep __P((void)); + /* ** SETEVENT -- set an event to happen at a specific time. ** @@ -41,7 +43,8 @@ ** none. */ -EVENT *FreeEventList; /* list of free events */ +static EVENT *volatile EventQueue; /* head of event queue */ +static EVENT *volatile FreeEventList; /* list of free events */ EVENT * setevent(intvl, func, arg) @@ -49,10 +52,7 @@ void (*func)(); int arg; { - register EVENT **evp; register EVENT *ev; - auto time_t now; - int wasblocked; if (intvl <= 0) { @@ -60,34 +60,89 @@ return NULL; } + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + FreeEventList = (EVENT *) xalloc(sizeof *FreeEventList); + FreeEventList->ev_link = NULL; + } + LEAVE_CRITICAL(); + + ev = sigsafe_setevent(intvl, func, arg); + + if (tTd(5, 5)) + dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", + (long) intvl, (long) (curtime() + intvl), + (u_long) func, arg, + ev == NULL ? 0 : (u_long) ev); + + return ev; +} + +/* +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +EVENT * +sigsafe_setevent(intvl, func, arg) + time_t intvl; + void (*func)(); + int arg; +{ + register EVENT **evp; + register EVENT *ev; + auto time_t now; + int wasblocked; + + if (intvl <= 0) + return NULL; + wasblocked = blocksignal(SIGALRM); now = curtime(); /* search event queue for correct position */ - for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link) + for (evp = (EVENT **) (&EventQueue); + (ev = *evp) != NULL; + evp = &ev->ev_link) { if (ev->ev_time >= now + intvl) break; } - /* insert new event */ - ev = FreeEventList; - if (ev == NULL) - ev = (EVENT *) xalloc(sizeof *ev); + ENTER_CRITICAL(); + if (FreeEventList == NULL) + { + /* + ** This shouldn't happen. If called from setevent(), + ** we have just malloced a FreeEventList entry. If + ** called from a signal handler, it should have been + ** from an existing event which tick() just added to the + ** FreeEventList. + */ + + LEAVE_CRITICAL(); + return NULL; + } else + { + ev = FreeEventList; FreeEventList = ev->ev_link; + } + LEAVE_CRITICAL(); + + /* insert new event */ ev->ev_time = now + intvl; ev->ev_func = func; ev->ev_arg = arg; ev->ev_pid = getpid(); + ENTER_CRITICAL(); ev->ev_link = *evp; *evp = ev; + LEAVE_CRITICAL(); - if (tTd(5, 5)) - dprintf("setevent: intvl=%ld, for=%ld, func=%lx, arg=%d, ev=%lx\n", - (long) intvl, (long)(now + intvl), (u_long) func, - arg, (u_long) ev); - (void) setsignal(SIGALRM, tick); intvl = EventQueue->ev_time - now; (void) alarm((unsigned) intvl < 1 ? 1 : intvl); @@ -122,7 +177,9 @@ /* find the parent event */ wasblocked = blocksignal(SIGALRM); - for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link) + for (evp = (EVENT **) (&EventQueue); + *evp != NULL; + evp = &(*evp)->ev_link) { if (*evp == ev) break; @@ -131,9 +188,11 @@ /* now remove it */ if (*evp != NULL) { + ENTER_CRITICAL(); *evp = ev->ev_link; ev->ev_link = FreeEventList; FreeEventList = ev; + LEAVE_CRITICAL(); } /* restore clocks and pick up anything spare */ @@ -177,9 +236,11 @@ for (ev = EventQueue; ev->ev_link != NULL; ev = ev->ev_link) continue; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = EventQueue; EventQueue = NULL; + LEAVE_CRITICAL(); /* restore clocks and pick up anything spare */ if (wasblocked == 0) @@ -200,6 +261,10 @@ ** ** Side Effects: ** calls the next function in EventQueue. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ /* ARGSUSED */ @@ -209,27 +274,67 @@ { register time_t now; register EVENT *ev; - int mypid = getpid(); + pid_t mypid; int save_errno = errno; (void) alarm(0); - now = curtime(); + FIX_SYSV_SIGNAL(sig, tick); + + errno = save_errno; + CHECK_CRITICAL(sig); + + mypid = getpid(); + while (PendingSignal != 0) + { + int sigbit; + int sig; + + if (bitset(PEND_SIGHUP, PendingSignal)) + { + sigbit = PEND_SIGHUP; + sig = SIGHUP; + } + else if (bitset(PEND_SIGINT, PendingSignal)) + { + sigbit = PEND_SIGINT; + sig = SIGINT; + } + else if (bitset(PEND_SIGTERM, PendingSignal)) + { + sigbit = PEND_SIGTERM; + sig = SIGTERM; + } + else if (bitset(PEND_SIGUSR1, PendingSignal)) + { + sigbit = PEND_SIGUSR1; + sig = SIGUSR1; + } + else + { + /* If we get here, we are in trouble */ + abort(); + } + PendingSignal &= ~sigbit; + kill(mypid, sig); + } + + now = curtime(); if (tTd(5, 4)) dprintf("tick: now=%ld\n", (long) now); - /* reset signal in case System V semantics */ - (void) setsignal(SIGALRM, tick); while ((ev = EventQueue) != NULL && (ev->ev_time <= now || ev->ev_pid != mypid)) { void (*f)(); int arg; - int pid; + pid_t pid; /* process the event on the top of the queue */ + ENTER_CRITICAL(); ev = EventQueue; EventQueue = EventQueue->ev_link; + LEAVE_CRITICAL(); if (tTd(5, 6)) dprintf("tick: ev=%lx, func=%lx, arg=%d, pid=%d\n", (u_long) ev, (u_long) ev->ev_func, @@ -239,9 +344,11 @@ f = ev->ev_func; arg = ev->ev_arg; pid = ev->ev_pid; + ENTER_CRITICAL(); ev->ev_link = FreeEventList; FreeEventList = ev; - if (pid != getpid()) + LEAVE_CRITICAL(); + if (pid != mypid) continue; if (EventQueue != NULL) { @@ -263,6 +370,72 @@ return SIGFUNC_RETURN; } /* +** PEND_SIGNAL -- Add a signal to the pending signal list +** +** Parameters: +** sig -- signal to add +** +** Returns: +** none. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +void +pend_signal(sig) + int sig; +{ + int sigbit; + int save_errno = errno; + + /* + ** Don't want to interrupt something critical, hence delay + ** the alarm for one second. Hopefully, by then we + ** will be out of the critical section. If not, then + ** we will just delay again. The events to be run will + ** still all be run, maybe just a little bit late. + */ + + switch (sig) + { + case SIGHUP: + sigbit = PEND_SIGHUP; + break; + + case SIGINT: + sigbit = PEND_SIGINT; + break; + + case SIGTERM: + sigbit = PEND_SIGTERM; + break; + + case SIGUSR1: + sigbit = PEND_SIGUSR1; + break; + + case SIGALRM: + /* don't have to pend these */ + sigbit = 0; + break; + + default: + /* If we get here, we are in trouble */ + abort(); + + /* NOTREACHED */ + break; + } + + if (sigbit != 0) + PendingSignal |= sigbit; + (void) setsignal(SIGALRM, tick); + (void) alarm(1); + errno = save_errno; +} + /* ** SLEEP -- a version of sleep that works with this stuff ** ** Because sleep uses the alarm facility, I must reimplement @@ -279,8 +452,9 @@ ** be run during that interval. */ -static bool SleepDone; +static bool volatile SleepDone; + #ifndef SLEEP_T # define SLEEP_T unsigned int #endif /* ! SLEEP_T */ @@ -306,5 +480,11 @@ static void endsleep() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + SleepDone = TRUE; } Index: gnu/usr.sbin/sendmail/sendmail/collect.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/collect.c,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/sendmail/collect.c 2000/04/07 19:20:38 1.2 +++ gnu/usr.sbin/sendmail/sendmail/collect.c 2001/05/29 01:31:14 1.5 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,11 +12,12 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: collect.c,v 8.136 2000/03/15 21:47:27 ca Exp $"; +static char id[] = "@(#)$Sendmail: collect.c,v 8.136.4.21 2001/05/17 18:10:14 gshapiro Exp $"; #endif /* ! lint */ #include + static void collecttimeout __P((time_t)); static void dferror __P((FILE *volatile, char *, ENVELOPE *)); static void eatfrom __P((char *volatile, ENVELOPE *)); @@ -46,8 +47,8 @@ */ static jmp_buf CtxCollectTimeout; -static bool CollectProgress; -static EVENT *CollectTimeout; +static bool volatile CollectProgress; +static EVENT *volatile CollectTimeout = NULL; /* values for input state machine */ #define IS_NORM 0 /* middle of line */ @@ -62,41 +63,6 @@ #define MS_BODY 2 /* reading message body */ #define MS_DISCARD 3 /* discarding rest of message */ -#if _FFR_MILTER -# define MILTER_EOH() \ -{ \ - if (bitset(CHHDR_MILTER, chompflags) && \ - rstat == EX_OK && \ - !bitset(EF_DISCARD, e->e_flags)) \ - { \ - char state; \ - char *response; \ - \ - response = milter_eoh(e, &state); \ - chompflags &= ~CHHDR_MILTER; \ - switch (state) \ - { \ - case SMFIR_REPLYCODE: \ - usrerr(response); \ - break; \ - \ - case SMFIR_REJECT: \ - usrerr("554 5.7.1 Message rejected"); \ - break; \ - \ - case SMFIR_DISCARD: \ - e->e_flags |= EF_DISCARD; \ - break; \ - \ - case SMFIR_TEMPFAIL: \ - usrerr("451 4.7.1 Try again later"); \ - break; \ - } \ - } \ -} -# endif /* _FFR_MILTER */ - - void collect(fp, smtpmode, hdrp, e) FILE *fp; @@ -118,8 +84,6 @@ volatile int hdrslen = 0; volatile int numhdrs = 0; volatile int dfd; - volatile int afd; - volatile int chompflags = CHHDR_CHECK|CHHDR_USER; volatile int rstat = EX_OK; u_char *volatile pbp; u_char peekbuf[8]; @@ -137,7 +101,9 @@ if (!headeronly) { struct stat stbuf; + long sff = SFF_OPENASROOT; + (void) strlcpy(dfname, queuename(e, 'd'), sizeof dfname); #if _FFR_QUEUE_FILE_MODE { @@ -145,18 +111,21 @@ if (bitset(S_IWGRP, QueueFileMode)) oldumask = umask(002); - df = bfopen(dfname, QueueFileMode, DataFileBufferSize, - SFF_OPENASROOT); + df = bfopen(dfname, QueueFileMode, + DataFileBufferSize, sff); if (bitset(S_IWGRP, QueueFileMode)) (void) umask(oldumask); } #else /* _FFR_QUEUE_FILE_MODE */ - df = bfopen(dfname, FileMode, DataFileBufferSize, - SFF_OPENASROOT); + df = bfopen(dfname, FileMode, DataFileBufferSize, sff); #endif /* _FFR_QUEUE_FILE_MODE */ if (df == NULL) { - syserr("Cannot create %s", dfname); + HoldErrs = FALSE; + if (smtpmode) + syserr("421 4.3.5 Unable to create data file"); + else + syserr("Cannot create %s", dfname); e->e_flags |= EF_NO_BODY_RETN; finis(TRUE, ExitStat); /* NOTREACHED */ @@ -179,12 +148,7 @@ */ if (smtpmode) - { message("354 Enter mail, end with \".\" on a line by itself"); -#if _FFR_MILTER - chompflags |= CHHDR_MILTER; -# endif /* _FFR_MILTER */ - } if (tTd(30, 2)) dprintf("collect\n"); @@ -235,18 +199,25 @@ { errno = 0; c = getc(fp); - if (errno != EINTR) - break; - clearerr(fp); + + if (c == EOF && errno == EINTR) + { + /* Interrupted, retry */ + clearerr(fp); + continue; + } + break; } CollectProgress = TRUE; if (TrafficLogFile != NULL && !headeronly) { if (istate == IS_BOL) - (void) fprintf(TrafficLogFile, "%05d <<< ", - (int) getpid()); + (void) fprintf(TrafficLogFile, + "%05d <<< ", + (int) getpid()); if (c == EOF) - (void) fprintf(TrafficLogFile, "[EOF]\n"); + (void) fprintf(TrafficLogFile, + "[EOF]\n"); else (void) putc(c, TrafficLogFile); } @@ -326,15 +297,23 @@ bufferchar: if (!headeronly) - e->e_msgsize++; + { + /* no overflow? */ + if (e->e_msgsize >= 0) + { + e->e_msgsize++; + if (MaxMessageSize > 0 && + !bitset(EF_TOOBIG, e->e_flags) && + e->e_msgsize > MaxMessageSize) + e->e_flags |= EF_TOOBIG; + } + } switch (mstate) { case MS_BODY: /* just put the character out */ - if (MaxMessageSize <= 0 || - e->e_msgsize <= MaxMessageSize) + if (!bitset(EF_TOOBIG, e->e_flags)) (void) putc(c, df); - /* FALLTHROUGH */ case MS_DISCARD: @@ -359,7 +338,7 @@ memmove(buf, obuf, bp - obuf); bp = &buf[bp - obuf]; if (obuf != bufbuf) - free(obuf); + sm_free(obuf); } if (c >= 0200 && c <= 0237) { @@ -372,8 +351,9 @@ else if (c != '\0') { *bp++ = c; + hdrslen++; if (MaxHeadersLength > 0 && - ++hdrslen > MaxHeadersLength) + hdrslen > MaxHeadersLength) { sm_syslog(LOG_NOTICE, e->e_id, "headers too large (%d max) from %s during message collect", @@ -424,7 +404,7 @@ clearerr(fp); errno = 0; c = getc(fp); - } while (errno == EINTR); + } while (c == EOF && errno == EINTR); if (c != EOF) (void) ungetc(c, fp); if (c == ' ' || c == '\t') @@ -438,7 +418,8 @@ bp++; *bp = '\0'; - if (bitset(H_EOH, chompheader(buf, (int *)&chompflags, + if (bitset(H_EOH, chompheader(buf, + CHHDR_CHECK | CHHDR_USER, hdrp, e))) { mstate = MS_BODY; @@ -461,19 +442,8 @@ dprintf("collect: rscheck(\"check_eoh\", \"%s $| %s\")\n", hnum, hsize); rstat = rscheck("check_eoh", hnum, hsize, e, FALSE, - TRUE, 4); - -#if _FFR_MILTER - /* - ** see if a header check already rejected - ** this message or if the check_eoh call - ** resulted in an error. Also, don't call - ** filters if we are discarding the message. - */ + TRUE, 4, NULL); - MILTER_EOH(); -# endif /* _FFR_MILTER */ - bp = buf; /* toss blank line */ @@ -486,8 +456,7 @@ } /* if not a blank separator, write it out */ - if (MaxMessageSize <= 0 || - e->e_msgsize <= MaxMessageSize) + if (!bitset(EF_TOOBIG, e->e_flags)) { while (*bp != '\0') (void) putc(*bp++, df); @@ -510,17 +479,9 @@ inputerr = TRUE; } -#if _FFR_MILTER - /* - ** If the message was completely empty (no headers, no body), - ** milter hasn't been sent the EOH so do it now. - */ - - MILTER_EOH(); -# endif /* _FFR_MILTER */ - /* reset global timer */ - clrevent(CollectTimeout); + if (CollectTimeout != NULL) + clrevent(CollectTimeout); if (headeronly) return; @@ -542,13 +503,6 @@ /* skip next few clauses */ /* EMPTY */ } - else if ((afd = fileno(df)) >= 0 && fsync(afd) < 0) - { - dferror(df, "fsync", e); - flush_errors(TRUE); - finis(TRUE, ExitStat); - /* NOTREACHED */ - } else if (bfcommit(df) < 0) { int save_errno = errno; @@ -563,7 +517,7 @@ st.st_size = -1; errno = EEXIST; syserr("collect: bfcommit(%s): already on disk, size = %ld", - dfile, st.st_size); + dfile, (long) st.st_size); dfd = fileno(df); if (dfd >= 0) dumpfd(dfd, TRUE, TRUE); @@ -573,6 +527,13 @@ flush_errors(TRUE); finis(save_errno != EEXIST, ExitStat); } + else if (bffsync(df) < 0) + { + dferror(df, "bffsync", e); + flush_errors(TRUE); + finis(TRUE, ExitStat); + /* NOTREACHED */ + } else if (bfclose(df) < 0) { dferror(df, "bfclose", e); @@ -686,11 +647,11 @@ break; case NRA_ADD_BCC: - addheader("Bcc", " ", &e->e_header); + addheader("Bcc", " ", 0, &e->e_header); break; case NRA_ADD_TO_UNDISCLOSED: - addheader("To", "undisclosed-recipients:;", &e->e_header); + addheader("To", "undisclosed-recipients:;", 0, &e->e_header); break; } @@ -703,13 +664,13 @@ if (tTd(30, 3)) dprintf("Adding %s: %s\n", hdr, q->q_paddr); - addheader(hdr, q->q_paddr, &e->e_header); + addheader(hdr, q->q_paddr, 0, &e->e_header); } } } /* check for message too large */ - if (MaxMessageSize > 0 && e->e_msgsize > MaxMessageSize) + if (bitset(EF_TOOBIG, e->e_flags)) { e->e_flags |= EF_NO_BODY_RETN|EF_CLRQUEUE; e->e_status = "5.2.3"; @@ -762,15 +723,37 @@ collecttimeout(timeout) time_t timeout; { - /* if no progress was made, die now */ - if (!CollectProgress) + int save_errno = errno; + + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + if (CollectProgress) + { + /* reset the timeout */ + CollectTimeout = sigsafe_setevent(timeout, collecttimeout, + timeout); + CollectProgress = FALSE; + } + else + { + /* event is done */ + CollectTimeout = NULL; + } + + /* if no progress was made or problem resetting event, die now */ + if (CollectTimeout == NULL) + { + errno = ETIMEDOUT; longjmp(CtxCollectTimeout, 1); + } - /* otherwise reset the timeout */ - CollectTimeout = setevent(timeout, collecttimeout, timeout); - CollectProgress = FALSE; + errno = save_errno; } -/* + /* ** DFERROR -- signal error on writing the data file. ** ** Parameters: @@ -900,6 +883,11 @@ p++; while (*p == ' ') p++; + if (strlen(p) < 17) + { + /* no room for the date */ + return; + } if (!(isascii(*p) && isupper(*p)) || p[3] != ' ' || p[13] != ':' || p[16] != ':') continue; @@ -912,8 +900,10 @@ continue; for (dt = MonthList; *dt != NULL; dt++) + { if (strncmp(*dt, &p[4], 3) == 0) break; + } if (*dt != NULL) break; } Index: gnu/usr.sbin/sendmail/sendmail/conf.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/conf.c,v retrieving revision 1.4 retrieving revision 1.7 diff -u -r1.4 -r1.7 --- gnu/usr.sbin/sendmail/sendmail/conf.c 2000/04/22 21:07:03 1.4 +++ gnu/usr.sbin/sendmail/sendmail/conf.c 2001/05/29 01:31:14 1.7 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,13 +12,15 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: conf.c,v 8.646 2000/03/21 19:31:53 ca Exp $"; +static char id[] = "@(#)$Sendmail: conf.c,v 8.646.2.2.2.86 2001/05/17 18:18:40 ca Exp $"; #endif /* ! lint */ #include #include -#include -#include + +# include +# include + #include #if NETINET || NETINET6 # include @@ -27,6 +29,7 @@ # include #endif /* HASULIMIT && defined(HPUX11) */ + static void setupmaps __P((void)); static void setupmailers __P((void)); static int get_num_procs_online __P((void)); @@ -190,9 +193,16 @@ { "truststickybit", DBS_TRUSTSTICKYBIT }, { "dontwarnforwardfileinunsafedirpath", DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, + { "insufficiententropy", DBS_INSUFFICIENTENTROPY }, #if _FFR_UNSAFE_SASL { "groupreadablesaslfile", DBS_GROUPREADABLESASLFILE }, #endif /* _FFR_UNSAFE_SASL */ +#if _FFR_UNSAFE_WRITABLE_INCLUDE + { "groupwritableforwardfile", DBS_GROUPWRITABLEFORWARDFILE }, + { "groupwritableincludefile", DBS_GROUPWRITABLEINCLUDEFILE }, + { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE }, + { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE }, +#endif /* _FFR_UNSAFE_WRITABLE_INCLUDE */ { NULL, 0 } }; @@ -370,7 +380,7 @@ { char buf[100]; - (void) strlcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", + (void) strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", sizeof buf); makemailer(buf); @@ -815,7 +825,7 @@ char *maptype[MAXMAPSTACK]; short mapreturn[MAXMAPACTIONS]; { - int svcno; + int svcno = 0; int save_errno = errno; #ifdef _USE_SUN_NSSWITCH_ @@ -835,7 +845,7 @@ else lk = nsw_conf->lookups; svcno = 0; - while (lk != NULL) + while (lk != NULL && svcno < MAXMAPSTACK) { maptype[svcno] = lk->service_name; if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN) @@ -872,7 +882,7 @@ errno = save_errno; return -1; } - for (svcno = 0; svcno < SVC_PATHSIZE; svcno++) + for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++) { switch (svcinfo->svcpath[svc][svcno]) { @@ -966,7 +976,7 @@ st = stab(buf, ST_SERVICE, ST_ENTER); if (st->s_service[0] != NULL) - free((void *) st->s_service[0]); + sm_free((void *) st->s_service[0]); p = newstr(p); for (svcno = 0; svcno < MAXMAPSTACK; ) { @@ -1216,6 +1226,10 @@ ** SETSIGNAL -- set a signal handler ** ** This is essentially old BSD "signal(3)". +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ sigfunc_t @@ -1223,56 +1237,123 @@ int sig; sigfunc_t handler; { +# if defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) + struct sigaction n, o; +# endif /* defined(SA_RESTART) || (!defined(SYS5SIGNALS) && !defined(BSD4_3)) */ + /* ** First, try for modern signal calls ** and restartable syscalls */ - -#ifdef SA_RESTART - struct sigaction n, o; +# ifdef SA_RESTART memset(&n, '\0', sizeof n); -# if USE_SA_SIGACTION +# if USE_SA_SIGACTION n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler; n.sa_flags = SA_RESTART|SA_SIGINFO; -# else /* USE_SA_SIGACTION */ +# else /* USE_SA_SIGACTION */ n.sa_handler = handler; n.sa_flags = SA_RESTART; -# endif /* USE_SA_SIGACTION */ +# endif /* USE_SA_SIGACTION */ if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; -#else /* SA_RESTART */ +# else /* SA_RESTART */ /* ** Else check for SYS5SIGNALS or ** BSD4_3 signals */ -# if defined(SYS5SIGNALS) || defined(BSD4_3) -# ifdef BSD4_3 +# if defined(SYS5SIGNALS) || defined(BSD4_3) +# ifdef BSD4_3 return signal(sig, handler); -# else /* BSD4_3 */ +# else /* BSD4_3 */ return sigset(sig, handler); -# endif /* BSD4_3 */ -# else /* defined(SYS5SIGNALS) || defined(BSD4_3) */ +# endif /* BSD4_3 */ +# else /* defined(SYS5SIGNALS) || defined(BSD4_3) */ /* ** Finally, if nothing else is available, ** go for a default */ - struct sigaction n, o; - memset(&n, '\0', sizeof n); n.sa_handler = handler; if (sigaction(sig, &n, &o) < 0) return SIG_ERR; return o.sa_handler; -# endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */ -#endif /* SA_RESTART */ +# endif /* defined(SYS5SIGNALS) || defined(BSD4_3) */ +# endif /* SA_RESTART */ } /* +** ALLSIGNALS -- act on all signals +** +** Parameters: +** block -- whether to block or release all signals. +** +** Returns: +** none. +*/ + +void +allsignals(block) + bool block; +{ +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ + if (block) + { + int mask = 0; + + mask |= sigmask(SIGALRM); + mask |= sigmask(SIGCHLD); + mask |= sigmask(SIGHUP); + mask |= sigmask(SIGINT); + mask |= sigmask(SIGTERM); + mask |= sigmask(SIGUSR1); + + (void) sigblock(mask); + } + else + sigsetmask(0); +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V + if (block) + { + (void) sigset(SIGALRM, SIG_HOLD); + (void) sigset(SIGCHLD, SIG_HOLD); + (void) sigset(SIGHUP, SIG_HOLD); + (void) sigset(SIGINT, SIG_HOLD); + (void) sigset(SIGTERM, SIG_HOLD); + (void) sigset(SIGUSR1, SIG_HOLD); + } + else + { + (void) sigset(SIGALRM, SIG_DFL); + (void) sigset(SIGCHLD, SIG_DFL); + (void) sigset(SIGHUP, SIG_DFL); + (void) sigset(SIGINT, SIG_DFL); + (void) sigset(SIGTERM, SIG_DFL); + (void) sigset(SIGUSR1, SIG_DFL); + } +# else /* ALTOS_SYSTEM_V */ + sigset_t sset; + + (void) sigemptyset(&sset); + (void) sigaddset(&sset, SIGALRM); + (void) sigaddset(&sset, SIGCHLD); + (void) sigaddset(&sset, SIGHUP); + (void) sigaddset(&sset, SIGINT); + (void) sigaddset(&sset, SIGTERM); + (void) sigaddset(&sset, SIGUSR1); + (void) sigprocmask(block ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL); +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ +} + /* ** BLOCKSIGNAL -- hold a signal to prevent delivery ** ** Parameters: @@ -1288,13 +1369,13 @@ blocksignal(sig) int sig; { -#ifdef BSD4_3 -# ifndef sigmask -# define sigmask(s) (1 << ((s) - 1)) -# endif /* ! sigmask */ +# ifdef BSD4_3 +# ifndef sigmask +# define sigmask(s) (1 << ((s) - 1)) +# endif /* ! sigmask */ return (sigblock(sigmask(sig)) & sigmask(sig)) != 0; -#else /* BSD4_3 */ -# ifdef ALTOS_SYSTEM_V +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); @@ -1302,7 +1383,7 @@ return -1; else return handler == SIG_HOLD; -# else /* ALTOS_SYSTEM_V */ +# else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; (void) sigemptyset(&sset); @@ -1311,8 +1392,8 @@ return -1; else return sigismember(&oset, sig); -# endif /* ALTOS_SYSTEM_V */ -#endif /* BSD4_3 */ +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ } /* ** RELEASESIGNAL -- release a held signal @@ -1330,10 +1411,10 @@ releasesignal(sig) int sig; { -#ifdef BSD4_3 +# ifdef BSD4_3 return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0; -#else /* BSD4_3 */ -# ifdef ALTOS_SYSTEM_V +# else /* BSD4_3 */ +# ifdef ALTOS_SYSTEM_V sigfunc_t handler; handler = sigset(sig, SIG_HOLD); @@ -1341,7 +1422,7 @@ return -1; else return handler == SIG_HOLD; -# else /* ALTOS_SYSTEM_V */ +# else /* ALTOS_SYSTEM_V */ sigset_t sset, oset; (void) sigemptyset(&sset); @@ -1350,8 +1431,8 @@ return -1; else return sigismember(&oset, sig); -# endif /* ALTOS_SYSTEM_V */ -#endif /* BSD4_3 */ +# endif /* ALTOS_SYSTEM_V */ +# endif /* BSD4_3 */ } /* ** HOLDSIGS -- arrange to hold all signals @@ -1445,6 +1526,7 @@ # endif /* _SCO_unix_ */ #endif /* SECUREWARE || defined(_SCO_unix_) */ + #ifdef VENDOR_DEFAULT VendorCode = VENDOR_DEFAULT; #else /* VENDOR_DEFAULT */ @@ -1501,6 +1583,7 @@ #define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */ #define LA_DEVSHORT 13 /* read short from a device */ #define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */ +#define LA_PSET 15 /* Solaris per-processor-set load average */ /* do guesses based on general OS type */ #ifndef LA_TYPE @@ -2058,6 +2141,28 @@ #endif /* LA_TYPE == LA_ALPHAOSF */ +#if LA_TYPE == LA_PSET + +static int +getla() +{ + double avenrun[3]; + + if (pset_getloadavg(PS_MYID, avenrun, + sizeof(avenrun) / sizeof(avenrun[0])) < 0) + { + if (tTd(3, 1)) + dprintf("getla: pset_getloadavg failed: %s", + errstring(errno)); + return -1; + } + if (tTd(3, 1)) + dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); + return ((int) (avenrun[0] + 0.5)); +} + +#endif /* LA_TYPE == LA_PSET */ + #if LA_TYPE == LA_ZERO static int @@ -2140,7 +2245,7 @@ { char labuf[8]; - snprintf(labuf, sizeof labuf, "%d", CurrentLA); + snprintf(labuf, sizeof labuf, "%d", la); define(macid("{load_avg}", NULL), newstr(labuf), e); } return la; @@ -2217,34 +2322,12 @@ ENVELOPE *e; int d; { - time_t now; - static time_t lastconn[MAXDAEMONS]; - static int conncnt[MAXDAEMONS]; - #ifdef XLA if (!xla_smtp_ok()) return TRUE; #endif /* XLA */ - - now = curtime(); - if (now != lastconn[d]) - { - lastconn[d] = now; - conncnt[d] = 0; - } - else if (conncnt[d]++ > ConnRateThrottle && ConnRateThrottle > 0) - { - /* sleep to flatten out connection load */ - sm_setproctitle(TRUE, e, "deferring connections on daemon %s: %d per second", - name, ConnRateThrottle); - if (LogLevel >= 9) - sm_syslog(LOG_INFO, NOQID, - "deferring connections on daemon %s: %d per second", - name, ConnRateThrottle); - (void) sleep(1); - } - CurrentLA = getla(); + CurrentLA = sm_getla(NULL); if (RefuseLA > 0 && CurrentLA >= RefuseLA) { sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: load average: %d", @@ -2301,6 +2384,7 @@ # define SPT_TYPE SPT_REUSEARGV #endif /* ! SPT_TYPE */ + #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN # if SPT_TYPE == SPT_PSTAT @@ -2428,7 +2512,7 @@ # if SPT_TYPE == SPT_SCO off_t seek_off; static int kmem = -1; - static int kmempid = -1; + static pid_t kmempid = -1; struct user u; # endif /* SPT_TYPE == SPT_SCO */ @@ -2460,7 +2544,7 @@ if (kmem < 0 || kmempid != getpid()) { if (kmem >= 0) - close(kmem); + (void) close(kmem); kmem = open(_PATH_KMEM, O_RDWR, 0); if (kmem < 0) return; @@ -2562,37 +2646,37 @@ waitfor(pid) pid_t pid; { -#ifdef WAITUNION +# ifdef WAITUNION union wait st; -#else /* WAITUNION */ +# else /* WAITUNION */ auto int st; -#endif /* WAITUNION */ +# endif /* WAITUNION */ pid_t i; -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) int savesig; -#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ do { errno = 0; -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) savesig = releasesignal(SIGCHLD); -#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ i = wait(&st); -#if defined(ISC_UNIX) || defined(_SCO_unix_) +# if defined(ISC_UNIX) || defined(_SCO_unix_) if (savesig > 0) blocksignal(SIGCHLD); -#endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ +# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */ if (i > 0) (void) proc_list_drop(i); } while ((i >= 0 || errno == EINTR) && i != pid); if (i < 0) return -1; -#ifdef WAITUNION +# ifdef WAITUNION return st.w_status; -#else /* WAITUNION */ +# else /* WAITUNION */ return st; -#endif /* WAITUNION */ +# endif /* WAITUNION */ } /* ** REAPCHILD -- pick up the body of my child, lest it become a zombie @@ -2606,6 +2690,10 @@ ** Side Effects: ** Picks up extant zombies. ** Control socket exits may restart/shutdown daemon. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. */ /* ARGSUSED0 */ @@ -2616,32 +2704,30 @@ int save_errno = errno; int st; pid_t pid; -#if HASWAITPID +# if HASWAITPID auto int status; int count; +# else /* HASWAITPID */ +# ifdef WNOHANG + union wait status; +# else /* WNOHANG */ + auto int status; +# endif /* WNOHANG */ +# endif /* HASWAITPID */ +# if HASWAITPID count = 0; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { st = status; if (count++ > 1000) - { - if (LogLevel > 0) - sm_syslog(LOG_ALERT, NOQID, - "reapchild: waitpid loop: pid=%d, status=%x", - pid, status); break; - } -#else /* HASWAITPID */ -# ifdef WNOHANG - union wait status; - +# else /* HASWAITPID */ +# ifdef WNOHANG while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) { st = status.w_status; -# else /* WNOHANG */ - auto int status; - +# else /* WNOHANG */ /* ** Catch one zombie -- we will be re-invoked (we hope) if there ** are more. Unreliable signals probably break this, but this @@ -2652,8 +2738,8 @@ if ((pid = wait(&status)) > 0) { st = status; -# endif /* WNOHANG */ -#endif /* HASWAITPID */ +# endif /* WNOHANG */ +# endif /* HASWAITPID */ /* Drop PID and check if it was a control socket child */ if (proc_list_drop(pid) == PROC_CONTROL && WIFEXITED(st)) @@ -2661,21 +2747,17 @@ /* if so, see if we need to restart or shutdown */ if (WEXITSTATUS(st) == EX_RESTART) { - /* emulate a SIGHUP restart */ - sighup(0); - /* NOTREACHED */ + RestartRequest = "control socket"; } else if (WEXITSTATUS(st) == EX_SHUTDOWN) { /* emulate a SIGTERM shutdown */ - intsig(0); + ShutdownRequest = "control socket"; /* NOTREACHED */ } } } -#ifdef SYS5SIGNALS - (void) setsignal(SIGCHLD, reapchild); -#endif /* SYS5SIGNALS */ + FIX_SYSV_SIGNAL(sig, reapchild); errno = save_errno; return SIGFUNC_RETURN; } @@ -2740,18 +2822,14 @@ */ if (first) { - newenv = (char **) malloc(sizeof(char *) * (envlen + 2)); - if (newenv == NULL) - return -1; - + newenv = (char **) xalloc(sizeof(char *) * (envlen + 2)); first = FALSE; (void) memcpy(newenv, environ, sizeof(char *) * envlen); } else { - newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2)); - if (newenv == NULL) - return -1; + newenv = (char **) xrealloc((char *)environ, + sizeof(char *) * (envlen + 2)); } /* actually add in the new entry */ @@ -2848,22 +2926,22 @@ int getdtsize() { -#ifdef RLIMIT_NOFILE +# ifdef RLIMIT_NOFILE struct rlimit rl; if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) return rl.rlim_cur; -#endif /* RLIMIT_NOFILE */ +# endif /* RLIMIT_NOFILE */ -#if HASGETDTABLESIZE +# if HASGETDTABLESIZE return getdtablesize(); -#else /* HASGETDTABLESIZE */ -# ifdef _SC_OPEN_MAX +# else /* HASGETDTABLESIZE */ +# ifdef _SC_OPEN_MAX return sysconf(_SC_OPEN_MAX); -# else /* _SC_OPEN_MAX */ +# else /* _SC_OPEN_MAX */ return NOFILE; -# endif /* _SC_OPEN_MAX */ -#endif /* HASGETDTABLESIZE */ +# endif /* _SC_OPEN_MAX */ +# endif /* HASGETDTABLESIZE */ } /* ** UNAME -- get the UUCP name of this system. @@ -2908,7 +2986,7 @@ return 0; } -# if 0 +# if 0 /* ** Popen is known to have security holes. */ @@ -2924,7 +3002,7 @@ if (name->nodename[0] != '\0') return 0; } -# endif /* 0 */ +# endif /* 0 */ return -1; } @@ -2971,21 +3049,21 @@ pid_t setsid __P ((void)) { -# ifdef TIOCNOTTY +# ifdef TIOCNOTTY int fd; fd = open("/dev/tty", O_RDWR, 0); if (fd >= 0) { - (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0); + (void) ioctl(fd, TIOCNOTTY, (char *) 0); (void) close(fd); } -# endif /* TIOCNOTTY */ -# ifdef SYS5SETPGRP +# endif /* TIOCNOTTY */ +# ifdef SYS5SETPGRP return setpgrp(); -# else /* SYS5SETPGRP */ +# else /* SYS5SETPGRP */ return setpgid(0, getpid()); -# endif /* SYS5SETPGRP */ +# endif /* SYS5SETPGRP */ } #endif /* !HASSETSID */ @@ -3240,7 +3318,7 @@ char *user; char *shell; { -#if HASGETUSERSHELL +# if HASGETUSERSHELL register char *p; extern char *getusershell(); @@ -3254,10 +3332,10 @@ break; endusershell(); return p != NULL; -#else /* HASGETUSERSHELL */ -# if USEGETCONFATTR +# else /* HASGETUSERSHELL */ +# if USEGETCONFATTR auto char *v; -# endif /* USEGETCONFATTR */ +# endif /* USEGETCONFATTR */ register FILE *shellf; char buf[MAXLINE]; @@ -3265,7 +3343,7 @@ ConfigLevel <= 1) return TRUE; -# if USEGETCONFATTR +# if USEGETCONFATTR /* ** Naturally IBM has a "better" idea..... ** @@ -3289,7 +3367,7 @@ } return FALSE; } -# endif /* USEGETCONFATTR */ +# endif /* USEGETCONFATTR */ shellf = fopen(_PATH_SHELLS, "r"); if (shellf == NULL) @@ -3331,7 +3409,7 @@ } (void) fclose(shellf); return FALSE; -#endif /* HASGETUSERSHELL */ +# endif /* HASGETUSERSHELL */ } /* ** FREEDISKSPACE -- see how much free space is on the queue filesystem @@ -3344,7 +3422,7 @@ ** block size is stored. ** ** Returns: -** The number of bytes free on the queue filesystem. +** The number of blocks free on the queue filesystem. ** -1 if the statfs call fails. ** ** Side effects: @@ -3385,48 +3463,48 @@ char *dir; long *bsize; { -#if SFS_TYPE != SFS_NONE -# if SFS_TYPE == SFS_USTAT +# if SFS_TYPE != SFS_NONE +# if SFS_TYPE == SFS_USTAT struct ustat fs; struct stat statbuf; -# define FSBLOCKSIZE DEV_BSIZE -# define SFS_BAVAIL f_tfree -# else /* SFS_TYPE == SFS_USTAT */ -# if defined(ultrix) +# define FSBLOCKSIZE DEV_BSIZE +# define SFS_BAVAIL f_tfree +# else /* SFS_TYPE == SFS_USTAT */ +# if defined(ultrix) struct fs_data fs; -# define SFS_BAVAIL fd_bfreen -# define FSBLOCKSIZE 1024L -# else /* defined(ultrix) */ -# if SFS_TYPE == SFS_STATVFS +# define SFS_BAVAIL fd_bfreen +# define FSBLOCKSIZE 1024L +# else /* defined(ultrix) */ +# if SFS_TYPE == SFS_STATVFS struct statvfs fs; -# define FSBLOCKSIZE fs.f_frsize -# else /* SFS_TYPE == SFS_STATVFS */ +# define FSBLOCKSIZE fs.f_frsize +# else /* SFS_TYPE == SFS_STATVFS */ struct statfs fs; -# define FSBLOCKSIZE fs.f_bsize -# endif /* SFS_TYPE == SFS_STATVFS */ -# endif /* defined(ultrix) */ -# endif /* SFS_TYPE == SFS_USTAT */ -# ifndef SFS_BAVAIL -# define SFS_BAVAIL f_bavail -# endif /* ! SFS_BAVAIL */ +# define FSBLOCKSIZE fs.f_bsize +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_USTAT */ +# ifndef SFS_BAVAIL +# define SFS_BAVAIL f_bavail +# endif /* ! SFS_BAVAIL */ -# if SFS_TYPE == SFS_USTAT +# if SFS_TYPE == SFS_USTAT if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) -# else /* SFS_TYPE == SFS_USTAT */ -# if SFS_TYPE == SFS_4ARGS +# else /* SFS_TYPE == SFS_USTAT */ +# if SFS_TYPE == SFS_4ARGS if (statfs(dir, &fs, sizeof fs, 0) == 0) -# else /* SFS_TYPE == SFS_4ARGS */ -# if SFS_TYPE == SFS_STATVFS +# else /* SFS_TYPE == SFS_4ARGS */ +# if SFS_TYPE == SFS_STATVFS if (statvfs(dir, &fs) == 0) -# else /* SFS_TYPE == SFS_STATVFS */ -# if defined(ultrix) +# else /* SFS_TYPE == SFS_STATVFS */ +# if defined(ultrix) if (statfs(dir, &fs) > 0) -# else /* defined(ultrix) */ +# else /* defined(ultrix) */ if (statfs(dir, &fs) == 0) -# endif /* defined(ultrix) */ -# endif /* SFS_TYPE == SFS_STATVFS */ -# endif /* SFS_TYPE == SFS_4ARGS */ -# endif /* SFS_TYPE == SFS_USTAT */ +# endif /* defined(ultrix) */ +# endif /* SFS_TYPE == SFS_STATVFS */ +# endif /* SFS_TYPE == SFS_4ARGS */ +# endif /* SFS_TYPE == SFS_USTAT */ { if (bsize != NULL) *bsize = FSBLOCKSIZE; @@ -3437,7 +3515,7 @@ else return (long) fs.SFS_BAVAIL; } -#endif /* SFS_TYPE != SFS_NONE */ +# endif /* SFS_TYPE != SFS_NONE */ return -1; } /* @@ -3461,7 +3539,8 @@ long msize; bool log; { - long bfree, bsize; + long bfree; + long bsize; if (MinBlocksFree <= 0 && msize <= 0) { @@ -3470,7 +3549,8 @@ return TRUE; } - if ((bfree = freediskspace(QueueDir, &bsize)) >= 0) + bfree = freediskspace(QueueDir, &bsize); + if (bfree >= 0) { if (tTd(4, 80)) dprintf("enoughdiskspace: bavail=%ld, need=%ld\n", @@ -3614,6 +3694,7 @@ ** type -- type of the lock. Bits can be: ** LOCK_EX -- exclusive lock. ** LOCK_NB -- non-blocking. +** LOCK_UN -- unlock. ** ** Returns: ** TRUE if the lock was acquired. @@ -3629,7 +3710,7 @@ { int i; int save_errno; -#if !HASFLOCK +# if !HASFLOCK int action; struct flock lfd; @@ -3686,15 +3767,15 @@ (save_errno != EACCES && save_errno != EAGAIN)) { int omode = -1; -# ifdef F_GETFL +# ifdef F_GETFL (void) fcntl(fd, F_GETFL, &omode); errno = save_errno; -# endif /* F_GETFL */ +# endif /* F_GETFL */ syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); dumpfd(fd, TRUE, TRUE); } -#else /* !HASFLOCK */ +# else /* !HASFLOCK */ if (ext == NULL) ext = ""; @@ -3717,15 +3798,15 @@ if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) { int omode = -1; -# ifdef F_GETFL +# ifdef F_GETFL (void) fcntl(fd, F_GETFL, &omode); errno = save_errno; -# endif /* F_GETFL */ +# endif /* F_GETFL */ syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)", filename, ext, fd, type, omode, geteuid()); dumpfd(fd, TRUE, TRUE); } -#endif /* !HASFLOCK */ +# endif /* !HASFLOCK */ if (tTd(55, 60)) dprintf("FAIL\n"); errno = save_errno; @@ -3793,7 +3874,7 @@ int fd; bool safedir; { -#if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ +# if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H)) int rval; @@ -3809,14 +3890,14 @@ errno = 0; rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); -# if SAFENFSPATHCONF +# if SAFENFSPATHCONF return errno == 0 && rval IS_SAFE_CHOWN; -# else /* SAFENFSPATHCONF */ +# else /* SAFENFSPATHCONF */ return safedir && errno == 0 && rval IS_SAFE_CHOWN; -# endif /* SAFENFSPATHCONF */ -#else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ +# endif /* SAFENFSPATHCONF */ +# else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); -#endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ +# endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ */ } /* ** RESETLIMITS -- reset system controlled resource limits @@ -4121,31 +4202,17 @@ dprintf("validate_connection(%s, %s)\n", hostname, anynet_ntoa(sap)); - if (rscheck("check_relay", hostname, anynet_ntoa(sap), e, TRUE, TRUE, 4) - != EX_OK) + if (rscheck("check_relay", hostname, anynet_ntoa(sap), + e, TRUE, TRUE, 4, NULL) != EX_OK) { static char reject[BUFSIZ*2]; extern char MsgBuf[]; if (tTd(48, 4)) dprintf(" ... validate_connection: BAD (rscheck)\n"); - - if (strlen(MsgBuf) > 5) - { - if (ISSMTPCODE(MsgBuf)) - { - int off; - if ((off = isenhsc(MsgBuf + 4, ' ')) > 0) - off += 5; - else - off = 4; - (void) strlcpy(reject, &MsgBuf[off], - sizeof reject); - } - else - (void) strlcpy(reject, MsgBuf, sizeof reject); - } + if (strlen(MsgBuf) >= 3) + (void) strlcpy(reject, MsgBuf, sizeof reject); else (void) strlcpy(reject, "Access denied", sizeof reject); @@ -4325,8 +4392,14 @@ ** Support IPv6 as well as IPv4. */ -#if NETINET6 && NEEDSGETIPNODE && __RES < 19990909 +#if NETINET6 && NEEDSGETIPNODE +# ifndef AI_DEFAULT +# define AI_DEFAULT 0 /* dummy */ +# endif /* ! AI_DEFAULT */ +# ifndef AI_ADDRCONFIG +# define AI_ADDRCONFIG 0 /* dummy */ +# endif /* ! AI_ADDRCONFIG */ # ifndef AI_V4MAPPED # define AI_V4MAPPED 0 /* dummy */ # endif /* ! AI_V4MAPPED */ @@ -4350,7 +4423,7 @@ resv6 = bitset(RES_USE_INET6, _res.options); _res.options |= RES_USE_INET6; } - h_errno = 0; + SM_SET_H_ERRNO(0); h = gethostbyname(name); *err = h_errno; if (family == AF_INET6 && !resv6) @@ -4367,18 +4440,33 @@ { struct hostent *h; - h_errno = 0; + SM_SET_H_ERRNO(0); h = gethostbyaddr(addr, len, family); *err = h_errno; return h; } -#endif /* NEEDSGETIPNODE && NETINET6 && __RES < 19990909 */ +# if _FFR_FREEHOSTENT +void +freehostent(h) + struct hostent *h; +{ + /* + ** Stub routine -- if they don't have getipnodeby*(), + ** they probably don't have the free routine either. + */ + + return; +} +# endif /* _FFR_FREEHOSTENT */ +#endif /* NEEDSGETIPNODE && NETINET6 */ + struct hostent * sm_gethostbyname(name, family) char *name; int family; { + int save_errno; struct hostent *h = NULL; #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) # if SOLARIS == 20300 || SOLARIS == 203 @@ -4389,19 +4477,21 @@ if (tTd(61, 10)) dprintf("_switch_gethostbyname_r(%s)... ", name); h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); + save_errno = errno; # else /* SOLARIS == 20300 || SOLARIS == 203 */ extern struct hostent *__switch_gethostbyname(); if (tTd(61, 10)) dprintf("__switch_gethostbyname(%s)... ", name); h = __switch_gethostbyname(name); + save_errno = errno; # endif /* SOLARIS == 20300 || SOLARIS == 203 */ #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ int nmaps; # if NETINET6 + int flags = AI_DEFAULT|AI_ALL; int err; # endif /* NETINET6 */ - int save_errno; char *maptype[MAXMAPSTACK]; short mapreturn[MAXMAPACTIONS]; char hbuf[MAXNAME]; @@ -4410,8 +4500,11 @@ dprintf("sm_gethostbyname(%s, %d)... ", name, family); # if NETINET6 - h = getipnodebyname(name, family, AI_V4MAPPED|AI_ALL, &err); - h_errno = err; +# if ADDRCONFIG_IS_BROKEN + flags &= ~AI_ADDRCONFIG; +# endif /* ADDRCONFIG_IS_BROKEN */ + h = getipnodebyname(name, family, flags, &err); + SM_SET_H_ERRNO(err); # else /* NETINET6 */ h = gethostbyname(name); # endif /* NETINET6 */ @@ -4424,9 +4517,12 @@ nmaps = switch_map_find("hosts", maptype, mapreturn); while (--nmaps >= 0) + { if (strcmp(maptype[nmaps], "nis") == 0 || strcmp(maptype[nmaps], "files") == 0) break; + } + if (nmaps >= 0) { /* try short name */ @@ -4436,7 +4532,7 @@ return NULL; } (void) strlcpy(hbuf, name, sizeof hbuf); - shorten_hostname(hbuf); + (void) shorten_hostname(hbuf); /* if it hasn't been shortened, there's no point */ if (strcmp(hbuf, name) != 0) @@ -4449,7 +4545,7 @@ h = getipnodebyname(hbuf, family, AI_V4MAPPED|AI_ALL, &err); - h_errno = err; + SM_SET_H_ERRNO(err); save_errno = errno; # else /* NETINET6 */ h = gethostbyname(hbuf); @@ -4512,31 +4608,47 @@ int type; { struct hostent *hp; + +#if NETINET6 + if (type == AF_INET6 && + IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr)) + { + /* Avoid reverse lookup for IPv6 unspecified address */ + SM_SET_H_ERRNO(HOST_NOT_FOUND); + return NULL; + } +#endif /* NETINET6 */ + #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) # if SOLARIS == 20300 || SOLARIS == 203 - static struct hostent he; - static char buf[1000]; - extern struct hostent *_switch_gethostbyaddr_r(); + { + static struct hostent he; + static char buf[1000]; + extern struct hostent *_switch_gethostbyaddr_r(); - hp = _switch_gethostbyaddr_r(addr, len, type, &he, buf, sizeof(buf), &h_errno); + hp = _switch_gethostbyaddr_r(addr, len, type, &he, + buf, sizeof(buf), &h_errno); + } # else /* SOLARIS == 20300 || SOLARIS == 203 */ - extern struct hostent *__switch_gethostbyaddr(); + { + extern struct hostent *__switch_gethostbyaddr(); - hp = __switch_gethostbyaddr(addr, len, type); + hp = __switch_gethostbyaddr(addr, len, type); + } # endif /* SOLARIS == 20300 || SOLARIS == 203 */ #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ # if NETINET6 - int err; -# endif /* NETINET6 */ + { + int err; -# if NETINET6 - hp = getipnodebyaddr(addr, len, type, &err); - h_errno = err; + hp = getipnodebyaddr(addr, len, type, &err); + SM_SET_H_ERRNO(err); + } # else /* NETINET6 */ hp = gethostbyaddr(addr, len, type); # endif /* NETINET6 */ - return hp; #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ + return hp; } /* ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid @@ -4657,14 +4769,16 @@ #if NETINET case AF_INET: hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, - sizeof(sa->sin.sin_addr), sa->sa.sa_family); + sizeof(sa->sin.sin_addr), + sa->sa.sa_family); break; #endif /* NETINET */ #if NETINET6 case AF_INET6: hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, - sizeof(sa->sin6.sin6_addr), sa->sa.sa_family); + sizeof(sa->sin6.sin6_addr), + sa->sa.sa_family); break; #endif /* NETINET6 */ @@ -4737,6 +4851,9 @@ *ha); } } +#if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); +#endif /* _FFR_FREEHOSTENT && NETINET6 */ return 0; } /* @@ -4783,7 +4900,7 @@ return; /* get the list of known IP address from the kernel */ -# ifdef SIOCGLIFNUM +# ifdef SIOCGLIFNUM lifn.lifn_family = AF_UNSPEC; lifn.lifn_flags = 0; if (ioctl(s, SIOCGLIFNUM, (char *)&lifn) < 0) @@ -4800,12 +4917,12 @@ dprintf("system has %d interfaces\n", numifs); } if (numifs < 0) -# endif /* SIOCGLIFNUM */ +# endif /* SIOCGLIFNUM */ numifs = MAXINTERFACES; if (numifs <= 0) { - close(s); + (void) close(s); return; } lifc.lifc_len = numifs * sizeof (struct lifreq); @@ -4816,7 +4933,8 @@ { if (tTd(0, 4)) dprintf("SIOCGLIFCONF failed: %s\n", errstring(errno)); - close(s); + (void) close(s); + sm_free(lifc.lifc_buf); return; } @@ -4832,9 +4950,9 @@ char *addr; struct in6_addr ia6; struct in_addr ia; -# ifdef SIOCGLIFFLAGS +# ifdef SIOCGLIFFLAGS struct lifreq ifrf; -# endif /* SIOCGLIFFLAGS */ +# endif /* SIOCGLIFFLAGS */ char ip_addr[256]; char buf6[INET6_ADDRSTRLEN]; int af = ifr->lifr_addr.ss_family; @@ -4849,7 +4967,10 @@ s = socket(af, SOCK_DGRAM, 0); if (s == -1) + { + sm_free(lifc.lifc_buf); return; + } /* ** If we don't have a complete ifr structure, @@ -4859,11 +4980,11 @@ if ((lifc.lifc_len - i) < sizeof *ifr) break; -# ifdef BSD4_4_SOCKADDR +# ifdef BSD4_4_SOCKADDR if (sa->sa.sa_len > sizeof ifr->lifr_addr) i += sizeof ifr->lifr_name + sa->sa.sa_len; else -# endif /* BSD4_4_SOCKADDR */ +# endif /* BSD4_4_SOCKADDR */ i += sizeof *ifr; if (tTd(0, 20)) @@ -4872,7 +4993,7 @@ if (af != AF_INET && af != AF_INET6) continue; -# ifdef SIOCGLIFFLAGS +# ifdef SIOCGLIFFLAGS memset(&ifrf, '\0', sizeof(struct lifreq)); (void) strlcpy(ifrf.lifr_name, ifr->lifr_name, sizeof(ifrf.lifr_name)); @@ -4889,7 +5010,7 @@ if (!bitset(IFF_UP, ifrf.lifr_flags)) continue; -# endif /* SIOCGLIFFLAGS */ +# endif /* SIOCGLIFFLAGS */ ip_addr[0] = '\0'; @@ -4897,8 +5018,22 @@ switch (af) { case AF_INET6: +# ifdef __KAME__ + /* convert into proper scoped address */ + if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || + IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && + sa->sin6.sin6_scope_id == 0) + { + struct in6_addr *ia6p; + + ia6p = &sa->sin6.sin6_addr; + sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | + ((unsigned int)ia6p->s6_addr[2] << 8)); + ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; + } +# endif /* __KAME__ */ ia6 = sa->sin6.sin6_addr; - if (ia6.s6_addr == in6addr_any.s6_addr) + if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) { addr = anynet_ntop(&ia6, buf6, sizeof buf6); message("WARNING: interface %s is UP with %s address", @@ -4912,7 +5047,7 @@ if (addr != NULL) (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", - sizeof ip_addr - 3, addr); + (int) sizeof ip_addr - 3, addr); break; case AF_INET: @@ -4927,7 +5062,7 @@ /* save IP address in text from */ (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", - sizeof ip_addr - 3, inet_ntoa(ia)); + (int) sizeof ip_addr - 3, inet_ntoa(ia)); break; } @@ -4941,15 +5076,15 @@ dprintf("\ta.k.a.: %s\n", ip_addr); } -# ifdef SIOCGLIFFLAGS +# ifdef SIOCGLIFFLAGS /* skip "loopback" interface "lo" */ if (bitset(IFF_LOOPBACK, ifrf.lifr_flags)) continue; -# endif /* SIOCGLIFFLAGS */ +# endif /* SIOCGLIFFLAGS */ (void) add_hostnames(sa); } - free(lifc.lifc_buf); - close(s); + sm_free(lifc.lifc_buf); + (void) close(s); #else /* NETINET6 && defined(SIOCGLIFCONF) */ # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN int s; @@ -4988,6 +5123,7 @@ if (tTd(0, 4)) dprintf("SIOCGIFCONF failed: %s\n", errstring(errno)); (void) close(s); + sm_free(ifc.ifc_buf); return; } @@ -4998,13 +5134,21 @@ for (i = 0; i < ifc.ifc_len; ) { + int af; struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; +# if NETINET6 + char *addr; + struct in6_addr ia6; +# endif /* NETINET6 */ struct in_addr ia; -# ifdef SIOCGIFFLAGS +# ifdef SIOCGIFFLAGS struct ifreq ifrf; -# endif /* SIOCGIFFLAGS */ +# endif /* SIOCGIFFLAGS */ char ip_addr[256]; +# if NETINET6 + char buf6[INET6_ADDRSTRLEN]; +# endif /* NETINET6 */ /* ** If we don't have a complete ifr structure, @@ -5014,20 +5158,25 @@ if ((ifc.ifc_len - i) < sizeof *ifr) break; -# ifdef BSD4_4_SOCKADDR +# ifdef BSD4_4_SOCKADDR if (sa->sa.sa_len > sizeof ifr->ifr_addr) i += sizeof ifr->ifr_name + sa->sa.sa_len; else -# endif /* BSD4_4_SOCKADDR */ +# endif /* BSD4_4_SOCKADDR */ i += sizeof *ifr; if (tTd(0, 20)) dprintf("%s\n", anynet_ntoa(sa)); - if (ifr->ifr_addr.sa_family != AF_INET) + af = ifr->ifr_addr.sa_family; + if (af != AF_INET +# if NETINET6 + && af != AF_INET6 +# endif /* NETINET6 */ + ) continue; -# ifdef SIOCGIFFLAGS +# ifdef SIOCGIFFLAGS memset(&ifrf, '\0', sizeof(struct ifreq)); (void) strlcpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name)); @@ -5035,25 +5184,74 @@ if (tTd(0, 41)) dprintf("\tflags: %lx\n", (unsigned long) ifrf.ifr_flags); -# define IFRFREF ifrf -# else /* SIOCGIFFLAGS */ -# define IFRFREF (*ifr) -# endif /* SIOCGIFFLAGS */ +# define IFRFREF ifrf +# else /* SIOCGIFFLAGS */ +# define IFRFREF (*ifr) +# endif /* SIOCGIFFLAGS */ + if (!bitset(IFF_UP, IFRFREF.ifr_flags)) continue; + ip_addr[0] = '\0'; + /* extract IP address from the list*/ - ia = sa->sin.sin_addr; - if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE) + switch (af) { - message("WARNING: interface %s is UP with %s address", - ifr->ifr_name, inet_ntoa(ia)); - continue; + case AF_INET: + ia = sa->sin.sin_addr; + if (ia.s_addr == INADDR_ANY || + ia.s_addr == INADDR_NONE) + { + message("WARNING: interface %s is UP with %s address", + ifr->ifr_name, inet_ntoa(ia)); + continue; + } + + /* save IP address in text from */ + (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", + (int) sizeof ip_addr - 3, + inet_ntoa(ia)); + break; + +# if NETINET6 + case AF_INET6: +# ifdef __KAME__ + /* convert into proper scoped address */ + if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || + IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && + sa->sin6.sin6_scope_id == 0) + { + struct in6_addr *ia6p; + + ia6p = &sa->sin6.sin6_addr; + sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | + ((unsigned int)ia6p->s6_addr[2] << 8)); + ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; + } +# endif /* __KAME__ */ + ia6 = sa->sin6.sin6_addr; + if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) + { + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + message("WARNING: interface %s is UP with %s address", + ifr->ifr_name, + addr == NULL ? "(NULL)" : addr); + continue; + } + + /* save IP address in text from */ + addr = anynet_ntop(&ia6, buf6, sizeof buf6); + if (addr != NULL) + (void) snprintf(ip_addr, sizeof ip_addr, + "[%.*s]", + (int) sizeof ip_addr - 3, addr); + break; + +# endif /* NETINET6 */ } - /* save IP address in text from */ - (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]", - (int) sizeof ip_addr - 3, inet_ntoa(ia)); + if (ip_addr[0] == '\0') + continue; if (!wordinclass(ip_addr, 'w')) { @@ -5068,7 +5266,7 @@ (void) add_hostnames(sa); } - free(ifc.ifc_buf); + sm_free(ifc.ifc_buf); (void) close(s); # undef IFRFREF # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ @@ -5130,9 +5328,13 @@ # ifdef _SC_NPROCESSORS_ONLN nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); # else /* _SC_NPROCESSORS_ONLN */ -# ifdef MPC_GETNUMSPUS - nproc = mpctl(MPC_GETNUMSPUS, 0, 0); -# endif /* MPC_GETNUMSPUS */ +# ifdef __hpux +# include + struct pst_dynamic psd; + + if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) + nproc = psd.psd_proc_cnt; +# endif /* __hpux */ # endif /* _SC_NPROCESSORS_ONLN */ #endif /* USESYSCTL */ @@ -5198,6 +5400,7 @@ static char *buf = NULL; static size_t bufsize; char *begin, *end; + int save_errno; int seq = 1; int idlen; char buf0[MAXLINE]; @@ -5206,7 +5409,7 @@ extern char *DoprEnd; VA_LOCAL_DECL - SyslogErrno = errno; + save_errno = SyslogErrno = errno; if (id == NULL) id = "NOQUEUE"; else if (strcmp(id, NOQID) == 0) @@ -5237,7 +5440,7 @@ /* String too small, redo with correct size */ bufsize += SnprfOverflow + 1; if (buf != buf0) - free(buf); + sm_free(buf); buf = xalloc(bufsize * sizeof (char)); } if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE) @@ -5256,6 +5459,7 @@ #endif /* LOG */ if (buf == buf0) buf = NULL; + errno = save_errno; return; } @@ -5310,6 +5514,7 @@ #endif /* LOG */ if (buf == buf0) buf = NULL; + errno = save_errno; } /* ** HARD_SYSLOG -- call syslog repeatedly until it works @@ -5392,6 +5597,9 @@ char *CompileOptions[] = { +#if EGD + "EGD", +#endif /* EGD */ #ifdef HESIOD "HESIOD", #endif /* HESIOD */ @@ -5467,12 +5675,18 @@ #if SCANF "SCANF", #endif /* SCANF */ +#if SFIO + "SFIO", +#endif /* SFIO */ #if SMTP "SMTP", #endif /* SMTP */ #if SMTPDEBUG "SMTPDEBUG", #endif /* SMTPDEBUG */ +#if STARTTLS + "STARTTLS", +#endif /* STARTTLS */ #ifdef SUID_ROOT_FILES_OK "SUID_ROOT_FILES_OK", #endif /* SUID_ROOT_FILES_OK */ @@ -5555,6 +5769,9 @@ #if HASSRANDOMDEV "HASSRANDOMDEV", #endif /* HASSRANDOMDEV */ +#if HASURANDOMDEV + "HASURANDOMDEV", +#endif /* HASURANDOMDEV */ #if HASSTRERROR "HASSTRERROR", #endif /* HASSTRERROR */ @@ -5603,6 +5820,12 @@ #if SIOCGIFNUM_IS_BROKEN "SIOCGIFNUM_IS_BROKEN", #endif /* SIOCGIFNUM_IS_BROKEN */ +#if SNPRINTF_IS_BROKEN + "SNPRINTF_IS_BROKEN", +#endif /* SNPRINTF_IS_BROKEN */ +#if SO_REUSEADDR_IS_BROKEN + "SO_REUSEADDR_IS_BROKEN", +#endif /* SO_REUSEADDR_IS_BROKEN */ #if SYS5SETPGRP "SYS5SETPGRP", #endif /* SYS5SETPGRP */ @@ -5620,3 +5843,4 @@ #endif /* USESETEUID */ NULL }; + Index: gnu/usr.sbin/sendmail/sendmail/conf.h =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/conf.h,v retrieving revision 1.6 retrieving revision 1.9 diff -u -r1.6 -r1.9 --- gnu/usr.sbin/sendmail/sendmail/conf.h 2000/08/20 18:59:13 1.6 +++ gnu/usr.sbin/sendmail/sendmail/conf.h 2001/05/29 01:31:14 1.9 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -10,7 +10,7 @@ * the sendmail distribution. * * - * $Sendmail: conf.h,v 8.496 2000/04/06 02:15:29 gshapiro Exp $ + * $Sendmail: conf.h,v 8.496.4.43 2001/05/20 22:29:59 gshapiro Exp $ */ /* @@ -27,20 +27,23 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */ #endif /* __GNUC__ */ -#include -#include -#include -#ifndef __QNX__ +# include +# include +# if SFIO && defined(SF_APPEND) +# undef SF_APPEND /* Both sfio/stdio.h and sys/stat.h define it */ +# endif /* SFIO && defined(SF_APPEND) */ +# include +# ifndef __QNX__ /* in QNX this grabs bogus LOCK_* manifests */ -# include -#endif /* ! __QNX__ */ -#include -#include -#include -#include -#include -#include -#include +# include +# endif /* ! __QNX__ */ +# include +# include +# include +# include +# include +# include +# include /* make sure TOBUFSIZ isn't larger than system limit for size of exec() args */ #ifdef ARG_MAX @@ -81,12 +84,13 @@ #define MAXMIMEARGS 20 /* max args in Content-Type: */ #define MAXMIMENESTING 20 /* max MIME multipart nesting */ #define QUEUESEGSIZE 1000 /* increment for queue size */ -#define MAXQFNAME 20 /* max qf file name length */ +#define MAXQFNAME 21 /* max qf file name length */ #define MACBUFSIZE 4096 /* max expanded macro buffer size */ #define TOBUFSIZE SM_ARG_MAX /* max buffer to hold address list */ #define MAXSHORTSTR 203 /* max short string length */ #define MAXMACNAMELEN 25 /* max macro name length */ #define MAXMACROID 0377 /* max macro id number */ + /* Must match (BITMAPBITS - 1) */ #ifndef MAXHDRSLEN # define MAXHDRSLEN (32 * 1024) /* max size of message headers */ #endif /* ! MAXHDRSLEN */ @@ -100,12 +104,18 @@ #define MAXLINKPATHLEN (MAXPATHLEN * MAXSYMLINKS) /* max link-expanded file */ #define DATA_PROGRESS_TIMEOUT 300 /* how ofter to check DATA progress */ #define ENHSCLEN 10 /* max len of enhanced status code */ +#if _FFR_DYNAMIC_TOBUF +# define DEFAULT_MAX_RCPT 100 /* max number of RCPTs per envelope */ +#endif /* _FFR_DYNAMIC_TOBUF */ #if SASL # ifndef AUTH_MECHANISMS -# define AUTH_MECHANISMS "GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# if STARTTLS && _FFR_EXT_MECH +# define AUTH_MECHANISMS "EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# else /* STARTTLS && _FFR_EXT_MECH */ +# define AUTH_MECHANISMS "GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5" +# endif /* STARTTLS && _FFR_EXT_MECH */ # endif /* ! AUTH_MECHANISMS */ -#else /* SASL */ #endif /* SASL */ #ifdef LDAPMAP @@ -227,6 +237,7 @@ # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps */ # endif /* ! HASGETUSERSHELL */ # ifdef HPUX11 +# define HASFCHOWN 1 /* has fchown(2) */ # define HASSNPRINTF 1 /* has snprintf(3) */ # ifndef BROKEN_RES_SEARCH # define BROKEN_RES_SEARCH 1 /* res_search(unknown) returns h_errno=0 */ @@ -477,6 +488,9 @@ # endif /* ! __svr4__ */ # define GIDSET_T gid_t # define USE_SA_SIGACTION 1 /* use sa_sigaction field */ +# if _FFR_MILTER +# define BROKEN_PTHREAD_SLEEP 1 /* sleep after pthread_create() fails */ +# endif /* _FFR_MILTER */ # ifndef _PATH_UNIX # define _PATH_UNIX "/dev/ksyms" # endif /* ! _PATH_UNIX */ @@ -504,6 +518,9 @@ # ifndef LA_TYPE # define LA_TYPE LA_KSTAT /* use kstat(3k) -- may work in < 2.5 */ # endif /* ! LA_TYPE */ +# ifndef RANDOMSHIFT /* random() doesn't work well (sometimes) */ +# define RANDOMSHIFT 8 +# endif /* RANDOMSHIFT */ # endif /* SOLARIS < 207 || (SOLARIS > 10000 && SOLARIS < 20700) */ # else /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ # ifndef HASRANDOM @@ -512,19 +529,31 @@ # endif /* SOLARIS >= 20500 || (SOLARIS < 10000 && SOLARIS >= 205) */ # if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) # define HASSNPRINTF 1 /* has snprintf starting in 2.6 */ +# else /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ +# if _FFR_MILTER +# define SM_INT32 int /* 32bit integer */ +# endif /* _FFR_MILTER */ # endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */ # if SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) # ifndef LA_TYPE # include -# define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ +# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) +# include +# define LA_TYPE LA_PSET /* pset_getloadavg(3c) appears in 2.9 */ +# else +# define LA_TYPE LA_SUBR /* getloadavg(3c) appears in 2.7 */ +# endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # endif /* ! LA_TYPE */ # define HASGETUSERSHELL 1 /* getusershell(3c) bug fixed in 2.7 */ # endif /* SOLARIS >= 20700 || (SOLARIS < 10000 && SOLARIS >= 207) */ # if SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) -# undef NETINET6 -# define NETINET6 1 /* IPv6 added in 2.8 */ # define HASSTRL 1 /* str*(3) added in 2.8 */ +# undef _PATH_SENDMAILPID /* tmpfs /var/run added in 2.8 */ +# define _PATH_SENDMAILPID "/var/run/sendmail.pid" # endif /* SOLARIS >= 20800 || (SOLARIS < 10000 && SOLARIS >= 208) */ +# if SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) +# define HASURANDOMDEV 1 /* /dev/[u]random added in S9 */ +# endif /* SOLARIS >= 20900 || (SOLARIS < 10000 && SOLARIS >= 209) */ # ifndef HASGETUSERSHELL # define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */ # endif /* ! HASGETUSERSHELL */ @@ -772,7 +801,7 @@ ** Also used for Apple Darwin support. */ -#if defined(__APPLE__) && !defined(NeXT) +#if defined(DARWIN) # define HASFCHMOD 1 /* has fchmod(2) syscall */ # define HASFLOCK 1 /* has flock(2) syscall */ # define HASUNAME 1 /* has uname(2) syscall */ @@ -800,7 +829,7 @@ # define SPT_TYPE SPT_PSSTRINGS # define SPT_PADCHAR '\0' /* pad process title with nulls */ # define ERRLIST_PREDEFINED /* don't declare sys_errlist */ -#endif /* __APPLE__ && ! NeXT */ +#endif /* DARWIN */ /* @@ -931,6 +960,7 @@ # define SAFENFSPATHCONF 1 /* pathconf(2) pessimizes on NFS filesystems */ # define GIDSET_T gid_t # define QUAD_T unsigned long long +# define SFIO_STDIO_COMPAT 1 /* can use RES_DEBUG */ # ifndef LA_TYPE # define LA_TYPE LA_SUBR # endif /* ! LA_TYPE */ @@ -939,10 +969,14 @@ # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # endif /* defined(__NetBSD__) && (NetBSD > 199307 || NetBSD0_9 > 1) */ +# if defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ +# endif /* defined(__NetBSD__) && ((__NetBSD_Version__ > 102070000) || (NetBSD1_2 > 8) || defined(NetBSD1_4) || defined(NetBSD1_3)) */ # if defined(__FreeBSD__) # define HASSETLOGIN 1 /* has setlogin(2) */ # if __FreeBSD_version >= 227001 # define HASSRANDOMDEV 1 /* has srandomdev(3) */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # endif /* __FreeBSD_version >= 227001 */ # undef SPT_TYPE # if __FreeBSD__ >= 2 @@ -971,12 +1005,18 @@ # undef SPT_TYPE # define SPT_TYPE SPT_BUILTIN /* setproctitle is in libc */ # define HASSETLOGIN 1 /* has setlogin(2) */ -# define HASSRANDOMDEV 1 /* has srandomdev(3) */ -# define HASSETUSERCONTEXT 1 /* has setusercontext(3) */ +# define HASSETREUID 0 /* OpenBSD has broken setreuid(2) emulation */ +# define HASURANDOMDEV 1 /* has /dev/urandom(4) */ # if OpenBSD < 199912 # define HASSTRL 0 /* strlcat(3) is broken in 2.5 and earlier */ # else /* OpenBSD < 199912 */ # define HASSTRL 1 /* has strlc{py,at}(3) functions */ +# if OpenBSD >= 200006 +# define HASSRANDOMDEV 1 /* has srandomdev(3) */ +# endif +# if OpenBSD >= 200012 +# define HASSETUSERCONTEXT 1 /* BSDI-style login classes */ +# endif # endif /* OpenBSD < 199912 */ # endif /* defined(__OpenBSD__) */ #endif /* defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) */ @@ -1365,6 +1405,10 @@ */ #ifdef __linux__ +# include +# if !defined(KERNEL_VERSION) /* not defined in 2.0.x kernel series */ +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +# endif /* KERNEL_VERSION */ # define BSD 1 /* include BSD defines */ # define USESETEUID 0 /* Have it due to POSIX, but doesn't work */ # define NEEDGETOPT 1 /* need a replacement for getopt(3) */ @@ -1384,7 +1428,6 @@ # endif /* ! HAS_IN_H */ # define USE_SIGLONGJMP 1 /* sigsetjmp needed for signal handling */ # ifndef HASFLOCK -# include # if LINUX_VERSION_CODE < 66399 # define HASFLOCK 0 /* flock(2) is broken after 0.99.13 */ # else /* LINUX_VERSION_CODE < 66399 */ @@ -1396,6 +1439,11 @@ # endif /* ! LA_TYPE */ # define SFS_TYPE SFS_VFS /* use statfs() impl */ # define SPT_PADCHAR '\0' /* pad process title with nulls */ +# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,0)) +# ifndef HASURANDOMDEV +# define HASURANDOMDEV 1 /* 2.0 (at least) has linux/drivers/char/random.c */ +# endif /* ! HASURANDOMDEV */ +# endif /* LINUX_VERSION_CODE */ # ifndef TZ_TYPE # define TZ_TYPE TZ_NONE /* no standard for Linux */ # endif /* ! TZ_TYPE */ @@ -1406,6 +1454,14 @@ # undef atol /* wounded in */ # if NETINET6 /* + ** Linux doesn't have a good way to tell userland what interfaces are + ** IPv6-capable. Therefore, the BIND resolver can not determine if there + ** are IPv6 interfaces to honor AI_ADDRCONFIG. Unfortunately, it assumes + ** that none are present. (Excuse the macro name ADDRCONFIG_IS_BROKEN.) + */ +# define ADDRCONFIG_IS_BROKEN 1 + + /* ** Indirectly included from glibc's . IPv6 support is native ** in 2.1 and later, but the APIs appear before the functions. */ @@ -1416,10 +1472,10 @@ # else /* (GLIBC_VERSION >= 0x201) */ # include /* IPv6 support */ # endif /* (GLIBC_VERSION >= 0x201) */ -# if (GLIBC_VERSION == 0x201 && !defined(NEEDSGETIPNODE)) +# if (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) /* Have APIs in , but no support in glibc */ # define NEEDSGETIPNODE 1 -# endif /* (GLIBC_VERSION == 0x201 && ! NEEDSGETIPNODE) */ +# endif /* (GLIBC_VERSION >= 0x201 && !defined(NEEDSGETIPNODE)) */ # undef GLIBC_VERSION # endif /* defined(__GLIBC__) && defined(__GLIBC_MINOR__) */ # endif /* NETINET6 */ @@ -1663,6 +1719,7 @@ # define __svr4__ # define SYS5SIGNALS 1 # define HASSETSID 1 +# define HASSNPRINTF 1 # define HASSETREUID 1 # define HASWAITPID 1 # define HASGETDTABLESIZE 1 @@ -1682,6 +1739,10 @@ # ifndef _PATH_SENDMAILPID # define _PATH_SENDMAILPID "/etc/sendmail.pid" # endif /* ! _PATH_SENDMAILPID */ +# undef offsetof /* avoid stddefs.h, sys/sysmacros.h conflict */ +#if !defined(SM_SET_H_ERRNO) && defined(_REENTRANT) +# define SM_SET_H_ERRNO(err) set_h_errno((err)) +#endif /* ! SM_SET_H_ERRNO && _REENTRANT */ #endif /* __svr5__ */ /* ###################################################################### */ @@ -1774,6 +1835,7 @@ # define __svr4__ # define HASFCHOWN 1 /* has fchown(2) call */ # define SIOCGIFNUM_IS_BROKEN 1 /* SIOCGIFNUM has non-std interface */ +# define SO_REUSEADDR_IS_BROKEN 1 /* doesn't work if accept() fails */ # define SYSLOG_BUFSIZE 1024 # define SPT_TYPE SPT_NONE # ifndef _XOPEN_SOURCE @@ -1853,7 +1915,7 @@ /* ** Amdahl UTS System V 2.1.5 (SVr3-based) ** -** From: Janet Jackson . +** From: Janet Jackson . */ #ifdef _UTS @@ -2174,6 +2236,7 @@ # define _PATH_SENDMAILPID "/var/run/sendmail.pid" #endif /* MOTO */ + /********************************************************************** ** End of Per-Operating System defines **********************************************************************/ @@ -2184,7 +2247,9 @@ /* general BSD defines */ #ifdef BSD # define HASGETDTABLESIZE 1 /* has getdtablesize(2) call */ -# define HASSETREUID 1 /* has setreuid(2) call */ +# ifndef HASSETREUID +# define HASSETREUID 1 /* has setreuid(2) call */ +# endif /* ! HASSETREUID */ # define HASINITGROUPS 1 /* has initgroups(3) call */ # ifndef IP_SRCROUTE # define IP_SRCROUTE 1 /* can check IP source routing */ @@ -2495,9 +2560,9 @@ # define NAMED_BIND 1 /* not one without the other */ #endif /* HESIOD && !defined(NAMED_BIND) */ -#if NAMED_BIND && !defined(__ksr__) && !defined(h_errno) +# if NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) extern int h_errno; -#endif /* NAMED_BIND && !defined(__ksr__) && !defined(h_errno) */ +# endif /* NAMED_BIND && !defined( __ksr__ ) && !defined( h_errno ) */ #ifdef LDAPMAP # include @@ -2675,6 +2740,10 @@ # define FORK fork /* function to call to fork mailer */ #endif /* ! FORK */ +/* setting h_errno */ +#ifndef SM_SET_H_ERRNO +# define SM_SET_H_ERRNO(err) h_errno = (err) +#endif /* SM_SET_H_ERRNO */ /* random routine -- set above using #ifdef _osname_ or in Makefile */ #if HASRANDOM @@ -2726,6 +2795,20 @@ #endif /* !defined(NGROUPS_MAX) && defined(NGROUPS) */ /* +** Some snprintf() implementations are rumored not to NUL terminate. +*/ +#if SNPRINTF_IS_BROKEN +# ifdef snprintf +# undef snprintf +# endif /* snprintf */ +# define snprintf sm_snprintf +# ifdef vsnprintf +# undef vsnprintf +# endif /* vsnprintf */ +# define vsnprintf sm_vsnprintf +#endif /* SNPRINTF_IS_BROKEN */ + +/* ** If we don't have a system syslog, simulate it. */ @@ -2740,5 +2823,17 @@ # define LOG_DEBUG 7 /* debug-level messages */ #endif /* !LOG */ +#if SFIO +# ifdef ERRLIST_PREDEFINED +# undef ERRLIST_PREDEFINED +# endif /* ERRLIST_PREDEFINED */ +# if !HASSNPRINTF +# define HASSNPRINTF 1 /* sfio includes snprintf() */ +# endif /* !HASSNPRINTF */ +#endif /* SFIO */ + +#ifndef SFIO_STDIO_COMPAT +# define SFIO_STDIO_COMPAT 0 +#endif /* ! SFIO_STDIO_COMPAT */ #endif /* CONF_H */ Index: gnu/usr.sbin/sendmail/sendmail/control.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/control.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -u -r1.1.1.1 -r1.4 --- gnu/usr.sbin/sendmail/sendmail/control.c 2000/04/02 19:05:44 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/control.c 2001/05/29 01:31:14 1.4 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 1999 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set @@ -9,11 +9,34 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: control.c,v 8.44 1999/11/29 22:03:49 ca Exp $"; +static char id[] = "@(#)$Sendmail: control.c,v 8.44.14.20 2001/05/03 17:24:03 gshapiro Exp $"; #endif /* ! lint */ #include +/* values for cmd_code */ +# define CMDERROR 0 /* bad command */ +# define CMDRESTART 1 /* restart daemon */ +# define CMDSHUTDOWN 2 /* end daemon */ +# define CMDHELP 3 /* help */ +# define CMDSTATUS 4 /* daemon status */ + +struct cmd +{ + char *cmd_name; /* command name */ + int cmd_code; /* internal code, see below */ +}; + +static struct cmd CmdTab[] = +{ + { "help", CMDHELP }, + { "restart", CMDRESTART }, + { "shutdown", CMDSHUTDOWN }, + { "status", CMDSTATUS }, + { NULL, CMDERROR } +}; + + int ControlSocket = -1; /* @@ -76,16 +99,26 @@ return -1; } - if (geteuid() == 0 && TrustedUid != 0) + if (geteuid() == 0) { - if (chown(ControlSocketName, TrustedUid, -1) < 0) + uid_t u = 0; + + if (RunAsUid != 0) + u = RunAsUid; + else if (TrustedUid != 0) + u = TrustedUid; + + if (u != 0 && + chown(ControlSocketName, u, -1) < 0) { save_errno = errno; sm_syslog(LOG_ALERT, NOQID, - "ownership change on %s failed: %s", - ControlSocketName, errstring(save_errno)); - message("050 ownership change on %s failed: %s", - ControlSocketName, errstring(save_errno)); + "ownership change on %s to uid %d failed: %s", + ControlSocketName, (int) u, + errstring(save_errno)); + message("050 ownership change on %s to uid %d failed: %s", + ControlSocketName, (int) u, + errstring(save_errno)); closecontrolsocket(TRUE); errno = save_errno; return -1; @@ -140,8 +173,8 @@ ControlSocket = -1; } - rval = safefile(ControlSocketName, RunAsUid, RunAsGid, RunAsUserName, - sff, S_IRUSR|S_IWUSR, NULL); + rval = safefile(ControlSocketName, RunAsUid, RunAsGid, + RunAsUserName, sff, S_IRUSR|S_IWUSR, NULL); /* if not safe, don't unlink */ if (rval != 0) @@ -197,34 +230,19 @@ ** none. */ -struct cmd -{ - char *cmd_name; /* command name */ - int cmd_code; /* internal code, see below */ -}; - -/* values for cmd_code */ -# define CMDERROR 0 /* bad command */ -# define CMDRESTART 1 /* restart daemon */ -# define CMDSHUTDOWN 2 /* end daemon */ -# define CMDHELP 3 /* help */ -# define CMDSTATUS 4 /* daemon status */ - -static struct cmd CmdTab[] = -{ - { "help", CMDHELP }, - { "restart", CMDRESTART }, - { "shutdown", CMDSHUTDOWN }, - { "status", CMDSTATUS }, - { NULL, CMDERROR } -}; - static jmp_buf CtxControlTimeout; static void controltimeout(timeout) time_t timeout; { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxControlTimeout, 1); } @@ -300,7 +318,7 @@ /* decode command */ for (c = CmdTab; c->cmd_name != NULL; c++) { - if (!strcasecmp(c->cmd_name, cmdbuf)) + if (strcasecmp(c->cmd_name, cmdbuf) == 0) break; } @@ -328,8 +346,23 @@ case CMDSTATUS: /* daemon status */ proc_list_probe(); - fprintf(s, "%d/%d/%ld/%d\r\n", CurChildren, MaxChildren, - freediskspace(QueueDir, NULL), sm_getla(NULL)); + { + long bsize; + long free; + + free = freediskspace(QueueDir, &bsize); + + /* + ** Prevent overflow and don't lose + ** precision (if bsize == 512) + */ + + free = (long)((double)free * ((double)bsize / 1024)); + + fprintf(s, "%d/%d/%ld/%d\r\n", + CurChildren, MaxChildren, + free, sm_getla(NULL)); + } proc_list_display(s); break; @@ -343,3 +376,4 @@ exit(exitstat); } #endif /* ! NOT_SENDMAIL */ + Index: gnu/usr.sbin/sendmail/sendmail/daemon.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/daemon.c,v retrieving revision 1.3 retrieving revision 1.7 diff -u -r1.3 -r1.7 --- gnu/usr.sbin/sendmail/sendmail/daemon.c 2000/06/18 00:04:21 1.3 +++ gnu/usr.sbin/sendmail/sendmail/daemon.c 2001/05/29 01:31:14 1.7 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -13,11 +13,12 @@ #include + #ifndef lint # ifdef DAEMON -static char id[] = "@(#)$Sendmail: daemon.c,v 8.401 2000/03/11 20:52:46 gshapiro Exp $ (with daemon mode)"; +static char id[] = "@(#)$Sendmail: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (with daemon mode)"; # else /* DAEMON */ -static char id[] = "@(#)$Sendmail: daemon.c,v 8.401 2000/03/11 20:52:46 gshapiro Exp $ (without daemon mode)"; +static char id[] = "@(#)$Sendmail: daemon.c,v 8.401.4.61 2001/05/27 22:14:40 gshapiro Exp $ (without daemon mode)"; # endif /* DAEMON */ #endif /* ! lint */ @@ -38,6 +39,10 @@ #if DAEMON +# if STARTTLS +# include +# endif /* STARTTLS */ + # include # if IP_SRCROUTE && NETINET @@ -82,6 +87,8 @@ static void connecttimeout __P((void)); static int opendaemonsocket __P((struct daemon *, bool)); static u_short setupdaemon __P((SOCKADDR *)); +static SIGFUNC_DECL sighup __P((int)); +static void restart_daemon __P((void)); /* ** DAEMON.C -- routines to use when running as a daemon. @@ -157,7 +164,6 @@ # endif /* NETUNIX */ extern ENVELOPE BlankEnvelope; -#define D(x,idx) x[idx] for (idx = 0; idx < ndaemons; idx++) { @@ -165,6 +171,7 @@ Daemons[idx].d_firsttime = TRUE; Daemons[idx].d_refuse_connections_until = (time_t) 0; } + /* ** Try to actually open the connection. */ @@ -172,9 +179,11 @@ if (tTd(15, 1)) { for (idx = 0; idx < ndaemons; idx++) + { dprintf("getrequests: daemon %s: port %d\n", Daemons[idx].d_name, ntohs(Daemons[idx].d_port)); + } } /* get a socket for the SMTP connection */ @@ -187,6 +196,10 @@ ControlSocketName, errstring(errno)); (void) setsignal(SIGCHLD, reapchild); + (void) setsignal(SIGHUP, sighup); + + /* workaround: can't seem to release the signal in the parent */ + (void) releasesignal(SIGHUP); /* write the pid to file */ log_sendmail_pid(e); @@ -219,67 +232,137 @@ bool control = FALSE; int save_errno; int pipefd[2]; + time_t timenow; +# if STARTTLS + long seed; +# endif /* STARTTLS */ + extern bool refuseconnections __P((char *, ENVELOPE *, int)); /* see if we are rejecting connections */ (void) blocksignal(SIGALRM); + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + + timenow = curtime(); + + /* + ** Use ConnRateThrottle only if the + ** last pass was for a connection + */ + + if (ConnRateThrottle > 0 && curdaemon >= 0) + { + static int conncnt = 0; + static time_t lastconn = 0; + + if (timenow != lastconn) + { + lastconn = timenow; + conncnt = 1; + } + else if (++conncnt > ConnRateThrottle) + { + /* sleep to flatten out connection load */ + sm_setproctitle(TRUE, e, + "deferring connections: %d per second", + ConnRateThrottle); + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "deferring connections: %d per second", + ConnRateThrottle); + (void) sleep(1); + } + } + for (idx = 0; idx < ndaemons; idx++) { - if (curtime() < Daemons[idx].d_refuse_connections_until) + if (timenow < Daemons[idx].d_refuse_connections_until) continue; + if (bitnset(D_DISABLE, Daemons[idx].d_flags)) + continue; if (refuseconnections(Daemons[idx].d_name, e, idx)) { if (Daemons[idx].d_socket >= 0) { - /* close socket so peer fails quickly */ - (void) close(Daemons[idx].d_socket); - Daemons[idx].d_socket = -1; + /* close socket so peer fails quickly */ + (void) close(Daemons[idx].d_socket); + Daemons[idx].d_socket = -1; } /* refuse connections for next 15 seconds */ - Daemons[idx].d_refuse_connections_until = curtime() + 15; + Daemons[idx].d_refuse_connections_until = timenow + 15; } else if (Daemons[idx].d_socket < 0 || Daemons[idx].d_firsttime) { - if (!Daemons[idx].d_firsttime && LogLevel >= 9) - sm_syslog(LOG_INFO, NOQID, - "accepting connections again for daemon %s", - Daemons[idx].d_name); + if (!Daemons[idx].d_firsttime && LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "accepting connections again for daemon %s", + Daemons[idx].d_name); - /* arrange to (re)open the socket if needed */ - (void) opendaemonsocket(&Daemons[idx], FALSE); - Daemons[idx].d_firsttime = FALSE; + /* arrange to (re)open the socket if needed */ + (void) opendaemonsocket(&Daemons[idx], FALSE); + Daemons[idx].d_firsttime = FALSE; } } - if (curtime() >= last_disk_space_check) + + /* May have been sleeping above, check again */ + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + + if (timenow >= last_disk_space_check) { + bool logged = FALSE; + if (!enoughdiskspace(MinBlocksFree + 1, FALSE)) { - if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + for (idx = 0; idx < ndaemons; idx++) { - /* log only if not logged before */ - if (LogLevel >= 9) - sm_syslog(LOG_INFO, NOQID, - "rejecting new messages: min free: %d", - MinBlocksFree); - sm_setproctitle(TRUE, e, - "rejecting new messages: min free: %d", - MinBlocksFree); - setbitn(D_ETRNONLY, Daemons[idx].d_flags); + if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + { + /* log only if not logged before */ + if (!logged) + { + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "rejecting new messages: min free: %ld", + MinBlocksFree); + logged = TRUE; + sm_setproctitle(TRUE, e, + "rejecting new messages: min free: %ld", + MinBlocksFree); + } + setbitn(D_ETRNONLY, Daemons[idx].d_flags); + } } } - else if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + else { - /* log only if not logged before */ - if (LogLevel >= 9) - sm_syslog(LOG_INFO, NOQID, - "accepting new messages (again)"); - /* title will be set below */ - clrbitn(D_ETRNONLY, Daemons[idx].d_flags); + for (idx = 0; idx < ndaemons; idx++) + { + if (bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + { + /* log only if not logged before */ + if (!logged) + { + if (LogLevel >= 9) + sm_syslog(LOG_INFO, NOQID, + "accepting new messages (again)"); + logged = TRUE; + } + + /* title will be set below */ + clrbitn(D_ETRNONLY, Daemons[idx].d_flags); + } + } } /* only check disk space once a minute */ - last_disk_space_check = curtime() + 60; + last_disk_space_check = timenow + 60; } # if XDEBUG @@ -320,10 +403,16 @@ for (;;) { + bool setproc = FALSE; int highest = -1; fd_set readfds; struct timeval timeout; + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + FD_ZERO(&readfds); for (idx = 0; idx < ndaemons; idx++) @@ -331,14 +420,17 @@ /* wait for a connection */ if (Daemons[idx].d_socket >= 0) { - if (!bitnset(D_ETRNONLY, Daemons[idx].d_flags)) + if (!setproc && + !bitnset(D_ETRNONLY, + Daemons[idx].d_flags)) { sm_setproctitle(TRUE, e, "accepting connections"); + setproc = TRUE; } if (Daemons[idx].d_socket > highest) highest = Daemons[idx].d_socket; - FD_SET(Daemons[idx].d_socket, &readfds); + FD_SET((u_int)Daemons[idx].d_socket, &readfds); } } @@ -351,25 +443,24 @@ } # endif /* NETUNIX */ - /* - ** if one socket is closed, set the timeout - ** to 5 seconds (so it might get reopened soon), - ** otherwise (all sockets open) 60. - */ - idx = 0; - while (idx < ndaemons && Daemons[idx].d_socket >= 0) - idx++; - if (idx < ndaemons) - timeout.tv_sec = 5; - else - timeout.tv_sec = 60; + timeout.tv_sec = 5; timeout.tv_usec = 0; t = select(highest + 1, FDSET_CAST &readfds, NULL, NULL, &timeout); + /* Did someone signal while waiting? */ + if (ShutdownRequest != NULL) + shutdown_daemon(); + else if (RestartRequest != NULL) + restart_daemon(); + + + if (DoQueueRun) (void) runqueue(TRUE, FALSE); + + curdaemon = -1; if (t <= 0) { timedout = TRUE; @@ -378,7 +469,6 @@ control = FALSE; errno = 0; - curdaemon = -1; /* look "round-robin" for an active socket */ if ((idx = olddaemon + 1) >= ndaemons) @@ -389,9 +479,29 @@ FD_ISSET(Daemons[idx].d_socket, &readfds)) { lotherend = Daemons[idx].d_socksize; + memset(&RealHostAddr, '\0', + sizeof RealHostAddr); t = accept(Daemons[idx].d_socket, (struct sockaddr *)&RealHostAddr, &lotherend); + + /* + ** If remote side closes before + ** accept() finishes, sockaddr + ** might not be fully filled in. + */ + + if (t >= 0 && + (lotherend == 0 || +# ifdef BSD4_4_SOCKADDR + RealHostAddr.sa.sa_len == 0 || +# endif /* BSD4_4_SOCKADDR */ + RealHostAddr.sa.sa_family != Daemons[idx].d_addr.sa.sa_family)) + { + (void) close(t); + t = -1; + errno = EINVAL; + } olddaemon = curdaemon = idx; break; } @@ -400,15 +510,41 @@ } # if NETUNIX if (curdaemon == -1 && ControlSocket >= 0 && - FD_ISSET(ControlSocket, &readfds)) + FD_ISSET(ControlSocket, &readfds)) { struct sockaddr_un sa_un; lotherend = sizeof sa_un; + memset(&sa_un, '\0', sizeof sa_un); t = accept(ControlSocket, (struct sockaddr *)&sa_un, &lotherend); - control = TRUE; + + /* + ** If remote side closes before + ** accept() finishes, sockaddr + ** might not be fully filled in. + */ + + if (t >= 0 && + (lotherend == 0 || +# ifdef BSD4_4_SOCKADDR + sa_un.sun_len == 0 || +# endif /* BSD4_4_SOCKADDR */ + sa_un.sun_family != AF_UNIX)) + { + (void) close(t); + t = -1; + errno = EINVAL; + } + if (t >= 0) + control = TRUE; + } +# else /* NETUNIX */ + if (curdaemon == -1) + { + /* No daemon to service */ + continue; } # endif /* NETUNIX */ if (t >= 0 || errno != EINTR) @@ -420,6 +556,7 @@ continue; } save_errno = errno; + timenow = curtime(); (void) blocksignal(SIGALRM); if (t < 0) { @@ -429,6 +566,15 @@ /* arrange to re-open the socket next time around */ (void) close(Daemons[curdaemon].d_socket); Daemons[curdaemon].d_socket = -1; +# if SO_REUSEADDR_IS_BROKEN + /* + ** Give time for bound socket to be released. + ** This creates a denial-of-service if you can + ** force accept() to fail on affected systems. + */ + + Daemons[curdaemon].d_refuse_connections_until = timenow + 15; +# endif /* SO_REUSEADDR_IS_BROKEN */ continue; } @@ -497,8 +643,17 @@ ** of a queue directory (and other things, e.g., MX selection) ** are not "really" random. */ +# if STARTTLS + seed = get_random(); + RAND_seed((void *) &last_disk_space_check, + sizeof last_disk_space_check); + RAND_seed((void *) &timenow, sizeof timenow); + RAND_seed((void *) &seed, sizeof seed); +# else /* STARTTLS */ (void) get_random(); +# endif /* STARTTLS */ +#ifndef DEBUG_NO_FORK /* ** Create a pipe to keep the child from writing to the ** socket until after the parent has closed it. Otherwise @@ -523,6 +678,9 @@ (void) close(t); continue; } +#else /* ! DEBUG_NO_FORK */ + pid = 0; +#endif /* ! DEBUG_NO_FORK */ if (pid == 0) { @@ -535,6 +693,18 @@ ** Verify calling user id if possible here. */ + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + + (void) releasesignal(SIGALRM); + (void) releasesignal(SIGCHLD); + (void) setsignal(SIGCHLD, SIG_DFL); + (void) setsignal(SIGHUP, SIG_DFL); + (void) setsignal(SIGTERM, intsig); + + if (!control) { define(macid("{daemon_addr}", NULL), @@ -546,10 +716,6 @@ newstr(status), &BlankEnvelope); } - (void) releasesignal(SIGALRM); - (void) releasesignal(SIGCHLD); - (void) setsignal(SIGCHLD, SIG_DFL); - (void) setsignal(SIGHUP, intsig); for (idx = 0; idx < ndaemons; idx++) { if (Daemons[idx].d_socket >= 0) @@ -562,7 +728,7 @@ { /* Add control socket process */ proc_list_add(getpid(), "console socket child", - PROC_CONTROL_CHILD); + PROC_CONTROL_CHILD); } else { @@ -579,6 +745,7 @@ anynet_ntoa(&RealHostAddr)); } +#ifndef DEBUG_NO_FORK if (pipefd[0] != -1) { auto char c; @@ -600,11 +767,13 @@ continue; (void) close(pipefd[0]); } +#endif /* ! DEBUG_NO_FORK */ /* control socket processing */ if (control) { control_command(t, e); + /* NOTREACHED */ exit(EX_SOFTWARE); } @@ -698,8 +867,7 @@ /* parent -- keep track of children */ if (control) { - snprintf(status, sizeof status, - "control socket server child"); + snprintf(status, sizeof status, "control socket server child"); proc_list_add(pid, status, PROC_CONTROL); } else @@ -713,15 +881,22 @@ /* close the read end of the synchronization pipe */ if (pipefd[0] != -1) + { (void) close(pipefd[0]); + pipefd[0] = -1; + } /* close the port so that others will hang (for a while) */ (void) close(t); /* release the child by closing the read end of the sync pipe */ if (pipefd[1] != -1) + { (void) close(pipefd[1]); + pipefd[1] = -1; + } } + if (tTd(15, 2)) dprintf("getreq: returning\n"); return &Daemons[curdaemon].d_flags; @@ -771,6 +946,14 @@ { save_errno = errno; syserr("opendaemonsocket: daemon %s: can't create server SMTP socket", d->d_name); + if (bitnset(D_OPTIONAL, d->d_flags) && + (save_errno == EAFNOSUPPORT || + save_errno == EPROTONOSUPPORT)) + { + syserr("opendaemonsocket: daemon %s: optional socket disabled", d->d_name); + setbitn(D_DISABLE, d->d_flags); + return -1; + } severe: if (LogLevel > 0) sm_syslog(LOG_ALERT, NOQID, @@ -1009,10 +1192,12 @@ struct daemon *d; { # if NETISO - short port; + short portno; # endif /* NETISO */ int l; char *h, *flags; + char *port = NULL; + char *addr = NULL; # if NETINET if (d->d_addr.sa.sa_family == AF_UNSPEC) @@ -1071,152 +1256,11 @@ break; case 'A': /* address */ - switch (d->d_addr.sa.sa_family) - { -# if NETINET - case AF_INET: - if (!isascii(*v) || !isdigit(*v) || - ((d->d_addr.sin.sin_addr.s_addr = inet_addr(v)) == INADDR_NONE)) - { - register struct hostent *hp; - - hp = sm_gethostbyname(v, AF_INET); - if (hp == NULL) - syserr("554 5.3.0 host \"%s\" unknown", - v); - else - { - while (*(hp->h_addr_list) && - hp->h_addrtype != AF_INET) - hp->h_addr_list++; - if (*(hp->h_addr_list) == NULL) - syserr("554 5.3.0 host \"%s\" unknown", - v); - else - memmove(&d->d_addr.sin.sin_addr, - *(hp->h_addr_list), - INADDRSZ); - } - } - break; -# endif /* NETINET */ - -# if NETINET6 - case AF_INET6: - if (!isascii(*v) || !isxdigit(*v) || - inet_pton(AF_INET6, v, - &d->d_addr.sin6.sin6_addr) != 1) - { - register struct hostent *hp; - - hp = sm_gethostbyname(v, AF_INET6); - if (hp == NULL) - syserr("554 5.3.0 host \"%s\" unknown", - v); - else - { - while (*(hp->h_addr_list) && - hp->h_addrtype != AF_INET6) - hp->h_addr_list++; - if (*(hp->h_addr_list) == NULL) - syserr("554 5.3.0 host \"%s\" unknown", - v); - else - memmove(&d->d_addr.sin6.sin6_addr, - *(hp->h_addr_list), - IN6ADDRSZ); - } - } - break; -# endif /* NETINET6 */ - - default: - syserr("554 5.3.5 address= option unsupported for family %d", - d->d_addr.sa.sa_family); - break; - } + addr = v; break; case 'P': /* port */ - switch (d->d_addr.sa.sa_family) - { -# if NETINET - case AF_INET: - if (isascii(*v) && isdigit(*v)) - d->d_addr.sin.sin_port = htons(atoi(v)); - else - { -# ifdef NO_GETSERVBYNAME - syserr("554 5.3.5 invalid port number: %s", - v); -# else /* NO_GETSERVBYNAME */ - register struct servent *sp; - - sp = getservbyname(v, "tcp"); - if (sp == NULL) - syserr("554 5.3.5 service \"%s\" unknown", - v); - else - d->d_addr.sin.sin_port = sp->s_port; -# endif /* NO_GETSERVBYNAME */ - } - break; -# endif /* NETINET */ - -# if NETINET6 - case AF_INET6: - if (isascii(*v) && isdigit(*v)) - d->d_addr.sin6.sin6_port = htons(atoi(v)); - else - { -# ifdef NO_GETSERVBYNAME - syserr("554 5.3.5 invalid port number: %s", - v); -# else /* NO_GETSERVBYNAME */ - register struct servent *sp; - - sp = getservbyname(v, "tcp"); - if (sp == NULL) - syserr("554 5.3.5 service \"%s\" unknown", - v); - else - d->d_addr.sin6.sin6_port = sp->s_port; -# endif /* NO_GETSERVBYNAME */ - } - break; -# endif /* NETINET6 */ - -# if NETISO - case AF_ISO: - /* assume two byte transport selector */ - if (isascii(*v) && isdigit(*v)) - port = htons(atoi(v)); - else - { -# ifdef NO_GETSERVBYNAME - syserr("554 5.3.5 invalid port number: %s", - v); -# else /* NO_GETSERVBYNAME */ - register struct servent *sp; - - sp = getservbyname(v, "tcp"); - if (sp == NULL) - syserr("554 5.3.5 service \"%s\" unknown", - v); - else - port = sp->s_port; -# endif /* NO_GETSERVBYNAME */ - } - memmove(TSEL(&d->d_addr.siso), - (char *) &port, 2); - break; -# endif /* NETISO */ - - default: - syserr("554 5.3.5 Port= option unsupported for family %d", - d->d_addr.sa.sa_family); - break; - } + port = v; break; case 'L': /* listen queue size */ @@ -1233,7 +1277,7 @@ if (!(isascii(*h) && isspace(*h))) { if (flags != d->d_mflags) - *f++ = ' '; + *flags++ = ' '; *flags++ = *h; if (isupper(*h)) *flags++ = *h; @@ -1242,7 +1286,7 @@ *flags++ = '\0'; for (; *v != '\0'; v++) if (!(isascii(*v) && isspace(*v))) - setbitn(*v, d->d_flags); + setbitn(bitidx(*v), d->d_flags); break; case 'S': /* send buffer size */ @@ -1262,6 +1306,167 @@ f); } } + + /* Check addr and port after finding family */ + if (addr != NULL) + { + switch (d->d_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (!isascii(*addr) || !isdigit(*addr) || + ((d->d_addr.sin.sin_addr.s_addr = inet_addr(addr)) == INADDR_NONE)) + { + register struct hostent *hp; + + hp = sm_gethostbyname(addr, AF_INET); + if (hp == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + addr); + else + { + while (*(hp->h_addr_list) != NULL && + hp->h_addrtype != AF_INET) + hp->h_addr_list++; + if (*(hp->h_addr_list) == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + addr); + else + memmove(&d->d_addr.sin.sin_addr, + *(hp->h_addr_list), + INADDRSZ); +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); + hp = NULL; +# endif /* _FFR_FREEHOSTENT && NETINET6 */ + } + } + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (!isascii(*addr) || + (!isxdigit(*addr) && *addr != ':') || + inet_pton(AF_INET6, addr, + &d->d_addr.sin6.sin6_addr) != 1) + { + register struct hostent *hp; + + hp = sm_gethostbyname(addr, AF_INET6); + if (hp == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + addr); + else + { + while (*(hp->h_addr_list) != NULL && + hp->h_addrtype != AF_INET6) + hp->h_addr_list++; + if (*(hp->h_addr_list) == NULL) + syserr("554 5.3.0 host \"%s\" unknown", + addr); + else + memmove(&d->d_addr.sin6.sin6_addr, + *(hp->h_addr_list), + IN6ADDRSZ); +# if _FFR_FREEHOSTENT + freehostent(hp); + hp = NULL; +# endif /* _FFR_FREEHOSTENT */ + } + } + break; +# endif /* NETINET6 */ + + default: + syserr("554 5.3.5 address= option unsupported for family %d", + d->d_addr.sa.sa_family); + break; + } + } + + if (port != NULL) + { + switch (d->d_addr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (isascii(*port) && isdigit(*port)) + d->d_addr.sin.sin_port = htons((u_short)atoi((const char *)port)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + port); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(port, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + port); + else + d->d_addr.sin.sin_port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (isascii(*port) && isdigit(*port)) + d->d_addr.sin6.sin6_port = htons((u_short)atoi(port)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + port); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(port, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + port); + else + d->d_addr.sin6.sin6_port = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + break; +# endif /* NETINET6 */ + +# if NETISO + case AF_ISO: + /* assume two byte transport selector */ + if (isascii(*port) && isdigit(*port)) + portno = htons((u_short)atoi(port)); + else + { +# ifdef NO_GETSERVBYNAME + syserr("554 5.3.5 invalid port number: %s", + port); +# else /* NO_GETSERVBYNAME */ + register struct servent *sp; + + sp = getservbyname(port, "tcp"); + if (sp == NULL) + syserr("554 5.3.5 service \"%s\" unknown", + port); + else + portno = sp->s_port; +# endif /* NO_GETSERVBYNAME */ + } + memmove(TSEL(&d->d_addr.siso), + (char *) &portno, 2); + break; +# endif /* NETISO */ + + default: + syserr("554 5.3.5 Port= option unsupported for family %d", + d->d_addr.sa.sa_family); + break; + } + } } /* ** SETDAEMONOPTIONS -- set options for running the MTA daemon @@ -1362,6 +1567,47 @@ define(macid("{client_flags}", NULL), "", &BlankEnvelope); } /* +** ADDR_FAMILY -- determine address family from address +** +** Parameters: +** addr -- the string representation of the address +** +** Returns: +** AF_INET, AF_INET6 or AF_UNSPEC +** +** Side Effects: +** none. +*/ + +static int +addr_family(addr) + char *addr; +{ +# if NETINET6 + SOCKADDR clt_addr; +# endif /* NETINET6 */ + +# if NETINET + if (inet_addr(addr) != INADDR_NONE) + { + if (tTd(16, 9)) + printf("addr_family(%s): INET\n", addr); + return AF_INET; + } +# endif /* NETINET */ +# if NETINET6 + if (inet_pton(AF_INET6, addr, &clt_addr.sin6.sin6_addr) == 1) + { + if (tTd(16, 9)) + printf("addr_family(%s): INET6\n", addr); + return AF_INET6; + } +# endif /* NETINET6 */ + if (tTd(16, 9)) + printf("addr_family(%s): UNSPEC\n", addr); + return AF_UNSPEC; +} + /* ** MAKECONNECTION -- make a connection to an SMTP socket on a machine. ** ** Parameters: @@ -1417,7 +1663,7 @@ for (; *p != '\0'; p++) { if (!(isascii(*p) && isspace(*p))) - setbitn(*p, d_flags); + setbitn(bitidx(*p), d_flags); } } @@ -1429,7 +1675,7 @@ /* look for just this one flag */ if (*p == D_IFNHELO) { - setbitn(*p, d_flags); + setbitn(bitidx(*p), d_flags); break; } } @@ -1442,36 +1688,28 @@ /* Set up the address for outgoing connection. */ if (bitnset(D_BINDIF, d_flags) && - (p = macvalue(macid("{if_addr}", NULL), e)) != NULL) + (p = macvalue(macid("{if_addr}", NULL), e)) != NULL && + *p != '\0') { - char *f; # if NETINET6 char p6[INET6_ADDRSTRLEN]; # endif /* NETINET6 */ memset(&clt_addr, '\0', sizeof clt_addr); - /* XXX set all necessary values... */ - if ((f = macvalue(macid("{if_family}", NULL), e)) != NULL) - clt_addr.sa.sa_family = atoi(f); - else - clt_addr.sa.sa_family = family; + /* infer the address family from the address itself */ + clt_addr.sa.sa_family = addr_family(p); switch (clt_addr.sa.sa_family) { # if NETINET case AF_INET: - if ((clt_addr.sin.sin_addr.s_addr = inet_addr(p)) - != INADDR_NONE) + clt_addr.sin.sin_addr.s_addr = inet_addr(p); + if (clt_addr.sin.sin_addr.s_addr != INADDR_NONE && + clt_addr.sin.sin_addr.s_addr != INADDR_LOOPBACK) { clt_bind = TRUE; socksize = sizeof (struct sockaddr_in); } - else if (clt_addr.sin.sin_port != 0) - { - clt_addr.sin.sin_addr.s_addr = INADDR_ANY; - clt_bind = TRUE; - socksize = sizeof (struct sockaddr_in); - } break; # endif /* NETINET */ @@ -1482,15 +1720,9 @@ else strlcpy(p6, p, sizeof p6); if (inet_pton(AF_INET6, p6, - &clt_addr.sin6.sin6_addr) == 1) - { - clt_bind = TRUE; - socksize = sizeof (struct sockaddr_in6); - } - else if (clt_addr.sin6.sin6_port != 0) + &clt_addr.sin6.sin6_addr) == 1 && + !IN6_IS_ADDR_LOOPBACK(&clt_addr.sin6.sin6_addr)) { - if (IN6_IS_ADDR_UNSPECIFIED(&clt_addr.sin6.sin6_addr)) - clt_addr.sin6.sin6_addr = in6addr_any; clt_bind = TRUE; socksize = sizeof (struct sockaddr_in6); } @@ -1504,12 +1736,14 @@ break; # endif /* 0 */ } + if (clt_bind) + family = clt_addr.sa.sa_family; } else { STRUCTCOPY(ClientAddr, clt_addr); if (clt_addr.sa.sa_family == AF_UNSPEC) - clt_addr.sa.sa_family = InetMode; + clt_addr.sa.sa_family = family; switch (clt_addr.sa.sa_family) { # if NETINET @@ -1551,7 +1785,7 @@ */ # if NAMED_BIND - h_errno = 0; + SM_SET_H_ERRNO(0); # endif /* NAMED_BIND */ errno = 0; memset(&CurHostAddr, '\0', sizeof CurHostAddr); @@ -1771,6 +2005,10 @@ syserr("Can't connect to address family %d", addr.sa.sa_family); mci_setstat(mci, EX_NOHOST, "5.1.2", NULL); errno = EINVAL; +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ return EX_NOHOST; } @@ -1781,15 +2019,22 @@ # ifdef XLA /* if too many connections, don't bother trying */ if (!xla_noqueue_ok(host)) + { +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ return EX_TEMPFAIL; + } # endif /* XLA */ firstconnect = TRUE; for (;;) { if (tTd(16, 1)) - dprintf("makeconnection (%s [%s])\n", - host, anynet_ntoa(&addr)); + dprintf("makeconnection (%s [%s].%d (%d))\n", + host, anynet_ntoa(&addr), ntohs(port), + addr.sa.sa_family); /* save for logging */ CurHostAddr = addr; @@ -1802,7 +2047,7 @@ } else { - s = socket(addr.sa.sa_family, SOCK_STREAM, 0); + s = socket(clt_addr.sa.sa_family, SOCK_STREAM, 0); } if (s < 0) { @@ -1812,6 +2057,10 @@ xla_host_end(host); # endif /* XLA */ mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL); +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ errno = save_errno; return EX_TEMPFAIL; } @@ -1885,6 +2134,10 @@ errno = save_errno; syserr("makeconnection: cannot bind socket [%s]", anynet_ntoa(&clt_addr)); +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ errno = save_errno; return EX_TEMPFAIL; } @@ -1900,9 +2153,11 @@ int i; if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0) - ev = setevent(TimeOuts.to_iconnect, connecttimeout, 0); + ev = setevent(TimeOuts.to_iconnect, + connecttimeout, 0); else if (TimeOuts.to_connect != 0) - ev = setevent(TimeOuts.to_connect, connecttimeout, 0); + ev = setevent(TimeOuts.to_connect, + connecttimeout, 0); else ev = NULL; @@ -1983,6 +2238,7 @@ } continue; } + errno = save_errno; # if NETINET6 if (family == AF_INET6) @@ -1992,6 +2248,13 @@ errstring(save_errno)); v6found = TRUE; family = AF_INET; +# if _FFR_FREEHOSTENT + if (hp != NULL) + { + freehostent(hp); + hp = NULL; + } +# endif /* _FFR_FREEHOSTENT */ goto v4retry; } v6tempfail: @@ -2008,10 +2271,22 @@ xla_host_end(host); # endif /* XLA */ mci_setstat(mci, EX_TEMPFAIL, "4.4.1", NULL); +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ errno = save_errno; return EX_TEMPFAIL; } +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + { + freehostent(hp); + hp = NULL; + } +# endif /* _FFR_FREEHOSTENT && NETINET6 */ + /* connection ok, put it into canonical form */ mci->mci_out = NULL; if ((mci->mci_out = fdopen(s, "w")) == NULL || @@ -2033,9 +2308,14 @@ if (getsockname(s, &addr.sa, &len) == 0) { char *name; + char *p; define(macid("{if_addr}", NULL), newstr(anynet_ntoa(&addr)), &BlankEnvelope); + p = xalloc(5); + snprintf(p, 4, "%d", addr.sa.sa_family); + define(macid("{if_family}", NULL), p, &BlankEnvelope); + name = hostnamebyanyaddr(&addr); define(macid("{if_name}", NULL), newstr(name), &BlankEnvelope); if (LogLevel > 11) @@ -2054,6 +2334,7 @@ { define(macid("{if_name}", NULL), NULL, &BlankEnvelope); define(macid("{if_addr}", NULL), NULL, &BlankEnvelope); + define(macid("{if_family}", NULL), NULL, &BlankEnvelope); } mci_setstat(mci, EX_OK, NULL, NULL); return EX_OK; @@ -2062,6 +2343,12 @@ static void connecttimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + errno = ETIMEDOUT; longjmp(CtxConnectTimeout, 1); } @@ -2162,6 +2449,124 @@ } # endif /* NETUNIX */ /* +** SIGHUP -- handle a SIGHUP signal +** +** Parameters: +** sig -- incoming signal. +** +** Returns: +** none. +** +** Side Effects: +** Sets RestartRequest which should cause the daemon +** to restart. +** +** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD +** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE +** DOING. +*/ + +/* ARGSUSED */ +static SIGFUNC_DECL +sighup(sig) + int sig; +{ + int save_errno = errno; + + FIX_SYSV_SIGNAL(sig, sighup); + RestartRequest = "signal"; + errno = save_errno; + return SIGFUNC_RETURN; +} + /* +** RESTART_DAEMON -- Performs a clean restart of the daemon +** +** Parameters: +** none. +** +** Returns: +** none. +** +** Side Effects: +** restarts the daemon or exits if restart fails. +*/ + +static void +restart_daemon() +{ + int i; + int save_errno; + char *reason; + sigfunc_t oalrm, ochld, ohup, oint, opipe, oterm, ousr1; + extern int DtableSize; + + allsignals(TRUE); + + reason = RestartRequest; + RestartRequest = NULL; + PendingSignal = 0; + + if (SaveArgv[0][0] != '/') + { + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, + "could not restart: need full path"); + finis(FALSE, EX_OSFILE); + } + if (LogLevel > 3) + sm_syslog(LOG_INFO, NOQID, "restarting %s due to %s", + SaveArgv[0], + reason == NULL ? "implicit call" : reason); + + closecontrolsocket(TRUE); + if (drop_privileges(TRUE) != EX_OK) + { + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, + "could not set[ug]id(%d, %d): %m", + RunAsUid, RunAsGid); + finis(FALSE, EX_OSERR); + } + + /* arrange for all the files to be closed */ + for (i = 3; i < DtableSize; i++) + { + register int j; + + if ((j = fcntl(i, F_GETFD, 0)) != -1) + (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); + } + + /* need to allow signals before execve() so make them harmless */ + oalrm = setsignal(SIGALRM, SIG_DFL); + ochld = setsignal(SIGCHLD, SIG_DFL); + ohup = setsignal(SIGHUP, SIG_DFL); + oint = setsignal(SIGINT, SIG_DFL); + opipe = setsignal(SIGPIPE, SIG_DFL); + oterm = setsignal(SIGTERM, SIG_DFL); + ousr1 = setsignal(SIGUSR1, SIG_DFL); + allsignals(FALSE); + + (void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron); + save_errno = errno; + + /* restore signals */ + allsignals(TRUE); + (void) setsignal(SIGALRM, oalrm); + (void) setsignal(SIGCHLD, ochld); + (void) setsignal(SIGHUP, ohup); + (void) setsignal(SIGINT, oint); + (void) setsignal(SIGPIPE, opipe); + (void) setsignal(SIGTERM, oterm); + (void) setsignal(SIGUSR1, ousr1); + + errno = save_errno; + if (LogLevel > 0) + sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m", + SaveArgv[0]); + finis(FALSE, EX_OSFILE); +} + /* ** MYHOSTNAME -- return the name of this host. ** ** Parameters: @@ -2182,10 +2587,8 @@ { register struct hostent *hp; - if (gethostname(hostbuf, size) < 0) - { + if (gethostname(hostbuf, size) < 0 || hostbuf[0] == '\0') (void) strlcpy(hostbuf, "localhost", size); - } hp = sm_gethostbyname(hostbuf, InetMode); if (hp == NULL) return NULL; @@ -2326,6 +2729,13 @@ static void authtimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxAuthTimeout, 1); } @@ -2334,6 +2744,7 @@ int fd; bool *may_be_forged; { + volatile u_short port = 0; SOCKADDR_LEN_T falen; register char *volatile p = NULL; SOCKADDR la; @@ -2366,7 +2777,7 @@ errno = 0; } (void) snprintf(hbuf, sizeof hbuf, "%s@localhost", - RealUserName); + RealUserName); if (tTd(9, 1)) dprintf("getauthinfo: %s\n", hbuf); return hbuf; @@ -2404,6 +2815,10 @@ if (addrcmp(hp, *ha, &RealHostAddr) == 0) break; *may_be_forged = *ha == NULL; +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); + hp = NULL; +# endif /* _FFR_FREEHOSTENT && NETINET6 */ } } @@ -2422,6 +2837,7 @@ /* no ident info */ goto noident; } + port = RealHostAddr.sin.sin_port; /* create ident query */ (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", @@ -2453,6 +2869,7 @@ /* no ident info */ goto noident; } + port = RealHostAddr.sin6.sin6_port; /* create ident query */ (void) snprintf(ibuf, sizeof ibuf, "%d,%d\r\n", @@ -2490,6 +2907,7 @@ /* put a timeout around the whole thing */ ev = setevent(TimeOuts.to_ident, authtimeout, 0); + /* connect to foreign IDENT server using same address as SMTP socket */ s = socket(la.sa.sa_family, SOCK_STREAM, 0); if (s < 0) @@ -2599,6 +3017,24 @@ clrevent(ev); noident: + /* put back the original incoming port */ + switch (RealHostAddr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (port > 0) + RealHostAddr.sin.sin_port = port; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (port > 0) + RealHostAddr.sin6.sin6_port = port; + break; +# endif /* NETINET6 */ + } + if (RealHostName == NULL) { if (tTd(9, 1)) @@ -2728,6 +3164,25 @@ # endif /* IP_SRCROUTE */ if (tTd(9, 1)) dprintf("getauthinfo: %s\n", hbuf); + + /* put back the original incoming port */ + switch (RealHostAddr.sa.sa_family) + { +# if NETINET + case AF_INET: + if (port > 0) + RealHostAddr.sin.sin_port = port; + break; +# endif /* NETINET */ + +# if NETINET6 + case AF_INET6: + if (port > 0) + RealHostAddr.sin6.sin6_port = port; + break; +# endif /* NETINET6 */ + } + return hbuf; } /* @@ -2786,7 +3241,7 @@ : s->s_namecanon.nc_cname); errno = s->s_namecanon.nc_errno; # if NAMED_BIND - h_errno = s->s_namecanon.nc_herrno; + SM_SET_H_ERRNO(s->s_namecanon.nc_herrno); # endif /* NAMED_BIND */ *statp = s->s_namecanon.nc_stat; if (*statp == EX_TEMPFAIL) @@ -2848,7 +3303,11 @@ else { if ((cp = strchr(name, ']')) == NULL) + { + if (tTd(9, 1)) + dprintf("FAILED\n"); return NULL; + } *cp = '\0'; hp = NULL; @@ -2869,6 +3328,10 @@ { /* found a match -- copy out */ ans = denlstring((char *) hp->h_name, TRUE, TRUE); +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); + hp = NULL; +# endif /* _FFR_FREEHOSTENT && NETINET6 */ } } @@ -2883,6 +3346,8 @@ cp = map_rewrite(map, name, strlen(name), NULL); else cp = map_rewrite(map, ans, strlen(ans), av); + if (tTd(9, 1)) + dprintf("FOUND %s\n", ans); return cp; } @@ -2952,6 +3417,8 @@ fixcrlf(hostbuf, TRUE); (void) fclose(f); } + if (hostbuf[0] == '\0') + (void) strlcpy(hostbuf, "localhost", size); return NULL; } /* @@ -3053,6 +3520,9 @@ cp = map_rewrite(map, name, strlen(name), NULL); else cp = map_rewrite(map, hp->h_name, strlen(hp->h_name), avp); +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ return cp; } @@ -3305,8 +3775,35 @@ && inet_addr(hp->h_name) == INADDR_NONE # endif /* NETINET */ ) - return denlstring((char *) hp->h_name, TRUE, TRUE); + { + char *name; + + name = denlstring((char *) hp->h_name, TRUE, TRUE); + +# if _FFR_FREEHOSTENT && NETINET6 + if (name == hp->h_name) + { + static char n[MAXNAME + 1]; + + /* Copy the string, hp->h_name is about to disappear */ + strlcpy(n, name, sizeof n); + name = n; + } + + freehostent(hp); +# endif /* _FFR_FREEHOSTENT && NETINET6 */ + return name; + } # endif /* NETINET || NETINET6 */ + +# if _FFR_FREEHOSTENT && NETINET6 + if (hp != NULL) + { + freehostent(hp); + hp = NULL; + } +# endif /* _FFR_FREEHOSTENT && NETINET6 */ + # if NETUNIX if (sap->sa.sa_family == AF_UNIX && sap->sunix.sun_path[0] == '\0') return "localhost"; Index: gnu/usr.sbin/sendmail/sendmail/deliver.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/deliver.c,v retrieving revision 1.2 retrieving revision 1.5 diff -u -r1.2 -r1.5 --- gnu/usr.sbin/sendmail/sendmail/deliver.c 2000/04/07 19:20:40 1.2 +++ gnu/usr.sbin/sendmail/sendmail/deliver.c 2001/05/29 01:31:14 1.5 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -12,15 +12,19 @@ */ #ifndef lint -static char id[] = "@(#)$Sendmail: deliver.c,v 8.600 2000/04/06 00:50:14 gshapiro Exp $"; +static char id[] = "@(#)$Sendmail: deliver.c,v 8.600.2.1.2.81 2001/05/23 02:15:42 ca Exp $"; #endif /* ! lint */ #include + #if HASSETUSERCONTEXT # include #endif /* HASSETUSERCONTEXT */ +#if STARTTLS || (SASL && SFIO) +# include "sfsasl.h" +#endif /* STARTTLS || (SASL && SFIO) */ static int deliver __P((ENVELOPE *, ADDRESS *)); static void dup_queue_file __P((ENVELOPE *, ENVELOPE *, int)); @@ -31,6 +35,9 @@ static char *hostsignature __P((MAILER *, char *)); #if SMTP +# if STARTTLS +static int starttls __P((MAILER *, MCI *, ENVELOPE *)); +# endif /* STARTTLS */ #endif /* SMTP */ /* @@ -128,21 +135,31 @@ if (e->e_hopcount > MaxHopCount) { + char *recip; + + if (e->e_sendqueue != NULL && + e->e_sendqueue->q_paddr != NULL) + recip = e->e_sendqueue->q_paddr; + else + recip = "(nobody)"; + errno = 0; #if QUEUE queueup(e, mode == SM_QUEUE || mode == SM_DEFER); #endif /* QUEUE */ e->e_flags |= EF_FATALERRS|EF_PM_NOTIFY|EF_CLRQUEUE; ExitStat = EX_UNAVAILABLE; - syserr("554 5.0.0 Too many hops %d (%d max): from %s via %s, to %s", - e->e_hopcount, MaxHopCount, e->e_from.q_paddr, - RealHostName == NULL ? "localhost" : RealHostName, - e->e_sendqueue->q_paddr); + syserr("554 5.4.6 Too many hops %d (%d max): from %s via %s, to %s", + e->e_hopcount, MaxHopCount, e->e_from.q_paddr, + RealHostName == NULL ? "localhost" : RealHostName, + recip); for (q = e->e_sendqueue; q != NULL; q = q->q_next) { if (QS_IS_DEAD(q->q_state)) continue; + q->q_state = QS_BADADDR; q->q_status = "5.4.6"; + q->q_rstatus = "554 5.4.6 Too many hops"; } return; } @@ -455,17 +472,19 @@ if (!somedeliveries && mode != SM_QUEUE && mode != SM_DEFER && mode != SM_VERIFY) { + time_t now = curtime(); + if (tTd(13, 29)) dprintf("No deliveries: auto-queuing\n"); mode = SM_QUEUE; /* treat this as a delivery in terms of counting tries */ - e->e_dtime = curtime(); + e->e_dtime = now; if (!expensive) e->e_ntries++; for (ee = splitenv; ee != NULL; ee = ee->e_sibling) { - ee->e_dtime = curtime(); + ee->e_dtime = now; if (!expensive) ee->e_ntries++; } @@ -476,10 +495,16 @@ (mode != SM_VERIFY && SuperSafe)) && (!bitset(EF_INQUEUE, e->e_flags) || splitenv != NULL)) { - /* be sure everything is instantiated in the queue */ - queueup(e, mode == SM_QUEUE || mode == SM_DEFER); + /* + ** Be sure everything is instantiated in the queue. + ** Split envelopes first in case the machine crashes. + ** If the original were done first, we may lose + ** recipients. + */ + for (ee = splitenv; ee != NULL; ee = ee->e_sibling) queueup(ee, mode == SM_QUEUE || mode == SM_DEFER); + queueup(e, mode == SM_QUEUE || mode == SM_DEFER); } #endif /* QUEUE */ @@ -619,6 +644,20 @@ return; } + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + + /* + ** Since we have accepted responsbility for the message, + ** change the SIGTERM handler. intsig() (the old handler) + ** would remove the envelope if this was a command line + ** message submission. + */ + + (void) setsignal(SIGTERM, SIG_DFL); + /* double fork to avoid zombies */ pid = fork(); if (pid > 0) @@ -779,7 +818,8 @@ ** Checkpoint the send list every few addresses */ - if (e->e_nsent >= CheckpointInterval) + if (CheckpointInterval > 0 && + e->e_nsent >= CheckpointInterval) { queueup(e, FALSE); e->e_nsent = 0; @@ -905,7 +945,7 @@ ** returns twice, once in parent and once in child. */ -int +pid_t dofork() { register pid_t pid = -1; @@ -975,11 +1015,18 @@ bool anyok; /* at least one address was OK */ bool goodmxfound = FALSE; /* at least one MX was OK */ bool ovr; +#if _FFR_DYNAMIC_TOBUF + int strsize; + int rcptcount; + static int tobufsize = 0; + static char *tobuf = NULL; +#else /* _FFR_DYNAMIC_TOBUF */ + char tobuf[TOBUFSIZE]; /* text line of to people */ +#endif /* _FFR_DYNAMIC_TOBUF */ int mpvect[2]; int rpvect[2]; char *mxhosts[MAXMXHOSTS + 1]; char *pv[MAXPV + 1]; - char tobuf[TOBUFSIZE]; /* text line of to people */ char buf[MAXNAME + 1]; char rpathbuf[MAXNAME + 1]; /* translated return path */ @@ -1099,7 +1146,7 @@ if (*mvp == NULL) { - /* running SMTP */ + /* running LMTP or SMTP */ #if SMTP clever = TRUE; *pvp = NULL; @@ -1109,6 +1156,14 @@ return EX_SOFTWARE; #endif /* SMTP */ } + else if (bitnset(M_LMTP, m->m_flags)) + { + /* not running LMTP */ + sm_syslog(LOG_ERR, NULL, + "Warning: mailer %s: LMTP flag (F=z) turned off", + m->m_name); + clrbitn(M_LMTP, m->m_flags); + } /* ** At this point *mvp points to the argument with $u. We @@ -1117,15 +1172,27 @@ ** always send another copy later. */ +#if _FFR_DYNAMIC_TOBUF + e->e_to = NULL; + strsize = 2; + rcptcount = 0; +#else /* _FFR_DYNAMIC_TOBUF */ tobuf[0] = '\0'; e->e_to = tobuf; +#endif /* _FFR_DYNAMIC_TOBUF */ + ctladdr = NULL; firstsig = hostsignature(firstto->q_mailer, firstto->q_host); for (; to != NULL; to = to->q_next) { /* avoid sending multiple recipients to dumb mailers */ +#if _FFR_DYNAMIC_TOBUF + if (tochain != NULL && !bitnset(M_MUSER, m->m_flags)) + break; +#else /* _FFR_DYNAMIC_TOBUF */ if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) break; +#endif /* _FFR_DYNAMIC_TOBUF */ /* if already sent or not for this host, don't send */ if (!QS_IS_OK(to->q_state) || @@ -1135,8 +1202,17 @@ continue; /* avoid overflowing tobuf */ +#if _FFR_DYNAMIC_TOBUF + strsize += strlen(to->q_paddr) + 1; + if (!clever && strsize > TOBUFSIZE) + break; + + if (++rcptcount > to->q_mailer->m_maxrcpt) + break; +#else /* _FFR_DYNAMIC_TOBUF */ if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) break; +#endif /* _FFR_DYNAMIC_TOBUF */ if (tTd(10, 1)) { @@ -1160,9 +1236,11 @@ /* ** Check to see that these people are allowed to ** talk to each other. + ** Check also for overflow of e_msgsize. */ - if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) + if (m->m_maxsize != 0 && + (e->e_msgsize > m->m_maxsize || e->e_msgsize < 0)) { e->e_flags |= EF_NO_BODY_RETN; if (bitnset(M_LOCALMAILER, to->q_mailer->m_flags)) @@ -1179,13 +1257,13 @@ continue; } #if NAMED_BIND - h_errno = 0; + SM_SET_H_ERRNO(0); #endif /* NAMED_BIND */ ovr = TRUE; /* do config file checking of compatibility */ rcode = rscheck("check_compat", e->e_from.q_paddr, to->q_paddr, - e, TRUE, TRUE, 4); + e, TRUE, TRUE, 4, NULL); if (rcode == EX_OK) { /* do in-code checking if not discarding */ @@ -1306,9 +1384,14 @@ to->q_tchain = tochain; tochain = to; +#if _FFR_DYNAMIC_TOBUF + e->e_to = "[CHAIN]"; +#else /* _FFR_DYNAMIC_TOBUF */ /* create list of users for error messages */ (void) strlcat(tobuf, ",", sizeof tobuf); (void) strlcat(tobuf, to->q_paddr, sizeof tobuf); +#endif /* _FFR_DYNAMIC_TOBUF */ + define('u', user, e); /* to user */ p = to->q_home; if (p == NULL && ctladdr != NULL) @@ -1358,13 +1441,44 @@ } /* see if any addresses still exist */ +#if _FFR_DYNAMIC_TOBUF + if (tochain == NULL) +#else /* _FFR_DYNAMIC_TOBUF */ if (tobuf[0] == '\0') +#endif /* _FFR_DYNAMIC_TOBUF */ { define('g', (char *) NULL, e); + e->e_to = NULL; return 0; } /* print out messages as full list */ +#if _FFR_DYNAMIC_TOBUF + { + int l = 1; + char *tobufptr; + + for (to = tochain; to != NULL; to = to->q_tchain) + l += strlen(to->q_paddr) + 1; + if (l < TOBUFSIZE) + l = TOBUFSIZE; + if (l > tobufsize) + { + if (tobuf != NULL) + sm_free(tobuf); + tobufsize = l; + tobuf = xalloc(tobufsize); + } + tobufptr = tobuf; + *tobufptr = '\0'; + for (to = tochain; to != NULL; to = to->q_tchain) + { + snprintf(tobufptr, tobufsize - (tobufptr - tobuf), + ",%s", to->q_paddr); + tobufptr += strlen(tobufptr); + } + } +#endif /* _FFR_DYNAMIC_TOBUF */ e->e_to = tobuf + 1; /* @@ -1406,7 +1520,7 @@ } errno = 0; #if NAMED_BIND - h_errno = 0; + SM_SET_H_ERRNO(0); #endif /* NAMED_BIND */ CurHostName = NULL; @@ -1508,7 +1622,7 @@ # endif /* NETUNIX */ ) { - port = htons(atoi(pv[2])); + port = htons((u_short)atoi(pv[2])); if (port == 0) { # ifdef NO_GETSERVBYNAME @@ -1619,10 +1733,10 @@ m->m_name); i = makeconnection(hostbuf, port, mci, e); } + mci->mci_errno = errno; mci->mci_lastuse = curtime(); mci->mci_deliveries = 0; mci->mci_exitstat = i; - mci->mci_errno = errno; # if NAMED_BIND mci->mci_herrno = h_errno; # endif /* NAMED_BIND */ @@ -1784,8 +1898,11 @@ (void) fflush(e->e_xfp); /* for debugging */ (void) fflush(stdout); (void) setsignal(SIGCHLD, SIG_DFL); + + DOFORK(FORK); /* pid is set by DOFORK */ + if (pid < 0) { /* failure */ @@ -1810,6 +1927,11 @@ struct stat stb; extern int DtableSize; + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + if (e->e_lockfp != NULL) (void) close(fileno(e->e_lockfp)); @@ -1821,7 +1943,7 @@ if (m != FileMailer || stat(tochain->q_user, &stb) < 0) stb.st_mode = 0; -#if HASSETUSERCONTEXT +# if HASSETUSERCONTEXT /* ** Set user resources. */ @@ -1839,7 +1961,7 @@ pwd, pwd->pw_uid, LOGIN_SETRESOURCES|LOGIN_SETPRIORITY); } -#endif /* HASSETUSERCONTEXT */ +# endif /* HASSETUSERCONTEXT */ /* tweak niceness */ if (m->m_nice != 0) @@ -1860,8 +1982,11 @@ u = ctladdr->q_user; if (initgroups(u, ctladdr->q_gid) == -1 && suidwarn) + { syserr("openmailer: initgroups(%s, %d) failed", u, ctladdr->q_gid); + exit(EX_TEMPFAIL); + } } else { @@ -1869,7 +1994,10 @@ gidset[0] = ctladdr->q_gid; if (setgroups(1, gidset) == -1 && suidwarn) + { syserr("openmailer: setgroups() failed"); + exit(EX_TEMPFAIL); + } } new_gid = ctladdr->q_gid; } @@ -1878,8 +2006,11 @@ if (!DontInitGroups) { if (initgroups(DefUser, DefGid) == -1 && suidwarn) + { syserr("openmailer: initgroups(%s, %d) failed", DefUser, DefGid); + exit(EX_TEMPFAIL); + } } else { @@ -1887,16 +2018,35 @@ gidset[0] = DefGid; if (setgroups(1, gidset) == -1 && suidwarn) + { syserr("openmailer: setgroups() failed"); + exit(EX_TEMPFAIL); + } } if (m->m_gid == 0) new_gid = DefGid; else new_gid = m->m_gid; + } + if (new_gid != NO_GID) + { + if (RunAsUid != 0 && + bitnset(M_SPECIFIC_UID, m->m_flags) && + new_gid != getgid() && + new_gid != getegid()) + { + /* Only root can change the gid */ + syserr("openmailer: insufficient privileges to change gid"); + exit(EX_TEMPFAIL); + } + + if (setgid(new_gid) < 0 && suidwarn) + { + syserr("openmailer: setgid(%ld) failed", + (long) new_gid); + exit(EX_TEMPFAIL); + } } - if (new_gid != NO_GID && setgid(new_gid) < 0 && suidwarn) - syserr("openmailer: setgid(%ld) failed", - (long) new_gid); /* change root to some "safe" directory */ if (m->m_rootdir != NULL) @@ -1906,10 +2056,16 @@ dprintf("openmailer: chroot %s\n", buf); if (chroot(buf) < 0) + { syserr("openmailer: Cannot chroot(%s)", buf); + exit(EX_TEMPFAIL); + } if (chdir("/") < 0) + { syserr("openmailer: cannot chdir(/)"); + exit(EX_TEMPFAIL); + } } /* reset user id */ @@ -1926,29 +2082,48 @@ new_ruid = DefUid; if (new_euid != NO_UID) { + if (RunAsUid != 0 && new_euid != RunAsUid) + { + /* Only root can change the uid */ + syserr("openmailer: insufficient privileges to change uid"); + exit(EX_TEMPFAIL); + } + vendor_set_uid(new_euid); -#if MAILER_SETUID_METHOD == USE_SETEUID +# if MAILER_SETUID_METHOD == USE_SETEUID if (seteuid(new_euid) < 0 && suidwarn) + { syserr("openmailer: seteuid(%ld) failed", (long) new_euid); -#endif /* MAILER_SETUID_METHOD == USE_SETEUID */ -#if MAILER_SETUID_METHOD == USE_SETREUID + exit(EX_TEMPFAIL); + } +# endif /* MAILER_SETUID_METHOD == USE_SETEUID */ +# if MAILER_SETUID_METHOD == USE_SETREUID if (setreuid(new_ruid, new_euid) < 0 && suidwarn) + { syserr("openmailer: setreuid(%ld, %ld) failed", (long) new_ruid, (long) new_euid); -#endif /* MAILER_SETUID_METHOD == USE_SETREUID */ -#if MAILER_SETUID_METHOD == USE_SETUID + exit(EX_TEMPFAIL); + } +# endif /* MAILER_SETUID_METHOD == USE_SETREUID */ +# if MAILER_SETUID_METHOD == USE_SETUID if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn) + { syserr("openmailer: setuid(%ld) failed", (long) new_euid); -#endif /* MAILER_SETUID_METHOD == USE_SETUID */ + exit(EX_TEMPFAIL); + } +# endif /* MAILER_SETUID_METHOD == USE_SETUID */ } else if (new_ruid != NO_UID) { vendor_set_uid(new_ruid); if (setuid(new_ruid) < 0 && suidwarn) + { syserr("openmailer: setuid(%ld) failed", (long) new_ruid); + exit(EX_TEMPFAIL); + } } if (tTd(11, 2)) @@ -2092,23 +2267,248 @@ #if SMTP if (clever && mci->mci_state != MCIS_CLOSED) { - static u_short again = 0; -# define ONLY_HELO_B 0x04 -# define ONLY_HELO bitset(ONLY_HELO_B, again) -# define SET_HELO again |= ONLY_HELO_B -# define CLR_HELO again &= ~ONLY_HELO_B +# if SASL && SFIO +# define DONE_AUTH(f) bitset(MCIF_AUTHACT, f) +# endif /* SASL && SFIO */ +# if STARTTLS +# define DONE_STARTTLS(f) bitset(MCIF_TLSACT, f) +# endif /* STARTTLS */ +# define ONLY_HELO(f) bitset(MCIF_ONLY_EHLO, f) +# define SET_HELO(f) f |= MCIF_ONLY_EHLO +# define CLR_HELO(f) f &= ~MCIF_ONLY_EHLO + +# if STARTTLS || (SASL && SFIO) +reconnect: /* after switching to an authenticated connection */ +# endif /* STARTTLS || (SASL && SFIO) */ # if SASL mci->mci_saslcap = NULL; # endif /* SASL */ - smtpinit(m, mci, e, ONLY_HELO); - CLR_HELO; + smtpinit(m, mci, e, ONLY_HELO(mci->mci_flags)); + CLR_HELO(mci->mci_flags); + +# if STARTTLS + /* first TLS then AUTH to provide a security layer */ + if (mci->mci_state != MCIS_CLOSED && + !DONE_STARTTLS(mci->mci_flags)) + { + int olderrors; + int dotpos; + bool usetls; + bool saveQuickAbort = QuickAbort; + bool saveSuprErrs = SuprErrs; + char *host = NULL; +# if _FFR_TLS_CLT1 + char *p; +# endif /* _FFR_TLS_CLT1 */ + char *srvname; + extern SOCKADDR CurHostAddr; + + rcode = EX_OK; + usetls = bitset(MCIF_TLS, mci->mci_flags); +# if _FFR_TLS_CLT1 + if (usetls && + (p = macvalue(macid("{client_flags}", NULL), e)) + != NULL) + { + for (; *p != '\0'; p++) + { + /* look for just this one flag */ + if (*p == D_CLTNOTLS) + { + usetls = FALSE; + break; + } + } + } +# endif /* _FFR_TLS_CLT1 */ + if (mci->mci_host != NULL) + { + srvname = mci->mci_host; + dotpos = strlen(srvname) - 1; + if (dotpos >= 0) + { + if (srvname[dotpos] == '.') + srvname[dotpos] = '\0'; + else + dotpos = -1; + } + } + else + { + srvname = ""; + dotpos = -1; + } + define(macid("{server_name}", NULL), + newstr(srvname), e); + if (CurHostAddr.sa.sa_family != 0) + define(macid("{server_addr}", NULL), + newstr(anynet_ntoa(&CurHostAddr)), e); + else + define(macid("{server_addr}", NULL), NULL, e); + if (usetls) + { + host = macvalue(macid("{server_name}", NULL), + e); +# if _FFR_TLS_O_T + olderrors = Errors; + QuickAbort = FALSE; + SuprErrs = TRUE; + if (rscheck("try_tls", srvname, NULL, + e, TRUE, FALSE, 8, host) != EX_OK + || Errors > olderrors) + usetls = FALSE; + SuprErrs = saveSuprErrs; + QuickAbort = saveQuickAbort; +# endif /* _FFR_TLS_O_T */ + } + + /* undo change of srvname */ + if (dotpos >= 0) + srvname[dotpos] = '.'; + if (usetls) + { + if ((rcode = starttls(m, mci, e)) == EX_OK) + { + /* start again without STARTTLS */ + mci->mci_flags |= MCIF_TLSACT; + } + else + { + char *s; + + /* + ** TLS negotation failed, what to do? + ** fall back to unencrypted connection + ** or abort? How to decide? + ** set a macro and call a ruleset. + */ + mci->mci_flags &= ~MCIF_TLS; + switch (rcode) + { + case EX_TEMPFAIL: + s = "TEMP"; + break; + case EX_USAGE: + s = "USAGE"; + break; + case EX_PROTOCOL: + s = "PROTOCOL"; + break; + case EX_SOFTWARE: + s = "SOFTWARE"; + break; + + /* everything else is a failure */ + default: + s = "FAILURE"; + rcode = EX_TEMPFAIL; + } + define(macid("{verify}", NULL), + newstr(s), e); + } + } + else if (mci->mci_ssl != NULL) + { + /* active TLS connection, use that data */ + (void) tls_get_info(mci->mci_ssl, e, FALSE, + mci->mci_host, FALSE); + } + else + define(macid("{verify}", NULL), "NONE", e); + olderrors = Errors; + QuickAbort = FALSE; + SuprErrs = TRUE; + + /* + ** rcode == EX_SOFTWARE is special: + ** the TLS negotation failed + ** we have to drop the connection no matter what + ** However, we call tls_server to give it the chance + ** to log the problem and return an appropriate + ** error code. + */ + if (rscheck("tls_server", + macvalue(macid("{verify}", NULL), e), + NULL, e, TRUE, TRUE, 6, host) != EX_OK || + Errors > olderrors || + rcode == EX_SOFTWARE) + { + char enhsc[ENHSCLEN]; + extern char MsgBuf[]; + + if (ISSMTPCODE(MsgBuf) && + extenhsc(MsgBuf + 4, ' ', enhsc) > 0) + { + p = newstr(MsgBuf); + } + else + { + p = "403 4.7.0 server not authenticated."; + (void) strlcpy(enhsc, "4.7.0", + sizeof enhsc); + } + SuprErrs = saveSuprErrs; + QuickAbort = saveQuickAbort; + + if (rcode == EX_SOFTWARE) + { + /* drop the connection */ + mci->mci_state = MCIS_QUITING; + if (mci->mci_in != NULL) + { + (void) fclose(mci->mci_in); + mci->mci_in = NULL; + } + mci->mci_flags &= ~MCIF_TLSACT; + (void) endmailer(mci, e, pv); + } + else + { + /* abort transfer */ + smtpquit(m, mci, e); + } + + /* avoid bogus error msg */ + mci->mci_errno = 0; + + /* temp or permanent failure? */ + rcode = (*p == '4') ? EX_TEMPFAIL + : EX_UNAVAILABLE; + mci_setstat(mci, rcode, newstr(enhsc), p); + + /* + ** hack to get the error message into + ** the envelope (done in giveresponse()) + */ + (void) strlcpy(SmtpError, p, sizeof SmtpError); + } + QuickAbort = saveQuickAbort; + SuprErrs = saveSuprErrs; + if (DONE_STARTTLS(mci->mci_flags) && + mci->mci_state != MCIS_CLOSED) + { + SET_HELO(mci->mci_flags); + mci->mci_flags &= ~MCIF_EXTENS; + goto reconnect; + } + } + else if (mci->mci_ssl != NULL) + { + /* active TLS connection, use that data */ + (void) tls_get_info(mci->mci_ssl, e, FALSE, + mci->mci_host, FALSE); + } +# endif /* STARTTLS */ # if SASL /* if other server supports authentication let's authenticate */ if (mci->mci_state != MCIS_CLOSED && mci->mci_saslcap != NULL && +# if SFIO + !DONE_AUTH(mci->mci_flags) && +# endif /* SFIO */ SASLInfo != NULL) { /* @@ -2117,6 +2517,49 @@ */ if (smtpauth(m, mci, e) == EX_OK) { +# if SFIO + int result; + sasl_ssf_t *ssf; + + /* get security strength (features) */ + result = sasl_getprop(mci->mci_conn, SASL_SSF, + (void **) &ssf); + if (LogLevel > 9) + sm_syslog(LOG_INFO, NOQID, + "SASL: outgoing connection to %.64s: mech=%.16s, bits=%d", + mci->mci_host, + macvalue(macid("{auth_type}", + NULL), e), + result == SASL_OK ? *ssf + : 0); + + /* + ** only switch to encrypted connection + ** if a security layer has been negotiated + */ + if (result == SASL_OK && *ssf > 0) + { + /* + ** convert sfio stuff to use SASL + ** check return values + ** if the call fails, + ** fall back to unencrypted version + ** unless some cf option requires + ** encryption then the connection must + ** be aborted + */ + if (sfdcsasl(mci->mci_in, mci->mci_out, + mci->mci_conn) == 0) + { + SET_HELO(mci->mci_flags); + mci->mci_flags &= ~MCIF_EXTENS; + mci->mci_flags |= MCIF_AUTHACT; + goto reconnect; + } + syserr("SASL TLS switch failed in client"); + } + /* else? XXX */ +# endif /* SFIO */ mci->mci_flags |= MCIF_AUTHACT; } @@ -2163,7 +2606,7 @@ rcode = mci->mci_exitstat; errno = mci->mci_errno; #if NAMED_BIND - h_errno = mci->mci_herrno; + SM_SET_H_ERRNO(mci->mci_herrno); #endif /* NAMED_BIND */ if (rcode == EX_OK) { @@ -2194,6 +2637,18 @@ /* get the exit status */ rcode = endmailer(mci, e, pv); + if (rcode == EX_TEMPFAIL && + SmtpError[0] == '\0') + { + /* + ** Need an e_message for mailq display. + ** We set SmtpError as + */ + + snprintf(SmtpError, sizeof SmtpError, + "%s mailer (%s) exited with EX_TEMPFAIL", + m->m_name, m->m_mailer); + } } else #if SMTP @@ -2210,16 +2665,34 @@ /* send the recipient list */ tobuf[0] = '\0'; + for (to = tochain; to != NULL; to = to->q_tchain) { e->e_to = to->q_paddr; +#if !_FFR_DYNAMIC_TOBUF if (strlen(to->q_paddr) + (t - tobuf) + 2 > sizeof tobuf) { /* not enough room */ continue; } +#endif /* !_FFR_DYNAMIC_TOBUF */ +# if STARTTLS +# if _FFR_TLS_RCPT + i = rscheck("tls_rcpt", to->q_user, NULL, e, + TRUE, TRUE, 4, mci->mci_host); + if (i != EX_OK) + { + /* avoid bogus error msg */ + errno = 0; + markfailure(e, to, mci, i, FALSE); + giveresponse(i, to->q_status, m, + mci, ctladdr, xstart, e); + continue; + } +# endif /* _FFR_TLS_RCPT */ +# endif /* STARTTLS */ if ((i = smtprcpt(to, m, mci, e)) != EX_OK) { @@ -2306,6 +2779,10 @@ rcode = smtpgetstat(m, mci, e); if (rcode == EX_OK) { +#if _FFR_DYNAMIC_TOBUF + (void) strlcat(tobuf, ",", tobufsize); + (void) strlcat(tobuf, to->q_paddr, tobufsize); +#else /* _FFR_DYNAMIC_TOBUF */ if (strlen(to->q_paddr) + strlen(tobuf) + 2 > sizeof tobuf) { @@ -2318,6 +2795,7 @@ (void) strlcat(tobuf, to->q_paddr, sizeof tobuf); } +#endif /* _FFR_DYNAMIC_TOBUF */ anyok = TRUE; } else @@ -2353,7 +2831,7 @@ ** Checkpoint the send list every few addresses */ - if (e->e_nsent >= CheckpointInterval) + if (CheckpointInterval > 0 && e->e_nsent >= CheckpointInterval) { queueup(e, FALSE); e->e_nsent = 0; @@ -2427,6 +2905,7 @@ errno = 0; define('g', (char *) NULL, e); + e->e_to = NULL; return rcode; } @@ -2583,6 +3062,12 @@ static void endwaittimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + errno = ETIMEDOUT; longjmp(EndWaitTimeout, 1); } @@ -2598,31 +3083,36 @@ char buf[MAXLINE]; EVENT *ev = NULL; - mci_unlock_host(mci); - -#if SASL - /* shutdown SASL */ - if (bitset(MCIF_AUTHACT, mci->mci_flags)) - { - sasl_dispose(&mci->mci_conn); - mci->mci_flags &= ~MCIF_AUTHACT; - } -#endif /* SASL */ + mci_unlock_host(mci); /* close output to mailer */ if (mci->mci_out != NULL) (void) fclose(mci->mci_out); /* copy any remaining input to transcript */ - if (mci->mci_in != NULL && e->e_xfp != NULL) + if (mci->mci_in != NULL && mci->mci_state != MCIS_ERROR && + e->e_xfp != NULL) { while (sfgets(buf, sizeof buf, mci->mci_in, TimeOuts.to_quit, "Draining Input") != NULL) - /* while (fgets(buf, sizeof buf, mci->mci_in) != NULL) */ (void) fputs(buf, e->e_xfp); } +#if SASL + /* shutdown SASL */ + if (bitset(MCIF_AUTHACT, mci->mci_flags)) + { + sasl_dispose(&mci->mci_conn); + mci->mci_flags &= ~MCIF_AUTHACT; + } +#endif /* SASL */ + +#if STARTTLS + /* shutdown TLS */ + (void) endtlsclt(mci); +#endif /* STARTTLS */ + /* now close the input */ if (mci->mci_in != NULL) (void) fclose(mci->mci_in); @@ -2643,9 +3133,9 @@ endwaittimeout, 0); else { - syserr("endmailer %s: wait timeout (%d)", + syserr("endmailer %s: wait timeout (%ld)", mci->mci_mailer->m_name, - mci->mci_mailer->m_wait); + (long) mci->mci_mailer->m_wait); return EX_TEMPFAIL; } } @@ -2912,12 +3402,12 @@ if (status != EX_OK && (status != EX_TEMPFAIL || e->e_message == NULL)) { if (e->e_message != NULL) - free(e->e_message); + sm_free(e->e_message); e->e_message = newstr(statmsg + off); } errno = 0; #if NAMED_BIND - h_errno = 0; + SM_SET_H_ERRNO(0); #endif /* NAMED_BIND */ } /* @@ -2958,6 +3448,7 @@ register char *bp; register char *p; int l; + time_t now; char buf[1024]; #if (SYSLOG_BUFSIZE) >= 256 @@ -2978,14 +3469,15 @@ } /* delay & xdelay: max 41 bytes */ + now = curtime(); snprintf(bp, SPACELEFT(buf, bp), ", delay=%s", - pintvl(curtime() - e->e_ctime, TRUE)); + pintvl(now - e->e_ctime, TRUE)); bp += strlen(bp); if (xstart != (time_t) 0) { snprintf(bp, SPACELEFT(buf, bp), ", xdelay=%s", - pintvl(curtime() - xstart, TRUE)); + pintvl(now - xstart, TRUE)); bp += strlen(bp); } @@ -3067,16 +3559,32 @@ p = e->e_to == NULL ? "NO-TO-LIST" : e->e_to; while (strlen(p) >= (SIZE_T) l) { - register char *q = strchr(p + l, ','); + register char *q; +#if _FFR_DYNAMIC_TOBUF + for (q = p + l; q > p; q--) + { + if (*q == ',') + break; + } + if (p == q) + break; +#else /* _FFR_DYNAMIC_TOBUF */ + q = strchr(p + l, ','); if (q == NULL) break; +#endif /* _FFR_DYNAMIC_TOBUF */ + sm_syslog(LOG_INFO, e->e_id, "to=%.*s [more]%s", - ++q - p, p, buf); + (int) (++q - p), p, buf); p = q; } +#if _FFR_DYNAMIC_TOBUF + sm_syslog(LOG_INFO, e->e_id, "to=%.*s%s", l, p, buf); +#else /* _FFR_DYNAMIC_TOBUF */ sm_syslog(LOG_INFO, e->e_id, "to=%s%s", p, buf); +#endif /* _FFR_DYNAMIC_TOBUF */ #else /* (SYSLOG_BUFSIZE) >= 256 */ @@ -3084,16 +3592,32 @@ p = e->e_to == NULL ? "NO-TO-LIST" : e->e_to; while (strlen(p) >= (SIZE_T) l) { - register char *q = strchr(p + l, ','); + register char *q; +#if _FFR_DYNAMIC_TOBUF + for (q = p + l; q > p; q--) + { + if (*q == ',') + break; + } + if (p == q) + break; +#else /* _FFR_DYNAMIC_TOBUF */ + q = strchr(p + l, ','); if (q == NULL) break; +#endif /* _FFR_DYNAMIC_TOBUF */ + sm_syslog(LOG_INFO, e->e_id, "to=%.*s [more]", - ++q - p, p); + (int) (++q - p), p); p = q; } +#if _FFR_DYNAMIC_TOBUF + sm_syslog(LOG_INFO, e->e_id, "to=%.*s", l, p); +#else /* _FFR_DYNAMIC_TOBUF */ sm_syslog(LOG_INFO, e->e_id, "to=%s", p); +#endif /* _FFR_DYNAMIC_TOBUF */ if (ctladdr != NULL) { @@ -3111,12 +3635,12 @@ } bp = buf; snprintf(bp, SPACELEFT(buf, bp), "delay=%s", - pintvl(curtime() - e->e_ctime, TRUE)); + pintvl(now - e->e_ctime, TRUE)); bp += strlen(bp); if (xstart != (time_t) 0) { snprintf(bp, SPACELEFT(buf, bp), ", xdelay=%s", - pintvl(curtime() - xstart, TRUE)); + pintvl(now - xstart, TRUE)); bp += strlen(bp); } @@ -3271,8 +3795,13 @@ e->e_dfp = fopen(df, "r"); if (e->e_dfp == NULL) - syserr("putbody: Cannot open %s for %s from %s", - df, e->e_to, e->e_from.q_paddr); + { + char *msg = "!putbody: Cannot open %s for %s from %s"; + + if (errno == ENOENT) + msg++; + syserr(msg, df, e->e_to, e->e_from.q_paddr); + } } if (e->e_dfp == NULL) { @@ -3284,6 +3813,7 @@ putline("<<< No Message Collected >>>", mci); goto endofmessage; } + if (e->e_dfino == (ino_t) 0) { struct stat stbuf; @@ -3384,7 +3914,7 @@ ostate = OS_HEAD; bp = buf; pbp = peekbuf; - while (!ferror(mci->mci_out)) + while (!ferror(mci->mci_out) && !dead) { if (pbp > peekbuf) c = *--pbp; @@ -3440,27 +3970,39 @@ (void) putc(padc, TrafficLogFile); for (xp = buf; xp < bp; xp++) - (void) putc(*xp, TrafficLogFile); + (void) putc((unsigned char) *xp, + TrafficLogFile); if (c == '\n') (void) fputs(mci->mci_mailer->m_eol, - TrafficLogFile); + TrafficLogFile); } if (padc != EOF) { if (putc(padc, mci->mci_out) == EOF) + { + dead = TRUE; continue; + } + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } pos++; } for (xp = buf; xp < bp; xp++) { - if (putc(*xp, mci->mci_out) == EOF) + if (putc((unsigned char) *xp, + mci->mci_out) == EOF) { dead = TRUE; break; } - - /* record progress for DATA timeout */ - DataProgress = TRUE; + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } } if (dead) continue; @@ -3469,6 +4011,11 @@ if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) break; + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } pos = 0; } else @@ -3478,8 +4025,6 @@ *pbp++ = c; } - /* record progress for DATA timeout */ - DataProgress = TRUE; bp = buf; /* determine next state */ @@ -3498,9 +4043,11 @@ if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) continue; - - /* record progress for DATA timeout */ - DataProgress = TRUE; + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } if (TrafficLogFile != NULL) { @@ -3544,9 +4091,19 @@ if (d == '\n' || d == EOF) { if (TrafficLogFile != NULL) - (void) putc(c, TrafficLogFile); - if (putc(c, mci->mci_out) == EOF) + (void) putc((unsigned char) c, + TrafficLogFile); + if (putc((unsigned char) c, + mci->mci_out) == EOF) + { + dead = TRUE; continue; + } + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } pos++; continue; } @@ -3554,10 +4111,15 @@ if (putc('!', mci->mci_out) == EOF || fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) + { + dead = TRUE; continue; - - /* record progress for DATA timeout */ - DataProgress = TRUE; + } + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } if (TrafficLogFile != NULL) { @@ -3576,21 +4138,33 @@ if (fputs(mci->mci_mailer->m_eol, mci->mci_out) == EOF) continue; + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } pos = 0; ostate = OS_HEAD; } else { if (TrafficLogFile != NULL) - (void) putc(c, TrafficLogFile); - if (putc(c, mci->mci_out) == EOF) + (void) putc((unsigned char) c, + TrafficLogFile); + if (putc((unsigned char) c, + mci->mci_out) == EOF) + { + dead = TRUE; continue; + } + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } pos++; ostate = OS_INLINE; } - - /* record progress for DATA timeout */ - DataProgress = TRUE; break; } } @@ -3601,18 +4175,22 @@ if (TrafficLogFile != NULL) { for (xp = buf; xp < bp; xp++) - (void) putc(*xp, TrafficLogFile); + (void) putc((unsigned char) *xp, + TrafficLogFile); } for (xp = buf; xp < bp; xp++) { - if (putc(*xp, mci->mci_out) == EOF) + if (putc((unsigned char) *xp, mci->mci_out) == + EOF) { dead = TRUE; break; } - - /* record progress for DATA timeout */ - DataProgress = TRUE; + else + { + /* record progress for DATA timeout */ + DataProgress = TRUE; + } } pos += bp - buf; } @@ -3651,7 +4229,7 @@ (void) bfrewind(e->e_dfp); /* some mailers want extra blank line at end of message */ - if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) && + if (!dead && bitnset(M_BLANKEND, mci->mci_mailer->m_flags) && buf[0] != '\0' && buf[0] != '\n') putline("", mci); @@ -3824,6 +4402,11 @@ int err; volatile int oflags = O_WRONLY|O_APPEND; + /* Reset global flags */ + RestartRequest = NULL; + ShutdownRequest = NULL; + PendingSignal = 0; + if (e->e_lockfp != NULL) (void) close(fileno(e->e_lockfp)); @@ -3840,7 +4423,8 @@ } if (TimeOuts.to_fileopen > 0) - ev = setevent(TimeOuts.to_fileopen, mailfiletimeout, 0); + ev = setevent(TimeOuts.to_fileopen, + mailfiletimeout, 0); else ev = NULL; @@ -3884,6 +4468,12 @@ { RealUserName = NULL; RealUid = mailer->m_uid; + if (RunAsUid != 0 && RealUid != RunAsUid) + { + /* Only root can change the uid */ + syserr("mailfile: insufficient privileges to change uid"); + exit(EX_TEMPFAIL); + } } else if (bitset(S_ISUID, mode)) { @@ -3911,15 +4501,34 @@ /* select a new group to run as */ if (bitnset(M_SPECIFIC_UID, mailer->m_flags)) + { RealGid = mailer->m_gid; + if (RunAsUid != 0 && + (RealGid != getgid() || + RealGid != getegid())) + { + /* Only root can change the gid */ + syserr("mailfile: insufficient privileges to change gid"); + exit(EX_TEMPFAIL); + } + } else if (bitset(S_ISGID, mode)) RealGid = stb.st_gid; - else if (ctladdr != NULL && ctladdr->q_uid != 0) - RealGid = ctladdr->q_gid; else if (ctladdr != NULL && ctladdr->q_uid == DefUid && ctladdr->q_gid == 0) + { + /* + ** Special case: This means it is an + ** alias and we should act as DefaultUser. + ** See alias()'s comments. + */ + RealGid = DefGid; + RealUserName = DefUser; + } + else if (ctladdr != NULL && ctladdr->q_uid != 0) + RealGid = ctladdr->q_gid; else if (mailer != NULL && mailer->m_gid != 0) RealGid = mailer->m_gid; else @@ -3939,8 +4548,11 @@ if (RealUserName != NULL && !DontInitGroups) { if (initgroups(RealUserName, RealGid) == -1 && suidwarn) + { syserr("mailfile: initgroups(%s, %d) failed", RealUserName, RealGid); + exit(EX_TEMPFAIL); + } } else { @@ -3948,7 +4560,10 @@ gidset[0] = RealGid; if (setgroups(1, gidset) == -1 && suidwarn) + { syserr("mailfile: setgroups() failed"); + exit(EX_TEMPFAIL); + } } /* @@ -3973,15 +4588,24 @@ dprintf("mailfile: deliver to %s\n", realfile); if (chdir("/") < 0) + { syserr("mailfile: cannot chdir(/)"); + exit(EX_CANTCREAT); + } /* now reset the group and user ids */ endpwent(); if (setgid(RealGid) < 0 && suidwarn) + { syserr("mailfile: setgid(%ld) failed", (long) RealGid); + exit(EX_TEMPFAIL); + } vendor_set_uid(RealUid); if (setuid(RealUid) < 0 && suidwarn) + { syserr("mailfile: setuid(%ld) failed", (long) RealUid); + exit(EX_TEMPFAIL); + } if (tTd(11, 2)) dprintf("mailfile: running as r/euid=%d/%d, r/egid=%d/%d\n", @@ -4114,7 +4738,7 @@ (*e->e_puthdr)(&mcibuf, e->e_header, e, M87F_OUTER); (*e->e_putbody)(&mcibuf, e, NULL); putline("\n", &mcibuf); - if (fflush(f) < 0 || + if (fflush(f) != 0 || (SuperSafe && fsync(fileno(f)) < 0) || ferror(f)) { @@ -4164,6 +4788,13 @@ static void mailfiletimeout() { + /* + ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD + ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE + ** DOING. + */ + + errno = ETIMEDOUT; longjmp(CtxMailfileTimeout, 1); } /* @@ -4199,6 +4830,7 @@ int len; int nmx; int hl; + time_t now; char *hp; char *endp; int oldoptions = _res.options; @@ -4210,17 +4842,19 @@ dprintf("hostsignature(%s)\n", host); /* - ** If local delivery, just return a constant. + ** If local delivery (and not remote), just return a constant. */ - if (bitnset(M_LOCALMAILER, m->m_flags)) + p = m->m_mailer; + if (bitnset(M_LOCALMAILER, m->m_flags) && + strcmp(p, "[IPC]") != 0 && + strcmp(p, "[TCP]") != 0) return "localhost"; /* ** Check to see if this uses IPC -- if not, it can't have MX records. */ - p = m->m_mailer; if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) { @@ -4257,6 +4891,7 @@ if (ConfigLevel < 2) _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ + now = curtime(); for (hp = host; hp != NULL; hp = endp) { #if NETINET6 @@ -4296,7 +4931,7 @@ mci = mci_get(hp, m); mci->mci_errno = errno; mci->mci_herrno = h_errno; - mci->mci_lastuse = curtime(); + mci->mci_lastuse = now; if (rcode == EX_NOHOST) mci_setstat(mci, rcode, "5.1.2", "550 Host unknown"); @@ -4327,7 +4962,7 @@ if (s->s_hostsig != NULL) { (void) strlcpy(p, s->s_hostsig, len); - free(s->s_hostsig); + sm_free(s->s_hostsig); s->s_hostsig = p; hl = strlen(p); p += hl; @@ -4496,4 +5131,206 @@ } #if SMTP +# if STARTTLS +static SSL_CTX *clt_ctx = NULL; + + /* +** INITCLTTLS -- initialize client side TLS +** +** Parameters: +** none. +** +** Returns: +** succeeded? +*/ + +bool +initclttls() +{ + if (clt_ctx != NULL) + return TRUE; /* already done */ + return inittls(&clt_ctx, TLS_I_CLT, FALSE, CltCERTfile, Cltkeyfile, + CACERTpath, CACERTfile, DHParams); +} + + /* +** STARTTLS -- try to start secure connection (client side) +** +** Parameters: +** m -- the mailer. +** mci -- the mailer connection info. +** e -- the envelope. +** +** Returns: +** success? +** (maybe this should be some other code than EX_ +** that denotes which stage failed.) +*/ + +static int +starttls(m, mci, e) + MAILER *m; + MCI *mci; + ENVELOPE *e; +{ + int smtpresult; + int result = 0; + int rfd, wfd; + SSL *clt_ssl = NULL; + + if (clt_ctx == NULL && !initclttls()) + return EX_TEMPFAIL; + smtpmessage("STARTTLS", m, mci); + + /* get the reply */ + smtpresult = reply(m, mci, e, TimeOuts.to_datafinal, NULL, NULL); + /* which timeout? XXX */ + + /* check return code from server */ + if (smtpresult == 454) + return EX_TEMPFAIL; + if (smtpresult == 501) + return EX_USAGE; + if (smtpresult == -1) + return smtpresult; + if (smtpresult != 220) + return EX_PROTOCOL; + + if (LogLevel > 13) + sm_syslog(LOG_INFO, e->e_id, "TLS: start client"); + + /* start connection */ + if ((clt_ssl = SSL_new(clt_ctx)) == NULL) + { + if (LogLevel > 5) + { + sm_syslog(LOG_ERR, e->e_id, + "TLS: error: client: SSL_new failed"); + if (LogLevel > 9) + tlslogerr(); + } + return EX_SOFTWARE; + } + + rfd = fileno(mci->mci_in); + wfd = fileno(mci->mci_out); + + /* SSL_clear(clt_ssl); ? */ + if (rfd < 0 || wfd < 0 || + (result = SSL_set_rfd(clt_ssl, rfd)) <= 0 || + (result = SSL_set_wfd(clt_ssl, wfd)) <= 0) + { + if (LogLevel > 5) + { + sm_syslog(LOG_ERR, e->e_id, + "TLS: error: SSL_set_xfd failed=%d", result); + if (LogLevel > 9) + tlslogerr(); + } + return EX_SOFTWARE; + } + SSL_set_connect_state(clt_ssl); + if ((result = SSL_connect(clt_ssl)) <= 0) + { + int i; + + /* what to do in this case? */ + i = SSL_get_error(clt_ssl, result); + if (LogLevel > 5) + { + sm_syslog(LOG_ERR, e->e_id, + "TLS: error: SSL_connect failed=%d (%d)", + result, i); + if (LogLevel > 9) + tlslogerr(); + } + SSL_free(clt_ssl); + clt_ssl = NULL; + return EX_SOFTWARE; + } + mci->mci_ssl = clt_ssl; + result = tls_get_info(clt_ssl, e, FALSE, mci->mci_host, TRUE); + + /* switch to use SSL... */ +#if SFIO + if (sfdctls(mci->mci_in, mci->mci_out, mci->mci_ssl) == 0) + return EX_OK; +#else /* SFIO */ +# if _FFR_TLS_TOREK + if (sfdctls(&mci->mci_in, &mci->mci_out, mci->mci_ssl) == 0) + return EX_OK; +# endif /* _FFR_TLS_TOREK */ +#endif /* SFIO */ + + /* failure */ + SSL_free(clt_ssl); + clt_ssl = NULL; + return EX_SOFTWARE; +} + + /* +** ENDTLSCLT -- shutdown secure connection (client side) +** +** Parameters: +** mci -- the mailer connection info. +** +** Returns: +** success? +*/ +int +endtlsclt(mci) + MCI *mci; +{ + int r; + + if (!bitset(MCIF_TLSACT, mci->mci_flags)) + return EX_OK; + r = endtls(mci->mci_ssl, "client"); + mci->mci_flags &= ~MCIF_TLSACT; + return r; +} + /* +** ENDTLS -- shutdown secure connection +** +** Parameters: +** ssl -- SSL connection information. +** side -- srv/clt (for logging). +** +** Returns: +** success? +*/ + +int +endtls(ssl, side) + SSL *ssl; + char *side; +{ + int ret = EX_OK; + + if (ssl != NULL) + { + int r; + + if ((r = SSL_shutdown(ssl)) < 0) + { + if (LogLevel > 11) + sm_syslog(LOG_WARNING, NOQID, + "SSL_shutdown %s failed: %d", + side, r); + ret = EX_SOFTWARE; + } + else if (r == 0) + { + if (LogLevel > 13) + sm_syslog(LOG_WARNING, NOQID, + "SSL_shutdown %s not done", + side); + ret = EX_SOFTWARE; + } + SSL_free(ssl); + ssl = NULL; + } + return ret; +} +# endif /* STARTTLS */ #endif /* SMTP */ Index: gnu/usr.sbin/sendmail/sendmail/domain.c =================================================================== RCS file: /cvs/src/gnu/usr.sbin/sendmail/sendmail/domain.c,v retrieving revision 1.1.1.1 retrieving revision 1.3 diff -u -r1.1.1.1 -r1.3 --- gnu/usr.sbin/sendmail/sendmail/domain.c 2000/04/02 19:05:45 1.1.1.1 +++ gnu/usr.sbin/sendmail/sendmail/domain.c 2001/02/28 02:43:54 1.3 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers. + * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. * All rights reserved. * Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved. * Copyright (c) 1988, 1993 @@ -15,12 +15,13 @@ #ifndef lint # if NAMED_BIND -static char id[] = "@(#)$Sendmail: domain.c,v 8.114 2000/02/01 05:49:56 gshapiro Exp $ (with name server)"; +static char id[] = "@(#)$Sendmail: domain.c,v 8.114.6.1.2.8 2001/02/12 21:40:19 gshapiro Exp $ (with name server)"; # else /* NAMED_BIND */ -static char id[] = "@(#)$Sendmail: domain.c,v 8.114 2000/02/01 05:49:56 gshapiro Exp $ (without name server)"; +static char id[] = "@(#)$Sendmail: domain.c,v 8.114.6.1.2.8 2001/02/12 21:40:19 gshapiro Exp $ (without name server)"; # endif /* NAMED_BIND */ #endif /* ! lint */ + #if NAMED_BIND # include @@ -227,12 +228,16 @@ hp = (HEADER *)&answer; cp = (u_char *)&answer + HFIXEDSZ; eom = (u_char *)&answer + n; - for (qdcount = ntohs(hp->qdcount); qdcount--; cp += n + QFIXEDSZ) + for (qdcount = ntohs((u_short)hp->qdcount); + qdcount--; + cp += n + QFIXEDSZ) + { if ((n = dn_skipname(cp, eom)) < 0) goto punt; + } buflen = sizeof(MXHostBuf) - 1; bp = MXHostBuf; - ancount = ntohs(hp->ancount); + ancount = ntohs((u_short)hp->ancount); while (--ancount >= 0 && cp < eom && nmx < MAXMXHOSTS - 1) { if ((n = dn_expand((u_char *)&answer, @@ -333,14 +338,10 @@ if (nmx == 0) { punt: - if (seenlocal && - (!TryNullMXList || - (sm_gethostbyname(host, AF_INET) == NULL -# if NETINET6 - && sm_gethostbyname(host, AF_INET6) == NULL -# endif /* NETINET6 */ - ))) + if (seenlocal) { + struct hostent *h = NULL; + /* ** If we have deleted all MX entries, this is ** an error -- we should NEVER send to a host that @@ -353,10 +354,49 @@ ** bad idea, but it's up to you.... */ - *rcode = EX_CONFIG; - syserr("MX list for %s points back to %s", - host, MyHostName); - return -1; + if (TryNullMXList) + { + SM_SET_H_ERRNO(0); + errno = 0; + h = sm_gethostbyname(host, AF_INET); + if (h == NULL) + { + if (errno == ETIMEDOUT || + h_errno == TRY_AGAIN || + (errno == ECONNREFUSED && + UseNameServer)) + { + *rcode = EX_TEMPFAIL; + return -1; + } +# if NETINET6 + SM_SET_H_ERRNO(0); + errno = 0; + h = sm_gethostbyname(host, AF_INET6); + if (h == NULL && + (errno == ETIMEDOUT || + h_errno == TRY_AGAIN || + (errno == ECONNREFUSED && + UseNameServer))) + { + *rcode = EX_TEMPFAIL; + return -1; + } +# endif /* NETINET6 */ + } + } + + if (h == NULL) + { + *rcode = EX_CONFIG; + syserr("MX list for %s points back to %s", + host, MyHostName); + return -1; + } +# if _FFR_FREEHOSTENT && NETINET6 + freehostent(h); + hp = NULL; +# endif /* _FFR_FREEHOSTENT && NETINET6 */ } if (strlen(host) >= (SIZE_T) sizeof MXHostBuf) { @@ -604,6 +644,8 @@ return FALSE; } + *statp = EX_OK; + /* ** Initialize domain search list. If there is at least one ** dot in the name, search the unmodified name first so we @@ -694,6 +736,7 @@ qtype == T_A ? "A" : qtype == T_MX ? "MX" : "???"); + errno = 0; ret = res_querydomain(host, *dp, C_IN, qtype, answer.qb2, sizeof(answer.qb2)); if (ret <= 0) @@ -704,15 +747,19 @@ if (errno == ECONNREFUSED || h_errno == TRY_AGAIN) { - /* the name server seems to be down */ - h_errno = TRY_AGAIN; + /* + ** the name server seems to be down or + ** broken. + */ + + SM_SET_H_ERRNO(TRY_AGAIN); *statp = EX_TEMPFAIL; /* ** If the ANY query is larger than the ** UDP packet size, the resolver will ** fall back to TCP. However, some - ** misconfigured firewalls black 53/TCP + ** misconfigured firewalls block 53/TCP ** so the ANY lookup fails whereas an MX ** or A record might work. Therefore, ** don't fail on ANY queries. @@ -721,8 +768,27 @@ ** the cache so this isn't dangerous. */ +#if _FFR_WORKAROUND_BROKEN_NAMESERVERS + if (WorkAroundBrokenAAAA) + { + /* + ** Only return if not TRY_AGAIN as an + ** attempt with a different qtype may + ** succeed (res_querydomain() calls + ** res_query() calls res_send() which + ** sets errno to ETIMEDOUT if the + **