]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - usr.sbin/makefs/getid.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / usr.sbin / makefs / getid.c
1 /*      $NetBSD: getid.c,v 1.5 2004/06/20 22:20:18 jmc 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  * 3. All advertising materials mentioning features or use of this software
50  *    must display the following acknowledgement:
51  *        This product includes software developed by the NetBSD
52  *        Foundation, Inc. and its contributors.
53  * 4. Neither the name of The NetBSD Foundation nor the names of its
54  *    contributors may be used to endorse or promote products derived
55  *    from this software without specific prior written permission.
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
58  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
59  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
60  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
61  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
62  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
63  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
64  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
65  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
66  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
67  * POSSIBILITY OF SUCH DAMAGE.
68  */
69
70 #include <sys/cdefs.h>
71 __FBSDID("$FreeBSD$");
72
73 #include <sys/param.h>
74
75 #include <grp.h>
76 #include <limits.h>
77 #include <pwd.h>
78 #include <stdlib.h>
79 #include <stdio.h>
80 #include <string.h>
81 #include <time.h>
82 #include <unistd.h>
83
84 #include "makefs.h"
85
86 #include "mtree.h"
87 #include "extern.h"
88
89 static  struct group *  gi_getgrnam(const char *);
90 static  struct group *  gi_getgrgid(gid_t);
91 static  int             gi_setgroupent(int);
92 static  void            gi_endgrent(void);
93 static  int             grstart(void);
94 static  int             grscan(int, gid_t, const char *);
95 static  int             grmatchline(int, gid_t, const char *);
96
97 static  struct passwd * gi_getpwnam(const char *);
98 static  struct passwd * gi_getpwuid(uid_t);
99 static  int             gi_setpassent(int);
100 static  void            gi_endpwent(void);
101 static  int             pwstart(void);
102 static  int             pwscan(int, uid_t, const char *);
103 static  int             pwmatchline(int, uid_t, const char *);
104
105 #define MAXGRP          200
106 #define MAXLINELENGTH   1024
107
108 static  FILE            *_gr_fp;
109 static  struct group    _gr_group;
110 static  int             _gr_stayopen;
111 static  int             _gr_filesdone;
112 static  FILE            *_pw_fp;
113 static  struct passwd   _pw_passwd;     /* password structure */
114 static  int             _pw_stayopen;   /* keep fd's open */
115 static  int             _pw_filesdone;
116
117 static  char            grfile[MAXPATHLEN];
118 static  char            pwfile[MAXPATHLEN];
119
120 static  char            *members[MAXGRP];
121 static  char            grline[MAXLINELENGTH];
122 static  char            pwline[MAXLINELENGTH];
123
124 int
125 setup_getid(const char *dir)
126 {
127         if (dir == NULL)
128                 return (0);
129
130                                 /* close existing databases */
131         gi_endgrent();
132         gi_endpwent();
133
134                                 /* build paths to new databases */
135         snprintf(grfile, sizeof(grfile), "%s/group", dir);
136         snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
137
138                                 /* try to open new databases */
139         if (!grstart() || !pwstart())
140                 return (0);
141
142                                 /* switch pwcache(3) lookup functions */
143         if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
144                             gi_getgrnam, gi_getgrgid) == -1
145             || pwcache_userdb(gi_setpassent, gi_endpwent,
146                             gi_getpwnam, gi_getpwuid) == -1)
147                 return (0);
148
149         return (1);
150 }
151
152
153 /*
154  * group lookup functions
155  */
156
157 static struct group *
158 gi_getgrnam(const char *name)
159 {
160         int rval;
161
162         if (!grstart())
163                 return NULL;
164         rval = grscan(1, 0, name);
165         if (!_gr_stayopen)
166                 endgrent();
167         return (rval) ? &_gr_group : NULL;
168 }
169
170 static struct group *
171 gi_getgrgid(gid_t gid)
172 {
173         int rval;
174
175         if (!grstart())
176                 return NULL;
177         rval = grscan(1, gid, NULL);
178         if (!_gr_stayopen)
179                 endgrent();
180         return (rval) ? &_gr_group : NULL;
181 }
182
183 static int
184 gi_setgroupent(int stayopen)
185 {
186
187         if (!grstart())
188                 return 0;
189         _gr_stayopen = stayopen;
190         return 1;
191 }
192
193 static void
194 gi_endgrent(void)
195 {
196
197         _gr_filesdone = 0;
198         if (_gr_fp) {
199                 (void)fclose(_gr_fp);
200                 _gr_fp = NULL;
201         }
202 }
203
204 static int
205 grstart(void)
206 {
207
208         _gr_filesdone = 0;
209         if (_gr_fp) {
210                 rewind(_gr_fp);
211                 return 1;
212         }
213         if (grfile[0] == '\0')                  /* sanity check */
214                 return 0;
215         return (_gr_fp = fopen(grfile, "r")) ? 1 : 0;
216 }
217
218
219 static int
220 grscan(int search, gid_t gid, const char *name)
221 {
222
223         if (_gr_filesdone)
224                 return 0;
225         for (;;) {
226                 if (!fgets(grline, sizeof(grline), _gr_fp)) {
227                         if (!search)
228                                 _gr_filesdone = 1;
229                         return 0;
230                 }
231                 /* skip lines that are too big */
232                 if (!strchr(grline, '\n')) {
233                         int ch;
234
235                         while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
236                                 ;
237                         continue;
238                 }
239                 if (grmatchline(search, gid, name))
240                         return 1;
241         }
242         /* NOTREACHED */
243 }
244
245 static int
246 grmatchline(int search, gid_t gid, const char *name)
247 {
248         unsigned long   id;
249         char            **m;
250         char            *cp, *bp, *ep;
251
252         /* name may be NULL if search is nonzero */
253
254         bp = grline;
255         memset(&_gr_group, 0, sizeof(_gr_group));
256         _gr_group.gr_name = strsep(&bp, ":\n");
257         if (search && name && strcmp(_gr_group.gr_name, name))
258                 return 0;
259         _gr_group.gr_passwd = strsep(&bp, ":\n");
260         if (!(cp = strsep(&bp, ":\n")))
261                 return 0;
262         id = strtoul(cp, &ep, 10);
263         if (id > GID_MAX || *ep != '\0')
264                 return 0;
265         _gr_group.gr_gid = (gid_t)id;
266         if (search && name == NULL && _gr_group.gr_gid != gid)
267                 return 0;
268         cp = NULL;
269         if (bp == NULL)
270                 return 0;
271         for (_gr_group.gr_mem = m = members;; bp++) {
272                 if (m == &members[MAXGRP - 1])
273                         break;
274                 if (*bp == ',') {
275                         if (cp) {
276                                 *bp = '\0';
277                                 *m++ = cp;
278                                 cp = NULL;
279                         }
280                 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
281                         if (cp) {
282                                 *bp = '\0';
283                                 *m++ = cp;
284                         }
285                         break;
286                 } else if (cp == NULL)
287                         cp = bp;
288         }
289         *m = NULL;
290         return 1;
291 }
292
293
294 /*
295  * user lookup functions
296  */
297
298 static struct passwd *
299 gi_getpwnam(const char *name)
300 {
301         int rval;
302
303         if (!pwstart())
304                 return NULL;
305         rval = pwscan(1, 0, name);
306         if (!_pw_stayopen)
307                 endpwent();
308         return (rval) ? &_pw_passwd : NULL;
309 }
310
311 static struct passwd *
312 gi_getpwuid(uid_t uid)
313 {
314         int rval;
315
316         if (!pwstart())
317                 return NULL;
318         rval = pwscan(1, uid, NULL);
319         if (!_pw_stayopen)
320                 endpwent();
321         return (rval) ? &_pw_passwd : NULL;
322 }
323
324 static int
325 gi_setpassent(int stayopen)
326 {
327
328         if (!pwstart())
329                 return 0;
330         _pw_stayopen = stayopen;
331         return 1;
332 }
333
334 static void
335 gi_endpwent(void)
336 {
337
338         _pw_filesdone = 0;
339         if (_pw_fp) {
340                 (void)fclose(_pw_fp);
341                 _pw_fp = NULL;
342         }
343 }
344
345 static int
346 pwstart(void)
347 {
348
349         _pw_filesdone = 0;
350         if (_pw_fp) {
351                 rewind(_pw_fp);
352                 return 1;
353         }
354         if (pwfile[0] == '\0')                  /* sanity check */
355                 return 0;
356         return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0;
357 }
358
359
360 static int
361 pwscan(int search, uid_t uid, const char *name)
362 {
363
364         if (_pw_filesdone)
365                 return 0;
366         for (;;) {
367                 if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
368                         if (!search)
369                                 _pw_filesdone = 1;
370                         return 0;
371                 }
372                 /* skip lines that are too big */
373                 if (!strchr(pwline, '\n')) {
374                         int ch;
375
376                         while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
377                                 ;
378                         continue;
379                 }
380                 if (pwmatchline(search, uid, name))
381                         return 1;
382         }
383         /* NOTREACHED */
384 }
385
386 static int
387 pwmatchline(int search, uid_t uid, const char *name)
388 {
389         unsigned long   id;
390         char            *cp, *bp, *ep;
391
392         /* name may be NULL if search is nonzero */
393
394         bp = pwline;
395         memset(&_pw_passwd, 0, sizeof(_pw_passwd));
396         _pw_passwd.pw_name = strsep(&bp, ":\n");                /* name */
397         if (search && name && strcmp(_pw_passwd.pw_name, name))
398                 return 0;
399
400         _pw_passwd.pw_passwd = strsep(&bp, ":\n");              /* passwd */
401
402         if (!(cp = strsep(&bp, ":\n")))                         /* uid */
403                 return 0;
404         id = strtoul(cp, &ep, 10);
405         if (id > UID_MAX || *ep != '\0')
406                 return 0;
407         _pw_passwd.pw_uid = (uid_t)id;
408         if (search && name == NULL && _pw_passwd.pw_uid != uid)
409                 return 0;
410
411         if (!(cp = strsep(&bp, ":\n")))                         /* gid */
412                 return 0;
413         id = strtoul(cp, &ep, 10);
414         if (id > GID_MAX || *ep != '\0')
415                 return 0;
416         _pw_passwd.pw_gid = (gid_t)id;
417
418         if (!(ep = strsep(&bp, ":")))                           /* class */
419                 return 0;
420         if (!(ep = strsep(&bp, ":")))                           /* change */
421                 return 0;
422         if (!(ep = strsep(&bp, ":")))                           /* expire */
423                 return 0;
424
425         if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))        /* gecos */
426                 return 0;
427         if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))          /* directory */
428                 return 0;
429         if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))        /* shell */
430                 return 0;
431
432         if (strchr(bp, ':') != NULL)
433                 return 0;
434
435         return 1;
436 }