1*2fe8fb19SBen Gras /* $NetBSD: pwcache.c,v 1.31 2010/03/23 20:28:59 drochner Exp $ */
2*2fe8fb19SBen Gras
3*2fe8fb19SBen Gras /*-
4*2fe8fb19SBen Gras * Copyright (c) 1992 Keith Muller.
5*2fe8fb19SBen Gras * Copyright (c) 1992, 1993
6*2fe8fb19SBen Gras * The Regents of the University of California. All rights reserved.
7*2fe8fb19SBen Gras *
8*2fe8fb19SBen Gras * This code is derived from software contributed to Berkeley by
9*2fe8fb19SBen Gras * Keith Muller of the University of California, San Diego.
10*2fe8fb19SBen Gras *
11*2fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
12*2fe8fb19SBen Gras * modification, are permitted provided that the following conditions
13*2fe8fb19SBen Gras * are met:
14*2fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
15*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
16*2fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
17*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
18*2fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
19*2fe8fb19SBen Gras * 3. Neither the name of the University nor the names of its contributors
20*2fe8fb19SBen Gras * may be used to endorse or promote products derived from this software
21*2fe8fb19SBen Gras * without specific prior written permission.
22*2fe8fb19SBen Gras *
23*2fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24*2fe8fb19SBen Gras * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*2fe8fb19SBen Gras * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*2fe8fb19SBen Gras * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27*2fe8fb19SBen Gras * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*2fe8fb19SBen Gras * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*2fe8fb19SBen Gras * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*2fe8fb19SBen Gras * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*2fe8fb19SBen Gras * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*2fe8fb19SBen Gras * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*2fe8fb19SBen Gras * SUCH DAMAGE.
34*2fe8fb19SBen Gras */
35*2fe8fb19SBen Gras
36*2fe8fb19SBen Gras /*-
37*2fe8fb19SBen Gras * Copyright (c) 2002 The NetBSD Foundation, Inc.
38*2fe8fb19SBen Gras * All rights reserved.
39*2fe8fb19SBen Gras *
40*2fe8fb19SBen Gras * Redistribution and use in source and binary forms, with or without
41*2fe8fb19SBen Gras * modification, are permitted provided that the following conditions
42*2fe8fb19SBen Gras * are met:
43*2fe8fb19SBen Gras * 1. Redistributions of source code must retain the above copyright
44*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer.
45*2fe8fb19SBen Gras * 2. Redistributions in binary form must reproduce the above copyright
46*2fe8fb19SBen Gras * notice, this list of conditions and the following disclaimer in the
47*2fe8fb19SBen Gras * documentation and/or other materials provided with the distribution.
48*2fe8fb19SBen Gras *
49*2fe8fb19SBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
50*2fe8fb19SBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
51*2fe8fb19SBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52*2fe8fb19SBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
53*2fe8fb19SBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54*2fe8fb19SBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55*2fe8fb19SBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56*2fe8fb19SBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57*2fe8fb19SBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58*2fe8fb19SBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59*2fe8fb19SBen Gras * POSSIBILITY OF SUCH DAMAGE.
60*2fe8fb19SBen Gras */
61*2fe8fb19SBen Gras
62*2fe8fb19SBen Gras #if HAVE_NBTOOL_CONFIG_H
63*2fe8fb19SBen Gras #include "nbtool_config.h"
64*2fe8fb19SBen Gras /*
65*2fe8fb19SBen Gras * XXX Undefine the renames of these functions so that we don't
66*2fe8fb19SBen Gras * XXX rename the versions found in the host's <pwd.h> by mistake!
67*2fe8fb19SBen Gras */
68*2fe8fb19SBen Gras #undef group_from_gid
69*2fe8fb19SBen Gras #undef user_from_uid
70*2fe8fb19SBen Gras #endif
71*2fe8fb19SBen Gras
72*2fe8fb19SBen Gras #include <sys/cdefs.h>
73*2fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
74*2fe8fb19SBen Gras #if 0
75*2fe8fb19SBen Gras static char sccsid[] = "@(#)cache.c 8.1 (Berkeley) 5/31/93";
76*2fe8fb19SBen Gras #else
77*2fe8fb19SBen Gras __RCSID("$NetBSD: pwcache.c,v 1.31 2010/03/23 20:28:59 drochner Exp $");
78*2fe8fb19SBen Gras #endif
79*2fe8fb19SBen Gras #endif /* LIBC_SCCS and not lint */
80*2fe8fb19SBen Gras
81*2fe8fb19SBen Gras #include "namespace.h"
82*2fe8fb19SBen Gras
83*2fe8fb19SBen Gras #include <sys/types.h>
84*2fe8fb19SBen Gras #include <sys/param.h>
85*2fe8fb19SBen Gras
86*2fe8fb19SBen Gras #include <assert.h>
87*2fe8fb19SBen Gras #include <grp.h>
88*2fe8fb19SBen Gras #include <pwd.h>
89*2fe8fb19SBen Gras #include <stdio.h>
90*2fe8fb19SBen Gras #include <stdlib.h>
91*2fe8fb19SBen Gras #include <string.h>
92*2fe8fb19SBen Gras #include <unistd.h>
93*2fe8fb19SBen Gras
94*2fe8fb19SBen Gras #if HAVE_NBTOOL_CONFIG_H
95*2fe8fb19SBen Gras /* XXX Now, re-apply the renaming that we undid above. */
96*2fe8fb19SBen Gras #define group_from_gid __nbcompat_group_from_gid
97*2fe8fb19SBen Gras #define user_from_uid __nbcompat_user_from_uid
98*2fe8fb19SBen Gras #endif
99*2fe8fb19SBen Gras
100*2fe8fb19SBen Gras #ifdef __weak_alias
101*2fe8fb19SBen Gras __weak_alias(user_from_uid,_user_from_uid)
102*2fe8fb19SBen Gras __weak_alias(group_from_gid,_group_from_gid)
103*2fe8fb19SBen Gras __weak_alias(pwcache_groupdb,_pwcache_groupdb)
104*2fe8fb19SBen Gras #endif
105*2fe8fb19SBen Gras
106*2fe8fb19SBen Gras #if !HAVE_PWCACHE_USERDB || HAVE_NBTOOL_CONFIG_H
107*2fe8fb19SBen Gras #include "pwcache.h"
108*2fe8fb19SBen Gras
109*2fe8fb19SBen Gras /*
110*2fe8fb19SBen Gras * routines that control user, group, uid and gid caches (for the archive
111*2fe8fb19SBen Gras * member print routine).
112*2fe8fb19SBen Gras * IMPORTANT:
113*2fe8fb19SBen Gras * these routines cache BOTH hits and misses, a major performance improvement
114*2fe8fb19SBen Gras */
115*2fe8fb19SBen Gras
116*2fe8fb19SBen Gras /*
117*2fe8fb19SBen Gras * function pointers to various name lookup routines.
118*2fe8fb19SBen Gras * these may be changed as necessary.
119*2fe8fb19SBen Gras */
120*2fe8fb19SBen Gras static int (*_pwcache_setgroupent)(int) = setgroupent;
121*2fe8fb19SBen Gras static void (*_pwcache_endgrent)(void) = endgrent;
122*2fe8fb19SBen Gras static struct group * (*_pwcache_getgrnam)(const char *) = getgrnam;
123*2fe8fb19SBen Gras static struct group * (*_pwcache_getgrgid)(gid_t) = getgrgid;
124*2fe8fb19SBen Gras static int (*_pwcache_setpassent)(int) = setpassent;
125*2fe8fb19SBen Gras static void (*_pwcache_endpwent)(void) = endpwent;
126*2fe8fb19SBen Gras static struct passwd * (*_pwcache_getpwnam)(const char *) = getpwnam;
127*2fe8fb19SBen Gras static struct passwd * (*_pwcache_getpwuid)(uid_t) = getpwuid;
128*2fe8fb19SBen Gras
129*2fe8fb19SBen Gras /*
130*2fe8fb19SBen Gras * internal state
131*2fe8fb19SBen Gras */
132*2fe8fb19SBen Gras static int pwopn; /* is password file open */
133*2fe8fb19SBen Gras static int gropn; /* is group file open */
134*2fe8fb19SBen Gras static UIDC **uidtb; /* uid to name cache */
135*2fe8fb19SBen Gras static GIDC **gidtb; /* gid to name cache */
136*2fe8fb19SBen Gras static UIDC **usrtb; /* user name to uid cache */
137*2fe8fb19SBen Gras static GIDC **grptb; /* group name to gid cache */
138*2fe8fb19SBen Gras
139*2fe8fb19SBen Gras static int uidtb_fail; /* uidtb_start() failed ? */
140*2fe8fb19SBen Gras static int gidtb_fail; /* gidtb_start() failed ? */
141*2fe8fb19SBen Gras static int usrtb_fail; /* usrtb_start() failed ? */
142*2fe8fb19SBen Gras static int grptb_fail; /* grptb_start() failed ? */
143*2fe8fb19SBen Gras
144*2fe8fb19SBen Gras
145*2fe8fb19SBen Gras static u_int st_hash(const char *, size_t, int);
146*2fe8fb19SBen Gras static int uidtb_start(void);
147*2fe8fb19SBen Gras static int gidtb_start(void);
148*2fe8fb19SBen Gras static int usrtb_start(void);
149*2fe8fb19SBen Gras static int grptb_start(void);
150*2fe8fb19SBen Gras
151*2fe8fb19SBen Gras
152*2fe8fb19SBen Gras static u_int
st_hash(const char * name,size_t len,int tabsz)153*2fe8fb19SBen Gras st_hash(const char *name, size_t len, int tabsz)
154*2fe8fb19SBen Gras {
155*2fe8fb19SBen Gras u_int key = 0;
156*2fe8fb19SBen Gras
157*2fe8fb19SBen Gras _DIAGASSERT(name != NULL);
158*2fe8fb19SBen Gras
159*2fe8fb19SBen Gras while (len--) {
160*2fe8fb19SBen Gras key += *name++;
161*2fe8fb19SBen Gras key = (key << 8) | (key >> 24);
162*2fe8fb19SBen Gras }
163*2fe8fb19SBen Gras
164*2fe8fb19SBen Gras return (key % tabsz);
165*2fe8fb19SBen Gras }
166*2fe8fb19SBen Gras
167*2fe8fb19SBen Gras /*
168*2fe8fb19SBen Gras * uidtb_start
169*2fe8fb19SBen Gras * creates an an empty uidtb
170*2fe8fb19SBen Gras * Return:
171*2fe8fb19SBen Gras * 0 if ok, -1 otherwise
172*2fe8fb19SBen Gras */
173*2fe8fb19SBen Gras static int
uidtb_start(void)174*2fe8fb19SBen Gras uidtb_start(void)
175*2fe8fb19SBen Gras {
176*2fe8fb19SBen Gras
177*2fe8fb19SBen Gras if (uidtb != NULL)
178*2fe8fb19SBen Gras return (0);
179*2fe8fb19SBen Gras if (uidtb_fail)
180*2fe8fb19SBen Gras return (-1);
181*2fe8fb19SBen Gras if ((uidtb = (UIDC **)calloc(UID_SZ, sizeof(UIDC *))) == NULL) {
182*2fe8fb19SBen Gras ++uidtb_fail;
183*2fe8fb19SBen Gras return (-1);
184*2fe8fb19SBen Gras }
185*2fe8fb19SBen Gras return (0);
186*2fe8fb19SBen Gras }
187*2fe8fb19SBen Gras
188*2fe8fb19SBen Gras /*
189*2fe8fb19SBen Gras * gidtb_start
190*2fe8fb19SBen Gras * creates an an empty gidtb
191*2fe8fb19SBen Gras * Return:
192*2fe8fb19SBen Gras * 0 if ok, -1 otherwise
193*2fe8fb19SBen Gras */
194*2fe8fb19SBen Gras static int
gidtb_start(void)195*2fe8fb19SBen Gras gidtb_start(void)
196*2fe8fb19SBen Gras {
197*2fe8fb19SBen Gras
198*2fe8fb19SBen Gras if (gidtb != NULL)
199*2fe8fb19SBen Gras return (0);
200*2fe8fb19SBen Gras if (gidtb_fail)
201*2fe8fb19SBen Gras return (-1);
202*2fe8fb19SBen Gras if ((gidtb = (GIDC **)calloc(GID_SZ, sizeof(GIDC *))) == NULL) {
203*2fe8fb19SBen Gras ++gidtb_fail;
204*2fe8fb19SBen Gras return (-1);
205*2fe8fb19SBen Gras }
206*2fe8fb19SBen Gras return (0);
207*2fe8fb19SBen Gras }
208*2fe8fb19SBen Gras
209*2fe8fb19SBen Gras /*
210*2fe8fb19SBen Gras * usrtb_start
211*2fe8fb19SBen Gras * creates an an empty usrtb
212*2fe8fb19SBen Gras * Return:
213*2fe8fb19SBen Gras * 0 if ok, -1 otherwise
214*2fe8fb19SBen Gras */
215*2fe8fb19SBen Gras static int
usrtb_start(void)216*2fe8fb19SBen Gras usrtb_start(void)
217*2fe8fb19SBen Gras {
218*2fe8fb19SBen Gras
219*2fe8fb19SBen Gras if (usrtb != NULL)
220*2fe8fb19SBen Gras return (0);
221*2fe8fb19SBen Gras if (usrtb_fail)
222*2fe8fb19SBen Gras return (-1);
223*2fe8fb19SBen Gras if ((usrtb = (UIDC **)calloc(UNM_SZ, sizeof(UIDC *))) == NULL) {
224*2fe8fb19SBen Gras ++usrtb_fail;
225*2fe8fb19SBen Gras return (-1);
226*2fe8fb19SBen Gras }
227*2fe8fb19SBen Gras return (0);
228*2fe8fb19SBen Gras }
229*2fe8fb19SBen Gras
230*2fe8fb19SBen Gras /*
231*2fe8fb19SBen Gras * grptb_start
232*2fe8fb19SBen Gras * creates an an empty grptb
233*2fe8fb19SBen Gras * Return:
234*2fe8fb19SBen Gras * 0 if ok, -1 otherwise
235*2fe8fb19SBen Gras */
236*2fe8fb19SBen Gras static int
grptb_start(void)237*2fe8fb19SBen Gras grptb_start(void)
238*2fe8fb19SBen Gras {
239*2fe8fb19SBen Gras
240*2fe8fb19SBen Gras if (grptb != NULL)
241*2fe8fb19SBen Gras return (0);
242*2fe8fb19SBen Gras if (grptb_fail)
243*2fe8fb19SBen Gras return (-1);
244*2fe8fb19SBen Gras if ((grptb = (GIDC **)calloc(GNM_SZ, sizeof(GIDC *))) == NULL) {
245*2fe8fb19SBen Gras ++grptb_fail;
246*2fe8fb19SBen Gras return (-1);
247*2fe8fb19SBen Gras }
248*2fe8fb19SBen Gras return (0);
249*2fe8fb19SBen Gras }
250*2fe8fb19SBen Gras
251*2fe8fb19SBen Gras /*
252*2fe8fb19SBen Gras * user_from_uid()
253*2fe8fb19SBen Gras * caches the name (if any) for the uid. If noname clear, we always
254*2fe8fb19SBen Gras * return the stored name (if valid or invalid match).
255*2fe8fb19SBen Gras * We use a simple hash table.
256*2fe8fb19SBen Gras * Return
257*2fe8fb19SBen Gras * Pointer to stored name (or a empty string)
258*2fe8fb19SBen Gras */
259*2fe8fb19SBen Gras const char *
user_from_uid(uid_t uid,int noname)260*2fe8fb19SBen Gras user_from_uid(uid_t uid, int noname)
261*2fe8fb19SBen Gras {
262*2fe8fb19SBen Gras struct passwd *pw;
263*2fe8fb19SBen Gras UIDC *ptr, **pptr;
264*2fe8fb19SBen Gras
265*2fe8fb19SBen Gras if ((uidtb == NULL) && (uidtb_start() < 0))
266*2fe8fb19SBen Gras return (NULL);
267*2fe8fb19SBen Gras
268*2fe8fb19SBen Gras /*
269*2fe8fb19SBen Gras * see if we have this uid cached
270*2fe8fb19SBen Gras */
271*2fe8fb19SBen Gras pptr = uidtb + (uid % UID_SZ);
272*2fe8fb19SBen Gras ptr = *pptr;
273*2fe8fb19SBen Gras
274*2fe8fb19SBen Gras if ((ptr != NULL) && (ptr->valid > 0) && (ptr->uid == uid)) {
275*2fe8fb19SBen Gras /*
276*2fe8fb19SBen Gras * have an entry for this uid
277*2fe8fb19SBen Gras */
278*2fe8fb19SBen Gras if (!noname || (ptr->valid == VALID))
279*2fe8fb19SBen Gras return (ptr->name);
280*2fe8fb19SBen Gras return (NULL);
281*2fe8fb19SBen Gras }
282*2fe8fb19SBen Gras
283*2fe8fb19SBen Gras /*
284*2fe8fb19SBen Gras * No entry for this uid, we will add it
285*2fe8fb19SBen Gras */
286*2fe8fb19SBen Gras if (!pwopn) {
287*2fe8fb19SBen Gras if (_pwcache_setpassent != NULL)
288*2fe8fb19SBen Gras (*_pwcache_setpassent)(1);
289*2fe8fb19SBen Gras ++pwopn;
290*2fe8fb19SBen Gras }
291*2fe8fb19SBen Gras
292*2fe8fb19SBen Gras if (ptr == NULL)
293*2fe8fb19SBen Gras *pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
294*2fe8fb19SBen Gras
295*2fe8fb19SBen Gras if ((pw = (*_pwcache_getpwuid)(uid)) == NULL) {
296*2fe8fb19SBen Gras /*
297*2fe8fb19SBen Gras * no match for this uid in the local password file
298*2fe8fb19SBen Gras * a string that is the uid in numeric format
299*2fe8fb19SBen Gras */
300*2fe8fb19SBen Gras if (ptr == NULL)
301*2fe8fb19SBen Gras return (NULL);
302*2fe8fb19SBen Gras ptr->uid = uid;
303*2fe8fb19SBen Gras (void)snprintf(ptr->name, UNMLEN, "%lu", (long) uid);
304*2fe8fb19SBen Gras ptr->valid = INVALID;
305*2fe8fb19SBen Gras if (noname)
306*2fe8fb19SBen Gras return (NULL);
307*2fe8fb19SBen Gras } else {
308*2fe8fb19SBen Gras /*
309*2fe8fb19SBen Gras * there is an entry for this uid in the password file
310*2fe8fb19SBen Gras */
311*2fe8fb19SBen Gras if (ptr == NULL)
312*2fe8fb19SBen Gras return (pw->pw_name);
313*2fe8fb19SBen Gras ptr->uid = uid;
314*2fe8fb19SBen Gras (void)strlcpy(ptr->name, pw->pw_name, UNMLEN);
315*2fe8fb19SBen Gras ptr->valid = VALID;
316*2fe8fb19SBen Gras }
317*2fe8fb19SBen Gras return (ptr->name);
318*2fe8fb19SBen Gras }
319*2fe8fb19SBen Gras
320*2fe8fb19SBen Gras /*
321*2fe8fb19SBen Gras * group_from_gid()
322*2fe8fb19SBen Gras * caches the name (if any) for the gid. If noname clear, we always
323*2fe8fb19SBen Gras * return the stored name (if valid or invalid match).
324*2fe8fb19SBen Gras * We use a simple hash table.
325*2fe8fb19SBen Gras * Return
326*2fe8fb19SBen Gras * Pointer to stored name (or a empty string)
327*2fe8fb19SBen Gras */
328*2fe8fb19SBen Gras const char *
group_from_gid(gid_t gid,int noname)329*2fe8fb19SBen Gras group_from_gid(gid_t gid, int noname)
330*2fe8fb19SBen Gras {
331*2fe8fb19SBen Gras struct group *gr;
332*2fe8fb19SBen Gras GIDC *ptr, **pptr;
333*2fe8fb19SBen Gras
334*2fe8fb19SBen Gras if ((gidtb == NULL) && (gidtb_start() < 0))
335*2fe8fb19SBen Gras return (NULL);
336*2fe8fb19SBen Gras
337*2fe8fb19SBen Gras /*
338*2fe8fb19SBen Gras * see if we have this gid cached
339*2fe8fb19SBen Gras */
340*2fe8fb19SBen Gras pptr = gidtb + (gid % GID_SZ);
341*2fe8fb19SBen Gras ptr = *pptr;
342*2fe8fb19SBen Gras
343*2fe8fb19SBen Gras if ((ptr != NULL) && (ptr->valid > 0) && (ptr->gid == gid)) {
344*2fe8fb19SBen Gras /*
345*2fe8fb19SBen Gras * have an entry for this gid
346*2fe8fb19SBen Gras */
347*2fe8fb19SBen Gras if (!noname || (ptr->valid == VALID))
348*2fe8fb19SBen Gras return (ptr->name);
349*2fe8fb19SBen Gras return (NULL);
350*2fe8fb19SBen Gras }
351*2fe8fb19SBen Gras
352*2fe8fb19SBen Gras /*
353*2fe8fb19SBen Gras * No entry for this gid, we will add it
354*2fe8fb19SBen Gras */
355*2fe8fb19SBen Gras if (!gropn) {
356*2fe8fb19SBen Gras if (_pwcache_setgroupent != NULL)
357*2fe8fb19SBen Gras (*_pwcache_setgroupent)(1);
358*2fe8fb19SBen Gras ++gropn;
359*2fe8fb19SBen Gras }
360*2fe8fb19SBen Gras
361*2fe8fb19SBen Gras if (ptr == NULL)
362*2fe8fb19SBen Gras *pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
363*2fe8fb19SBen Gras
364*2fe8fb19SBen Gras if ((gr = (*_pwcache_getgrgid)(gid)) == NULL) {
365*2fe8fb19SBen Gras /*
366*2fe8fb19SBen Gras * no match for this gid in the local group file, put in
367*2fe8fb19SBen Gras * a string that is the gid in numberic format
368*2fe8fb19SBen Gras */
369*2fe8fb19SBen Gras if (ptr == NULL)
370*2fe8fb19SBen Gras return (NULL);
371*2fe8fb19SBen Gras ptr->gid = gid;
372*2fe8fb19SBen Gras (void)snprintf(ptr->name, GNMLEN, "%lu", (long) gid);
373*2fe8fb19SBen Gras ptr->valid = INVALID;
374*2fe8fb19SBen Gras if (noname)
375*2fe8fb19SBen Gras return (NULL);
376*2fe8fb19SBen Gras } else {
377*2fe8fb19SBen Gras /*
378*2fe8fb19SBen Gras * there is an entry for this group in the group file
379*2fe8fb19SBen Gras */
380*2fe8fb19SBen Gras if (ptr == NULL)
381*2fe8fb19SBen Gras return (gr->gr_name);
382*2fe8fb19SBen Gras ptr->gid = gid;
383*2fe8fb19SBen Gras (void)strlcpy(ptr->name, gr->gr_name, GNMLEN);
384*2fe8fb19SBen Gras ptr->valid = VALID;
385*2fe8fb19SBen Gras }
386*2fe8fb19SBen Gras return (ptr->name);
387*2fe8fb19SBen Gras }
388*2fe8fb19SBen Gras
389*2fe8fb19SBen Gras /*
390*2fe8fb19SBen Gras * uid_from_user()
391*2fe8fb19SBen Gras * caches the uid for a given user name. We use a simple hash table.
392*2fe8fb19SBen Gras * Return
393*2fe8fb19SBen Gras * the uid (if any) for a user name, or a -1 if no match can be found
394*2fe8fb19SBen Gras */
395*2fe8fb19SBen Gras int
uid_from_user(const char * name,uid_t * uid)396*2fe8fb19SBen Gras uid_from_user(const char *name, uid_t *uid)
397*2fe8fb19SBen Gras {
398*2fe8fb19SBen Gras struct passwd *pw;
399*2fe8fb19SBen Gras UIDC *ptr, **pptr;
400*2fe8fb19SBen Gras size_t namelen;
401*2fe8fb19SBen Gras
402*2fe8fb19SBen Gras /*
403*2fe8fb19SBen Gras * return -1 for mangled names
404*2fe8fb19SBen Gras */
405*2fe8fb19SBen Gras if (name == NULL || ((namelen = strlen(name)) == 0))
406*2fe8fb19SBen Gras return (-1);
407*2fe8fb19SBen Gras if ((usrtb == NULL) && (usrtb_start() < 0))
408*2fe8fb19SBen Gras return (-1);
409*2fe8fb19SBen Gras
410*2fe8fb19SBen Gras /*
411*2fe8fb19SBen Gras * look up in hash table, if found and valid return the uid,
412*2fe8fb19SBen Gras * if found and invalid, return a -1
413*2fe8fb19SBen Gras */
414*2fe8fb19SBen Gras pptr = usrtb + st_hash(name, namelen, UNM_SZ);
415*2fe8fb19SBen Gras ptr = *pptr;
416*2fe8fb19SBen Gras
417*2fe8fb19SBen Gras if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
418*2fe8fb19SBen Gras if (ptr->valid == INVALID)
419*2fe8fb19SBen Gras return (-1);
420*2fe8fb19SBen Gras *uid = ptr->uid;
421*2fe8fb19SBen Gras return (0);
422*2fe8fb19SBen Gras }
423*2fe8fb19SBen Gras
424*2fe8fb19SBen Gras if (!pwopn) {
425*2fe8fb19SBen Gras if (_pwcache_setpassent != NULL)
426*2fe8fb19SBen Gras (*_pwcache_setpassent)(1);
427*2fe8fb19SBen Gras ++pwopn;
428*2fe8fb19SBen Gras }
429*2fe8fb19SBen Gras
430*2fe8fb19SBen Gras if (ptr == NULL)
431*2fe8fb19SBen Gras *pptr = ptr = (UIDC *)malloc(sizeof(UIDC));
432*2fe8fb19SBen Gras
433*2fe8fb19SBen Gras /*
434*2fe8fb19SBen Gras * no match, look it up, if no match store it as an invalid entry,
435*2fe8fb19SBen Gras * or store the matching uid
436*2fe8fb19SBen Gras */
437*2fe8fb19SBen Gras if (ptr == NULL) {
438*2fe8fb19SBen Gras if ((pw = (*_pwcache_getpwnam)(name)) == NULL)
439*2fe8fb19SBen Gras return (-1);
440*2fe8fb19SBen Gras *uid = pw->pw_uid;
441*2fe8fb19SBen Gras return (0);
442*2fe8fb19SBen Gras }
443*2fe8fb19SBen Gras (void)strlcpy(ptr->name, name, UNMLEN);
444*2fe8fb19SBen Gras if ((pw = (*_pwcache_getpwnam)(name)) == NULL) {
445*2fe8fb19SBen Gras ptr->valid = INVALID;
446*2fe8fb19SBen Gras return (-1);
447*2fe8fb19SBen Gras }
448*2fe8fb19SBen Gras ptr->valid = VALID;
449*2fe8fb19SBen Gras *uid = ptr->uid = pw->pw_uid;
450*2fe8fb19SBen Gras return (0);
451*2fe8fb19SBen Gras }
452*2fe8fb19SBen Gras
453*2fe8fb19SBen Gras /*
454*2fe8fb19SBen Gras * gid_from_group()
455*2fe8fb19SBen Gras * caches the gid for a given group name. We use a simple hash table.
456*2fe8fb19SBen Gras * Return
457*2fe8fb19SBen Gras * the gid (if any) for a group name, or a -1 if no match can be found
458*2fe8fb19SBen Gras */
459*2fe8fb19SBen Gras int
gid_from_group(const char * name,gid_t * gid)460*2fe8fb19SBen Gras gid_from_group(const char *name, gid_t *gid)
461*2fe8fb19SBen Gras {
462*2fe8fb19SBen Gras struct group *gr;
463*2fe8fb19SBen Gras GIDC *ptr, **pptr;
464*2fe8fb19SBen Gras size_t namelen;
465*2fe8fb19SBen Gras
466*2fe8fb19SBen Gras /*
467*2fe8fb19SBen Gras * return -1 for mangled names
468*2fe8fb19SBen Gras */
469*2fe8fb19SBen Gras if (name == NULL || ((namelen = strlen(name)) == 0))
470*2fe8fb19SBen Gras return (-1);
471*2fe8fb19SBen Gras if ((grptb == NULL) && (grptb_start() < 0))
472*2fe8fb19SBen Gras return (-1);
473*2fe8fb19SBen Gras
474*2fe8fb19SBen Gras /*
475*2fe8fb19SBen Gras * look up in hash table, if found and valid return the uid,
476*2fe8fb19SBen Gras * if found and invalid, return a -1
477*2fe8fb19SBen Gras */
478*2fe8fb19SBen Gras pptr = grptb + st_hash(name, namelen, GID_SZ);
479*2fe8fb19SBen Gras ptr = *pptr;
480*2fe8fb19SBen Gras
481*2fe8fb19SBen Gras if ((ptr != NULL) && (ptr->valid > 0) && !strcmp(name, ptr->name)) {
482*2fe8fb19SBen Gras if (ptr->valid == INVALID)
483*2fe8fb19SBen Gras return (-1);
484*2fe8fb19SBen Gras *gid = ptr->gid;
485*2fe8fb19SBen Gras return (0);
486*2fe8fb19SBen Gras }
487*2fe8fb19SBen Gras
488*2fe8fb19SBen Gras if (!gropn) {
489*2fe8fb19SBen Gras if (_pwcache_setgroupent != NULL)
490*2fe8fb19SBen Gras (*_pwcache_setgroupent)(1);
491*2fe8fb19SBen Gras ++gropn;
492*2fe8fb19SBen Gras }
493*2fe8fb19SBen Gras
494*2fe8fb19SBen Gras if (ptr == NULL)
495*2fe8fb19SBen Gras *pptr = ptr = (GIDC *)malloc(sizeof(GIDC));
496*2fe8fb19SBen Gras
497*2fe8fb19SBen Gras /*
498*2fe8fb19SBen Gras * no match, look it up, if no match store it as an invalid entry,
499*2fe8fb19SBen Gras * or store the matching gid
500*2fe8fb19SBen Gras */
501*2fe8fb19SBen Gras if (ptr == NULL) {
502*2fe8fb19SBen Gras if ((gr = (*_pwcache_getgrnam)(name)) == NULL)
503*2fe8fb19SBen Gras return (-1);
504*2fe8fb19SBen Gras *gid = gr->gr_gid;
505*2fe8fb19SBen Gras return (0);
506*2fe8fb19SBen Gras }
507*2fe8fb19SBen Gras
508*2fe8fb19SBen Gras (void)strlcpy(ptr->name, name, GNMLEN);
509*2fe8fb19SBen Gras if ((gr = (*_pwcache_getgrnam)(name)) == NULL) {
510*2fe8fb19SBen Gras ptr->valid = INVALID;
511*2fe8fb19SBen Gras return (-1);
512*2fe8fb19SBen Gras }
513*2fe8fb19SBen Gras ptr->valid = VALID;
514*2fe8fb19SBen Gras *gid = ptr->gid = gr->gr_gid;
515*2fe8fb19SBen Gras return (0);
516*2fe8fb19SBen Gras }
517*2fe8fb19SBen Gras
518*2fe8fb19SBen Gras #define FLUSHTB(arr, len, fail) \
519*2fe8fb19SBen Gras do { \
520*2fe8fb19SBen Gras if (arr != NULL) { \
521*2fe8fb19SBen Gras for (i = 0; i < len; i++) \
522*2fe8fb19SBen Gras if (arr[i] != NULL) \
523*2fe8fb19SBen Gras free(arr[i]); \
524*2fe8fb19SBen Gras arr = NULL; \
525*2fe8fb19SBen Gras } \
526*2fe8fb19SBen Gras fail = 0; \
527*2fe8fb19SBen Gras } while (/* CONSTCOND */0);
528*2fe8fb19SBen Gras
529*2fe8fb19SBen Gras int
pwcache_userdb(int (* a_setpassent)(int),void (* a_endpwent)(void),struct passwd * (* a_getpwnam)(const char *),struct passwd * (* a_getpwuid)(uid_t))530*2fe8fb19SBen Gras pwcache_userdb(
531*2fe8fb19SBen Gras int (*a_setpassent)(int),
532*2fe8fb19SBen Gras void (*a_endpwent)(void),
533*2fe8fb19SBen Gras struct passwd * (*a_getpwnam)(const char *),
534*2fe8fb19SBen Gras struct passwd * (*a_getpwuid)(uid_t))
535*2fe8fb19SBen Gras {
536*2fe8fb19SBen Gras int i;
537*2fe8fb19SBen Gras
538*2fe8fb19SBen Gras /* a_setpassent and a_endpwent may be NULL */
539*2fe8fb19SBen Gras if (a_getpwnam == NULL || a_getpwuid == NULL)
540*2fe8fb19SBen Gras return (-1);
541*2fe8fb19SBen Gras
542*2fe8fb19SBen Gras if (_pwcache_endpwent != NULL)
543*2fe8fb19SBen Gras (*_pwcache_endpwent)();
544*2fe8fb19SBen Gras FLUSHTB(uidtb, UID_SZ, uidtb_fail);
545*2fe8fb19SBen Gras FLUSHTB(usrtb, UNM_SZ, usrtb_fail);
546*2fe8fb19SBen Gras pwopn = 0;
547*2fe8fb19SBen Gras _pwcache_setpassent = a_setpassent;
548*2fe8fb19SBen Gras _pwcache_endpwent = a_endpwent;
549*2fe8fb19SBen Gras _pwcache_getpwnam = a_getpwnam;
550*2fe8fb19SBen Gras _pwcache_getpwuid = a_getpwuid;
551*2fe8fb19SBen Gras
552*2fe8fb19SBen Gras return (0);
553*2fe8fb19SBen Gras }
554*2fe8fb19SBen Gras
555*2fe8fb19SBen Gras int
pwcache_groupdb(int (* a_setgroupent)(int),void (* a_endgrent)(void),struct group * (* a_getgrnam)(const char *),struct group * (* a_getgrgid)(gid_t))556*2fe8fb19SBen Gras pwcache_groupdb(
557*2fe8fb19SBen Gras int (*a_setgroupent)(int),
558*2fe8fb19SBen Gras void (*a_endgrent)(void),
559*2fe8fb19SBen Gras struct group * (*a_getgrnam)(const char *),
560*2fe8fb19SBen Gras struct group * (*a_getgrgid)(gid_t))
561*2fe8fb19SBen Gras {
562*2fe8fb19SBen Gras int i;
563*2fe8fb19SBen Gras
564*2fe8fb19SBen Gras /* a_setgroupent and a_endgrent may be NULL */
565*2fe8fb19SBen Gras if (a_getgrnam == NULL || a_getgrgid == NULL)
566*2fe8fb19SBen Gras return (-1);
567*2fe8fb19SBen Gras
568*2fe8fb19SBen Gras if (_pwcache_endgrent != NULL)
569*2fe8fb19SBen Gras (*_pwcache_endgrent)();
570*2fe8fb19SBen Gras FLUSHTB(gidtb, GID_SZ, gidtb_fail);
571*2fe8fb19SBen Gras FLUSHTB(grptb, GNM_SZ, grptb_fail);
572*2fe8fb19SBen Gras gropn = 0;
573*2fe8fb19SBen Gras _pwcache_setgroupent = a_setgroupent;
574*2fe8fb19SBen Gras _pwcache_endgrent = a_endgrent;
575*2fe8fb19SBen Gras _pwcache_getgrnam = a_getgrnam;
576*2fe8fb19SBen Gras _pwcache_getgrgid = a_getgrgid;
577*2fe8fb19SBen Gras
578*2fe8fb19SBen Gras return (0);
579*2fe8fb19SBen Gras }
580*2fe8fb19SBen Gras
581*2fe8fb19SBen Gras
582*2fe8fb19SBen Gras #ifdef TEST_PWCACHE
583*2fe8fb19SBen Gras
584*2fe8fb19SBen Gras struct passwd *
test_getpwnam(const char * name)585*2fe8fb19SBen Gras test_getpwnam(const char *name)
586*2fe8fb19SBen Gras {
587*2fe8fb19SBen Gras static struct passwd foo;
588*2fe8fb19SBen Gras
589*2fe8fb19SBen Gras memset(&foo, 0, sizeof(foo));
590*2fe8fb19SBen Gras if (strcmp(name, "toor") == 0) {
591*2fe8fb19SBen Gras foo.pw_uid = 666;
592*2fe8fb19SBen Gras return &foo;
593*2fe8fb19SBen Gras }
594*2fe8fb19SBen Gras return (getpwnam(name));
595*2fe8fb19SBen Gras }
596*2fe8fb19SBen Gras
597*2fe8fb19SBen Gras int
main(int argc,char * argv[])598*2fe8fb19SBen Gras main(int argc, char *argv[])
599*2fe8fb19SBen Gras {
600*2fe8fb19SBen Gras uid_t u;
601*2fe8fb19SBen Gras int r, i;
602*2fe8fb19SBen Gras
603*2fe8fb19SBen Gras printf("pass 1 (default userdb)\n");
604*2fe8fb19SBen Gras for (i = 1; i < argc; i++) {
605*2fe8fb19SBen Gras printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n",
606*2fe8fb19SBen Gras i, pwopn, usrtb_fail, usrtb);
607*2fe8fb19SBen Gras r = uid_from_user(argv[i], &u);
608*2fe8fb19SBen Gras if (r == -1)
609*2fe8fb19SBen Gras printf(" uid_from_user %s: failed\n", argv[i]);
610*2fe8fb19SBen Gras else
611*2fe8fb19SBen Gras printf(" uid_from_user %s: %d\n", argv[i], u);
612*2fe8fb19SBen Gras }
613*2fe8fb19SBen Gras printf("pass 1 finish: pwopn %d usrtb_fail %d usrtb %p\n",
614*2fe8fb19SBen Gras pwopn, usrtb_fail, usrtb);
615*2fe8fb19SBen Gras
616*2fe8fb19SBen Gras puts("");
617*2fe8fb19SBen Gras printf("pass 2 (replacement userdb)\n");
618*2fe8fb19SBen Gras printf("pwcache_userdb returned %d\n",
619*2fe8fb19SBen Gras pwcache_userdb(setpassent, test_getpwnam, getpwuid));
620*2fe8fb19SBen Gras printf("pwopn %d usrtb_fail %d usrtb %p\n", pwopn, usrtb_fail, usrtb);
621*2fe8fb19SBen Gras
622*2fe8fb19SBen Gras for (i = 1; i < argc; i++) {
623*2fe8fb19SBen Gras printf("i: %d, pwopn %d usrtb_fail %d usrtb %p\n",
624*2fe8fb19SBen Gras i, pwopn, usrtb_fail, usrtb);
625*2fe8fb19SBen Gras u = -1;
626*2fe8fb19SBen Gras r = uid_from_user(argv[i], &u);
627*2fe8fb19SBen Gras if (r == -1)
628*2fe8fb19SBen Gras printf(" uid_from_user %s: failed\n", argv[i]);
629*2fe8fb19SBen Gras else
630*2fe8fb19SBen Gras printf(" uid_from_user %s: %d\n", argv[i], u);
631*2fe8fb19SBen Gras }
632*2fe8fb19SBen Gras printf("pass 2 finish: pwopn %d usrtb_fail %d usrtb %p\n",
633*2fe8fb19SBen Gras pwopn, usrtb_fail, usrtb);
634*2fe8fb19SBen Gras
635*2fe8fb19SBen Gras puts("");
636*2fe8fb19SBen Gras printf("pass 3 (null pointers)\n");
637*2fe8fb19SBen Gras printf("pwcache_userdb returned %d\n",
638*2fe8fb19SBen Gras pwcache_userdb(NULL, NULL, NULL));
639*2fe8fb19SBen Gras
640*2fe8fb19SBen Gras return (0);
641*2fe8fb19SBen Gras }
642*2fe8fb19SBen Gras #endif /* TEST_PWCACHE */
643*2fe8fb19SBen Gras #endif /* !HAVE_PWCACHE_USERDB */
644