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