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: #if !defined(lint) && !defined(NOSCCS) 12: static char SccsId[] = "@(#)envelope.c 5.12.1 (2.11BSD GTE) 7/15/94"; 13: #endif 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: 236: /* 237: ** Give this envelope a reality. 238: ** I.e., an id, a transcript, and a creation time. 239: */ 240: 241: openxscript(CurEnv); 242: CurEnv->e_ctime = curtime(); 243: 244: /* 245: ** Set OutChannel to something useful if stdout isn't it. 246: ** This arranges that any extra stuff the mailer produces 247: ** gets sent back to the user on error (because it is 248: ** tucked away in the transcript). 249: */ 250: 251: if (OpMode == MD_DAEMON && QueueRun) 252: OutChannel = CurEnv->e_xfp; 253: 254: /* 255: ** Set up some basic system macros. 256: */ 257: 258: /* process id */ 259: (void) sprintf(pbuf, "%d", getpid()); 260: define('p', pbuf, CurEnv); 261: 262: /* hop count */ 263: (void) sprintf(cbuf, "%d", CurEnv->e_hopcount); 264: define('c', cbuf, CurEnv); 265: 266: /* time as integer, unix time, arpa time */ 267: settime(); 268: 269: #ifdef TTYNAME 270: /* tty name */ 271: if (macvalue('y', CurEnv) == NULL) 272: { 273: p = ttyname(2); 274: if (p != NULL) 275: { 276: if (rindex(p, '/') != NULL) 277: p = rindex(p, '/') + 1; 278: (void) strcpy(ybuf, p); 279: define('y', ybuf, CurEnv); 280: } 281: } 282: #endif TTYNAME 283: } 284: /* 285: ** SETTIME -- set the current time. 286: ** 287: ** Parameters: 288: ** none. 289: ** 290: ** Returns: 291: ** none. 292: ** 293: ** Side Effects: 294: ** Sets the various time macros -- $a, $b, $d, $t. 295: */ 296: 297: settime() 298: { 299: register char *p; 300: auto time_t now; 301: static char tbuf[20]; /* holds "current" time */ 302: static char dbuf[30]; /* holds ctime(tbuf) */ 303: register struct tm *tm; 304: extern char *arpadate(); 305: extern struct tm *gmtime(); 306: extern char *macvalue(); 307: 308: now = curtime(); 309: tm = gmtime(&now); 310: (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1, 311: tm->tm_mday, tm->tm_hour, tm->tm_min); 312: define('t', tbuf, CurEnv); 313: (void) strcpy(dbuf, ctime(&now)); 314: *index(dbuf, '\n') = '\0'; 315: if (macvalue('d', CurEnv) == NULL) 316: define('d', dbuf, CurEnv); 317: p = newstr(arpadate(dbuf)); 318: if (macvalue('a', CurEnv) == NULL) 319: define('a', p, CurEnv); 320: define('b', p, CurEnv); 321: } 322: /* 323: ** OPENXSCRIPT -- Open transcript file 324: ** 325: ** Creates a transcript file for possible eventual mailing or 326: ** sending back. 327: ** 328: ** Parameters: 329: ** e -- the envelope to create the transcript in/for. 330: ** 331: ** Returns: 332: ** none 333: ** 334: ** Side Effects: 335: ** Creates the transcript file. 336: */ 337: 338: openxscript(e) 339: register ENVELOPE *e; 340: { 341: register char *p; 342: 343: # ifdef LOG 344: if (LogLevel > 19) 345: syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)"); 346: # endif LOG 347: if (e->e_xfp != NULL) 348: return; 349: p = queuename(e, 'x'); 350: e->e_xfp = fopen(p, "w"); 351: if (e->e_xfp == NULL) 352: syserr("Can't create %s", p); 353: else 354: (void) chmod(p, 0644); 355: } 356: /* 357: ** CLOSEXSCRIPT -- close the transcript file. 358: ** 359: ** Parameters: 360: ** e -- the envelope containing the transcript to close. 361: ** 362: ** Returns: 363: ** none. 364: ** 365: ** Side Effects: 366: ** none. 367: */ 368: 369: closexscript(e) 370: register ENVELOPE *e; 371: { 372: if (e->e_xfp == NULL) 373: return; 374: (void) fclose(e->e_xfp); 375: e->e_xfp = NULL; 376: } 377: /* 378: ** SETSENDER -- set the person who this message is from 379: ** 380: ** Under certain circumstances allow the user to say who 381: ** s/he is (using -f or -r). These are: 382: ** 1. The user's uid is zero (root). 383: ** 2. The user's login name is in an approved list (typically 384: ** from a network server). 385: ** 3. The address the user is trying to claim has a 386: ** "!" character in it (since #2 doesn't do it for 387: ** us if we are dialing out for UUCP). 388: ** A better check to replace #3 would be if the 389: ** effective uid is "UUCP" -- this would require me 390: ** to rewrite getpwent to "grab" uucp as it went by, 391: ** make getname more nasty, do another passwd file 392: ** scan, or compile the UID of "UUCP" into the code, 393: ** all of which are reprehensible. 394: ** 395: ** Assuming all of these fail, we figure out something 396: ** ourselves. 397: ** 398: ** Parameters: 399: ** from -- the person we would like to believe this message 400: ** is from, as specified on the command line. 401: ** 402: ** Returns: 403: ** none. 404: ** 405: ** Side Effects: 406: ** sets sendmail's notion of who the from person is. 407: */ 408: 409: setsender(from) 410: char *from; 411: { 412: register char **pvp; 413: char *realname = NULL; 414: register struct passwd *pw; 415: char buf[MAXNAME]; 416: char pvpbuf[PSBUFSIZE]; 417: extern struct passwd *getpwnam(); 418: extern char *macvalue(); 419: extern char **prescan(); 420: extern bool safefile(); 421: extern char *FullName; 422: 423: # ifdef DEBUG 424: if (tTd(45, 1)) 425: printf("setsender(%s)\n", from == NULL ? "" : from); 426: # endif DEBUG 427: 428: /* 429: ** Figure out the real user executing us. 430: ** Username can return errno != 0 on non-errors. 431: */ 432: 433: if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP) 434: realname = from; 435: if (realname == NULL || realname[0] == '\0') 436: { 437: extern char *username(); 438: 439: realname = username(); 440: } 441: 442: /* 443: ** Determine if this real person is allowed to alias themselves. 444: */ 445: 446: if (from != NULL) 447: { 448: extern bool trusteduser(); 449: 450: if (!trusteduser(realname) && 451: # ifdef DEBUG 452: (!tTd(1, 9) || getuid() != geteuid()) && 453: # endif DEBUG 454: index(from, '!') == NULL && getuid() != 0) 455: { 456: /* network sends -r regardless (why why why?) */ 457: /* syserr("%s, you cannot use the -f flag", realname); */ 458: from = NULL; 459: } 460: } 461: 462: SuprErrs = TRUE; 463: if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL) 464: { 465: /* log garbage addresses for traceback */ 466: if (from != NULL) 467: { 468: # ifdef LOG 469: if (LogLevel >= 1) 470: syslog(LOG_ERR, "Unparseable user %s wants to be %s", 471: realname, from); 472: # endif LOG 473: } 474: from = newstr(realname); 475: if (parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL && 476: parseaddr("postmaster", &CurEnv->e_from, 1, '\0') == NULL) 477: { 478: syserr("setsender: can't even parse postmaster!"); 479: } 480: } 481: else 482: FromFlag = TRUE; 483: CurEnv->e_from.q_flags |= QDONTSEND; 484: loweraddr(&CurEnv->e_from); 485: SuprErrs = FALSE; 486: 487: if (CurEnv->e_from.q_mailer == LocalMailer && 488: (pw = getpwnam(CurEnv->e_from.q_user)) != NULL) 489: { 490: /* 491: ** Process passwd file entry. 492: */ 493: 494: 495: /* extract home directory */ 496: CurEnv->e_from.q_home = newstr(pw->pw_dir); 497: define('z', CurEnv->e_from.q_home, CurEnv); 498: 499: /* extract user and group id */ 500: CurEnv->e_from.q_uid = pw->pw_uid; 501: CurEnv->e_from.q_gid = pw->pw_gid; 502: 503: /* if the user has given fullname already, don't redefine */ 504: if (FullName == NULL) 505: FullName = macvalue('x', CurEnv); 506: if (FullName != NULL && FullName[0] == '\0') 507: FullName = NULL; 508: 509: /* extract full name from passwd file */ 510: if (FullName == NULL && pw->pw_gecos != NULL && 511: strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0) 512: { 513: buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf); 514: if (buf[0] != '\0') 515: FullName = newstr(buf); 516: } 517: if (FullName != NULL) 518: define('x', FullName, CurEnv); 519: } 520: else 521: { 522: #ifndef V6 523: if (CurEnv->e_from.q_home == NULL) 524: CurEnv->e_from.q_home = getenv("HOME"); 525: #endif V6 526: CurEnv->e_from.q_uid = getuid(); 527: CurEnv->e_from.q_gid = getgid(); 528: } 529: 530: if (CurEnv->e_from.q_uid != 0) 531: { 532: DefUid = CurEnv->e_from.q_uid; 533: DefGid = CurEnv->e_from.q_gid; 534: } 535: 536: /* 537: ** Rewrite the from person to dispose of possible implicit 538: ** links in the net. 539: */ 540: 541: pvp = prescan(from, '\0', pvpbuf); 542: if (pvp == NULL) 543: { 544: syserr("cannot prescan from (%s)", from); 545: finis(); 546: } 547: rewrite(pvp, 3); 548: rewrite(pvp, 1); 549: rewrite(pvp, 4); 550: cataddr(pvp, buf, sizeof buf); 551: define('f', newstr(buf), CurEnv); 552: 553: /* save the domain spec if this mailer wants it */ 554: if (CurEnv->e_from.q_mailer != NULL && 555: bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags)) 556: { 557: extern char **copyplist(); 558: 559: while (*pvp != NULL && strcmp(*pvp, "@") != 0) 560: pvp++; 561: if (*pvp != NULL) 562: CurEnv->e_fromdomain = copyplist(pvp, TRUE); 563: } 564: } 565: /* 566: ** TRUSTEDUSER -- tell us if this user is to be trusted. 567: ** 568: ** Parameters: 569: ** user -- the user to be checked. 570: ** 571: ** Returns: 572: ** TRUE if the user is in an approved list. 573: ** FALSE otherwise. 574: ** 575: ** Side Effects: 576: ** none. 577: */ 578: 579: bool 580: trusteduser(user) 581: char *user; 582: { 583: register char **ulist; 584: extern char *TrustedUsers[]; 585: 586: for (ulist = TrustedUsers; *ulist != NULL; ulist++) 587: if (strcmp(*ulist, user) == 0) 588: return (TRUE); 589: return (FALSE); 590: }