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