xref: /netbsd-src/usr.sbin/mtree/getid.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /*	$NetBSD: getid.c,v 1.6 2007/12/12 22:59:58 lukem 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.6 2007/12/12 22:59:58 lukem 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