|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Eric P. Allman ! 3: * Copyright (c) 1988 Regents of the University of California. ! 4: * All rights reserved. ! 5: * ! 6: * Redistribution and use in source and binary forms are permitted provided ! 7: * that: (1) source distributions retain this entire copyright notice and ! 8: * comment, and (2) distributions including binaries display the following ! 9: * acknowledgement: ``This product includes software developed by the ! 10: * University of California, Berkeley and its contributors'' in the ! 11: * documentation or other materials provided with the distribution and in ! 12: * all advertising materials mentioning features or use of this software. ! 13: * Neither the name of the University nor the names of its contributors may ! 14: * be used to endorse or promote products derived from this software without ! 15: * specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: */ ! 20: ! 21: #ifndef lint ! 22: static char sccsid[] = "@(#)envelope.c 5.22 (Berkeley) 6/1/90"; ! 23: #endif /* not lint */ ! 24: ! 25: #include <sys/types.h> ! 26: #include <sys/time.h> ! 27: #include <sys/stat.h> ! 28: #include <pwd.h> ! 29: #include <sys/file.h> ! 30: #include "sendmail.h" ! 31: ! 32: /* ! 33: ** NEWENVELOPE -- allocate a new envelope ! 34: ** ! 35: ** Supports inheritance. ! 36: ** ! 37: ** Parameters: ! 38: ** e -- the new envelope to fill in. ! 39: ** ! 40: ** Returns: ! 41: ** e. ! 42: ** ! 43: ** Side Effects: ! 44: ** none. ! 45: */ ! 46: ! 47: ENVELOPE * ! 48: newenvelope(e) ! 49: register ENVELOPE *e; ! 50: { ! 51: register ENVELOPE *parent; ! 52: extern putheader(), putbody(); ! 53: extern ENVELOPE BlankEnvelope; ! 54: ! 55: parent = CurEnv; ! 56: if (e == CurEnv) ! 57: parent = e->e_parent; ! 58: clearenvelope(e, TRUE); ! 59: if (e == CurEnv) ! 60: bcopy((char *) &NullAddress, (char *) &e->e_from, sizeof e->e_from); ! 61: else ! 62: bcopy((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from); ! 63: e->e_parent = parent; ! 64: e->e_ctime = curtime(); ! 65: e->e_msgpriority = parent->e_msgsize; ! 66: e->e_puthdr = putheader; ! 67: e->e_putbody = putbody; ! 68: if (CurEnv->e_xfp != NULL) ! 69: (void) fflush(CurEnv->e_xfp); ! 70: ! 71: return (e); ! 72: } ! 73: /* ! 74: ** DROPENVELOPE -- deallocate an envelope. ! 75: ** ! 76: ** Parameters: ! 77: ** e -- the envelope to deallocate. ! 78: ** ! 79: ** Returns: ! 80: ** none. ! 81: ** ! 82: ** Side Effects: ! 83: ** housekeeping necessary to dispose of an envelope. ! 84: ** Unlocks this queue file. ! 85: */ ! 86: ! 87: dropenvelope(e) ! 88: register ENVELOPE *e; ! 89: { ! 90: bool queueit = FALSE; ! 91: register ADDRESS *q; ! 92: ! 93: if (tTd(50, 1)) ! 94: { ! 95: printf("dropenvelope %x id=", e); ! 96: xputs(e->e_id); ! 97: printf(" flags=%o\n", e->e_flags); ! 98: } ! 99: #ifdef LOG ! 100: if (LogLevel > 10) ! 101: syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d", ! 102: e->e_id == NULL ? "(none)" : e->e_id, ! 103: e->e_flags, getpid()); ! 104: #endif LOG ! 105: ! 106: /* we must have an id to remove disk files */ ! 107: if (e->e_id == NULL) ! 108: return; ! 109: ! 110: /* ! 111: ** Extract state information from dregs of send list. ! 112: */ ! 113: ! 114: for (q = e->e_sendqueue; q != NULL; q = q->q_next) ! 115: { ! 116: if (bitset(QQUEUEUP, q->q_flags)) ! 117: queueit = TRUE; ! 118: } ! 119: ! 120: /* ! 121: ** Send back return receipts as requested. ! 122: */ ! 123: ! 124: if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags)) ! 125: { ! 126: auto ADDRESS *rlist = NULL; ! 127: ! 128: sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist); ! 129: (void) returntosender("Return receipt", rlist, FALSE); ! 130: } ! 131: ! 132: /* ! 133: ** Arrange to send error messages if there are fatal errors. ! 134: */ ! 135: ! 136: if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET) ! 137: savemail(e); ! 138: ! 139: /* ! 140: ** Instantiate or deinstantiate the queue. ! 141: */ ! 142: ! 143: if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) || ! 144: bitset(EF_CLRQUEUE, e->e_flags)) ! 145: { ! 146: if (e->e_df != NULL) ! 147: xunlink(e->e_df); ! 148: xunlink(queuename(e, 'q')); ! 149: } ! 150: else if (queueit || !bitset(EF_INQUEUE, e->e_flags)) ! 151: { ! 152: #ifdef QUEUE ! 153: FILE *lockfp, *queueup(); ! 154: lockfp = queueup(e, FALSE, FALSE); ! 155: if (lockfp != NULL) ! 156: (void) fclose(lockfp); ! 157: #else QUEUE ! 158: syserr("dropenvelope: queueup"); ! 159: #endif QUEUE ! 160: } ! 161: ! 162: /* now unlock the job */ ! 163: closexscript(e); ! 164: unlockqueue(e); ! 165: ! 166: /* make sure that this envelope is marked unused */ ! 167: e->e_id = e->e_df = NULL; ! 168: if (e->e_dfp != NULL) ! 169: (void) fclose(e->e_dfp); ! 170: e->e_dfp = NULL; ! 171: } ! 172: /* ! 173: ** CLEARENVELOPE -- clear an envelope without unlocking ! 174: ** ! 175: ** This is normally used by a child process to get a clean ! 176: ** envelope without disturbing the parent. ! 177: ** ! 178: ** Parameters: ! 179: ** e -- the envelope to clear. ! 180: ** fullclear - if set, the current envelope is total ! 181: ** garbage and should be ignored; otherwise, ! 182: ** release any resources it may indicate. ! 183: ** ! 184: ** Returns: ! 185: ** none. ! 186: ** ! 187: ** Side Effects: ! 188: ** Closes files associated with the envelope. ! 189: ** Marks the envelope as unallocated. ! 190: */ ! 191: ! 192: clearenvelope(e, fullclear) ! 193: register ENVELOPE *e; ! 194: bool fullclear; ! 195: { ! 196: register HDR *bh; ! 197: register HDR **nhp; ! 198: extern ENVELOPE BlankEnvelope; ! 199: ! 200: if (!fullclear) ! 201: { ! 202: /* clear out any file information */ ! 203: if (e->e_xfp != NULL) ! 204: (void) fclose(e->e_xfp); ! 205: if (e->e_dfp != NULL) ! 206: (void) fclose(e->e_dfp); ! 207: } ! 208: ! 209: /* now clear out the data */ ! 210: STRUCTCOPY(BlankEnvelope, *e); ! 211: bh = BlankEnvelope.e_header; ! 212: nhp = &e->e_header; ! 213: while (bh != NULL) ! 214: { ! 215: *nhp = (HDR *) xalloc(sizeof *bh); ! 216: bcopy((char *) bh, (char *) *nhp, sizeof *bh); ! 217: bh = bh->h_link; ! 218: nhp = &(*nhp)->h_link; ! 219: } ! 220: } ! 221: /* ! 222: ** INITSYS -- initialize instantiation of system ! 223: ** ! 224: ** In Daemon mode, this is done in the child. ! 225: ** ! 226: ** Parameters: ! 227: ** none. ! 228: ** ! 229: ** Returns: ! 230: ** none. ! 231: ** ! 232: ** Side Effects: ! 233: ** Initializes the system macros, some global variables, ! 234: ** etc. In particular, the current time in various ! 235: ** forms is set. ! 236: */ ! 237: ! 238: initsys() ! 239: { ! 240: static char cbuf[5]; /* holds hop count */ ! 241: static char pbuf[10]; /* holds pid */ ! 242: #ifdef TTYNAME ! 243: static char ybuf[10]; /* holds tty id */ ! 244: register char *p; ! 245: #endif TTYNAME ! 246: extern char *ttyname(); ! 247: extern char *macvalue(); ! 248: extern char Version[]; ! 249: ! 250: /* ! 251: ** Give this envelope a reality. ! 252: ** I.e., an id, a transcript, and a creation time. ! 253: */ ! 254: ! 255: openxscript(CurEnv); ! 256: CurEnv->e_ctime = curtime(); ! 257: ! 258: /* ! 259: ** Set OutChannel to something useful if stdout isn't it. ! 260: ** This arranges that any extra stuff the mailer produces ! 261: ** gets sent back to the user on error (because it is ! 262: ** tucked away in the transcript). ! 263: */ ! 264: ! 265: if (OpMode == MD_DAEMON && QueueRun) ! 266: OutChannel = CurEnv->e_xfp; ! 267: ! 268: /* ! 269: ** Set up some basic system macros. ! 270: */ ! 271: ! 272: /* process id */ ! 273: (void) sprintf(pbuf, "%d", getpid()); ! 274: define('p', pbuf, CurEnv); ! 275: ! 276: /* hop count */ ! 277: (void) sprintf(cbuf, "%d", CurEnv->e_hopcount); ! 278: define('c', cbuf, CurEnv); ! 279: ! 280: /* time as integer, unix time, arpa time */ ! 281: settime(); ! 282: ! 283: #ifdef TTYNAME ! 284: /* tty name */ ! 285: if (macvalue('y', CurEnv) == NULL) ! 286: { ! 287: p = ttyname(2); ! 288: if (p != NULL) ! 289: { ! 290: if (rindex(p, '/') != NULL) ! 291: p = rindex(p, '/') + 1; ! 292: (void) strcpy(ybuf, p); ! 293: define('y', ybuf, CurEnv); ! 294: } ! 295: } ! 296: #endif TTYNAME ! 297: } ! 298: /* ! 299: ** SETTIME -- set the current time. ! 300: ** ! 301: ** Parameters: ! 302: ** none. ! 303: ** ! 304: ** Returns: ! 305: ** none. ! 306: ** ! 307: ** Side Effects: ! 308: ** Sets the various time macros -- $a, $b, $d, $t. ! 309: */ ! 310: ! 311: settime() ! 312: { ! 313: register char *p; ! 314: auto time_t now; ! 315: static char tbuf[20]; /* holds "current" time */ ! 316: static char dbuf[30]; /* holds ctime(tbuf) */ ! 317: register struct tm *tm; ! 318: extern char *arpadate(); ! 319: extern struct tm *gmtime(); ! 320: extern char *macvalue(); ! 321: ! 322: now = curtime(); ! 323: tm = gmtime(&now); ! 324: (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1, ! 325: tm->tm_mday, tm->tm_hour, tm->tm_min); ! 326: define('t', tbuf, CurEnv); ! 327: (void) strcpy(dbuf, ctime(&now)); ! 328: *index(dbuf, '\n') = '\0'; ! 329: if (macvalue('d', CurEnv) == NULL) ! 330: define('d', dbuf, CurEnv); ! 331: p = newstr(arpadate(dbuf)); ! 332: if (macvalue('a', CurEnv) == NULL) ! 333: define('a', p, CurEnv); ! 334: define('b', p, CurEnv); ! 335: } ! 336: /* ! 337: ** OPENXSCRIPT -- Open transcript file ! 338: ** ! 339: ** Creates a transcript file for possible eventual mailing or ! 340: ** sending back. ! 341: ** ! 342: ** Parameters: ! 343: ** e -- the envelope to create the transcript in/for. ! 344: ** ! 345: ** Returns: ! 346: ** none ! 347: ** ! 348: ** Side Effects: ! 349: ** Creates the transcript file. ! 350: */ ! 351: ! 352: openxscript(e) ! 353: register ENVELOPE *e; ! 354: { ! 355: register char *p; ! 356: int fd; ! 357: ! 358: # ifdef LOG ! 359: if (LogLevel > 19) ! 360: syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)"); ! 361: # endif LOG ! 362: if (e->e_xfp != NULL) ! 363: return; ! 364: p = queuename(e, 'x'); ! 365: fd = open(p, O_WRONLY|O_CREAT, 0644); ! 366: if (fd < 0) ! 367: syserr("Can't create %s", p); ! 368: else ! 369: e->e_xfp = fdopen(fd, "w"); ! 370: } ! 371: /* ! 372: ** CLOSEXSCRIPT -- close the transcript file. ! 373: ** ! 374: ** Parameters: ! 375: ** e -- the envelope containing the transcript to close. ! 376: ** ! 377: ** Returns: ! 378: ** none. ! 379: ** ! 380: ** Side Effects: ! 381: ** none. ! 382: */ ! 383: ! 384: closexscript(e) ! 385: register ENVELOPE *e; ! 386: { ! 387: if (e->e_xfp == NULL) ! 388: return; ! 389: (void) fclose(e->e_xfp); ! 390: e->e_xfp = NULL; ! 391: } ! 392: /* ! 393: ** SETSENDER -- set the person who this message is from ! 394: ** ! 395: ** Under certain circumstances allow the user to say who ! 396: ** s/he is (using -f or -r). These are: ! 397: ** 1. The user's uid is zero (root). ! 398: ** 2. The user's login name is in an approved list (typically ! 399: ** from a network server). ! 400: ** 3. The address the user is trying to claim has a ! 401: ** "!" character in it (since #2 doesn't do it for ! 402: ** us if we are dialing out for UUCP). ! 403: ** A better check to replace #3 would be if the ! 404: ** effective uid is "UUCP" -- this would require me ! 405: ** to rewrite getpwent to "grab" uucp as it went by, ! 406: ** make getname more nasty, do another passwd file ! 407: ** scan, or compile the UID of "UUCP" into the code, ! 408: ** all of which are reprehensible. ! 409: ** ! 410: ** Assuming all of these fail, we figure out something ! 411: ** ourselves. ! 412: ** ! 413: ** Parameters: ! 414: ** from -- the person we would like to believe this message ! 415: ** is from, as specified on the command line. ! 416: ** ! 417: ** Returns: ! 418: ** none. ! 419: ** ! 420: ** Side Effects: ! 421: ** sets sendmail's notion of who the from person is. ! 422: */ ! 423: ! 424: setsender(from) ! 425: char *from; ! 426: { ! 427: register char **pvp; ! 428: char *realname = NULL; ! 429: register struct passwd *pw; ! 430: char buf[MAXNAME]; ! 431: char pvpbuf[PSBUFSIZE]; ! 432: extern struct passwd *getpwnam(); ! 433: extern char *macvalue(); ! 434: extern char **prescan(); ! 435: extern bool safefile(); ! 436: extern char *FullName; ! 437: ! 438: if (tTd(45, 1)) ! 439: printf("setsender(%s)\n", from == NULL ? "" : from); ! 440: ! 441: /* ! 442: ** Figure out the real user executing us. ! 443: ** Username can return errno != 0 on non-errors. ! 444: */ ! 445: ! 446: if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP) ! 447: realname = from; ! 448: if (realname == NULL || realname[0] == '\0') ! 449: { ! 450: extern char *username(); ! 451: ! 452: realname = username(); ! 453: } ! 454: ! 455: /* ! 456: ** Determine if this real person is allowed to alias themselves. ! 457: */ ! 458: ! 459: if (from != NULL) ! 460: { ! 461: extern bool trusteduser(); ! 462: ! 463: if (!trusteduser(realname) && getuid() != geteuid() && ! 464: index(from, '!') == NULL && getuid() != 0) ! 465: { ! 466: /* network sends -r regardless (why why why?) */ ! 467: /* syserr("%s, you cannot use the -f flag", realname); */ ! 468: from = NULL; ! 469: } ! 470: } ! 471: ! 472: SuprErrs = TRUE; ! 473: if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL) ! 474: { ! 475: /* log garbage addresses for traceback */ ! 476: if (from != NULL) ! 477: { ! 478: # ifdef LOG ! 479: if (LogLevel >= 1) ! 480: if (realname == from && RealHostName != NULL) ! 481: syslog(LOG_NOTICE, ! 482: "from=%s unparseable, received from %s", ! 483: from, RealHostName); ! 484: else ! 485: syslog(LOG_NOTICE, ! 486: "Unparseable username %s wants from=%s", ! 487: realname, from); ! 488: # endif LOG ! 489: } ! 490: from = newstr(realname); ! 491: if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL && ! 492: parseaddr("postmaster", &CurEnv->e_from, 1, '\0') == NULL) ! 493: { ! 494: syserr("setsender: can't even parse postmaster!"); ! 495: } ! 496: } ! 497: else ! 498: FromFlag = TRUE; ! 499: CurEnv->e_from.q_flags |= QDONTSEND; ! 500: loweraddr(&CurEnv->e_from); ! 501: SuprErrs = FALSE; ! 502: ! 503: if (CurEnv->e_from.q_mailer == LocalMailer && ! 504: (pw = getpwnam(CurEnv->e_from.q_user)) != NULL) ! 505: { ! 506: /* ! 507: ** Process passwd file entry. ! 508: */ ! 509: ! 510: ! 511: /* extract home directory */ ! 512: CurEnv->e_from.q_home = newstr(pw->pw_dir); ! 513: define('z', CurEnv->e_from.q_home, CurEnv); ! 514: ! 515: /* extract user and group id */ ! 516: CurEnv->e_from.q_uid = pw->pw_uid; ! 517: CurEnv->e_from.q_gid = pw->pw_gid; ! 518: ! 519: /* if the user has given fullname already, don't redefine */ ! 520: if (FullName == NULL) ! 521: FullName = macvalue('x', CurEnv); ! 522: if (FullName != NULL && FullName[0] == '\0') ! 523: FullName = NULL; ! 524: ! 525: /* extract full name from passwd file */ ! 526: if (FullName == NULL && pw->pw_gecos != NULL && ! 527: strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0) ! 528: { ! 529: buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf); ! 530: if (buf[0] != '\0') ! 531: FullName = newstr(buf); ! 532: } ! 533: if (FullName != NULL) ! 534: define('x', FullName, CurEnv); ! 535: } ! 536: else ! 537: { ! 538: if (CurEnv->e_from.q_home == NULL) ! 539: CurEnv->e_from.q_home = getenv("HOME"); ! 540: CurEnv->e_from.q_uid = getuid(); ! 541: CurEnv->e_from.q_gid = getgid(); ! 542: } ! 543: ! 544: /* ! 545: ** Rewrite the from person to dispose of possible implicit ! 546: ** links in the net. ! 547: */ ! 548: ! 549: pvp = prescan(from, '\0', pvpbuf); ! 550: if (pvp == NULL) ! 551: { ! 552: # ifdef LOG ! 553: if (LogLevel >= 1) ! 554: syslog(LOG_NOTICE, "cannot prescan from (%s)", from); ! 555: # endif ! 556: usrerr("cannot prescan from (%s)", from); ! 557: finis(); ! 558: } ! 559: rewrite(pvp, 3); ! 560: rewrite(pvp, 1); ! 561: rewrite(pvp, 4); ! 562: cataddr(pvp, buf, sizeof buf); ! 563: define('f', newstr(buf), CurEnv); ! 564: ! 565: /* save the domain spec if this mailer wants it */ ! 566: if (CurEnv->e_from.q_mailer != NULL && ! 567: bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags)) ! 568: { ! 569: extern char **copyplist(); ! 570: ! 571: while (*pvp != NULL && strcmp(*pvp, "@") != 0) ! 572: pvp++; ! 573: if (*pvp != NULL) ! 574: CurEnv->e_fromdomain = copyplist(pvp, TRUE); ! 575: } ! 576: } ! 577: /* ! 578: ** TRUSTEDUSER -- tell us if this user is to be trusted. ! 579: ** ! 580: ** Parameters: ! 581: ** user -- the user to be checked. ! 582: ** ! 583: ** Returns: ! 584: ** TRUE if the user is in an approved list. ! 585: ** FALSE otherwise. ! 586: ** ! 587: ** Side Effects: ! 588: ** none. ! 589: */ ! 590: ! 591: bool ! 592: trusteduser(user) ! 593: char *user; ! 594: { ! 595: register char **ulist; ! 596: extern char *TrustedUsers[]; ! 597: ! 598: for (ulist = TrustedUsers; *ulist != NULL; ulist++) ! 599: if (strcmp(*ulist, user) == 0) ! 600: return (TRUE); ! 601: return (FALSE); ! 602: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.