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