xref: /dragonfly/usr.sbin/mtree/getid.c (revision 7ff0fc30)
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
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 *
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 *
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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