getpwent.c revision 1.24 1 /* $NetBSD: getpwent.c,v 1.24 1998/02/02 02:41:25 perry Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
6 * Portions Copyright (c) 1994, 1995, Jason Downs. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37 #include <sys/cdefs.h>
38 #if defined(LIBC_SCCS) && !defined(lint)
39 #if 0
40 static char sccsid[] = "@(#)getpwent.c 8.2 (Berkeley) 4/27/95";
41 #else
42 __RCSID("$NetBSD: getpwent.c,v 1.24 1998/02/02 02:41:25 perry Exp $");
43 #endif
44 #endif /* LIBC_SCCS and not lint */
45
46 #include "namespace.h"
47 #include <sys/param.h>
48 #include <fcntl.h>
49 #include <db.h>
50 #include <syslog.h>
51 #include <pwd.h>
52 #include <utmp.h>
53 #include <errno.h>
54 #include <unistd.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <limits.h>
58 #include <netgroup.h>
59 #ifdef YP
60 #include <machine/param.h>
61 #include <stdio.h>
62 #include <rpc/rpc.h>
63 #include <rpcsvc/yp_prot.h>
64 #include <rpcsvc/ypclnt.h>
65 #endif
66
67 #ifdef __weak_alias
68 __weak_alias(endpwent,_endpwent);
69 __weak_alias(getpwent,_getpwent);
70 __weak_alias(getpwnam,_getpwnam);
71 __weak_alias(getpwuid,_getpwuid);
72 __weak_alias(setpassent,_setpassent);
73 __weak_alias(setpwent,_setpwent);
74 #endif
75
76
77 /*
78 * The lookup techniques and data extraction code here must be kept
79 * in sync with that in `pwd_mkdb'.
80 */
81
82 static struct passwd _pw_passwd; /* password structure */
83 static DB *_pw_db; /* password database */
84 static int _pw_keynum; /* key counter */
85 static int _pw_stayopen; /* keep fd's open */
86 static int _pw_flags; /* password flags */
87 static int __hashpw __P((DBT *));
88 static int __initdb __P((void));
89
90 const char __yp_token[] = "__YP!"; /* Let pwd_mkdb pull this in. */
91
92 #ifdef YP
93 enum _ypmode { YPMODE_NONE, YPMODE_FULL, YPMODE_USER, YPMODE_NETGRP };
94 static enum _ypmode __ypmode;
95
96 static char *__ypcurrent, *__ypdomain;
97 static int __ypcurrentlen;
98 static struct passwd *__ypproto = (struct passwd *)NULL;
99 static int __ypflags;
100 static char line[1024];
101 static long prbuf[1024 / sizeof(long)];
102 static DB *__ypexclude = (DB *)NULL;
103
104 static int __has_yppw __P((void));
105 static int __ypexclude_add __P((const char *));
106 static int __ypexclude_is __P((const char *));
107 static void __ypproto_set __P((void));
108 static int __ypparse __P((struct passwd *, char *));
109
110 static int
111 __ypexclude_add(name)
112 const char *name;
113 {
114 DBT key, data;
115
116 /* initialize the exclusion table if needed. */
117 if(__ypexclude == (DB *)NULL) {
118 __ypexclude = dbopen(NULL, O_RDWR, 600, DB_HASH, NULL);
119 if(__ypexclude == (DB *)NULL)
120 return(1);
121 }
122
123 /* set up the key */
124 key.data = (char *)name;
125 key.size = strlen(name);
126
127 /* data is nothing. */
128 data.data = NULL;
129 data.size = 0;
130
131 /* store it */
132 if((__ypexclude->put)(__ypexclude, &key, &data, 0) == -1)
133 return(1);
134
135 return(0);
136 }
137
138 static int
139 __ypexclude_is(name)
140 const char *name;
141 {
142 DBT key, data;
143
144 if(__ypexclude == (DB *)NULL)
145 return(0); /* nothing excluded */
146
147 /* set up the key */
148 key.data = (char *)name;
149 key.size = strlen(name);
150
151 if((__ypexclude->get)(__ypexclude, &key, &data, 0) == 0)
152 return(1); /* excluded */
153
154 return(0);
155 }
156
157 static void
158 __ypproto_set()
159 {
160 char *ptr;
161 struct passwd *pw = &_pw_passwd;
162
163 /* make this the new prototype */
164 ptr = (char *)prbuf;
165
166 /* first allocate the struct. */
167 __ypproto = (struct passwd *)ptr;
168 ptr += sizeof(struct passwd);
169
170 /* name */
171 if(pw->pw_name && (pw->pw_name)[0]) {
172 ptr = (char *)ALIGN(ptr);
173 bcopy(pw->pw_name, ptr, strlen(pw->pw_name) + 1);
174 __ypproto->pw_name = ptr;
175 ptr += (strlen(pw->pw_name) + 1);
176 } else
177 __ypproto->pw_name = (char *)NULL;
178
179 /* password */
180 if(pw->pw_passwd && (pw->pw_passwd)[0]) {
181 ptr = (char *)ALIGN(ptr);
182 bcopy(pw->pw_passwd, ptr, strlen(pw->pw_passwd) + 1);
183 __ypproto->pw_passwd = ptr;
184 ptr += (strlen(pw->pw_passwd) + 1);
185 } else
186 __ypproto->pw_passwd = (char *)NULL;
187
188 /* uid */
189 __ypproto->pw_uid = pw->pw_uid;
190
191 /* gid */
192 __ypproto->pw_gid = pw->pw_gid;
193
194 /* change (ignored anyway) */
195 __ypproto->pw_change = pw->pw_change;
196
197 /* class (ignored anyway) */
198 __ypproto->pw_class = "";
199
200 /* gecos */
201 if(pw->pw_gecos && (pw->pw_gecos)[0]) {
202 ptr = (char *)ALIGN(ptr);
203 bcopy(pw->pw_gecos, ptr, strlen(pw->pw_gecos) + 1);
204 __ypproto->pw_gecos = ptr;
205 ptr += (strlen(pw->pw_gecos) + 1);
206 } else
207 __ypproto->pw_gecos = (char *)NULL;
208
209 /* dir */
210 if(pw->pw_dir && (pw->pw_dir)[0]) {
211 ptr = (char *)ALIGN(ptr);
212 bcopy(pw->pw_dir, ptr, strlen(pw->pw_dir) + 1);
213 __ypproto->pw_dir = ptr;
214 ptr += (strlen(pw->pw_dir) + 1);
215 } else
216 __ypproto->pw_dir = (char *)NULL;
217
218 /* shell */
219 if(pw->pw_shell && (pw->pw_shell)[0]) {
220 ptr = (char *)ALIGN(ptr);
221 bcopy(pw->pw_shell, ptr, strlen(pw->pw_shell) + 1);
222 __ypproto->pw_shell = ptr;
223 ptr += (strlen(pw->pw_shell) + 1);
224 } else
225 __ypproto->pw_shell = (char *)NULL;
226
227 /* expire (ignored anyway) */
228 __ypproto->pw_expire = pw->pw_expire;
229
230 /* flags */
231 __ypflags = _pw_flags;
232 }
233
234 static int
235 __ypparse(pw, s)
236 struct passwd *pw;
237 char *s;
238 {
239 char *bp, *cp, *ep;
240 unsigned long id;
241
242 /* since this is currently using strsep(), parse it first */
243 bp = s;
244 pw->pw_name = strsep(&bp, ":\n");
245 pw->pw_passwd = strsep(&bp, ":\n");
246 if (!(cp = strsep(&bp, ":\n")))
247 return 1;
248 id = strtoul(cp, &ep, 10);
249 if (id > UID_MAX || *ep != '\0')
250 return 1;
251 pw->pw_uid = (uid_t)id;
252 if (!(cp = strsep(&bp, ":\n")))
253 return 1;
254 id = strtoul(cp, &ep, 10);
255 if (id > GID_MAX || *ep != '\0')
256 return 1;
257 pw->pw_gid = (gid_t)id;
258 pw->pw_change = 0;
259 pw->pw_class = "";
260 pw->pw_gecos = strsep(&bp, ":\n");
261 pw->pw_dir = strsep(&bp, ":\n");
262 pw->pw_shell = strsep(&bp, ":\n");
263 pw->pw_expire = 0;
264
265 /* now let the prototype override, if set. */
266 if(__ypproto != (struct passwd *)NULL) {
267 #ifdef YP_OVERRIDE_PASSWD
268 if(__ypproto->pw_passwd != (char *)NULL)
269 pw->pw_passwd = __ypproto->pw_passwd;
270 #endif
271 if(!(__ypflags & _PASSWORD_NOUID))
272 pw->pw_uid = __ypproto->pw_uid;
273 if(!(__ypflags & _PASSWORD_NOGID))
274 pw->pw_gid = __ypproto->pw_gid;
275 if(__ypproto->pw_gecos != (char *)NULL)
276 pw->pw_gecos = __ypproto->pw_gecos;
277 if(__ypproto->pw_dir != (char *)NULL)
278 pw->pw_dir = __ypproto->pw_dir;
279 if(__ypproto->pw_shell != (char *)NULL)
280 pw->pw_shell = __ypproto->pw_shell;
281 }
282 return 0;
283 }
284 #endif
285
286 struct passwd *
287 getpwent()
288 {
289 DBT key;
290 char bf[sizeof(_pw_keynum) + 1];
291 #ifdef YP
292 static char *name = (char *)NULL;
293 const char *user, *host, *dom;
294 int has_yppw;
295 #endif
296
297 if (!_pw_db && !__initdb())
298 return((struct passwd *)NULL);
299
300 #ifdef YP
301 has_yppw = __has_yppw();
302
303 again:
304 if(has_yppw && (__ypmode != YPMODE_NONE)) {
305 char *key, *data;
306 int keylen, datalen;
307 int r, s;
308
309 if(!__ypdomain) {
310 if( _yp_check(&__ypdomain) == 0) {
311 __ypmode = YPMODE_NONE;
312 goto again;
313 }
314 }
315 switch(__ypmode) {
316 case YPMODE_FULL:
317 data = NULL;
318 if(__ypcurrent) {
319 key = NULL;
320 r = yp_next(__ypdomain, "passwd.byname",
321 __ypcurrent, __ypcurrentlen,
322 &key, &keylen, &data, &datalen);
323 free(__ypcurrent);
324 if(r != 0) {
325 __ypcurrent = NULL;
326 if (key)
327 free(key);
328 }
329 else {
330 __ypcurrent = key;
331 __ypcurrentlen = keylen;
332 }
333 } else {
334 r = yp_first(__ypdomain, "passwd.byname",
335 &__ypcurrent, &__ypcurrentlen,
336 &data, &datalen);
337 }
338 if(r != 0) {
339 __ypmode = YPMODE_NONE;
340 if(data)
341 free(data);
342 data = NULL;
343 goto again;
344 }
345 bcopy(data, line, datalen);
346 free(data);
347 data = NULL;
348 break;
349 case YPMODE_NETGRP:
350 s = getnetgrent(&host, &user, &dom);
351 if(s == 0) { /* end of group */
352 endnetgrent();
353 __ypmode = YPMODE_NONE;
354 goto again;
355 }
356 if(user && *user) {
357 data = NULL;
358 r = yp_match(__ypdomain, "passwd.byname",
359 user, strlen(user),
360 &data, &datalen);
361 } else
362 goto again;
363 if(r != 0) {
364 /*
365 * if the netgroup is invalid, keep looking
366 * as there may be valid users later on.
367 */
368 if(data)
369 free(data);
370 goto again;
371 }
372 bcopy(data, line, datalen);
373 free(data);
374 data = NULL;
375 break;
376 case YPMODE_USER:
377 if(name != (char *)NULL) {
378 data = NULL;
379 r = yp_match(__ypdomain, "passwd.byname",
380 name, strlen(name),
381 &data, &datalen);
382 __ypmode = YPMODE_NONE;
383 free(name);
384 name = NULL;
385 if(r != 0) {
386 if(data)
387 free(data);
388 goto again;
389 }
390 bcopy(data, line, datalen);
391 free(data);
392 data = (char *)NULL;
393 } else { /* XXX */
394 __ypmode = YPMODE_NONE;
395 goto again;
396 }
397 break;
398 case YPMODE_NONE:
399 abort(); /* cannot happen */
400 break;
401 }
402
403 line[datalen] = '\0';
404 if (__ypparse(&_pw_passwd, line))
405 goto again;
406 return &_pw_passwd;
407 }
408 #endif
409
410 ++_pw_keynum;
411 bf[0] = _PW_KEYBYNUM;
412 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
413 key.data = (u_char *)bf;
414 key.size = sizeof(_pw_keynum) + 1;
415 if(__hashpw(&key)) {
416 #ifdef YP
417 /* if we don't have YP at all, don't bother. */
418 if(has_yppw) {
419 if(_pw_passwd.pw_name[0] == '+') {
420 /* set the mode */
421 switch(_pw_passwd.pw_name[1]) {
422 case '\0':
423 __ypmode = YPMODE_FULL;
424 break;
425 case '@':
426 __ypmode = YPMODE_NETGRP;
427 setnetgrent(_pw_passwd.pw_name + 2);
428 break;
429 default:
430 __ypmode = YPMODE_USER;
431 name = strdup(_pw_passwd.pw_name + 1);
432 break;
433 }
434
435 /* save the prototype */
436 __ypproto_set();
437 goto again;
438 } else if(_pw_passwd.pw_name[0] == '-') {
439 /* an attempted exclusion */
440 switch(_pw_passwd.pw_name[1]) {
441 case '\0':
442 break;
443 case '@':
444 setnetgrent(_pw_passwd.pw_name + 2);
445 while(getnetgrent(&host, &user, &dom)) {
446 if(user && *user)
447 __ypexclude_add(user);
448 }
449 endnetgrent();
450 break;
451 default:
452 __ypexclude_add(_pw_passwd.pw_name + 1);
453 break;
454 }
455 goto again;
456 }
457 }
458 #endif
459 return &_pw_passwd;
460 }
461 return (struct passwd *)NULL;
462 }
463
464 #ifdef YP
465
466 /*
467 * See if the YP token is in the database. Only works if pwd_mkdb knows
468 * about the token.
469 */
470 static int
471 __has_yppw()
472 {
473 DBT key, data;
474 DBT pkey, pdata;
475 char bf[MAXLOGNAME];
476
477 key.data = (u_char *)__yp_token;
478 key.size = strlen(__yp_token);
479
480 /* Pre-token database support. */
481 bf[0] = _PW_KEYBYNAME;
482 bf[1] = '+';
483 pkey.data = (u_char *)bf;
484 pkey.size = 2;
485
486 if ((_pw_db->get)(_pw_db, &key, &data, 0)
487 && (_pw_db->get)(_pw_db, &pkey, &pdata, 0))
488 return(0); /* No YP. */
489 return(1);
490 }
491 #endif
492
493 struct passwd *
494 getpwnam(name)
495 const char *name;
496 {
497 DBT key;
498 int len, rval;
499 char bf[MAXLOGNAME + 1];
500
501 if (!_pw_db && !__initdb())
502 return((struct passwd *)NULL);
503
504 #ifdef YP
505 /*
506 * If YP is active, we must sequence through the passwd file
507 * in sequence.
508 */
509 if (__has_yppw()) {
510 int r;
511 int s = -1;
512 const char *host, *user, *dom;
513
514 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
515 bf[0] = _PW_KEYBYNUM;
516 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
517 key.data = (u_char *)bf;
518 key.size = sizeof(_pw_keynum) + 1;
519 if(__hashpw(&key) == 0)
520 break;
521 switch(_pw_passwd.pw_name[0]) {
522 case '+':
523 if(!__ypdomain) {
524 if(_yp_check(&__ypdomain) == 0) {
525 continue;
526 }
527 }
528 /* save the prototype */
529 __ypproto_set();
530
531 switch(_pw_passwd.pw_name[1]) {
532 case '\0':
533 if(__ypcurrent) {
534 free(__ypcurrent);
535 __ypcurrent = NULL;
536 }
537 r = yp_match(__ypdomain,
538 "passwd.byname",
539 name, strlen(name),
540 &__ypcurrent, &__ypcurrentlen);
541 if(r != 0) {
542 if(__ypcurrent)
543 free(__ypcurrent);
544 __ypcurrent = NULL;
545 continue;
546 }
547 break;
548 case '@':
549 pwnam_netgrp:
550 if(__ypcurrent) {
551 free(__ypcurrent);
552 __ypcurrent = NULL;
553 }
554 if(s == -1) /* first time */
555 setnetgrent(_pw_passwd.pw_name + 2);
556 s = getnetgrent(&host, &user, &dom);
557 if(s == 0) { /* end of group */
558 endnetgrent();
559 s = -1;
560 continue;
561 } else {
562 if(user && *user) {
563 r = yp_match(__ypdomain,
564 "passwd.byname",
565 user, strlen(user),
566 &__ypcurrent,
567 &__ypcurrentlen);
568 } else
569 goto pwnam_netgrp;
570 if(r != 0) {
571 if(__ypcurrent)
572 free(__ypcurrent);
573 __ypcurrent = NULL;
574 /*
575 * just because this
576 * user is bad, doesn't
577 * mean they all are.
578 */
579 goto pwnam_netgrp;
580 }
581 }
582 break;
583 default:
584 if(__ypcurrent) {
585 free(__ypcurrent);
586 __ypcurrent = NULL;
587 }
588 user = _pw_passwd.pw_name + 1;
589 r = yp_match(__ypdomain,
590 "passwd.byname",
591 user, strlen(user),
592 &__ypcurrent,
593 &__ypcurrentlen);
594 if(r != 0) {
595 if(__ypcurrent)
596 free(__ypcurrent);
597 __ypcurrent = NULL;
598 continue;
599 }
600 break;
601 }
602 bcopy(__ypcurrent, line, __ypcurrentlen);
603 line[__ypcurrentlen] = '\0';
604 if(__ypparse(&_pw_passwd, line)
605 || __ypexclude_is(_pw_passwd.pw_name)) {
606 if(s == 1) /* inside netgrp */
607 goto pwnam_netgrp;
608 continue;
609 }
610 break;
611 case '-':
612 /* attempted exclusion */
613 switch(_pw_passwd.pw_name[1]) {
614 case '\0':
615 break;
616 case '@':
617 setnetgrent(_pw_passwd.pw_name + 2);
618 while(getnetgrent(&host, &user, &dom)) {
619 if(user && *user)
620 __ypexclude_add(user);
621 }
622 endnetgrent();
623 break;
624 default:
625 __ypexclude_add(_pw_passwd.pw_name + 1);
626 break;
627 }
628 break;
629
630 continue;
631 }
632 if(strcmp(_pw_passwd.pw_name, name) == 0) {
633 if (!_pw_stayopen) {
634 (void)(_pw_db->close)(_pw_db);
635 _pw_db = (DB *)NULL;
636 }
637 if(__ypexclude != (DB *)NULL) {
638 (void)(__ypexclude->close)(__ypexclude);
639 __ypexclude = (DB *)NULL;
640 }
641 __ypproto = (struct passwd *)NULL;
642 return &_pw_passwd;
643 }
644 if(s == 1) /* inside netgrp */
645 goto pwnam_netgrp;
646 continue;
647 }
648 if (!_pw_stayopen) {
649 (void)(_pw_db->close)(_pw_db);
650 _pw_db = (DB *)NULL;
651 }
652 if(__ypexclude != (DB *)NULL) {
653 (void)(__ypexclude->close)(__ypexclude);
654 __ypexclude = (DB *)NULL;
655 }
656 __ypproto = (struct passwd *)NULL;
657 return (struct passwd *)NULL;
658 }
659 #endif /* YP */
660
661 bf[0] = _PW_KEYBYNAME;
662 len = strlen(name);
663 len = MIN(len, MAXLOGNAME);
664 bcopy(name, bf + 1, len);
665 key.data = (u_char *)bf;
666 key.size = len + 1;
667 rval = __hashpw(&key);
668
669 if (!_pw_stayopen) {
670 (void)(_pw_db->close)(_pw_db);
671 _pw_db = (DB *)NULL;
672 }
673 return(rval ? &_pw_passwd : (struct passwd *)NULL);
674 }
675
676 struct passwd *
677 getpwuid(uid)
678 uid_t uid;
679 {
680 DBT key;
681 char bf[sizeof(_pw_keynum) + 1];
682 uid_t keyuid;
683 int rval;
684
685 if (!_pw_db && !__initdb())
686 return((struct passwd *)NULL);
687
688 #ifdef YP
689 /*
690 * If YP is active, we must sequence through the passwd file
691 * in sequence.
692 */
693 if (__has_yppw()) {
694 char uidbuf[20];
695 int r;
696 int s = -1;
697 const char *host, *user, *dom;
698
699 snprintf(uidbuf, sizeof(uidbuf), "%u", uid);
700 for(_pw_keynum=1; _pw_keynum; _pw_keynum++) {
701 bf[0] = _PW_KEYBYNUM;
702 bcopy((char *)&_pw_keynum, bf + 1, sizeof(_pw_keynum));
703 key.data = (u_char *)bf;
704 key.size = sizeof(_pw_keynum) + 1;
705 if(__hashpw(&key) == 0)
706 break;
707 switch(_pw_passwd.pw_name[0]) {
708 case '+':
709 if(!__ypdomain) {
710 if(_yp_check(&__ypdomain) == 0) {
711 continue;
712 }
713 }
714 /* save the prototype */
715 __ypproto_set();
716
717 switch(_pw_passwd.pw_name[1]) {
718 case '\0':
719 if(__ypcurrent) {
720 free(__ypcurrent);
721 __ypcurrent = NULL;
722 }
723 r = yp_match(__ypdomain, "passwd.byuid",
724 uidbuf, strlen(uidbuf),
725 &__ypcurrent, &__ypcurrentlen);
726 if(r != 0) {
727 if(__ypcurrent)
728 free(__ypcurrent);
729 __ypcurrent = NULL;
730 continue;
731 }
732 break;
733 case '@':
734 pwuid_netgrp:
735 if(__ypcurrent) {
736 free(__ypcurrent);
737 __ypcurrent = NULL;
738 }
739 if(s == -1) /* first time */
740 setnetgrent(_pw_passwd.pw_name + 2);
741 s = getnetgrent(&host, &user, &dom);
742 if(s == 0) { /* end of group */
743 endnetgrent();
744 s = -1;
745 continue;
746 } else {
747 if(user && *user) {
748 r = yp_match(__ypdomain,
749 "passwd.byname",
750 user, strlen(user),
751 &__ypcurrent,
752 &__ypcurrentlen);
753 } else
754 goto pwuid_netgrp;
755 if(r != 0) {
756 if(__ypcurrent)
757 free(__ypcurrent);
758 __ypcurrent = NULL;
759 /*
760 * just because this
761 * user is bad, doesn't
762 * mean they all are.
763 */
764 goto pwuid_netgrp;
765 }
766 }
767 break;
768 default:
769 if(__ypcurrent) {
770 free(__ypcurrent);
771 __ypcurrent = NULL;
772 }
773 user = _pw_passwd.pw_name + 1;
774 r = yp_match(__ypdomain,
775 "passwd.byname",
776 user, strlen(user),
777 &__ypcurrent,
778 &__ypcurrentlen);
779 if(r != 0) {
780 if(__ypcurrent)
781 free(__ypcurrent);
782 __ypcurrent = NULL;
783 continue;
784 }
785 break;
786 }
787 bcopy(__ypcurrent, line, __ypcurrentlen);
788 line[__ypcurrentlen] = '\0';
789 if(__ypparse(&_pw_passwd, line)
790 || __ypexclude_is(_pw_passwd.pw_name)) {
791 if(s == 1) /* inside netgroup */
792 goto pwuid_netgrp;
793 continue;
794 }
795 break;
796 case '-':
797 /* attempted exclusion */
798 switch(_pw_passwd.pw_name[1]) {
799 case '\0':
800 break;
801 case '@':
802 setnetgrent(_pw_passwd.pw_name + 2);
803 while(getnetgrent(&host, &user, &dom)) {
804 if(user && *user)
805 __ypexclude_add(user);
806 }
807 endnetgrent();
808 break;
809 default:
810 __ypexclude_add(_pw_passwd.pw_name + 1);
811 break;
812 }
813 break;
814
815 continue;
816 }
817 if( _pw_passwd.pw_uid == uid) {
818 if (!_pw_stayopen) {
819 (void)(_pw_db->close)(_pw_db);
820 _pw_db = (DB *)NULL;
821 }
822 if (__ypexclude != (DB *)NULL) {
823 (void)(__ypexclude->close)(__ypexclude);
824 __ypexclude = (DB *)NULL;
825 }
826 __ypproto = NULL;
827 return &_pw_passwd;
828 }
829 if(s == 1) /* inside netgroup */
830 goto pwuid_netgrp;
831 continue;
832 }
833 if (!_pw_stayopen) {
834 (void)(_pw_db->close)(_pw_db);
835 _pw_db = (DB *)NULL;
836 }
837 if(__ypexclude != (DB *)NULL) {
838 (void)(__ypexclude->close)(__ypexclude);
839 __ypexclude = (DB *)NULL;
840 }
841 __ypproto = (struct passwd *)NULL;
842 return (struct passwd *)NULL;
843 }
844 #endif /* YP */
845
846 bf[0] = _PW_KEYBYUID;
847 keyuid = uid;
848 bcopy(&keyuid, bf + 1, sizeof(keyuid));
849 key.data = (u_char *)bf;
850 key.size = sizeof(keyuid) + 1;
851 rval = __hashpw(&key);
852
853 if (!_pw_stayopen) {
854 (void)(_pw_db->close)(_pw_db);
855 _pw_db = (DB *)NULL;
856 }
857 return(rval ? &_pw_passwd : (struct passwd *)NULL);
858 }
859
860 int
861 setpassent(stayopen)
862 int stayopen;
863 {
864 _pw_keynum = 0;
865 _pw_stayopen = stayopen;
866 #ifdef YP
867 __ypmode = YPMODE_NONE;
868 if(__ypcurrent)
869 free(__ypcurrent);
870 __ypcurrent = NULL;
871 if(__ypexclude != (DB *)NULL) {
872 (void)(__ypexclude->close)(__ypexclude);
873 __ypexclude = (DB *)NULL;
874 }
875 __ypproto = (struct passwd *)NULL;
876 #endif
877 return(1);
878 }
879
880 void
881 setpwent()
882 {
883 (void) setpassent(0);
884 }
885
886 void
887 endpwent()
888 {
889 _pw_keynum = 0;
890 if (_pw_db) {
891 (void)(_pw_db->close)(_pw_db);
892 _pw_db = (DB *)NULL;
893 }
894 #ifdef YP
895 __ypmode = YPMODE_NONE;
896 if(__ypcurrent)
897 free(__ypcurrent);
898 __ypcurrent = NULL;
899 if(__ypexclude != (DB *)NULL) {
900 (void)(__ypexclude->close)(__ypexclude);
901 __ypexclude = (DB *)NULL;
902 }
903 __ypproto = (struct passwd *)NULL;
904 #endif
905 }
906
907 static int
908 __initdb()
909 {
910 static int warned;
911 char *p;
912
913 #ifdef YP
914 __ypmode = YPMODE_NONE;
915 #endif
916 p = (geteuid()) ? _PATH_MP_DB : _PATH_SMP_DB;
917 _pw_db = dbopen(p, O_RDONLY, 0, DB_HASH, NULL);
918 if (_pw_db)
919 return(1);
920 if (!warned)
921 syslog(LOG_ERR, "%s: %m", p);
922 warned = 1;
923 return(0);
924 }
925
926 static int
927 __hashpw(key)
928 DBT *key;
929 {
930 char *p, *t;
931 static u_int max;
932 static char *line;
933 DBT data;
934
935 if ((_pw_db->get)(_pw_db, key, &data, 0))
936 return(0);
937 p = (char *)data.data;
938 if (data.size > max && !(line = realloc(line, (max += 1024))))
939 return(0);
940
941 /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
942 t = line;
943 #define EXPAND(e) e = t; while ((*t++ = *p++));
944 #define SCALAR(v) memmove(&(v), p, sizeof v); p += sizeof v
945 EXPAND(_pw_passwd.pw_name);
946 EXPAND(_pw_passwd.pw_passwd);
947 SCALAR(_pw_passwd.pw_uid);
948 SCALAR(_pw_passwd.pw_gid);
949 SCALAR(_pw_passwd.pw_change);
950 EXPAND(_pw_passwd.pw_class);
951 EXPAND(_pw_passwd.pw_gecos);
952 EXPAND(_pw_passwd.pw_dir);
953 EXPAND(_pw_passwd.pw_shell);
954 SCALAR(_pw_passwd.pw_expire);
955
956 /* See if there's any data left. If so, read in flags. */
957 if (data.size > (p - (char *)data.data)) {
958 SCALAR(_pw_flags);
959 } else
960 _pw_flags = _PASSWORD_NOUID|_PASSWORD_NOGID; /* default */
961
962 return(1);
963 }
964