home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / src / hostacc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  12.5 KB  |  354 lines

  1. /*
  2.  *      @(#) hostacc.c  -       Implementation of host access for the
  3.  *                              experimental FTP daemon developed at
  4.  *                              Washington University.
  5.  *  $Id: hostacc.c,v 1.10 1997/01/14 22:45:48 sob Exp $
  6.  *
  7.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  8.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  9.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  10.  *
  11.  * AUTHOR
  12.  *      Bart Muijzer    <bartm@cv.ruu.nl>
  13.  *
  14.  * HISTORY
  15.  *      930316  BM      Created
  16.  *      930317  BM      Converted to local naming convention;
  17.  *                      added rhost_ok(), cleanup code in enghacc()
  18.  *      930318  BM      Ported to BSD; fixed memory leaks
  19.  *      930322  BM      Changed algorithm: not in configfile =  allow
  20.  *                                         in configfile and match = allow|deny
  21.  *                                         in configfile and no match = deny
  22.  *
  23.  */
  24.  
  25. #include "config.h"
  26.  
  27. #ifdef  HOST_ACCESS
  28.  
  29. #include "hostacc.h"
  30.  
  31. static  char    linbuf[MAXLEN];  /* Buffer to hold one line of config-file  */
  32. static  char    unibuf[MAXLEN];  /* Buffer to hold unified line             */
  33. static  hacc_t  ha_arr[MAXLIN];  /* Array with host access information      */
  34.  
  35. static  FILE    *ptFp;           /* FILE * into host access config file     */
  36. static  int     iHaInd = 0;      /* Index in ha_arr                         */
  37. static  int     iHaSize;         /* Will hold actual #elems in ha_arr       */
  38. static  int     iFirstTim = 1;   /* Used by gethacc() to see if index in    */
  39.                                  /* ha_arr needs to be reset                */
  40.  
  41. /* ------------------------------------------------------------------------ *\
  42.  * FUNCTION  : rhost_ok                                                     *
  43.  * PURPOSE   : Check if a host is allowed to make a connection              *
  44.  * ARGUMENTS : Remote user name, remote host name, remote host address      *
  45.  * RETURNS   : 1 if host is granted access, 0 if not                        *
  46. \* ------------------------------------------------------------------------ */
  47.  
  48. int     rhost_ok(pcRuser, pcRhost, pcRaddr)
  49. char    *pcRuser,
  50.         *pcRhost,
  51.         *pcRaddr;
  52. {
  53.         hacc_t  *ptHtmp;
  54.         char    *pcHost;
  55.         char    *ha_login;
  56.         int     iInd, iLineMatch = 0, iUserSeen = 0;
  57.         int     m;
  58.  
  59.         switch(sethacc()){
  60.         case 1:
  61.                 /* no hostaccess file; disable mechanism */
  62.                 return(1);
  63.                 break;
  64.         case -1:
  65.                 syslog(LOG_INFO, "rhost_ok: sethacc failed");
  66.                 return(0);
  67.                 break;
  68.         default:
  69.                 break;
  70.         }
  71.  
  72.         /* user names "ftp" and "anonymous" are equivalent */
  73.         if (!strcasecmp(pcRuser, "anonymous"))
  74.                 pcRuser = "ftp";
  75.  
  76.         while (((ptHtmp = gethacc()) != (hacc_t *)NULL) && !iLineMatch)
  77.         {
  78.                 if (strcasecmp(ptHtmp->ha_login, "anonymous"))
  79.                         ha_login = ptHtmp->ha_login;
  80.                 else
  81.                         ha_login = "ftp";
  82.  
  83.                 if ((strcasecmp(pcRuser, ha_login)) && strcmp(ha_login, "*"))
  84.                         /* wrong user, check rest of file */
  85.                         continue;
  86.  
  87.                 /*
  88.                  * We have seen a line regarding the current user.
  89.                  * Remember this.
  90.                  */
  91.                 iUserSeen = 1;
  92.  
  93.                 for(iInd=0, pcHost=ptHtmp->ha_hosts[0];
  94.                     ((pcHost != NULL) && !iLineMatch);
  95.                     pcHost=ptHtmp->ha_hosts[++iInd])
  96.                 {
  97.                         if (isdigit(*pcHost))
  98.                         {
  99.                                 iLineMatch = !fnmatch(pcHost, pcRaddr, NULL);
  100.                         }
  101.                         else
  102.                         {
  103.                                 iLineMatch = !fnmatch(pcHost, pcRhost, NULL);
  104.                         }
  105.                         if (iLineMatch)
  106.                         {
  107.                                 iLineMatch = (ptHtmp->ha_type == ALLOW) ? 1 : 0;
  108.                                 goto match;
  109.                         }
  110.                 }
  111.         }
  112.  
  113. match:
  114.         /*
  115.          * At this point, iUserSeen == 1 if we've seen lines regarding
  116.          * the current user, and 0 otherwise. If we reached the end of
  117.          * the config file without a match we allow. Else, we allow or
  118.          * deny according to the rule found.
  119.          */
  120.  
  121.         if (endhacc())
  122.         {
  123.                 syslog(LOG_INFO, "rhost_ok: endhacc failed");
  124.                 return(0);
  125.         }
  126.  
  127.         if (iUserSeen)
  128.                 return(ptHtmp == NULL) ? 0 : iLineMatch;
  129.         else
  130.                 /* Nothing at all about user in configfile, allow */
  131.                 return(1);
  132. }
  133.  
  134. /* ------------------------------------------------------------------------ *\
  135.  * FUNCTION  : sethacc                                                      *
  136.  * PURPOSE   : Initialize data structures for host access                   *
  137.  * ARGUMENTS : None                                                         *
  138.  * RETURNS   : -1 on failure, 1 if host access file doesn't exist,          *
  139.  *             0 otherwise                                                  *
  140. \* ------------------------------------------------------------------------ */
  141.  
  142. static  int     sethacc()
  143. {
  144.         int     iHaHind = 0;                    /* Index in list of hosts   */
  145.         char    *pcBegin, *pcEnd, *pcColon;
  146.         char    *pcTmp1, *pcTmp2;
  147.  
  148.         /* Open config file */
  149.         if ((ptFp = fopen(_PATH_FTPHOSTS, "r")) == NULL)
  150.         {
  151.                 if (errno == ENOENT)
  152.                         return(1);
  153.                 else {
  154.                 fatal("Can't open host access file");
  155.                 return (-1);
  156.                 }
  157.         }
  158.  
  159.         while (fgets(linbuf, MAXLEN, ptFp) != NULL)
  160.         {
  161.                 iHaHind = 0;
  162.  
  163.                 /* Find first non-whitespace character */
  164.                 for (pcBegin=linbuf;
  165.                      ((*pcBegin == '\t') || (*pcBegin == ' '));
  166.                      pcBegin++)
  167.                         ;
  168.                 
  169.                 /* Get rid of comments */
  170.                 if ((pcEnd = strchr(linbuf, '#')) != NULL)
  171.                         *pcEnd = '\0';
  172.                 
  173.  
  174.                 /* Skip empty lines */
  175.                 if ((pcBegin == pcEnd) || (*pcBegin == '\n'))
  176.                         continue;
  177.                 
  178.                 /* Substitute all whitespace by a single ":" so we can
  179.                  * easily break on words later on. The easiest way is 
  180.                  * to copy the result into a temporary buffer (called
  181.                  * the "unified buffer" because it will store a line in 
  182.                  * the same format, regardless of the format the original
  183.                  * line was in).
  184.                  * The result will look like: "allow:name:host:host:host"
  185.                  */
  186.                 for (pcTmp1=pcBegin, pcTmp2=unibuf; *pcTmp1; pcTmp1++)
  187.                 {
  188.                         if (*pcTmp1 != '\t' && *pcTmp1 != ' ' && *pcTmp1 != '\n')
  189.                                 *pcTmp2++ = *pcTmp1;
  190.                         else
  191.                                 /* whitespace */
  192.                                 if (*(pcTmp2-1) == ':')
  193.                                         continue;
  194.                                 else
  195.                                         *pcTmp2++ = ':';
  196.                 }
  197.  
  198.                 /* Throw away trailing whitespace, now indicated by
  199.                  * the last character of the unified buffer being a 
  200.                  * colon. Remember where the news string ends.
  201.                  */
  202.                 pcEnd = (*(pcTmp2 - 1) == ':') ? (pcTmp2 - 1) : pcTmp2;
  203.                 *pcEnd = '\0';          /* Terminate new string */
  204.                                 
  205.                 /* Store what's left of the line into the
  206.                  * hacc_t structure. First the access type,
  207.                  * then the loginname, and finally a list of
  208.                  * hosts to which all this applies.
  209.                  */
  210.                 pcBegin = unibuf;
  211.                 if (!strncmp(pcBegin, "deny", 4))
  212.                 {
  213.                         ha_arr[iHaInd].ha_type = DENY;
  214.                         pcBegin += 5;
  215.                 } else 
  216.                         if (!strncmp(pcBegin, "allow", 5))
  217.                         {
  218.                                 ha_arr[iHaInd].ha_type = ALLOW;
  219.                                 pcBegin += 6;
  220.                         }
  221.                         else {
  222.                                 fatal("Format error in host access file");
  223.                                 return(-1);
  224.                         }
  225.  
  226.                 if((pcColon = strchr(pcBegin, ':')) != NULL)
  227.                         ha_arr[iHaInd].ha_login =
  228.                                 strnsav(pcBegin, (pcColon-pcBegin));
  229.                 else
  230.                 {
  231.                         fatal("Format error in host access file");
  232.                         return(-1);
  233.                 }
  234.  
  235.                 pcBegin = pcColon+1;
  236.                 while ((pcColon = strchr(pcBegin, ':')) != NULL)
  237.                 {
  238.                         ha_arr[iHaInd].ha_hosts[iHaHind++] =
  239.                                 strnsav(pcBegin, (pcColon-pcBegin));
  240.                         pcBegin = pcColon+1;
  241.                         if (iHaHind >= MAXHST)
  242.                         {
  243.                                 fatal("Line too long");
  244.                                 return(-1);
  245.                         }
  246.                 }
  247.                 ha_arr[iHaInd].ha_hosts[iHaHind++] =
  248.                                 strnsav(pcBegin, (pcEnd-pcBegin));
  249.                 ha_arr[iHaInd].ha_hosts[iHaHind] = NULL;
  250.  
  251.                 /*
  252.                  * Check if we need to expand the array with
  253.                  * host access information
  254.                  */
  255.                 if (++iHaInd > MAXLIN)
  256.                 {
  257.                         fatal("Config file too big!!");
  258.                         return(-1);
  259.                 }
  260.         }
  261.         iHaSize = iHaInd;               /* Record current size of ha_arr */
  262.         return ((feof(ptFp)) ? 0 : -1);
  263. }
  264.  
  265. /* ------------------------------------------------------------------------ *\
  266.  * FUNCTION  : gethacc                                                      *
  267.  * PURPOSE   : return pointer to the next host_access structure             *
  268.  * ARGUMENTS : None                                                         *
  269.  * RETURNS   : NULL on failure, pointervalue otherwise                      *
  270. \* ------------------------------------------------------------------------ */
  271.  
  272. static  hacc_t  *gethacc()
  273. {
  274.         static  int     iHaInd;
  275.         hacc_t  *ptTmp;
  276.  
  277.         if ((ptTmp = (hacc_t *)malloc(sizeof(hacc_t))) == NULL)
  278.                 return(NULL);
  279.  
  280.         if (iFirstTim)
  281.         {
  282.                 iFirstTim = 0;
  283.                 iHaInd = 0;
  284.         }
  285.         if (iHaInd >= iHaSize)
  286.                 return ((hacc_t *)NULL);
  287.         else {
  288. #ifdef USG
  289.                 memmove(ptTmp, &(ha_arr[iHaInd]), sizeof(hacc_t));
  290. #else
  291.                 bcopy(&(ha_arr[iHaInd]), ptTmp, sizeof(hacc_t));
  292. #endif
  293.                 iHaInd++;
  294.                 return(ptTmp);
  295.         }
  296. }
  297.  
  298. /* ------------------------------------------------------------------------ *\
  299.  * FUNCTION  : endhacc                                                      *
  300.  * PURPOSE   : Free allocated data structures for host access               *
  301.  * ARGUMENTS : None                                                         *
  302.  * RETURNS   : -1 on failure, 0 otherwise                                   *
  303. \* ------------------------------------------------------------------------ */
  304.  
  305. static  int     endhacc()
  306. {
  307.         int     iInd;
  308.         hacc_t  *ptHtmp;
  309.  
  310.     for (ptHtmp = ha_arr;
  311.          ptHtmp < ha_arr + MAXLIN && ptHtmp->ha_type;
  312.          ptHtmp++)
  313.     {
  314.         ptHtmp->ha_type = 0;
  315.         if (ptHtmp->ha_login) {
  316.             free(ptHtmp->ha_login);
  317.             ptHtmp->ha_login = NULL;
  318.         }
  319.         for(iInd=0;
  320.             iInd < MAXHST && ptHtmp->ha_hosts[iInd];
  321.             iInd++) {
  322.             free(ptHtmp->ha_hosts[iInd]);
  323.             ptHtmp->ha_hosts[iInd] = NULL;
  324.         }
  325.     }
  326.  
  327.         if (fclose(ptFp))
  328.                 return (-1);
  329.         return (0);
  330. }
  331.  
  332. /* ------------------------------------------------------------------------ */
  333.  
  334. static  void    fatal(pcMsg)
  335. char    *pcMsg;
  336. {
  337.         syslog(LOG_INFO, "host_access: %s", pcMsg);
  338. }
  339.  
  340. static  char    *strnsav(pcStr,iLen)
  341. char    *pcStr;
  342. int     iLen;
  343. {
  344.         char    *pcBuf;
  345.  
  346.         if ((pcBuf = (char *)malloc(iLen+1)) == NULL)
  347.                 return(NULL);
  348.         strncpy(pcBuf,pcStr,iLen);
  349.         pcBuf[iLen] = '\0';
  350.         return(pcBuf);
  351. }
  352.  
  353. #endif  /* HOST_ACCESS */
  354.