hostacc.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:11k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

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