-----BEGIN PRIVACY-ENHANCED MESSAGE----- Proc-Type: 4,MIC-CLEAR Content-Domain: RFC822 Originator-Certificate: MIICozCCAgwCAREwDQYJKoZIhvcNAQECBQAwgYYxC zAJBgNVBAYTAlVTMSswKQYDVQQKEyJEZWZlbnNlIEluZm9ybWF0aW9uIFN5c3Rlb XMgQWdlbmN5MTAwLgYDVQQLEydDZW50ZXIgZm9yIEluZm9ybWF0aW9uIFN5c3Rlb XMgU2VjdXJpdHkxGDAWBgNVBAsTD0NvdW50ZXJtZWFzdXJlczAeFw05MzEyMDkxO DU5MTZaFw05NTEyMDkxODU5MTZaMIGxMQswCQYDVQQGEwJVUzErMCkGA1UEChMiR GVmZW5zZSBJbmZvcm1hdGlvbiBTeXN0ZW1zIEFnZW5jeTEwMC4GA1UECxMnQ2Vud GVyIGZvciBJbmZvcm1hdGlvbiBTeXN0ZW1zIFNlY3VyaXR5MRgwFgYDVQQLEw9Db 3VudGVybWVhc3VyZXMxEzARBgNVBAsTCk9wZXJhdGlvbnMxFDASBgNVBAMTC1Bld GUgSGFtbWVzMIGaMAoGBFUIAQECAgQAA4GLADCBhwKBgQDFFJkcaDOuS+6Ai2vmT bwY6JRbhdzPsl6X60hnXruOw2WvrAhc8BTFB+id75m3M55i+Th6MxWH20QHyQq5u yVghOu/s37OxIrj7irNPjtUdPv8b2m4hNGEW53QH6GmXkxLmgLzOhookpoYPC+uw 2MzibDnleVI50d2m//XsWs7hwIBAzANBgkqhkiG9w0BAQIFAAOBgQDHH6CmBoyWU zPlqVnEWYKIBsifqdTJzkKfnoST7NDRIakUP49FP86Cyy1+2AKpUCWaxjq+wGHCH RCNFCCrOwdC9z8XwJal/c69ml6eLRhOoX77ANndpU9E5+eHxP+6Ute6lc63K7+Lz 5xOULjmgaMmKDkTXveVcQO6R2CTY37vcA== Issuer-Certificate: MIICNTCCAZ4CASIwDQYJKoZIhvcNAQECBQAwRDELMAkGA 1UEBhMCVVMxCzAJBgNVBAgTAk1EMSgwJgYDVQQKEx9UcnVzdGVkIEluZm9ybWF0a W9uIFN5c3RlbXMgUENBMB4XDTk0MDIyNTE0NDkxMloXDTk0MDMwNzE0NDkxMlowg YYxCzAJBgNVBAYTAlVTMSswKQYDVQQKEyJEZWZlbnNlIEluZm9ybWF0aW9uIFN5c 3RlbXMgQWdlbmN5MTAwLgYDVQQLEydDZW50ZXIgZm9yIEluZm9ybWF0aW9uIFN5c 3RlbXMgU2VjdXJpdHkxGDAWBgNVBAsTD0NvdW50ZXJtZWFzdXJlczCBmjAKBgRVC AEBAgIEAAOBiwAwgYcCgYEA19l6BN7iTGYEU61qJETIjBh3iAeHzoL8sZ5KwFRZD S/a1KnYlD1zJHR/KeQCOBWW2HzX43TFLCNGU7UD9i6m8AymLe5IJf/bGh0Rne7Jd Q1GAOLw7/J4hE57IMbGETZpzeU1D9IYxiERRNio/oa422lUlS9JZHLA5jaPNcUrX P8CAQMwDQYJKoZIhvcNAQECBQADgYEApkliqAdudoOxvOFmQkOZbSgtlpn61VcNC R7azDNJa2ulevaebptwSTs2OvMeuR/J0Ez4TC7XrJXLVjI5huRAqc+EWGRpZYRMa CARZyE7gGYjUqS7DIQazfskeWiB8zheyW5tCVn+jnB09AZXtgbM6qRjyqrmSdCpg CtfgazIKqI= Issuer-Certificate: MIIB8jCCAVsCAQEwDQYJKoZIhvcNAQECBQAwRDELMAkGA 1UEBhMCVVMxCzAJBgNVBAgTAk1EMSgwJgYDVQQKEx9UcnVzdGVkIEluZm9ybWF0a W9uIFN5c3RlbXMgUENBMB4XDTkzMDUyODE3MTEyN1oXDTk1MDUyODE3MTEyN1owR DELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1EMSgwJgYDVQQKEx9UcnVzdGVkIEluZ m9ybWF0aW9uIFN5c3RlbXMgUENBMIGaMAoGBFUIAQECAgQAA4GLADCBhwKBgQDbL xaRlS3u54yyRgVDI5dcE9nlasL8fJqOGlyo7xH2FZnr3kUfsFj7OGiYsr6UbvqwK nyfMIRUrXDUa64leGmft3SK27psDUHOynRSCc40d/HrDf810U5tnTamBKUIMqivK 4GoL0tMRA1eX6hALAvLLgK1HbnwZAo6GqQGW8CIJQIBAzANBgkqhkiG9w0BAQIFA AOBgQDBp5aC6oV6IuFi8JCctq57bew604HHNllgjjp7zdXafq6jctRg2g91k/yFW h19bJC/tNrb0WVwuZOs5L/FToPMNIIHzaW/YSROBmyhTDYaKHZGj0P1+iNjMbHt9 dm1QEHGIfKgBwFidItnOa74DfkXdijlPRnr/+E2Ib6PM+hEfQ== MIC-Info: RSA-MD5,RSA,cC2+IYz3zix6+gD3RtyWoQOWSNbhawjlG6C/bdHtmQp DASEq+CuUJvf052Qc+dDIUpnSjim9rrEyJXB5kmrTi1FnggnguXbO7eegOByp70A fExs/bj50Uf5xo6oP842gHpmGLrP0vUGQI+OY6/S2INfhnLNkxhkK9yUcmk2JfxA = <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Automated Systems Security Incident Support Team _____ ___ ___ _____ ___ _____ | / /\ / \ / \ | / \ | | / Integritas / \ \___ \___ | \___ | | < et /____\ \ \ | \ | | \ Celeritas / \ \___/ \___/ __|__ \___/ | |_____\ <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Bulletin 95-03 Release date: 2 February, 1995, 3:45 PM EST (GMT -4) SUBJECT: Unix /bin/mail Vulnerabilities. SUMMARY: Vulnerabilities in /bin/mail have been widely publicized and discussed on various Internet discussion forums, and automated exploit scripts and related information are available from several sources. These scripts have been used in numerous Internet attacks. BACKGROUND: The /bin/mail utility on several Unix versions based on BSD 4.3 Unix contains a security vulnerability. The vulnerability is the result of race conditions that exist during the delivery of e-mail messages to local users. The following is a list of systems with a vulnerability status for each. If your vendor's name is not listed, please contact the vendor or ASSIST for more information. Vendor or Source Status ---------------- ------------ Apple Computer, Inc. Not vulnerable Berkeley SW Design, Inc. (BSDI) Not vulnerable Cray Research, Inc. Not vulnerable Data General Corp. Not vulnerable Digital Equipment Corp. Vulnerable FreeBSD Not vulnerable Harris Not vulnerable IBM Not vulnerable NetBSD Not vulnerable NeXT, Inc. Not vulnerable Pyramid Not vulnerable The Santa Cruz Operation (SCO) Vulnerable Solbourne (Grumman) Vulnerable Sun Microsystems, Inc. SunOS 4.x vulnerable Solaris 2.x not vulnerable IMPACT: These race conditions will allow local users (users that have an account on the system) to create or modify files on the system and obtain privileged access to the system. RECOMMENDED SOLUTION: Obtain and install the appropriate patch from the vendor or replace /bin/mail with mail.local. Patch information: DEC The /bin/mail patch is a part of a comprehensive Security Enhanced Kit that addresses other security problems as well. This kit was released on May 17, 1994 and was described in DEC Security Advisory #0505. OSF/1 users should upgrade to a minimum of version 2.0 and install Security Enhanced Kit CSCPAT_4061 v1.0. Ultrix users should upgrade to at least version 4.4 and install Security Enhanced Kit CSCPAT_4060 v1.0. Both kits are available from your Digital support channel or electronically by request via DSNlink. SCO Vulnerabilities in SCO's /bin/mail utility are removed by applying SCO's Support Level Supplement (SLS) uod392a. It is available via anonymous FTP from ftp.sco.com in the /SLS directory: Description Filename MD5 Checksum ------------ ------------- -------------------------------- Disk image uod392a.Z 2c26669d89f61174f751774115f367a5 Cover letter uod392a.ltr.Z 52db39424d5d23576e065af2b80aee49 Solbourne Grumman System Support Corporation now performs all Solbourne software and hardware support. Please contact them for further information: E-mail: support@nts.gssc.com Phone: 1-800-447-2861 FTP: ftp.nts.gssc.com Sun Sun has made patches available to remove vulnerabilities in /bin/mail. These patches will be updated in the near future to remove additional vulnerabilities that have recently been identified, however ASSIST recommends installing the available patches as soon as possible to correct problems currently being exploited. The availability of the new patches will be announced when they are released. The patches can be obtained from your local Sun Answer Center or through anonymous FTP from sunsolve1.sun.com in the /pub/patches directory: SunOS Filename MD5 Checksum ------- --------------- -------------------------------- 4.1.x 100224-13.tar.Z 90a507017a1a40c4622b3f1f00ce5d2d 4.1.3U1 101436-08.tar.Z 0e64560edc61eb4b3da81a932e8b11e1 Replacing /bin/mail with mail.local. For sites unable to obtain a vendor patch for a vulnerable version of /bin/mail, a replacement package called mail.local has been developed and made freely available on the Internet. The /bin/mail program is relatively complex software, serving both as a mail delivery agent and a user interface, allowing users to send and read E-mail messages. The mail.local package was written to perform only one task: the delivery of mail to local users. It is comparatively small, and the code has been examined carefully by experts in the security community. Although the current version of mail.local is not a perfect solution, it addresses the vulnerabilities currently being exploited in /bin/mail. The current version of mail.local has been tested on SunOS 4.1 and Ultrix 4.X systems. Mail.local.c for BSD 4.3 systems, along with a README file containing installation instructions, can be found on the anonymous FTP servers listed below. In addition, Appendix A of this advisory contains the mail.local.c README file (from the CERT Coordination Center) and Appendix B contains mail.local.c. Location Filename -------- -------- assist.mil /pub/tools/mail.local/mail.local.c MD5 c0d64e740b42f6dc5cc54a2bc37c31b0 info.cert.org /pub/tools/mail.local/mail.local.c MD5 c0d64e740b42f6dc5cc54a2bc37c31b0 coast.cs.purdue.edu /pub/tools/unix/mail.local/mail.local.c MD5 c0d64e740b42f6dc5cc54a2bc37c31b0 ASSIST would like to thank the CERT Coordination Center and DOE CIAC for information contained in this bulletin. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ASSIST is an element of the Defense Information Systems Agency (DISA), Center for Information Systems Security (CISS), that provides service to the entire DoD community. Constituents of the DoD with questions about ASSIST or computer security security issues, can contact ASSIST using one of the methods listed below. Non-DoD organizations/institutions, contact the Forum of Incident Response and Security Teams (FIRST) (FIRST) representative. To obtain a list of FIRST member organizations and their constituencies send an email to docserver@first.org with an empty "subject" line and a message body containing the line "send first-contacts". ASSIST Information Resources: To be included in the distribution list for the ASSIST bulletins, send your Milnet (Internet) e-mail address to assist-request@assist.mil. Back issues of ASSIST bulletins, and other security related information, are available from the ASSIST BBS at 703-756-7993/1154 DSN 289-7993/1154, and through anonymous FTP from assist.mil (IP address 199.211.123.11). Note: assist.mil will only accept anonymous FTP connections from Milnet addresses that are registered with the NIC or DNS. ASSIST Contact Information: PHONE: 800-357-4231 (or 703-756-7974 DSN 289), duty hours are 06:00 to 22:30 EDT (GMT -4) Monday through Friday. During off duty hours, weekends and holidays, ASSIST can be reached via pager at 800-791- 4857. The page will be answered within 30 minutes, however if a quicker response is required, prefix the phone number with "999". ELECTRONIC MAIL: Send to assist@assist.mil. ASSIST BBS: Leave a message for the "sysop". Privacy Enhanced Mail (PEM): ASSIST uses PEM, a public key encryption tool, to digitally sign all bulletins that are distributed through e-mail. The section of seemingly random characters between the "BEGIN PRIVACY-ENHANCED MESSAGE" and "BEGIN ASSIST BULLETIN" contains machine-readable digital signature information generated by PEM, not corrupted data. PEM software for UNIX systems is available from Trusted Information Systems (TIS) at no cost, and can be obtained via anonymous FTP from ftp.tis.com (IP 192.94.214.96). Note: The TIS software is just one of several implementations of PEM currently available and additional versions are likely to be offered from other sources in the near future. Reference herein to any specific commercial product, process, or service by trade name, trademark manufacturer, or otherwise, does not constitute or imply its endorsement, recommendation, or favoring by ASSIST. The views and opinions of authors expressed herein shall not be used for advertising or product endorsement purposes. Appendix A: README File for mail.local.c /bin/mail is a setuid root program with several security vulnerabilities. If you cannot obtain a vendor-supplied replacement for /bin/mail, the CERT Coordination Center suggests using mail.local as a replacement for /bin/mail. In the early days of UNIX, /bin/mail was used to read and to send e-mail. Over the years, many users have switched to e-mail programs with better user interfaces and more features. On BSD 4.3 based UNIX systems using sendmail, /bin/mail is still being used as the local delivery agent. These systems could be at risk. Systems based on UNIX system III or system IV are not vulnerable. mail.local is a replacement for the /bin/mail program. It is only a delivery agent for sendmail and does not have a user interface. It is distributed as a C source file. For operating systems based on BSD 4.3, mail.local.c from a BSD 4.4 distribution will not compile. The version of mail.local.c in this directory was ported to BSD 4.3 by Eric Allman. It should compile and operate on most BSD 4.3 systems. It has been tested on SunOS 4.1.x and Ultrix 4.x systems. To install mail.local, edit the source file to set the _PATH_MAILDIR to the directory where users' spooled mail files are located. The default is "/var/spool/mail". SunOS % cc -Bstatic -O -o mail.local mail.local.c Ultrix % cc -O -o mail.local mail.local.c -Dultrix As root: # mv mail.local $INSTALL_DIR Substitute $INSTALL_DIR for the full pathname of the directory where mail.local will be installed. # chown root $INSTALL_DIR/mail.local # chmod 4711 $INSTALL_DIR/mail.local Edit the sendmail.cf file (in /etc or /usr/lib) search for Mlocal. On that line, replace /bin/mail with $INSTALL_DIR/mail.local. Restart the sendmail process. For versions of sendmail using frozen configuration files, it is important to refreeze the configuration file before restarting the sendmail process. Test the e-mail system. When you are satisfied that everything is working, disable the setuid root bit on the /bin/mail program. # chmod 0711 /bin/mail OR # chmod 0711 /usr/bin/mail **************************************************************************** * The CERT Coordination Center will not formally review, evaluate, or * * endorse the program described. The decision to use the program * * described is the responsibility of each user or organization and we * * encourage each organization to thoroughly evaluate this program * * before installation or use. * **************************************************************************** Appendix B: mail.local.c /*- * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static char copyright[] = "@(#) Copyright (c) 1990, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)mail.local.c 8.18 (Berkeley) 1/25/95"; #endif /* not lint */ /* * This is not intended to compile on System V derived systems * such as Solaris or HP-UX, since they use a totally different * approach to mailboxes (essentially, they have a setgid program * rather than setuid, and they rely on the ability to "give away" * files to do their work). IT IS NOT A BUG that this doesn't * compile on such architectures. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if __STDC__ #include #else #include #endif #ifndef LOCK_EX # include #endif #ifdef BSD4_4 # include "pathnames.h" #endif #ifndef __P # ifdef __STDC__ # define __P(protos) protos # else # define __P(protos) () # define const # endif #endif #ifndef __dead # if defined(__GNUC__) && (__GNUC__ < 2 || __GNUC_MINOR__ < 5) && !defined(__STRICT_ANSI__) # define __dead __volatile # else # define __dead # endif #endif #ifndef BSD4_4 # define _BSD_VA_LIST_ va_list extern char *strerror __P((int)); #endif #ifndef _PATH_LOCTMP # define _PATH_LOCTMP "/tmp/local.XXXXXX" #endif #ifndef _PATH_MAILDIR # define _PATH_MAILDIR "/var/spool/mail" #endif #ifndef S_ISREG # define S_ISREG(mode) (((mode) & _S_IFMT) == S_IFREG) #endif int eval = EX_OK; /* sysexits.h error value. */ void deliver __P((int, char *)); void e_to_sys __P((int)); __dead void err __P((const char *, ...)); void notifybiff __P((char *)); int store __P((char *)); void usage __P((void)); void vwarn __P((const char *, _BSD_VA_LIST_)); void warn __P((const char *, ...)); int main(argc, argv) int argc; char *argv[]; { struct passwd *pw; int ch, fd; uid_t uid; char *from; extern char *optarg; extern int optind; /* make sure we have some open file descriptors */ for (fd = 10; fd < 30; fd++) (void) close(fd); /* use a reasonable umask */ (void) umask(0077); #ifdef LOG_MAIL openlog("mail.local", 0, LOG_MAIL); #else openlog("mail.local", 0); #endif from = NULL; while ((ch = getopt(argc, argv, "df:r:")) != EOF) switch(ch) { case 'd': /* Backward compatible. */ break; case 'f': case 'r': /* Backward compatible. */ if (from != NULL) { warn("multiple -f options"); usage(); } from = optarg; break; case '?': default: usage(); } argc -= optind; argv += optind; if (!*argv) usage(); /* * If from not specified, use the name from getlogin() if the * uid matches, otherwise, use the name from the password file * corresponding to the uid. */ uid = getuid(); if (!from && (!(from = getlogin()) || !(pw = getpwnam(from)) || pw->pw_uid != uid)) from = (pw = getpwuid(uid)) ? pw->pw_name : "???"; /* * There is no way to distinguish the error status of one delivery * from the rest of the deliveries. So, if we failed hard on one * or more deliveries, but had no failures on any of the others, we * return a hard failure. If we failed temporarily on one or more * deliveries, we return a temporary failure regardless of the other * failures. This results in the delivery being reattempted later * at the expense of repeated failures and multiple deliveries. */ for (fd = store(from); *argv; ++argv) deliver(fd, *argv); exit(eval); } int store(from) char *from; { FILE *fp; time_t tval; int fd, eline; char line[2048]; char tmpbuf[sizeof _PATH_LOCTMP + 1]; strcpy(tmpbuf, _PATH_LOCTMP); if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL) { e_to_sys(errno); err("unable to open temporary file"); } (void)unlink(tmpbuf); (void)time(&tval); (void)fprintf(fp, "From %s %s", from, ctime(&tval)); line[0] = '\0'; for (eline = 1; fgets(line, sizeof(line), stdin);) { if (line[0] == '\n') eline = 1; else { if (eline && line[0] == 'F' && !memcmp(line, "From ", 5)) (void)putc('>', fp); eline = 0; } (void)fprintf(fp, "%s", line); if (ferror(fp)) { e_to_sys(errno); err("temporary file write error"); } } /* If message not newline terminated, need an extra. */ if (!strchr(line, '\n')) (void)putc('\n', fp); /* Output a newline; note, empty messages are allowed. */ (void)putc('\n', fp); if (fflush(fp) == EOF || ferror(fp)) { e_to_sys(errno); err("temporary file write error"); } return (fd); } void deliver(fd, name) int fd; char *name; { struct stat fsb, sb; struct passwd *pw; int mbfd, nr, nw, off; char *p; char biffmsg[100], buf[8*1024], path[MAXPATHLEN]; off_t curoff; /* * Disallow delivery to unknown names -- special mailboxes can be * handled in the sendmail aliases file. */ if (!(pw = getpwnam(name))) { if (eval != EX_TEMPFAIL) eval = EX_UNAVAILABLE; warn("unknown name: %s", name); return; } /* * Keep name reasonably short to avoid buffer overruns. * This isn't necessary on BSD because of the proper * definition of snprintf(), but it can cause problems * on other systems. * Also, clear out any bogus characters. */ if (strlen(name) > 40) name[40] = '\0'; for (p = name; *p != '\0'; p++) { if (!isascii(*p)) *p &= 0x7f; else if (!isprint(*p)) *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 * the lstat returned, but before the open. We attempt to detect * this by comparing the original stat information and information * returned by an fstat of the file descriptor returned by the open. * * NB: this is a symptom of a larger problem, that the mail spooling * directory is writeable by the wrong users. If that directory is * writeable, system security is compromised for other reasons, and * it cannot be fixed here. * * If we created the mailbox, set the owner/group. If that fails, * just return. Another process may have already opened it, so we * can't unlink it. Historically, binmail set the owner/group at * each mail delivery. We no longer do this, assuming that if the * ownership or permissions were changed there was a reason. * * XXX * open(2) should support flock'ing the file. */ tryagain: lockmbox(path); if (lstat(path, &sb)) { mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); if (mbfd == -1) { if (errno == EEXIST) goto tryagain; } else if (fchown(mbfd, pw->pw_uid, pw->pw_gid)) { e_to_sys(errno); warn("chown %u.%u: %s", pw->pw_uid, pw->pw_gid, name); unlockmbox(); return; } } else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) { e_to_sys(errno); warn("%s: irregular file", path); unlockmbox(); return; } else if (sb.st_uid != pw->pw_uid) { warn("%s: wrong ownership (%d)", path, sb.st_uid); unlockmbox(); return; } else { mbfd = open(path, O_APPEND|O_WRONLY, 0); if (mbfd != -1 && (fstat(mbfd, &fsb) || fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode) || sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino || sb.st_uid != fsb.st_uid)) { warn("%s: file changed after open", path); (void)close(mbfd); unlockmbox(); return; } } if (mbfd == -1) { e_to_sys(errno); warn("%s: %s", path, strerror(errno)); unlockmbox(); return; } /* Wait until we can get a lock on the file. */ if (flock(mbfd, LOCK_EX)) { e_to_sys(errno); warn("%s: %s", path, strerror(errno)); unlockmbox(); goto err1; } /* Get the starting offset of the new message for biff. */ curoff = lseek(mbfd, (off_t)0, SEEK_END); (void)snprintf(biffmsg, sizeof(biffmsg), sizeof curoff > sizeof(long) ? "%s@%qd\n" : "%s@%ld\n", name, curoff); /* Copy the message into the file. */ if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1) { e_to_sys(errno); warn("temporary file: %s", strerror(errno)); goto err1; } while ((nr = read(fd, buf, sizeof(buf))) > 0) for (off = 0; off < nr; off += nw) if ((nw = write(mbfd, buf + off, nr - off)) < 0) { e_to_sys(errno); warn("%s: %s", path, strerror(errno)); goto err2;; } if (nr < 0) { e_to_sys(errno); warn("temporary file: %s", strerror(errno)); goto err2;; } /* Flush to disk, don't wait for update. */ if (fsync(mbfd)) { e_to_sys(errno); warn("%s: %s", path, strerror(errno)); err2: (void)ftruncate(mbfd, curoff); err1: (void)close(mbfd); unlockmbox(); return; } /* Close and check -- NFS doesn't write until the close. */ if (close(mbfd)) { e_to_sys(errno); warn("%s: %s", path, strerror(errno)); unlockmbox(); return; } unlockmbox(); notifybiff(biffmsg); } /* * user.lock files are necessary for compatibility with other * systems, e.g., when the mail spool file is NFS exported. * Alas, mailbox locking is more than just a local matter. * EPA 11/94. */ char lockname[MAXPATHLEN]; int locked = 0; lockmbox(path) char *path; { int statfailed = 0; if (locked) return; sprintf(lockname, "%s.lock", path); for (;; sleep(5)) { int fd; struct stat st; time_t now; fd = open(lockname, O_WRONLY|O_EXCL|O_CREAT, 0); if (fd >= 0) { locked = 1; close(fd); return; } if (stat(lockname, &st) < 0) { if (statfailed++ > 5) return; continue; } statfailed = 0; time(&now); if (now < st.st_ctime + 300) continue; unlink(lockname); } } unlockmbox() { if (!locked) return; unlink(lockname); locked = 0; } void notifybiff(msg) char *msg; { static struct sockaddr_in addr; static int f = -1; struct hostent *hp; struct servent *sp; int len; if (!addr.sin_family) { /* Be silent if biff service not available. */ if (!(sp = getservbyname("biff", "udp"))) return; if (!(hp = gethostbyname("localhost"))) { warn("localhost: %s", strerror(errno)); return; } addr.sin_family = hp->h_addrtype; memcpy(&addr.sin_addr, hp->h_addr, hp->h_length); addr.sin_port = sp->s_port; } if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { warn("socket: %s", strerror(errno)); return; } len = strlen(msg) + 1; if (sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)) != len) warn("sendto biff: %s", strerror(errno)); } void usage() { eval = EX_USAGE; err("usage: mail.local [-f from] user ..."); } #if __STDC__ void err(const char *fmt, ...) #else void err(fmt, va_alist) const char *fmt; va_dcl #endif { va_list ap; #if __STDC__ va_start(ap, fmt); #else va_start(ap); #endif vwarn(fmt, ap); va_end(ap); exit(eval); } void #if __STDC__ warn(const char *fmt, ...) #else warn(fmt, va_alist) const char *fmt; va_dcl #endif { va_list ap; #if __STDC__ va_start(ap, fmt); #else va_start(ap); #endif vwarn(fmt, ap); va_end(ap); } void vwarn(fmt, ap) const char *fmt; _BSD_VA_LIST_ ap; { /* * Log the message to stderr. * * Don't use LOG_PERROR as an openlog() flag to do this, * it's not portable enough. */ if (eval != EX_USAGE) (void)fprintf(stderr, "mail.local: "); (void)vfprintf(stderr, fmt, ap); (void)fprintf(stderr, "\n"); #ifndef ultrix /* Log the message to syslog. */ vsyslog(LOG_ERR, fmt, ap); #else { char fmtbuf[10240]; (void) sprintf(fmtbuf, fmt, ap); syslog(LOG_ERR, "%s", fmtbuf); } #endif } /* * e_to_sys -- * Guess which errno's are temporary. Gag me. */ void e_to_sys(num) int num; { /* Temporary failures override hard errors. */ if (eval == EX_TEMPFAIL) return; switch(num) { /* Hopefully temporary errors. */ #ifdef EAGAIN case EAGAIN: /* Resource temporarily unavailable */ #endif #ifdef EDQUOT case EDQUOT: /* Disc quota exceeded */ #endif #ifdef EBUSY case EBUSY: /* Device busy */ #endif #ifdef EPROCLIM case EPROCLIM: /* Too many processes */ #endif #ifdef EUSERS case EUSERS: /* Too many users */ #endif #ifdef ECONNABORTED case ECONNABORTED: /* Software caused connection abort */ #endif #ifdef ECONNREFUSED case ECONNREFUSED: /* Connection refused */ #endif #ifdef ECONNRESET case ECONNRESET: /* Connection reset by peer */ #endif #ifdef EDEADLK case EDEADLK: /* Resource deadlock avoided */ #endif #ifdef EFBIG case EFBIG: /* File too large */ #endif #ifdef EHOSTDOWN case EHOSTDOWN: /* Host is down */ #endif #ifdef EHOSTUNREACH case EHOSTUNREACH: /* No route to host */ #endif #ifdef EMFILE case EMFILE: /* Too many open files */ #endif #ifdef ENETDOWN case ENETDOWN: /* Network is down */ #endif #ifdef ENETRESET case ENETRESET: /* Network dropped connection on reset */ #endif #ifdef ENETUNREACH case ENETUNREACH: /* Network is unreachable */ #endif #ifdef ENFILE case ENFILE: /* Too many open files in system */ #endif #ifdef ENOBUFS case ENOBUFS: /* No buffer space available */ #endif #ifdef ENOMEM case ENOMEM: /* Cannot allocate memory */ #endif #ifdef ENOSPC case ENOSPC: /* No space left on device */ #endif #ifdef EROFS case EROFS: /* Read-only file system */ #endif #ifdef ESTALE case ESTALE: /* Stale NFS file handle */ #endif #ifdef ETIMEDOUT case ETIMEDOUT: /* Connection timed out */ #endif #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN && EWOULDBLOCK != EDEADLK case EWOULDBLOCK: /* Operation would block. */ #endif eval = EX_TEMPFAIL; break; default: eval = EX_UNAVAILABLE; break; } } #ifndef BSD4_4 char * strerror(eno) int eno; { extern int sys_nerr; extern char *sys_errlist[]; static char ebuf[60]; if (eno >= 0 && eno <= sys_nerr) return sys_errlist[eno]; (void) sprintf(ebuf, "Error %d", eno); return ebuf; } #if __STDC__ snprintf(char *buf, int bufsiz, const char *fmt, ...) #else snprintf(buf, bufsiz, fmt, va_alist) char *buf; int bufsiz; const char *fmt; va_dcl #endif { va_list ap; #if __STDC__ va_start(ap, fmt); #else va_start(ap); #endif vsprintf(buf, fmt, ap); va_end(ap); } #endif #ifdef ultrix /* * Copyright (c) 1987, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(LIBC_SCCS) && !defined(lint) static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93"; #endif /* LIBC_SCCS and not lint */ #include #include #include #include #include #include static int _gettemp(); mkstemp(path) char *path; { int fd; return (_gettemp(path, &fd) ? fd : -1); } /* char * mktemp(path) char *path; { return(_gettemp(path, (int *)NULL) ? path : (char *)NULL); } */ static _gettemp(path, doopen) char *path; register int *doopen; { extern int errno; register char *start, *trv; struct stat sbuf; u_int pid; pid = getpid(); for (trv = path; *trv; ++trv); /* extra X's get set to 0's */ while (*--trv == 'X') { *trv = (pid % 10) + '0'; pid /= 10; } /* * check the target directory; if you have six X's and it * doesn't exist this runs for a *very* long time. */ for (start = trv + 1;; --trv) { if (trv <= path) break; if (*trv == '/') { *trv = '\0'; if (stat(path, &sbuf)) return(0); if (!S_ISDIR(sbuf.st_mode)) { errno = ENOTDIR; return(0); } *trv = '/'; break; } } for (;;) { if (doopen) { if ((*doopen = open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0) return(1); if (errno != EEXIST) return(0); } else if (stat(path, &sbuf)) return(errno == ENOENT ? 1 : 0); /* tricky little algorithm for backward compatibility */ for (trv = start;;) { if (!*trv) return(0); if (*trv == 'z') *trv++ = 'a'; else { if (isdigit(*trv)) *trv = 'a'; else ++*trv; break; } } } /*NOTREACHED*/ } #endif -----END PRIVACY-ENHANCED MESSAGE-----