]> 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 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 <netdb.h>
25 #include <string.h>
26 #include <bits/libc-lock.h>
27 #include <rpcsvc/yp.h>
28 #include <rpcsvc/ypclnt.h>
29 #include <rpcsvc/nis.h>
30 #include <rpcsvc/nislib.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 char buf [20 + strlen (nis_local_directory ())];
215 char *p;
216
217 p = stpcpy (buf, "passwd.org_dir.");
218 p = stpcpy (p, nis_local_directory ());
219 pwdtable = strdup (buf);
220 if (pwdtable == NULL)
221 return NSS_STATUS_TRYAGAIN;
222 pwdtablelen = strlen (pwdtable);
223 }
224
225 ent->blacklist.current = 0;
226 if (ent->blacklist.data != NULL)
227 ent->blacklist.data[0] = '\0';
228
229 if (ent->stream == NULL)
230 {
231 ent->stream = fopen ("/etc/passwd", "r");
232
233 if (ent->stream == NULL)
234 status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
235 }
236 else
237 rewind (ent->stream);
238
239 give_pwd_free (&ent->pwd);
240
241 return status;
242 }
243
244
245 enum nss_status
246 _nss_compat_setpwent (void)
247 {
248 enum nss_status result;
249
250 __libc_lock_lock (lock);
251
252 if (ni == NULL)
253 {
254 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
255 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
256 }
257
258 result = internal_setpwent (&ext_ent);
259
260 __libc_lock_unlock (lock);
261
262 return result;
263 }
264
265
266 static enum nss_status
267 internal_endpwent (ent_t *ent)
268 {
269 if (ent->stream != NULL)
270 {
271 fclose (ent->stream);
272 ent->stream = NULL;
273 }
274
275 if (ent->netgroup)
276 __internal_endnetgrent (&ent->netgrdata);
277
278 ent->nis = ent->first = ent->netgroup = 0;
279
280 if (ent->oldkey != NULL)
281 {
282 free (ent->oldkey);
283 ent->oldkey = NULL;
284 ent->oldkeylen = 0;
285 }
286
287 if (ent->result != NULL)
288 {
289 nis_freeresult (ent->result);
290 ent->result = NULL;
291 }
292
293 ent->blacklist.current = 0;
294 if (ent->blacklist.data != NULL)
295 ent->blacklist.data[0] = '\0';
296
297 give_pwd_free (&ent->pwd);
298
299 return NSS_STATUS_SUCCESS;
300 }
301
302 enum nss_status
303 _nss_compat_endpwent (void)
304 {
305 enum nss_status result;
306
307 __libc_lock_lock (lock);
308
309 result = internal_endpwent (&ext_ent);
310
311 __libc_lock_unlock (lock);
312
313 return result;
314 }
315
316 static enum nss_status
317 getpwent_next_nis_netgr (struct passwd *result, ent_t *ent, char *group,
318 char *buffer, size_t buflen)
319 {
320 struct parser_data *data = (void *) buffer;
321 char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
322 int status, outvallen;
323 size_t p2len;
324
325 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
326 {
327 ent->netgroup = 0;
328 ent->first = 0;
329 give_pwd_free (&ent->pwd);
330 return NSS_STATUS_UNAVAIL;
331 }
332
333 if (ent->first == TRUE)
334 {
335 memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
336 __internal_setnetgrent (group, &ent->netgrdata);
337 ent->first = FALSE;
338 }
339
340 while (1)
341 {
342 char *saved_cursor;
343 int parse_res;
344
345 saved_cursor = ent->netgrdata.cursor;
346 status = __internal_getnetgrent_r (&host, &user, &domain,
347 &ent->netgrdata, buffer, buflen);
348 if (status != 1)
349 {
350 __internal_endnetgrent (&ent->netgrdata);
351 ent->netgroup = 0;
352 give_pwd_free (&ent->pwd);
353 return NSS_STATUS_RETURN;
354 }
355
356 if (user == NULL || user[0] == '-')
357 continue;
358
359 if (domain != NULL && strcmp (ypdomain, domain) != 0)
360 continue;
361
362 if (yp_match (ypdomain, "passwd.byname", user,
363 strlen (user), &outval, &outvallen)
364 != YPERR_SUCCESS)
365 continue;
366
367 p2len = pwd_need_buflen (&ent->pwd);
368 if (p2len > buflen)
369 {
370 __set_errno (ERANGE);
371 return NSS_STATUS_TRYAGAIN;
372 }
373 p2 = buffer + (buflen - p2len);
374 buflen -= p2len;
375 p = strncpy (buffer, outval, buflen);
376 while (isspace (*p))
377 p++;
378 free (outval);
379 if ((parse_res = _nss_files_parse_pwent (p, result, data, buflen)) == -1)
380 {
381 ent->netgrdata.cursor = saved_cursor;
382 return NSS_STATUS_TRYAGAIN;
383 }
384
385 if (parse_res)
386 {
387 copy_pwd_changes (result, &ent->pwd, p2, p2len);
388 break;
389 }
390 }
391
392 return NSS_STATUS_SUCCESS;
393 }
394
395 static enum nss_status
396 getpwent_next_nisplus_netgr (struct passwd *result, ent_t *ent, char *group,
397 char *buffer, size_t buflen)
398 {
399 char *ypdomain, *host, *user, *domain, *p2;
400 int status, parse_res;
401 size_t p2len;
402 nis_result *nisres;
403
404 /* Maybe we should use domainname here ? We need the current
405 domainname for the domain field in netgroups */
406 if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
407 {
408 ent->netgroup = 0;
409 ent->first = 0;
410 give_pwd_free (&ent->pwd);
411 return NSS_STATUS_UNAVAIL;
412 }
413
414 if (ent->first == TRUE)
415 {
416 bzero (&ent->netgrdata, sizeof (struct __netgrent));
417 __internal_setnetgrent (group, &ent->netgrdata);
418 ent->first = FALSE;
419 }
420
421 while (1)
422 {
423 char *saved_cursor;
424
425 saved_cursor = ent->netgrdata.cursor;
426 status = __internal_getnetgrent_r (&host, &user, &domain,
427 &ent->netgrdata, buffer, buflen);
428 if (status != 1)
429 {
430 __internal_endnetgrent (&ent->netgrdata);
431 ent->netgroup = 0;
432 give_pwd_free (&ent->pwd);
433 return NSS_STATUS_RETURN;
434 }
435
436 if (user == NULL || user[0] == '-')
437 continue;
438
439 if (domain != NULL && strcmp (ypdomain, domain) != 0)
440 continue;
441
442 p2len = pwd_need_buflen (&ent->pwd);
443 if (p2len > buflen)
444 {
445 __set_errno (ERANGE);
446 return NSS_STATUS_TRYAGAIN;
447 }
448 p2 = buffer + (buflen - p2len);
449 buflen -= p2len;
450 {
451 char buf[strlen (user) + 30 + pwdtablelen];
452 sprintf(buf, "[name=%s],%s", user, pwdtable);
453 nisres = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
454 }
455 if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS)
456 {
457 nis_freeresult (nisres);
458 continue;
459 }
460 if ((parse_res = _nss_nisplus_parse_pwent (nisres, result, buffer,
461 buflen)) == -1)
462 {
463 nis_freeresult (nisres);
464 ent->netgrdata.cursor = saved_cursor;
465 return NSS_STATUS_TRYAGAIN;
466 }
467 nis_freeresult (nisres);
468
469 if (parse_res)
470 {
471 copy_pwd_changes (result, &ent->pwd, p2, p2len);
472 break;
473 }
474 }
475
476 return NSS_STATUS_SUCCESS;
477 }
478
479 static enum nss_status
480 getpwent_next_netgr (struct passwd *result, ent_t *ent, char *group,
481 char *buffer, size_t buflen)
482 {
483 if (use_nisplus)
484 return getpwent_next_nisplus_netgr (result, ent, group, buffer, buflen);
485 else
486 return getpwent_next_nis_netgr (result, ent, group, buffer, buflen);
487 }
488
489 static enum nss_status
490 getpwent_next_nisplus (struct passwd *result, ent_t *ent, char *buffer,
491 size_t buflen)
492 {
493 int parse_res;
494 size_t p2len;
495 char *p2;
496
497 p2len = pwd_need_buflen (&ent->pwd);
498 if (p2len > buflen)
499 {
500 __set_errno (ERANGE);
501 return NSS_STATUS_TRYAGAIN;
502 }
503 p2 = buffer + (buflen - p2len);
504 buflen -= p2len;
505 do
506 {
507 bool_t saved_first;
508 nis_result *saved_res;
509
510 if (ent->first)
511 {
512 saved_first = TRUE;
513 saved_res = ent->result;
514
515 ent->result = nis_first_entry(pwdtable);
516 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
517 {
518 ent->nis = 0;
519 give_pwd_free (&ent->pwd);
520 return niserr2nss (ent->result->status);
521 }
522 ent->first = FALSE;
523 }
524 else
525 {
526 nis_result *res;
527
528 res = nis_next_entry(pwdtable, &ent->result->cookie);
529 saved_res = ent->result;
530 saved_first = FALSE;
531 ent->result = res;
532 if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
533 {
534 ent->nis = 0;
535 nis_freeresult (saved_res);
536 give_pwd_free (&ent->pwd);
537 return niserr2nss (ent->result->status);
538 }
539 }
540 if ((parse_res = _nss_nisplus_parse_pwent (ent->result, result, buffer,
541 buflen)) == -1)
542 {
543 nis_freeresult (ent->result);
544 ent->result = saved_res;
545 ent->first = saved_first;
546 __set_errno (ERANGE);
547 return NSS_STATUS_TRYAGAIN;
548 }
549 else
550 {
551 if (!saved_first)
552 nis_freeresult (saved_res);
553 }
554
555 if (parse_res &&
556 in_blacklist (result->pw_name, strlen (result->pw_name), ent))
557 parse_res = 0; /* if result->pw_name in blacklist,search next entry */
558 }
559 while (!parse_res);
560
561 copy_pwd_changes (result, &ent->pwd, p2, p2len);
562
563 return NSS_STATUS_SUCCESS;
564 }
565
566 static enum nss_status
567 getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer,
568 size_t buflen)
569 {
570 struct parser_data *data = (void *) buffer;
571 char *domain, *outkey, *outval, *p, *p2;
572 int outkeylen, outvallen, parse_res;
573 size_t p2len;
574
575 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
576 {
577 ent->nis = 0;
578 give_pwd_free (&ent->pwd);
579 return NSS_STATUS_UNAVAIL;
580 }
581
582 p2len = pwd_need_buflen (&ent->pwd);
583 if (p2len > buflen)
584 {
585 __set_errno (ERANGE);
586 return NSS_STATUS_TRYAGAIN;
587 }
588 p2 = buffer + (buflen - p2len);
589 buflen -= p2len;
590 do
591 {
592 bool_t saved_first;
593 char *saved_oldkey;
594 int saved_oldlen;
595
596 if (ent->first)
597 {
598 if (yp_first (domain, "passwd.byname", &outkey, &outkeylen,
599 &outval, &outvallen) != YPERR_SUCCESS)
600 {
601 ent->nis = 0;
602 give_pwd_free (&ent->pwd);
603 return NSS_STATUS_UNAVAIL;
604 }
605
606 saved_first = TRUE;
607 saved_oldkey = ent->oldkey;
608 saved_oldlen = ent->oldkeylen;
609 ent->oldkey = outkey;
610 ent->oldkeylen = outkeylen;
611 ent->first = FALSE;
612 }
613 else
614 {
615 if (yp_next (domain, "passwd.byname", ent->oldkey, ent->oldkeylen,
616 &outkey, &outkeylen, &outval, &outvallen)
617 != YPERR_SUCCESS)
618 {
619 ent->nis = 0;
620 give_pwd_free (&ent->pwd);
621 return NSS_STATUS_NOTFOUND;
622 }
623
624 saved_first = FALSE;
625 saved_oldkey = ent->oldkey;
626 saved_oldlen = ent->oldkeylen;
627 ent->oldkey = outkey;
628 ent->oldkeylen = outkeylen;
629 }
630
631 /* Copy the found data to our buffer */
632 p = strncpy (buffer, outval, buflen);
633
634 /* ...and free the data. */
635 free (outval);
636
637 while (isspace (*p))
638 ++p;
639 if ((parse_res = _nss_files_parse_pwent (p, result, data, buflen)) == -1)
640 {
641 free (ent->oldkey);
642 ent->oldkey = saved_oldkey;
643 ent->oldkeylen = saved_oldlen;
644 ent->first = saved_first;
645 __set_errno (ERANGE);
646 return NSS_STATUS_TRYAGAIN;
647 }
648 else
649 {
650 if (!saved_first)
651 free (saved_oldkey);
652 }
653 if (parse_res &&
654 in_blacklist (result->pw_name, strlen (result->pw_name), ent))
655 parse_res = 0;
656 }
657 while (!parse_res);
658
659 copy_pwd_changes (result, &ent->pwd, p2, p2len);
660
661 return NSS_STATUS_SUCCESS;
662 }
663
664 /* This function handle the +user entrys in /etc/passwd */
665 static enum nss_status
666 getpwent_next_file_plususer (struct passwd *result, char *buffer,
667 size_t buflen)
668 {
669 struct parser_data *data = (void *) buffer;
670 struct passwd pwd;
671 int parse_res;
672 char *p;
673 size_t plen;
674
675 memset (&pwd, '\0', sizeof (struct passwd));
676
677 copy_pwd_changes (&pwd, result, NULL, 0);
678
679 plen = pwd_need_buflen (&pwd);
680 if (plen > buflen)
681 {
682 __set_errno (ERANGE);
683 return NSS_STATUS_TRYAGAIN;
684 }
685 p = buffer + (buflen - plen);
686 buflen -= plen;
687
688 if (use_nisplus) /* Do the NIS+ query here */
689 {
690 nis_result *res;
691 char buf[strlen (result->pw_name) + 24 + pwdtablelen];
692
693 sprintf(buf, "[name=%s],%s", &result->pw_name[1], pwdtable);
694 res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
695 if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
696 {
697 enum nss_status status = niserr2nss (res->status);
698
699 nis_freeresult (res);
700 return status;
701 }
702 if ((parse_res = _nss_nisplus_parse_pwent (res, result, buffer,
703 buflen)) == -1)
704 {
705 nis_freeresult (res);
706 __set_errno (ERANGE);
707 return NSS_STATUS_TRYAGAIN;
708 }
709 nis_freeresult (res);
710 }
711 else /* Use NIS */
712 {
713 char *domain;
714 char *outval;
715 int outvallen;
716
717 if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
718 return NSS_STATUS_TRYAGAIN;
719
720 if (yp_match (domain, "passwd.byname", &result->pw_name[1],
721 strlen (result->pw_name) - 1, &outval, &outvallen)
722 != YPERR_SUCCESS)
723 return NSS_STATUS_TRYAGAIN;
724 p = strncpy (buffer, outval,
725 buflen < (size_t) outvallen ? buflen : (size_t) outvallen);
726 free (outval);
727 while (isspace (*p))
728 p++;
729 if ((parse_res = _nss_files_parse_pwent (p, result, data, buflen)) == -1)
730 {
731 __set_errno (ERANGE);
732 return NSS_STATUS_TRYAGAIN;
733 }
734 }
735
736 if (parse_res > 0)
737 {
738 copy_pwd_changes (result, &pwd, p, plen);
739 give_pwd_free (&pwd);
740 /* We found the entry. */
741 return NSS_STATUS_SUCCESS;
742 }
743 else
744 {
745 /* Give buffer the old len back */
746 buflen += plen;
747 give_pwd_free (&pwd);
748 }
749 return NSS_STATUS_RETURN;
750 }
751
752 static enum nss_status
753 getpwent_next_file (struct passwd *result, ent_t *ent,
754 char *buffer, size_t buflen)
755 {
756 struct parser_data *data = (void *) buffer;
757 while (1)
758 {
759 fpos_t pos;
760 char *p;
761 int parse_res;
762
763 do
764 {
765 fgetpos (ent->stream, &pos);
766 p = fgets (buffer, buflen, ent->stream);
767 if (p == NULL)
768 return NSS_STATUS_NOTFOUND;
769
770 /* Terminate the line for any case. */
771 buffer[buflen - 1] = '\0';
772
773 /* Skip leading blanks. */
774 while (isspace (*p))
775 ++p;
776 }
777 while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */
778 /* Parse the line. If it is invalid, loop to
779 get the next line of the file to parse. */
780 !(parse_res = _nss_files_parse_pwent (p, result, data, buflen)));
781
782 if (parse_res == -1)
783 {
784 /* The parser ran out of space. */
785 fsetpos (ent->stream, &pos);
786 __set_errno (ERANGE);
787 return NSS_STATUS_TRYAGAIN;
788 }
789
790 if (result->pw_name[0] != '+' && result->pw_name[0] != '-')
791 /* This is a real entry. */
792 break;
793
794 /* -@netgroup */
795 if (result->pw_name[0] == '-' && result->pw_name[1] == '@'
796 && result->pw_name[2] != '\0')
797 {
798 char buf2[1024];
799 char *user, *host, *domain;
800 struct __netgrent netgrdata;
801
802 bzero (&netgrdata, sizeof (struct __netgrent));
803 __internal_setnetgrent (&result->pw_name[2], &netgrdata);
804 while (__internal_getnetgrent_r (&host, &user, &domain,
805 &netgrdata, buf2, sizeof (buf2)))
806 {
807 if (user != NULL && user[0] != '-')
808 blacklist_store_name (user, ent);
809 }
810 __internal_endnetgrent (&netgrdata);
811 continue;
812 }
813
814 /* +@netgroup */
815 if (result->pw_name[0] == '+' && result->pw_name[1] == '@'
816 && result->pw_name[2] != '\0')
817 {
818 int status;
819
820 ent->netgroup = TRUE;
821 ent->first = TRUE;
822 copy_pwd_changes (&ent->pwd, result, NULL, 0);
823
824 status = getpwent_next_netgr (result, ent, &result->pw_name[2],
825 buffer, buflen);
826 if (status == NSS_STATUS_RETURN)
827 continue;
828 else
829 return status;
830 }
831
832 /* -user */
833 if (result->pw_name[0] == '-' && result->pw_name[1] != '\0'
834 && result->pw_name[1] != '@')
835 {
836 blacklist_store_name (&result->pw_name[1], ent);
837 continue;
838 }
839
840 /* +user */
841 if (result->pw_name[0] == '+' && result->pw_name[1] != '\0'
842 && result->pw_name[1] != '@')
843 {
844 enum nss_status status;
845
846 status = getpwent_next_file_plususer (result, buffer, buflen);
847 if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
848 break;
849 else
850 if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
851 continue;
852 else
853 return status;
854 }
855
856 /* +:... */
857 if (result->pw_name[0] == '+' && result->pw_name[1] == '\0')
858 {
859 ent->nis = TRUE;
860 ent->first = TRUE;
861 copy_pwd_changes (&ent->pwd, result, NULL, 0);
862
863 if (use_nisplus)
864 return getpwent_next_nisplus (result, ent, buffer, buflen);
865 else
866 return getpwent_next_nis (result, ent, buffer, buflen);
867 }
868 }
869
870 return NSS_STATUS_SUCCESS;
871 }
872
873
874 static enum nss_status
875 internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer,
876 size_t buflen)
877 {
878 if (ent->netgroup)
879 {
880 int status;
881
882 /* We are searching members in a netgroup */
883 /* Since this is not the first call, we don't need the group name */
884 status = getpwent_next_netgr (pw, ent, NULL, buffer, buflen);
885 if (status == NSS_STATUS_RETURN)
886 return getpwent_next_file (pw, ent, buffer, buflen);
887 else
888 return status;
889 }
890 else if (ent->nis)
891 {
892 if (use_nisplus)
893 return getpwent_next_nisplus (pw, ent, buffer, buflen);
894 else
895 return getpwent_next_nis (pw, ent, buffer, buflen);
896 }
897 else
898 return getpwent_next_file (pw, ent, buffer, buflen);
899 }
900
901 enum nss_status
902 _nss_compat_getpwent_r (struct passwd *pwd, char *buffer,
903 size_t buflen)
904 {
905 enum nss_status status = NSS_STATUS_SUCCESS;
906
907 __libc_lock_lock (lock);
908
909 if (ni == NULL)
910 {
911 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
912 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
913 }
914
915 /* Be prepared that the setpwent function was not called before. */
916 if (ext_ent.stream == NULL)
917 status = internal_setpwent (&ext_ent);
918
919 if (status == NSS_STATUS_SUCCESS)
920 status = internal_getpwent_r (pwd, &ext_ent, buffer, buflen);
921
922 __libc_lock_unlock (lock);
923
924 return status;
925 }
926
927
928 enum nss_status
929 _nss_compat_getpwnam_r (const char *name, struct passwd *pwd,
930 char *buffer, size_t buflen)
931 {
932 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
933 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
934 enum nss_status status;
935
936 if (name[0] == '-' || name[0] == '+')
937 return NSS_STATUS_NOTFOUND;
938
939 __libc_lock_lock (lock);
940
941 if (ni == NULL)
942 {
943 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
944 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
945 }
946
947 __libc_lock_unlock (lock);
948
949 status = internal_setpwent (&ent);
950 if (status != NSS_STATUS_SUCCESS)
951 return status;
952
953 while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen))
954 == NSS_STATUS_SUCCESS)
955 if (strcmp (pwd->pw_name, name) == 0)
956 break;
957
958 internal_endpwent (&ent);
959 return status;
960 }
961
962
963 enum nss_status
964 _nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd,
965 char *buffer, size_t buflen)
966 {
967 ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0},
968 {NULL, NULL, 0, 0, NULL, NULL, NULL}};
969 enum nss_status status;
970
971 __libc_lock_lock (lock);
972
973 if (ni == NULL)
974 {
975 __nss_database_lookup ("passwd_compat", NULL, "nis", &ni);
976 use_nisplus = (strcmp (ni->name, "nisplus") == 0);
977 }
978
979 __libc_lock_unlock (lock);
980
981 status = internal_setpwent (&ent);
982 if (status != NSS_STATUS_SUCCESS)
983 return status;
984
985 while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen))
986 == NSS_STATUS_SUCCESS)
987 if (pwd->pw_uid == uid && pwd->pw_name[0] != '+' && pwd->pw_name[0] != '-')
988 break;
989
990 internal_endpwent (&ent);
991 return status;
992 }
993
994
995 /* Support routines for remembering -@netgroup and -user entries.
996 The names are stored in a single string with `|' as separator. */
997 static void
998 blacklist_store_name (const char *name, ent_t *ent)
999 {
1000 int namelen = strlen (name);
1001 char *tmp;
1002
1003 /* first call, setup cache */
1004 if (ent->blacklist.size == 0)
1005 {
1006 ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen);
1007 ent->blacklist.data = malloc (ent->blacklist.size);
1008 if (ent->blacklist.data == NULL)
1009 return;
1010 ent->blacklist.data[0] = '|';
1011 ent->blacklist.data[1] = '\0';
1012 ent->blacklist.current = 1;
1013 }
1014 else
1015 {
1016 if (in_blacklist (name, namelen, ent))
1017 return; /* no duplicates */
1018
1019 if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size)
1020 {
1021 ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen);
1022 tmp = realloc (ent->blacklist.data, ent->blacklist.size);
1023 if (tmp == NULL)
1024 {
1025 free (ent->blacklist.data);
1026 ent->blacklist.size = 0;
1027 return;
1028 }
1029 ent->blacklist.data = tmp;
1030 }
1031 }
1032
1033 tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name);
1034 *tmp++ = '|';
1035 *tmp = '\0';
1036 ent->blacklist.current += namelen + 1;
1037
1038 return;
1039 }
1040
1041 /* returns TRUE if ent->blacklist contains name, else FALSE */
1042 static bool_t
1043 in_blacklist (const char *name, int namelen, ent_t *ent)
1044 {
1045 char buf[namelen + 3];
1046 char *cp;
1047
1048 if (ent->blacklist.data == NULL)
1049 return FALSE;
1050
1051 buf[0] = '|';
1052 cp = stpcpy (&buf[1], name);
1053 *cp++= '|';
1054 *cp = '\0';
1055 return strstr (ent->blacklist.data, buf) != NULL;
1056 }
This page took 0.08711 seconds and 6 git commands to generate.