1 #pragma ident   "%Z%%M% %I%     %E% SMI"
   2 
   3 /****************************************************************************  
   4  
   5   Copyright (c) 1999,2000 WU-FTPD Development Group.  
   6   All rights reserved.
   7   
   8   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
   9     The Regents of the University of California.
  10   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
  11   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
  12   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
  13   Portions Copyright (c) 1998 Sendmail, Inc.
  14   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
  15   Portions Copyright (c) 1997 by Stan Barber.
  16   Portions Copyright (c) 1997 by Kent Landfield.
  17   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
  18     Free Software Foundation, Inc.  
  19  
  20   Use and distribution of this software and its source code are governed 
  21   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
  22  
  23   If you did not receive a copy of the license, it may be obtained online
  24   at http://www.wu-ftpd.org/license.html.
  25  
  26   $Id: acl.c,v 1.9 2000/07/01 18:17:38 wuftpd Exp $
  27  
  28 ****************************************************************************/
  29 #include "config.h"
  30 
  31 #include <stdio.h>
  32 #include <errno.h>
  33 #include <string.h>
  34 #ifdef HAVE_SYS_SYSLOG_H
  35 #include <sys/syslog.h>
  36 #endif
  37 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
  38 #include <syslog.h>
  39 #endif
  40 
  41 #include <sys/types.h>
  42 #include <sys/stat.h>
  43 #include <sys/file.h>
  44 
  45 #ifdef HAVE_PATHS_H
  46 #include <paths.h>
  47 #endif
  48 #include "pathnames.h"
  49 #include "extensions.h"
  50 #include "proto.h"
  51 
  52 char *aclbuf = NULL;
  53 static struct aclmember *aclmembers;
  54 
  55 /*************************************************************************/
  56 /* FUNCTION  : getaclentry                                               */
  57 /* PURPOSE   : Retrieve a named entry from the ACL                       */
  58 /* ARGUMENTS : pointer to the keyword and a handle to the acl members    */
  59 /* RETURNS   : pointer to the acl member containing the keyword or NULL  */
  60 /*************************************************************************/
  61 
  62 struct aclmember *getaclentry(char *keyword, struct aclmember **next)
  63 {
  64     do {
  65         if (!*next)
  66             *next = aclmembers;
  67         else
  68             *next = (*next)->next;
  69     } while (*next && strcasecmp((*next)->keyword, keyword));
  70 
  71     return (*next);
  72 }
  73 
  74 /*************************************************************************/
  75 /* FUNCTION  : parseacl                                                  */
  76 /* PURPOSE   : Parse the acl buffer into its components                  */
  77 /* ARGUMENTS : A pointer to the acl file                                 */
  78 /* RETURNS   : nothing                                                   */
  79 /*************************************************************************/
  80 
  81 void parseacl(void)
  82 {
  83     char *ptr, *aclptr = aclbuf, *line;
  84     int cnt;
  85     struct aclmember *member, *acltail;
  86 
  87     if (!aclbuf || !(*aclbuf))
  88         return;
  89 
  90     aclmembers = (struct aclmember *) NULL;
  91     acltail = (struct aclmember *) NULL;
  92 
  93     while (*aclptr != '\0') {
  94         line = aclptr;
  95         while (*aclptr && *aclptr != '\n')
  96             aclptr++;
  97         *aclptr++ = (char) NULL;
  98 
  99         /* deal with comments */
 100         if ((ptr = strchr(line, '#')) != NULL)
 101             /* allowed escaped '#' chars for path-filter (DiB) */
 102             if ((ptr > aclbuf) && (*(ptr - 1) != '\\'))
 103                 *ptr = '\0';
 104 
 105         ptr = strtok(line, " \t");
 106         if (ptr) {
 107             member = (struct aclmember *) calloc(1, sizeof(struct aclmember));
 108 
 109             if (member == NULL) {
 110                 syslog(LOG_ERR, "calloc error parsing acl");
 111                 exit(1);
 112             }
 113             (void) strncpy(member->keyword, ptr, MAXKWLEN);
 114             member->keyword[MAXKWLEN - 1] = '\0';
 115             cnt = 0;
 116             while ((ptr = strtok(NULL, " \t")) != NULL) {
 117                 if (cnt >= MAXARGS) {
 118                     syslog(LOG_ERR,
 119                      "Too many args (>%d) in ftpaccess: %s %s %s %s %s ...",
 120                            MAXARGS - 1, member->keyword, member->arg[0],
 121                            member->arg[1], member->arg[2], member->arg[3]);
 122                     break;
 123                 }
 124                 member->arg[cnt++] = ptr;
 125             }
 126             if (acltail)
 127                 acltail->next = member;
 128             acltail = member;
 129             if (!aclmembers)
 130                 aclmembers = member;
 131         }
 132     }
 133 }
 134 
 135 /*************************************************************************/
 136 /* FUNCTION  : readacl                                                   */
 137 /* PURPOSE   : Read the acl into memory                                  */
 138 /* ARGUMENTS : The pathname of the acl                                   */
 139 /* RETURNS   : 0 if error, 1 if no error                                 */
 140 /*************************************************************************/
 141 
 142 int readacl(char *aclpath)
 143 {
 144     FILE *aclfile;
 145     struct stat finfo;
 146     struct aclmember *member;
 147     extern int use_accessfile;
 148 
 149     if (!use_accessfile)
 150         return (0);
 151 
 152     while (aclmembers) {
 153         member = aclmembers->next;
 154         free(aclmembers);
 155         aclmembers = member;
 156     }
 157 
 158     if (aclbuf) {
 159         free(aclbuf);
 160         aclbuf = NULL;
 161     }
 162 
 163     if ((aclfile = fopen(aclpath, "r")) == NULL) {
 164         syslog(LOG_ERR, "cannot open access file %s: %s", aclpath,
 165                strerror(errno));
 166         return (0);
 167     }
 168     if (fstat(fileno(aclfile), &finfo) != 0) {
 169         syslog(LOG_ERR, "cannot fstat access file %s: %s", aclpath,
 170                strerror(errno));
 171         (void) fclose(aclfile);
 172         return (0);
 173     }
 174     if (finfo.st_size == 0) {
 175         aclbuf = (char *) calloc(1, 1);
 176     }
 177     else {
 178         if (!(aclbuf = (char *) malloc((size_t) finfo.st_size + 1))) {
 179             syslog(LOG_ERR, "could not malloc aclbuf (%d bytes)", (size_t) finfo.st_size + 1);
 180             (void) fclose(aclfile);
 181             return (0);
 182         }
 183         if (!fread(aclbuf, (size_t) finfo.st_size, 1, aclfile)) {
 184             syslog(LOG_ERR, "error reading acl file %s: %s", aclpath,
 185                    strerror(errno));
 186             free(aclbuf);
 187             aclbuf = NULL;
 188             (void) fclose(aclfile);
 189             return (0);
 190         }
 191         *(aclbuf + finfo.st_size) = '\0';
 192     }
 193     (void) fclose(aclfile);
 194     return (1);
 195 }