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