]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - usr.sbin/makefs/getid.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.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  *
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/cdefs.h>
64 __FBSDID("$FreeBSD$");
65
66 #include <sys/param.h>
67
68 #include <grp.h>
69 #include <limits.h>
70 #include <pwd.h>
71 #include <stdlib.h>
72 #include <stdio.h>
73 #include <string.h>
74 #include <time.h>
75 #include <unistd.h>
76
77 #include "makefs.h"
78
79 #include "mtree.h"
80 #include "extern.h"
81
82 static  struct group *  gi_getgrnam(const char *);
83 static  struct group *  gi_getgrgid(gid_t);
84 static  int             gi_setgroupent(int);
85 static  void            gi_endgrent(void);
86 static  int             grstart(void);
87 static  int             grscan(int, gid_t, const char *);
88 static  int             grmatchline(int, gid_t, const char *);
89
90 static  struct passwd * gi_getpwnam(const char *);
91 static  struct passwd * gi_getpwuid(uid_t);
92 static  int             gi_setpassent(int);
93 static  void            gi_endpwent(void);
94 static  int             pwstart(void);
95 static  int             pwscan(int, uid_t, const char *);
96 static  int             pwmatchline(int, uid_t, const char *);
97
98 #define MAXGRP          200
99 #define MAXLINELENGTH   1024
100
101 static  FILE            *_gr_fp;
102 static  struct group    _gr_group;
103 static  int             _gr_stayopen;
104 static  int             _gr_filesdone;
105 static  FILE            *_pw_fp;
106 static  struct passwd   _pw_passwd;     /* password structure */
107 static  int             _pw_stayopen;   /* keep fd's open */
108 static  int             _pw_filesdone;
109
110 static  char            grfile[MAXPATHLEN];
111 static  char            pwfile[MAXPATHLEN];
112
113 static  char            *members[MAXGRP];
114 static  char            grline[MAXLINELENGTH];
115 static  char            pwline[MAXLINELENGTH];
116
117 int
118 setup_getid(const char *dir)
119 {
120         if (dir == NULL)
121                 return (0);
122
123                                 /* close existing databases */
124         gi_endgrent();
125         gi_endpwent();
126
127                                 /* build paths to new databases */
128         snprintf(grfile, sizeof(grfile), "%s/group", dir);
129         snprintf(pwfile, sizeof(pwfile), "%s/master.passwd", dir);
130
131                                 /* try to open new databases */
132         if (!grstart() || !pwstart())
133                 return (0);
134
135                                 /* switch pwcache(3) lookup functions */
136         if (pwcache_groupdb(gi_setgroupent, gi_endgrent,
137                             gi_getgrnam, gi_getgrgid) == -1
138             || pwcache_userdb(gi_setpassent, gi_endpwent,
139                             gi_getpwnam, gi_getpwuid) == -1)
140                 return (0);
141
142         return (1);
143 }
144
145
146 /*
147  * group lookup functions
148  */
149
150 static struct group *
151 gi_getgrnam(const char *name)
152 {
153         int rval;
154
155         if (!grstart())
156                 return NULL;
157         rval = grscan(1, 0, name);
158         if (!_gr_stayopen)
159                 endgrent();
160         return (rval) ? &_gr_group : NULL;
161 }
162
163 static struct group *
164 gi_getgrgid(gid_t gid)
165 {
166         int rval;
167
168         if (!grstart())
169                 return NULL;
170         rval = grscan(1, gid, NULL);
171         if (!_gr_stayopen)
172                 endgrent();
173         return (rval) ? &_gr_group : NULL;
174 }
175
176 static int
177 gi_setgroupent(int stayopen)
178 {
179
180         if (!grstart())
181                 return 0;
182         _gr_stayopen = stayopen;
183         return 1;
184 }
185
186 static void
187 gi_endgrent(void)
188 {
189
190         _gr_filesdone = 0;
191         if (_gr_fp) {
192                 (void)fclose(_gr_fp);
193                 _gr_fp = NULL;
194         }
195 }
196
197 static int
198 grstart(void)
199 {
200
201         _gr_filesdone = 0;
202         if (_gr_fp) {
203                 rewind(_gr_fp);
204                 return 1;
205         }
206         if (grfile[0] == '\0')                  /* sanity check */
207                 return 0;
208         return (_gr_fp = fopen(grfile, "r")) ? 1 : 0;
209 }
210
211
212 static int
213 grscan(int search, gid_t gid, const char *name)
214 {
215
216         if (_gr_filesdone)
217                 return 0;
218         for (;;) {
219                 if (!fgets(grline, sizeof(grline), _gr_fp)) {
220                         if (!search)
221                                 _gr_filesdone = 1;
222                         return 0;
223                 }
224                 /* skip lines that are too big */
225                 if (!strchr(grline, '\n')) {
226                         int ch;
227
228                         while ((ch = getc(_gr_fp)) != '\n' && ch != EOF)
229                                 ;
230                         continue;
231                 }
232                 if (grmatchline(search, gid, name))
233                         return 1;
234         }
235         /* NOTREACHED */
236 }
237
238 static int
239 grmatchline(int search, gid_t gid, const char *name)
240 {
241         unsigned long   id;
242         char            **m;
243         char            *cp, *bp, *ep;
244
245         /* name may be NULL if search is nonzero */
246
247         bp = grline;
248         memset(&_gr_group, 0, sizeof(_gr_group));
249         _gr_group.gr_name = strsep(&bp, ":\n");
250         if (search && name && strcmp(_gr_group.gr_name, name))
251                 return 0;
252         _gr_group.gr_passwd = strsep(&bp, ":\n");
253         if (!(cp = strsep(&bp, ":\n")))
254                 return 0;
255         id = strtoul(cp, &ep, 10);
256         if (id > GID_MAX || *ep != '\0')
257                 return 0;
258         _gr_group.gr_gid = (gid_t)id;
259         if (search && name == NULL && _gr_group.gr_gid != gid)
260                 return 0;
261         cp = NULL;
262         if (bp == NULL)
263                 return 0;
264         for (_gr_group.gr_mem = m = members;; bp++) {
265                 if (m == &members[MAXGRP - 1])
266                         break;
267                 if (*bp == ',') {
268                         if (cp) {
269                                 *bp = '\0';
270                                 *m++ = cp;
271                                 cp = NULL;
272                         }
273                 } else if (*bp == '\0' || *bp == '\n' || *bp == ' ') {
274                         if (cp) {
275                                 *bp = '\0';
276                                 *m++ = cp;
277                         }
278                         break;
279                 } else if (cp == NULL)
280                         cp = bp;
281         }
282         *m = NULL;
283         return 1;
284 }
285
286
287 /*
288  * user lookup functions
289  */
290
291 static struct passwd *
292 gi_getpwnam(const char *name)
293 {
294         int rval;
295
296         if (!pwstart())
297                 return NULL;
298         rval = pwscan(1, 0, name);
299         if (!_pw_stayopen)
300                 endpwent();
301         return (rval) ? &_pw_passwd : NULL;
302 }
303
304 static struct passwd *
305 gi_getpwuid(uid_t uid)
306 {
307         int rval;
308
309         if (!pwstart())
310                 return NULL;
311         rval = pwscan(1, uid, NULL);
312         if (!_pw_stayopen)
313                 endpwent();
314         return (rval) ? &_pw_passwd : NULL;
315 }
316
317 static int
318 gi_setpassent(int stayopen)
319 {
320
321         if (!pwstart())
322                 return 0;
323         _pw_stayopen = stayopen;
324         return 1;
325 }
326
327 static void
328 gi_endpwent(void)
329 {
330
331         _pw_filesdone = 0;
332         if (_pw_fp) {
333                 (void)fclose(_pw_fp);
334                 _pw_fp = NULL;
335         }
336 }
337
338 static int
339 pwstart(void)
340 {
341
342         _pw_filesdone = 0;
343         if (_pw_fp) {
344                 rewind(_pw_fp);
345                 return 1;
346         }
347         if (pwfile[0] == '\0')                  /* sanity check */
348                 return 0;
349         return (_pw_fp = fopen(pwfile, "r")) ? 1 : 0;
350 }
351
352
353 static int
354 pwscan(int search, uid_t uid, const char *name)
355 {
356
357         if (_pw_filesdone)
358                 return 0;
359         for (;;) {
360                 if (!fgets(pwline, sizeof(pwline), _pw_fp)) {
361                         if (!search)
362                                 _pw_filesdone = 1;
363                         return 0;
364                 }
365                 /* skip lines that are too big */
366                 if (!strchr(pwline, '\n')) {
367                         int ch;
368
369                         while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
370                                 ;
371                         continue;
372                 }
373                 if (pwmatchline(search, uid, name))
374                         return 1;
375         }
376         /* NOTREACHED */
377 }
378
379 static int
380 pwmatchline(int search, uid_t uid, const char *name)
381 {
382         unsigned long   id;
383         char            *cp, *bp, *ep;
384
385         /* name may be NULL if search is nonzero */
386
387         bp = pwline;
388         memset(&_pw_passwd, 0, sizeof(_pw_passwd));
389         _pw_passwd.pw_name = strsep(&bp, ":\n");                /* name */
390         if (search && name && strcmp(_pw_passwd.pw_name, name))
391                 return 0;
392
393         _pw_passwd.pw_passwd = strsep(&bp, ":\n");              /* passwd */
394
395         if (!(cp = strsep(&bp, ":\n")))                         /* uid */
396                 return 0;
397         id = strtoul(cp, &ep, 10);
398         if (id > UID_MAX || *ep != '\0')
399                 return 0;
400         _pw_passwd.pw_uid = (uid_t)id;
401         if (search && name == NULL && _pw_passwd.pw_uid != uid)
402                 return 0;
403
404         if (!(cp = strsep(&bp, ":\n")))                         /* gid */
405                 return 0;
406         id = strtoul(cp, &ep, 10);
407         if (id > GID_MAX || *ep != '\0')
408                 return 0;
409         _pw_passwd.pw_gid = (gid_t)id;
410
411         if (!(ep = strsep(&bp, ":")))                           /* class */
412                 return 0;
413         if (!(ep = strsep(&bp, ":")))                           /* change */
414                 return 0;
415         if (!(ep = strsep(&bp, ":")))                           /* expire */
416                 return 0;
417
418         if (!(_pw_passwd.pw_gecos = strsep(&bp, ":\n")))        /* gecos */
419                 return 0;
420         if (!(_pw_passwd.pw_dir = strsep(&bp, ":\n")))          /* directory */
421                 return 0;
422         if (!(_pw_passwd.pw_shell = strsep(&bp, ":\n")))        /* shell */
423                 return 0;
424
425         if (strchr(bp, ':') != NULL)
426                 return 0;
427
428         return 1;
429 }