diff options
Diffstat (limited to 'contrib')
23 files changed, 679 insertions, 149 deletions
diff --git a/contrib/CVS/Entries b/contrib/CVS/Entries deleted file mode 100644 index 82a9d101..00000000 --- a/contrib/CVS/Entries +++ /dev/null @@ -1,4 +0,0 @@ -D/lib//// -D/libexec//// -/Makefile/-1.50/Mon Mar 5 11:15:41 2012// -/Makefile.inc/-1.2/Sun Jan 28 19:34:26 2001// diff --git a/contrib/CVS/Repository b/contrib/CVS/Repository deleted file mode 100644 index 31ac4266..00000000 --- a/contrib/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -src/libexec diff --git a/contrib/CVS/Root b/contrib/CVS/Root deleted file mode 100644 index 7040dfb5..00000000 --- a/contrib/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -anoncvs@anoncvs.spacehopper.org:/cvs diff --git a/contrib/libexec/CVS/Entries b/contrib/libexec/CVS/Entries deleted file mode 100644 index cc09ac02..00000000 --- a/contrib/libexec/CVS/Entries +++ /dev/null @@ -1,3 +0,0 @@ -D/mail.local//// -/Makefile/1.50/Mon Jul 9 11:41:26 2012// -/Makefile.inc/1.2/Mon Jul 9 11:41:26 2012// diff --git a/contrib/libexec/CVS/Repository b/contrib/libexec/CVS/Repository deleted file mode 100644 index 31ac4266..00000000 --- a/contrib/libexec/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -src/libexec diff --git a/contrib/libexec/CVS/Root b/contrib/libexec/CVS/Root deleted file mode 100644 index 7040dfb5..00000000 --- a/contrib/libexec/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -anoncvs@anoncvs.spacehopper.org:/cvs diff --git a/contrib/libexec/Makefile.am b/contrib/libexec/Makefile.am index 6079ae6a..0e3a271f 100644 --- a/contrib/libexec/Makefile.am +++ b/contrib/libexec/Makefile.am @@ -1 +1 @@ -SUBDIRS = mail.local encrypt +SUBDIRS = mail.local lockspool encrypt diff --git a/contrib/libexec/encrypt/Makefile.am b/contrib/libexec/encrypt/Makefile.am index 6ad7b82d..2f96e60d 100644 --- a/contrib/libexec/encrypt/Makefile.am +++ b/contrib/libexec/encrypt/Makefile.am @@ -1,7 +1,7 @@ pkglibexec_PROGRAMS = encrypt encrypt_SOURCES = encrypt.c -encrypt_SOURCES += $(top_srcdir)/smtpd/log.c +encrypt_SOURCES += $(top_srcdir)/usr.sbin/smtpd/log.c AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat diff --git a/contrib/libexec/lockspool/Makefile.am b/contrib/libexec/lockspool/Makefile.am new file mode 100644 index 00000000..2801c101 --- /dev/null +++ b/contrib/libexec/lockspool/Makefile.am @@ -0,0 +1,20 @@ +pkglibexec_PROGRAMS = lockspool + +lockspool_SOURCES = lockspool.c +lockspool_SOURCES += locking.c +lockspool_SOURCES += $(top_srcdir)/usr.sbin/smtpd/log.c + +EXTRA_DIST = mail.local.h pathnames.h + +AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat -I$(top_srcdir)/mail.local + +LIBCOMPAT = $(top_builddir)/openbsd-compat/libopenbsd.a + +LDADD = $(LIBCOMPAT) + +install-exec-hook: $(CONFIGFILES) $(MANPAGES) + chown root $(DESTDIR)$(pkglibexecdir)/lockspool || true + chmod 4555 $(DESTDIR)$(pkglibexecdir)/lockspool || true + +uninstall-hook: + rmdir $(DESTDIR)$(pkglibexecdir) 2> /dev/null || /bin/true diff --git a/contrib/libexec/lockspool/locking.c b/contrib/libexec/lockspool/locking.c new file mode 100644 index 00000000..e4922dd6 --- /dev/null +++ b/contrib/libexec/lockspool/locking.c @@ -0,0 +1,181 @@ +/* $OpenBSD: locking.c,v 1.14 2020/02/09 14:59:20 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. + */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <pwd.h> +#include <syslog.h> +#include <time.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdarg.h> +#include "pathnames.h" +#include "mail.local.h" + +static char lpath[PATH_MAX]; + +void +rellock(void) +{ + + if (lpath[0]) + unlink(lpath); +} + +int +getlock(const 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(sb.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) { + mwarn("%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); + } + } + close(lfd); + } + sleep(1U << 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) { + mwarn("%s: %s", lpath, strerror(errno)); + return(-1); + } + sleep(1U << tries); + tries++; + } + } + return(lfd); +} + +void +baditem(char *path) +{ + char npath[PATH_MAX]; + int fd; + + if (unlink(path) == 0) + return; + snprintf(npath, sizeof npath, "%s/mailXXXXXXXXXX", _PATH_MAILDIR); + if ((fd = mkstemp(npath)) == -1) + return; + close(fd); + if (rename(path, npath) == -1) + unlink(npath); + else + mwarn("nasty spool item %s renamed to %s", path, npath); + /* XXX if we fail to rename, another attempt will happen later */ +} + +void +mwarn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); +} + +void +merr(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + exit(eval); +} diff --git a/contrib/libexec/lockspool/lockspool.1 b/contrib/libexec/lockspool/lockspool.1 new file mode 100644 index 00000000..ea5524bf --- /dev/null +++ b/contrib/libexec/lockspool/lockspool.1 @@ -0,0 +1,77 @@ +.\" $OpenBSD: lockspool.1,v 1.14 2019/01/25 00:19:26 millert Exp $ +.\" +.\" Copyright (c) 1998 Todd C. Miller <millert@openbsd.org> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd $Mdocdate: January 25 2019 $ +.Dt LOCKSPOOL 1 +.Os +.Sh NAME +.Nm lockspool +.Nd lock user's system mailbox +.Sh SYNOPSIS +.Nm lockspool +.Op Ar username +.Sh DESCRIPTION +.Nm +is useful for a client mail program to attain proper locking. +.Nm +obtains a +.Pa username.lock +for the calling user and retains it until stdin is closed or a signal like +.Dv SIGINT , +.Dv SIGTERM , +or +.Dv SIGHUP +is received. +Additionally, the superuser may specify the name of a user in order +to lock a different mailbox. +.Pp +If +.Nm +is able to create the lock file, +.Dq 1 +is written to stdout, otherwise +.Dq 0 +is written and an error message is written to stderr. +.Nm +will try up to 10 times to get the lock (sleeping +for a short period in between tries). +.Pp +Typical usage is for a user mail agent (such as +.Xr mail 1 ) +to open a pipe to +.Nm +when it needs to lock the user's mail spool. +Closing the pipe will cause +.Nm +to release the lock. +.Sh FILES +.Bl -tag -width /var/mail/username.lock -compact +.It Pa /var/mail/username.lock +user's mail lock file +.El +.Sh EXIT STATUS +The +.Nm +utility exits 0 on success, and 1 if an error occurs. +.Sh SEE ALSO +.Xr mail 1 , +.Xr mail.local 8 , +.Xr smtpd 8 +.Sh HISTORY +The +.Nm +program appeared in +.Ox 2.4 . diff --git a/contrib/libexec/lockspool/lockspool.c b/contrib/libexec/lockspool/lockspool.c new file mode 100644 index 00000000..9277241b --- /dev/null +++ b/contrib/libexec/lockspool/lockspool.c @@ -0,0 +1,124 @@ +/* $OpenBSD: lockspool.c,v 1.21 2020/02/09 14:59:20 millert Exp $ */ + +/* + * Copyright (c) 1998 Theo de Raadt <deraadt@theos.com> + * Copyright (c) 1998 Todd C. Miller <millert@openbsd.org> + * 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. + * + * 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. + */ + +#include "includes.h" + +#include <signal.h> +#include <pwd.h> +#include <syslog.h> +#include <unistd.h> +#include <errno.h> +#include <stdio.h> +#include <paths.h> +#include <stdlib.h> +#include <poll.h> +#include <err.h> + +#include "mail.local.h" + +void unhold(int); +void usage(void); + +extern char *__progname; + +int +main(int argc, char *argv[]) +{ + struct passwd *pw; + struct pollfd pfd; + ssize_t nread; + char *from, c; + int holdfd; + +#if HAVE_UNVEIL + if (unveil(_PATH_MAILDIR, "rwc") == -1) + err(1, "unveil"); +#endif +#if HAVE_PLEDGE + if (pledge("stdio rpath wpath getpw cpath fattr", NULL) == -1) + err(1, "pledge"); +#endif + + openlog(__progname, LOG_PERROR, LOG_MAIL); + + if (argc != 1 && argc != 2) + usage(); + if (argc == 2 && getuid() != 0) + merr(1, "you must be root to lock someone else's spool"); + + signal(SIGTERM, unhold); + signal(SIGINT, unhold); + signal(SIGHUP, unhold); + signal(SIGPIPE, unhold); + + if (argc == 2) + pw = getpwnam(argv[1]); + else + pw = getpwuid(getuid()); + if (pw == NULL) + exit (1); + from = pw->pw_name; + + holdfd = getlock(from, pw); + if (holdfd == -1) { + write(STDOUT_FILENO, "0\n", 2); + exit (1); + } + write(STDOUT_FILENO, "1\n", 2); + + /* wait for the other end of the pipe to close, then release the lock */ + pfd.fd = STDIN_FILENO; + pfd.events = POLLIN; + do { + if (poll(&pfd, 1, INFTIM) == -1) { + if (errno != EINTR) + break; + } + do { + nread = read(STDIN_FILENO, &c, 1); + } while (nread == 1 || (nread == -1 && errno == EINTR)); + } while (nread == -1 && errno == EAGAIN); + rellock(); + exit (0); +} + +/*ARGSUSED*/ +void +unhold(int signo) +{ + + rellock(); + _exit(0); +} + +void +usage(void) +{ + + merr(1, "usage: %s [username]", __progname); +} diff --git a/contrib/libexec/lockspool/mail.local.h b/contrib/libexec/lockspool/mail.local.h new file mode 100644 index 00000000..bc3137cb --- /dev/null +++ b/contrib/libexec/lockspool/mail.local.h @@ -0,0 +1,42 @@ +/* $OpenBSD: mail.local.h,v 1.7 2020/02/09 14:59:21 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. 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. + */ + +void baditem(char *); +int deliver(int, char *, int); +void merr(int, const char *, ...); +void mwarn(const char *, ...); +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); diff --git a/contrib/libexec/lockspool/pathnames.h b/contrib/libexec/lockspool/pathnames.h new file mode 100644 index 00000000..0a2c2731 --- /dev/null +++ b/contrib/libexec/lockspool/pathnames.h @@ -0,0 +1,38 @@ +/* $OpenBSD: pathnames.h,v 1.5 2003/06/02 19:38:24 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. 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. + * + * from: @(#)pathnames.h 5.3 (Berkeley) 1/17/91 + */ +#ifdef HAVE_PATHS_H +#include <paths.h> +#endif + +#define _PATH_LOCTMP "/tmp/local.XXXXXXXXXX" +#define _PATH_LOCKSPOOL PATH_LIBEXEC"/lockspool" diff --git a/contrib/libexec/mail.local/CVS/Entries b/contrib/libexec/mail.local/CVS/Entries deleted file mode 100644 index e02ca255..00000000 --- a/contrib/libexec/mail.local/CVS/Entries +++ /dev/null @@ -1,7 +0,0 @@ -/locking.c/1.10/Mon Jan 10 21:00:50 2011// -/mail.local.c/1.32/Tue Oct 27 23:59:31 2009// -/Makefile/1.3/Mon Jul 9 11:41:26 2012// -/mail.local.8/1.29/Mon Jul 9 11:36:35 2012// -/mail.local.h/1.5/Mon Jul 9 11:36:35 2012// -/pathnames.h/1.5/Mon Jul 9 11:36:35 2012// -D diff --git a/contrib/libexec/mail.local/CVS/Repository b/contrib/libexec/mail.local/CVS/Repository deleted file mode 100644 index ca372a1e..00000000 --- a/contrib/libexec/mail.local/CVS/Repository +++ /dev/null @@ -1 +0,0 @@ -src/libexec/mail.local diff --git a/contrib/libexec/mail.local/CVS/Root b/contrib/libexec/mail.local/CVS/Root deleted file mode 100644 index 7040dfb5..00000000 --- a/contrib/libexec/mail.local/CVS/Root +++ /dev/null @@ -1 +0,0 @@ -anoncvs@anoncvs.spacehopper.org:/cvs diff --git a/contrib/libexec/mail.local/Makefile.am b/contrib/libexec/mail.local/Makefile.am index 97325c74..217659c1 100644 --- a/contrib/libexec/mail.local/Makefile.am +++ b/contrib/libexec/mail.local/Makefile.am @@ -2,11 +2,11 @@ pkglibexec_PROGRAMS = mail.local mail_local_SOURCES = mail.local.c mail_local_SOURCES += locking.c -mail_local_SOURCES += $(top_srcdir)/smtpd/log.c +mail_local_SOURCES += $(top_srcdir)/usr.sbin/smtpd/log.c EXTRA_DIST = mail.local.h pathnames.h -AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat +AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat -DPATH_LIBEXEC=\"$(pkglibexecdir)\" LIBCOMPAT = $(top_builddir)/openbsd-compat/libopenbsd.a diff --git a/contrib/libexec/mail.local/locking.c b/contrib/libexec/mail.local/locking.c index ab6eb1a8..85a48d5e 100644 --- a/contrib/libexec/mail.local/locking.c +++ b/contrib/libexec/mail.local/locking.c @@ -1,4 +1,4 @@ -/* $OpenBSD: locking.c,v 1.10 2011/01/10 21:00:50 millert Exp $ */ +/* $OpenBSD: locking.c,v 1.14 2020/02/09 14:59:20 millert Exp $ */ /* * Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com> @@ -30,13 +30,15 @@ #include "includes.h" -#include <sys/param.h> +#include <sys/types.h> + #include <sys/stat.h> #include <fcntl.h> #include <pwd.h> #include <syslog.h> #include <time.h> #include <unistd.h> +#include <limits.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -45,7 +47,7 @@ #include "pathnames.h" #include "mail.local.h" -static char lpath[MAXPATHLEN]; +static char lpath[PATH_MAX]; void rellock(void) @@ -56,7 +58,7 @@ rellock(void) } int -getlock(char *name, struct passwd *pw) +getlock(const char *name, struct passwd *pw) { struct stat sb, fsb; int lfd=-1; @@ -66,9 +68,8 @@ getlock(char *name, struct passwd *pw) (void)snprintf(lpath, sizeof lpath, "%s/%s.lock", _PATH_MAILDIR, name); - if (stat(_PATH_MAILDIR, &sb) == -1) - merr(FATAL, "%s: %s", _PATH_MAILDIR, strerror(errno)); - if ((sb.st_mode & S_IWOTH) == S_IWOTH) { + 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. @@ -93,19 +94,12 @@ getlock(char *name, struct passwd *pw) } goto again; } -#ifndef O_EXLOCK -#define O_EXLOCK 0 -#endif if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK, S_IRUSR|S_IWUSR)) != -1) break; -#ifndef O_EXLOCK - /* XXX : do something! */ -#endif again: if (tries > 10) { - merr(NOTFATAL, "%s: %s", lpath, - strerror(errno)); + mwarn("%s: %s", lpath, strerror(errno)); seteuid(0); return(-1); } @@ -121,6 +115,7 @@ again: seteuid(pw->pw_uid); } } + close(lfd); } sleep(1U << tries); tries++; @@ -136,7 +131,7 @@ again: S_IRUSR|S_IWUSR)) != -1) break; if (tries > 9) { - merr(NOTFATAL, "%s: %s", lpath, strerror(errno)); + mwarn("%s: %s", lpath, strerror(errno)); return(-1); } sleep(1U << tries); @@ -149,7 +144,7 @@ again: void baditem(char *path) { - char npath[MAXPATHLEN]; + char npath[PATH_MAX]; int fd; if (unlink(path) == 0) @@ -161,19 +156,27 @@ baditem(char *path) if (rename(path, npath) == -1) unlink(npath); else - merr(NOTFATAL, "nasty spool item %s renamed to %s", - path, npath); + mwarn("nasty spool item %s renamed to %s", path, npath); /* XXX if we fail to rename, another attempt will happen later */ } void -merr(int isfatal, const char *fmt, ...) +mwarn(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); +} + +void +merr(int eval, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsyslog(LOG_ERR, fmt, ap); va_end(ap); - if (isfatal) - exit(1); + exit(eval); } diff --git a/contrib/libexec/mail.local/mail.local.8 b/contrib/libexec/mail.local/mail.local.8 index f77fa6da..330a4473 100644 --- a/contrib/libexec/mail.local/mail.local.8 +++ b/contrib/libexec/mail.local/mail.local.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: mail.local.8,v 1.29 2010/09/03 11:35:08 jmc Exp $ +.\" $OpenBSD: mail.local.8,v 1.31 2014/09/16 21:28:51 jmc Exp $ .\" Copyright (c) 1990 The Regents of the University of California. .\" All rights reserved. .\" @@ -28,7 +28,7 @@ .\" .\" from: @(#)mail.local.8 6.8 (Berkeley) 4/27/91 .\" -.Dd $Mdocdate: September 3 2010 $ +.Dd $Mdocdate: September 16 2014 $ .Dt MAIL.LOCAL 8 .Os .Sh NAME @@ -125,7 +125,7 @@ user's mailbox directory .Xr flock 2 , .Xr getservbyname 3 , .Xr comsat 8 , -.Xr sendmail 8 +.Xr smtpd 8 .Sh HISTORY A superset of .Nm @@ -134,17 +134,12 @@ A superset of as the program .Xr mail 1 . .Sh BUGS -Since -.Xr sendmail 8 -bases its idea of whether a message has been delivered or not -on the return value from -.Nm mail.local , -using quotas in +Using quotas in .Pa /var/mail -can be problematic. -By default, +can be problematic if using .Xr sendmail 8 -will ask +as an MTA, +since it asks .Nm to deliver a message to multiple recipients if possible. This causes problems in a quota environment since a message may be @@ -157,8 +152,13 @@ to attempt redelivery later. That means that some users will keep getting the same message every time .Xr sendmail 8 runs its queue. +This problem does not exist for +.Xr smtpd 8 +users. .Pp -If you are running with disk quotas on +If you are running +.Xr sendmail 8 +and have disk quotas on .Pa /var/mail it is imperative that you unset the .Dq m diff --git a/contrib/libexec/mail.local/mail.local.c b/contrib/libexec/mail.local/mail.local.c index d1f7d2f2..a574b3fe 100644 --- a/contrib/libexec/mail.local/mail.local.c +++ b/contrib/libexec/mail.local/mail.local.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mail.local.c,v 1.32 2009/10/27 23:59:31 deraadt Exp $ */ +/* $OpenBSD: mail.local.c,v 1.39 2020/02/09 14:59:20 millert Exp $ */ /*- * Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com> @@ -33,20 +33,25 @@ #include "includes.h" -#include <sys/param.h> +#include <sys/types.h> + #include <sys/stat.h> #include <sys/socket.h> +#include <sys/wait.h> #include <netinet/in.h> +#include <sysexits.h> #include <syslog.h> #include <fcntl.h> #include <netdb.h> #include <pwd.h> #include <time.h> #include <unistd.h> +#include <limits.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <signal.h> #include "pathnames.h" #include "mail.local.h" @@ -54,21 +59,21 @@ int main(int argc, char *argv[]) { struct passwd *pw; - int ch, fd, eval, lockfile=1, holdme=0; + int ch, fd, eval, lockfile=1; uid_t uid; char *from; openlog("mail.local", LOG_PERROR, LOG_MAIL); from = NULL; - while ((ch = getopt(argc, argv, "lLdf:r:H")) != -1) + while ((ch = getopt(argc, argv, "lLdf:r:")) != -1) switch (ch) { case 'd': /* backward compatible */ break; case 'f': case 'r': /* backward compatible */ if (from) - merr(FATAL, "multiple -f options"); + merr(EX_USAGE, "multiple -f options"); from = optarg; break; case 'l': @@ -77,25 +82,14 @@ main(int argc, char *argv[]) case 'L': lockfile=0; break; - case 'H': - holdme=1; - break; default: usage(); } argc -= optind; argv += optind; - /* Support -H flag for backwards compat */ - if (holdme) { - execl(_PATH_LOCKSPOOL, "lockspool", (char *)NULL); - merr(FATAL, "execl: lockspool: %s", strerror(errno)); - } else { - if (!*argv) - usage(); - if (geteuid() != 0) - merr(FATAL, "may only be run by the superuser"); - } + if (!*argv) + usage(); /* * If from not specified, use the name from getlogin() if the @@ -108,8 +102,10 @@ main(int argc, char *argv[]) from = (pw = getpwuid(uid)) ? pw->pw_name : "???"; fd = storemail(from); - for (eval = 0; *argv; ++argv) - eval |= deliver(fd, *argv, lockfile); + for (eval = 0; *argv; ++argv) { + if ((ch = deliver(fd, *argv, lockfile)) != 0) + eval = ch; + } exit(eval); } @@ -119,24 +115,31 @@ storemail(char *from) FILE *fp = NULL; time_t tval; int fd, eline; - ssize_t len; - size_t linesz; + size_t len; char *line, *tbuf; if ((tbuf = strdup(_PATH_LOCTMP)) == NULL) - merr(FATAL, "unable to allocate memory"); + merr(EX_OSERR, "unable to allocate memory"); if ((fd = mkstemp(tbuf)) == -1 || !(fp = fdopen(fd, "w+"))) - merr(FATAL, "unable to open temporary file"); + merr(EX_OSERR, "unable to open temporary file"); (void)unlink(tbuf); free(tbuf); (void)time(&tval); (void)fprintf(fp, "From %s %s", from, ctime(&tval)); - for (eline = 1, line = NULL, linesz = 0; - (len = getline(&line, &linesz, stdin)) != -1;) { + for (eline = 1, tbuf = NULL; (line = fgetln(stdin, &len));) { + /* We have to NUL-terminate the line since fgetln does not */ if (line[len - 1] == '\n') - line[--len] = '\0'; + line[len - 1] = '\0'; + else { + /* No trailing newline, so alloc space and copy */ + if ((tbuf = malloc(len + 1)) == NULL) + merr(EX_OSERR, "unable to allocate memory"); + memcpy(tbuf, line, len); + tbuf[len] = '\0'; + line = tbuf; + } if (line[0] == '\0') eline = 1; else { @@ -149,13 +152,13 @@ storemail(char *from) if (ferror(fp)) break; } - free(line); + free(tbuf); /* Output a newline; note, empty messages are allowed. */ (void)putc('\n', fp); (void)fflush(fp); if (ferror(fp)) - merr(FATAL, "temporary file write error"); + merr(EX_OSERR, "temporary file write error"); return(fd); } @@ -164,8 +167,8 @@ deliver(int fd, char *name, int lockfile) { struct stat sb, fsb; struct passwd *pw; - int mbfd=-1, rval=1, lfd=-1; - char biffmsg[100], buf[8*1024], path[MAXPATHLEN]; + int mbfd=-1, lfd=-1, rval=EX_OSERR; + char biffmsg[100], buf[8*1024], path[PATH_MAX]; off_t curoff; size_t off; ssize_t nr, nw; @@ -175,30 +178,27 @@ deliver(int fd, char *name, int lockfile) * handled in the sendmail aliases file. */ if (!(pw = getpwnam(name))) { - merr(NOTFATAL, "unknown name: %s", name); - return(1); + mwarn("unknown name: %s", name); + return(EX_NOUSER); } (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); + return(EX_OSERR); } /* after this point, always exit via bad to remove lockfile */ retry: if (lstat(path, &sb)) { if (errno != ENOENT) { - merr(NOTFATAL, "%s: %s", path, strerror(errno)); + mwarn("%s: %s", path, strerror(errno)); goto bad; } -#ifndef O_EXLOCK -#define O_EXLOCK 0 -#endif if ((mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|O_EXLOCK, - S_IRUSR|S_IWUSR)) < 0) { + S_IRUSR|S_IWUSR)) == -1) { #ifndef HAVE_O_EXLOCK /* XXX : do something! */ #endif @@ -206,7 +206,8 @@ retry: /* file appeared since lstat */ goto retry; } else { - merr(NOTFATAL, "%s: %s", path, strerror(errno)); + mwarn("%s: %s", path, strerror(errno)); + rval = EX_CANTCREAT; goto bad; } } @@ -216,49 +217,48 @@ retry: * that if the ownership or permissions were changed there * was a reason for doing so. */ - if (fchown(mbfd, pw->pw_uid, pw->pw_gid) < 0) { - merr(NOTFATAL, "chown %u:%u: %s", - pw->pw_uid, pw->pw_gid, name); + if (fchown(mbfd, pw->pw_uid, pw->pw_gid) == -1) { + mwarn("chown %u:%u: %s", pw->pw_uid, pw->pw_gid, name); goto bad; } } else { if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)) { - merr(NOTFATAL, "%s: linked or special file", path); + mwarn("%s: linked or special file", path); goto bad; } if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK, - S_IRUSR|S_IWUSR)) < 0) { - merr(NOTFATAL, "%s: %s", path, strerror(errno)); + S_IRUSR|S_IWUSR)) == -1) { + mwarn("%s: %s", path, strerror(errno)); goto bad; } - if (fstat(mbfd, &fsb)) { + if (fstat(mbfd, &fsb) == -1) { /* relating error to path may be bad style */ - merr(NOTFATAL, "%s: %s", path, strerror(errno)); + mwarn("%s: %s", path, strerror(errno)); goto bad; } if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) { - merr(NOTFATAL, "%s: changed after open", path); + mwarn("%s: changed after open", path); goto bad; } /* paranoia? */ if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) { - merr(NOTFATAL, "%s: linked or special file", path); + mwarn("%s: linked or special file", path); + rval = EX_CANTCREAT; goto bad; } } curoff = lseek(mbfd, 0, SEEK_END); - (void)snprintf(biffmsg, sizeof biffmsg, "%s@%qd\n", name, - (long long int) curoff); + (void)snprintf(biffmsg, sizeof biffmsg, "%s@%lld\n", name, curoff); if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { - merr(NOTFATAL, "temporary file: %s", strerror(errno)); + mwarn("temporary file: %s", strerror(errno)); goto bad; } while ((nr = read(fd, buf, sizeof(buf))) > 0) - for (off = 0; off < (size_t)nr; off += nw) - if ((nw = write(mbfd, buf + off, nr - off)) < 0) { - merr(NOTFATAL, "%s: %s", path, strerror(errno)); + for (off = 0; off < nr; off += nw) + if ((nw = write(mbfd, buf + off, nr - off)) == -1) { + mwarn("%s: %s", path, strerror(errno)); (void)ftruncate(mbfd, curoff); goto bad; } @@ -267,14 +267,12 @@ retry: rval = 0; } else { (void)ftruncate(mbfd, curoff); - merr(FATAL, "temporary file: %s", strerror(errno)); + mwarn("temporary file: %s", strerror(errno)); } bad: - if (lfd != -1) { - rellock(); - close(lfd); - } + if (lfd != -1) + unlockspool(); if (mbfd != -1) { (void)fsync(mbfd); /* Don't wait for update. */ @@ -289,39 +287,106 @@ bad: void notifybiff(char *msg) { - static struct sockaddr_in addr; + static struct addrinfo *res0; + struct addrinfo hints, *res; static int f = -1; - struct hostent *hp; - struct servent *sp; size_t len; + int error; - if (!addr.sin_family) { - /* Be silent if biff service not available. */ - if (!(sp = getservbyname("biff", "udp"))) - return; - if (!(hp = gethostbyname("localhost"))) { - merr(NOTFATAL, "localhost: %s", strerror(errno)); + if (res0 == NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + + error = getaddrinfo("localhost", "biff", &hints, &res0); + if (error) { + /* Be silent if biff service not available. */ + if (error != EAI_SERVICE) { + mwarn("localhost: %s", gai_strerror(error)); + } return; } -#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN - addr.sin_len = sizeof(struct sockaddr_in); -#endif - addr.sin_family = hp->h_addrtype; - addr.sin_port = sp->s_port; - bcopy(hp->h_addr, &addr.sin_addr, (size_t)hp->h_length); } - if (f < 0 && (f = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { - merr(NOTFATAL, "socket: %s", strerror(errno)); + + if (f == -1) { + for (res = res0; res != NULL; res = res->ai_next) { + f = socket(res->ai_family, res->ai_socktype, + res->ai_protocol); + if (f != -1) + break; + } + } + if (f == -1) { + mwarn("socket: %s", strerror(errno)); return; } - len = strlen(msg) + 1; - if (sendto(f, msg, len, 0, (struct sockaddr *)&addr, sizeof(addr)) - != (ssize_t)len) - merr(NOTFATAL, "sendto biff: %s", strerror(errno)); + + len = strlen(msg) + 1; /* XXX */ + if (sendto(f, msg, len, 0, res->ai_addr, res->ai_addrlen) != len) + mwarn("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(EX_OSERR, "pipe: %s", strerror(errno)); + return -1; + } + + signal(SIGPIPE, SIG_IGN); + switch ((lockpid = fork())) { + case -1: + merr(EX_OSERR, "fork: %s", strerror(errno)); + return -1; + case 0: + /* child */ + close(pfd[0]); + dup2(pfd[1], STDOUT_FILENO); + execl(_PATH_LOCKSPOOL, "lockspool", (char *)NULL); + merr(EX_OSERR, "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(EX_OSERR, "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) { - merr(FATAL, "usage: mail.local [-Ll] [-f from] user ..."); + merr(EX_USAGE, "usage: mail.local [-Ll] [-f from] user ..."); } diff --git a/contrib/libexec/mail.local/mail.local.h b/contrib/libexec/mail.local/mail.local.h index 0377aa20..bc3137cb 100644 --- a/contrib/libexec/mail.local/mail.local.h +++ b/contrib/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.7 2020/02/09 14:59:21 millert Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. @@ -29,14 +29,14 @@ * SUCH DAMAGE. */ -#define FATAL 1 -#define NOTFATAL 0 - void baditem(char *); int deliver(int, char *, int); void merr(int, const char *, ...); -int getlock(char *, struct passwd *); +void mwarn(const char *, ...); +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); diff --git a/contrib/libexec/mail.local/pathnames.h b/contrib/libexec/mail.local/pathnames.h index a39a6c90..0a2c2731 100644 --- a/contrib/libexec/mail.local/pathnames.h +++ b/contrib/libexec/mail.local/pathnames.h @@ -35,4 +35,4 @@ #endif #define _PATH_LOCTMP "/tmp/local.XXXXXXXXXX" -#define _PATH_LOCKSPOOL "/usr/libexec/lockspool" +#define _PATH_LOCKSPOOL PATH_LIBEXEC"/lockspool" |