home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / smail-3.1.28 / contrib / akcs / akcs.c next >
Encoding:
C/C++ Source or Header  |  1990-10-23  |  9.0 KB  |  335 lines

  1. /* @(#)contrib/akcs/akcs.c    1.2 10/24/90 05:17:09 */
  2.  
  3. /*
  4.  *    Copyright (C) 1987, 1988 Ronald S. Karr and Landon Curt Noll
  5.  *
  6.  *    Changed, modified, mangled and hacked by Karl Denninger
  7.  *    (karl@ddsw1.MCS.COM); changes copyright 1989 Karl Denninger.
  8.  *
  9.  * See the file COPYING, distributed with smail, for restriction
  10.  * and warranty information.
  11.  */
  12.  
  13. /*
  14.  * akcs.c:
  15.  *    direct mail to a transport which will deliver to local AKCS(tm)
  16.  *    mailboxes.  Match only local addresses which are login names
  17.  *    for AKCS on the local host.
  18.  *
  19.  * Specifications for the akcs directing driver:
  20.  *
  21.  *    private attribute data:
  22.  *        transport (name):  the name of the transport to use in delivering
  23.  *        mail to local users.
  24.  */
  25. #include <stdio.h>
  26. #include <pwd.h>
  27. #include "defs.h"
  28. #include "../smail.h"
  29. #include "../smailconf.h"
  30. #include "../parse.h"
  31. #include "../addr.h"
  32. #include "../log.h"
  33. #include "../direct.h"
  34. #include "../transport.h"
  35. #include "../exitcodes.h"
  36. #include "../dys.h"
  37. #include "akcs.h"
  38. #ifndef DEPEND
  39. # include "../extern.h"
  40. # include "../debug.h"
  41. # include "../error.h"
  42. #endif
  43.  
  44.  
  45. /*
  46.  * akcs_user_info - fill an addr structure with user information
  47.  *
  48.  * if the remainder field if the addr structure matches a username,
  49.  * fill in fields which pertain to the user's password file entry.
  50.  * Note that this only checks the AKCS information files.
  51.  *
  52.  */
  53. void
  54. akcs_user_info(addr)
  55.     struct addr *addr;            /* addr structure to check */
  56. {
  57.     char    tmp[512];        /* Temporary space */
  58.     char    usr[32];        /* User space */
  59.     char    basedir[132];
  60.     FILE    *fid, *fid2;
  61.  
  62.     if (addr->flags & (ADDR_NOTUSER|ADDR_ISUSER)) {
  63.     /* a previous call to akcs_user_info() already took care of this */
  64.     return;
  65.     }
  66.  
  67.     /* get the AKCS password entry if one exists */
  68.     if ((fid = fopen("/etc/akcsparams", "r")) == NULL) {
  69.     addr->flags |= ADDR_NOTUSER;    /* No parameter file, no AKCS! */
  70.     return;                /* Pass on this one... */
  71.     }
  72.     while (fgets(tmp, 132, fid) != NULL) {
  73.     if (sscanf(tmp, "Base: %[!-z]", basedir)) {
  74.         sprintf(tmp, "%s/AKCS.p.users", basedir);
  75.             if ((fid2 = fopen(tmp, "r")) == NULL) {    /* Open user file */
  76.             fclose(fid);        /* Close parameter file */
  77.             addr->flags |= ADDR_NOTUSER;    /* Not there */
  78.             return;
  79.             }
  80.         while (fgets(tmp, 512, fid2) != NULL) {
  81.             if (sscanf(tmp, "%[!-z]", usr) <= 0)
  82.                 continue;        /* There's a problem */
  83.             if (!strcmp(usr, addr->remainder)) {    /* This user? */
  84.                 addr->flags |= ADDR_ISUSER;        /* Save it if so */
  85.                 sprintf(tmp, "%s/.users/%s", basedir, addr->remainder);
  86.                 addr->home = COPY_STRING(tmp);
  87.                 fclose(fid);    /* Close parameter file */
  88.                 fclose(fid2);
  89.                 return;            /* Exit with success */
  90.             }
  91.         }
  92.         fclose(fid2);
  93.     }
  94.     }
  95.     fclose(fid);
  96.     addr->flags |= ADDR_NOTUSER;
  97.     return;
  98. }
  99.  
  100.  
  101. /*
  102.  * dtd_akcs - direct to local akcs mailboxes
  103.  */
  104. /*ARGSUSED*/
  105. struct addr *
  106. dtd_akcs(dp, in, out, new, defer, fail)
  107.     struct director *dp;        /* director entry */
  108.     struct addr *in;            /* input local-form addrs */
  109.     struct addr **out;            /* output resolved addrs */
  110.     struct addr **new;            /* output new addrs to resolve */
  111.     struct addr **defer;        /* addrs to defer to a later time */
  112.     struct addr **fail;            /* unresolvable addrs */
  113. {
  114.     register struct addr *cur;        /* temp for processing input */
  115.     struct addr *pass = NULL;        /* addrs to pass to next director */
  116.     struct addr *next;            /* next value for cur */
  117.     struct akcs_private *priv = (struct akcs_private *)dp->private;
  118.  
  119.     DEBUG(DBG_DRIVER_HI, "dtd_akcs called\n");
  120.     for (cur = in; cur; cur = next) {
  121.     next = cur->succ;
  122.  
  123.     if (priv->prefix) {
  124.         struct addr *new;
  125.         int len = strlen(priv->prefix);
  126.  
  127.         /*
  128.          * if we are testing against a prefix, strip the prefix and
  129.          * lookup the name in the passwd file.  If found, return a
  130.          * new fully resolved addr.
  131.          */
  132.         if (strncmpic(priv->prefix, cur->remainder, len) != 0) {
  133.         cur->succ = pass;
  134.         pass = cur;
  135.         continue;        /* did not start with prefix */
  136.         }
  137.         new = alloc_addr();
  138.         new->remainder = COPY_STRING(cur->remainder + len);
  139.         akcs_user_info(new);
  140.         if (new->flags&ADDR_NOTUSER) {
  141.         /* we did not match a user on the local host */
  142.         xfree(new->remainder);
  143.         xfree((char *)new);
  144.         cur->succ = pass;
  145.         pass = cur;
  146.         continue;
  147.         }
  148.         new->in_addr = COPY_STRING(new->remainder);
  149.         new->director = dp;
  150.         new->parent = cur;
  151.         cur = new;
  152.     } else {        /* The prefix didn't match, ignore it */
  153.         cur->succ = pass;
  154.         pass = cur;
  155.         continue;
  156.     }
  157.  
  158.     DEBUG2(DBG_DRIVER_LO, "director %s matched user %s\n",
  159.            dp->name, cur->remainder);
  160.     cur->director = dp;        /* matched address */
  161.  
  162.     /* attach the transport */
  163.     cur->transport = find_transport(priv->transport);
  164.     if (cur->transport == NULL) {
  165.         /*
  166.          * ERR_122 - user transport not specified
  167.          *
  168.          * DESCRIPTION
  169.          *      No transport attribute was specified for a user
  170.          *      director.  The attribute is required.
  171.          *
  172.          * ACTIONS
  173.          *      Defer the message with a configuration error.
  174.          *
  175.          * RESOLUTION
  176.          *      The director file should be edited to specify the
  177.          *      correct transport for local delivery.
  178.          */
  179.         cur->error = note_error(ERR_CONFERR|ERR_122,
  180.                   xprintf("director %s: transport not defined",
  181.                       dp->name));
  182.         cur->succ = *defer;
  183.         *defer = cur;
  184.         continue;
  185.     }
  186.     cur->next_addr = COPY_STRING(cur->remainder);
  187.     cur->succ = *out;
  188.     *out = cur;
  189.     }
  190.  
  191.     return pass;            /* return addrs for next director */
  192. }
  193.  
  194. /*
  195.  * dtv_akcs - verify a AKCS user on the local host
  196.  */
  197. /*ARGSUSED*/
  198. void
  199. dtv_akcs(dp, in, retry, okay, defer, fail)
  200.     struct director *dp;        /* director entry */
  201.     struct addr *in;            /* input local-form addrs */
  202.     struct addr **retry;        /* output list of unmatched addrs */
  203.     struct addr **okay;            /* output list of verified addrs */
  204.     struct addr **defer;        /* temporariliy unverifiable addrs */
  205.     struct addr **fail;            /* unverified addrs */
  206. {
  207.     register struct addr *cur;        /* temp for processing input */
  208.     struct addr *next;            /* next value for cur */
  209.     struct akcs_private *priv = (struct akcs_private *)dp->private;
  210.  
  211.     DEBUG(DBG_DRIVER_HI, "dtv_akcs called\n");
  212.  
  213.     /* loop over all of the input addrs */
  214.     for (cur = in; cur; cur = next) {
  215.     next = cur->succ;
  216.  
  217.     if (priv->prefix) {
  218.         int len = strlen(priv->prefix);
  219.  
  220.         /*
  221.          * if we are testing against a prefix, strip the prefix and
  222.          * see if the remaining string matches a local user
  223.          */
  224.         if (strncmpic(priv->prefix, cur->remainder, len) == 0 &&
  225.         akcs_user_valid(cur->remainder + len))
  226.         {
  227.         /* matched */
  228.         cur->succ = *okay;
  229.         *okay = cur;
  230.         continue;
  231.         }
  232.     } else {
  233.         /* fill in any user information */
  234.         akcs_user_info(cur);
  235.  
  236.         /* match only if this is a user */
  237.         if (cur->flags&ADDR_ISUSER) {
  238.         cur->succ = *okay;
  239.         *okay = cur;
  240.         continue;
  241.         }
  242.     }
  243.  
  244.     /* didn't match */
  245.     cur->succ = *retry;
  246.     *retry = cur;
  247.     }
  248. }
  249.  
  250. /*
  251.  * dtb_user - read the configuration file attributes
  252.  */
  253. char *
  254. dtb_akcs(dp, attrs)
  255.     struct director *dp;        /* director entry being defined */
  256.     struct attribute *attrs;        /* list of per-driver attributes */
  257. {
  258.     char *error;
  259.     static struct attr_table akcs_attributes[] = {
  260.     { "transport", t_string, NULL, NULL, OFFSET(akcs_private, transport) },
  261.     { "prefix", t_string, NULL, NULL, OFFSET(akcs_private, prefix) },
  262.     };
  263.     static struct attr_table *end_akcs_attributes = ENDTABLE(akcs_attributes);
  264.     static struct akcs_private akcs_template = {
  265.     "akcs",
  266.     NULL,
  267.     };
  268.     struct akcs_private *priv;        /* new akcs_private structure */
  269.  
  270.     /* copy the template private data */
  271.     priv = (struct akcs_private *)xmalloc(sizeof(*priv));
  272.     (void) memcpy((char *)priv, (char *)&akcs_template, sizeof(*priv));
  273.  
  274.     dp->private = (char *)priv;
  275.     /* fill in the attributes of the private data */
  276.     error = fill_attributes((char *)priv,
  277.                 attrs,
  278.                 &dp->flags,
  279.                 akcs_attributes,
  280.                 end_akcs_attributes);
  281.  
  282.     if (error) {
  283.     return error;
  284.     } else {
  285.     if (priv->transport == NULL) {
  286.         return "transport attribute required";
  287.     }
  288.     if (find_transport(priv->transport) == NULL) {
  289.         return xprintf("unknown transport: %s", priv->transport);
  290.     }
  291.     return NULL;
  292.     }
  293. }
  294.  
  295. /*
  296.  * akcs_user_valid - is the address given valid?
  297.  *
  298.  * if the passed field matches a username, return non-zero.
  299.  * 
  300.  */
  301. int
  302. akcs_user_valid(addr)
  303.     char    *addr;            /* addr to check */
  304. {
  305.     char    tmp[512];        /* Temporary space */
  306.     char    usr[32];        /* User space */
  307.     FILE    *fid, *fid2;
  308.     char    basedir[132];
  309.  
  310.     /* get the AKCS password entry if one exists */
  311.     if ((fid = fopen("/etc/akcsparams", "r")) == NULL) {
  312.     return(0);                /* Pass on this one... */
  313.     }
  314.     while (fgets(tmp, 132, fid) != NULL) {
  315.     if (sscanf(tmp, "Base: %[!-z]", basedir)) {
  316.         sprintf(tmp, "%s/AKCS.p.users", basedir);
  317.             if ((fid2 = fopen(tmp, "r")) == NULL) {    /* Open user file */
  318.             fclose(fid);        /* Close parameter file */
  319.             return(0);
  320.             }
  321.         while (fgets(tmp, 512, fid2) != NULL) {
  322.             if (!strcmp(usr, addr)) {
  323.                 fclose(fid);    /* Close parameter file */
  324.                 fclose(fid2);
  325.                 return(-1);    /* It's ok */
  326.             }
  327.         }
  328.         fclose(fid2);
  329.     }
  330.     }
  331.     fclose(fid);
  332.     return(0);
  333. }
  334.  
  335.