summaryrefslogtreecommitdiff
path: root/libexec
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2020-02-02 23:17:10 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2020-02-02 23:17:10 +0000
commit029e8e958246f40e0880c3f2be18c40d49f0c8f2 (patch)
treed150ddf5dc3425ca757f62f01970be0de856cc0a /libexec
parente63751b4c0f5809f81add56755a6d261f9ff0de3 (diff)
Allow mail.local to be run as non-root.
If mail.local is invoked by a non-root user, open a pipe to lockspool(1) for file locking. It is only possible to delivery to a pre-existing mail spool when running mail.local as non-root. OK gilles@ deraadt@
Diffstat (limited to 'libexec')
-rw-r--r--libexec/mail.local/locking.c4
-rw-r--r--libexec/mail.local/mail.local.c73
-rw-r--r--libexec/mail.local/mail.local.h6
3 files changed, 71 insertions, 12 deletions
diff --git a/libexec/mail.local/locking.c b/libexec/mail.local/locking.c
index 191b2dfeed7..d63642c1828 100644
--- a/libexec/mail.local/locking.c
+++ b/libexec/mail.local/locking.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: locking.c,v 1.12 2015/01/16 06:39:50 deraadt Exp $ */
+/* $OpenBSD: locking.c,v 1.13 2020/02/02 23:17:09 millert Exp $ */
/*
* Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com>
@@ -55,7 +55,7 @@ rellock(void)
}
int
-getlock(char *name, struct passwd *pw)
+getlock(const char *name, struct passwd *pw)
{
struct stat sb, fsb;
int lfd=-1;
diff --git a/libexec/mail.local/mail.local.c b/libexec/mail.local/mail.local.c
index ddfaae20a0a..635b2558ee5 100644
--- a/libexec/mail.local/mail.local.c
+++ b/libexec/mail.local/mail.local.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mail.local.c,v 1.36 2019/06/28 13:32:53 deraadt Exp $ */
+/* $OpenBSD: mail.local.c,v 1.37 2020/02/02 23:17:09 millert Exp $ */
/*-
* Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com>
@@ -34,6 +34,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <syslog.h>
#include <fcntl.h>
@@ -46,6 +47,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#include "pathnames.h"
#include "mail.local.h"
@@ -92,8 +94,6 @@ main(int argc, char *argv[])
} else {
if (!*argv)
usage();
- if (geteuid() != 0)
- merr(FATAL, "may only be run by the superuser");
}
/*
@@ -188,7 +188,7 @@ deliver(int fd, char *name, int lockfile)
(void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name);
if (lockfile) {
- lfd = getlock(name, pw);
+ lfd = lockspool(name, pw);
if (lfd == -1)
return (1);
}
@@ -270,10 +270,8 @@ retry:
}
bad:
- if (lfd != -1) {
- rellock();
- close(lfd);
- }
+ if (lfd != -1)
+ unlockspool();
if (mbfd != -1) {
(void)fsync(mbfd); /* Don't wait for update. */
@@ -328,6 +326,65 @@ notifybiff(char *msg)
merr(NOTFATAL, "sendto biff: %s", strerror(errno));
}
+static int lockfd = -1;
+static pid_t lockpid = -1;
+
+int
+lockspool(const char *name, struct passwd *pw)
+{
+ int pfd[2];
+ char ch;
+
+ if (geteuid() == 0)
+ return getlock(name, pw);
+
+ /* If not privileged, open pipe to lockspool(1) instead */
+ if (pipe2(pfd, O_CLOEXEC) == -1) {
+ merr(FATAL, "pipe: %s", strerror(errno));
+ return -1;
+ }
+
+ signal(SIGPIPE, SIG_IGN);
+ switch ((lockpid = fork())) {
+ case -1:
+ merr(FATAL, "fork: %s", strerror(errno));
+ return -1;
+ case 0:
+ /* child */
+ close(pfd[0]);
+ dup2(pfd[1], STDOUT_FILENO);
+ execl(_PATH_LOCKSPOOL, "lockspool", (char *)NULL);
+ merr(FATAL, "execl: lockspool: %s", strerror(errno));
+ /* NOTREACHED */
+ break;
+ default:
+ /* parent */
+ close(pfd[1]);
+ lockfd = pfd[0];
+ break;
+ }
+
+ if (read(lockfd, &ch, 1) != 1 || ch != '1') {
+ unlockspool();
+ merr(FATAL, "lockspool: unable to get lock");
+ }
+
+ return lockfd;
+}
+
+void
+unlockspool(void)
+{
+ if (lockpid != -1) {
+ waitpid(lockpid, NULL, 0);
+ lockpid = -1;
+ } else {
+ rellock();
+ }
+ close(lockfd);
+ lockfd = -1;
+}
+
void
usage(void)
{
diff --git a/libexec/mail.local/mail.local.h b/libexec/mail.local/mail.local.h
index 0377aa20364..92a0b78cf37 100644
--- a/libexec/mail.local/mail.local.h
+++ b/libexec/mail.local/mail.local.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mail.local.h,v 1.5 2006/04/01 22:48:57 deraadt Exp $ */
+/* $OpenBSD: mail.local.h,v 1.6 2020/02/02 23:17:09 millert Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -35,8 +35,10 @@
void baditem(char *);
int deliver(int, char *, int);
void merr(int, const char *, ...);
-int getlock(char *, struct passwd *);
+int getlock(const char *, struct passwd *);
void notifybiff(char *);
void rellock(void);
int storemail(char *);
+int lockspool(const char *, struct passwd *);
+void unlockspool(void);
void usage(void);