1 /* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
2 
3 This library is free software; you can redistribute it and/or
4 modify it under the terms of the GNU Library General Public License as
5 published by the Free Software Foundation; either version 2 of the
6 License, or (at your option) any later version.
7 
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 Library General Public License for more details.
12 
13 You should have received a copy of the GNU Library General Public
14 License along with this library; see the file COPYING.LIB.  If
15 not, write to the Free Software Foundation, Inc., 51 Franklin Street,
16 Suite 500, Boston, MA 02110-1335, USA.  */
17 
18 /* Required to tell conf.h not to include the standard ProFTPD
19  * header files
20  */
21 
22 #define __PROFTPD_SUPPORT_LIBRARY
23 
24 #include <conf.h>
25 #include "libsupp.h"
26 
27 /* From log.c/log.h */
28 #define PR_LOG_ERR LOG_ERR
29 extern void pr_log_pri(int, char *, ...);
30 
31 /* From support.c */
32 extern int sstrncpy(char *dst, const char *src, size_t n);
33 
34 #define NPWDFIELDS 	7
35 #define NGRPFIELDS 	4
36 
37 #ifndef BUFSIZ
38 #define BUFSIZ		PR_TUNABLE_BUFFER_SIZE
39 #endif
40 
41 /* Provides fgetpwent()/fgetgrent() functions.  Note that the format of the
42  * files is probably NOT platform dependent, so use of these functions will
43  * require a strict format:
44  *
45  *   "username:password:uid:gid:gecos:home:shell"
46  */
47 
48 #ifndef HAVE_FGETPWENT
49 
50 static char pwdbuf[BUFSIZ];
51 static char *pwdfields[NPWDFIELDS];
52 static struct passwd pwent;
53 
supp_getpwent(const char * buf)54 static struct passwd *supp_getpwent(const char *buf) {
55   register unsigned int i;
56   register char *cp;
57   char *ep = NULL, *buffer = NULL;
58   char **fields = NULL;
59   struct passwd *pwd = NULL;
60 
61   fields = pwdfields;
62   buffer = pwdbuf;
63   pwd = &pwent;
64 
65   sstrncpy(buffer, buf, BUFSIZ-1);
66   buffer[BUFSIZ-1] = '\0';
67 
68   for(cp = buffer, i = 0; i < NPWDFIELDS && cp; i++) {
69     fields[i] = cp;
70     while (*cp && *cp != ':')
71       ++cp;
72 
73     if (*cp)
74       *cp++ = '\0';
75     else
76       cp = 0;
77   }
78 
79   if (i != NPWDFIELDS || *fields[2] == '\0' || *fields[3] == '\0')
80     return 0;
81 
82   pwd->pw_name = fields[0];
83   pwd->pw_passwd = fields[1];
84 
85   if (fields[2][0] == '\0' ||
86      ((pwd->pw_uid = strtol(fields[2], &ep, 10)) == 0 && *ep))
87        return 0;
88 
89   if (fields[3][0] == '\0' ||
90      ((pwd->pw_gid = strtol(fields[3], &ep, 10)) == 0 && *ep))
91        return 0;
92 
93   pwd->pw_gecos = fields[4];
94   pwd->pw_dir = fields[5];
95   pwd->pw_shell = fields[6];
96 
97   return pwd;
98 }
99 
fgetpwent(FILE * fp)100 struct passwd *fgetpwent(FILE *fp) {
101   char buf[BUFSIZ] = {'\0'};
102 
103   while (fgets(buf, sizeof(buf), fp) != (char*) 0) {
104 
105     /* ignore empty and comment lines */
106     if (buf[0] == '\0' || buf[0] == '#')
107       continue;
108 
109     buf[strlen(buf)-1] = '\0';
110     return supp_getpwent(buf);
111   }
112 
113   return NULL;
114 }
115 #endif /* HAVE_FGETPWENT */
116 
117 #ifndef HAVE_FGETGRENT
118 #define MAXMEMBERS 4096
119 
120 static char *grpbuf = NULL;
121 static struct group grent;
122 static char *grpfields[NGRPFIELDS];
123 static char *members[MAXMEMBERS+1];
124 
fgetbufline(char ** buf,int * buflen,FILE * fp)125 static char *fgetbufline(char **buf, int *buflen, FILE *fp) {
126   char *cp = *buf;
127 
128   while (fgets(cp, (*buflen) - (cp - *buf), fp) != NULL) {
129 
130     /* Is this a full line? */
131     if (strchr(cp, '\n'))
132       return *buf;
133 
134     /* No -- allocate a larger buffer, doubling buflen. */
135     *buflen += *buflen;
136 
137     {
138       char *new_buf;
139 
140       new_buf = realloc(*buf, *buflen);
141       if (new_buf == NULL)
142         break;
143 
144       *buf = new_buf;
145     }
146 
147     cp = *buf + (cp - *buf);
148     cp = strchr(cp, '\0');
149   }
150 
151   free(*buf);
152   *buf = NULL;
153   *buflen = 0;
154 
155   return NULL;
156 }
157 
supp_grplist(char * s)158 static char **supp_grplist(char *s) {
159   int nmembers = 0;
160 
161   while (s && *s && nmembers < MAXMEMBERS) {
162     members[nmembers++] = s;
163     while (*s && *s != ',')
164       s++;
165 
166     if (*s)
167       *s++ = '\0';
168   }
169 
170   members[nmembers] = NULL;
171   return members;
172 }
173 
supp_getgrent(const char * buf)174 static struct group *supp_getgrent(const char *buf) {
175   int i;
176   char *cp;
177 
178   i = strlen(buf) + 1;
179 
180   if (!grpbuf) {
181     grpbuf = malloc(i);
182 
183   } else {
184     char *new_buf;
185 
186     new_buf = realloc(grpbuf, i);
187     if (new_buf == NULL)
188       return NULL;
189 
190     grpbuf = new_buf;
191   }
192 
193   if (!grpbuf)
194     return NULL;
195 
196   sstrncpy(grpbuf, buf, i);
197 
198   if ((cp = strrchr(grpbuf, '\n')))
199     *cp = '\0';
200 
201   for (cp = grpbuf, i = 0; i < NGRPFIELDS && cp; i++) {
202     grpfields[i] = cp;
203 
204     if ((cp = strchr(cp, ':')))
205       *cp++ = 0;
206   }
207 
208   if (i < (NGRPFIELDS - 1)) {
209     pr_log_pri(PR_LOG_ERR, "Malformed entry in group file: %s", buf);
210     return NULL;
211   }
212 
213   if (*grpfields[2] == '\0')
214     return NULL;
215 
216   grent.gr_name = grpfields[0];
217   grent.gr_passwd = grpfields[1];
218   grent.gr_gid = atoi(grpfields[2]);
219   grent.gr_mem = supp_grplist(grpfields[3]);
220 
221   return &grent;
222 }
223 
fgetgrent(FILE * fp)224 struct group *fgetgrent(FILE *fp) {
225   char *cp = NULL, *buf = malloc(BUFSIZ);
226   int buflen = BUFSIZ;
227   struct group *grp = NULL;
228 
229   if (!buf)
230     return NULL;
231 
232   while (fgetbufline(&buf, &buflen, fp) != NULL) {
233 
234     /* ignore comment and empty lines */
235     if (buf[0] == '\0' || buf[0] == '#')
236       continue;
237 
238     if ((cp = strchr(buf, '\n')) != NULL)
239       *cp = '\0';
240 
241     grp = supp_getgrent(buf);
242     free(buf);
243 
244     return grp;
245   }
246 
247   return NULL;
248 }
249 
250 #endif /* HAVE_FGETGRENT */
251