🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.mail.sendmail
Article #52

Re: System mailbox in user's home directory. How?!

#52
From: Paul A Vixie
Date: Tue, 03 Nov 1992 20:40
184 lines
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!vixie
References: <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