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