diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1998-08-15 21:04:36 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1998-08-15 21:04:36 +0000 |
commit | 7931b8588f564d72815d8ccdd897665d7d0e1fbe (patch) | |
tree | 856f54a2c6fe8787fa78afb17d82621f08243974 /libexec | |
parent | 419d35e63268d3263b1b2192a4e4d85e883ae103 (diff) |
Break out locking code into its own file so it can be shared with lockspool.
Call lockspool when invoked with -H flag for backward compatibility.
Diffstat (limited to 'libexec')
-rw-r--r-- | libexec/mail.local/Makefile | 3 | ||||
-rw-r--r-- | libexec/mail.local/locking.c | 191 | ||||
-rw-r--r-- | libexec/mail.local/mail.local.8 | 14 | ||||
-rw-r--r-- | libexec/mail.local/mail.local.c | 227 | ||||
-rw-r--r-- | libexec/mail.local/mail.local.h | 46 | ||||
-rw-r--r-- | libexec/mail.local/pathnames.h | 3 |
6 files changed, 263 insertions, 221 deletions
diff --git a/libexec/mail.local/Makefile b/libexec/mail.local/Makefile index f61891cb428..5226f554de9 100644 --- a/libexec/mail.local/Makefile +++ b/libexec/mail.local/Makefile @@ -1,7 +1,8 @@ # from: @(#)Makefile 5.3 (Berkeley) 1/17/91 -# $Id: Makefile,v 1.1 1995/10/18 08:43:19 deraadt Exp $ +# $OpenBSD: Makefile,v 1.2 1998/08/15 21:04:31 millert Exp $ PROG= mail.local +SRCS= mail.local.c locking.c MAN= mail.local.8 BINOWN= root BINMODE=4555 diff --git a/libexec/mail.local/locking.c b/libexec/mail.local/locking.c new file mode 100644 index 00000000000..c0a4b8e95c4 --- /dev/null +++ b/libexec/mail.local/locking.c @@ -0,0 +1,191 @@ +/* $OpenBSD: locking.c,v 1.1 1998/08/15 21:04:33 millert Exp $ */ + +/* + * Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com> + * Copyright (c) 1996-1998 David Mazieres <dm@lcs.mit.edu> + * 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. The name of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``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 AUTHORS 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 rcsid[] = "$OpenBSD: locking.c,v 1.1 1998/08/15 21:04:33 millert Exp $"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pwd.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include "pathnames.h" +#include "mail.local.h" + +static char lpath[MAXPATHLEN]; + +void +rellock() +{ + + if (lpath[0]) + unlink(lpath); +} + +int +getlock(name, pw) + char *name; + struct passwd *pw; +{ + struct stat sb, fsb; + int lfd=-1; + char buf[8*1024]; + int tries = 0; + + (void)snprintf(lpath, sizeof lpath, "%s/%s.lock", + _PATH_MAILDIR, name); + + if (stat(_PATH_MAILDIR, &sb) != -1 && + (sb.st_mode & S_IWOTH) == S_IWOTH) { + /* + * We have a writeable spool, deal with it as + * securely as possible. + */ + time_t ctim = -1; + + seteuid(pw->pw_uid); + if (lstat(lpath, &sb) != -1) + ctim = sb.st_ctime; + while (1) { + /* + * Deal with existing user.lock files + * or directories or symbolic links that + * should not be here. + */ + if (readlink(lpath, buf, sizeof buf-1) != -1) { + if (lstat(lpath, &sb) != -1 && + S_ISLNK(fsb.st_mode)) { + seteuid(sb.st_uid); + unlink(lpath); + seteuid(pw->pw_uid); + } + goto again; + } + if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK, + S_IRUSR|S_IWUSR)) != -1) + break; +again: + if (tries > 10) { + err(NOTFATAL, "%s: %s", lpath, + strerror(errno)); + seteuid(0); + return(-1); + } + if (tries > 9 && + (lfd = open(lpath, O_WRONLY|O_EXLOCK, 0)) != -1) { + if (fstat(lfd, &fsb) != -1 && + lstat(lpath, &sb) != -1) { + if (fsb.st_dev == sb.st_dev && + fsb.st_ino == sb.st_ino && + ctim == fsb.st_ctime ) { + seteuid(fsb.st_uid); + baditem(lpath); + seteuid(pw->pw_uid); + } + } + } + sleep(1 << tries); + tries++; + continue; + } + seteuid(0); + } else { + /* + * Only root can write the spool directory. + */ + while (1) { + if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL, + S_IRUSR|S_IWUSR)) != -1) + break; + if (tries > 9) { + err(NOTFATAL, "%s: %s", lpath, strerror(errno)); + return(-1); + } + sleep(1 << tries); + tries++; + } + } + return(lfd); +} + +void +baditem(path) + char *path; +{ + char npath[MAXPATHLEN]; + int fd; + + if (unlink(path) == 0) + return; + snprintf(npath, sizeof npath, "%s/mailXXXXXXXXXX", _PATH_MAILDIR); + if ((fd = mkstemp(npath)) == -1) + return; + (void)close(fd); + if (rename(path, npath) == -1) + unlink(npath); + else + err(NOTFATAL, "nasty spool item %s renamed to %s", + path, npath); + /* XXX if we fail to rename, another attempt will happen later */ +} + +#ifdef __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void +#ifdef __STDC__ +err(int isfatal, const char *fmt, ...) +#else +err(isfatal, fmt) + int isfatal; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + if (isfatal) + exit(1); +} diff --git a/libexec/mail.local/mail.local.8 b/libexec/mail.local/mail.local.8 index 4050f83d55d..cd6d244f876 100644 --- a/libexec/mail.local/mail.local.8 +++ b/libexec/mail.local/mail.local.8 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" from: @(#)mail.local.8 6.8 (Berkeley) 4/27/91 -.\" $Id: mail.local.8,v 1.12 1998/02/24 05:00:24 millert Exp $ +.\" $Id: mail.local.8,v 1.13 1998/08/15 21:04:33 millert Exp $ .\" .Dd April 27, 1991 .Dt MAIL.LOCAL 8 @@ -43,7 +43,6 @@ .Op Fl L .Op Fl l .Op Fl f Ar from -.Op Fl H .Ar user ... .Sh DESCRIPTION .Nm Mail.local @@ -69,17 +68,6 @@ Request that .Fn flock be used for locking the mail spool rather than .Nm username.lock . -.It Fl H -This mode is useful for a client mail program to attain proper locking. -In this mode -.Nm mail.local -(ignoring all other arguments) attains a -.Nm username.lock -for the calling user and retains it until stdin is closed or a signal -like SIGINT, SIGTERM, or SIGHUP is received. If -.Nm mail.local -is able to create the lock file, ``1'' is written to stdout, otherwise -``0'' is written and an error message is written to stderr. .El .Pp Individual mail messages in the mailbox are delimited by an empty diff --git a/libexec/mail.local/mail.local.c b/libexec/mail.local/mail.local.c index dd59d84813a..76dfcabf6ae 100644 --- a/libexec/mail.local/mail.local.c +++ b/libexec/mail.local/mail.local.c @@ -1,4 +1,8 @@ +/* $OpenBSD: mail.local.c,v 1.19 1998/08/15 21:04:34 millert Exp $ */ + /*- + * Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com> + * Copyright (c) 1996-1998 David Mazieres <dm@lcs.mit.edu> * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. * @@ -38,8 +42,11 @@ char copyright[] = #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)mail.local.c 5.6 (Berkeley) 6/19/91";*/ -static char rcsid[] = "$Id: mail.local.c,v 1.18 1998/05/18 09:58:03 deraadt Exp $"; +#if 0 +static char sccsid[] = "from: @(#)mail.local.c 5.6 (Berkeley) 6/19/91"; +#else +static char rcsid[] = "$OpenBSD: mail.local.c,v 1.19 1998/08/15 21:04:34 millert Exp $"; +#endif #endif /* not lint */ #include <sys/param.h> @@ -58,26 +65,13 @@ static char rcsid[] = "$Id: mail.local.c,v 1.18 1998/05/18 09:58:03 deraadt Exp #include <stdlib.h> #include <string.h> #include "pathnames.h" - -#define FATAL 1 -#define NOTFATAL 0 - -int deliver __P((int, char *, int)); -void err __P((int, const char *, ...)); -void notifybiff __P((char *)); -int store __P((char *)); -void usage __P((void)); -int dohold __P((void)); -int getlock __P((char *, struct passwd *)); -void rellock __P((void)); +#include "mail.local.h" int main(argc, argv) int argc; char **argv; { - extern int optind; - extern char *optarg; struct passwd *pw; int ch, fd, eval, lockfile=1, holdme=0; uid_t uid; @@ -112,11 +106,16 @@ main(argc, argv) argc -= optind; argv += optind; - if (!*argv && !holdme) - usage(); - - if (holdme) - exit(dohold()); + /* Support -H flag for backwards compat */ + if (holdme) { + execl(_PATH_LOCKSPOOL, "lockspool", NULL); + err(FATAL, "execl: lockspool: %s", strerror(errno)); + } else { + if (!*argv) + usage(); + if (geteuid() != 0) + err(FATAL, "may only be run by the superuser"); + } /* * If from not specified, use the name from getlogin() if the @@ -134,50 +133,6 @@ main(argc, argv) exit(eval); } -void -unhold() -{ - rellock(); - exit(0); -} - -int -dohold() -{ - struct passwd *pw; - char *from, c; - int holdfd; - - signal(SIGTERM, unhold); - signal(SIGINT, unhold); - signal(SIGHUP, unhold); - - from = getlogin(); - if (from) { - pw = getpwnam(from); - if (pw == NULL) - return (1); - } else { - pw = getpwuid(getuid()); - if (pw) - from = pw->pw_name; - else - return (1); - } - - holdfd = getlock(from, pw); - if (holdfd == -1) { - write(STDOUT_FILENO, "0\n", 2); - return (1); - } - write(STDOUT_FILENO, "1\n", 2); - - while (read(0, &c, 1) == -1 && errno == EINTR) - ; - rellock(); - return (0); -} - int store(from) char *from; @@ -223,118 +178,6 @@ store(from) return(fd); } -void -baditem(path) - char *path; -{ - char npath[MAXPATHLEN]; - - if (unlink(path) == 0) - return; - snprintf(npath, sizeof npath, "%s/mailXXXXXXXXXX", _PATH_MAILDIR); - if (mktemp(npath) == NULL) - return; - if (rename(path, npath) != -1) - err(NOTFATAL, "nasty spool item %s renamed to %s", - path, npath); - /* XXX if we fail to rename, another attempt will happen later */ -} - -char lpath[MAXPATHLEN]; - -void -rellock() -{ - if (lpath[0]) - unlink(lpath); -} - -int -getlock(name, pw) - char *name; - struct passwd *pw; -{ - struct stat sb, fsb; - int lfd=-1; - char buf[8*1024]; - int tries = 0; - - (void)snprintf(lpath, sizeof lpath, "%s/%s.lock", - _PATH_MAILDIR, name); - - if (stat(_PATH_MAILDIR, &sb) != -1 && - (sb.st_mode & S_IWOTH) == S_IWOTH) { - /* - * We have a writeable spool, deal with it as - * securely as possible. - */ - time_t ctim = -1; - - seteuid(pw->pw_uid); - if (lstat(lpath, &sb) != -1) - ctim = sb.st_ctime; - while (1) { - /* - * Deal with existing user.lock files - * or directories or symbolic links that - * should not be here. - */ - if (readlink(lpath, buf, sizeof buf-1) != -1) { - if (lstat(lpath, &sb) != -1 && - S_ISLNK(fsb.st_mode)) { - seteuid(sb.st_uid); - unlink(lpath); - seteuid(pw->pw_uid); - } - goto again; - } - if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK, - S_IRUSR|S_IWUSR)) != -1) - break; -again: - if (tries > 10) { - err(NOTFATAL, "%s: %s", lpath, - strerror(errno)); - seteuid(0); - return(-1); - } - if (tries > 9 && - (lfd = open(lpath, O_WRONLY|O_EXLOCK, 0)) != -1) { - if (fstat(lfd, &fsb) != -1 && - lstat(lpath, &sb) != -1) { - if (fsb.st_dev == sb.st_dev && - fsb.st_ino == sb.st_ino && - ctim == fsb.st_ctime ) { - seteuid(fsb.st_uid); - baditem(lpath); - seteuid(pw->pw_uid); - } - } - } - sleep(1 << tries); - tries++; - continue; - } - seteuid(0); - } else { - /* - * Only root can write the spool directory. - */ - while (1) { - if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL, - S_IRUSR|S_IWUSR)) != -1) - break; - if (tries > 9) { - err(NOTFATAL, "%s: %s", lpath, strerror(errno)); - return(-1); - } - sleep(1 << tries); - tries++; - } - } - return (lfd); -} - int deliver(fd, name, lockfile) int fd; @@ -492,33 +335,5 @@ notifybiff(msg) void usage() { - err(FATAL, "usage: mail.local [-lLH] [-f from] user ..."); -} - -#ifdef __STDC__ -#include <stdarg.h> -#else -#include <varargs.h> -#endif - -void -#ifdef __STDC__ -err(int isfatal, const char *fmt, ...) -#else -err(isfatal, fmt) - int isfatal; - char *fmt; - va_dcl -#endif -{ - va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - vsyslog(LOG_ERR, fmt, ap); - va_end(ap); - if (isfatal) - exit(1); + err(FATAL, "usage: mail.local [-lL] [-f from] user ..."); } diff --git a/libexec/mail.local/mail.local.h b/libexec/mail.local/mail.local.h new file mode 100644 index 00000000000..8e13010818d --- /dev/null +++ b/libexec/mail.local/mail.local.h @@ -0,0 +1,46 @@ +/* $OpenBSD: mail.local.h,v 1.1 1998/08/15 21:04:35 millert Exp $ */ + +/*- + * Copyright (c) 1990 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. + */ + +#define FATAL 1 +#define NOTFATAL 0 + +void baditem __P((char *)); +int deliver __P((int, char *, int)); +void err __P((int, const char *, ...)); +int getlock __P((char *, struct passwd *)); +void notifybiff __P((char *)); +void rellock __P((void)); +int store __P((char *)); +void usage __P((void)); diff --git a/libexec/mail.local/pathnames.h b/libexec/mail.local/pathnames.h index ed790d93196..db5c1b2941b 100644 --- a/libexec/mail.local/pathnames.h +++ b/libexec/mail.local/pathnames.h @@ -31,8 +31,9 @@ * SUCH DAMAGE. * * from: @(#)pathnames.h 5.3 (Berkeley) 1/17/91 - * $Id: pathnames.h,v 1.2 1998/02/24 04:52:53 millert Exp $ + * $Id: pathnames.h,v 1.3 1998/08/15 21:04:35 millert Exp $ */ #include <paths.h> #define _PATH_LOCTMP "/tmp/local.XXXXXXXXXX" +#define _PATH_LOCKSPOOL "/usr/libexec/lockspool" |