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