]> sourceware.org Git - glibc.git/blob - nis/nss_compat/compat-pwd.c
Update.
[glibc.git] / nis / nss_compat / compat-pwd.c
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
19
20 #include <nss.h>
21 #include <pwd.h>
22 #include <errno.h>
23 #include <ctype.h>
24 #include <fcntl.h>
25 #include <netdb.h>
26 #include <string.h>
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/nis.h>
31 #include <nsswitch.h>
32
33 #include "netgroup.h"
34 #include "nss-nisplus.h"
35 #include "nisplus-parser.h"
36
37 static service_user *ni = NULL;
38 static bool_t use_nisplus = FALSE; /* default: passwd_compat: nis */
39 static nis_name pwdtable = NULL; /* Name of the pwd table */
40 static size_t pwdtablelen = 0;
41
42 /* Get the declaration of the parser function. */
43 #define ENTNAME pwent
44 #define STRUCTURE passwd
45 #define EXTERN_PARSER
46 #include <nss/nss_files/files-parse.c>
47
48 /* Structure for remembering -@netgroup and -user members ... */
49 #define BLACKLIST_INITIAL_SIZE 512
50 #define BLACKLIST_INCREMENT 256
51 struct blacklist_t
52 {
53 char *data;
54 int current;
55 int size;
56 };
57
58 struct ent_t
59 {
60 bool_t netgroup;
61 bool_t nis;
62 bool_t first;
63 char *oldkey;
64 int oldkeylen;
65 nis_result *result;
66 FILE *stream;
67 struct blacklist_t blacklist;
68 struct passwd pwd;
69 struct __netgrent netgrdata;
70 };
71 typedef struct ent_t ent_t;
72
73 static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
74 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
75
76 /* Protect global state against multiple changers. */
77 __libc_lock_define_initialized (static, lock)
78
79 /* Prototypes for local functions. */
80 static void blacklist_store_name (const char *, ent_t *);
81 static int in_blacklist (const char *, int, ent_t *);
82
83 static void
84 give_pwd_free (struct passwd *pwd)
85 {
86 if (pwd->pw_name != NULL)
87 free (pwd->pw_name);
88 if (pwd->pw_passwd != NULL)
89 free (pwd->pw_passwd);
90 if (pwd->pw_gecos != NULL)
91 free (pwd->pw_gecos);
92 if (pwd->pw_dir != NULL)
93 free (pwd->pw_dir);
94 if (pwd->pw_shell != NULL)
95 free (pwd->pw_shell);
96
97 memset (pwd, '\0', sizeof (struct passwd));
98 }
99
100 static size_t
101 pwd_need_buflen (struct passwd *pwd)
102 {
103 size_t len = 0;
104
105 if (pwd->pw_passwd != NULL)
106 len += strlen (pwd->pw_passwd) + 1;
107
108 if (pwd->pw_gecos != NULL)
109 len += strlen (pwd->pw_gecos) + 1;
110
111 if (pwd->pw_dir != NULL)
112 len += strlen (pwd->pw_dir) + 1;
113
114 if (pwd->pw_shell != NULL)
115 len += strlen (pwd->pw_shell) + 1;
116
117 return len;
118 }
119
120 static void
121 copy_pwd_changes (struct passwd *dest, struct passwd *src,
122 char *buffer, size_t buflen)
123 {
124 if (src->pw_passwd != NULL && strlen (src->pw_passwd))
125 {
126 if (buffer == NULL)
127 dest->pw_passwd = strdup (src->pw_passwd);
128 else if (dest->pw_passwd &&
129 strlen (dest->pw_passwd) >= strlen (src->pw_passwd))
130 strcpy (dest->pw_passwd, src->pw_passwd);
131 else
132 {
133 dest->pw_passwd = buffer;
134 strcpy (dest->pw_passwd, src->pw_passwd);
135 buffer += strlen (dest->pw_passwd) + 1;
136 buflen = buflen - (strlen (dest->pw_passwd) + 1);
137 }
138 }
139
140 if (src->pw_gecos != NULL && strlen (src->pw_gecos))
141 {
142 if (buffer == NULL)
143 dest->pw_gecos = strdup (src->pw_gecos);
144 else if (dest->pw_gecos &&
145 strlen (dest->pw_gecos) >= strlen (src->pw_gecos))
146 strcpy (dest->pw_gecos, src->pw_gecos);
147 else
148 {
149 dest->pw_gecos = buffer;
150 strcpy (dest->pw_gecos, src->pw_gecos);
151 buffer += strlen (dest->pw_gecos) + 1;
152 buflen = buflen - (strlen (dest->pw_gecos) + 1);
153 }
154 }
155 if (src->pw_dir != NULL && strlen (src->pw_dir))
156 {
157 if (buffer == NULL)
158 dest->pw_dir = strdup (src->pw_dir);
159 else if (dest->pw_dir &&
160 strlen (dest->pw_dir) >= strlen (src->pw_dir))
161 strcpy (dest->pw_dir, src->pw_dir);
162 else
163 {
164 dest->pw_dir = buffer;
165 strcpy (dest->pw_dir, src->pw_dir);
166 buffer += strlen (dest->pw_dir) + 1;
167 buflen = buflen - (strlen (dest->pw_dir) + 1);
168 }
169 }
170
171 if (src->pw_shell != NULL && strlen (src->pw_shell))
172 {
173 if (buffer == NULL)
174 dest->pw_shell = strdup (src->pw_shell);
175 else if (dest->pw_shell &&
176 strlen (dest->pw_shell) >= strlen (src->pw_shell))
177 strcpy (dest->pw_shell, src->pw_shell);
178 else
179 {
180 dest->pw_shell = buffer;
181 strcpy (dest->pw_shell, src->pw_shell);
182 buffer += strlen (dest->pw_shell) + 1;
183 buflen = buflen - (strlen (dest->pw_shell) + 1);
184 }
185 }
186 }
187
188 static enum nss_status
189 internal_setpwent (ent_t *ent)
190 {
191 enum nss_status status = NSS_STATUS_SUCCESS;
192
193 ent->nis = ent->first = ent->netgroup = 0;
194
195 /* If something was left over free it. */
196 if (ent->netgroup)
197 __internal_endnetgrent (&ent->netgrdata);
198
199 if (ent->oldkey != NULL)
200 {
201 free (ent->oldkey);
202 ent->oldkey = NULL;
203 ent->oldkeylen = 0;
204 }
205
206 if (ent->result != NULL)
207 {
208 nis_freeresult (ent->result);
209 ent->result = NULL;
210 }
211
212 if (pwdtable == NULL)
213 {
214 static const char key[] = "passwd.org_dir.";
215 const char *local_dir = nis_local_directory ();
216 size_t len_local_dir = strlen (local_dir);
217
218 pwdtable = malloc (sizeof (key) + len_local_dir);
219 if (pwdtable == NULL)
220 return NSS_STATUS_TRYAGAIN;
221
222 pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable,
223 key, sizeof (key) - 1),
224 local_dir, len_local_dir + 1)
225 - pwdtable) - 1;
226 }
227
228 if (ent->blacklist.data != NULL)
229 {
230 ent->blacklist.current = 1;
231 ent->blacklist.data[0] = '|';
232 ent->blacklist.data[1] = '\0';
233 }
234 else
235 ent->blacklist.current = 0;
236
237 if (ent->stream == NULL)
238 {
239 ent->stream = fopen ("/etc/passwd", "r");
240
241 if (ent->stream == NULL)
242 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
243 else
244 {
245 /* We have to make sure the file is `closed on exec'. */
246 int result, flags;
247
248 result = flags = fcntl (fileno (ent->stream), F_GETFD, 0);
249 if (result >= 0)
250 {
251 flags |= FD_CLOEXEC;
252 result = fcntl (fileno (ent->stream), F_SETFD, flags);
253 }
254 if (result < 0)
255 {
256 /* Something went wrong. Close the stream and return a
257 failure. */
258 fclose (ent->stream);
259 ent->stream = NULL;
260 status = NSS_STATUS_UNAVAIL;
261 }
262 }
263 }
264 else
265 rewind (ent->stream);
266
267 give_pwd_free (&ent->pwd);
268
269 return status;
270 }
271
272
273 enum nss_status
274 _nss_compat_setpwent (void)
275 {
276 enum nss_status result;
277
278 __libc_lock_lock (lock);
279
280 if (ni == NULL)
281 {
282 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
283 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
284 }
285
286 result = internal_setpwent (&ext_ent);
287
288 __libc_lock_unlock (lock);
289
290 return result;
291 }
292
293
294 static enum nss_status
295 internal_endpwent (ent_t *ent)
296 {
297 if (ent->stream != NULL)
298 {
299 fclose (ent->stream);
300 ent->stream = NULL;
301 }
302
303 if (ent->netgroup)
304 __internal_endnetgrent (&ent->netgrdata);
305
306 ent->nis = ent->first = ent->netgroup = 0;
307
308 if (ent->oldkey != NULL)
309 {
310 free (ent->oldkey);
311 ent->oldkey = NULL;
312 ent->oldkeylen = 0;
313 }
314
315 if (ent->result != NULL)
316 {
317 nis_freeresult (ent->result);
318 ent->result = NULL;
319 }
320
321 if (ent->blacklist.data != NULL)
322 {
323 ent->blacklist.current = 1;
324 ent->blacklist.data[0] = '|';
325 ent->blacklist.data[1] = '\0';
326 }
327 else
328 ent->blacklist.current = 0;
329
330 give_pwd_free (&ent->pwd);
331
332 return NSS_STATUS_SUCCESS;
333 }
334
335 enum nss_status
336 _nss_compat_endpwent (void)
337 {
338 enum nss_status result;
339
340 __libc_lock_lock (lock);
341
342 result = internal_endpwent (&ext_ent);
343
344 __libc_lock_unlock (lock);
345
346 return result;
347 }
348
349 static enum nss_status
350 getpwent_next_nis_netgr (const char *name, struct passwd *result, ent_t *ent,
351 char *group, char *buffer, size_t buflen, int *errnop)
352 {
353 struct parser_data *data = (void *) buffer;
354 char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
355 int status, outvallen;
356 size_t p2len;
357
358 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
359 {
360 ent->netgroup = 0;
361 ent->first = 0;
362 give_pwd_free (&ent->pwd);
363 return NSS_STATUS_UNAVAIL;
364 }
365
366 if (ent->first == TRUE)
367 {
368 memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
369 __internal_setnetgrent (group, &ent->netgrdata);
370 ent->first = FALSE;
371 }
372
373 while (1)
374 {
375 char *saved_cursor;
376 int parse_res;
377
378 saved_cursor = ent->netgrdata.cursor;
379 status = __internal_getnetgrent_r (&host, &user, &domain,
380 &ent->netgrdata, buffer, buflen,
381 errnop);
382 if (status != 1)
383 {
384 __internal_endnetgrent (&ent->netgrdata);
385 ent->netgroup = 0;
386 give_pwd_free (&ent->pwd);
387 return NSS_STATUS_RETURN;
388 }
389
390 if (user == NULL || user[0] == '-')
391 continue;
392
393 if (domain != NULL && strcmp (ypdomain, domain) != 0)
394 continue;
395
396 /* If name != NULL, we are called from getpwnam. */
397 if (name != NULL)
398 if (strcmp (user, name) != 0)
399 continue;
400
401 if (yp_match (ypdomain, "passwd.byname", user,
402 strlen (user), &outval, &outvallen)
403 != YPERR_SUCCESS)
404 continue;
405
406 p2len = pwd_need_buflen (&ent->pwd);
407 if (p2len > buflen)
408 {
409 free (outval);
410 *errnop = ERANGE;
411 return NSS_STATUS_TRYAGAIN;
412 }
413 p2 = buffer + (buflen - p2len);
414 buflen -= p2len;
415
416 if (buflen < ((size_t) outvallen + 1))
417 {
418 free (outval);
419 *errnop = ERANGE;
420 return NSS_STATUS_TRYAGAIN;
421 }
422 p = strncpy (buffer, outval, buflen);
423
424 while (isspace (*p))
425 p++;
426 free (outval);
427 parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop);
428 if (parse_res == -1)
429 {
430 ent->netgrdata.cursor = saved_cursor;
431 return NSS_STATUS_TRYAGAIN;
432 }
433
434 if (parse_res)
435 {
436 /* Store the User in the blacklist for the "+" at the end of
437 /etc/passwd */
438 blacklist_store_name (result->pw_name, ent);
439 copy_pwd_changes (result, &ent->pwd, p2, p2len);
440 break;
441 }
442 }
443
444 return NSS_STATUS_SUCCESS;
445 }
446
447 static enum nss_status
448 getpwent_next_nisplus_netgr (const char *name, struct passwd *result,
449 ent_t *ent, char *group, char *buffer,
450 size_t buflen, int *errnop)
451 {
452 char *ypdomain, *host, *user, *domain, *p2;
453 int status, parse_res;
454 size_t p2len;
455 nis_result *nisres;
456
457 /* Maybe we should use domainname here ? We need the current
458 domainname for the domain field in netgroups */
459 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
460 {
461 ent->netgroup = 0;
462 ent->first = 0;
463 give_pwd_free (&ent->pwd);
464 return NSS_STATUS_UNAVAIL;
465 }
466
467 if (ent->first == TRUE)
468 {
469 bzero (&ent->netgrdata, sizeof (struct __netgrent));
470 __internal_setnetgrent (group, &ent->netgrdata);
471 ent->first = FALSE;
472 }
473
474 while (1)
475 {
476 char *saved_cursor;
477
478 saved_cursor = ent->netgrdata.cursor;
479 status = __internal_getnetgrent_r (&host, &user, &domain,
480 &ent->netgrdata, buffer, buflen,
481 errnop);
482 if (status != 1)
483 {
484 __internal_endnetgrent (&ent->netgrdata);
485 ent->netgroup = 0;
486 give_pwd_free (&ent->pwd);
487 return NSS_STATUS_RETURN;
488 }
489
490 if (user == NULL || user[0] == '-')
491 continue;
492
493 if (domain != NULL && strcmp (ypdomain, domain) != 0)
494 continue;
495
496 /* If name != NULL, we are called from getpwnam */
497 if (name != NULL)
498 if (strcmp (user, name) != 0)
499 continue;
500
501 p2len = pwd_need_buflen (&ent->pwd);
502 if (p2len > buflen)
503 {
504 *errnop = ERANGE;
505 return NSS_STATUS_TRYAGAIN;
506 }
507 p2 = buffer + (buflen - p2len);
508 buflen -= p2len;
509 {
510 char buf[strlen (user) + 30 + pwdtablelen];
511 sprintf(buf, "[name=%s],%s", user, pwdtable);
512 nisres = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
513 }
514 if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS)
515 {
516 nis_freeresult (nisres);
517 continue;
518 }
519 parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
520 buflen, errnop);
521 if (parse_res == -1)
522 {
523 nis_freeresult (nisres);
524 ent->netgrdata.cursor = saved_cursor;
525 *errnop = ERANGE;
526 return NSS_STATUS_TRYAGAIN;
527 }
528 nis_freeresult (nisres);
529
530 if (parse_res)
531 {
532 /* Store the User in the blacklist for the "+" at the end of
533 /etc/passwd */
534 blacklist_store_name (result->pw_name, ent);
535 copy_pwd_changes (result, &ent->pwd, p2, p2len);
536 break;
537 }
538 }
539
540 return NSS_STATUS_SUCCESS;
541 }
542
543 /* get the next user from NIS+ (+ entry) */
544 static enum nss_status
545 getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
546 size_t buflen, int *errnop)
547 {
548 int parse_res;
549 size_t p2len;
550 char *p2;
551
552 p2len = pwd_need_buflen (&ent->pwd);
553 if (p2len > buflen)
554 {
555 *errnop = ERANGE;
556 return NSS_STATUS_TRYAGAIN;
557 }
558 p2 = buffer + (buflen - p2len);
559 buflen -= p2len;
560 do
561 {
562 bool_t saved_first;
563 nis_result *saved_res;
564
565 if (ent->first)
566 {
567 saved_first = TRUE;
568 saved_res = ent->result;
569
570 ent->result = nis_first_entry (pwdtable);
571 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
572 {
573 ent->nis = 0;
574 give_pwd_free (&ent->pwd);
575 return niserr2nss (ent->result->status);
576 }
577 ent->first = FALSE;
578 }
579 else
580 {
581 nis_result *res;
582
583 res = nis_next_entry (pwdtable, &ent->result->cookie);
584 saved_res = ent->result;
585 saved_first = FALSE;
586 ent->result = res;
587 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
588 {
589 ent->nis = 0;
590 nis_freeresult (saved_res);
591 give_pwd_free (&ent->pwd);
592 return niserr2nss (ent->result->status);
593 }
594 }
595 parse_res = _nss_nisplus_parse_pwent (ent->result, result, buffer,
596 buflen, errnop);
597 if (parse_res == -1)
598 {
599 nis_freeresult (ent->result);
600 ent->result = saved_res;
601 ent->first = saved_first;
602 *errnop = ERANGE;
603 return NSS_STATUS_TRYAGAIN;
604 }
605 else
606 {
607 if (!saved_first)
608 nis_freeresult (saved_res);
609 }
610
611 if (parse_res &&
612 in_blacklist (result->pw_name, strlen (result->pw_name), ent))
613 parse_res = 0; /* if result->pw_name in blacklist,search next entry */
614 }
615 while (!parse_res);
616
617 copy_pwd_changes (result, &ent->pwd, p2, p2len);
618
619 return NSS_STATUS_SUCCESS;
620 }
621
622 static enum nss_status
623 getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
624 size_t buflen, int *errnop)
625 {
626 struct parser_data *data = (void *) buffer;
627 char *domain, *outkey, *outval, *p, *p2;
628 int outkeylen, outvallen, parse_res;
629 size_t p2len;
630
631 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
632 {
633 ent->nis = 0;
634 give_pwd_free (&ent->pwd);
635 return NSS_STATUS_UNAVAIL;
636 }
637
638 p2len = pwd_need_buflen (&ent->pwd);
639 if (p2len > buflen)
640 {
641 *errnop = ERANGE;
642 return NSS_STATUS_TRYAGAIN;
643 }
644 p2 = buffer + (buflen - p2len);
645 buflen -= p2len;
646 do
647 {
648 bool_t saved_first;
649 char *saved_oldkey;
650 int saved_oldlen;
651
652 if (ent->first)
653 {
654 if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
655 &outval, &outvallen) != YPERR_SUCCESS)
656 {
657 ent->nis = 0;
658 give_pwd_free (&ent->pwd);
659 return NSS_STATUS_UNAVAIL;
660 }
661
662 if (buflen < ((size_t) outvallen + 1))
663 {
664 free (outval);
665 *errnop = ERANGE;
666 return NSS_STATUS_TRYAGAIN;
667 }
668
669 saved_first = TRUE;
670 saved_oldkey = ent->oldkey;
671 saved_oldlen = ent->oldkeylen;
672 ent->oldkey = outkey;
673 ent->oldkeylen = outkeylen;
674 ent->first = FALSE;
675 }
676 else
677 {
678 if (yp_next (domain, "passwd.byname", ent->oldkey, ent->oldkeylen,
679 &outkey, &outkeylen, &outval, &outvallen)
680 != YPERR_SUCCESS)
681 {
682 ent->nis = 0;
683 give_pwd_free (&ent->pwd);
684 *errnop = ENOENT;
685 return NSS_STATUS_NOTFOUND;
686 }
687
688 if (buflen < ((size_t) outvallen + 1))
689 {
690 free (outval);
691 *errnop = ERANGE;
692 return NSS_STATUS_TRYAGAIN;
693 }
694
695 saved_first = FALSE;
696 saved_oldkey = ent->oldkey;
697 saved_oldlen = ent->oldkeylen;
698 ent->oldkey = outkey;
699 ent->oldkeylen = outkeylen;
700 }
701
702 /* Copy the found data to our buffer */
703 p = strncpy (buffer, outval, buflen);
704
705 /* ...and free the data. */
706 free (outval);
707
708 while (isspace (*p))
709 ++p;
710 parse_res = _nss_files_parse_pwent (p, result, data, buflen, errnop);
711 if (parse_res == -1)
712 {
713 free (ent->oldkey);
714 ent->oldkey = saved_oldkey;
715 ent->oldkeylen = saved_oldlen;
716 ent->first = saved_first;
717 *errnop = ERANGE;
718 return NSS_STATUS_TRYAGAIN;
719 }
720 else
721 {
722 if (!saved_first)
723 free (saved_oldkey);
724 }
725 if (parse_res
726 && in_blacklist (result->pw_name, strlen (result->pw_name), ent))
727 parse_res = 0;
728 }
729 while (!parse_res);
730
731 copy_pwd_changes (result, &ent->pwd, p2, p2len);
732
733 return NSS_STATUS_SUCCESS;
734 }
735
736 /* This function handle the +user entrys in /etc/passwd */
737 static enum nss_status
738 getpwnam_plususer (const char *name, struct passwd *result, char *buffer,
739 size_t buflen, int *errnop)
740 {
741 struct parser_data *data = (void *) buffer;
742 struct passwd pwd;
743 int parse_res;
744 char *p;
745 size_t plen;
746
747 memset (&pwd, '\0', sizeof (struct passwd));
748
749 copy_pwd_changes (&pwd, result, NULL, 0);
750
751 plen = pwd_need_buflen (&pwd);
752 if (plen > buflen)
753 {
754 *errnop = ERANGE;
755 return NSS_STATUS_TRYAGAIN;
756 }
757 p = buffer + (buflen - plen);
758 buflen -= plen;
759
760 if (use_nisplus) /* Do the NIS+ query here */
761 {
762 nis_result *res;
763 char buf[strlen (name) + 24 + pwdtablelen];
764
765 sprintf(buf, "[name=%s],%s", name, pwdtable);
766 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
767 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
768 {
769 enum nss_status status = niserr2nss (res->status);
770
771 nis_freeresult (res);
772 return status;
773 }
774 parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
775 buflen, errnop);
776 if (parse_res == -1)
777 {
778 nis_freeresult (res);
779 *errnop = ERANGE;
780 return NSS_STATUS_TRYAGAIN;
781 }
782 nis_freeresult (res);
783 }
784 else /* Use NIS */
785 {
786 char *domain, *outval, *ptr;
787 int outvallen;
788
789 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
790 return NSS_STATUS_NOTFOUND;
791
792 if (yp_match (domain, "passwd.byname", name, strlen (name),
793 &outval, &outvallen) != YPERR_SUCCESS)
794 {
795 *errnop = ENOENT;
796 return NSS_STATUS_NOTFOUND;
797 }
798
799 if (buflen < ((size_t) outvallen + 1))
800 {
801 free (outval);
802 *errnop = ERANGE;
803 return NSS_STATUS_TRYAGAIN;
804 }
805 ptr = strncpy (buffer, outval, buflen);
806 free (outval);
807 while (isspace (*ptr))
808 ptr++;
809 parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop);
810 if (parse_res == -1)
811 return NSS_STATUS_TRYAGAIN;
812 }
813
814 if (parse_res > 0)
815 {
816 copy_pwd_changes (result, &pwd, p, plen);
817 give_pwd_free (&pwd);
818 /* We found the entry. */
819 return NSS_STATUS_SUCCESS;
820 }
821 else
822 {
823 /* Give buffer the old len back */
824 buflen += plen;
825 give_pwd_free (&pwd);
826 }
827 return NSS_STATUS_RETURN;
828 }
829
830 static enum nss_status
831 getpwent_next_file (struct passwd *result, ent_t *ent,
832 char *buffer, size_t buflen, int *errnop)
833 {
834 struct parser_data *data = (void *) buffer;
835 while (1)
836 {
837 fpos_t pos;
838 char *p;
839 int parse_res;
840
841 do
842 {
843 fgetpos (ent->stream, &pos);
844 buffer[buflen - 1] = '\xff';
845 p = fgets (buffer, buflen, ent->stream);
846 if (p == NULL && feof (ent->stream))
847 {
848 *errnop = ENOENT;
849 return NSS_STATUS_NOTFOUND;
850 }
851 if (p == NULL || buffer[buflen - 1] != '\xff')
852 {
853 fsetpos (ent->stream, &pos);
854 *errnop = ERANGE;
855 return NSS_STATUS_TRYAGAIN;
856 }
857
858 /* Terminate the line for any case. */
859 buffer[buflen - 1] = '\0';
860
861 /* Skip leading blanks. */
862 while (isspace (*p))
863 ++p;
864 }
865 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
866 /* Parse the line. If it is invalid, loop to
867 get the next line of the file to parse. */
868 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
869 errnop)));
870
871 if (parse_res == -1)
872 {
873 /* The parser ran out of space. */
874 fsetpos (ent->stream, &pos);
875 *errnop = ERANGE;
876 return NSS_STATUS_TRYAGAIN;
877 }
878
879 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
880 /* This is a real entry. */
881 break;
882
883 /* -@netgroup */
884 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
885 && result->pw_name[2] != '\0')
886 {
887 /* XXX Do not use fixed length buffer. */
888 char buf2[1024];
889 char *user, *host, *domain;
890 struct __netgrent netgrdata;
891
892 bzero (&netgrdata, sizeof (struct __netgrent));
893 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
894 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
895 buf2, sizeof (buf2), errnop))
896 {
897 if (user != NULL && user[0] != '-')
898 blacklist_store_name (user, ent);
899 }
900 __internal_endnetgrent (&netgrdata);
901 continue;
902 }
903
904 /* +@netgroup */
905 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
906 && result->pw_name[2] != '\0')
907 {
908 int status;
909
910 ent->netgroup = TRUE;
911 ent->first = TRUE;
912 copy_pwd_changes (&ent->pwd, result, NULL, 0);
913
914 if (use_nisplus)
915 status = getpwent_next_nisplus_netgr (NULL, result, ent,
916 &result->pw_name[2],
917 buffer, buflen, errnop);
918 else
919 status = getpwent_next_nis_netgr (NULL, result, ent,
920 &result->pw_name[2],
921 buffer, buflen, errnop);
922 if (status == NSS_STATUS_RETURN)
923 continue;
924 else
925 {
926 if (status == NSS_STATUS_NOTFOUND)
927 *errnop = ENOENT;
928 return status;
929 }
930 }
931
932 /* -user */
933 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
934 && result->pw_name[1] != '@')
935 {
936 blacklist_store_name (&result->pw_name[1], ent);
937 continue;
938 }
939
940 /* +user */
941 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
942 && result->pw_name[1] != '@')
943 {
944 enum nss_status status;
945
946 /* Store the User in the blacklist for the "+" at the end of
947 /etc/passwd */
948 blacklist_store_name (&result->pw_name[1], ent);
949 status = getpwnam_plususer (&result->pw_name[1], result, buffer,
950 buflen, errnop);
951 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
952 break;
953 else
954 if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
955 || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */
956 continue;
957 else
958 {
959 if (status == NSS_STATUS_TRYAGAIN)
960 {
961 /* The parser ran out of space */
962 fsetpos (ent->stream, &pos);
963 *errnop = ERANGE;
964 }
965 return status;
966 }
967 }
968
969 /* +:... */
970 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
971 {
972 ent->nis = TRUE;
973 ent->first = TRUE;
974 copy_pwd_changes (&ent->pwd, result, NULL, 0);
975
976 if (use_nisplus)
977 return getpwent_next_nisplus (result, ent, buffer, buflen, errnop);
978 else
979 return getpwent_next_nis (result, ent, buffer, buflen, errnop);
980 }
981 }
982
983 return NSS_STATUS_SUCCESS;
984 }
985
986
987 static enum nss_status
988 internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer,
989 size_t buflen, int *errnop)
990 {
991 if (ent->netgroup)
992 {
993 int status;
994
995 /* We are searching members in a netgroup */
996 /* Since this is not the first call, we don't need the group name */
997 if (use_nisplus)
998 status = getpwent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer,
999 buflen, errnop);
1000 else
1001 status = getpwent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen,
1002 errnop);
1003 if (status == NSS_STATUS_RETURN)
1004 return getpwent_next_file (pw, ent, buffer, buflen, errnop);
1005 else
1006 return status;
1007 }
1008 else
1009 if (ent->nis)
1010 {
1011 if (use_nisplus)
1012 return getpwent_next_nisplus (pw, ent, buffer, buflen, errnop);
1013 else
1014 return getpwent_next_nis (pw, ent, buffer, buflen, errnop);
1015 }
1016 else
1017 return getpwent_next_file (pw, ent, buffer, buflen, errnop);
1018 }
1019
1020 enum nss_status
1021 _nss_compat_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen,
1022 int *errnop)
1023 {
1024 enum nss_status status = NSS_STATUS_SUCCESS;
1025
1026 __libc_lock_lock (lock);
1027
1028 if (ni == NULL)
1029 {
1030 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
1031 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
1032 }
1033
1034 /* Be prepared that the setpwent function was not called before. */
1035 if (ext_ent.stream == NULL)
1036 status = internal_setpwent (&ext_ent);
1037
1038 if (status == NSS_STATUS_SUCCESS)
1039 status = internal_getpwent_r (pwd, &ext_ent, buffer, buflen, errnop);
1040
1041 __libc_lock_unlock (lock);
1042
1043 return status;
1044 }
1045
1046 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
1047 static enum nss_status
1048 internal_getpwnam_r (const char *name, struct passwd *result, ent_t *ent,
1049 char *buffer, size_t buflen, int *errnop)
1050 {
1051 struct parser_data *data = (void *) buffer;
1052
1053 while (1)
1054 {
1055 fpos_t pos;
1056 char *p;
1057 int parse_res;
1058
1059 do
1060 {
1061 fgetpos (ent->stream, &pos);
1062 buffer[buflen - 1] = '\xff';
1063 p = fgets (buffer, buflen, ent->stream);
1064 if (p == NULL && feof (ent->stream))
1065 {
1066 *errnop = ENOENT;
1067 return NSS_STATUS_NOTFOUND;
1068 }
1069 if (p == NULL || buffer[buflen - 1] != '\xff')
1070 {
1071 fsetpos (ent->stream, &pos);
1072 *errnop = ERANGE;
1073 return NSS_STATUS_TRYAGAIN;
1074 }
1075
1076 /* Terminate the line for any case. */
1077 buffer[buflen - 1] = '\0';
1078
1079 /* Skip leading blanks. */
1080 while (isspace (*p))
1081 ++p;
1082 }
1083 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
1084 /* Parse the line. If it is invalid, loop to
1085 get the next line of the file to parse. */
1086 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
1087 errnop)));
1088
1089 if (parse_res == -1)
1090 {
1091 /* The parser ran out of space. */
1092 fsetpos (ent->stream, &pos);
1093 *errnop = ERANGE;
1094 return NSS_STATUS_TRYAGAIN;
1095 }
1096
1097 /* This is a real entry. */
1098 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
1099 {
1100 if (strcmp (result->pw_name, name) == 0)
1101 return NSS_STATUS_SUCCESS;
1102 else
1103 continue;
1104 }
1105
1106 /* -@netgroup */
1107 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
1108 && result->pw_name[2] != '\0')
1109 {
1110 /* XXX Do not use fixed length buffers. */
1111 char buf2[1024];
1112 char *user, *host, *domain;
1113 struct __netgrent netgrdata;
1114
1115 bzero (&netgrdata, sizeof (struct __netgrent));
1116 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
1117 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
1118 buf2, sizeof (buf2), errnop))
1119 {
1120 if (user != NULL && user[0] != '-')
1121 if (strcmp (user, name) == 0)
1122 return NSS_STATUS_NOTFOUND;
1123 }
1124 __internal_endnetgrent (&netgrdata);
1125 continue;
1126 }
1127
1128 /* +@netgroup */
1129 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
1130 && result->pw_name[2] != '\0')
1131 {
1132 char buf[strlen (result->pw_name)];
1133 int status;
1134
1135 strcpy (buf, &result->pw_name[2]);
1136 ent->netgroup = TRUE;
1137 ent->first = TRUE;
1138 copy_pwd_changes (&ent->pwd, result, NULL, 0);
1139
1140 do
1141 {
1142 if (use_nisplus)
1143 status = getpwent_next_nisplus_netgr (name, result, ent, buf,
1144 buffer, buflen, errnop);
1145 else
1146 status = getpwent_next_nis_netgr (name, result, ent, buf,
1147 buffer, buflen, errnop);
1148 if (status == NSS_STATUS_RETURN)
1149 continue;
1150
1151 if (status == NSS_STATUS_SUCCESS &&
1152 strcmp (result->pw_name, name) == 0)
1153 return NSS_STATUS_SUCCESS;
1154 } while (status == NSS_STATUS_SUCCESS);
1155 continue;
1156 }
1157
1158 /* -user */
1159 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
1160 && result->pw_name[1] != '@')
1161 {
1162 if (strcmp (&result->pw_name[1], name) == 0)
1163 {
1164 *errnop = ENOENT;
1165 return NSS_STATUS_NOTFOUND;
1166 }
1167 else
1168 continue;
1169 }
1170
1171 /* +user */
1172 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
1173 && result->pw_name[1] != '@')
1174 {
1175 if (strcmp (name, &result->pw_name[1]) == 0)
1176 {
1177 enum nss_status status;
1178
1179 status = getpwnam_plususer (name, result, buffer, buflen,
1180 errnop);
1181 if (status == NSS_STATUS_RETURN)
1182 /* We couldn't parse the entry */
1183 return NSS_STATUS_NOTFOUND;
1184 else
1185 return status;
1186 }
1187 }
1188
1189 /* +:... */
1190 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
1191 {
1192 enum nss_status status;
1193
1194 status = getpwnam_plususer (name, result, buffer, buflen, errnop);
1195 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
1196 break;
1197 else
1198 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
1199 return NSS_STATUS_NOTFOUND;
1200 else
1201 return status;
1202 }
1203 }
1204 return NSS_STATUS_SUCCESS;
1205 }
1206
1207 enum nss_status
1208 _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
1209 char *buffer, size_t buflen, int *errnop)
1210 {
1211 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
1212 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
1213 enum nss_status status;
1214
1215 if (name[0] == '-' || name[0] == '+')
1216 {
1217 *errnop = ENOENT;
1218 return NSS_STATUS_NOTFOUND;
1219 }
1220
1221 __libc_lock_lock (lock);
1222
1223 if (ni == NULL)
1224 {
1225 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
1226 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
1227 }
1228
1229 __libc_lock_unlock (lock);
1230
1231 status = internal_setpwent (&ent);
1232 if (status != NSS_STATUS_SUCCESS)
1233 return status;
1234
1235 status = internal_getpwnam_r (name, pwd, &ent, buffer, buflen, errnop);
1236
1237 internal_endpwent (&ent);
1238
1239 return status;
1240 }
1241
1242 /* This function handle the + entry in /etc/passwd for getpwuid */
1243 static enum nss_status
1244 getpwuid_plususer (uid_t uid, struct passwd *result, char *buffer,
1245 size_t buflen, int *errnop)
1246 {
1247 struct parser_data *data = (void *) buffer;
1248 struct passwd pwd;
1249 int parse_res;
1250 char *p;
1251 size_t plen;
1252
1253 memset (&pwd, '\0', sizeof (struct passwd));
1254
1255 copy_pwd_changes (&pwd, result, NULL, 0);
1256
1257 plen = pwd_need_buflen (&pwd);
1258 if (plen > buflen)
1259 {
1260 *errnop = ERANGE;
1261 return NSS_STATUS_TRYAGAIN;
1262 }
1263 p = buffer + (buflen - plen);
1264 buflen -= plen;
1265
1266 if (use_nisplus) /* Do the NIS+ query here */
1267 {
1268 nis_result *res;
1269 char buf[1024 + pwdtablelen];
1270
1271 snprintf(buf, sizeof (buf), "[uid=%d],%s", uid, pwdtable);
1272 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
1273 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
1274 {
1275 enum nss_status status = niserr2nss (res->status);
1276
1277 nis_freeresult (res);
1278 return status;
1279 }
1280 if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
1281 buflen, errnop)) == -1)
1282 {
1283 nis_freeresult (res);
1284 *errnop = ERANGE;
1285 return NSS_STATUS_TRYAGAIN;
1286 }
1287 nis_freeresult (res);
1288 }
1289 else /* Use NIS */
1290 {
1291 char buf[1024];
1292 char *domain, *outval, *ptr;
1293 int outvallen;
1294
1295 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
1296 {
1297 *errnop = errno;
1298 return NSS_STATUS_TRYAGAIN;
1299 }
1300
1301 sprintf (buf, "%d", uid);
1302 if (yp_match (domain, "passwd.byuid", buf, strlen (buf),
1303 &outval, &outvallen)
1304 != YPERR_SUCCESS)
1305 {
1306 *errnop = errno;
1307 return NSS_STATUS_TRYAGAIN;
1308 }
1309
1310 if ( buflen < ((size_t) outvallen + 1))
1311 {
1312 free (outval);
1313 *errnop = ERANGE;
1314 return NSS_STATUS_TRYAGAIN;
1315 }
1316
1317 ptr = strncpy (buffer, outval, buflen);
1318 free (outval);
1319
1320 while (isspace (*ptr))
1321 ptr++;
1322 parse_res = _nss_files_parse_pwent (ptr, result, data, buflen, errnop);
1323 if (parse_res == -1)
1324 return NSS_STATUS_TRYAGAIN;
1325 }
1326
1327 if (parse_res > 0)
1328 {
1329 copy_pwd_changes (result, &pwd, p, plen);
1330 give_pwd_free (&pwd);
1331 /* We found the entry. */
1332 return NSS_STATUS_SUCCESS;
1333 }
1334 else
1335 {
1336 /* Give buffer the old len back */
1337 buflen += plen;
1338 give_pwd_free (&pwd);
1339 }
1340 return NSS_STATUS_RETURN;
1341 }
1342
1343 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
1344 static enum nss_status
1345 internal_getpwuid_r (uid_t uid, struct passwd *result, ent_t *ent,
1346 char *buffer, size_t buflen, int *errnop)
1347 {
1348 struct parser_data *data = (void *) buffer;
1349
1350 while (1)
1351 {
1352 fpos_t pos;
1353 char *p;
1354 int parse_res;
1355
1356 do
1357 {
1358 fgetpos (ent->stream, &pos);
1359 buffer[buflen - 1] = '\xff';
1360 p = fgets (buffer, buflen, ent->stream);
1361 if (p == NULL && feof (ent->stream))
1362 return NSS_STATUS_NOTFOUND;
1363 if (p == NULL || buffer[buflen - 1] != '\xff')
1364 {
1365 fsetpos (ent->stream, &pos);
1366 *errnop = ERANGE;
1367 return NSS_STATUS_TRYAGAIN;
1368 }
1369
1370 /* Terminate the line for any case. */
1371 buffer[buflen - 1] = '\0';
1372
1373 /* Skip leading blanks. */
1374 while (isspace (*p))
1375 ++p;
1376 }
1377 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
1378 /* Parse the line. If it is invalid, loop to
1379 get the next line of the file to parse. */
1380 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen,
1381 errnop)));
1382
1383 if (parse_res == -1)
1384 {
1385 /* The parser ran out of space. */
1386 fsetpos (ent->stream, &pos);
1387 *errnop = ERANGE;
1388 return NSS_STATUS_TRYAGAIN;
1389 }
1390
1391 /* This is a real entry. */
1392 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
1393 {
1394 if (result->pw_uid == uid)
1395 return NSS_STATUS_SUCCESS;
1396 else
1397 continue;
1398 }
1399
1400 /* -@netgroup */
1401 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
1402 && result->pw_name[2] != '\0')
1403 {
1404 /* XXX Do not use fixed length buffers. */
1405 char buf2[1024];
1406 char *user, *host, *domain;
1407 struct __netgrent netgrdata;
1408
1409 bzero (&netgrdata, sizeof (struct __netgrent));
1410 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
1411 while (__internal_getnetgrent_r (&host, &user, &domain, &netgrdata,
1412 buf2, sizeof (buf2), errnop))
1413 {
1414 if (user != NULL && user[0] != '-')
1415 blacklist_store_name (user, ent);
1416 }
1417 __internal_endnetgrent (&netgrdata);
1418 continue;
1419 }
1420
1421 /* +@netgroup */
1422 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
1423 && result->pw_name[2] != '\0')
1424 {
1425 char buf[strlen (result->pw_name)];
1426 int status;
1427
1428 strcpy (buf, &result->pw_name[2]);
1429 ent->netgroup = TRUE;
1430 ent->first = TRUE;
1431 copy_pwd_changes (&ent->pwd, result, NULL, 0);
1432
1433 do
1434 {
1435 if (use_nisplus)
1436 status = getpwent_next_nisplus_netgr (NULL, result, ent, buf,
1437 buffer, buflen, errnop);
1438 else
1439 status = getpwent_next_nis_netgr (NULL, result, ent, buf,
1440 buffer, buflen, errnop);
1441 if (status == NSS_STATUS_RETURN)
1442 continue;
1443
1444 if (status == NSS_STATUS_SUCCESS && uid == result->pw_uid)
1445 return NSS_STATUS_SUCCESS;
1446 } while (status == NSS_STATUS_SUCCESS);
1447 continue;
1448 }
1449
1450 /* -user */
1451 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
1452 && result->pw_name[1] != '@')
1453 {
1454 blacklist_store_name (&result->pw_name[1], ent);
1455 continue;
1456 }
1457
1458 /* +user */
1459 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
1460 && result->pw_name[1] != '@')
1461 {
1462 enum nss_status status;
1463
1464 /* Store the User in the blacklist for the "+" at the end of
1465 /etc/passwd */
1466 blacklist_store_name (&result->pw_name[1], ent);
1467 status = getpwnam_plususer (&result->pw_name[1], result, buffer,
1468 buflen, errnop);
1469 if (status == NSS_STATUS_SUCCESS && result->pw_uid == uid)
1470 break;
1471 else
1472 continue;
1473 }
1474
1475 /* +:... */
1476 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
1477 {
1478 enum nss_status status;
1479
1480 status = getpwuid_plususer (uid, result, buffer, buflen, errnop);
1481 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
1482 break;
1483 else
1484 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
1485 return NSS_STATUS_NOTFOUND;
1486 else
1487 return status;
1488 }
1489 }
1490 return NSS_STATUS_SUCCESS;
1491 }
1492
1493 enum nss_status
1494 _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
1495 char *buffer, size_t buflen, int *errnop)
1496 {
1497 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
1498 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
1499 enum nss_status status;
1500
1501 __libc_lock_lock (lock);
1502
1503 if (ni == NULL)
1504 {
1505 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
1506 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
1507 }
1508
1509 __libc_lock_unlock (lock);
1510
1511 status = internal_setpwent (&ent);
1512 if (status != NSS_STATUS_SUCCESS)
1513 return status;
1514
1515 status = internal_getpwuid_r (uid, pwd, &ent, buffer, buflen, errnop);
1516
1517 internal_endpwent (&ent);
1518
1519 return status;
1520 }
1521
1522
1523 /* Support routines for remembering -@netgroup and -user entries.
1524 The names are stored in a single string with `|' as separator. */
1525 static void
1526 blacklist_store_name (const char *name, ent_t *ent)
1527 {
1528 int namelen = strlen (name);
1529 char *tmp;
1530
1531 /* first call, setup cache */
1532 if (ent->blacklist.size == 0)
1533 {
1534 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
1535 ent->blacklist.data = malloc (ent->blacklist.size);
1536 if (ent->blacklist.data == NULL)
1537 return;
1538 ent->blacklist.data[0] = '|';
1539 ent->blacklist.data[1] = '\0';
1540 ent->blacklist.current = 1;
1541 }
1542 else
1543 {
1544 if (in_blacklist (name, namelen, ent))
1545 return; /* no duplicates */
1546
1547 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
1548 {
1549 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
1550 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
1551 if (tmp == NULL)
1552 {
1553 free (ent->blacklist.data);
1554 ent->blacklist.size = 0;
1555 return;
1556 }
1557 ent->blacklist.data = tmp;
1558 }
1559 }
1560
1561 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
1562 *tmp++ = '|';
1563 *tmp = '\0';
1564 ent->blacklist.current += namelen + 1;
1565
1566 return;
1567 }
1568
1569 /* returns TRUE if ent->blacklist contains name, else FALSE */
1570 static bool_t
1571 in_blacklist (const char *name, int namelen, ent_t *ent)
1572 {
1573 char buf[namelen + 3];
1574 char *cp;
1575
1576 if (ent->blacklist.data == NULL)
1577 return FALSE;
1578
1579 buf[0] = '|';
1580 cp = stpcpy (&buf[1], name);
1581 *cp++= '|';
1582 *cp = '\0';
1583 return strstr (ent->blacklist.data, buf) != NULL;
1584 }
This page took 0.109011 seconds and 6 git commands to generate.