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: }