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