From b9c8c1657f0b305bf96d70e952ec8cf2ec33504c Mon Sep 17 00:00:00 2001 From: gilles Date: Wed, 25 Jul 2018 10:19:28 +0000 Subject: [PATCH] delivery to a filename should be in mbox format otherwise it will lack the ^From separator and corrupt files ok eric@ --- usr.sbin/smtpd/lka_session.c | 4 +- usr.sbin/smtpd/mail.mboxfile.8 | 34 ++++++++++++ usr.sbin/smtpd/mail.mboxfile.c | 99 ++++++++++++++++++++++++++++++++++ usr.sbin/smtpd/mail/Makefile | 6 +-- 4 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 usr.sbin/smtpd/mail.mboxfile.8 create mode 100644 usr.sbin/smtpd/mail.mboxfile.c diff --git a/usr.sbin/smtpd/lka_session.c b/usr.sbin/smtpd/lka_session.c index 28be05ee781..3c1cbe1ac31 100644 --- a/usr.sbin/smtpd/lka_session.c +++ b/usr.sbin/smtpd/lka_session.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lka_session.c,v 1.86 2018/07/08 13:10:49 gilles Exp $ */ +/* $OpenBSD: lka_session.c,v 1.87 2018/07/25 10:19:28 gilles Exp $ */ /* * Copyright (c) 2011 Gilles Chehade @@ -515,7 +515,7 @@ lka_submit(struct lka_session *lks, struct rule *rule, struct expandnode *xn) "run with %s privileges", SMTPD_USER); if (xn->type == EXPAND_FILENAME) - format = "/bin/cat - >> %s"; + format = "/usr/libexec/mail.mboxfile -f %%{mbox.from} %s"; else if (xn->type == EXPAND_FILTER) format = "%s"; (void)snprintf(ep->mda_exec, sizeof(ep->mda_exec), diff --git a/usr.sbin/smtpd/mail.mboxfile.8 b/usr.sbin/smtpd/mail.mboxfile.8 new file mode 100644 index 00000000000..015adcb518a --- /dev/null +++ b/usr.sbin/smtpd/mail.mboxfile.8 @@ -0,0 +1,34 @@ +.\" $OpenBSD: mail.mboxfile.8,v 1.1 2018/07/25 10:19:28 gilles Exp $ +.\" +.\" Copyright (c) 2017 Gilles Chehade +.\" +.\" 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: July 25 2018 $ +.Dt MAIL.MDA 8 +.Os +.Sh NAME +.Nm mail.mboxfile +.Nd deliver mail to a file in mbox format +.Sh SYNOPSIS +.Nm mail.mboxfile +.Ar file +.Sh DESCRIPTION +.Nm +appends mail to a file in mbox format and acknowledges delivery success or failure +with its exit status. +.Sh EXIT STATUS +.Ex -std mail.mboxfile +.Sh SEE ALSO +.Xr mail 1 , +.Xr smtpd 8 diff --git a/usr.sbin/smtpd/mail.mboxfile.c b/usr.sbin/smtpd/mail.mboxfile.c new file mode 100644 index 00000000000..6dbcc0583b4 --- /dev/null +++ b/usr.sbin/smtpd/mail.mboxfile.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018 Gilles Chehade + * + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void mboxfile_engine(const char *sender, const char *filename); + +int +main(int argc, char *argv[]) +{ + int ch; + char *sender = ""; + + if (! geteuid()) + errx(1, "mail.mboxfile: may not be executed as root"); + + while ((ch = getopt(argc, argv, "f:")) != -1) { + switch (ch) { + case 'f': + sender = optarg; + break; + default: + break; + } + } + argc -= optind; + argv += optind; + + if (argc > 1) + errx(1, "mail.mboxfile: only one mboxfile is allowed"); + + mboxfile_engine(sender, argv[0]); + + return (0); +} + +static void +mboxfile_engine(const char *sender, const char *filename) +{ + int fd; + FILE *fp; + char *line = NULL; + size_t linesize = 0; + ssize_t linelen; + time_t now; + + time(&now); + + fd = open(filename, O_CREAT | O_APPEND | O_WRONLY | O_EXLOCK, 0600); + if (fd < 0) + err(1, NULL); + + if ((fp = fdopen(fd, "w")) == NULL) + err(1, NULL); + + fprintf(fp, "From %s %s", sender, ctime(&now)); + while ((linelen = getline(&line, &linesize, stdin)) != -1) { + line[strcspn(line, "\n")] = '\0'; + if (strncmp(line, "From ", 5) == 0) + fprintf(fp, ">%s\n", line); + else + fprintf(fp, "%s\n", line); + } + fprintf(fp, "\n"); + free(line); + if (ferror(stdin)) + err(1, NULL); + + if (fflush(fp) == EOF || + ferror(fp) || + fsync(fd) < 0 || + fclose(fp) == EOF) + err(1, NULL); +} diff --git a/usr.sbin/smtpd/mail/Makefile b/usr.sbin/smtpd/mail/Makefile index 8ac3eb0a7a4..b2bc2a2683c 100644 --- a/usr.sbin/smtpd/mail/Makefile +++ b/usr.sbin/smtpd/mail/Makefile @@ -1,9 +1,9 @@ -# $OpenBSD: Makefile,v 1.7 2018/05/23 12:51:41 tb Exp $ +# $OpenBSD: Makefile,v 1.8 2018/07/25 10:19:28 gilles Exp $ .PATH: ${.CURDIR}/.. -PROGS= mail.lmtp mail.maildir mail.mda +PROGS= mail.lmtp mail.maildir mail.mboxfile mail.mda -MAN= mail.lmtp.8 mail.maildir.8 mail.mda.8 +MAN= mail.lmtp.8 mail.maildir.8 mail.mboxfile.8 mail.mda.8 BINOWN= root BINGRP= wheel -- 2.20.1