summaryrefslogtreecommitdiff
path: root/libexec/mail.local/locking.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1998-08-15 21:04:36 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1998-08-15 21:04:36 +0000
commit7931b8588f564d72815d8ccdd897665d7d0e1fbe (patch)
tree856f54a2c6fe8787fa78afb17d82621f08243974 /libexec/mail.local/locking.c
parent419d35e63268d3263b1b2192a4e4d85e883ae103 (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/mail.local/locking.c')
-rw-r--r--libexec/mail.local/locking.c191
1 files changed, 191 insertions, 0 deletions
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);
+}