home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65 / src / envelope.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-06-05  |  13.3 KB  |  603 lines

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