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" | +-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-+