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