1256996Sbrooks/*	$NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $	*/
2244541Sbrooks/*	from: NetBSD: getpwent.c,v 1.48 2000/10/03 03:22:26 enami Exp */
3244541Sbrooks/*	from: NetBSD: getgrent.c,v 1.41 2002/01/12 23:51:30 lukem Exp */
4244541Sbrooks
5244541Sbrooks/*
6244541Sbrooks * Copyright (c) 1987, 1988, 1989, 1993, 1994, 1995
7244541Sbrooks *	The Regents of the University of California.  All rights reserved.
8244541Sbrooks *
9244541Sbrooks * Redistribution and use in source and binary forms, with or without
10244541Sbrooks * modification, are permitted provided that the following conditions
11244541Sbrooks * are met:
12244541Sbrooks * 1. Redistributions of source code must retain the above copyright
13244541Sbrooks *    notice, this list of conditions and the following disclaimer.
14244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
15244541Sbrooks *    notice, this list of conditions and the following disclaimer in the
16244541Sbrooks *    documentation and/or other materials provided with the distribution.
17244541Sbrooks * 3. Neither the name of the University nor the names of its contributors
18244541Sbrooks *    may be used to endorse or promote products derived from this software
19244541Sbrooks *    without specific prior written permission.
20244541Sbrooks *
21244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22244541Sbrooks * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23244541Sbrooks * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24244541Sbrooks * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25244541Sbrooks * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26244541Sbrooks * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27244541Sbrooks * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28244541Sbrooks * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29244541Sbrooks * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30244541Sbrooks * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31244541Sbrooks * SUCH DAMAGE.
32244541Sbrooks */
33244541Sbrooks
34244541Sbrooks/*-
35244541Sbrooks * Copyright (c) 2002 The NetBSD Foundation, Inc.
36244541Sbrooks * All rights reserved.
37244541Sbrooks *
38244541Sbrooks * This code is derived from software contributed to The NetBSD Foundation
39244541Sbrooks * by Luke Mewburn of Wasabi Systems.
40244541Sbrooks *
41244541Sbrooks * Redistribution and use in source and binary forms, with or without
42244541Sbrooks * modification, are permitted provided that the following conditions
43244541Sbrooks * are met:
44244541Sbrooks * 1. Redistributions of source code must retain the above copyright
45244541Sbrooks *    notice, this list of conditions and the following disclaimer.
46244541Sbrooks * 2. Redistributions in binary form must reproduce the above copyright
47244541Sbrooks *    notice, this list of conditions and the following disclaimer in the
48244541Sbrooks *    documentation and/or other materials provided with the distribution.
49244541Sbrooks *
50244541Sbrooks * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51244541Sbrooks * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52244541Sbrooks * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53244541Sbrooks * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54244541Sbrooks * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55244541Sbrooks * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56244541Sbrooks * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57244541Sbrooks * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58244541Sbrooks * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59244541Sbrooks * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60244541Sbrooks * POSSIBILITY OF SUCH DAMAGE.
61244541Sbrooks */
62244541Sbrooks
63244541Sbrooks#if HAVE_NBTOOL_CONFIG_H
64244541Sbrooks#include "nbtool_config.h"
65244541Sbrooks#endif
66244541Sbrooks
67244541Sbrooks#include <sys/cdefs.h>
68256996Sbrooks__RCSID("$NetBSD: getid.c,v 1.8 2013/10/16 17:27:42 christos Exp $");
69244541Sbrooks
70244541Sbrooks#include <sys/param.h>
71244541Sbrooks
72244541Sbrooks#include <grp.h>
73244541Sbrooks#include <limits.h>
74244541Sbrooks#include <pwd.h>
75244541Sbrooks#include <stdlib.h>
76244541Sbrooks#include <stdio.h>
77244541Sbrooks#include <string.h>
78244541Sbrooks#include <time.h>
79244541Sbrooks#include <unistd.h>
80244541Sbrooks
81244541Sbrooks#include "extern.h"
82244541Sbrooks
83244541Sbrooksstatic	struct group *	gi_getgrnam(const char *);
84244541Sbrooksstatic	struct group *	gi_getgrgid(gid_t);
85244541Sbrooksstatic	int		gi_setgroupent(int);
86244541Sbrooksstatic	void		gi_endgrent(void);
87244541Sbrooksstatic	int		grstart(void);
88244541Sbrooksstatic	int		grscan(int, gid_t, const char *);
89244541Sbrooksstatic	int		grmatchline(int, gid_t, const char *);
90244541Sbrooks
91244541Sbrooksstatic	struct passwd *	gi_getpwnam(const char *);
92244541Sbrooksstatic	struct passwd *	gi_getpwuid(uid_t);
93244541Sbrooksstatic	int		gi_setpassent(int);
94244541Sbrooksstatic	void		gi_endpwent(void);
95244541Sbrooksstatic	int		pwstart(void);
96244541Sbrooksstatic	int		pwscan(int, uid_t, const char *);
97244541Sbrooksstatic	int		pwmatchline(int, uid_t, const char *);
98244541Sbrooks
99244541Sbrooks#define	MAXGRP		200
100244541Sbrooks#define	MAXLINELENGTH	1024
101244541Sbrooks
102244541Sbrooksstatic	FILE		*_gr_fp;
103244541Sbrooksstatic	struct group	_gr_group;
104244541Sbrooksstatic	int		_gr_stayopen;
105244541Sbrooksstatic	int		_gr_filesdone;
106244541Sbrooksstatic	FILE		*_pw_fp;
107244541Sbrooksstatic	struct passwd	_pw_passwd;	/* password structure */
108244541Sbrooksstatic	int		_pw_stayopen;	/* keep fd's open */
109244541Sbrooksstatic	int		_pw_filesdone;
110244541Sbrooks
111244541Sbrooksstatic	char		grfile[MAXPATHLEN];
112244541Sbrooksstatic	char		pwfile[MAXPATHLEN];
113244541Sbrooks
114244541Sbrooksstatic	char		*members[MAXGRP];
115244541Sbrooksstatic	char		grline[MAXLINELENGTH];
116244541Sbrooksstatic	char		pwline[MAXLINELENGTH];
117244541Sbrooks
118244541Sbrooksint
119244541Sbrookssetup_getid(const char *dir)
120244541Sbrooks{
121244541Sbrooks	if (dir == NULL)
122244541Sbrooks		return (0);
123244541Sbrooks
124244541Sbrooks				/* close existing databases */
125244541Sbrooks	gi_endgrent();
126244541Sbrooks	gi_endpwent();
127244541Sbrooks
128244541Sbrooks				/* build paths to new databases */
129244541Sbrooks	snprintf(grfile, sizeof(grfile), "%s/group", dir);
130244541Sbrooks	snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
131244541Sbrooks
132244541Sbrooks				/* try to open new databases */
133244541Sbrooks	if (!grstart() || !pwstart())
134244541Sbrooks		return (0);
135244541Sbrooks
136244541Sbrooks				/* switch pwcache(3) lookup functions */
137244541Sbrooks	if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
138244541Sbrooks			    gi_getgrnam, gi_getgrgid) == -1
139244541Sbrooks	    || pwcache_userdb(gi_setpassent, gi_endpwent,
140244541Sbrooks			    gi_getpwnam, gi_getpwuid) == -1)
141244541Sbrooks		return (0);
142244541Sbrooks
143244541Sbrooks	return (1);
144244541Sbrooks}
145244541Sbrooks
146244541Sbrooks
147244541Sbrooks/*
148244541Sbrooks * group lookup functions
149244541Sbrooks */
150244541Sbrooks
151244541Sbrooksstatic struct group *
152244541Sbrooksgi_getgrnam(const char *name)
153244541Sbrooks{
154244541Sbrooks	int rval;
155244541Sbrooks
156244541Sbrooks	if (!grstart())
157244541Sbrooks		return NULL;
158244541Sbrooks	rval = grscan(1, 0, name);
159244541Sbrooks	if (!_gr_stayopen)
160244541Sbrooks		endgrent();
161244541Sbrooks	return (rval) ? &_gr_group : NULL;
162244541Sbrooks}
163244541Sbrooks
164244541Sbrooksstatic struct group *
165244541Sbrooksgi_getgrgid(gid_t gid)
166244541Sbrooks{
167244541Sbrooks	int rval;
168244541Sbrooks
169244541Sbrooks	if (!grstart())
170244541Sbrooks		return NULL;
171244541Sbrooks	rval = grscan(1, gid, NULL);
172244541Sbrooks	if (!_gr_stayopen)
173244541Sbrooks		endgrent();
174244541Sbrooks	return (rval) ? &_gr_group : NULL;
175244541Sbrooks}
176244541Sbrooks
177244541Sbrooksstatic int
178244541Sbrooksgi_setgroupent(int stayopen)
179244541Sbrooks{
180244541Sbrooks
181244541Sbrooks	if (!grstart())
182244541Sbrooks		return 0;
183244541Sbrooks	_gr_stayopen = stayopen;
184244541Sbrooks	return 1;
185244541Sbrooks}
186244541Sbrooks
187244541Sbrooksstatic void
188244541Sbrooksgi_endgrent(void)
189244541Sbrooks{
190244541Sbrooks
191244541Sbrooks	_gr_filesdone = 0;
192244541Sbrooks	if (_gr_fp) {
193244541Sbrooks		(void)fclose(_gr_fp);
194244541Sbrooks		_gr_fp = NULL;
195244541Sbrooks	}
196244541Sbrooks}
197244541Sbrooks
198244541Sbrooksstatic int
199244541Sbrooksgrstart(void)
200244541Sbrooks{
201244541Sbrooks
202244541Sbrooks	_gr_filesdone = 0;
203244541Sbrooks	if (_gr_fp) {
204244541Sbrooks		rewind(_gr_fp);
205244541Sbrooks		return 1;
206244541Sbrooks	}
207244541Sbrooks	if (grfile[0] == '\0')			/* sanity check */
208244541Sbrooks		return 0;
209244541Sbrooks	return (_gr_fp = fopen(grfile, "r")) ? 1 : 0;
210244541Sbrooks}
211244541Sbrooks
212244541Sbrooks
213244541Sbrooksstatic int
214244541Sbrooksgrscan(int search, gid_t gid, const char *name)
215244541Sbrooks{
216244541Sbrooks
217244541Sbrooks	if (_gr_filesdone)
218244541Sbrooks		return 0;
219244541Sbrooks	for (;;) {
220244541Sbrooks		if (!fgets(grline, sizeof(grline), _gr_fp)) {
221244541Sbrooks			if (!search)
222244541Sbrooks				_gr_filesdone = 1;
223244541Sbrooks			return 0;
224244541Sbrooks		}
225244541Sbrooks		/* skip lines that are too big */
226244541Sbrooks		if (!strchr(grline, '\n')) {
227244541Sbrooks			int ch;
228244541Sbrooks
229244541Sbrooks			while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
230244541Sbrooks				;
231244541Sbrooks			continue;
232244541Sbrooks		}
233256996Sbrooks		/* skip comments */
234256996Sbrooks		if (pwline[0] == '#')
235256996Sbrooks			continue;
236244541Sbrooks		if (grmatchline(search, gid, name))
237244541Sbrooks			return 1;
238244541Sbrooks	}
239244541Sbrooks	/* NOTREACHED */
240244541Sbrooks}
241244541Sbrooks
242244541Sbrooksstatic int
243244541Sbrooksgrmatchline(int search, gid_t gid, const char *name)
244244541Sbrooks{
245244541Sbrooks	unsigned long	id;
246244541Sbrooks	char		**m;
247244541Sbrooks	char		*cp, *bp, *ep;
248244541Sbrooks
249244541Sbrooks	/* name may be NULL if search is nonzero */
250244541Sbrooks
251244541Sbrooks	bp = grline;
252244541Sbrooks	memset(&_gr_group, 0, sizeof(_gr_group));
253244541Sbrooks	_gr_group.gr_name = strsep(&bp, ":\n");
254244541Sbrooks	if (search && name && strcmp(_gr_group.gr_name, name))
255244541Sbrooks		return 0;
256244541Sbrooks	_gr_group.gr_passwd = strsep(&bp, ":\n");
257244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))
258244541Sbrooks		return 0;
259244541Sbrooks	id = strtoul(cp, &ep, 10);
260244541Sbrooks	if (id > GID_MAX || *ep != '\0')
261244541Sbrooks		return 0;
262244541Sbrooks	_gr_group.gr_gid = (gid_t)id;
263244541Sbrooks	if (search && name == NULL && _gr_group.gr_gid != gid)
264244541Sbrooks		return 0;
265244541Sbrooks	cp = NULL;
266244541Sbrooks	if (bp == NULL)
267244541Sbrooks		return 0;
268244541Sbrooks	for (_gr_group.gr_mem = m = members;; bp++) {
269244541Sbrooks		if (m == &members[MAXGRP - 1])
270244541Sbrooks			break;
271244541Sbrooks		if (*bp == ',') {
272244541Sbrooks			if (cp) {
273244541Sbrooks				*bp = '\0';
274244541Sbrooks				*m++ = cp;
275244541Sbrooks				cp = NULL;
276244541Sbrooks			}
277244541Sbrooks		} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
278244541Sbrooks			if (cp) {
279244541Sbrooks				*bp = '\0';
280244541Sbrooks				*m++ = cp;
281244541Sbrooks			}
282244541Sbrooks			break;
283244541Sbrooks		} else if (cp == NULL)
284244541Sbrooks			cp = bp;
285244541Sbrooks	}
286244541Sbrooks	*m = NULL;
287244541Sbrooks	return 1;
288244541Sbrooks}
289244541Sbrooks
290244541Sbrooks
291244541Sbrooks/*
292244541Sbrooks * user lookup functions
293244541Sbrooks */
294244541Sbrooks
295244541Sbrooksstatic struct passwd *
296244541Sbrooksgi_getpwnam(const char *name)
297244541Sbrooks{
298244541Sbrooks	int rval;
299244541Sbrooks
300244541Sbrooks	if (!pwstart())
301244541Sbrooks		return NULL;
302244541Sbrooks	rval = pwscan(1, 0, name);
303244541Sbrooks	if (!_pw_stayopen)
304244541Sbrooks		endpwent();
305244541Sbrooks	return (rval) ? &_pw_passwd : NULL;
306244541Sbrooks}
307244541Sbrooks
308244541Sbrooksstatic struct passwd *
309244541Sbrooksgi_getpwuid(uid_t uid)
310244541Sbrooks{
311244541Sbrooks	int rval;
312244541Sbrooks
313244541Sbrooks	if (!pwstart())
314244541Sbrooks		return NULL;
315244541Sbrooks	rval = pwscan(1, uid, NULL);
316244541Sbrooks	if (!_pw_stayopen)
317244541Sbrooks		endpwent();
318244541Sbrooks	return (rval) ? &_pw_passwd : NULL;
319244541Sbrooks}
320244541Sbrooks
321244541Sbrooksstatic int
322244541Sbrooksgi_setpassent(int stayopen)
323244541Sbrooks{
324244541Sbrooks
325244541Sbrooks	if (!pwstart())
326244541Sbrooks		return 0;
327244541Sbrooks	_pw_stayopen = stayopen;
328244541Sbrooks	return 1;
329244541Sbrooks}
330244541Sbrooks
331244541Sbrooksstatic void
332244541Sbrooksgi_endpwent(void)
333244541Sbrooks{
334244541Sbrooks
335244541Sbrooks	_pw_filesdone = 0;
336244541Sbrooks	if (_pw_fp) {
337244541Sbrooks		(void)fclose(_pw_fp);
338244541Sbrooks		_pw_fp = NULL;
339244541Sbrooks	}
340244541Sbrooks}
341244541Sbrooks
342244541Sbrooksstatic int
343244541Sbrookspwstart(void)
344244541Sbrooks{
345244541Sbrooks
346244541Sbrooks	_pw_filesdone = 0;
347244541Sbrooks	if (_pw_fp) {
348244541Sbrooks		rewind(_pw_fp);
349244541Sbrooks		return 1;
350244541Sbrooks	}
351244541Sbrooks	if (pwfile[0] == '\0')			/* sanity check */
352244541Sbrooks		return 0;
353244541Sbrooks	return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0;
354244541Sbrooks}
355244541Sbrooks
356244541Sbrooks
357244541Sbrooksstatic int
358244541Sbrookspwscan(int search, uid_t uid, const char *name)
359244541Sbrooks{
360244541Sbrooks
361244541Sbrooks	if (_pw_filesdone)
362244541Sbrooks		return 0;
363244541Sbrooks	for (;;) {
364244541Sbrooks		if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
365244541Sbrooks			if (!search)
366244541Sbrooks				_pw_filesdone = 1;
367244541Sbrooks			return 0;
368244541Sbrooks		}
369244541Sbrooks		/* skip lines that are too big */
370244541Sbrooks		if (!strchr(pwline, '\n')) {
371244541Sbrooks			int ch;
372244541Sbrooks
373244541Sbrooks			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
374244541Sbrooks				;
375244541Sbrooks			continue;
376244541Sbrooks		}
377256996Sbrooks		/* skip comments */
378256996Sbrooks		if (pwline[0] == '#')
379256996Sbrooks			continue;
380244541Sbrooks		if (pwmatchline(search, uid, name))
381244541Sbrooks			return 1;
382244541Sbrooks	}
383244541Sbrooks	/* NOTREACHED */
384244541Sbrooks}
385244541Sbrooks
386244541Sbrooksstatic int
387244541Sbrookspwmatchline(int search, uid_t uid, const char *name)
388244541Sbrooks{
389244541Sbrooks	unsigned long	id;
390244541Sbrooks	char		*cp, *bp, *ep;
391244541Sbrooks
392244541Sbrooks	/* name may be NULL if search is nonzero */
393244541Sbrooks
394244541Sbrooks	bp = pwline;
395244541Sbrooks	memset(&_pw_passwd, 0, sizeof(_pw_passwd));
396244541Sbrooks	_pw_passwd.pw_name = strsep(&bp, ":\n");		/* name */
397244541Sbrooks	if (search && name && strcmp(_pw_passwd.pw_name, name))
398244541Sbrooks		return 0;
399244541Sbrooks
400244541Sbrooks	_pw_passwd.pw_passwd = strsep(&bp, ":\n");		/* passwd */
401244541Sbrooks
402244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))				/* uid */
403244541Sbrooks		return 0;
404244541Sbrooks	id = strtoul(cp, &ep, 10);
405244541Sbrooks	if (id > UID_MAX || *ep != '\0')
406244541Sbrooks		return 0;
407244541Sbrooks	_pw_passwd.pw_uid = (uid_t)id;
408244541Sbrooks	if (search && name == NULL && _pw_passwd.pw_uid != uid)
409244541Sbrooks		return 0;
410244541Sbrooks
411244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))				/* gid */
412244541Sbrooks		return 0;
413244541Sbrooks	id = strtoul(cp, &ep, 10);
414244541Sbrooks	if (id > GID_MAX || *ep != '\0')
415244541Sbrooks		return 0;
416244541Sbrooks	_pw_passwd.pw_gid = (gid_t)id;
417244541Sbrooks
418244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* class */
419244541Sbrooks		return 0;
420244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* change */
421244541Sbrooks		return 0;
422244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* expire */
423244541Sbrooks		return 0;
424244541Sbrooks
425244541Sbrooks	if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))	/* gecos */
426244541Sbrooks		return 0;
427244541Sbrooks	if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))		/* directory */
428244541Sbrooks		return 0;
429244541Sbrooks	if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))	/* shell */
430244541Sbrooks		return 0;
431244541Sbrooks
432244541Sbrooks	if (strchr(bp, ':') != NULL)
433244541Sbrooks		return 0;
434244541Sbrooks
435244541Sbrooks	return 1;
436244541Sbrooks}
437244541Sbrooks
438