chip@ateng.ateng.com (Chip Salzenberg) (11/30/88)
This is an offical patch for deliver 1.00. Please apply it. Patch number: 5 Date: 29 Nov 1988 Priority: SKY-HIGH Changes: The big change: Temp files are kept with modes of zero. The filenames given to delivery files in $HEADER and $BODY are now *copies* of the original temp files. This is an important change; it prevents errant delivery files from stomping on the real temp files, which are later copied into mailboxes. Temp files are no longer given to a user when writing to his mailbox. Makefile target "clobber" now implies "clean". New program "uid" eliminates klugy test for root in Makefile. Index: patchlevel.h Prereq: 4 *************** *** 1 **** ! #define PATCHLEVEL 4 --- 1 ---- ! #define PATCHLEVEL 5 Index: Makefile *************** *** 1,4 **** ! # $Header: Makefile,v 1.8 88/11/21 13:11:27 network Exp $ # # Makefile for deliver # --- 1,4 ---- ! # $Header: Makefile,v 1.11 88/11/28 18:45:20 network Exp $ # # Makefile for deliver # *************** *** 71,76 **** --- 71,78 ---- SRC2 = main.c mbox.c procs.c subs.c sysdep.c uucp.c SRCS = $(SRC1) $(SRC2) + UIDSRC = uid.c + OBJS = context.o copymsg.o debug.o dest.o dfile.o lock.o \ main.o mbox.o procs.o subs.o sysdep.o uucp.o *************** *** 81,106 **** .PHONY: all install lint shar clean clobber # # How to compile and link the program. # ! all: deliver deliver: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(OBJS): $(HDRS) ! clean:: ! rm -f $(OBJS) ! ! # ! # This is a klugy way to determine if you are root or not. ! # I'm open to suggestions! (Remember that 'su' counts.) ! # ! ! install: deliver ! @if [ ! -w /etc ]; \ then \ - echo ""; \ echo "Sorry! You must be root to install deliver."; \ exit 1; \ fi --- 83,106 ---- .PHONY: all install lint shar clean clobber # + # "make clobber" implies "make clean". + # + + clobber:: clean + + # # How to compile and link the program. # ! all: deliver uid ! deliver: $(OBJS) $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) $(OBJS): $(HDRS) ! install: deliver uid ! @if [ `./uid -uU | fgrep '(root)' | wc -l` -ne 2 ]; \ then \ echo "Sorry! You must be root to install deliver."; \ exit 1; \ fi *************** *** 109,127 **** chown root $(BIN)/deliver chmod 4711 $(BIN)/deliver clobber:: rm -f deliver # # Look for fuzz. # ! lint: lint.out ! lint.out: $(HDRS) $(SRCS) ! lint $(SRCS) -lc $(LIBS) >lint.out clean:: ! rm -f lint.out # # Make distribution sharchives. --- 109,146 ---- chown root $(BIN)/deliver chmod 4711 $(BIN)/deliver + clean:: + rm -f $(OBJS) clobber:: rm -f deliver # + # A little program to check on user and group id's. + # (I wish that the System V "id" program were available everywhere.) + # + + uid: $(UIDSRC) sysdep.o + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(UIDSRC) sysdep.o $(LIBS) + @rm -f $@.o + uid: config.h + + clobber:: + rm -f uid + + # # Look for fuzz. # ! lint: deliver.lint uid.lint + deliver.lint: $(HDRS) $(SRCS) + lint $(SRCS) -lc $(LIBS) >$@ + + uid.lint: uid.c + lint uid.c -lc $(LIBS) >$@ + clean:: ! rm -f *.lint # # Make distribution sharchives. *************** *** 128,135 **** # shar: $(DELSHAR).01 $(DELSHAR).02 $(DELSHAR).03 ! $(DELSHAR).01: $(DOCS) $(MF) $(HDRS) ! $(SHAR) >$@ $(DOCS) $(MF) $(HDRS) $(DELSHAR).02: $(SRC1) $(SHAR) >$@ $(SRC1) $(DELSHAR).03: $(SRC2) --- 147,154 ---- # shar: $(DELSHAR).01 $(DELSHAR).02 $(DELSHAR).03 ! $(DELSHAR).01: $(DOCS) $(MF) $(HDRS) $(UIDSRC) ! $(SHAR) >$@ $(DOCS) $(MF) $(HDRS) $(UIDSRC) $(DELSHAR).02: $(SRC1) $(SHAR) >$@ $(SRC1) $(DELSHAR).03: $(SRC2) Index: copymsg.c *************** *** 1,9 **** ! /* $Header: copymsg.c,v 1.2 88/11/18 12:17:40 network Exp $ * * Take the message from standard input and write it to two temp files, * one for the header (including the empty line) and one for the body. * * $Log: copymsg.c,v $ * Revision 1.2 88/11/18 12:17:40 network * patch2: Improved signal handling. * patch2: Make sure all environment variables are always provided. --- 1,13 ---- ! /* $Header: copymsg.c,v 1.3 88/11/28 18:07:46 network Exp $ * * Take the message from standard input and write it to two temp files, * one for the header (including the empty line) and one for the body. * * $Log: copymsg.c,v $ + * Revision 1.3 88/11/28 18:07:46 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.2 88/11/18 12:17:40 network * patch2: Improved signal handling. * patch2: Make sure all environment variables are always provided. *************** *** 51,57 **** * Create temporary files to hold the header and message body. */ ! for (t = 0; t < T_MAX; ++t) { int fd; --- 55,61 ---- * Create temporary files to hold the header and message body. */ ! for (t = T_HDR; t <= T_BODY; ++t) { int fd; *************** *** 77,83 **** if (verbose) { message("header=%s, body=%s\n", ! tfile[T_HEADER], tfile[T_BODY]); } /* --- 81,87 ---- if (verbose) { message("header=%s, body=%s\n", ! tfile[T_HDR], tfile[T_BODY]); } /* *************** *** 152,162 **** * Finally! Write the From_ line. */ ! (void) fputs("From ", dfp[T_HEADER]); ! (void) fputs(sender, dfp[T_HEADER]); ! (void) fputc(' ', dfp[T_HEADER]); (void) time(&now); ! (void) fputs(ctime(&now), dfp[T_HEADER]); /* * Copy the rest of the header (if any). --- 156,166 ---- * Finally! Write the From_ line. */ ! (void) fputs("From ", dfp[T_HDR]); ! (void) fputs(sender, dfp[T_HDR]); ! (void) fputc(' ', dfp[T_HDR]); (void) time(&now); ! (void) fputs(ctime(&now), dfp[T_HDR]); /* * Copy the rest of the header (if any). *************** *** 198,204 **** if (isspace(buf[0])) ; /* continuation */ else if (ISFROM(buf) || (buf[0] == '>')) ! (void) fputc('>', dfp[T_HEADER]); else { /* look for the colon on a header label */ --- 202,208 ---- if (isspace(buf[0])) ; /* continuation */ else if (ISFROM(buf) || (buf[0] == '>')) ! (void) fputc('>', dfp[T_HDR]); else { /* look for the colon on a header label */ *************** *** 212,218 **** /* Write the line to the header file. */ ! (void) fputs(buf, dfp[T_HEADER]); } /* --- 216,222 ---- /* Write the line to the header file. */ ! (void) fputs(buf, dfp[T_HDR]); } /* *************** *** 221,227 **** * to produce a valid message. */ ! (void) fputc('\n', dfp[T_HEADER]); /* * Copy the body (if any). --- 225,231 ---- * to produce a valid message. */ ! (void) fputc('\n', dfp[T_HDR]); /* * Copy the body (if any). *************** *** 268,274 **** * let's not keep it secret. */ ! for (t = 0; t < T_MAX; ++t) { if (ferror(dfp[t])) { --- 272,278 ---- * let's not keep it secret. */ ! for (t = T_HDR; t <= T_BODY; ++t) { if (ferror(dfp[t])) { *************** *** 286,291 **** --- 290,374 ---- } /*---------------------------------------------------------------------- + * Create another copy of each temp file, for security reasons. + * Also, put their names in the environment. + */ + + int + copy_again() + { + int r, t; + + for (r = T_HDR, t = T_HDRCOPY; r <= T_BODY; ++r, ++t) + { + /* + * If the file exists, remove it but keep its name. + * Otherwise, make a new name and put that name in + * the environment. + */ + + if (tfile[t]) + (void) unlink(tfile[t]); + else + { + tfile[t] = tempfile(); + if (tenv[t]) + alloc_env(tenv[t], tfile[t]); + } + + /* + * Create the file and copy the contents of the + * original file to it. + */ + + if (tfd[t] != -1) + (void) close(tfd[t]); + + if ((tfd[t] = tcreate(tfile[t])) == -1) + return -1; + + (void) lseek(tfd[r], 0L, 0); + if (copyfd(tfd[r], tfd[t]) < 0) + return -1; + } + + if (verbose) + { + message("copy_again: header to %s, body to %s\n", + tfile[T_HDRCOPY], tfile[T_BODYCOPY]); + } + + return 0; + } + + /*---------------------------------------------------------------------- + * Copy a file via file descriptors. + */ + + int + copyfd(src_fd, dest_fd) + int src_fd; + int dest_fd; + { + char buf[BUFSIZ]; + int rd, wr; + + while ((rd = read(src_fd, buf, sizeof(buf))) > 0) + { + if ((wr = write(dest_fd, buf, (unsigned) rd)) != rd) + { + if (wr == -1) + syserr("can't write in copyfd"); + else + error("write error -- disk full?\n"); + return -1; + } + } + + return 0; + } + + /*---------------------------------------------------------------------- * Return a pointer to a temporary filename, or NULL if error. */ *************** *** 315,321 **** { int fd; ! if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600)) == -1) { syserr("can't create %s", name); return -1; --- 398,404 ---- { int fd; ! if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0)) == -1) { syserr("can't create %s", name); return -1; Index: deliver.h *************** *** 1,8 **** ! /* $Header: deliver.h,v 1.5 88/11/18 12:16:55 network Exp $ * * General pull-it-together include file. * * $Log: deliver.h,v $ * Revision 1.5 88/11/18 12:16:55 network * patch2: Improved signal handling. * patch2: Make sure all environment variables are always provided. --- 1,12 ---- ! /* $Header: deliver.h,v 1.6 88/11/28 18:07:53 network Exp $ * * General pull-it-together include file. * * $Log: deliver.h,v $ + * Revision 1.6 88/11/28 18:07:53 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.5 88/11/18 12:16:55 network * patch2: Improved signal handling. * patch2: Make sure all environment variables are always provided. *************** *** 63,74 **** extern int trust_delfiles; /* Do we trust the delivery files? */ /* Temp file indices: */ ! #define T_HEADER 0 /* Temp file for message header */ ! #define T_BODY 1 /* Temp file for message body */ ! #define T_MAX 2 /* Number of temp files */ extern char *ttype[T_MAX]; /* Temp file types (for messages) */ extern char *tfile[T_MAX]; /* Temp file names */ extern int tfd[T_MAX]; /* Temp file fd's */ extern SIGFLAG got_sig; /* We caught a signal and should exit */ --- 67,81 ---- extern int trust_delfiles; /* Do we trust the delivery files? */ /* Temp file indices: */ ! #define T_HDR 0 /* Message header */ ! #define T_BODY 1 /* Message body */ ! #define T_HDRCOPY 2 /* Copy of message header */ ! #define T_BODYCOPY 3 /* Copy of message body */ ! #define T_MAX 4 /* Number of temp files */ extern char *ttype[T_MAX]; /* Temp file types (for messages) */ extern char *tfile[T_MAX]; /* Temp file names */ + extern char *tenv[T_MAX]; /* Temp file environment names */ extern int tfd[T_MAX]; /* Temp file fd's */ extern SIGFLAG got_sig; /* We caught a signal and should exit */ Index: dfile.c *************** *** 1,8 **** ! /* $Header: dfile.c,v 1.5 88/11/26 13:20:45 network Exp $ * * Filter destination(s) through delivery file(s). * * $Log: dfile.c,v $ * Revision 1.5 88/11/26 13:20:45 network * patch4: Add return type of signal handlers to config.h. * patch4: Provide a version of getopt() for systems that lack it. --- 1,12 ---- ! /* $Header: dfile.c,v 1.6 88/11/28 18:07:57 network Exp $ * * Filter destination(s) through delivery file(s). * * $Log: dfile.c,v $ + * Revision 1.6 88/11/28 18:07:57 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.5 88/11/26 13:20:45 network * patch4: Add return type of signal handlers to config.h. * patch4: Provide a version of getopt() for systems that lack it. *************** *** 256,265 **** return -1; } ! /* Make sure that the temp files are readable to the new process. */ ! give_temps(ct); /* Here we go! */ if (verbose) --- 260,275 ---- return -1; } ! /* Copy the temp files again */ ! if (copy_again() < 0) ! return -1; + /* Allow the given user to own and read the copies */ + + if (give_temps(ct) < 0) + return -1; + /* Here we go! */ if (verbose) *************** *** 376,392 **** * This is needed because the temps are readable by owner only. */ give_temps(ct) CONTEXT *ct; { ! int t; if (!ct) ! return; ! for (t = 0; t < T_MAX; ++t) { if (chown(tfile[t], ct->uid, ct->gid) == -1) ! syserr("can't chown %s", tfile[t]); } } --- 386,415 ---- * This is needed because the temps are readable by owner only. */ + int give_temps(ct) CONTEXT *ct; { ! int err, t; if (!ct) ! return -1; ! err = 0; ! for (t = T_HDRCOPY; t <= T_BODYCOPY; ++t) { + if (chmod(tfile[t], 0600) == -1) + { + syserr("can't chmod %s", tfile[t]); + ++err; + } if (chown(tfile[t], ct->uid, ct->gid) == -1) ! { ! syserr("can't chown %s to %d/%d", ! tfile[t], ct->uid, ct->gid); ! ++err; ! } } + + return err ? -1 : 0; } Index: main.c *************** *** 1,8 **** ! /* $Header: main.c,v 1.8 88/11/26 13:20:51 network Exp $ * * A program to deliver local mail with some flexibility. * * $Log: main.c,v $ * Revision 1.8 88/11/26 13:20:51 network * patch4: Add return type of signal handlers to config.h. * patch4: Provide a version of getopt() for systems that lack it. --- 1,12 ---- ! /* $Header: main.c,v 1.9 88/11/28 18:08:03 network Exp $ * * A program to deliver local mail with some flexibility. * * $Log: main.c,v $ + * Revision 1.9 88/11/28 18:08:03 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.8 88/11/26 13:20:51 network * patch4: Add return type of signal handlers to config.h. * patch4: Provide a version of getopt() for systems that lack it. *************** *** 92,100 **** int trust_user = FALSE; int trust_delfiles = FALSE; ! char *ttype[T_MAX] = { "header", "body" }; ! char *tfile[T_MAX] = { NULL, NULL }; ! int tfd[T_MAX] = { -1, -1 }; /* * Local functions. --- 96,105 ---- int trust_user = FALSE; int trust_delfiles = FALSE; ! char *ttype[T_MAX] = { "header", "body", "header copy", "body copy" }; ! char *tfile[T_MAX] = { NULL, NULL, NULL, NULL }; ! char *tenv[T_MAX] = { NULL, NULL, ENV_HEADER, ENV_BODY }; ! int tfd[T_MAX] = { -1, -1, -1, -1 }; /* * Local functions. *************** *** 476,481 **** --- 481,488 ---- for (t = 0; t < T_MAX; ++t) { + if (tfd[t] != -1) + (void) close(tfd[t]); if (tfile[t] && unlink(tfile[t]) == -1) syserr("can't unlink %s", tfile[t]); } *************** *** 610,618 **** alloc_env(ENV_HOSTNAME, hostname); if (sender && *sender) alloc_env(ENV_SENDER, sender); - - alloc_env(ENV_HEADER, tfile[T_HEADER]); - alloc_env(ENV_BODY, tfile[T_BODY]); alloc_env("IFS", " \t\n"); } --- 617,622 ---- Index: mbox.c *************** *** 1,8 **** ! /* $Header: mbox.c,v 1.2 88/09/14 19:42:06 network Exp $ * * Finally! Put the message in the specified mailbox(es). * * $Log: mbox.c,v $ * Revision 1.2 88/09/14 19:42:06 network * Portability to System V and BSD. * General fixup. --- 1,12 ---- ! /* $Header: mbox.c,v 1.3 88/11/28 18:08:13 network Exp $ * * Finally! Put the message in the specified mailbox(es). * * $Log: mbox.c,v $ + * Revision 1.3 88/11/28 18:08:13 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.2 88/09/14 19:42:06 network * Portability to System V and BSD. * General fixup. *************** *** 29,35 **** static mbox_dest(); static int mbox_write(); - static int mbox_copy(); /*---------------------------------------------------------------------- * Deliver mail to all valid destinations. --- 33,38 ---- *************** *** 93,100 **** if (d->class == CL_MBOX) { - give_temps(ct); - if (sfork() == 0) { if (become(ct, !boxdelivery) < 0) --- 96,101 ---- *************** *** 217,223 **** (void) lseek(fd, 0L, 2); /* No error check: may be a special file */ ! for (t = 0; t < T_MAX; ++t) { if (lseek(tfd[t], 0L, 0) == -1) { --- 218,224 ---- (void) lseek(fd, 0L, 2); /* No error check: may be a special file */ ! for (t = T_HDR; t <= T_BODY; ++t) { if (lseek(tfd[t], 0L, 0) == -1) { *************** *** 226,246 **** break; } ! switch (mbox_copy(tfd[t], fd)) { - case 1: - syserr("can't read %s file %s", ttype[t], tfile[t]); ret = -1; break; - case 2: - syserr("can't write to mailbox %s as %s", - mailbox, ct->name); - ret = -1; - break; - default: - continue; } - break; } if (verbose) --- 227,237 ---- break; } ! if (copyfd(tfd[t], fd) < 0) { ret = -1; break; } } if (verbose) *************** *** 256,284 **** ret = -1; return ret; - } - - /*---------------------------------------------------------------------- - * Copy the named file to the given file descriptor. - */ - - static int - mbox_copy(ifd, ofd) - int ifd; - int ofd; - { - char buf[BUFSIZ]; - int rd; - - while ((rd = read(ifd, buf, sizeof(buf))) > 0) - { - errno = 255; /* to avoid bogus syserr() output */ - if (write(ofd, buf, (unsigned) rd) != rd) - return 2; - } - - if (rd == -1) - return 1; - - return 0; } --- 247,250 ---- Index: uid.c *************** *** 0 **** --- 1,143 ---- + /* $Header: uid.c,v 1.2 88/11/28 18:08:20 network Exp $ + * + * I wish the System V "id" program were universally available; but it + * isn't, so I've written this replacement. + * + * usage: uid [-options] + * + * Default action is to print one line in the manner of "id": + * uid=201(chip) gid=50(group) euid=0(root) egid=0(root) + * (Note that the "euid" and "egid" entries are not output if they are + * the same as the "uid" and "gid" values.) + * + * If an option string is specified, it disables the normal behavior in + * favor of displaying id information, one per line, in the order that + * the options appear in the option string. Legal options are: + * u real uid + * g real gid + * U effective uid + * G effective gid + * + * NOTE: This program is not a paragon of good style. + * It's just something I needed for a Makefile. + * + * $Log: uid.c,v $ + * Revision 1.2 88/11/28 18:08:20 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * + */ + + #include <stdio.h> + #include <pwd.h> + #include <grp.h> + #include "config.h" + + #ifdef NULL + #undef NULL + #endif + #define NULL 0 + + extern struct passwd *getpwuid(); + extern struct group *getgrgid(); + + char *progname = "uid"; + + char *uid_desc(); + char *gid_desc(); + + main(argc, argv) + int argc; + char **argv; + { + int uid, gid, euid, egid; + int c, lines, errcount; + + uid = getuid(); + gid = getgid(); + euid = geteuid(); + egid = getegid(); + + errcount = 0; + lines = 0; + + while ((c = getopt(argc, argv, "ugUG")) != EOF) + { + switch (c) + { + case 'u': + (void) printf("%s\n", uid_desc(uid)); + ++lines; + break; + + case 'g': + (void) printf("%s\n", gid_desc(gid)); + ++lines; + break; + + case 'U': + (void) printf("%s\n", uid_desc(euid)); + ++lines; + break; + + case 'G': + (void) printf("%s\n", gid_desc(egid)); + ++lines; + break; + + case '?': + ++errcount; + break; + } + } + + if (errcount) + { + (void) fprintf(stderr, "usage: uid [-ugUG]\n"); + exit(1); + } + + if (lines == 0) + { + (void) printf("uid=%s", uid_desc(uid)); + (void) printf(" gid=%s", gid_desc(gid)); + + if (euid != uid) + (void) printf(" euid=%s", uid_desc(euid)); + if (egid != gid) + (void) printf(" egid=%s", gid_desc(egid)); + + (void) printf("\n"); + } + + exit(0); + /* NOTREACHED */ + } + + char * + uid_desc(uid) + int uid; + { + struct passwd *pw; + static char buf[80]; + + (void) sprintf(buf, "%d", uid); + if ((pw = getpwuid(uid)) != NULL) + (void) sprintf(buf + strlen(buf), "(%s)", pw->pw_name); + + return buf; + } + + char * + gid_desc(gid) + int gid; + { + struct group *gr; + static char buf[80]; + + (void) sprintf(buf, "%d", gid); + if ((gr = getgrgid(gid)) != NULL) + (void) sprintf(buf + strlen(buf), "(%s)", gr->gr_name); + + return buf; + } Index: uucp.c *************** *** 1,4 **** ! /* $Header: uucp.c,v 1.1 88/06/06 09:39:42 chip Exp $ * * Handle mail destined for other hosts via UUCP. * Deliver is intended as a very low-level program, so we don't --- 1,4 ---- ! /* $Header: uucp.c,v 1.2 88/11/28 18:08:23 network Exp $ * * Handle mail destined for other hosts via UUCP. * Deliver is intended as a very low-level program, so we don't *************** *** 5,10 **** --- 5,14 ---- * do anything fancy here. We just hand the message to uux. * * $Log: uucp.c,v $ + * Revision 1.2 88/11/28 18:08:23 network + * patch5: Copy temp files before handing them to delivery files. + * patch5: Introduce "uid" program. + * * Revision 1.1 88/06/06 09:39:42 chip * Initial revision * *************** *** 109,115 **** int fd; char buf[BUFSIZ]; ! if ((fd = dup(tfd[T_HEADER])) == -1) { syserr("can't dup header fd"); return -1; --- 113,119 ---- int fd; char buf[BUFSIZ]; ! if ((fd = dup(tfd[T_HDR])) == -1) { syserr("can't dup header fd"); return -1; -- Chip Salzenberg <chip@ateng.com> or <uunet!ateng!chip> A T Engineering Me? Speak for my company? Surely you jest! Beware of programmers carrying screwdrivers.