1273796Sbrooks/*	$NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 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>
68273796Sbrooks__RCSID("$NetBSD: getid.c,v 1.10 2014/10/27 21:46:45 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;
209273796Sbrooks
210273796Sbrooks	_gr_fp = fopen(grfile, "r");
211273796Sbrooks	if (_gr_fp != NULL)
212273796Sbrooks		return 1;
213273796Sbrooks	warn("Can't open `%s'", grfile);
214273796Sbrooks	return 0;
215244541Sbrooks}
216244541Sbrooks
217244541Sbrooks
218244541Sbrooksstatic int
219244541Sbrooksgrscan(int search, gid_t gid, const char *name)
220244541Sbrooks{
221244541Sbrooks
222244541Sbrooks	if (_gr_filesdone)
223244541Sbrooks		return 0;
224244541Sbrooks	for (;;) {
225244541Sbrooks		if (!fgets(grline, sizeof(grline), _gr_fp)) {
226244541Sbrooks			if (!search)
227244541Sbrooks				_gr_filesdone = 1;
228244541Sbrooks			return 0;
229244541Sbrooks		}
230244541Sbrooks		/* skip lines that are too big */
231244541Sbrooks		if (!strchr(grline, '\n')) {
232244541Sbrooks			int ch;
233244541Sbrooks
234244541Sbrooks			while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
235244541Sbrooks				;
236244541Sbrooks			continue;
237244541Sbrooks		}
238256687Sbrooks		/* skip comments */
239273796Sbrooks		if (grline[0] == '#')
240256687Sbrooks			continue;
241244541Sbrooks		if (grmatchline(search, gid, name))
242244541Sbrooks			return 1;
243244541Sbrooks	}
244244541Sbrooks	/* NOTREACHED */
245244541Sbrooks}
246244541Sbrooks
247244541Sbrooksstatic int
248244541Sbrooksgrmatchline(int search, gid_t gid, const char *name)
249244541Sbrooks{
250244541Sbrooks	unsigned long	id;
251244541Sbrooks	char		**m;
252244541Sbrooks	char		*cp, *bp, *ep;
253244541Sbrooks
254244541Sbrooks	/* name may be NULL if search is nonzero */
255244541Sbrooks
256244541Sbrooks	bp = grline;
257244541Sbrooks	memset(&_gr_group, 0, sizeof(_gr_group));
258244541Sbrooks	_gr_group.gr_name = strsep(&bp, ":\n");
259244541Sbrooks	if (search && name && strcmp(_gr_group.gr_name, name))
260244541Sbrooks		return 0;
261244541Sbrooks	_gr_group.gr_passwd = strsep(&bp, ":\n");
262244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))
263244541Sbrooks		return 0;
264244541Sbrooks	id = strtoul(cp, &ep, 10);
265244541Sbrooks	if (id > GID_MAX || *ep != '\0')
266244541Sbrooks		return 0;
267244541Sbrooks	_gr_group.gr_gid = (gid_t)id;
268244541Sbrooks	if (search && name == NULL && _gr_group.gr_gid != gid)
269244541Sbrooks		return 0;
270244541Sbrooks	cp = NULL;
271244541Sbrooks	if (bp == NULL)
272244541Sbrooks		return 0;
273244541Sbrooks	for (_gr_group.gr_mem = m = members;; bp++) {
274244541Sbrooks		if (m == &members[MAXGRP - 1])
275244541Sbrooks			break;
276244541Sbrooks		if (*bp == ',') {
277244541Sbrooks			if (cp) {
278244541Sbrooks				*bp = '\0';
279244541Sbrooks				*m++ = cp;
280244541Sbrooks				cp = NULL;
281244541Sbrooks			}
282244541Sbrooks		} else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
283244541Sbrooks			if (cp) {
284244541Sbrooks				*bp = '\0';
285244541Sbrooks				*m++ = cp;
286244541Sbrooks			}
287244541Sbrooks			break;
288244541Sbrooks		} else if (cp == NULL)
289244541Sbrooks			cp = bp;
290244541Sbrooks	}
291244541Sbrooks	*m = NULL;
292244541Sbrooks	return 1;
293244541Sbrooks}
294244541Sbrooks
295244541Sbrooks
296244541Sbrooks/*
297244541Sbrooks * user lookup functions
298244541Sbrooks */
299244541Sbrooks
300244541Sbrooksstatic struct passwd *
301244541Sbrooksgi_getpwnam(const char *name)
302244541Sbrooks{
303244541Sbrooks	int rval;
304244541Sbrooks
305244541Sbrooks	if (!pwstart())
306244541Sbrooks		return NULL;
307244541Sbrooks	rval = pwscan(1, 0, name);
308244541Sbrooks	if (!_pw_stayopen)
309244541Sbrooks		endpwent();
310244541Sbrooks	return (rval) ? &_pw_passwd : NULL;
311244541Sbrooks}
312244541Sbrooks
313244541Sbrooksstatic struct passwd *
314244541Sbrooksgi_getpwuid(uid_t uid)
315244541Sbrooks{
316244541Sbrooks	int rval;
317244541Sbrooks
318244541Sbrooks	if (!pwstart())
319244541Sbrooks		return NULL;
320244541Sbrooks	rval = pwscan(1, uid, NULL);
321244541Sbrooks	if (!_pw_stayopen)
322244541Sbrooks		endpwent();
323244541Sbrooks	return (rval) ? &_pw_passwd : NULL;
324244541Sbrooks}
325244541Sbrooks
326244541Sbrooksstatic int
327244541Sbrooksgi_setpassent(int stayopen)
328244541Sbrooks{
329244541Sbrooks
330244541Sbrooks	if (!pwstart())
331244541Sbrooks		return 0;
332244541Sbrooks	_pw_stayopen = stayopen;
333244541Sbrooks	return 1;
334244541Sbrooks}
335244541Sbrooks
336244541Sbrooksstatic void
337244541Sbrooksgi_endpwent(void)
338244541Sbrooks{
339244541Sbrooks
340244541Sbrooks	_pw_filesdone = 0;
341244541Sbrooks	if (_pw_fp) {
342244541Sbrooks		(void)fclose(_pw_fp);
343244541Sbrooks		_pw_fp = NULL;
344244541Sbrooks	}
345244541Sbrooks}
346244541Sbrooks
347244541Sbrooksstatic int
348244541Sbrookspwstart(void)
349244541Sbrooks{
350244541Sbrooks
351244541Sbrooks	_pw_filesdone = 0;
352244541Sbrooks	if (_pw_fp) {
353244541Sbrooks		rewind(_pw_fp);
354244541Sbrooks		return 1;
355244541Sbrooks	}
356244541Sbrooks	if (pwfile[0] == '\0')			/* sanity check */
357244541Sbrooks		return 0;
358273796Sbrooks	_pw_fp = fopen(pwfile, "r");
359273796Sbrooks	if (_pw_fp != NULL)
360273796Sbrooks		return 1;
361273796Sbrooks	warn("Can't open `%s'", pwfile);
362273796Sbrooks	return 0;
363244541Sbrooks}
364244541Sbrooks
365244541Sbrooks
366244541Sbrooksstatic int
367244541Sbrookspwscan(int search, uid_t uid, const char *name)
368244541Sbrooks{
369244541Sbrooks
370244541Sbrooks	if (_pw_filesdone)
371244541Sbrooks		return 0;
372244541Sbrooks	for (;;) {
373244541Sbrooks		if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
374244541Sbrooks			if (!search)
375244541Sbrooks				_pw_filesdone = 1;
376244541Sbrooks			return 0;
377244541Sbrooks		}
378244541Sbrooks		/* skip lines that are too big */
379244541Sbrooks		if (!strchr(pwline, '\n')) {
380244541Sbrooks			int ch;
381244541Sbrooks
382244541Sbrooks			while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
383244541Sbrooks				;
384244541Sbrooks			continue;
385244541Sbrooks		}
386256687Sbrooks		/* skip comments */
387256687Sbrooks		if (pwline[0] == '#')
388256687Sbrooks			continue;
389244541Sbrooks		if (pwmatchline(search, uid, name))
390244541Sbrooks			return 1;
391244541Sbrooks	}
392244541Sbrooks	/* NOTREACHED */
393244541Sbrooks}
394244541Sbrooks
395244541Sbrooksstatic int
396244541Sbrookspwmatchline(int search, uid_t uid, const char *name)
397244541Sbrooks{
398244541Sbrooks	unsigned long	id;
399244541Sbrooks	char		*cp, *bp, *ep;
400244541Sbrooks
401244541Sbrooks	/* name may be NULL if search is nonzero */
402244541Sbrooks
403244541Sbrooks	bp = pwline;
404244541Sbrooks	memset(&_pw_passwd, 0, sizeof(_pw_passwd));
405244541Sbrooks	_pw_passwd.pw_name = strsep(&bp, ":\n");		/* name */
406244541Sbrooks	if (search && name && strcmp(_pw_passwd.pw_name, name))
407244541Sbrooks		return 0;
408244541Sbrooks
409244541Sbrooks	_pw_passwd.pw_passwd = strsep(&bp, ":\n");		/* passwd */
410244541Sbrooks
411244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))				/* uid */
412244541Sbrooks		return 0;
413244541Sbrooks	id = strtoul(cp, &ep, 10);
414244541Sbrooks	if (id > UID_MAX || *ep != '\0')
415244541Sbrooks		return 0;
416244541Sbrooks	_pw_passwd.pw_uid = (uid_t)id;
417244541Sbrooks	if (search && name == NULL && _pw_passwd.pw_uid != uid)
418244541Sbrooks		return 0;
419244541Sbrooks
420244541Sbrooks	if (!(cp = strsep(&bp, ":\n")))				/* gid */
421244541Sbrooks		return 0;
422244541Sbrooks	id = strtoul(cp, &ep, 10);
423244541Sbrooks	if (id > GID_MAX || *ep != '\0')
424244541Sbrooks		return 0;
425244541Sbrooks	_pw_passwd.pw_gid = (gid_t)id;
426244541Sbrooks
427244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* class */
428244541Sbrooks		return 0;
429244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* change */
430244541Sbrooks		return 0;
431244541Sbrooks	if (!(ep = strsep(&bp, ":")))				/* expire */
432244541Sbrooks		return 0;
433244541Sbrooks
434244541Sbrooks	if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))	/* gecos */
435244541Sbrooks		return 0;
436244541Sbrooks	if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))		/* directory */
437244541Sbrooks		return 0;
438244541Sbrooks	if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))	/* shell */
439244541Sbrooks		return 0;
440244541Sbrooks
441244541Sbrooks	if (strchr(bp, ':') != NULL)
442244541Sbrooks		return 0;
443244541Sbrooks
444244541Sbrooks	return 1;
445244541Sbrooks}
446244541Sbrooks
447