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

Defined functions

closexscript defined in line 369; used 1 times
settime defined in line 297; used 2 times
trusteduser defined in line 579; used 3 times

Defined variables

SccsId defined in line 12; never used
Last modified: 1994-07-15
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4840
Valid CSS Valid XHTML 1.0 Strict