diff options
author | 2020-04-30 02:06:46 +0200 | |
---|---|---|
committer | 2020-04-30 02:06:46 +0200 | |
commit | d4180f85d53f7381da9fcc7257cf61d0b29497a0 (patch) | |
tree | 928f5541f702f22aec334cd7262d611821ff44cf /contrib | |
parent | Merge remote-tracking branch 'portable/native' (diff) | |
download | OpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.tar.xz OpenSMTPD-d4180f85d53f7381da9fcc7257cf61d0b29497a0.zip |
merge histories
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/Makefile.am | 1 | ||||
-rw-r--r-- | contrib/libexec/Makefile.am | 1 | ||||
-rw-r--r-- | contrib/libexec/encrypt/Makefile.am | 13 | ||||
-rw-r--r-- | contrib/libexec/encrypt/encrypt.c | 102 | ||||
-rw-r--r-- | contrib/libexec/lockspool/Makefile.am | 20 | ||||
-rw-r--r-- | contrib/libexec/lockspool/locking.c | 181 | ||||
-rw-r--r-- | contrib/libexec/lockspool/lockspool.1 | 77 | ||||
-rw-r--r-- | contrib/libexec/lockspool/lockspool.c | 124 | ||||
-rw-r--r-- | contrib/libexec/lockspool/mail.local.h | 42 | ||||
-rw-r--r-- | contrib/libexec/lockspool/pathnames.h | 38 | ||||
-rw-r--r-- | contrib/libexec/mail.local/Makefile.am | 22 | ||||
-rw-r--r-- | contrib/libexec/mail.local/locking.c | 182 | ||||
-rw-r--r-- | contrib/libexec/mail.local/mail.local.8 | 183 | ||||
-rw-r--r-- | contrib/libexec/mail.local/mail.local.c | 392 | ||||
-rw-r--r-- | contrib/libexec/mail.local/mail.local.h | 42 | ||||
-rw-r--r-- | contrib/libexec/mail.local/pathnames.h | 38 |
16 files changed, 1458 insertions, 0 deletions
diff --git a/contrib/Makefile.am b/contrib/Makefile.am new file mode 100644 index 00000000..37a8e73a --- /dev/null +++ b/contrib/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = libexec diff --git a/contrib/libexec/Makefile.am b/contrib/libexec/Makefile.am new file mode 100644 index 00000000..0e3a271f --- /dev/null +++ b/contrib/libexec/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = mail.local lockspool encrypt diff --git a/contrib/libexec/encrypt/Makefile.am b/contrib/libexec/encrypt/Makefile.am new file mode 100644 index 00000000..6ad7b82d --- /dev/null +++ b/contrib/libexec/encrypt/Makefile.am @@ -0,0 +1,13 @@ +pkglibexec_PROGRAMS = encrypt + +encrypt_SOURCES = encrypt.c +encrypt_SOURCES += $(top_srcdir)/smtpd/log.c + +AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat + +LIBCOMPAT = $(top_builddir)/openbsd-compat/libopenbsd.a + +LDADD = $(LIBCOMPAT) + +uninstall-hook: + rmdir $(DESTDIR)$(pkglibexecdir) 2> /dev/null || /bin/true diff --git a/contrib/libexec/encrypt/encrypt.c b/contrib/libexec/encrypt/encrypt.c new file mode 100644 index 00000000..80275921 --- /dev/null +++ b/contrib/libexec/encrypt/encrypt.c @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013 Sunil Nimmagadda <sunil@sunilnimmagadda.com> + * Copyright (c) 2013 Gilles Chehade <gilles@poolp.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. + */ + +#include "includes.h" + +#ifdef HAVE_CRYPT_H +#include <crypt.h> /* needed for crypt() */ +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#define PASSWORD_LEN 128 +#define SALT_LEN 16 + +static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + +static void to64(char *, long int, int); +static void print_passwd(const char *); + +int +main(int argc, char *argv[]) +{ + char *line; + size_t linesz; + ssize_t linelen; + + if (argc > 2) { + fprintf(stderr, "usage: encrypt <string>\n"); + return (1); + } + + if (argc == 2) { + print_passwd(argv[1]); + return (0); + } + + line = NULL; + linesz = 0; + while ((linelen = getline(&line, &linesz, stdin)) != -1) { + if (line[linelen - 1] == '\n') + line[linelen - 1] = '\0'; + print_passwd(line); + } + free(line); + + return (0); +} + +void +print_passwd(const char *string) +{ + const char *ids[] = { "2a", "6", "5", "3", "2", "1", NULL }; + const char *id; + char salt[SALT_LEN+1]; + char buffer[PASSWORD_LEN]; + int n; + const char *p; + + for (n = 0; n < SALT_LEN; ++n) + to64(&salt[n], arc4random_uniform(0xff), 1); + salt[SALT_LEN] = '\0'; + + for (n = 0; ids[n]; n++) { + id = ids[n]; + (void)snprintf(buffer, sizeof buffer, "$%s$%s$", id, salt); + if ((p = crypt(string, buffer)) == NULL) + continue; + if (strncmp(p, buffer, strlen(buffer)) != 0) + continue; + printf("%s\n", p); + return; + } + + salt[2] = 0; + printf("%s\n", crypt(string, salt)); +} + +void +to64(char *s, long int v, int n) +{ + while (--n >= 0) { + *s++ = itoa64[v & 0x3f]; + v >>= 6; + } +} diff --git a/contrib/libexec/lockspool/Makefile.am b/contrib/libexec/lockspool/Makefile.am new file mode 100644 index 00000000..dacf5386 --- /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)/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/Makefile.am b/contrib/libexec/mail.local/Makefile.am new file mode 100644 index 00000000..bd5211a2 --- /dev/null +++ b/contrib/libexec/mail.local/Makefile.am @@ -0,0 +1,22 @@ +pkglibexec_PROGRAMS = mail.local + +mail_local_SOURCES = mail.local.c +mail_local_SOURCES += locking.c +mail_local_SOURCES += $(top_srcdir)/smtpd/log.c + +EXTRA_DIST = mail.local.h pathnames.h + +AM_CPPFLAGS = -I$(top_srcdir)/openbsd-compat -DPATH_LIBEXEC=\"$(pkglibexecdir)\" + +LIBCOMPAT = $(top_builddir)/openbsd-compat/libopenbsd.a + +LDADD = $(LIBCOMPAT) + +# need to define _GNU_SOURCE to get: +# EAI_NODATA defined +# {v,}asprintf +# setres{g,u}id +#CFLAGS += -D_GNU_SOURCE + +uninstall-hook: + rmdir $(DESTDIR)$(pkglibexecdir) 2> /dev/null || /bin/true diff --git a/contrib/libexec/mail.local/locking.c b/contrib/libexec/mail.local/locking.c new file mode 100644 index 00000000..85a48d5e --- /dev/null +++ b/contrib/libexec/mail.local/locking.c @@ -0,0 +1,182 @@ +/* $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/mail.local/mail.local.8 b/contrib/libexec/mail.local/mail.local.8 new file mode 100644 index 00000000..330a4473 --- /dev/null +++ b/contrib/libexec/mail.local/mail.local.8 @@ -0,0 +1,183 @@ +.\" $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. +.\" +.\" 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: @(#)mail.local.8 6.8 (Berkeley) 4/27/91 +.\" +.Dd $Mdocdate: September 16 2014 $ +.Dt MAIL.LOCAL 8 +.Os +.Sh NAME +.Nm mail.local +.Nd store mail in a mailbox +.Sh SYNOPSIS +.Nm mail.local +.Op Fl Ll +.Op Fl f Ar from +.Ar user ... +.Sh DESCRIPTION +.Nm +reads the standard input up to an end-of-file and appends it to each +.Ar user Ns 's +.Pa mail +file. +The +.Ar user +must be a valid user name. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl f Ar from +Specify the sender's name. +.It Fl L +Don't create a +.Pa username.lock +file while locking the spool. +.It Fl l +For compatibility, request that files named +.Pa username.lock +be used for locking. +(This is the default behavior.) +.El +.Pp +Individual mail messages in the mailbox are delimited by an empty +line followed by a line beginning with the string +.Dq "From\&\ " . +A line containing the string +.Dq "From\&\ " , +the sender's name and a timestamp is prepended to each delivered mail message. +A blank line is appended to each message. +A greater-than character +.Pq Ql > +is prepended to any line in the message which could be mistaken for a +.Dq "From\&\ " +delimiter line. +.Pp +Significant efforts have been made to ensure that +.Nm +acts as securely as possible if the spool directory is mode 1777 or 755. +The default of mode 755 is more secure, but it prevents mail clients from using +.Pa username.lock +style locking. +The use of 1777 is more flexible in an NFS shared-spool environment, +so many sites use it. +However, it does carry some risks, such as attackers filling the spool disk. +Some of these problems may be alleviated +by making the spool a separate filesystem, and placing quotas on it. +The use of any mode other than 1777 and 755 for the spool directory is +recommended against but may work properly. +.Pp +The mailbox is always locked using +.Xr flock 2 +while mail is appended. +Unless the +.Fl L +flag is specified, a +.Pa username.lock +file is also used. +.Pp +If the +.Xr biff 1 +service is returned by +.Xr getservbyname 3 , +the biff server is notified of delivered mail. +.Sh ENVIRONMENT +.Bl -tag -width indent +.It Ev TZ +Used to set the appropriate time zone on the timestamp. +.El +.Sh FILES +.Bl -tag -width /tmp/local.XXXXXXXXXX -compact +.It Pa /tmp/local.XXXXXXXXXX +temporary files +.It Pa /var/mail/user +user's mailbox directory +.El +.Sh EXIT STATUS +.Ex -std mail.local +.Sh SEE ALSO +.Xr biff 1 , +.Xr mail 1 , +.Xr flock 2 , +.Xr getservbyname 3 , +.Xr comsat 8 , +.Xr smtpd 8 +.Sh HISTORY +A superset of +.Nm +(handling mailbox reading as well as mail delivery) appeared in +.At v7 +as the program +.Xr mail 1 . +.Sh BUGS +Using quotas in +.Pa /var/mail +can be problematic if using +.Xr sendmail 8 +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 +delivered to some users but not others due to disk quotas. +Even though the message was delivered to some of the recipients, +.Nm +will exit with an exit code > 0, causing +.Xr sendmail 8 +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 +.Xr sendmail 8 +and have disk quotas on +.Pa /var/mail +it is imperative that you unset the +.Dq m +mailer flag for the +.Sq local +mailer. +To do this, locate the line beginning with +.Dq Mlocal +in +.Pa /etc/mail/sendmail.cf +and remove the +.Dq m +from the flags section, denoted by +.Dq F= . +Alternately, you can override the default mailer flags by adding the line: +.Pp +.Dl define(`LOCAL_MAILER_FLAGS', `rn9S')dnl +.Pp +to your +.Dq \.mc +file (this is the source file that is used to generate +.Pa /etc/mail/sendmail.cf ) . diff --git a/contrib/libexec/mail.local/mail.local.c b/contrib/libexec/mail.local/mail.local.c new file mode 100644 index 00000000..a574b3fe --- /dev/null +++ b/contrib/libexec/mail.local/mail.local.c @@ -0,0 +1,392 @@ +/* $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> + * Copyright (c) 1996-1998 David Mazieres <dm@lcs.mit.edu> + * 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. + */ + +#include "includes.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" + +int +main(int argc, char *argv[]) +{ + struct passwd *pw; + 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:")) != -1) + switch (ch) { + case 'd': /* backward compatible */ + break; + case 'f': + case 'r': /* backward compatible */ + if (from) + merr(EX_USAGE, "multiple -f options"); + from = optarg; + break; + case 'l': + lockfile=1; + break; + case 'L': + lockfile=0; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (!*argv) + usage(); + + /* + * If from not specified, use the name from getlogin() if the + * uid matches, otherwise, use the name from the password file + * corresponding to the uid. + */ + uid = getuid(); + if (!from && (!(from = getlogin()) || + !(pw = getpwnam(from)) || pw->pw_uid != uid)) + from = (pw = getpwuid(uid)) ? pw->pw_name : "???"; + + fd = storemail(from); + for (eval = 0; *argv; ++argv) { + if ((ch = deliver(fd, *argv, lockfile)) != 0) + eval = ch; + } + exit(eval); +} + +int +storemail(char *from) +{ + FILE *fp = NULL; + time_t tval; + int fd, eline; + size_t len; + char *line, *tbuf; + + if ((tbuf = strdup(_PATH_LOCTMP)) == NULL) + merr(EX_OSERR, "unable to allocate memory"); + if ((fd = mkstemp(tbuf)) == -1 || !(fp = fdopen(fd, "w+"))) + 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, tbuf = NULL; (line = fgetln(stdin, &len));) { + /* We have to NUL-terminate the line since fgetln does not */ + if (line[len - 1] == '\n') + 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 { + if (eline && line[0] == 'F' && len > 5 && + !memcmp(line, "From ", 5)) + (void)putc('>', fp); + eline = 0; + } + (void)fprintf(fp, "%s\n", line); + if (ferror(fp)) + break; + } + free(tbuf); + + /* Output a newline; note, empty messages are allowed. */ + (void)putc('\n', fp); + (void)fflush(fp); + if (ferror(fp)) + merr(EX_OSERR, "temporary file write error"); + return(fd); +} + +int +deliver(int fd, char *name, int lockfile) +{ + struct stat sb, fsb; + struct passwd *pw; + 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; + + /* + * Disallow delivery to unknown names -- special mailboxes can be + * handled in the sendmail aliases file. + */ + if (!(pw = getpwnam(name))) { + mwarn("unknown name: %s", name); + return(EX_NOUSER); + } + + (void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR, name); + + if (lockfile) { + lfd = lockspool(name, pw); + if (lfd == -1) + return(EX_OSERR); + } + + /* after this point, always exit via bad to remove lockfile */ +retry: + if (lstat(path, &sb)) { + if (errno != ENOENT) { + mwarn("%s: %s", path, strerror(errno)); + goto bad; + } + if ((mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|O_EXLOCK, + S_IRUSR|S_IWUSR)) == -1) { +#ifndef HAVE_O_EXLOCK + /* XXX : do something! */ +#endif + if (errno == EEXIST) { + /* file appeared since lstat */ + goto retry; + } else { + mwarn("%s: %s", path, strerror(errno)); + rval = EX_CANTCREAT; + goto bad; + } + } + /* + * Set the owner and group. Historically, binmail repeated + * this at each mail delivery. We no longer do this, assuming + * that if the ownership or permissions were changed there + * was a reason for doing so. + */ + 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)) { + mwarn("%s: linked or special file", path); + goto bad; + } + if ((mbfd = open(path, O_APPEND|O_WRONLY|O_EXLOCK, + S_IRUSR|S_IWUSR)) == -1) { + mwarn("%s: %s", path, strerror(errno)); + goto bad; + } + if (fstat(mbfd, &fsb) == -1) { + /* relating error to path may be bad style */ + mwarn("%s: %s", path, strerror(errno)); + goto bad; + } + if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) { + mwarn("%s: changed after open", path); + goto bad; + } + /* paranoia? */ + if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)) { + mwarn("%s: linked or special file", path); + rval = EX_CANTCREAT; + goto bad; + } + } + + curoff = lseek(mbfd, 0, SEEK_END); + (void)snprintf(biffmsg, sizeof biffmsg, "%s@%lld\n", name, curoff); + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { + mwarn("temporary file: %s", strerror(errno)); + goto bad; + } + + while ((nr = read(fd, buf, sizeof(buf))) > 0) + 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; + } + + if (nr == 0) { + rval = 0; + } else { + (void)ftruncate(mbfd, curoff); + mwarn("temporary file: %s", strerror(errno)); + } + +bad: + if (lfd != -1) + unlockspool(); + + if (mbfd != -1) { + (void)fsync(mbfd); /* Don't wait for update. */ + (void)close(mbfd); /* Implicit unlock. */ + } + + if (!rval) + notifybiff(biffmsg); + return(rval); +} + +void +notifybiff(char *msg) +{ + static struct addrinfo *res0; + struct addrinfo hints, *res; + static int f = -1; + size_t len; + int error; + + 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; + } + } + + 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; /* 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(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 new file mode 100644 index 00000000..bc3137cb --- /dev/null +++ b/contrib/libexec/mail.local/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/mail.local/pathnames.h b/contrib/libexec/mail.local/pathnames.h new file mode 100644 index 00000000..0a2c2731 --- /dev/null +++ b/contrib/libexec/mail.local/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" |