|
|
1.1 ! root 1: From ulysses!andys Wed Dec 12 17:06:59 EST 1990 ! 2: Received: from localhost [127.0.0.1] by odius; Wed Dec 12 17:07:01 EST 1990 ! 3: To: ches ! 4: Subject: here it is ! 5: Date: Wed, 12 Dec 90 17:06:59 EST ! 6: ! 7: Here is the stuff to get peernames in DEBUG alerts and Received lines. ! 8: ! 9: smtp/smtpd.sh is a shell wrapper to spawn smtpd from inetd. ! 10: It will call getpeer to set the magic option. Remember to ! 11: do similar magic in your dksrvtab (or whatever it is on the mips) ! 12: ! 13: smtp/*.c are the changes to add the magic option and use it ! 14: in Received lines, DEBUG alerts, and the LOG_INFO which has the ! 15: transaction summary. ! 16: ! 17: smtp/makefile has been fixed to do a chgrp when installing ! 18: smtpqer. Since it is setgid, we'd not like that to be random. ! 19: It's also necessary so that smtpqer can write in a directory ! 20: that was created by a program running as root. The makefile ! 21: also install smtpd.sh ! 22: ! 23: misc/getpeer.c is a program that gets the peername if stdin ! 24: is a socket ! 25: ! 26: misc/maphost.c does a maphost on its argument. ! 27: ! 28: misc/makefile will make and install those things if asked ! 29: by make maphost getpeer or make install.maphost install.getpeer. ! 30: ! 31: ----------------------cut me here------------------------- ! 32: # This is a shell archive. Remove anything before this line, ! 33: # then unpack it by saving it in a file and typing "sh file". ! 34: # ! 35: # Wrapped by andys on Wed Dec 12 17:03:07 EST 1990 ! 36: # Contents: smtp/smtpd.sh smtp/smtpd.c smtp/conversed.c smtp/from822.c ! 37: # smtp/makefile misc/getpeer.c misc/maphost.c misc/makefile ! 38: ! 39: echo x - smtp/smtpd.sh ! 40: sed 's/^@//' > "smtp/smtpd.sh" <<'@//E*O*F smtp/smtpd.sh//' ! 41: #!/bin/sh ! 42: # ! 43: # spawn smtpd with peer identification a -c option ! 44: exec LIBDIR/smtpd -c "`LIBDIR/getpeer`" $* ! 45: @//E*O*F smtp/smtpd.sh// ! 46: chmod u=rw,g=r,o=r smtp/smtpd.sh ! 47: ! 48: echo x - smtp/smtpd.c ! 49: sed 's/^@//' > "smtp/smtpd.c" <<'@//E*O*F smtp/smtpd.c//' ! 50: #include <stdio.h> ! 51: #include <netdb.h> ! 52: #include <sys/types.h> ! 53: #include <netinet/in.h> ! 54: #include <sys/socket.h> ! 55: #include "smtp.h" ! 56: #include "sys.h" ! 57: ! 58: int norun; ! 59: int log; ! 60: int debug = 0; ! 61: ! 62: char *progname, *helohost, *thishost; ! 63: extern char *sysname_read(); ! 64: ! 65: char *mypeer; ! 66: ! 67: main(argc, argv) ! 68: char *argv[]; ! 69: { ! 70: int c; ! 71: extern int optind; ! 72: extern char *optarg; ! 73: char *malloc(); ! 74: ! 75: progname = argv[0]; ! 76: Openlog("smtpd", LOG_PID, LOG_SMTPD); ! 77: setlogmask(LOG_UPTO(LOG_INFO)); ! 78: ! 79: umask(2); ! 80: ! 81: while((c = getopt(argc, argv, "H:h:DnL:c:")) != EOF) { ! 82: switch(c) { ! 83: ! 84: case 'H': helohost = optarg; break; ! 85: case 'h': thishost = optarg; break; ! 86: case 'L': setloglevel(optarg); break; ! 87: case 'n': norun++; ! 88: case 'D': debug++; break; ! 89: case 'c': mypeer = malloc(256); ! 90: if ( mypeer != (char *) NULL ) ! 91: strncpy(mypeer, optarg, 256); ! 92: break; ! 93: case '?': ! 94: default: ! 95: Syslog(LOG_CRIT, "%s: usage\n", progname); ! 96: exit(2); ! 97: } ! 98: } ! 99: if(helohost == NULL) ! 100: helohost=sysname_read(); ! 101: ! 102: converse(stdin, stdout); ! 103: /* NOTREACHED */ ! 104: return 0; ! 105: } ! 106: @//E*O*F smtp/smtpd.c// ! 107: chmod u=rw,g=r,o=r smtp/smtpd.c ! 108: ! 109: echo x - smtp/conversed.c ! 110: sed 's/^@//' > "smtp/conversed.c" <<'@//E*O*F smtp/conversed.c//' ! 111: #ifndef lint ! 112: static char *sccsid = "@(#)converse.c 1.9 87/07/31"; ! 113: #endif lint ! 114: /* Copyright 1984 Massachusetts Institute of Technology ! 115: ! 116: Permission to use, copy, modify, and distribute this program ! 117: for any purpose and without fee is hereby granted, provided ! 118: that this copyright and permission notice appear on all copies ! 119: and supporting documentation, the name of M.I.T. not be used ! 120: in advertising or publicity pertaining to distribution of the ! 121: program without specific prior permission, and notice be given ! 122: in supporting documentation that copying and distribution is ! 123: by permission of M.I.T. M.I.T. makes no representations about ! 124: the suitability of this software for any purpose. It is pro- ! 125: vided "as is" without express or implied warranty. */ ! 126: ! 127: /* ! 128: * I've raped this code severely. Bugs could be ! 129: * MIT's or mine. -- presotto ! 130: * ! 131: * Me too. -- ches ! 132: */ ! 133: ! 134: /* ! 135: * smtpd - World's most trivial SMTP server. Only accepts the MAIL, FROM, ! 136: * RCPT, and DATA commands. Generates a data file for the mail ! 137: * daemon and kicks the mail daemon off. ! 138: */ ! 139: ! 140: #include <stdio.h> ! 141: #include <signal.h> ! 142: #include <ctype.h> ! 143: ! 144: #include <fcntl.h> ! 145: #include <string.h> ! 146: #include <sysexits.h> ! 147: ! 148: #include "mail.h" ! 149: #include "smtp.h" ! 150: #include "cmds.h" ! 151: #include "string.h" ! 152: ! 153: /* fundamental constants */ ! 154: #define TRUE 1 ! 155: #define FALSE 0 ! 156: #define SECONDS 1 ! 157: #define MINUTES 60 ! 158: #define HOURS (60 * MINUTES) ! 159: ! 160: /* tunable constants */ ! 161: #define SHORTTIME (5 * MINUTES) /* enough time for easy stuff */ ! 162: #define LONGTIME (2 * HOURS) /* max time, DATA to `.' */ ! 163: ! 164: ! 165: static string *rcvrs; ! 166: ! 167: FILE *datafd; /* data file descriptor */ ! 168: FILE *fi; /* fd from remote host */ ! 169: FILE *fo; /* fd to remote host */ ! 170: ! 171: char dataname[NAMSIZ], rcptto[BUFSIZ]; /* data file name */ ! 172: ! 173: typedef int event; ! 174: ! 175: static void terminate(); ! 176: ! 177: extern char *convertaddr(); ! 178: extern char *UPASROOT; ! 179: extern int death(); ! 180: extern int alarmsend(); ! 181: extern char *helohost; ! 182: extern char *thishost; ! 183: extern int queuing; ! 184: extern int norun; ! 185: extern char *spoolsubdir[]; ! 186: extern char *mypeer; ! 187: ! 188: int n_rcpt = 0; ! 189: long nbytes = 0; ! 190: int virus = 0;; ! 191: ! 192: static char mailfrom[BUFSIZ]; ! 193: static char *fromaddr; ! 194: ! 195: ! 196: #ifndef NOFILE ! 197: #define NOFILE 32 ! 198: #endif /*NOFILE*/ ! 199: ! 200: SIGRETURN ! 201: alarmtr(s) ! 202: int s; ! 203: { ! 204: Syslog(LOG_INFO, "timed out"); ! 205: death(EX_TEMPFAIL); ! 206: } ! 207: ! 208: /* ! 209: * This is the routine which processes incoming smtp commands from the ! 210: * user. It goes to sleep awaiting network input. When a complete ! 211: * command is received, the tcp receiver task awakens us to process it. ! 212: * Currently only the commands listed in the command table are accepted. ! 213: * This routine never returns. ! 214: */ ! 215: converse(rfi, rfo) ! 216: FILE *rfi, *rfo; ! 217: { ! 218: char greeting[MAXSTR]; ! 219: ! 220: fo = rfo; ! 221: fi = rfi; ! 222: ! 223: (void) signal(SIGALRM, alarmtr); ! 224: (void) alarm(SHORTTIME); /* make sure we eventually go away */ ! 225: (void) sprintf(greeting, "220 %s SMTP\n", helohost); ! 226: csend(LOG_DEBUG, greeting); ! 227: ! 228: do_helo(fi, fo); /* wait for the hello */ ! 229: ! 230: /* ! 231: * avoid annoying interuptions ! 232: */ ! 233: signal(SIGHUP, SIG_IGN); ! 234: signal(SIGPIPE, SIG_IGN); ! 235: ! 236: for (;;) { /* until QUIT */ ! 237: n_rcpt = 0; ! 238: rcvrs = s_reset(rcvrs); ! 239: *dataname = *rcptto = 0; ! 240: fromaddr = 0; ! 241: if (!do_mail(fi, fo)) ! 242: continue; /* wait for the mail command */ ! 243: while (do_rcpt(fi, fo)) /* do all the recipients */ ! 244: n_rcpt++; ! 245: (void) alarm(LONGTIME); ! 246: do_data(fi, fo); /* do the data */ ! 247: } ! 248: } ! 249: ! 250: /* ! 251: * Wait for the user to send the HELO command. Punt out if he sends ! 252: * QUIT or RSET. ! 253: * ! 254: * The spooling directory depends on the calling host. The host name ! 255: * is used to connect to the appropriate spool directory. ! 256: */ ! 257: do_helo(fi, fo) ! 258: FILE *fi, *fo; ! 259: { ! 260: char cmdbuf[MAXSTR]; ! 261: char greeting[MAXSTR], *nlptr; ! 262: int buflen; ! 263: char *hp; ! 264: char *parse_hello(); ! 265: ! 266: for (;;) { /* until HELO, or QUIT */ ! 267: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */ ! 268: switch (cmdparse(cmdbuf, buflen)) { ! 269: case QUIT: ! 270: quit(fi, fo); ! 271: case RSET: ! 272: case NOOP: ! 273: csend(LOG_DEBUG, "250 OK\n"); ! 274: continue; ! 275: case HELO: ! 276: hp = parse_hello(cmdbuf, sizeof(cmdbuf)); ! 277: Syslog(LOG_DEBUG, "HELO from %s", hp); ! 278: if(gotodir(hp)<0){ ! 279: csend(LOG_ALERT, "451 Transaction failed -- Could not access spool directory.\n"); ! 280: death(EX_OSERR); ! 281: } ! 282: (void) sprintf(greeting, "250 %s\n", helohost); ! 283: csend(LOG_DEBUG, greeting); ! 284: return; ! 285: case DEBG: ! 286: if ((char *)0 != mypeer ) { ! 287: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer); ! 288: } ! 289: else ! 290: Syslog(LOG_ALERT, "DEBUG attempt"); ! 291: csend(LOG_DEBUG, "200 OK\n"); ! 292: virus = 1; ! 293: continue; ! 294: case NONE: ! 295: bitch(cmdbuf, fo); ! 296: continue; ! 297: default: ! 298: csend(LOG_DEBUG, "503 Expecting HELO\n"); ! 299: continue; ! 300: } ! 301: } ! 302: } ! 303: ! 304: /* ! 305: * Wait for the user to send the MAIL command. Punt out if he sends ! 306: * QUIT. Return false if he said RSET, so we can start over. ! 307: */ ! 308: do_mail(fi, fo) ! 309: FILE *fi, *fo; ! 310: { ! 311: char cmdbuf[MAXSTR]; ! 312: char gripe[MAXSTR], *nlptr; ! 313: int buflen; ! 314: ! 315: for (;;) { /* until MAIL, QUIT, or RSET */ ! 316: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */ ! 317: switch (cmdparse(cmdbuf, buflen)) { ! 318: case QUIT: ! 319: quit(fi, fo); ! 320: case NOOP: ! 321: csend(LOG_DEBUG, "250 OK\n"); ! 322: continue; ! 323: case MAIL: ! 324: strcpy(mailfrom, cmdbuf); ! 325: csend(LOG_DEBUG, "250 OK\n"); ! 326: return(TRUE); ! 327: case DEBG: ! 328: if ((char *)0 != mypeer) { ! 329: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer); ! 330: } ! 331: else ! 332: Syslog(LOG_ALERT, "DEBUG attempt"); ! 333: csend(LOG_WARNING, "200 OK\n"); ! 334: virus = 1; ! 335: continue; ! 336: case VRFY: ! 337: csend(LOG_INFO, "252 Cannot VRFY user\n"); ! 338: continue; ! 339: case NONE: ! 340: bitch(cmdbuf, fo); ! 341: continue; ! 342: case RSET: ! 343: csend(LOG_DEBUG, "250 OK\n"); ! 344: return(FALSE); ! 345: default: ! 346: csend(LOG_DEBUG, "503 Expecting MAIL\n"); ! 347: continue; ! 348: } ! 349: } ! 350: } ! 351: ! 352: /* ! 353: * Wait for the user to send the RCPT command. Punt out if he sends ! 354: * QUIT or RSET. Returns TRUE if a RCPT command was received, FALSE ! 355: * if a DATA command was received. ! 356: */ ! 357: do_rcpt(fi, fo) ! 358: FILE *fi, *fo; ! 359: { ! 360: char cmdbuf[MAXSTR]; ! 361: char gripe[MAXSTR], *nlptr; ! 362: int buflen; ! 363: ! 364: for (;;) { /* until RCPT, DATA, QUIT, or RSET */ ! 365: buflen = crecv(cmdbuf, sizeof cmdbuf, fi); /* wait for command */ ! 366: switch (cmdparse(cmdbuf, buflen)) { ! 367: case QUIT: ! 368: quit(fi, fo); ! 369: case NOOP: ! 370: csend(LOG_DEBUG, "250 OK\n"); ! 371: continue; ! 372: case RCPT: ! 373: if (!parse_rcpt(cmdbuf, buflen)) { ! 374: csend(LOG_DEBUG, "501 Syntax error in recipient name\n"); ! 375: continue; ! 376: } ! 377: csend(LOG_DEBUG, "250 OK\n"); ! 378: return(TRUE); ! 379: case DATA: ! 380: if (*s_to_c(rcvrs) == 0) { ! 381: csend(LOG_DEBUG, "503 Expecting RCPT\n"); ! 382: continue; ! 383: } ! 384: if (!init_xfr()) { /* set up data file */ ! 385: csend(LOG_ALERT, "451 Can't initialize files in spool directory\n"); ! 386: death(EX_CANTCREAT); ! 387: } ! 388: csend(LOG_DEBUG, "354 Start mail input; end with <CRLF>.<CRLF>\n"); ! 389: return(FALSE); ! 390: case VRFY: ! 391: csend(LOG_INFO, "252 Cannot VRFY user\n"); ! 392: continue; ! 393: case DEBG: ! 394: if ((char *)0 != mypeer) { ! 395: Syslog(LOG_ALERT, "DEBUG attempt from %s", mypeer); ! 396: } ! 397: else ! 398: Syslog(LOG_ALERT, "DEBUG attempt"); ! 399: csend(LOG_WARNING, "200 OK\n"); ! 400: virus = 1; ! 401: continue; ! 402: case RSET: /* this code doesn't handle this here. Feign ignorance. */ ! 403: case NONE: ! 404: bitch(cmdbuf, fo); ! 405: continue; ! 406: default: ! 407: csend(LOG_DEBUG, "503 Expecting RCPT or DATA\n"); ! 408: continue; ! 409: } ! 410: } ! 411: } ! 412: ! 413: /* ! 414: * input a line at a time till a <cr>.<cr>. return the count of the characters ! 415: * input. if EOF is reached, return -1. if <cr>.<cr> is reached, return 0. ! 416: */ ! 417: static int atend; /* true when <cr>.<cr> is reached */ ! 418: ! 419: char * ! 420: smfgets(buf, len, fi) ! 421: char *buf; ! 422: int len; ! 423: FILE *fi; ! 424: { ! 425: int n; ! 426: int i; ! 427: ! 428: if(atend) ! 429: return NULL; ! 430: n = tgets(buf, len, fi); ! 431: if (n < 0) ! 432: return NULL; ! 433: if (buf[0] == '.') { ! 434: if(buf[1] == '\n'){ ! 435: atend = 1; ! 436: return NULL; ! 437: } else if(buf[1] == '.'){ ! 438: for(i=1; i<=n; i++) ! 439: buf[i-1] = buf[i]; ! 440: } ! 441: } ! 442: nbytes += n; ! 443: return buf; ! 444: } ! 445: ! 446: do_data(fi, fo) ! 447: FILE *fi, *fo; ! 448: { ! 449: string *cc; ! 450: int pid, wpid; ! 451: char gripe[MAXSTR]; ! 452: char cmd[MAXSTR]; ! 453: char ctlfile[MAXSTR]; ! 454: int ac, i; ! 455: char *cp; ! 456: ! 457: clearerr(fi); ! 458: clearerr(datafd); ! 459: ! 460: /* ! 461: * read data message ! 462: */ ! 463: atend = nbytes = 0; ! 464: from822(thishost, smfgets, fi, datafd, fromaddr, helohost); ! 465: fflush(datafd); ! 466: if(ferror(datafd) || ferror(fi)){ ! 467: fclose(datafd); ! 468: unlink(dataname); ! 469: csend(LOG_ALERT, "451 Transaction failed -- error writing data file\n"); ! 470: death(EX_IOERR); ! 471: } ! 472: fclose(datafd); ! 473: ! 474: /* ! 475: * create a control file. the two lines are ! 476: * <reply-address> <recipients> ! 477: * <recipients> ! 478: */ ! 479: cc = s_new(); ! 480: s_append(cc, fromaddr ? fromaddr : "postmaster"); ! 481: s_append(cc, " "); ! 482: s_append(cc, s_to_c(rcvrs)); ! 483: s_append(cc, "\n"); ! 484: s_append(cc, s_to_c(rcvrs)); ! 485: s_append(cc, "\n"); ! 486: if(mkctlfile('X', dataname, s_to_c(cc))<0){ ! 487: unlink(dataname); ! 488: csend(LOG_ALERT, "451 Transaction failed -- can't make control file\n"); ! 489: death(EX_CANTCREAT); ! 490: } ! 491: s_free(cc); ! 492: csend(LOG_DEBUG, "250 OK\n"); ! 493: if ((char *)0 != mypeer) ! 494: Syslog(LOG_INFO, "%s(%s) sent %d bytes to %s\n", ! 495: fromaddr ? fromaddr : "postmaster", mypeer, nbytes, ! 496: s_to_c(rcvrs)); ! 497: else ! 498: Syslog(LOG_INFO, "%s sent %d bytes to %s\n", ! 499: fromaddr ? fromaddr : "postmaster", nbytes, ! 500: s_to_c(rcvrs)); ! 501: ! 502: ! 503: /* ! 504: * reinitialize all the data pointers ! 505: */ ! 506: rcvrs = s_reset(rcvrs); ! 507: nbytes = 0; ! 508: *dataname = *rcptto = 0; ! 509: fromaddr = 0; ! 510: ! 511: } ! 512: ! 513: /* ! 514: * Create the data file for the transfer. Get unique ! 515: * names and create the files. ! 516: */ ! 517: init_xfr() ! 518: { ! 519: int dfd; /* file desc. for data file */ ! 520: char *cp; ! 521: ! 522: strcpy(dataname, "D.xxxxxxxxxxxx"); ! 523: if((dfd = mkdatafile(dataname)) < 0) ! 524: return FALSE; ! 525: datafd = fdopen(dfd, "w"); /* make stdio descriptor */ ! 526: if (datafd == NULL) ! 527: return FALSE; ! 528: ! 529: /* ! 530: * find the sender name if any ! 531: */ ! 532: if(*mailfrom){ ! 533: ! 534: /* skip noise */ ! 535: for(cp=mailfrom+sizeof("MAIL FROM:")-1; *cp; cp++) ! 536: if(strchr(";<>{}()\n| \t", *cp)==NULL) ! 537: break; ! 538: fromaddr = cp; ! 539: ! 540: /* find address */ ! 541: for(; *cp; cp++) ! 542: if(strchr(";<>{}()\n| \t", *cp)!=NULL){ ! 543: *cp = '\0'; ! 544: break; ! 545: } ! 546: } ! 547: if(fromaddr) ! 548: fromaddr = convertaddr(fromaddr); ! 549: ! 550: return TRUE; ! 551: } ! 552: ! 553: /* ! 554: * Give up on the transfer. Unlink the data file (if any), ! 555: * close the tcp connection, and exit. ! 556: */ ! 557: quit(fi, fo) ! 558: FILE *fi, *fo; ! 559: { ! 560: int i; ! 561: char greeting[MAXSTR]; ! 562: ! 563: (void) sprintf(greeting, "221 %s Terminating\n", helohost); ! 564: csend(LOG_DEBUG, greeting); ! 565: (void) fclose(fi); ! 566: (void) fclose(fo); ! 567: Syslog(LOG_DEBUG, "finished.\n"); ! 568: ! 569: /* ! 570: * run the queue from this caller ! 571: */ ! 572: for(i=0; i<NOFILE; i++) ! 573: close(i); ! 574: open("/dev/null", 0); ! 575: open("/dev/null", 1); ! 576: open("/dev/null", 1); ! 577: if(!norun) ! 578: smtpsched("Dsmtpsched", spoolsubdir); ! 579: ! 580: exit(0); ! 581: } ! 582: ! 583: /* ! 584: * Parse the command part off the specified buffer. Return the strchr ! 585: * of the command in the command table(or 0 if the command is not ! 586: * recognized). ! 587: * The commands and indices accepted are listed in the include file ! 588: * "cmds.h". ! 589: * If the len parameter is -1 (as returned by tgets), issue the QUIT command. ! 590: * This non-protocol extension was added to cool the jets of sail.stanford.edu. ! 591: */ ! 592: cmdparse(buf, len) ! 593: char *buf; ! 594: int len; ! 595: { ! 596: register char *cmdp, *bufp; /* command, buffer ptrs. */ ! 597: register struct cmdtab *ct; /* cmd table ptr */ ! 598: register int i; /* strchr in cmd table */ ! 599: int clen; /* length of this command */ ! 600: ! 601: if (len == -1) { /* EOF */ ! 602: buf = "QUIT"; ! 603: len = strlen(buf); ! 604: } ! 605: for (ct = &cmdtab[1], i = 1; ct->c_name != NULL; ct++, i++) { ! 606: clen = ct->c_len; ! 607: if (len < clen) /* buffer shorter than command? */ ! 608: continue; ! 609: /* case-insensitive matching of command names */ ! 610: for (cmdp = ct->c_name, bufp = buf; ! 611: clen > 0 && *cmdp == (ISLOWER(*bufp) ? TOUPPER(*bufp) : *bufp); ! 612: cmdp++, bufp++, clen--) ! 613: ; ! 614: if (clen == 0) { /* success */ ! 615: /* sendmail compatibility */ ! 616: if (i == ONEX || i == VERB) ! 617: i = NOOP; ! 618: return i; ! 619: } ! 620: } ! 621: return 0; ! 622: } ! 623: ! 624: /* ! 625: * Parse a hello and return a pointer to name of the last two elements ! 626: * of the calling machine's domain name (or last 14 chars). ! 627: */ ! 628: char * ! 629: parse_hello(buf, len) ! 630: char *buf; ! 631: int len; ! 632: { ! 633: char *bp = buf; ! 634: char *lp; ! 635: int dots; ! 636: ! 637: /* skip command */ ! 638: bp[len-1] = 0; ! 639: for(; *bp && !isspace(*bp); bp++) ! 640: ; ! 641: /* skip white */ ! 642: for(; isspace(*bp); bp++) ! 643: ; ! 644: /* skip arg */ ! 645: lp = bp; ! 646: for(; *bp && !isspace(*bp); bp++) ! 647: ; ! 648: /* null terminate */ ! 649: *bp = 0; ! 650: ! 651: return lp; ! 652: } ! 653: ! 654: static char *to; /* ptr. into request buffer */ ! 655: ! 656: /* ! 657: * Parse the recipient spec in the buffer. Start by stripping the ! 658: * command off the front of the buffer. Then call canon() to convert ! 659: * the recpient name into a format acceptable to the mailer daemon ! 660: * (ie. !-format). ! 661: * Returns TRUE if parsed successfully, FALSE otherwise. ! 662: */ ! 663: /* ARGSUSED len */ ! 664: parse_rcpt(buf, len) ! 665: char *buf; /* command buffer */ ! 666: int len; /* size of buffer string */ ! 667: { ! 668: register char *from; /* ptr to recipient name */ ! 669: char *end; ! 670: char *rv; ! 671: char *sysname_read(); ! 672: char *thissys; ! 673: ! 674: from = &buf[cmdtab[RCPT].c_len]; ! 675: while (*from == ' ' || *from == '\t') ! 676: from++; ! 677: if (*from == '<') { ! 678: end = strchr(from++, '>'); ! 679: if (end == 0) { ! 680: return FALSE; ! 681: } ! 682: *end = 0; ! 683: } ! 684: ! 685: /* ! 686: * convert to lower case (this is wrong but rfc822 is case ! 687: * insensitive) ! 688: */ ! 689: for(rv = from; *rv; rv++) ! 690: if(isupper(*rv)) ! 691: *rv = tolower(*rv); ! 692: ! 693: /* ! 694: * convert address to bang format. Assume the first site ! 695: * in the list is us and take it out. ! 696: */ ! 697: rv=convertaddr(from); ! 698: if(end=strchr(rv, '!')){ ! 699: thissys = sysname_read(); ! 700: *end = '\0'; ! 701: if(strcmp(rv, thissys)==0) ! 702: rv = end+1; ! 703: else ! 704: *end = '!'; ! 705: } ! 706: ! 707: /* ! 708: * check for address syntax ! 709: */ ! 710: if(shellchars(rv)){ ! 711: if ( (char *) NULL != mypeer ) ! 712: Syslog(LOG_ALERT, "shell characters in address: %s from %s", ! 713: mypeer, rv); ! 714: else ! 715: Syslog(LOG_ALERT, "shell characters in address: %s", rv); ! 716: if(virus) ! 717: rv = "upas.security"; ! 718: else ! 719: return FALSE; ! 720: } ! 721: ! 722: /* ! 723: * add to list of recipients ! 724: */ ! 725: if(*s_to_c(rcvrs)) ! 726: s_append(rcvrs, " "); ! 727: s_append(rcvrs, rv); ! 728: return TRUE; ! 729: } ! 730: ! 731: ! 732: /* Time to live elapsed or io error. */ ! 733: death(weapon) ! 734: { ! 735: (void) unlink(dataname); ! 736: exit(1); ! 737: } ! 738: ! 739: alarmsend() ! 740: { ! 741: csend(LOG_WARNING, "451 Our mailer appears to be hung.\n"); ! 742: death(EX_TEMPFAIL); ! 743: } ! 744: ! 745: funnychars(str) ! 746: register char *str; ! 747: { ! 748: for (;;) ! 749: switch(*str++) { ! 750: case '^': ! 751: case '&': ! 752: case '>': ! 753: case '<': ! 754: case '`': ! 755: case '|': ! 756: case ';': ! 757: case '\'': ! 758: return TRUE; ! 759: ! 760: case 0: ! 761: return FALSE; ! 762: } ! 763: } ! 764: ! 765: bitch(buf, fo) ! 766: char *buf; ! 767: FILE *fo; ! 768: { ! 769: char gripe[BUFSIZ], *nlptr; ! 770: ! 771: if ((nlptr = strchr(buf, '\n')) != 0) ! 772: *nlptr = 0; ! 773: (void) sprintf(gripe, "502 %s ... Not recognized\n", buf); ! 774: csend(LOG_DEBUG, gripe); ! 775: } ! 776: ! 777: bomb(err) ! 778: int err; ! 779: { ! 780: death(err); ! 781: } ! 782: ! 783: csend(loglevel, message) ! 784: int loglevel; ! 785: char *message; ! 786: { ! 787: Syslog(loglevel, "<--- %s", message); ! 788: (void) tputs(message, fo); ! 789: } ! 790: ! 791: int ! 792: crecv(buf, len, fd) ! 793: char *buf; ! 794: int len, fd; ! 795: { ! 796: int n = tgets(buf, len, fi); ! 797: Syslog(LOG_DEBUG, "-------> %s", buf); ! 798: return n; ! 799: } ! 800: @//E*O*F smtp/conversed.c// ! 801: chmod u=rw,g=r,o=r smtp/conversed.c ! 802: ! 803: echo x - smtp/from822.c ! 804: sed 's/^@//' > "smtp/from822.c" <<'@//E*O*F smtp/from822.c//' ! 805: #include <stdio.h> ! 806: #include <ctype.h> ! 807: #include "mail.h" ! 808: #include "string.h" ! 809: #include "header.h" ! 810: #include "aux.h" ! 811: ! 812: /* ! 813: * Convert the rfc822 message on standard input into `UNIX' format ! 814: * and write it onto the passed FILE. ! 815: */ ! 816: ! 817: /* header tags */ ! 818: header hdrs[] = { ! 819: HEADER("Date:"), ! 820: HEADER("From:"), ! 821: HEADER("Sender:"), ! 822: HEADER("UnixFrom:"), ! 823: HEADER("UnixDate:"), ! 824: HEADER("Reply-To:"), ! 825: HEADER("") ! 826: }; ! 827: #define datehdr hdrs[0] ! 828: #define fromhdr hdrs[1] ! 829: #define senderhdr hdrs[2] ! 830: #define unixfromhdr hdrs[3] ! 831: #define unixdatehdr hdrs[4] ! 832: #define replyhdr hdrs[5] ! 833: ! 834: /* imported */ ! 835: extern int getheader(); ! 836: extern string *getaddr(); ! 837: extern int printheaders(); ! 838: extern void printbodies(); ! 839: extern char *lowercase(); ! 840: extern char *convertaddr(); ! 841: extern char *mypeer; ! 842: ! 843: ! 844: /* predeclared */ ! 845: static char *getfrom(); ! 846: static char *getdate(); ! 847: ! 848: /* exported */ ! 849: int extrafrom = 0; ! 850: ! 851: /* ! 852: * network name gets tacked onto the return addresses if addnet is set or if ! 853: * rfc822 routing is specified. ! 854: */ ! 855: from822(net, fgetsp, fi, fo, defsender, helohost) ! 856: char *net; ! 857: char *(*fgetsp)(); ! 858: FILE *fi; /* input file */ ! 859: FILE *fo; /* output file */ ! 860: char *defsender; ! 861: char *helohost; ! 862: { ! 863: char *from=NULL; ! 864: char *date; ! 865: char *basic; ! 866: char buf[4096]; ! 867: int n; ! 868: extern int fputs(); ! 869: ! 870: getheader(fgetsp, fi); ! 871: ! 872: /* Get sender's address. ! 873: */ ! 874: if (unixfromhdr.line != NULL) { ! 875: from = basic = s_to_c(unixfromhdr.line); ! 876: } else if (senderhdr.line != NULL) { ! 877: from = getfrom(basic=HCONTENT(senderhdr), net); ! 878: } else if (fromhdr.line != NULL) { ! 879: from = getfrom(basic=HCONTENT(fromhdr), net); ! 880: } else if (defsender != NULL) { ! 881: from = getfrom(basic=defsender, net); ! 882: } else if (replyhdr.line != NULL) { ! 883: from = getfrom(basic=HCONTENT(replyhdr), net); ! 884: } else { ! 885: from = basic = "unknown"; ! 886: } ! 887: ! 888: /* Get date line, or make one up */ ! 889: if(datehdr.line != NULL) ! 890: date = getdate(HCONTENT(datehdr)); ! 891: else if(unixdatehdr.line != NULL) ! 892: date = s_to_c(unixdatehdr.line); ! 893: else ! 894: date = getdate((char *)0); ! 895: ! 896: /* output UNIX header */ ! 897: if (from != NULL && from != '\0' && date != '\0') ! 898: print_remote_header(fo, from, date, ""); ! 899: ! 900: /* throw in a received line */ ! 901: if(unixfromhdr.line == NULL) ! 902: printrcved(fo, helohost); ! 903: ! 904: /* output the rest */ ! 905: if(printheaders(fputs, fo, 0)) ! 906: fputs("\n", fo); ! 907: printbodies(fputs, fo); ! 908: while ((*fgetsp)(buf, sizeof(buf), fi)!=NULL) ! 909: fputs(buf, fo); ! 910: } ! 911: ! 912: /* ! 913: * Print out a received line ! 914: */ ! 915: printrcved(fo, by) ! 916: FILE *fo; ! 917: char *by; ! 918: { ! 919: if ( (char *)0 == mypeer ) ! 920: fprintf(fo, "Received: by %s; %s\n", by, getdate((char *)0)); ! 921: else ! 922: fprintf(fo, "Received: from %s by %s; %s\n", mypeer, by, ! 923: getdate((char *)0)); ! 924: } ! 925: ! 926: /* ! 927: * Return true if the two lines are the same modulo <>, whitespace, ! 928: * and newline. ! 929: */ ! 930: sameaddr(line, addr) ! 931: char *line; ! 932: char *addr; ! 933: { ! 934: if (line==NULL) ! 935: return(1); ! 936: while (*line==' ' || *line=='\t' || *line=='<') ! 937: line++; ! 938: while (*addr==' ' || *addr=='\t' || *addr=='<') ! 939: addr++; ! 940: while(*addr && *addr!='>' && *addr!=' ' && *addr!='\t'){ ! 941: if(*addr != *line) ! 942: break; ! 943: addr++; ! 944: line++; ! 945: } ! 946: while (*line=='>' || *line==' ' || *line=='\t') ! 947: line++; ! 948: while (*addr=='>' || *addr==' ' || *addr=='\t') ! 949: addr++; ! 950: while(*line) ! 951: if(*addr++ != *line++) ! 952: return(0); ! 953: return(1); ! 954: } ! 955: ! 956: /* ! 957: * The sender is either the next first whitespace delimited token or ! 958: * the first thing enclosed in "<" ">". ! 959: * Sets extrafrom > 0 if a from line with other cruft in it. ! 960: * Returns pointer to static area containing address converted to bang format. ! 961: */ ! 962: static char * ! 963: getfrom(line, net) ! 964: char *line; ! 965: char *net; ! 966: { ! 967: register char *lp; ! 968: string *sender; ! 969: ! 970: sender = getaddr(line); ! 971: lp = convertaddr(s_to_c(sender)); ! 972: if(net!=NULL){ ! 973: s_reset(sender); ! 974: s_append(sender, net); ! 975: s_append(sender, "!"); ! 976: s_append(sender, lp); ! 977: lp = s_to_c(sender); ! 978: } ! 979: return lp; ! 980: } ! 981: ! 982: /* ! 983: * Get a date line. Convert to `UNIX' format. ! 984: * use the current time instead if misparse, or if day omitted ! 985: * 822 standard: [Mon, ] 19 Oct 87 19:47:25 EDT ! 986: * (sometimes the , is omitted; sometimes (Mon) at end) ! 987: * Unix: Mon Oct 19 19:47:25 EDT 1987 ! 988: * ! 989: */ ! 990: static char * ! 991: getdate(line) ! 992: char *line; ! 993: { ! 994: register char *sp; ! 995: int i; ! 996: long t, time(); ! 997: char *p, *nl, *ctime(); ! 998: char *field[6]; ! 999: static string *date=0; ! 1000: static string *olddate=0; ! 1001: ! 1002: date = s_reset(date); ! 1003: olddate = s_reset(olddate); ! 1004: if (line) { ! 1005: s_append(olddate, line); ! 1006: sp = s_to_c(olddate); ! 1007: for (i = 0; *sp && i < 6; i++) { ! 1008: while (isspace(*sp) || *sp == ',' || *sp == '-') ! 1009: *sp++ = '\0'; ! 1010: field[i] = sp; ! 1011: while (!isspace(*sp) && *sp != ',' && *sp != '-' ! 1012: && *sp != '\0') ! 1013: sp++; ! 1014: } ! 1015: *sp = '\0'; ! 1016: if (i==6 && isalpha(*field[0])) { ! 1017: s_append(date, field[0]); ! 1018: s_putc(date, ' '); ! 1019: s_append(date, field[2]); ! 1020: s_putc(date, ' '); ! 1021: if(strlen(field[1])==1) ! 1022: s_putc(date, ' '); ! 1023: s_append(date, field[1]); ! 1024: s_putc(date, ' '); ! 1025: s_append(date, field[4]); ! 1026: s_putc(date, ' '); ! 1027: for (p = field[5]; *p; p++) ! 1028: if(islower(*p)) ! 1029: *p = toupper(*p); ! 1030: s_append(date, field[5]); ! 1031: s_putc(date, ' '); ! 1032: if (field[3][2]=='\0') ! 1033: s_append(date, "19"); ! 1034: s_append(date, field[3]); ! 1035: } ! 1036: } ! 1037: s_terminate(date); ! 1038: if (*s_to_c(date) == '\0') { ! 1039: s_append(date, thedate()); ! 1040: } ! 1041: return s_to_c(date); ! 1042: } ! 1043: ! 1044: /* Return 1 if addr has only one bang in it */ ! 1045: int ! 1046: onehop(addr) ! 1047: char *addr; ! 1048: { ! 1049: register char *p; ! 1050: register int cnt=0; ! 1051: ! 1052: for (p=addr; *p; ) ! 1053: if (*p++ == '!') ! 1054: if (cnt++>0) ! 1055: return 0; ! 1056: return 1; ! 1057: } ! 1058: @//E*O*F smtp/from822.c// ! 1059: chmod u=rw,g=r,o=r smtp/from822.c ! 1060: ! 1061: echo x - smtp/makefile ! 1062: sed 's/^@//' > "smtp/makefile" <<'@//E*O*F smtp/makefile//' ! 1063: # COBJ is for sysname_read() ! 1064: COBJ=log.o ../common/common.a ../libc/libc.a ../config/config.o ! 1065: ! 1066: QEROBJ=smtpqer.o to822addr.o qlib.o $(COBJ) ! 1067: SMTPOBJ=smtp.o converse.o netio.o to822addr.o to822.o header.o $(COBJ) ! 1068: SMTPDOBJ=smtpd.o conversed.o netio.o qlib.o from822addr.o from822.o header.o $(COBJ) ! 1069: ! 1070: CFLAGS=${UNIX} -g -I. -I../libc -I../common ${SCFLAGS} ! 1071: LIB=/usr/lib/upas ! 1072: ! 1073: ! 1074: all: smtp smtpd smtpqer smtpsched ! 1075: ! 1076: ! 1077: smtp: ../ipc/libipc.a $(SMTPOBJ) ! 1078: $(CC) $(SMTPOBJ) ../ipc/libipc.a -o smtp $(SLFLAGS) ! 1079: ! 1080: smtpd: $(SMTPDOBJ) ! 1081: $(CC) $(SMTPDOBJ) -o smtpd $(SLFLAGS) ! 1082: ! 1083: smtpqer: $(QEROBJ) ! 1084: $(CC) $(QEROBJ) -o smtpqer $(SLFLAGS) ! 1085: ! 1086: smtpsched: smtpsched.o qlib.o ! 1087: $(CC) smtpsched.o qlib.o $(COBJ) -o smtpsched $(SLFLAGS) ! 1088: ! 1089: ! 1090: from822.o: header.h ../common/mail.h ../common/string.h ../common/aux.h ! 1091: from822addr.o: ../common/string.h ! 1092: header.o: header.h ../common/mail.h ../common/string.h ../common/aux.h ! 1093: converse.o: smtp.h ../common/mail.h ../common/string.h ! 1094: conversed.o: smtp.h cmds.h ../common/mail.h ../common/string.h ! 1095: smtp.o: smtp.h ../common/string.h ../common/aux.h ! 1096: netio.o: smtp.h ! 1097: qlib.o: smtp.h ../common/string.h ! 1098: smtpqer.o: ../common/string.h ../common/mail.h ! 1099: smtpsched.o: smtp.h ../common/string.h ! 1100: to822.o: header.h addrformat.h ../common/mail.h ../common/string.h \ ! 1101: ../common/aux.h ! 1102: to822addr.o: addrformat.h ../common/string.h ! 1103: ! 1104: sedfile: ! 1105: echo 's+LIBDIR+$(LIB)+g' >sed.file ! 1106: ! 1107: install: dirs sedfile $(LIB)/smtp $(LIB)/smtpd $(LIB)/smtpqer $(LIB)/smtpsched install.smtpd.sh ! 1108: ! 1109: dirs: ! 1110: -mkdir /usr/spool/smtpq ! 1111: -chown uucp /usr/spool/smtpq ! 1112: -chmod 775 /usr/spool/smtpq ! 1113: ! 1114: install.smtpd.sh: ! 1115: sed -f sed.file smtpd.sh >$(LIB)/smtpd.sh ! 1116: -chmod 775 $(LIB)/smtpd.sh ! 1117: ! 1118: $(LIB)/smtp: smtp ! 1119: chmod 755 smtp ! 1120: cp smtp $(LIB)/smtp ! 1121: strip $(LIB)/smtp ! 1122: ! 1123: $(LIB)/smtpd: smtpd ! 1124: chmod 755 smtpd ! 1125: cp smtpd $(LIB)/smtpd ! 1126: strip $(LIB)/smtpd ! 1127: ! 1128: $(LIB)/smtpqer: smtpqer ! 1129: cp smtpqer $(LIB)/smtpqer ! 1130: strip $(LIB)/smtpqer ! 1131: chown uucp $(LIB)/smtpqer ! 1132: chgrp uucp $(LIB)/smtpqer ! 1133: chmod 6775 $(LIB)/smtpqer ! 1134: ! 1135: $(LIB)/smtpsched: smtpsched ! 1136: chmod 755 smtpsched ! 1137: cp smtpsched $(LIB)/smtpsched ! 1138: strip $(LIB)/smtpsched ! 1139: ! 1140: ! 1141: clean: ! 1142: rm -f smtp smtpd smtpqer smtpsched *.o sed.file ! 1143: @//E*O*F smtp/makefile// ! 1144: chmod u=rw,g=r,o=r smtp/makefile ! 1145: ! 1146: echo x - misc/getpeer.c ! 1147: sed 's/^@//' > "misc/getpeer.c" <<'@//E*O*F misc/getpeer.c//' ! 1148: #include <stdio.h> ! 1149: #include <sys/types.h> ! 1150: #include <sys/socket.h> ! 1151: #include <netdb.h> ! 1152: #include <netinet/in.h> ! 1153: ! 1154: main(argc, argv) ! 1155: int argc; ! 1156: char *argv[]; ! 1157: { ! 1158: int iplen; ! 1159: char *adc, *inet_ntoa(); ! 1160: struct sockaddr_in ip; ! 1161: struct hostent *hp, *gethostbyaddr(); ! 1162: ! 1163: iplen = sizeof(ip); ! 1164: if ( -1 == getpeername(0, &ip, &iplen) ) { ! 1165: perror("getpeername"); ! 1166: exit(1); ! 1167: } ! 1168: adc = inet_ntoa(ip.sin_addr); ! 1169: if ( NULL == (hp = gethostbyaddr(&ip.sin_addr, sizeof(ip.sin_addr), ! 1170: AF_INET) ) ) ! 1171: printf("[%s]\n", adc); ! 1172: else ! 1173: printf("%s [%s]\n", hp->h_name, adc); ! 1174: } ! 1175: @//E*O*F misc/getpeer.c// ! 1176: chmod u=rw,g=r,o=r misc/getpeer.c ! 1177: ! 1178: echo x - misc/maphost.c ! 1179: sed 's/^@//' > "misc/maphost.c" <<'@//E*O*F misc/maphost.c//' ! 1180: #include <stdio.h> ! 1181: #include <dk.h> ! 1182: ! 1183: main(argc, argv) ! 1184: int argc; ! 1185: char *argv[]; ! 1186: { ! 1187: if ( argc != 2 ) { ! 1188: fprintf(stderr, "Usage maphost host\n"); ! 1189: exit(1); ! 1190: } ! 1191: printf("%s\n", maphost(argv[1], 's', "", "", "")); ! 1192: exit(0); ! 1193: } ! 1194: @//E*O*F misc/maphost.c// ! 1195: chmod u=rw,g=r,o=r misc/maphost.c ! 1196: ! 1197: echo x - misc/makefile ! 1198: sed 's/^@//' > "misc/makefile" <<'@//E*O*F misc/makefile//' ! 1199: LIB=/usr/lib/upas ! 1200: CFLAGS=${UNIX} -g -I. -I../libc -I../common -I/usr/include -I/usr/include/sys ! 1201: LFLAGS=-g ! 1202: HOSTNAME=cat /etc/whoami ! 1203: ! 1204: #DKINCLUDE=-I/usr/include/dkit ! 1205: ! 1206: @.c.o: ; $(CC) -c $(CFLAGS) $(DKINCLUDE) $*.c ! 1207: all: mail ! 1208: ! 1209: maphost: maphost.o ! 1210: cc maphost.o -L/usr/dk/lib -ldk -o maphost ! 1211: ! 1212: getpeer: getpeer.o ! 1213: cc getpeer.o -o getpeer ! 1214: ! 1215: sedfile: ! 1216: echo 's+LIBDIR+$(LIB)+g' >sed.file ! 1217: echo 's+HOSTNAME+$(HOSTNAME)+g' >>sed.file ! 1218: ! 1219: install: sedfile install.fish install.mail.sh ! 1220: ! 1221: install.getpeer: getpeer sedfile ! 1222: cp getpeer $(LIB) ! 1223: -chmod 775 $(LIB)/getpeer ! 1224: strip $(LIB)/getpeer ! 1225: ! 1226: install.maphost: maphost sedfile ! 1227: cp maphost $(LIB) ! 1228: -chmod 775 $(LIB)/maphost ! 1229: strip $(LIB)/maphost ! 1230: ! 1231: install.fish: ! 1232: cp gone.msg $(LIB) ! 1233: sed -f sed.file gone.fishing >$(LIB)/gone.fishing ! 1234: -chmod 775 $(LIB)/gone.fishing ! 1235: -chown bin $(LIB)/gone.fishing $(LIB)/gone.msg ! 1236: ! 1237: install.mail.sh: ! 1238: sed -f sed.file mail.sh >/bin/mail ! 1239: -chown bin /bin/mail ! 1240: -chmod 775 /bin/mail ! 1241: ! 1242: install.notify: notify ! 1243: cp notify $(LIB)/notify ! 1244: -chmod 775 $(LIB)/notify ! 1245: -chown bin $(LIB)/notify ! 1246: ! 1247: install.mail: mail ! 1248: cp mail /bin ! 1249: strip /bin/mail ! 1250: ! 1251: notify: notify.o ! 1252: cc $(LFLAGS) notify.o -o notify ! 1253: ! 1254: mail: mail.o ../config/config.o ! 1255: cc $(LFLAGS) mail.o ../config/config.o -o mail ! 1256: ! 1257: clean: ! 1258: -rm -f *.[oOa] core a.out *.sL notify ! 1259: -rm -f sed.file mail getpeer maphost ! 1260: ! 1261: @//E*O*F misc/makefile// ! 1262: chmod u=rw,g=r,o=r misc/makefile ! 1263: ! 1264: exit 0 ! 1265:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.