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