1
0
mirror of https://github.com/openbsd/src.git synced 2026-04-27 23:56:05 +00:00

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@
This commit is contained in:
millert
2020-02-02 23:17:09 +00:00
parent 43304138eb
commit c711e4838d
3 changed files with 71 additions and 12 deletions

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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);