home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / src / submit / mgt_submit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-02-28  |  27.6 KB  |  973 lines

  1. /*
  2.  *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
  3.  *
  4.  *
  5.  *     Copyright (C) 1979,1980,1981  University of Delaware
  6.  *
  7.  *     Department of Electrical Engineering
  8.  *     University of Delaware
  9.  *     Newark, Delaware  19711
  10.  *
  11.  *     Phone:  (302) 738-1163
  12.  *
  13.  *
  14.  *     This program module was developed as part of the University
  15.  *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
  16.  *
  17.  *     Acquisition, use, and distribution of this module and its listings
  18.  *     are subject restricted to the terms of a license agreement.
  19.  *     Documents describing systems using this module must cite its source.
  20.  *
  21.  *     The above statements must be retained with all copies of this
  22.  *     program and may not be removed without the consent of the
  23.  *     University of Delaware.
  24.  *
  25.  *
  26.  *     version  -1    David H. Crocker    March   1979
  27.  *     version   0    David H. Crocker    April   1980
  28.  *     version  v7    David H. Crocker    May     1981
  29.  *     version   1    David H. Crocker    October 1981
  30.  *
  31.  */
  32. #include "util.h"
  33. #include "mmdf.h"
  34. #include "ch.h"
  35. #include <pwd.h>
  36. #include "cnvtdate.h"
  37. #include "ap.h"
  38. #include "dm.h"
  39. #include "msg.h"
  40. #include "hdr.h"
  41. #include "ns.h"
  42.  
  43. /*  enforce management policies on message submission   */
  44.  
  45. /*  currently, we are only concerned about author authenticity and
  46.  *  format conformance.
  47.  *
  48.  *  Jun 82  D. Crocker      add adruid, for proc/file address protection
  49.  *  Jul 82  D. Crocker      add mgt_hops, checking for looping
  50.  *                          fix use of From, over Sender, for return addr
  51.  *                          add use of Reply-to, over From, fro return addr
  52.  *  Jul 82  A. Chang (suny) mgt_author require mbox==username
  53.  */
  54.  
  55. extern Chan **ch_tbsrch;           /* complete list of channels          */
  56. extern FILE *mq_mffp;
  57. extern char *ch_dflnam;            /* default channel name             */
  58.  
  59. extern struct passwd *getpwmid ();
  60. extern struct ll_struct *logptr;
  61. extern char *index ();
  62. extern char *multcat();
  63. extern Chan *ch_nm2struct();
  64. extern Domain *dm_v2route();
  65.  
  66. LOCFUN mgt_forward(), mgt_author(), mgt_messageid(), mst_srcinfo(),
  67.     mgt_via(), mgt_rcv();
  68.  
  69. extern long tx_msize;             /* char count of message text         */
  70.  
  71. extern short pro_vfadr;
  72.  
  73. extern int    effecid,
  74.         userid,
  75.         adruid,
  76.         maxhops,
  77.         mgt_addid,
  78.         dlv_flgs;
  79.  
  80. extern char *adr_orgspec;         /* original mailbox specification     */
  81. extern char *adr_fulldmn;      /* used for the delay channel     */
  82. extern char *blt();
  83. extern char *compress ();
  84.  
  85. extern    short    lnk_nadrs;    /* number of addressees for message   */
  86.  
  87. extern char *mq_munique,          /* name of the message                */
  88.         *prm_dupval (),
  89.         *strdup (),
  90.         *locfullmachine,
  91.         *locmachine,
  92.         *locfullname,
  93.         *locname,
  94.         *locdomain,
  95.         nlnultrm[],           /* termination break-set for ut_stdin */
  96.         *mailid,
  97.         *username;
  98.  
  99. char *mgt_txsrc = NULL;           /* some text for Source-Info:         */
  100. char *mgt_return = NULL;          /* return address                     */
  101. int    mgt_gotid;          /* have seen a message-id: field    */
  102. int     mgt_inalias;              /* is address in alias file           */
  103.  
  104. short   mgt_s2return = FALSE;     /* get return from Sender             */
  105.  
  106. char    mgt_dlname[] = "delay";      /* name of the delay channel        */
  107. int     mgt_nodelay = FALSE;      /* don't use delay channel if true    */
  108. int     mgt_amdelay = FALSE;      /* I really am the delay channel      */
  109.  
  110. LOCVAR struct ch_hstchan
  111. {
  112.     Chan *mgt_achan;              /* channel relay coming in on         */
  113.     char *mgt_ahost;              /* official host name on channel      */
  114. }   mgt_vchan;                    /* caller is coming in from chan x    */
  115.  
  116. LOCVAR Chan *mgt_chdfl;
  117. LOCVAR short   mgt_trust,        /* pass on author authentication?     */
  118. #define NRMFROM 0                 /*    normal checking                 */
  119. #define FLGFROM 1                 /*    flag as unauthenticated         */
  120. #define OKFROM  2                 /*    ignore validity                 */
  121.     mgt_rt2sndr,              /* if a return mail message is needed */
  122.                   /*    send it to submittor            */
  123.     mgt_rtgot,                /* got the return address             */
  124.     mgt_remail,               /* this was remailed                  */
  125.     mgt_okauthor,             /* an author field was acceptable     */
  126.     mgt_fmcnt,                /* number of from fields seen         */
  127.     mgt_sncnt,                /* number of sender fields seen       */
  128.  
  129.     mgt_doloc,                /* send "immediate" channels, if any  */
  130.     mgt_donet,                /* send "network" channels, if any    */
  131.     mgt_loops,                /* number of times through this site  */
  132.     mgt_hops;                 /* number of hops message has gone    */
  133. /* */
  134.  
  135. mgt_init ()
  136. {
  137. #ifdef DEBUG
  138.     ll_log (logptr, LLOGBTR, "mgt_init ()");
  139. #endif
  140.     if (ch_dflnam[0] != '\0')
  141.     if ((mgt_chdfl = ch_nm2struct (ch_dflnam)) == (Chan *) NOTOK)
  142.         err_abrt (RP_PARM, "'%s' invalid default channel name", ch_dflnam);
  143.  
  144.     return (RP_OK);
  145. }
  146.  
  147. mgt_minit ()                      /* initialize for new message         */
  148. {
  149.     register Chan **chanptr;
  150.  
  151. #ifdef DEBUG
  152.     ll_log (logptr, LLOGBTR, "mgt_minit ()");
  153. #endif
  154.  
  155.     if (mgt_txsrc)                /* if previously set                  */
  156.     free (mgt_txsrc);
  157. /**/ll_log(logptr, LLOGFTR, "mgt_txsrc freed");
  158.     if (mgt_vchan.mgt_ahost)      /*  "     "       "                   */
  159.     free (mgt_vchan.mgt_ahost);
  160. /**/ll_log(logptr, LLOGFTR, "mgt_vchan.mgt_ahost freed");
  161.     if (mgt_return)
  162.     free (mgt_return);
  163. /**/ll_log(logptr, LLOGFTR, "mgt_return freed");
  164.  
  165.     mgt_vchan.mgt_achan =  (Chan *) 0;
  166. /**/ll_log(logptr, LLOGFTR, "mgt_vchan.mgt_achan reset");
  167.     mgt_vchan.mgt_ahost =  (char *) 0;
  168. /**/ll_log(logptr, LLOGFTR, "mgt_vchan.mgt_ahost reset");
  169.     mgt_txsrc = (char *) 0;
  170. /**/ll_log(logptr, LLOGFTR, "mgt_txsrc reset");
  171.     mgt_return = (char *) 0;
  172. /**/ll_log(logptr, LLOGFTR, "mgt_return reset");
  173.  
  174.     mgt_trust = NRMFROM;
  175.  
  176.     mgt_remail =
  177.     mgt_rt2sndr =
  178.     mgt_s2return =
  179.     mgt_rtgot =
  180.     mgt_okauthor = FALSE;
  181.     mgt_fmcnt =
  182.     mgt_sncnt =
  183.     mgt_gotid =
  184.     mgt_loops =
  185.     mgt_hops = 0;
  186.  
  187.     for (chanptr = ch_tbsrch; *chanptr != 0; chanptr++)
  188.     (*chanptr) -> ch_access &= ~DLVRDID;
  189.                   /* reset "used" bit, for channel      */
  190. /**/ll_log(logptr, LLOGBTR, "leaving mgt_init()");
  191.     return (RP_OK);
  192. }
  193. /* */
  194.  
  195. char *
  196.     mgt_parm (theparm)
  197. register char *theparm;
  198. {
  199.     char *ptr;
  200.  
  201. #ifdef DEBUG
  202.     ll_log (logptr, LLOGBTR, "mgt_parm (%s)",theparm);
  203. #endif
  204.     switch (*theparm)
  205.     {
  206.     case '-':
  207.         break;
  208.  
  209.     case 'h':                 /* hostname for relay source          */
  210.         theparm = prm_dupval (++theparm, &mgt_vchan.mgt_ahost);
  211.         break;                /* just save the info, for now        */
  212.  
  213.     case 'i':                 /* relaying Indirectly                */
  214.         theparm = prm_dupval (++theparm, &ptr);
  215.         mgt_forward (ptr);
  216.         free (ptr);
  217.         break;                /* certify legality of relaying       */
  218.  
  219.     case 'l':                 /* send local now, if have any        */
  220.         mgt_doloc = TRUE;
  221.         break;
  222.  
  223.     case 'n':                 /* send net now, if have any          */
  224.         mgt_donet = TRUE;
  225.         break;
  226.  
  227.     case 'r':                 /* get RETURN from login info         */
  228.         mgt_rt2sndr = TRUE;   /*   and not explicit specification   */
  229.         break;
  230.  
  231.     case 's':                 /* get RETURN from Sender info        */
  232.         mgt_s2return = TRUE;
  233.         break;
  234.  
  235.     case 't':                 /* TRUST me; don't authenticate       */
  236.         mgt_trust = OKFROM;
  237.         break;
  238.  
  239.     case 'u':                 /* (close to 't'); no authentication  */
  240.         mgt_trust = FLGFROM;
  241.         break;
  242.  
  243.     case 'd':                 /* don't use delay channel            */
  244.         mgt_nodelay = TRUE;
  245.         break;
  246.  
  247.     case 'j':                 /* I really am the delay channel      */
  248.         mgt_amdelay = TRUE;
  249.         mgt_nodelay = TRUE;
  250.         break;
  251.  
  252.     case 'k':
  253.         theparm = prm_dupval (++theparm, &ptr);
  254. #ifdef NAMESERVER
  255.         ns_settimeo(atoi(ptr));
  256. #endif
  257.         free(ptr);
  258.         break;
  259.  
  260.     default:
  261.         return ((char *) NOTOK);    /* not a management parameter   */
  262.     }
  263.  
  264.     return (theparm);
  265. }
  266. /* */
  267.  
  268. mgt_pend ()                       /* end of parameters                  */
  269. {
  270.     AP_ptr rtntree;
  271.     AP_ptr local, domain, route;
  272.     char rtnbuf[ADDRSIZE];
  273.     register short len;
  274.  
  275. #ifdef DEBUG
  276.     ll_log (logptr, LLOGBTR, "mgt_pend ()");
  277. #endif
  278.  
  279.     mgt_source();
  280.  
  281.     if (mgt_rt2sndr)              /* Use sender for return address      */
  282.     {
  283.     mgt_return = multcat(mailid, "@", locfullname, (char *)0);
  284.     mgt_rtgot = TRUE;
  285.     }
  286.     else {                         /* submittor specifying return        */
  287.     if (!mgt_s2return)         /* take msg directly                  */
  288.     {
  289.         register char *cp;
  290.  
  291.         if ((len = ut_stdin (rtnbuf, LINESIZE, nlnultrm, NOTOK)) <= 0)
  292.         err_abrt (RP_LIO, "error copying return address");
  293.  
  294.         /* Suck up leading white space */
  295.         for (cp = rtnbuf; isspace(*cp); cp++);
  296.  
  297.         if (*cp == '\n')
  298.         *cp = '\0';
  299.         if (*cp == '\0')
  300.         /*   Special Case:  Null return address --> Quiet flag */
  301.         dlv_flgs |= ADR_NORET;
  302.         else if (len > (sizeof(rtnbuf) - 1))
  303.         err_msg (RP_LIO, "return address too long");
  304.         else if ((rtntree = ap_s2tree (cp)) == (AP_ptr) NOTOK)
  305.         err_msg (RP_PARM, "Problem with return address '%s'", rtnbuf);
  306.         else {
  307.         rtntree = ap_normalize (mgt_vchan.mgt_ahost, (char *) 0,
  308.                             rtntree, (Chan *)0);
  309.         if(rtntree == (AP_ptr)MAYBE)
  310.             err_msg (RP_NS, "Nameserver timeout for '%s'", rtnbuf);
  311.         ap_t2parts(rtntree, (AP_ptr *)0, (AP_ptr *)0, &local,
  312.                             &domain, &route);
  313.         mgt_return = ap_p2s( (AP_ptr) 0, (AP_ptr) 0, local, domain,
  314.                                 route);
  315.         ap_sqdelete (rtntree, (AP_ptr) 0);
  316.         ap_free (rtntree);   /* delete full string                 */
  317.         if(mgt_return == (char *)MAYBE)
  318.             err_msg (RP_NS, "Nameserver timeout for '%s'", rtnbuf);
  319.         mgt_rtgot = TRUE;
  320.         }
  321.     }
  322.     }
  323.  
  324.     if (mgt_vchan.mgt_achan == (Chan *) 0)
  325.     auth_init (username, (mgt_trust == NRMFROM));
  326.     else
  327.     auth_init ((mgt_return ? mgt_return : ""), (mgt_trust == NRMFROM));
  328.  
  329.     if(pro_vfadr)
  330.     pro_reply (RP_OK, "Sender is '%s'", mgt_return ? mgt_return : "");
  331. #ifdef DEBUG
  332.     ll_log (logptr, LLOGFTR, "mgt_return: '%s'", mgt_return ? mgt_return : "");
  333. #endif
  334. }
  335. /* */
  336.  
  337. #define AOKNUM 50
  338.  
  339. mgt_aok (thechan, hostr, mbox, parm) /* is address acceptable for sending  */
  340. Chan *thechan;                    /* internal chan name/code            */
  341. char *hostr,                      /* official name of host              */
  342.      *mbox,                       /* name of mailbox                    */
  343.      *parm;                       /* local-mailbox parameter            */
  344. {
  345.     register struct passwd *pwdptr;
  346.  
  347. #ifdef DEBUG
  348.     ll_log (logptr, LLOGBTR, "mgt_aok (%s, %s, %s, %s)", thechan->ch_name,
  349.         hostr, mbox, parm);
  350. #endif
  351.  
  352. /* if address maps to file or process, login uid must meet the following
  353.  * restrictions.
  354.  */
  355.  
  356.     if (thechan == mgt_chdfl)    /* "local" address              */
  357.     {
  358.     switch (parm[0]) 
  359.     {
  360.     case '/':           /* file destination                 */
  361.     case '|':           /* process destination              */
  362.         if ((pwdptr = getpwmid (mbox)) == (struct passwd *) NULL)
  363.         {
  364.         ll_err (logptr, LLOGTMP,
  365.                 "user '%s' not in passwd file", mbox);
  366.         return (FALSE); /* can't deliver to non-persons */
  367.         }
  368. #ifdef DEBUG
  369.         ll_log (logptr, LLOGFTR, "caller uid (%d), parm uid (%d)",
  370.             adruid, pwdptr -> pw_uid);
  371. #endif
  372.         if (!mgt_inalias)
  373.                 /* only accept from alias file    */
  374.                 /* unless 'insecure'              */
  375. #ifdef INSECURE
  376.         /*
  377.          *  Only do this code if you are willing to take the
  378.          *  implied security risk.  I do not trust this (DPK).
  379.          *
  380.          *  Must be ((your own login id or privelidged user)
  381.          *  and locally originated) (SEK - note de Morgan!!)
  382.          */
  383.         if (((adruid != pwdptr -> pw_uid) && (adruid != 0)) ||
  384.             (mgt_vchan.mgt_achan != (Chan *) 0))
  385. #endif
  386.             return (FALSE);
  387.     }
  388.     }
  389.  
  390. /* is this address subject to immediate transmission, if requested?
  391.  * the check, here, is more for convenience than for enforcement,
  392.  * since Deliver will have to redo the check.  this is just to
  393.  * avoid calling Deliver unnecessarily.
  394.  */
  395.  
  396.     if (! (thechan -> ch_access & (DLVRPSV | DLVRBAK)))
  397.     {                             /* an active, foreground-able chan?   */
  398.     if ((thechan -> ch_access & DLVRIMM) || mgt_donet)
  399.         thechan -> ch_access |= DLVRDID;  /* channel may be run now */
  400.     }
  401.  
  402.     if (mgt_vchan.mgt_achan == (Chan *) 0)
  403.     return (auth_user (mgt_chdfl -> ch_lname, hostr,
  404.                         mgt_chdfl, thechan));
  405.     else
  406.     return (auth_user (mgt_vchan.mgt_ahost, hostr,
  407.                     mgt_vchan.mgt_achan, thechan));
  408.                 /* apply control policies relating to */
  409.                 /* channel access                     */
  410. }
  411.  
  412. mgt_aend ()
  413. {                                 /* record some stats                  */
  414.     char sizstr[11];
  415.  
  416. #ifdef DEBUG
  417.     ll_log (logptr, LLOGBTR, "mgt_aend ()");
  418. #endif
  419.  
  420.     if (lnk_nadrs <= 0)
  421.     err_msg (RP_NDEL, "No valid addresses");
  422.  
  423.     sprintf (sizstr, "%ld", tx_msize);
  424.                   /* ll_log can't handle longs          */
  425.     if (mgt_vchan.mgt_achan == 0) /* local submission                   */
  426.     ll_log (logptr, LLOGBST, "lin %s (%d, %s) %s %s",
  427.         mq_munique, lnk_nadrs, sizstr, mgt_chdfl->ch_queue, mailid);
  428.     else
  429.     {                             /* claiming to be a relay             */
  430.     if (!mgt_s2return &&       /* hack past possible bad parsing     */
  431.         mgt_return != NULL && !isnull (*mgt_return) &&
  432.         !index(mgt_return, '@'))/* add host if necessary if not given */
  433.     {
  434.         char *cp;
  435.  
  436.         cp = multcat(mgt_return, "@", mgt_vchan.mgt_ahost, (char *)0);
  437.         free (mgt_return);
  438.         mgt_return = cp;
  439.     }
  440.  
  441.     ll_log (logptr, LLOGBST, "rin %s (%d, %s) %s %s %s",
  442.         mq_munique, lnk_nadrs, sizstr,
  443.         mgt_vchan.mgt_achan -> ch_queue, mgt_vchan.mgt_ahost,
  444.         mgt_return);
  445.  
  446.     }
  447.     auth_end ();
  448.     return (RP_OK);
  449. }
  450.  
  451. /* */
  452.  
  453. mgt_source ()                     /* ready to process headers */
  454. {
  455.     char linebuf[LINESIZE];
  456.  
  457.     if (mgt_vchan.mgt_achan != 0)
  458.     {
  459.     if (mgt_vchan.mgt_ahost == 0)
  460.     {                         /* no source host named               */
  461.         if (mgt_vchan.mgt_achan -> ch_host == NORELAY)
  462.         {                     /* not a single relay for the chan    */
  463.         if(mgt_amdelay && PRIV_USER(userid))
  464.             mgt_vchan.mgt_ahost = strdup(adr_fulldmn);
  465.         else    /* cheat here should do an err_abrt with RP_NS ?? */
  466.             if (tb_k2val (mgt_vchan.mgt_achan -> ch_table, TRUE,
  467.                  username, linebuf) != OK)
  468.                   /* derive it from login name          */
  469.             err_abrt(RP_PARM,"'%s' not an authorized %s (%s) relay",
  470.                 username,
  471.                 mgt_vchan.mgt_achan -> ch_table -> tb_name,
  472.                 mgt_vchan.mgt_achan -> ch_name);
  473.         else 
  474.             mgt_vchan.mgt_ahost = strdup (linebuf);
  475.         }
  476.         else            /* take name from ch_tai structure    */
  477.         mgt_vchan.mgt_ahost = strdup (mgt_vchan.mgt_achan -> ch_host);
  478.     }
  479.     else if (!PRIV_USER(userid))    /* trying to name host explicitly     */
  480.         err_abrt (RP_PARM,
  481.                 "only root, mmdf and daemons may name source host");
  482.     }
  483. }
  484.  
  485. mgt_hinit ()                     /* ready to process headers */
  486. {
  487.     if (mgt_vchan.mgt_achan != 0)
  488.     mgt_via();
  489. }
  490.  
  491. /*
  492.  *  Authentication of "Resent" messages is quit a bit looser than
  493.  *  authentication of original messages.  This is due to the fact
  494.  *  that a message might be resent several times, each time gaining
  495.  *  a new set of Resent- headers.  The last set wins.   (DPK, 17 July 84)
  496.  */
  497. mgt_hdr (name, contents, hdr_state)
  498.     char *name,
  499.     contents[];
  500.     int hdr_state;
  501. {
  502.     int ind,
  503.     argc;
  504.     char *argv[25];
  505.  
  506. #ifdef DEBUG
  507.     ll_log (logptr, LLOGBTR, "mgt_hdr ()");
  508. #endif
  509.  
  510.     if (prefix ("Resent-", name))
  511.     {
  512.     name += 7;
  513.     goto doremail;
  514.     }
  515.     if (prefix ("Remailed-", name))
  516.     {
  517.     name += 9;
  518.     goto doremail;
  519.     }
  520.     if (prefix ("Redistributed-", name))
  521.     {
  522.     name += 14;
  523. doremail:
  524.     if (!mgt_remail)
  525.     {
  526.         mgt_sncnt = mgt_fmcnt = 0;
  527.         mgt_remail = TRUE;
  528.     }
  529.     if (lexequ ("Sender", name))
  530.         goto dosn;
  531.     if (lexequ ("From", name))
  532.         goto dofm;
  533.     if (lexequ ("Reply-to", name))
  534.         goto dorplyto;
  535.     }
  536.  
  537.     if (lexequ ("Sender", name))
  538.     {
  539.     if (!mgt_remail)
  540.     {
  541. dosn:
  542.         mgt_sncnt++;
  543.         if (mgt_trust == NRMFROM)
  544.         mgt_okauthor = mgt_author (contents);
  545.  
  546.         if (mgt_s2return) {   /* use Sender field for return addr   */
  547.         compress (contents, contents);
  548.         mgt_return = strdup(contents);
  549.         mgt_rtgot = TRUE;
  550.         }
  551.  
  552.     }
  553.     }
  554.     else
  555.     if (lexequ ("From", name))
  556.     {
  557.     if (!mgt_remail)
  558.     {
  559. dofm:
  560.         mgt_fmcnt++;
  561.  
  562.         /* Sender overrides; contents of From     */
  563.         if (mgt_trust == NRMFROM)
  564.         if (mgt_remail || mgt_sncnt == 0)
  565.             mgt_okauthor = mgt_author (contents);
  566.  
  567.         if (mgt_s2return && !mgt_rt2sndr && !mgt_rtgot) {
  568.         compress (contents, contents);
  569.         mgt_return = strdup(contents);
  570.         }                     /* get return from From, if no Sender */
  571.     }
  572.     }
  573.     else
  574.     if (lexequ ("Reply-To", name))
  575.     {
  576.     if (!mgt_remail)
  577.     {
  578. dorplyto:
  579.         if (!mgt_s2return && !mgt_rt2sndr && !mgt_rtgot)
  580.         {
  581.         compress (contents, contents);
  582.         mgt_return = strdup(contents);;
  583.         mgt_rtgot = TRUE;  /* From doesn't set it, but Reply-to does */
  584.         }
  585.     }
  586.     }
  587.     else
  588.     if (lexequ ("Via", name))   /* old rfc733 pseudo-standard   */
  589.     {
  590.     /*
  591.      * Only inc mgt_hops if this is the first line of the trace
  592.      */
  593.     if (hdr_state != HDR_MOR && ++mgt_hops > maxhops)
  594.     {
  595.         if (mgt_vchan.mgt_achan != (Chan *) 0)
  596.         ll_log (logptr, LLOGTMP, "reject on hop count from: %s %s %s",
  597.             mgt_vchan.mgt_achan -> ch_name, mgt_vchan.mgt_ahost,
  598.             mgt_return);
  599.         else
  600.         ll_log (logptr, LLOGTMP, "reject last hop:  %s", contents);
  601.         err_msg (RP_NDEL, "Message has travelled too many hops");
  602.     }
  603.  
  604.     argc = str2arg (contents, 25, argv, (char *) 0);
  605. #ifdef DEBUG
  606.     ll_log (logptr, LLOGFTR, "from '%s'; contents '%s'",
  607.         mgt_vchan.mgt_ahost, argv[0]);
  608. #endif
  609.  
  610.     if (mgt_vchan.mgt_achan != (Chan *) 0 &&
  611.         lexequ (mgt_vchan.mgt_ahost, argv[0]) &&
  612.         ++mgt_loops > 2)
  613.     {
  614.         ll_log (logptr, LLOGTMP, "reject on loop from:  %s %s %s",
  615.             mgt_vchan.mgt_achan -> ch_name, mgt_vchan.mgt_ahost,
  616.             mgt_return);
  617.         err_msg (RP_NDEL,
  618.             "Message has been through this site (%s) already",
  619.             locfullname);
  620.     }
  621.     }
  622.     if (lexequ ("Received", name)) /* RFC822 standard   */
  623.     {
  624.     /*
  625.      * Only inc mgt_hops if this is the first line of the trace
  626.      */
  627.     if (hdr_state != HDR_MOR && ++mgt_hops > maxhops)
  628.     {
  629.         if (mgt_vchan.mgt_achan != (Chan *) 0)
  630.         ll_log (logptr, LLOGTMP, "reject on hop count from: %s %s %s",
  631.             mgt_vchan.mgt_achan -> ch_name, mgt_vchan.mgt_ahost,
  632.             mgt_return);
  633.         else
  634.         ll_log (logptr, LLOGTMP, "reject last hop:  %s", contents);
  635.         err_msg (RP_NDEL, "Message has travelled too many hops");
  636.     }
  637.  
  638.     argc = str2arg (contents, 25, argv, (char *) 0);
  639.     for (ind = 0; ind < argc - 2; ind += 2)
  640.         if (lexequ (argv[ind], "by"))
  641.         break;          /* found the field naming the receiver */
  642.  
  643.     if (ind++ < argc)
  644.     {                       /* compare our name with 'received' name */
  645. #ifdef DEBUG
  646.         ll_log (logptr, LLOGFTR, "from '%s'; contents '%s'",
  647.             mgt_vchan.mgt_ahost, argv[ind]);
  648. #endif
  649.  
  650.         if (mgt_vchan.mgt_achan != (Chan *) 0 &&
  651.             lexequ (mgt_vchan.mgt_achan -> ch_lname, argv[ind]) &&
  652.             ++mgt_loops > 2)
  653.         {
  654.         ll_log (logptr, LLOGTMP, "reject on loop from:  %s %s %s",
  655.             mgt_vchan.mgt_achan -> ch_name,
  656.             mgt_vchan.mgt_achan -> ch_lname,
  657.             mgt_return);
  658.         err_msg (RP_NDEL,
  659.             "Message has been through this site (%s) too many times",
  660.             mgt_vchan.mgt_achan -> ch_lname);
  661.         }
  662.     }
  663.     }
  664.     if (lexequ ("Message-Id", name))
  665.     {
  666.     mgt_gotid++;
  667.     }
  668.     return (RP_OK);     /* no management policies, for this one         */
  669. }
  670. /* */
  671.  
  672. mgt_hend ()
  673. {
  674. #ifdef DEBUG
  675.     ll_log (logptr, LLOGBTR, "mgt_hend ()");
  676.     ll_log (logptr, LLOGFTR, "uid=%d,effec=%d, fmcnt=%d,okauth=%d",
  677.                 userid, effecid, mgt_fmcnt, mgt_okauthor);
  678. #endif
  679.  
  680.     if (!mgt_remail) {
  681.     if (mgt_sncnt == 0 && mgt_fmcnt > 1 && mgt_trust == NRMFROM)
  682.         err_msg (RP_PARM, "Too many From: lines");
  683.     if (mgt_sncnt > 1 && mgt_trust == NRMFROM)
  684.         err_msg (RP_PARM, "Too many Sender: lines");
  685.     }
  686.  
  687.     if (mgt_trust == OKFROM)     /* pure trust requested               */
  688.     {
  689.     if (!PRIV_USER(userid) && mgt_vchan.mgt_achan == 0)
  690.                   /* trust root, mmdf, and relays      */
  691.         mgt_trust = FLGFROM; /* otherwise note, but honor          */
  692.     }
  693.  
  694.     if (mgt_addid && !mgt_gotid)
  695.     mgt_messageid ();
  696.  
  697.     if (mgt_trust == FLGFROM || mgt_txsrc != 0)
  698.     mgt_srcinfo ();           /* this must follow the above "if"    */
  699.  
  700.     if (mgt_trust != NRMFROM)
  701.     return (RP_OK);           /* not checking for these errors      */
  702.  
  703.     if (!mgt_okauthor)
  704.     err_msg (RP_PARM, "No valid author specification present");
  705.  
  706.     return (RP_OK);
  707. }
  708. /* */
  709.  
  710. LOCFUN
  711.     mgt_forward (channame)    /* certify source as relay site       */
  712.     char channame[];
  713. {                                 /* map username to "host" on chan     */
  714.     register Chan *thechan;       /* chan claiming to come from         */
  715.  
  716. #ifdef DEBUG
  717.     ll_log (logptr, LLOGBTR, "mgt_forward (%s)", channame);
  718. #endif
  719.  
  720.     if ((thechan = ch_nm2struct (channame)) == (Chan *) NOTOK)
  721.     err_abrt (RP_PARM, "Channel '%s' does not exist", channame);
  722.  
  723.     mgt_vchan.mgt_achan = thechan;
  724. }
  725.  
  726. /* */
  727.  
  728. LOCFUN
  729.     mgt_author (contents)     /* does component contain only the    */
  730.     char contents[];
  731. {                                 /* address of the actual sender?      */
  732.     struct passwd *pwdptr;
  733.     AP_ptr  locptr,               /* local & domain parts               */
  734.         dmnptr,
  735.         aptr;
  736.     int retval = TRUE;
  737.  
  738. #ifdef DEBUG
  739.     ll_log (logptr, LLOGBTR, "mgt_author(%s)", contents);
  740. #endif
  741.  
  742.     /* do not normalize.  evaluate as is */
  743.     if ((aptr = ap_s2tree (contents)) == (AP_ptr) NOTOK
  744.     || ap_t2parts (aptr, (AP_ptr *) 0, (AP_ptr *) 0,
  745.         &locptr, &dmnptr, (AP_ptr *) 0) != (AP_ptr) OK) {
  746.     retval = FALSE;         /* only allowed one address in the field */
  747.     goto cleanup;
  748.     }
  749.  
  750. #ifdef DEBUG
  751.     ll_log (logptr, LLOGBTR, "checking: %s, uid %d, %s", locptr -> ap_obvalue,
  752.         userid, dmnptr ? dmnptr -> ap_obvalue : "No Domain");
  753. #endif
  754.     if ((pwdptr = getpwmid (locptr -> ap_obvalue)) == (struct passwd *)NULL
  755.       || pwdptr -> pw_uid != userid)
  756.       retval = FALSE;
  757.     /*
  758.      *  If a domain was specified, make sure it was the proper one.
  759.      */
  760.     if (retval == TRUE && dmnptr != (AP_ptr) 0) {
  761.     Dmn_route dmnroute;
  762.     char tmpbuf[LINESIZE];
  763.  
  764. #ifdef DEBUG
  765.     ll_log (logptr, LLOGBTR, "mgt_author, v2route(%s)",dmnptr->ap_obvalue);
  766. #endif
  767.     switch ((int)dm_v2route (dmnptr -> ap_obvalue, tmpbuf, &dmnroute)) {
  768.     case MAYBE:
  769.         retval = FALSE;
  770.         break;
  771.     case OK:                /* Can't happen ??  -DPK- */
  772.         retval = TRUE;
  773.         break;
  774.     default:
  775. #ifdef DEBUG
  776.         ll_log (logptr, LLOGBTR, "mgt_author, h2chan(%s)", dmnroute.dm_argv[0]);
  777. #endif
  778.         if (ch_h2chan (dmnroute.dm_argv[0], 1) != OK)
  779.         retval = FALSE;
  780.         break;
  781.     case NOTOK:
  782. #ifdef DEBUG
  783.         ll_log (logptr, LLOGBTR, "mgt_author, h2chan(%s)", dmnptr->ap_obvalue);
  784. #endif
  785.         if (ch_h2chan (dmnptr -> ap_obvalue, 1) != OK)
  786.         retval = FALSE;
  787.         break;
  788.     }
  789.     }
  790.  
  791. cleanup:
  792.     if (aptr && aptr != (AP_ptr)NOTOK) {
  793.     ap_sqdelete (aptr, (AP_ptr) 0);
  794.     ap_free (aptr);
  795.     }
  796.  
  797. #ifdef DEBUG
  798.     ll_log (logptr, LLOGBTR, "mgt_author, returns %d", retval);
  799. #endif
  800.     return (retval);
  801. }
  802. /* */
  803.  
  804. LOCFUN
  805.     mgt_messageid ()            /* add Message-ID: */
  806. {
  807.     char buf[32];
  808. #ifdef DEBUG
  809.     ll_log (logptr, LLOGBTR, "mgt_messageid ()");
  810. #endif
  811.  
  812.     if (isstr(locfullmachine))
  813.     fprintf(mq_mffp, "Message-ID:  <%s.%s@%s>\n",
  814.         cnvtdate(TIMCOM, buf), &mq_munique[4], locfullmachine);
  815.     else
  816.     fprintf(mq_mffp, "Message-ID:  <%s.%s@%s>\n",
  817.         cnvtdate(TIMCOM, buf), &mq_munique[4], locfullname);
  818. }
  819.  
  820. LOCFUN
  821.     mgt_srcinfo ()            /* add Source-Info field, maybe       */
  822. {
  823. #ifdef DEBUG
  824.     ll_log (logptr, LLOGBTR, "mgt_srcinfo ()");
  825. #endif
  826.  
  827.     fputs ("Source-Info:  ", mq_mffp);
  828.     if (mgt_trust == FLGFROM)
  829.     {                             /* note the lack of authentication    */
  830.     fputs ("From (or Sender) name not authenticated.\n", mq_mffp);
  831.     if (mgt_txsrc != 0)       /* indent second line of text         */
  832.         fputs ("     ", mq_mffp);
  833.     }
  834.     if (mgt_txsrc != 0)           /* user wants to say something        */
  835.     {
  836.     fputs (mgt_txsrc, mq_mffp);
  837.     if (mgt_txsrc[strlen (mgt_txsrc) - 1] != '\n')
  838.         putc ('\n', mq_mffp);
  839.     }
  840. }
  841.  
  842. /* */
  843.  
  844. LOCFUN
  845.     mgt_via ()                /* note fact of relaying              */
  846. {
  847.     extern char *cnvtdate ();
  848.     char    thedate[LINESIZE];
  849.     int len;
  850. #ifdef VIATRACE
  851.     char    *p;
  852. #endif
  853.  
  854. #ifdef DEBUG
  855.     ll_log (logptr, LLOGBTR, "mgt_via ()");
  856. #endif
  857.  
  858. /* Received: by hostname.net; date                                      */
  859. /*  e.g.:                                                               */
  860. /* Received: by Rand-Unix.ArpaNet; 21 Jan 79 12:40 EDT                  */
  861.  
  862.     if (mgt_vchan.mgt_achan -> ch_login != NOLOGIN)
  863.                   /* single login authorized to relay   */
  864.     if (!PRIV_USER(userid))      /* caller is not special id           */
  865.         if (!lexequ (mgt_vchan.mgt_achan -> ch_login, username))
  866.                   /* caller not the authorized id       */
  867.         err_abrt (RP_USER, "%s not authorized to submit mail as %s",
  868.                 username, mgt_vchan.mgt_achan -> ch_name);
  869.  
  870.     cnvtdate (TIMSHRT, thedate);  /* net name & short date/time         */
  871.  
  872. /*  if mail always goes through a relay, for this channel, then the
  873.  *  host/chan combination is a constant and source reference is not
  874.  *  useful; only the receiver will be listed.  The channel name is
  875.  *  used to specify the transfer link.
  876.  */
  877.  
  878. #ifdef VIATRACE
  879.                 /* needed for standard UK sites */
  880.                 /* note reversed domain ordering*/
  881.     len = mgt_rcv (0, "Via:");
  882.     if (mgt_vchan.mgt_achan -> ch_host == NORELAY)
  883.     p = ap_dmflip (mgt_vchan.mgt_ahost);
  884.     else
  885.     p  = ap_dmflip (mgt_vchan.mgt_achan -> ch_host);
  886.     len = mgt_rcv (len, " %s;", p);
  887.     free (p);
  888. #else /* VIATRACE */
  889.  
  890.     len = mgt_rcv (0, "Received:");
  891.  
  892.     if(mgt_amdelay != TRUE){    /* special string for Delay channel */
  893.     if (mgt_vchan.mgt_achan -> ch_host == NORELAY)
  894.         len = mgt_rcv (len, "from %s", mgt_vchan.mgt_ahost);
  895.     else
  896.         len = mgt_rcv (len, "from %s", mgt_vchan.mgt_achan -> ch_host);
  897.     }
  898.  
  899. #ifndef UCL
  900.     /* We must have a seperate "locmachine" here since the name we
  901.      * want to record is dependant on the channel.
  902.      * What confuses me is why doesn't the UCL portion have the domain
  903.      * flipped around?  And also, why don't they make it relative to
  904.      * the channel?  And another thing, why doesn't the non-UCL portion
  905.      * put the "show" information in the header?
  906.      * -- DSH
  907.      */
  908.     if (isstr (locmachine))
  909.     len = mgt_rcv (len, "by %s.%s.%s", locmachine,
  910.         mgt_vchan.mgt_achan -> ch_lname,
  911.         mgt_vchan.mgt_achan -> ch_ldomain);
  912.     else
  913.     len = mgt_rcv (len, "by %s.%s",
  914.         mgt_vchan.mgt_achan -> ch_lname,
  915.         mgt_vchan.mgt_achan -> ch_ldomain);
  916.     if (adr_orgspec != (char *) 0)
  917.     len = mgt_rcv (len, "for %s", adr_orgspec);
  918.     len = mgt_rcv (len, "id %s;", &mq_munique[4]);
  919.             /* skip the "msg." preface */
  920. #else /* UCL */
  921.     if (isstr (locmachine))
  922.     len = mgt_rcv (len, "by %s.%s.%s ", locmachine, locname, locdomain);
  923.     else
  924.     len = mgt_rcv (len, "by %s.%s ", locname, locdomain);
  925.             /* SEK use local rather than channel pref names? */
  926.             /* structure ch_show to suit tase               */
  927.     if(mgt_amdelay == TRUE)
  928.     len = mgt_rcv (len, " with Delay channel");
  929.     else
  930.     len = mgt_rcv (len, " %s", mgt_vchan.mgt_achan -> ch_show);
  931.     len = mgt_rcv (len, " id %s;", &mq_munique[4]);
  932.             /* skip the "msg." preface */
  933. #endif /* UCL */
  934.  
  935. #endif /* VIATRACE */
  936.     (void) mgt_rcv (len, "%s\n", thedate);
  937. }
  938.  
  939. /* VARARGS2 */
  940.  
  941. LOCVAR
  942. mgt_rcv (curlen, fmt, val1, val2, val3)
  943.     int curlen;
  944.     char *fmt, *val1, *val2, *val3;
  945. {
  946.     char linebuf[LINESIZE];
  947.     int len;
  948.  
  949.     sprintf (linebuf, fmt, val1, val2, val3);
  950.     len = strlen (linebuf);
  951.     if ((curlen + len) > 77)
  952.     {
  953.     fputs ("\n          ", mq_mffp);
  954.     curlen = 10;
  955.     }
  956.     else
  957.     if (curlen > 0)
  958.         putc (' ', mq_mffp);
  959.     fputs (linebuf, mq_mffp);
  960.     return (curlen + len);
  961. }
  962.  
  963. /* generate a delay channel 'host parameter' */
  964.  
  965. char    *
  966. mgt_dstgen()
  967. {
  968.     char    *multcat();
  969.     return(multcat(mgt_vchan.mgt_achan == NULL ?
  970.             mgt_dlname : mgt_vchan.mgt_achan->ch_name,
  971.             "&", mgt_vchan.mgt_ahost, (char *)0));
  972. }
  973.