home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / wu-ftpd-.000 / wu-ftpd- / wu-ftpd-2.4 / src / hostacc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-01  |  12.0 KB  |  334 lines

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