9 date 93.08.25.17.32.49; author jromine; state Exp;
14 date 93.08.25.17.32.24; author jromine; state Exp;
25 @off_t fixes for BSD44
28 @#define MFDEBUG /* temporarily */
30 static char Id[] = "@@(#)$Id:$";
43 * Developed from the Berkeley mail program of the same name
44 * by Mike Obrien at RAND to run with the MMDF mail system.
45 * Rewritten by Doug Kingston, US Army Ballistics Research Laboratory
46 * Hacked a lot by Steve Bellovin (smb@@unc)
48 * This program runs SETUID to root so that it can set effective and
49 * real [ug]ids to mmdflogin.
51 * 27-Oct-82 Marshall T. Rose <mrose%uci@@rand-relay>
52 * Support proper munging by using the UCI mail filtering
53 * routines (enabled by #ifdef MF)
54 * Also use ll_log() package (enabled by #ifdef LOG)
56 * 17-Oct-83 Marshall T. Rose <mrose%uci@@rand-relay>
57 * New interfacing. Remove the #ifdef:s
61 #define NAMESZ 64 /* Limit on component name size */
69 char *Fromtmp = "/tmp/rml.f.XXXXXX";
70 char *Msgtmp = "/tmp/rml.m.XXXXXX";
71 char *Errtmp = "/tmp/rml.e.XXXXXX";
72 char *Okhosts = "/usr/mmdf/table/rmail.ok";
73 char *Okdests = "/usr/mmdf/table/rmail.okdests";
75 extern char cmddfldir[];
76 extern char logdfldir[];
77 extern char mmdflogin[];
78 extern char pathsubmit[];
79 extern char sitesignature[];
80 extern char supportaddr[];
81 extern struct ll_struct chanlog;
83 char *dupfpath (), *index(), *rindex();
84 struct passwd *getpwnam(), *getpwuid();
89 struct ll_struct *logptr = &chanlog;
91 FILE *fromf; /* temporary out for colon-less UUCP "From" lines */
92 FILE *msgf; /* temporary out for message text */
93 FILE *mmdf; /* filtered mail file */
94 FILE *pipef; /* output to "submit" or "uux" */
95 char date[LINESIZE]; /* date of origination from uucp header */
96 char from[LINESIZE]; /* accumulated path of sender */
97 char origsys[NAMESZ]; /* originating system */
98 char origpath[LINESIZE];/* path from us to originating system */
99 char usrfrm[LINESIZE];
100 char Mailsys[LINESIZE];
101 int pbroke; /* broken-pipe flag */
102 int rtnflag; /* note was sent back */
111 char fromwhom[NAMESZ]; /* user on remote system */
113 char linebuf[LINESIZE]; /* scratchpad */
114 char sys[NAMESZ]; /* an element in the uucp path */
121 fprintf(stderr, "Usage: rmail user [user ...]\n");
126 ll_hdinit (logptr, "RM");
127 logptr -> ll_file = dupfpath (logptr -> ll_file, logdfldir);
129 if ((pw = getpwnam (mmdflogin)) == NULL) {
130 fprintf (stderr, "Cannot find mmdflogin\n");
136 sprintf (Mailsys, "%s <%s@@%s>",
137 sitesignature, mmdflogin, LocalName ());
141 { /* BE VERY SURE... */
144 for (i = fileno (stdout); i <= HIGHFD; i++)
148 /* create file to hold stderr output. We first open some */
149 /* null file to make sure stdout is taken. If stdin isn't */
150 /* open either, we've got so much trouble it isn't even worth */
151 /* worrying about a little more */
152 open("/dev/null", 0);
154 if (freopen(Errtmp, "w", stderr) == NULL) {
155 fprintf(stderr, "Can't create %s\n", Errtmp);
156 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
160 dup2 (fileno (stderr), fileno (stdout));
162 /* Create temp file for rest of message */
164 if ((msgf=fdopen(creat(Msgtmp, Tmpmode), "w")) == NULL) {
165 fprintf(stderr, "Can't create %s\n", Msgtmp);
166 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
171 /* create temp file for colon-less UUCP "From" lines */
173 if ((fromf=fdopen(creat(Fromtmp, Tmpmode), "w")) == NULL) {
174 fprintf(stderr, "Can't create %s\n", Fromtmp);
175 ll_log (logptr, LLOGFAT, "Unable to create '%s'",
183 if( fgets(linebuf, sizeof linebuf, stdin) == NULL )
185 if( strncmp(linebuf, "From ", 5)
186 && strncmp(linebuf, ">From ", 6) )
189 if (linebuf[0] != '>')
191 fputs(linebuf, fromf); /* Save, we may forward via UUCP */
192 cp = index (linebuf, ' '); /* start of name */
194 cp = index (cp, ' '); /* cp at end of name */
195 *cp++ = 0; /* term. name, cp at date */
196 strcpy (fromwhom, fromptr);
197 strncpy (date, cp, 24); /* Mon Nov 10 23:12:09 1981 */
200 cp = index(cp+1, 'r');
202 cp = rindex(fromwhom, '!');
206 p = rindex(fromwhom, '!');
207 if (p != NULL) strcpy(origsys, p+1);
208 else strcpy(origsys, fromwhom);
209 strcat(from, fromwhom);
211 strcpy(fromwhom, cp+1);
214 strcpy (sys, SystemName ());
216 strcpy (origsys, sys);
220 if (strncmp(cp, "remote from ", 12) == 0)
224 sscanf(cp, "remote from %s", sys);
226 strcpy(origsys, sys); /* Save for quick ref. */
230 if( fromwhom[0] == '\0' ) /* No from line, illegal */
235 strcpy (origpath, from);
236 strcat (from, fromwhom);
237 mf_get_addr (from, usrfrm);
238 if ((cp = rindex (usrfrm, '<')) != NULL) {
239 strcpy (usrfrm, ++cp);/* sigh */
240 if ((cp = rindex (usrfrm, '>')) != NULL)
243 if (usrfrm[0] == NULL)
244 sprintf (usrfrm, "%s!%s%%%s@@%s",
245 SystemName (), from, UucpChan (), LocalName ());
246 ll_log (logptr, LLOGGEN, "Rmail from '%s' (%s)", from, usrfrm);
247 fputs (linebuf, msgf);
248 if (rp_isbad (txtcpy (stdin, msgf)))
249 fputs ("\n *** Problem during receipt from UUCP ***\n", msgf);
251 freopen (Msgtmp, "r", msgf);
252 freopen (Fromtmp, "r", fromf);
258 for (argv++; --argc > 0; ) {
265 signal(SIGPIPE, brpipe);
266 if (rp_isbad(deliver(*argv++)) && !rtnflag)
270 /* Send back a copy if something nasty happened. For now, we use */
271 /* a real kludge -- we see if we noted some error, or if we find */
272 /* anything written to stderr.... */
276 if (cpyback) {rcpy();zcpy();}
286 * deliver() -- Handle all deliveries be they returns, automatic
287 * copies, or the real thing. Based on the address
288 * the letter is accepted or returned with a copy
289 * to the system administrators
291 * main() has set up the "from" string and the
295 " --------------- End of Returned Mail ---------------\n";
302 char linebuf[LINESIZE];
303 char tmpbuf[LINESIZE];
305 switch (adrcheck (to)) {
307 ll_log (logptr, LLOGGEN, "Rmail to '%s' via MMDF", to);
308 if (rp_isbad (replyval =
309 xsubmit (NULL, usrfrm, NULL, NULL, to)))
312 if (mf_get_msg () == NOTOK)
314 replyval = txtcpy (mmdf, pipef);
316 i = (pclose(pipef) >> 8 ) & 0xff;
317 if (rp_isgood(replyval)) replyval = i;
322 ll_log (logptr, LLOGGEN, "Rmail to '%s' via UUCP", to);
323 if (rp_isbad (replyval = xuucp(from, to)))
325 replyval = txtcpy(msgf, pipef);
327 i = (pclose(pipef) >> 8 ) & 0xff;
328 if (rp_isgood(replyval)) replyval = (i == 0 ? RP_OK : RP_LIO);
336 ll_log (logptr, LLOGGEN, "Illegal Rmail to '%s'", to);
337 switch (adrcheck (from)) {
340 replyval = xsubmit (dtimenow (), Mailsys,
341 from, supportaddr, from);
343 txtcpy(fromf, pipef);
345 fputs (rtnend, pipef);
347 i = (pclose(pipef) >> 8 ) & 0xff;
348 if (rp_isgood(replyval)) replyval = i;
353 replyval = xuucp (mmdflogin, from);
354 if (rp_isbad (replyval))
356 fprintf (pipef, "To: %s\n", from);
357 fprintf (pipef, "Cc: %s\n", supportaddr);
359 txtcpy(fromf, pipef);
361 fputs (rtnend, pipef);
363 i = (pclose(pipef) >> 8 ) & 0xff;
364 if (rp_isgood(replyval))
365 replyval = (i == 0 ? RP_OK : RP_LIO);
370 /* And now for the mail overseer's copy */
372 ll_log (logptr, LLOGGEN, "Notifying %s", supportaddr);
376 replyval = xsubmit (dtimenow (), Mailsys,
377 usrfrm, supportaddr, supportaddr);
378 if (rp_isbad (replyval))
381 txtcpy (fromf, pipef);
382 txtcpy (msgf, pipef);
383 fputs (rtnend, pipef);
385 i = (pclose(pipef) >> 8 ) & 0xff;
386 if (rp_isgood(replyval)) replyval = i;
395 adrcheck (adr) /* Gateway to Arpanet? */
404 if ((adrxp = seekadrx (adr)) == NULL)
406 strcpy (err, adrxp -> err ? adrxp -> err : "");
407 strcpy (host, adrxp -> host ? adrxp -> host : "");
408 strcpy (mbox, adrxp -> mbox ? adrxp -> mbox : "");
409 while (seekadrx (NULL))
412 if (err[0] || mbox[0] == NULL)
414 if (index (mbox, '!') || host[0] == NULL)
416 if (rp_isgood (lookup (origsys, Okhosts)))
418 if (index (host, '@@') || rp_isbad (okhost (host)))
425 okhost(host) /* Host permitted to use mail facilities? */
428 if (rp_isgood (lookup (origsys, Okhosts)))
429 return (RP_OK); /* Fully privledged originator */
430 if (rp_isgood (lookup (host, Okhosts)))
431 return (RP_OK); /* Fully privledged dest */
432 if (rp_isgood (lookup (host, Okdests)))
433 return (RP_OK); /* Unrestricted Dest. Host, OK */
434 return(RP_NO); /* Not permitted; must be bad */
440 * lookup() -- This lookup function looks for strings which
441 * must be the first string on a line. Sorry Dave (dhc)
442 * but the MMDF channel functions are too specific
443 * to be easily used here without much kludging.
446 /*****************************************
447 **** Can this be a call to a MMDF function??
448 **** Remember I have the RHOSTs table and the OKHOSTS table.
449 ******************************************/
455 char entry[LINESIZE];
458 if ((lookf = fopen (where, "r")) == NULL)
459 return (RP_NO); /* Unknown problem */
460 while (fgets (entry, sizeof entry, lookf) != NULL) {
462 while (*cp != '\n' && *cp != ' ' && *cp != '\t')
465 if (lexequ (what, entry)) {
477 char *rtnmessage[] = {
478 " Your message has been intercepted trying to access\n",
479 "a restricted access host (e.g. an ARPANET host). A copy\n",
480 "of your message has been sent to the system administrators.\n",
481 "The text of your message follows.\n\n",
482 " --------------- Returned Mail Follows --------------\n",
491 fprintf (pipef, "Subject: Illegal Address (%s)\n\n", badadr);
492 for (cpp = rtnmessage; *cpp; cpp++)
502 while (!pbroke && (nread = fread (buffer, sizeof (*buffer), BUFSIZ, frm)) > 0)
503 fwrite (buffer, sizeof (*buffer), nread, to);
504 return (ferror (frm) ? RP_LIO : RP_OK );
509 xsubmit (date, from, to, cc, realto)
510 char *date, *from, *to, *cc, *realto;
512 char cmdstr[LINESIZE],
515 getfpath (pathsubmit, cmddfldir, submit);
516 sprintf (cmdstr, "%s '-mlti%s*'", submit, UucpChan ());
519 if ((pipef = popen (cmdstr, "w")) == NULL)
523 printf ("%s\n", cmdstr);
526 fprintf (pipef, "%s\n%s\n!\n", from, realto);
529 fprintf (pipef, "Date: %s\n", date);
530 fprintf (pipef, "From: %s\n", from);
533 fprintf (pipef, "To: %s", to);
534 if (index (to, '@@'))
535 fputc ('\n', pipef);/* Explicit host specified */
537 fprintf (pipef, "@@%s\n", LocalName ());
540 fprintf (pipef, "Cc: %s\n", cc);
551 char cmdstr[LINESIZE];
553 sprintf (cmdstr, "/etc/delivermail -r%s -ep -m -s -i %s", from, to);
556 if ((pipef = popen (cmdstr, "w")) == NULL)
560 printf ("%s\n", cmdstr);
568 brpipe() /* catch broken-pipe signals */
570 signal(SIGPIPE, SIG_IGN);
574 char *oopsmessage[] = {
575 "\n\n\tThe system administrators (%s) have been informed of the\n",
576 "problem, but have not been given a copy of your message.\n",
588 ll_log (logptr, LLOGGEN, "Advising %s of failure as %s...", from, usrfrm);
590 sprintf (buffer, "Problems sending mail:\n\n");
591 if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", usrfrm)
596 if ((fp = fopen (Errtmp, "r")) != NULL) {
598 if (ftell (fp) == 0L)
599 fprintf (pipef, "\tunknown problem\n");
603 ml_txt ("\tunknown problem\n");
605 for (i = 0; oopsmessage[i]; i++) {
606 sprintf (message, oopsmessage[i], supportaddr);
609 fprintf (pipef, "\n\nReturned message follows:\n\n---------------\n\n");
615 if (ml_end (OK) != OK) {
619 if (cp = index (buffer, '\n'))
621 ll_log (logptr, LLOGFAT, "Unable to post failure notice");
622 ll_log (logptr, LLOGFAT, "info: %s", buffer);
632 ll_log (logptr, LLOGGEN, "Advising %s of failure...", supportaddr);
634 sprintf (buffer, "Problems sending mail for %s (aka %s):\n\n",
636 if (ml_1adr (NO, NO, sitesignature, "Problems sending mail", supportaddr)
641 if ((fp = fopen (Errtmp, "r")) != NULL) {
643 if (ftell (fp) == 0L)
644 fprintf (pipef, "\tunknown problem\n");
648 ml_txt ("\tunable to open error file\n");
650 if (ml_end (OK) != OK) {
654 if (cp = index (buffer, '\n'))
656 ll_log (logptr, LLOGFAT, "Unable to post failure notice");
657 ll_log (logptr, LLOGFAT, "info: %s", buffer);
676 strcpy (tmpfil, "/tmp/rmailXXXXXX");
677 unlink (mktemp (tmpfil));
678 if ((fd = creat (tmpfil, Tmpmode)) == NOTOK)
681 if ((fd = open (tmpfil, 2)) == NOTOK)
683 if ((out = fdopen (fd, "w")) == NULL) {
687 if ((td = dup (fd)) == NOTOK) {
692 fprintf (out, "From %s %s\n", from, date);
693 if (rp_isbad (txtcpy (msgf, out))) {
699 lseek (td, (off_t)0, 0);
701 strcpy (mmdfil, "/tmp/mmdfXXXXXX");
702 unlink (mktemp (mmdfil));
703 if ((fd = creat (mmdfil, Tmpmode)) == NOTOK) {
708 if ((fd = open (mmdfil, 2)) == NOTOK) {
713 if ((md = dup (fd)) == NOTOK) {
722 switch (i = uucp_to_mmdf (td, fd, TRUE)) {
724 lseek (md, (off_t)0, 0);
725 if ((mmdf = fdopen (md, "r")) != NULL)
731 sprintf (buffer, "rmail(%d) filtering failed(%d)\n",
733 if (ml_1adr (NO, NO, sitesignature, "MF Failure", supportaddr)
738 lseek (td, (off_t)0, 0);
739 if ((md = dup (td)) == NOTOK)
740 ml_txt ("unable to dup() descriptor for message copy\n");
742 if ((fp = fdopen (md, "r")) == NULL) {
743 ml_txt ("unable to fdopen() descriptor for message copy\n");
747 ml_txt ("\n --Message Follows--\n");
752 if (ml_end (OK) != OK) {
756 if (cp = index (buffer, '\n'))
758 ll_log (logptr, LLOGFAT, "Unable to post failure notice");
759 ll_log (logptr, LLOGFAT, "info: %s", buffer);
775 mf_get_addr (from, to)
783 if ((adrxp = seekadrx (from)) == NULL)
785 addr_convert (adrxp, to, TRUE);
786 while (seekadrx (NULL))