1 /* $NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 christos Exp $ */
2 /* from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
3 /* from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
4
5 /*
6 * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
7 * The Regents of the University of California. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*-
35 * Copyright (c) 2002 The NetBSD Foundation, Inc.
36 * All rights reserved.
37 *
38 * This code is derived from software contributed to The NetBSD Foundation
39 * by Luke Mewburn of Wasabi Systems.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 *
50 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60 * POSSIBILITY OF SUCH DAMAGE.
61 */
62
63 #include <sys/param.h>
64
65 #include <grp.h>
66 #include <limits.h>
67 #include <pwd.h>
68 #include <stdlib.h>
69 #include <stdio.h>
70 #include <string.h>
71 #include <time.h>
72 #include <unistd.h>
73
74 #include "extern.h"
75
76 static struct group * gi_getgrnam(const char *);
77 static struct group * gi_getgrgid(gid_t);
78 static int gi_setgroupent(int);
79 static void gi_endgrent(void);
80 static int grstart(void);
81 static int grscan(int, gid_t, const char *);
82 static int grmatchline(int, gid_t, const char *);
83
84 static struct passwd * gi_getpwnam(const char *);
85 static struct passwd * gi_getpwuid(uid_t);
86 static int gi_setpassent(int);
87 static void gi_endpwent(void);
88 static int pwstart(void);
89 static int pwscan(int, uid_t, const char *);
90 static int pwmatchline(int, uid_t, const char *);
91
92 #define MAXGRP 200
93 #define MAXLINELENGTH 1024
94
95 static FILE *_gr_fp;
96 static struct group _gr_group;
97 static int _gr_stayopen;
98 static int _gr_filesdone;
99 static FILE *_pw_fp;
100 static struct passwd _pw_passwd; /* password structure */
101 static int _pw_stayopen; /* keep fd's open */
102 static int _pw_filesdone;
103
104 static char grfile[MAXPATHLEN];
105 static char pwfile[MAXPATHLEN];
106
107 static char *members[MAXGRP];
108 static char grline[MAXLINELENGTH];
109 static char pwline[MAXLINELENGTH];
110
111 int
setup_getid(const char * dir)112 setup_getid(const char *dir)
113 {
114 if (dir == NULL)
115 return (0);
116
117 /* close existing databases */
118 gi_endgrent();
119 gi_endpwent();
120
121 /* build paths to new databases */
122 snprintf(grfile, sizeof(grfile), "%s/group", dir);
123 snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
124
125 /* try to open new databases */
126 if (!grstart() || !pwstart())
127 return (0);
128
129 /* switch pwcache(3) lookup functions */
130 if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
131 gi_getgrnam, gi_getgrgid) == -1
132 || pwcache_userdb(gi_setpassent, gi_endpwent,
133 gi_getpwnam, gi_getpwuid) == -1)
134 return (0);
135
136 return (1);
137 }
138
139
140 /*
141 * group lookup functions
142 */
143
144 static struct group *
gi_getgrnam(const char * name)145 gi_getgrnam(const char *name)
146 {
147 int rval;
148
149 if (!grstart())
150 return NULL;
151 rval = grscan(1, 0, name);
152 if (!_gr_stayopen)
153 endgrent();
154 return (rval) ? &_gr_group : NULL;
155 }
156
157 static struct group *
gi_getgrgid(gid_t gid)158 gi_getgrgid(gid_t gid)
159 {
160 int rval;
161
162 if (!grstart())
163 return NULL;
164 rval = grscan(1, gid, NULL);
165 if (!_gr_stayopen)
166 endgrent();
167 return (rval) ? &_gr_group : NULL;
168 }
169
170 static int
gi_setgroupent(int stayopen)171 gi_setgroupent(int stayopen)
172 {
173
174 if (!grstart())
175 return 0;
176 _gr_stayopen = stayopen;
177 return 1;
178 }
179
180 static void
gi_endgrent(void)181 gi_endgrent(void)
182 {
183
184 _gr_filesdone = 0;
185 if (_gr_fp) {
186 (void)fclose(_gr_fp);
187 _gr_fp = NULL;
188 }
189 }
190
191 static int
grstart(void)192 grstart(void)
193 {
194
195 _gr_filesdone = 0;
196 if (_gr_fp) {
197 rewind(_gr_fp);
198 return 1;
199 }
200 if (grfile[0] == '\0') /* sanity check */
201 return 0;
202
203 _gr_fp = fopen(grfile, "r");
204 if (_gr_fp != NULL)
205 return 1;
206 warn("Can't open `%s'", grfile);
207 return 0;
208 }
209
210
211 static int
grscan(int search,gid_t gid,const char * name)212 grscan(int search, gid_t gid, const char *name)
213 {
214
215 if (_gr_filesdone)
216 return 0;
217 for (;;) {
218 if (!fgets(grline, sizeof(grline), _gr_fp)) {
219 if (!search)
220 _gr_filesdone = 1;
221 return 0;
222 }
223 /* skip lines that are too big */
224 if (!strchr(grline, '\n')) {
225 int ch;
226
227 while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
228 ;
229 continue;
230 }
231 /* skip comments */
232 if (grline[0] == '#')
233 continue;
234 if (grmatchline(search, gid, name))
235 return 1;
236 }
237 /* NOTREACHED */
238 }
239
240 static int
grmatchline(int search,gid_t gid,const char * name)241 grmatchline(int search, gid_t gid, const char *name)
242 {
243 unsigned long id;
244 char **m;
245 char *cp, *bp, *ep;
246
247 /* name may be NULL if search is nonzero */
248
249 bp = grline;
250 memset(&_gr_group, 0, sizeof(_gr_group));
251 _gr_group.gr_name = strsep(&bp, ":\n");
252 if (search && name && strcmp(_gr_group.gr_name, name))
253 return 0;
254 _gr_group.gr_passwd = strsep(&bp, ":\n");
255 if (!(cp = strsep(&bp, ":\n")))
256 return 0;
257 id = strtoul(cp, &ep, 10);
258 if (id > GID_MAX || *ep != '\0')
259 return 0;
260 _gr_group.gr_gid = (gid_t)id;
261 if (search && name == NULL && _gr_group.gr_gid != gid)
262 return 0;
263 cp = NULL;
264 if (bp == NULL)
265 return 0;
266 for (_gr_group.gr_mem = m = members;; bp++) {
267 if (m == &members[MAXGRP - 1])
268 break;
269 if (*bp == ',') {
270 if (cp) {
271 *bp = '\0';
272 *m++ = cp;
273 cp = NULL;
274 }
275 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
276 if (cp) {
277 *bp = '\0';
278 *m++ = cp;
279 }
280 break;
281 } else if (cp == NULL)
282 cp = bp;
283 }
284 *m = NULL;
285 return 1;
286 }
287
288
289 /*
290 * user lookup functions
291 */
292
293 static struct passwd *
gi_getpwnam(const char * name)294 gi_getpwnam(const char *name)
295 {
296 int rval;
297
298 if (!pwstart())
299 return NULL;
300 rval = pwscan(1, 0, name);
301 if (!_pw_stayopen)
302 endpwent();
303 return (rval) ? &_pw_passwd : NULL;
304 }
305
306 static struct passwd *
gi_getpwuid(uid_t uid)307 gi_getpwuid(uid_t uid)
308 {
309 int rval;
310
311 if (!pwstart())
312 return NULL;
313 rval = pwscan(1, uid, NULL);
314 if (!_pw_stayopen)
315 endpwent();
316 return (rval) ? &_pw_passwd : NULL;
317 }
318
319 static int
gi_setpassent(int stayopen)320 gi_setpassent(int stayopen)
321 {
322
323 if (!pwstart())
324 return 0;
325 _pw_stayopen = stayopen;
326 return 1;
327 }
328
329 static void
gi_endpwent(void)330 gi_endpwent(void)
331 {
332
333 _pw_filesdone = 0;
334 if (_pw_fp) {
335 (void)fclose(_pw_fp);
336 _pw_fp = NULL;
337 }
338 }
339
340 static int
pwstart(void)341 pwstart(void)
342 {
343
344 _pw_filesdone = 0;
345 if (_pw_fp) {
346 rewind(_pw_fp);
347 return 1;
348 }
349 if (pwfile[0] == '\0') /* sanity check */
350 return 0;
351 _pw_fp = fopen(pwfile, "r");
352 if (_pw_fp != NULL)
353 return 1;
354 warn("Can't open `%s'", pwfile);
355 return 0;
356 }
357
358
359 static int
pwscan(int search,uid_t uid,const char * name)360 pwscan(int search, uid_t uid, const char *name)
361 {
362
363 if (_pw_filesdone)
364 return 0;
365 for (;;) {
366 if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
367 if (!search)
368 _pw_filesdone = 1;
369 return 0;
370 }
371 /* skip lines that are too big */
372 if (!strchr(pwline, '\n')) {
373 int ch;
374
375 while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
376 ;
377 continue;
378 }
379 /* skip comments */
380 if (pwline[0] == '#')
381 continue;
382 if (pwmatchline(search, uid, name))
383 return 1;
384 }
385 /* NOTREACHED */
386 }
387
388 static int
pwmatchline(int search,uid_t uid,const char * name)389 pwmatchline(int search, uid_t uid, const char *name)
390 {
391 unsigned long id;
392 char *cp, *bp, *ep;
393
394 /* name may be NULL if search is nonzero */
395
396 bp = pwline;
397 memset(&_pw_passwd, 0, sizeof(_pw_passwd));
398 _pw_passwd.pw_name = strsep(&bp, ":\n"); /* name */
399 if (search && name && strcmp(_pw_passwd.pw_name, name))
400 return 0;
401
402 _pw_passwd.pw_passwd = strsep(&bp, ":\n"); /* passwd */
403
404 if (!(cp = strsep(&bp, ":\n"))) /* uid */
405 return 0;
406 id = strtoul(cp, &ep, 10);
407 if (id > UID_MAX || *ep != '\0')
408 return 0;
409 _pw_passwd.pw_uid = (uid_t)id;
410 if (search && name == NULL && _pw_passwd.pw_uid != uid)
411 return 0;
412
413 if (!(cp = strsep(&bp, ":\n"))) /* gid */
414 return 0;
415 id = strtoul(cp, &ep, 10);
416 if (id > GID_MAX || *ep != '\0')
417 return 0;
418 _pw_passwd.pw_gid = (gid_t)id;
419
420 if (!(ep = strsep(&bp, ":"))) /* class */
421 return 0;
422 if (!(ep = strsep(&bp, ":"))) /* change */
423 return 0;
424 if (!(ep = strsep(&bp, ":"))) /* expire */
425 return 0;
426
427 if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n"))) /* gecos */
428 return 0;
429 if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n"))) /* directory */
430 return 0;
431 if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n"))) /* shell */
432 return 0;
433
434 if (strchr(bp, ':') != NULL)
435 return 0;
436
437 return 1;
438 }
439
440