Article View: comp.mail.sendmail
Article #52Re: System mailbox in user's home directory. How?!
From: Paul A Vixie
Date: Tue, 03 Nov 1992 20:40
Date: Tue, 03 Nov 1992 20:40
184 lines
6187 bytes
6187 bytes
this can't be done through the aliases file, for two reasons: (1) sendmail
runs as the sender (if sender is a local user) or as daemon (or whatever Ou
is in the .cf file); as you've noted, this means that the ~user/sys-mbox
files will all be owned by the first sender and subsequent messages will
not be deliverable for permission reasons; (2) there is no locking at all
on sendmail's "append to file" alias mechanism -- so there is no way for
a user agent to know that a message is being appended while a user is
reading or deleting messages from her mailbox.
what you need is to create a small C program that will do what you want,
and call it instead of "/bin/mail -d $u" to deliver local mail. as an
exercise, i just wrote such a small C program and tested it. here it is,
without warranty or support or promise. Watch out for my signature...
/* homedelivery - deliver a message to file in user's home dir (from sendmail)
* vix 03nov92 [original]
*/
/*
* This program is intended to be used instead of /bin/mail if you wish to
* deliver mail to file in the user's home directory instead of to a file
* in the system's main spool directory as /bin/mail would do. The locking
* used is flock(), which means that your user agent had better be compiled
* to use flock() as well or mail may be lost if it is delivered while the
* user agent is pulling old mail out.
*
* This program makes no sanity checks on the format of the message on stdin.
* After locating and opening the mailbox file, stdin is appended without any
* translation whatever; marker of four control-A characters is appended after
* the message, since MM and MH use that to delimit messages in a mail drop.
* Because this program is so blaise about appending random trash to mailboxes,
* it should be made executable only by the uid or gid used by your transport,
* except that this doesn't work in sendmail's case since it runs as the
* sender if the sender is local. This program must run as root since it
* must "become" the recipient in order to safely open files in her home
* directory. Mode 4555, owner root, will work though it opens you to
* denial-of-service attacks from other local users. (So does /bin/mail.)
* Life would be just wonderful if there were a way for this process to
* verify that it is a child of the transport (sendmail, for example), but
* that's impossible to do in a portable way.
*
* Paul Vixie <vix@al.org>, November 3, 1992
*/
#include <stdio.h>
#include <pwd.h>
#include <sysexits.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/file.h>
#define STDIN 0
static char MailboxFile[] = "system-mailbox";
static char Marker[] = "\001\001\001\001\n";
static char *Prog;
static int MailboxMode = 0600;
static int HomeDelivery();
static void AlarmTimer();
static char *User;
main(argc, argv)
int argc;
char **argv;
{
int errors;
Prog = *argv++;
argc--;
if (argc < 1) {
fprintf(stderr, "usage: %s username [...]\n");
exit(EX_USAGE);
}
errors = 0;
while (argc--) {
errors += HomeDelivery(*argv++);
}
if (errors) {
exit(EX_NOUSER);
}
exit(EX_OK);
}
static int
HomeDelivery(user)
char *user;
{
struct passwd *pw;
unsigned short status;
int mailbox, buflen;
char buffer[BUFSIZ];
pw = getpwnam(user);
if (!pw) {
fprintf(stderr, "%s: no such user \"%s\"",
Prog, user);
return 1;
}
/* fork to avoid losing exec's setuid bits from set[gu]id calls */
switch (fork()) {
case -1: fprintf(stderr, "%s: can't fork (user was %s) - %s\n",
Prog, user, strerror(errno));
return 1;
case 0: /* child */
break;
default: wait(&status);
return (status >> 8);
}
/* child continues */
if (0 > initgroups(user, pw->pw_gid)) {
fprintf(stderr, "%s: getgroups(%s, %d) - %s\n",
Prog, user, pw->pw_gid, strerror(errno));
exit(1);
}
if (0 > setuid(pw->pw_uid)) {
fprintf(stderr, "%s: setuid(%d) (user %s) - %s\n",
Prog, pw->pw_uid, user, strerror(errno));
exit(1);
}
if (0 > chdir(pw->pw_dir)) {
fprintf(stderr, "%s: ~%s (%s) - %s\n",
Prog, user, pw->pw_dir, strerror(errno));
exit(1);
}
mailbox = open(MailboxFile, O_WRONLY|O_APPEND|O_CREAT, MailboxMode);
if (mailbox < 0) {
fprintf(stderr, "%s: %s/%s - %s\n",
Prog, pw->pw_dir, MailboxFile, strerror(errno));
exit(1);
}
User = user;
signal(SIGALRM, AlarmTimer);
alarm(300); /* 5 minutes */
if (0 < flock(mailbox, LOCK_EX)) {
fprintf(stderr, "%s: flock(%s/%s) - %s\n",
Prog, pw->pw_dir, MailboxFile, strerror(errno));
exit(1);
}
alarm(0);
signal(SIGALRM, SIG_DFL);
/* close() or exit() will implicitly flock(LOCK_UN) for us */
while (0 < (buflen = read(STDIN, buffer, BUFSIZ))) {
write(mailbox, buffer, buflen);
}
if (0 == buflen) {
buflen = write(mailbox, Marker, strlen(Marker));
}
if (0 > buflen) {
fprintf(stderr, "%s: write() failed - %s\n",
Prog, strerror(errno));
exit(1);
}
if (0 > close(mailbox)) {
fprintf(stderr, "%s: close() failed - %s\n",
Prog, strerror(errno));
exit(1);
}
exit(0);
}
static void
AlarmTimer()
{
fprintf(stderr, "%s: flock timed out - mail not sent to %s\n",
Prog, User);
exit(1);
}
--
Paul Vixie, DEC Network Systems Lab
Palo Alto, California, USA "Don't be a rebel, or a conformist;
<vixie@pa.dec.com> decwrl!vixie they're the same thing, anyway. Find
<paul@vix.com> vixie!paul your own path, and stay on it." -me
Technical Details
Message-ID:
<VIXIE.92Nov3124030@cognition.pa.dec.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!usc!sdd.hp.com!zaphod.mps.ohio-state.edu!cs.utexas.edu!sun-barr!olivea!decwrl!pa.dec.com!vixieReferences:
<1992Nov3.121126.608@cine88.cineca.it>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!usc!sdd.hp.com!zaphod.mps.ohio-state.edu!cs.utexas.edu!sun-barr!olivea!decwrl!pa.dec.com!vixie From: vixie@pa.dec.com (Paul A Vixie) Newsgroups: comp.mail.sendmail Subject: Re: System mailbox in user's home directory. How?! Message-ID: <VIXIE.92Nov3124030@cognition.pa.dec.com> Date: 3 Nov 92 20:40:30 GMT References: <1992Nov3.121126.608@cine88.cineca.it> Sender: news@PA.dec.com (News) Organization: DEC Network Software Lab Lines: 184 In-Reply-To: marcello@deis20.cineca.it's message of 3 Nov 92 12:11:26 +0100