ast@cs.vu.nl (Andy Tanenbaum) (11/11/89)
Oops!
I am VERY sorry for this (actually I am ashamed...), but here
is the first "official patch" for W-MAIL version 2.6, which
was posted for me by Dr. Tanenbaum last week.
This update kit consists of TWO updates:
1) In the process of editing W-MAIL from 2.5 to 2.6 I
inserted a typo. The bug causes W-MAIL to behave very
strange in 'interactive' mode (e.g. the command mode).
It will refuse to print letters, and it always shows
an extra newline after a command has been typed.
The cure for this typo is contained in the cdiff-file
called 'patch1A.cdiff'.
2) The second patch is about a VERY serious bug, which
was brought to my attention by Rich Salz. Thanks, Rich!
Since W-MAIL is setuid-root, problems may arise with
system security. In fact, W-MAIL DOES NOT CHECK PERMISSIONS
AT ALL. For example, it is possible to set the environ-
mental variable "DEADLETTER" to some serious file like
"/etc/passwd", and then create a situation in which WMAIL
dumps the message in DEADLETTER. What will happen?
Correct, since the program is SetUID-root the message will
be dumped on the file /etc/passwd: CRASH !
This sort of problem also arises with saving messages, and
with the "SIGNATURE" variable.
Since this is a VERY serious problem, I immediately started
hacking on the fix. During that process (I tried various
solutions, and only this one seems to be OK) I found some
other minor things as well.
The second patch cures all this.
W-MAIL 2.7 has been tested VERY thorougly; it should be OK
now. Please let me know if it isn't.....
It also contains the new README file.
Regards,
Fred van Kempen.
---------------------------- cut here ----------------------------------
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive"
# Contents:
# README patch1A.cdiff patch1B.cdiff
#
# Wrapped by root@minixug on Sat Nov 11 04:19:19 1989
#
PATH=/bin:/usr/bin:/usr/local/bin:/usr/ucb:/tmp ; export PATH
if test -f 'README' -a "${1}" != "-c"
then
echo "$0: Will not overwrite existing file: 'README'"
else
echo "x - README"
sed 's/^X//' <<\END_OF_SHAR >'README'
X W-MAIL Local Mail Agent (MINIX)
X
X MicroWalt W-MAIL V2.7
X =====================
X
XThis archive contains the sources of the W-MAIL program, which
Xis a MINIX version of the MAILX program available on most UNIXes.
X
XIt does not need the presence of UUCP in order to run. However,
Xfor non-local mail delivery a remote mailer (like MicroWalt UMAIL)
Xis required to be present.
X
XRevision History:
X2.5 10/10/89 Initial posting.
X
X2.6 11/07/89 General fixes and a cleanup.
X - The Makefile-macro 'OTHERS' now contains 'wmail.h'
X as well. This caused incomplete archives to be
X distributed. Also, the parameters to 'shar' and 'tar'
X have been adapted to the new tar(1) and shar(1) programs.
X
X - Fixed '.' problem in edit_mail().
X
X - The strings 'findbuff', 'lbuff' and 'inbuff' have been
X moved to the routines in which they are used.
X
X - The bug in the more() code has been fixed. This bug
X cause gargabe to be printed in some circumstances.
X
X - The dead_letter() function no longer puts the file
X in the user's HOME directory. It now looks if there
X is an environmental variable "DEADLETTER"; if it
X exists its value will be used as the file name.
X Otherwise, the message will be dumped in the file
X "dead.letter" in the current directory.
X
X - All references to 'NIL' have been changed into 'NULL'.
X It was a bit confusing to have both around.
X
X - The code to scan message-headers has been changed
X radically. All message fields are now stored in the
X 'LETTER' structure dynamically. This saves a lot of
X memory, and thus allows for larger mailboxes.
X
X - The 'reply' bug has been fixed. This bug was caused
X by the UMAIL mailer, because it generated the wrong
X type of "From_" header. The header is now scanned by
X a separate routine in 'ummain.c' called 'old_hdr()'.
X
X - The source has been edited to make it conform to the
X new MINIX Style Sheet as posted by Andrew Tanenbaum.
X
X - The version-number has been increased to 2.6.
X
X2.7 11/10/89 Bug fixes:
X - The typo in wminteract() has been corrected. It said
X "interrupted = TRUE" where it should be "== TRUE".
X
X - Also, fixed all security problems within W-MAIL. This
X is done by calling the new 'allowed()' routine before
X a file is opened or created.
X
X - Some minor (cosmetic) changes.
X
X - The version-number has been increased to 2.6.
X
X
XOne last note:
X If you are compiling this program, and you get a lot of
X "illegal conversion of int to pointer" errors, please make
X sure that your header files in /usr/include have the
X "extern" declarations. Do NOT add them to this program...
X
XEnjoy!
X
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X| MINIX User Group (Holland) UUCP: hp4nl!kyber!minixug!waltje |
X| c/o Fred van Kempen, or: minixug!waltje@kyber.UUCP |
X| Hoefbladhof 27 |
X| 2215 DV VOORHOUT |
X| The Netherlands "A good programmer knows his Sources" |
X+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
X
END_OF_SHAR
fi
if test -f 'patch1A.cdiff' -a "${1}" != "-c"
then
echo "$0: Will not overwrite existing file: 'patch1A.cdiff'"
else
echo "x - patch1A.cdiff"
sed 's/^X//' <<\END_OF_SHAR >'patch1A.cdiff'
X*** wmail.h.old Wed Nov 8 17:01:45 1989
X--- wmail.h Wed Nov 8 17:01:52 1989
X***************
X*** 17,23 ****
X #include <setjmp.h>
X
X
X! #define VERSION "2.6 (11/07/89)"
X
X #define DROPNAME "/usr/spool/mail/%s" /* User Mailbox */
X #define LOCKNAME "/usr/spool/mail/%s.lock" /* lockfile for box */
X--- 17,23 ----
X #include <setjmp.h>
X
X
X! #define VERSION "2.6 (11/08/89)"
X
X #define DROPNAME "/usr/spool/mail/%s" /* User Mailbox */
X #define LOCKNAME "/usr/spool/mail/%s.lock" /* lockfile for box */
X*** wminteract.c.o Wed Nov 8 16:57:42 1989
X--- wminteract.c Wed Nov 8 16:57:47 1989
X***************
X*** 240,246 ****
X signal(SIGINT, onint);
X }
X
X! if (interrupted = TRUE) printf("\n");
X printf(PROMPT, let->seqno);
X fflush(stdout);
X
X--- 240,246 ----
X signal(SIGINT, onint);
X }
X
X! if (interrupted == TRUE) printf("\n");
X printf(PROMPT, let->seqno);
X fflush(stdout);
X
END_OF_SHAR
fi
if test -f 'patch1B.cdiff' -a "${1}" != "-c"
then
echo "$0: Will not overwrite existing file: 'patch1B.cdiff'"
else
echo "x - patch1B.cdiff"
sed 's/^X//' <<\END_OF_SHAR >'patch1B.cdiff'
X*** old/wmail.h Sat Nov 11 03:50:44 1989
X--- wmail.h Sat Nov 11 02:40:02 1989
X***************
X*** 17,23 ****
X #include <setjmp.h>
X
X
X! #define VERSION "2.6 (11/08/89)"
X
X #define DROPNAME "/usr/spool/mail/%s" /* User Mailbox */
X #define LOCKNAME "/usr/spool/mail/%s.lock" /* lockfile for box */
X--- 17,23 ----
X #include <setjmp.h>
X
X
X! #define VERSION "2.7 (11/10/89)"
X
X #define DROPNAME "/usr/spool/mail/%s" /* User Mailbox */
X #define LOCKNAME "/usr/spool/mail/%s.lock" /* lockfile for box */
X***************
X*** 63,71 ****
X
X
X extern char *Version;
X! extern int remote; /* use RMAIL to deliver (if any) */
X! extern int loclink; /* LMAIL: local delivery only! */
X! extern int old_uid, old_gid; /* UID/GID of calling user */
X extern int printmode; /* print-and-exit mode */
X extern int immediate; /* send remote immediately! */
X extern int quitmode; /* take interrupts */
X--- 63,71 ----
X
X
X extern char *Version;
X! extern int old_uid, old_gid; /* "real" ID's of caller */
X! extern int remote; /* use RMAIL to deliver (if any) */
X! extern int loclink; /* LMAIL: local delivery only! */
X extern int printmode; /* print-and-exit mode */
X extern int immediate; /* send remote immediately! */
X extern int quitmode; /* take interrupts */
X***************
X*** 99,104 ****
X--- 99,105 ----
X extern char *basename(/* char *name */);
X extern char *basepath(/* char *name */);
X extern char *whoami(/* void */);
X+ extern int allowed(/* char *name, int mode */);
X extern void showlet(/* LETTER *let */);
X extern void printlet(/* LETTER *let, FILE *tofp */);
X extern void printall(/* void */);
X*** old/wmcreate.c Sat Nov 11 03:51:41 1989
X--- wmcreate.c Sat Nov 11 02:28:11 1989
X***************
X*** 15,20 ****
X--- 15,21 ----
X *
X * Revisions:
X * 11/07/89 FvK Edited a little for the new MSS.
X+ * 11/10/89 FvK Fixed the overall security-bug.
X */
X #include <stdio.h>
X #include <string.h>
X***************
X*** 96,101 ****
X--- 97,103 ----
X /*
X * Add a .signature file after the message.
X * Skip this if infp is a file.
X+ * Check first for security!
X */
X if (isatty(fileno(infp))) {
X sp = getenv("SIGNATURE");
X***************
X*** 108,116 ****
X strcat(tmp, SIGNATURE);
X } else strcpy(tmp, sp);
X
X! if ((sigfp = fopen(tmp, "r")) != (FILE *)NULL) {
X! while ((c = fgetc(sigfp)) != EOF) fputc(c, tempfp);
X! fclose(sigfp);
X }
X }
X } else { /* Fast file copy for local delivery. */
X--- 110,125 ----
X strcat(tmp, SIGNATURE);
X } else strcpy(tmp, sp);
X
X! /* Check if we may read the file. */
X! if (allowed(tmp, 04) == TRUE) {
X! if ((sigfp = fopen(tmp, "r")) != (FILE *)NULL) {
X! while ((c = fgetc(sigfp)) != EOF)
X! fputc(c, tempfp);
X! fclose(sigfp);
X! }
X! } else {
X! fprintf(stderr, "%s: cannot read file \"%s\"\n",
X! progname, tmp);
X }
X }
X } else { /* Fast file copy for local delivery. */
X*** old/wmdeliver.c Sat Nov 11 03:52:30 1989
X--- wmdeliver.c Sat Nov 11 02:32:43 1989
X***************
X*** 16,21 ****
X--- 16,22 ----
X * Revisions:
X * 11/07/89 FvK Edited a little for the new MSS.
X * Fixed "dead.letter" pathname.
X+ * 11/10/89 FvK Fixed the overall security-bug.
X *
X * To Do:
X * - Aliases.
X***************
X*** 185,191 ****
X if ((pw = getpwnam(adressee)) == (struct passwd *)NULL) {
X fprintf(stderr, "%s: user %s unknown\n", progname, adressee);
X ++errs;
X- dead_letter();
X continue;
X } else {
X sprintf(mailbox, DROPNAME, adressee);
X--- 186,191 ----
X***************
X*** 210,216 ****
X "%s: forward-user %s unknown\n",
X progname, adressee);
X ++errs;
X- dead_letter();
X continue;
X } else {
X sprintf(mailbox, DROPNAME, adressee);
X--- 210,215 ----
X***************
X*** 236,242 ****
X "%s: could not create maildrop for %s\n",
X progname, vec[i]);
X ++errs;
X- dead_letter();
X continue;
X }
X ++created;
X--- 235,240 ----
X***************
X*** 247,253 ****
X "%s: could not lock maildrop for %s\n",
X progname, vec[i]);
X ++errs;
X- dead_letter();
X continue;
X }
X sleep(LOCKWAIT);
X--- 245,250 ----
X***************
X*** 265,271 ****
X progname, vec[i]);
X unlink(lockname);
X ++errs;
X- dead_letter();
X continue;
X }
X
X--- 262,267 ----
X***************
X*** 274,280 ****
X progname, vec[i]);
X unlink(lockname);
X ++errs;
X- dead_letter();
X continue;
X }
X
X--- 270,275 ----
X***************
X*** 291,297 ****
X fprintf(stderr, "%s: error delivering to user %s",
X progname, vec[i]);
X perror("");
X- dead_letter();
X ++errs;
X }
X
X--- 286,291 ----
X***************
X*** 305,346 ****
X signal(SIGHUP, sighup);
X signal(SIGQUIT, sigquit);
X
X! return((errs == 0) ? FALSE : TRUE);
X }
X
X
X /*
X * Save the current message to file 'dead.letter'.
X- * This is sometimes needed when delivery fails.
X *
X * If the environmental variable "DEADLETTER" is defined,
X * use its value as the file name. Otherwise, use DEADLETTER
X! * in the current directory.
X */
X void dead_letter(void)
X {
X char cpbuff[1024];
X char fname[PATHLEN];
X! char *sp;
X! register FILE *inf, *outf;
X
X fname[0] = '\0';
X inf = fopen(msg_temp, "r");
X if ((sp = getenv("DEADLETTER")) != NULL) strcpy(fname, sp);
X else strcpy(fname, DEADLETTER);
X
X! inf = fopen(msg_temp, "r");
X! if (inf == (FILE *)NULL) {
X fprintf(stderr, "%s: cannot open \"%s\"\n", progname, msg_temp);
X return;
X }
X
X! outf = fopen(fname, "w");
X! if (outf == (FILE *)NULL) {
X! fprintf(stderr, "%s: cannot create \"%s\"\n", progname, fname);
X return;
X }
X
X /* Copy temp. file to dead.letter. */
X while (TRUE) {
X if (fgets(cpbuff, sizeof(cpbuff), inf) == (char *)NULL) break;
X--- 299,348 ----
X signal(SIGHUP, sighup);
X signal(SIGQUIT, sigquit);
X
X! return((errs == 0) ? 0 : -1);
X }
X
X
X /*
X * Save the current message to file 'dead.letter'.
X *
X * If the environmental variable "DEADLETTER" is defined,
X * use its value as the file name. Otherwise, use DEADLETTER
X! * in the current directory. Check if we may write to that file!
X */
X void dead_letter(void)
X {
X char cpbuff[1024];
X char fname[PATHLEN];
X! register FILE *inf, *outf;
X! char *sp;
X
X fname[0] = '\0';
X inf = fopen(msg_temp, "r");
X if ((sp = getenv("DEADLETTER")) != NULL) strcpy(fname, sp);
X else strcpy(fname, DEADLETTER);
X
X! /* Open the message file. */
X! if ((inf = fopen(msg_temp, "r")) == (FILE *)NULL) {
X fprintf(stderr, "%s: cannot open \"%s\"\n", progname, msg_temp);
X return;
X }
X
X! /* Check if we may create/write that file. */
X! if (allowed(fname, 02) == FALSE) {
X! /* We may not. Say so! */
X! fprintf(stderr, "%s: cannot create \"%s\"\n", progname, fname);
X! fclose(inf);
X return;
X }
X
X+ /* We may, create the dump-file. */
X+ if ((outf = fopen(fname, "w")) == (FILE *)NULL) {
X+ fprintf(stderr, "%s: cannot create \"%s\"\n", progname, fname);
X+ fclose(inf);
X+ return;
X+ }
X+
X /* Copy temp. file to dead.letter. */
X while (TRUE) {
X if (fgets(cpbuff, sizeof(cpbuff), inf) == (char *)NULL) break;
X***************
X*** 350,355 ****
X fclose(inf);
X fclose(outf);
X
X! chown(fname, old_uid, old_gid);
X! fprintf(stderr, "%s: dumped message on file \"%s\"\n", progname, fname);
X! }
X--- 352,356 ----
X fclose(inf);
X fclose(outf);
X
X! fprintf(stderr, "%s: dumped message on file \"%s\"\n", progname, fname);
X! }
X*** old/wminteract.c Sat Nov 11 03:52:03 1989
X--- wminteract.c Sat Nov 11 02:37:24 1989
X***************
X*** 15,26 ****
X--- 15,28 ----
X *
X * Revisions:
X * 11/07/89 FvK Edited a little for the new MSS.
X+ * 11/10/89 FvK Fixed the overall security-bug.
X *
X * To Do:
X * - Builtin escapes (~i and friends)
X */
X #include <stdio.h>
X #include <ctype.h>
X+ #include <errno.h>
X #include <string.h>
X #include <signal.h>
X #include <unistd.h>
X***************
X*** 61,68 ****
X if ((shell = getenv("SHELL")) == NULL) shell = SHELL;
X
X if ((pid = fork()) == 0) {
X! setgid(old_gid); /* UUCP or USER */
X! setuid(old_uid); /* UUCP or USER */
X umask(oldmask);
X
X execl(shell, shell, "-c", command, NULL);
X--- 63,70 ----
X if ((shell = getenv("SHELL")) == NULL) shell = SHELL;
X
X if ((pid = fork()) == 0) {
X! setuid(old_uid); /* security! */
X! setgid(old_gid);
X umask(oldmask);
X
X execl(shell, shell, "-c", command, NULL);
X***************
X*** 112,117 ****
X--- 114,121 ----
X
X /*
X * Save the current letter to a disk-file.
X+ * Do this as a child process to make sure we
X+ * do not violate system security!
X */
X void savelet(let, savefile, withhead)
X LETTER *let;
X***************
X*** 121,138 ****
X off_t curr, limit, oldpos;
X register char *bp;
X FILE *savefp;
X! int c;
X
X bp = savefile;
X while (*bp && *bp!='\n') bp++;
X *bp = '\0';
X
X! if ((savefp = fopen(savefile, "a")) == (FILE *)NULL) {
X fprintf(stderr, "%s: cannot append to savefile \"%s\"\n",
X progname, savefile);
X return;
X }
X
X oldpos = ftell(boxfp);
X fseek(boxfp, (curr = let->location), SEEK_SET);
X limit = (let->next != NIL_LET) ? let->next->location : -1L;
X--- 125,152 ----
X off_t curr, limit, oldpos;
X register char *bp;
X FILE *savefp;
X! int c, temp;
X
X bp = savefile;
X while (*bp && *bp!='\n') bp++;
X *bp = '\0';
X
X! /* Check if we may write to that file. */
X! if (allowed(savefile, 02) == FALSE) {
X fprintf(stderr, "%s: cannot append to savefile \"%s\"\n",
X progname, savefile);
X return;
X }
X
X+ /* We may, go ahead! */
X+ if ((savefp = fopen(savefile, "a")) == (FILE *)NULL) {
X+ fprintf(stderr, "%s: cannot append to savefile \"%s\"\n",
X+ progname, savefile);
X+ return;
X+ }
X+
X+ temp = umask(oldmask); /* set previous umask() */
X+
X oldpos = ftell(boxfp);
X fseek(boxfp, (curr = let->location), SEEK_SET);
X limit = (let->next != NIL_LET) ? let->next->location : -1L;
X***************
X*** 149,154 ****
X--- 163,170 ----
X fprintf(stderr, "%s: savefile write error:", progname);
X }
X
X+ umask(temp); /* set previous umask() */
X+
X chown(savefile, old_uid, old_gid);
X }
X
X*** old/wmmain.c Sat Nov 11 03:51:15 1989
X--- wmmain.c Sat Nov 11 03:46:34 1989
X***************
X*** 17,22 ****
X--- 17,23 ----
X * it uses too much space now.
X * Fixed the "reply" bug that was caused
X * by a badly-decoded "From_" line.
X+ * 11/10/89 FvK Fixed the overall security-bug.
X */
X #include <sys/stat.h>
X #include <stdio.h>
X***************
X*** 29,37 ****
X
X
X char *Version = VERSION;
X! int remote = FALSE; /* use RMAIL to deliver (if any) */
X! int loclink = FALSE; /* LMAIL: local delivery only! */
X! int old_uid, old_gid; /* UID/GID of calling user */
X int printmode = FALSE; /* print-and-exit mode */
X int immediate = FALSE; /* send remote immediately! */
X int quitmode = FALSE; /* take interrupts */
X--- 30,38 ----
X
X
X char *Version = VERSION;
X! int old_uid, old_gid; /* "real" ID's of caller */
X! int remote = FALSE; /* use RMAIL to deliver (if any) */
X! int loclink = FALSE; /* LMAIL: local delivery only! */
X int printmode = FALSE; /* print-and-exit mode */
X int immediate = FALSE; /* send remote immediately! */
X int quitmode = FALSE; /* take interrupts */
X***************
X*** 110,194 ****
X
X
X /*
X! * Find the given entry in the mail-header
X! * Search for the first occurence of string 'text' in the header.
X! * Copy the text following it into the 'let' structure.
X! * Return buffer if found, else NULL.
X! */
X! char *find_string(let, text)
X! LETTER *let;
X! char *text;
X! {
X! static char findbuff[128];
X! static char inbuff[512];
X! off_t curr, limit;
X! register char *sp;
X! int all;
X!
X! fseek(boxfp, let->location, SEEK_SET);
X! limit = (off_t) -1L;
X! if (let->next != NIL_LET) limit = let->next->location;
X!
X! all = FALSE;
X! curr = let->location;
X! while (curr != limit && all==FALSE) {
X! if (fgets(inbuff, sizeof(inbuff), boxfp) == NULL) all = TRUE;
X! if (inbuff[0] == '\0') all = TRUE; /* end-of-header */
X!
X! if (!strncmp(inbuff, text, strlen(text))) {
X! sp = &inbuff[0]; /* remove '\n' */
X! while (*sp && *sp!='\n') sp++;
X! *sp = '\0';
X! sp = &inbuff[0] + strlen(text); /* copy to static buff */
X! strcpy(findbuff, sp);
X! return(findbuff); /* return adress of buff */
X! }
X!
X! curr += (off_t) strlen(inbuff); /* update message offset */
X!
X! if (all==FALSE && limit > 0L) /* quit if past message */
X! if (curr >= limit) all = TRUE;
X! }
X! return(NULL);
X }
X
X
X /*
X! * Check is the first line of the mailbox contains a line like
X! *
X! * Forward to XXXX
X! *
X! * then all mail for the calling user is being forwarded
X! * to user XXXX. Return a 1 value if this is the case.
X! * Otherwise, return 0 (or -1 for error).
X! */
X! int chk_box(void)
X! {
X! char xbuf[128];
X! FILE *fp;
X! char *bp;
X!
X! if (access(mailbox, 4) < 0 ||
X! (fp = fopen(mailbox, "r")) == (FILE *)NULL) {
X! if (usedrop && errno==ENOENT) return(-1);
X! fprintf(stderr, "%s: cannot access mailbox ", progname);
X! perror(mailbox);
X! exit(1);
X! }
X!
X! bp = fgets(xbuf, sizeof(xbuf), fp);
X! fclose(fp);
X!
X! if (bp!=NULL && !strncmp(xbuf, "Forward to ", 11)) {
X! strcpy(forward, strrchr(xbuf, ' ') + 1); /* get username */
X! forward[strlen(forward)-1] = '\0'; /* remove \n */
X! return(1);
X! }
X! return(0);
X }
X
X
X /*
X * Decode an old-style (V6/V7) mail header.
X * This is a line like:
X *
X--- 111,238 ----
X
X
X /*
X! * Check if we may perform operation 'mode' on
X! * file 'name'. System Security!
X! * If the error is 'ENOENT', then test the parent
X! * directory for the desired access.
X! */
X! int allowed(name, mode)
X! char *name; /* name of file to be checked */
X! unsigned short mode; /* mode to check (R=4, W=2, X=1) */
X! {
X! char abuf[1024]; /* temp. buf for filename */
X! struct stat stb;
X! char *p;
X!
X! /* Is this 'The Master' calling? */
X! if (old_uid == 0 && old_gid == 0) return(TRUE);
X!
X! if (stat(name, &stb) < 0) {
X! if (errno == ENOENT) { /* file does not exist */
X! strcpy(abuf, name); /* so check its parent dir */
X! p = strrchr(abuf, '/');
X! if (p == (char *)NULL) /* plain filename, */
X! getcwd(abuf, 1023); /* get current dir */
X! else *p = '\0'; /* strip 'file' part */
X! if (stat(abuf, &stb) < 0) return(FALSE); /* error? */
X! } else return(FALSE); /* it exists, other error! */
X! }
X!
X! /* We now have the status of the file or its parent dir. */
X! if (stb.st_uid == old_uid) { /* we are owner! */
X! if ((stb.st_mode >> 6) & mode)
X! return(TRUE); /* OK, we may do it. */
X! else return(FALSE); /* Alas... */
X! } else if (stb.st_uid == old_gid) { /* are we the same group? */
X! if ((stb.st_mode >>3) & mode)
X! return(TRUE); /* OK, we may do it. */
X! else return(FALSE); /* Alas... */
X! } else if (stb.st_mode & mode) /* we are 'others' */
X! return(TRUE); /* OK, we may do it. */
X! return(FALSE); /* Alas... */
X }
X
X
X /*
X! * Find the given entry in the mail-header
X! * Search for the first occurence of string 'text' in the header.
X! * Copy the text following it into the 'let' structure.
X! * Return buffer if found, else NULL.
X! */
X! char *find_string(let, text)
X! LETTER *let;
X! char *text;
X! {
X! static char findbuff[128];
X! static char inbuff[512];
X! off_t curr, limit;
X! register char *sp;
X! int all;
X!
X! fseek(boxfp, let->location, SEEK_SET);
X! limit = (off_t) -1L;
X! if (let->next != NIL_LET) limit = let->next->location;
X!
X! all = FALSE;
X! curr = let->location;
X! while (curr != limit && all==FALSE) {
X! if (fgets(inbuff, sizeof(inbuff), boxfp) == NULL) all = TRUE;
X! if (inbuff[0] == '\0') all = TRUE; /* end-of-header */
X!
X! if (!strncmp(inbuff, text, strlen(text))) {
X! sp = &inbuff[0]; /* remove '\n' */
X! while (*sp && *sp!='\n') sp++;
X! *sp = '\0';
X! sp = &inbuff[0] + strlen(text); /* copy to static buff */
X! strcpy(findbuff, sp);
X! return(findbuff); /* return adress of buff */
X! }
X!
X! curr += (off_t) strlen(inbuff); /* update message offset */
X!
X! if (all==FALSE && limit > 0L) /* quit if past message */
X! if (curr >= limit) all = TRUE;
X! }
X! return(NULL);
X }
X
X
X /*
X+ * Check is the first line of the mailbox contains a line like
X+ *
X+ * Forward to XXXX
X+ *
X+ * then all mail for the calling user is being forwarded
X+ * to user XXXX. Return a 1 value if this is the case.
X+ * Otherwise, return 0 (or -1 for error).
X+ */
X+ int chk_box(void)
X+ {
X+ char xbuf[128];
X+ FILE *fp;
X+ char *bp;
X+
X+ if (access(mailbox, 4) < 0 ||
X+ (fp = fopen(mailbox, "r")) == (FILE *)NULL) {
X+ if (usedrop && errno==ENOENT) return(-1);
X+ fprintf(stderr, "%s: cannot access mailbox ", progname);
X+ perror(mailbox);
X+ exit(1);
X+ }
X+
X+ bp = fgets(xbuf, sizeof(xbuf), fp);
X+ fclose(fp);
X+
X+ if (bp!=NULL && !strncmp(xbuf, "Forward to ", 11)) {
X+ strcpy(forward, strrchr(xbuf, ' ') + 1); /* get username */
X+ forward[strlen(forward)-1] = '\0'; /* remove \n */
X+ return(1);
X+ }
X+ return(0);
X+ }
X+
X+
X+ /*
X * Decode an old-style (V6/V7) mail header.
X * This is a line like:
X *
X***************
X*** 361,371 ****
X {
X int c, st;
X
X! strcpy(sender, whoami());
X! old_uid = getuid(); /* get calling user and save */
X! old_gid = getgid();
X! setuid(geteuid()); /* set UID to ROOT (SU) */
X! setgid(getegid()); /* set GID to ROOT (SU) */
X
X progname = basename(argv[0]); /* how are we called? */
X if (*progname == 'l') {
X--- 405,416 ----
X {
X int c, st;
X
X! strcpy(sender, whoami()); /* get our real name */
X!
X! old_uid = getuid(); /* This is dangerous, but */
X! old_gid = getgid(); /* is is necessary for the */
X! setuid(geteuid()); /* message delivery! */
X! setgid(getegid());
X
X progname = basename(argv[0]); /* how are we called? */
X if (*progname == 'l') {
X***************
X*** 385,393 ****
X checkonly++;
X break;
X case 'f': /* use another mailbox. */
X! setuid(old_uid);
X! setgid(old_gid);
X! usedrop = FALSE;
X strncpy(mailbox, optarg, PATHLEN - 1);
X break;
X case 'i': /* Use another input-file. */
X--- 430,438 ----
X checkonly++;
X break;
X case 'f': /* use another mailbox. */
X! usedrop = FALSE;
X! setuid(old_uid); /* security! */
X! setgid(old_gid);
X strncpy(mailbox, optarg, PATHLEN - 1);
X break;
X case 'i': /* Use another input-file. */
X***************
X*** 442,449 ****
X
X if (needupdate) updatebox();
X }
X! } else st = deliver(argc - optind, argv + optind);
X!
X! unlink(msg_temp);
X! exit(st);
X! }
X--- 487,497 ----
X
X if (needupdate) updatebox();
X }
X! } else {
X! st = deliver(argc - optind, argv + optind);
X!
X! if (st != 0) dead_letter(); /* something went wrong... */
X! }
X! unlink(msg_temp);
X! exit(st);
X! }
X*** old/wmread.c Sat Nov 11 03:51:30 1989
X--- wmread.c Sat Nov 11 01:34:47 1989
X***************
X*** 15,20 ****
X--- 15,21 ----
X *
X * Revisions:
X * 11/07/89 FvK Edited a little for the new MSS.
X+ * 11/10/89 FvK Increased more() buffer size.
X *
X * To Do:
X * - TERMCAP/TERMINFO use !
X***************
X*** 26,32 ****
X #include "wmail.h"
X
X
X! static char mobuf[128]; /* output buffer */
X static int mline; /* current terminal line */
X static int mcol; /* current terminal column */
X static int mobc; /* position in output buffer (== chars in) */
X--- 27,33 ----
X #include "wmail.h"
X
X
X! static char mobuf[512]; /* output buffer */
X static int mline; /* current terminal line */
X static int mcol; /* current terminal column */
X static int mobc; /* position in output buffer (== chars in) */
X***************
X*** 159,166 ****
X st = mline = mcol = mobc = misdone = 0;
X printf("Message %d:\n", let->seqno);
X while(curr != limit && ((c = fgetc(boxfp)) != EOF) && st==0) {
X! if (mobc == 128) {
X! st = lwrite(fd, mobuf, 128);
X mobc = 0;
X }
X mobuf[mobc++] = (char) c;
X--- 160,167 ----
X st = mline = mcol = mobc = misdone = 0;
X printf("Message %d:\n", let->seqno);
X while(curr != limit && ((c = fgetc(boxfp)) != EOF) && st==0) {
X! if (mobc == 512) {
X! st = lwrite(fd, mobuf, mobc);
X mobc = 0;
X }
X mobuf[mobc++] = (char) c;
X
END_OF_SHAR
fi
echo " End of archive"
rm -f /tmp/uudecode
exit 0
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+
| MINIX User Group (Holland) UUCP: hp4nl!kyber!minixug!waltje |
| c/o Fred van Kempen, or: minixug!waltje@kyber.UUCP |
| Hoefbladhof 27 |
| 2215 DV VOORHOUT |
| The Netherlands "A good programmer knows his Sources" |
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+