xref: /dragonfly/usr.sbin/mtree/getid.c (revision 50c6cbc7)
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 #if HAVE_NBTOOL_CONFIG_H
64 #include "nbtool_config.h"
65 #endif
66 
67 #include <sys/param.h>
68 
69 #include <grp.h>
70 #include <limits.h>
71 #include <pwd.h>
72 #include <stdlib.h>
73 #include <stdio.h>
74 #include <string.h>
75 #include <time.h>
76 #include <unistd.h>
77 
78 #include "extern.h"
79 
80 static	struct group *	gi_getgrnam(const char *);
81 static	struct group *	gi_getgrgid(gid_t);
82 static	int		gi_setgroupent(int);
83 static	void		gi_endgrent(void);
84 static	int		grstart(void);
85 static	int		grscan(int, gid_t, const char *);
86 static	int		grmatchline(int, gid_t, const char *);
87 
88 static	struct passwd *	gi_getpwnam(const char *);
89 static	struct passwd *	gi_getpwuid(uid_t);
90 static	int		gi_setpassent(int);
91 static	void		gi_endpwent(void);
92 static	int		pwstart(void);
93 static	int		pwscan(int, uid_t, const char *);
94 static	int		pwmatchline(int, uid_t, const char *);
95 
96 #define	MAXGRP		200
97 #define	MAXLINELENGTH	1024
98 
99 static	FILE		*_gr_fp;
100 static	struct group	_gr_group;
101 static	int		_gr_stayopen;
102 static	int		_gr_filesdone;
103 static	FILE		*_pw_fp;
104 static	struct passwd	_pw_passwd;	/* password structure */
105 static	int		_pw_stayopen;	/* keep fd's open */
106 static	int		_pw_filesdone;
107 
108 static	char		grfile[MAXPATHLEN];
109 static	char		pwfile[MAXPATHLEN];
110 
111 static	char		*members[MAXGRP];
112 static	char		grline[MAXLINELENGTH];
113 static	char		pwline[MAXLINELENGTH];
114 
115 int
116 setup_getid(const char *dir)
117 {
118 	if (dir == NULL)
119 		return (0);
120 
121 				/* close existing databases */
122 	gi_endgrent();
123 	gi_endpwent();
124 
125 				/* build paths to new databases */
126 	snprintf(grfile, sizeof(grfile), "%s/group", dir);
127 	snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
128 
129 				/* try to open new databases */
130 	if (!grstart() || !pwstart())
131 		return (0);
132 
133 				/* switch pwcache(3) lookup functions */
134 	if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
135 			    gi_getgrnam, gi_getgrgid) == -1
136 	    || pwcache_userdb(gi_setpassent, gi_endpwent,
137 			    gi_getpwnam, gi_getpwuid) == -1)
138 		return (0);
139 
140 	return (1);
141 }
142 
143 
144 /*
145  * group lookup functions
146  */
147 
148 static struct group *
149 gi_getgrnam(const char *name)
150 {
151 	int rval;
152 
153 	if (!grstart())
154 		return NULL;
155 	rval = grscan(1, 0, name);
156 	if (!_gr_stayopen)
157 		endgrent();
158 	return (rval) ? &_gr_group : NULL;
159 }
160 
161 static struct group *
162 gi_getgrgid(gid_t gid)
163 {
164 	int rval;
165 
166 	if (!grstart())
167 		return NULL;
168 	rval = grscan(1, gid, NULL);
169 	if (!_gr_stayopen)
170 		endgrent();
171 	return (rval) ? &_gr_group : NULL;
172 }
173 
174 static int
175 gi_setgroupent(int stayopen)
176 {
177 
178 	if (!grstart())
179 		return 0;
180 	_gr_stayopen = stayopen;
181 	return 1;
182 }
183 
184 static void
185 gi_endgrent(void)
186 {
187 
188 	_gr_filesdone = 0;
189 	if (_gr_fp) {
190 		(void)fclose(_gr_fp);
191 		_gr_fp = NULL;
192 	}
193 }
194 
195 static int
196 grstart(void)
197 {
198 
199 	_gr_filesdone = 0;
200 	if (_gr_fp) {
201 		rewind(_gr_fp);
202 		return 1;
203 	}
204 	if (grfile[0] == '\0')			/* sanity check */
205 		return 0;
206 
207 	_gr_fp = fopen(grfile, "r");
208 	if (_gr_fp != NULL)
209 		return 1;
210 	warn("Can't open `%s'", grfile);
211 	return 0;
212 }
213 
214 
215 static int
216 grscan(int search, gid_t gid, const char *name)
217 {
218 
219 	if (_gr_filesdone)
220 		return 0;
221 	for (;;) {
222 		if (!fgets(grline, sizeof(grline), _gr_fp)) {
223 			if (!search)
224 				_gr_filesdone = 1;
225 			return 0;
226 		}
227 		/* skip lines that are too big */
228 		if (!strchr(grline, '\n')) {
229 			int ch;
230 
231 			while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
232 				;
233 			continue;
234 		}
235 		/* skip comments */
236 		if (grline[0] == '#')
237 			continue;
238 		if (grmatchline(search, gid, name))
239 			return 1;
240 	}
241 	/* NOTREACHED */
242 }
243 
244 static int
245 grmatchline(int search, gid_t gid, const char *name)
246 {
247 	unsigned long	id;
248 	char		**m;
249 	char		*cp, *bp, *ep;
250 
251 	/* name may be NULL if search is nonzero */
252 
253 	bp = grline;
254 	memset(&_gr_group, 0, sizeof(_gr_group));
255 	_gr_group.gr_name = strsep(&bp, ":\n");
256 	if (search && name && strcmp(_gr_group.gr_name, name))
257 		return 0;
258 	_gr_group.gr_passwd = strsep(&bp, ":\n");
259 	if (!(cp = strsep(&bp, ":\n")))
260 		return 0;
261 	id = strtoul(cp, &ep, 10);
262 	if (id > GID_MAX || *ep != '\0')
263 		return 0;
264 	_gr_group.gr_gid = (gid_t)id;
265 	if (search && name == NULL && _gr_group.gr_gid != gid)
266 		return 0;
267 	cp = NULL;
268 	if (bp == NULL)
269 		return 0;
270 	for (_gr_group.gr_mem = m = members;; bp++) {
271 		if (m == &members[MAXGRP - 1])
272 			break;
273 		if (*bp == ',') {
274 			if (cp) {
275 				*bp = '\0';
276 				*m++ = cp;
277 				cp = NULL;
278 			}
279 		} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
280 			if (cp) {
281 				*bp = '\0';
282 				*m++ = cp;
283 			}
284 			break;
285 		} else if (cp == NULL)
286 			cp = bp;
287 	}
288 	*m = NULL;
289 	return 1;
290 }
291 
292 
293 /*
294  * user lookup functions
295  */
296 
297 static struct passwd *
298 gi_getpwnam(const char *name)
299 {
300 	int rval;
301 
302 	if (!pwstart())
303 		return NULL;
304 	rval = pwscan(1, 0, name);
305 	if (!_pw_stayopen)
306 		endpwent();
307 	return (rval) ? &_pw_passwd : NULL;
308 }
309 
310 static struct passwd *
311 gi_getpwuid(uid_t uid)
312 {
313 	int rval;
314 
315 	if (!pwstart())
316 		return NULL;
317 	rval = pwscan(1, uid, NULL);
318 	if (!_pw_stayopen)
319 		endpwent();
320 	return (rval) ? &_pw_passwd : NULL;
321 }
322 
323 static int
324 gi_setpassent(int stayopen)
325 {
326 
327 	if (!pwstart())
328 		return 0;
329 	_pw_stayopen = stayopen;
330 	return 1;
331 }
332 
333 static void
334 gi_endpwent(void)
335 {
336 
337 	_pw_filesdone = 0;
338 	if (_pw_fp) {
339 		(void)fclose(_pw_fp);
340 		_pw_fp = NULL;
341 	}
342 }
343 
344 static int
345 pwstart(void)
346 {
347 
348 	_pw_filesdone = 0;
349 	if (_pw_fp) {
350 		rewind(_pw_fp);
351 		return 1;
352 	}
353 	if (pwfile[0] == '\0')			/* sanity check */
354 		return 0;
355 	_pw_fp = fopen(pwfile, "r");
356 	if (_pw_fp != NULL)
357 		return 1;
358 	warn("Can't open `%s'", pwfile);
359 	return 0;
360 }
361 
362 
363 static int
364 pwscan(int search, uid_t uid, const char *name)
365 {
366 
367 	if (_pw_filesdone)
368 		return 0;
369 	for (;;) {
370 		if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
371 			if (!search)
372 				_pw_filesdone = 1;
373 			return 0;
374 		}
375 		/* skip lines that are too big */
376 		if (!strchr(pwline, '\n')) {
377 			int ch;
378 
379 			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
380 				;
381 			continue;
382 		}
383 		/* skip comments */
384 		if (pwline[0] == '#')
385 			continue;
386 		if (pwmatchline(search, uid, name))
387 			return 1;
388 	}
389 	/* NOTREACHED */
390 }
391 
392 static int
393 pwmatchline(int search, uid_t uid, const char *name)
394 {
395 	unsigned long	id;
396 	char		*cp, *bp, *ep;
397 
398 	/* name may be NULL if search is nonzero */
399 
400 	bp = pwline;
401 	memset(&_pw_passwd, 0, sizeof(_pw_passwd));
402 	_pw_passwd.pw_name = strsep(&bp, ":\n");		/* name */
403 	if (search && name && strcmp(_pw_passwd.pw_name, name))
404 		return 0;
405 
406 	_pw_passwd.pw_passwd = strsep(&bp, ":\n");		/* passwd */
407 
408 	if (!(cp = strsep(&bp, ":\n")))				/* uid */
409 		return 0;
410 	id = strtoul(cp, &ep, 10);
411 	if (id > UID_MAX || *ep != '\0')
412 		return 0;
413 	_pw_passwd.pw_uid = (uid_t)id;
414 	if (search && name == NULL && _pw_passwd.pw_uid != uid)
415 		return 0;
416 
417 	if (!(cp = strsep(&bp, ":\n")))				/* gid */
418 		return 0;
419 	id = strtoul(cp, &ep, 10);
420 	if (id > GID_MAX || *ep != '\0')
421 		return 0;
422 	_pw_passwd.pw_gid = (gid_t)id;
423 
424 	if (!(ep = strsep(&bp, ":")))				/* class */
425 		return 0;
426 	if (!(ep = strsep(&bp, ":")))				/* change */
427 		return 0;
428 	if (!(ep = strsep(&bp, ":")))				/* expire */
429 		return 0;
430 
431 	if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))	/* gecos */
432 		return 0;
433 	if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))		/* directory */
434 		return 0;
435 	if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))	/* shell */
436 		return 0;
437 
438 	if (strchr(bp, ':') != NULL)
439 		return 0;
440 
441 	return 1;
442 }
443 
444