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.
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.
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.
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. */
27 #include <bits/libc-lock.h>
28 #include <rpcsvc/yp.h>
29 #include <rpcsvc/ypclnt.h>
30 #include <rpcsvc/nis.h>
33 /* Comment out the following line for the production version. */
34 /* #define NDEBUG 1 */
38 #include "nss-nisplus.h"
39 #include "nisplus-parser.h"
41 static service_user
*ni
= NULL
;
42 static bool_t use_nisplus
= FALSE
; /* default: passwd_compat: nis */
43 static nis_name pwdtable
= NULL
; /* Name of the password table */
44 static size_t pwdtablelen
= 0;
46 /* Get the declaration of the parser function. */
48 #define STRUCTURE spwd
50 #include <nss/nss_files/files-parse.c>
52 /* Structure for remembering -@netgroup and -user members ... */
53 #define BLACKLIST_INITIAL_SIZE 512
54 #define BLACKLIST_INCREMENT 256
71 struct blacklist_t blacklist
;
73 struct __netgrent netgrdata
;
75 typedef struct ent_t ent_t
;
77 static ent_t ext_ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
78 {NULL
, NULL
, 0, 0, 0, 0, 0, 0, 0}};
80 /* Protect global state against multiple changers. */
81 __libc_lock_define_initialized (static, lock
)
83 /* Prototypes for local functions. */
84 static void blacklist_store_name (const char *, ent_t
*);
85 static int in_blacklist (const char *, int, ent_t
*);
88 give_spwd_free (struct spwd
*pwd
)
90 if (pwd
->sp_namp
!= NULL
)
92 if (pwd
->sp_pwdp
!= NULL
)
95 memset (pwd
, '\0', sizeof (struct spwd
));
99 spwd_need_buflen (struct spwd
*pwd
)
103 if (pwd
->sp_pwdp
!= NULL
)
104 len
+= strlen (pwd
->sp_pwdp
) + 1;
110 copy_spwd_changes (struct spwd
*dest
, struct spwd
*src
,
111 char *buffer
, size_t buflen
)
113 if (src
->sp_pwdp
!= NULL
&& strlen (src
->sp_pwdp
))
116 dest
->sp_pwdp
= strdup (src
->sp_pwdp
);
117 else if (dest
->sp_pwdp
&&
118 strlen (dest
->sp_pwdp
) >= strlen (src
->sp_pwdp
))
119 strcpy (dest
->sp_pwdp
, src
->sp_pwdp
);
122 dest
->sp_pwdp
= buffer
;
123 strcpy (dest
->sp_pwdp
, src
->sp_pwdp
);
124 buffer
+= strlen (dest
->sp_pwdp
) + 1;
125 buflen
= buflen
- (strlen (dest
->sp_pwdp
) + 1);
128 if (src
->sp_lstchg
!= 0)
129 dest
->sp_lstchg
= src
->sp_lstchg
;
130 if (src
->sp_min
!= 0)
131 dest
->sp_min
= src
->sp_min
;
132 if (src
->sp_max
!= 0)
133 dest
->sp_max
= src
->sp_max
;
134 if (src
->sp_warn
!= 0)
135 dest
->sp_warn
= src
->sp_warn
;
136 if (src
->sp_inact
!= 0)
137 dest
->sp_inact
= src
->sp_inact
;
138 if (src
->sp_expire
!= 0)
139 dest
->sp_expire
= src
->sp_expire
;
140 if (src
->sp_flag
!= 0)
141 dest
->sp_flag
= src
->sp_flag
;
144 static enum nss_status
145 internal_setspent (ent_t
*ent
)
147 enum nss_status status
= NSS_STATUS_SUCCESS
;
149 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
151 /* If something was left over free it. */
153 __internal_endnetgrent (&ent
->netgrdata
);
155 if (ent
->oldkey
!= NULL
)
162 if (ent
->result
!= NULL
)
164 nis_freeresult (ent
->result
);
168 if (pwdtable
== NULL
)
170 static const char key
[] = "passwd.org_dir.";
171 const char *local_dir
= nis_local_directory ();
172 size_t len_local_dir
= strlen (local_dir
);
174 pwdtable
= malloc (sizeof (key
) + len_local_dir
);
175 if (pwdtable
== NULL
)
176 return NSS_STATUS_TRYAGAIN
;
178 pwdtablelen
= ((char *) mempcpy (mempcpy (pwdtable
,
179 key
, sizeof (key
) - 1),
180 local_dir
, len_local_dir
+ 1)
183 /* *Maybe* (I'm no NIS expert) we have to duplicate the `local_dir'
184 value since it might change during our work. So add a test here. */
185 assert (pwdtablelen
== sizeof (key
) + len_local_dir
);
188 ent
->blacklist
.current
= 0;
189 if (ent
->blacklist
.data
!= NULL
)
190 ent
->blacklist
.data
[0] = '\0';
192 if (ent
->stream
== NULL
)
194 ent
->stream
= fopen ("/etc/shadow", "r");
196 if (ent
->stream
== NULL
)
197 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
200 /* We have to make sure the file is `closed on exec'. */
203 result
= flags
= fcntl (fileno (ent
->stream
), F_GETFD
, 0);
207 result
= fcntl (fileno (ent
->stream
), F_SETFD
, flags
);
211 /* Something went wrong. Close the stream and return a
213 fclose (ent
->stream
);
215 status
= NSS_STATUS_UNAVAIL
;
220 rewind (ent
->stream
);
222 give_spwd_free (&ent
->pwd
);
229 _nss_compat_setspent (void)
231 enum nss_status result
;
233 __libc_lock_lock (lock
);
237 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
238 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
241 result
= internal_setspent (&ext_ent
);
243 __libc_lock_unlock (lock
);
249 static enum nss_status
250 internal_endspent (ent_t
*ent
)
252 if (ent
->stream
!= NULL
)
254 fclose (ent
->stream
);
259 __internal_endnetgrent (&ent
->netgrdata
);
261 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
263 if (ent
->oldkey
!= NULL
)
270 if (ent
->result
!= NULL
)
272 nis_freeresult (ent
->result
);
276 ent
->blacklist
.current
= 0;
277 if (ent
->blacklist
.data
!= NULL
)
278 ent
->blacklist
.data
[0] = '\0';
280 give_spwd_free (&ent
->pwd
);
282 return NSS_STATUS_SUCCESS
;
286 _nss_compat_endspent (void)
288 enum nss_status result
;
290 __libc_lock_lock (lock
);
292 result
= internal_endspent (&ext_ent
);
294 __libc_lock_unlock (lock
);
300 static enum nss_status
301 getspent_next_nis_netgr (const char *name
, struct spwd
*result
, ent_t
*ent
,
302 char *group
, char *buffer
, size_t buflen
)
304 struct parser_data
*data
= (void *) buffer
;
305 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
306 int status
, outvallen
;
309 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
313 give_spwd_free (&ent
->pwd
);
314 return NSS_STATUS_UNAVAIL
;
317 if (ent
->first
== TRUE
)
319 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
320 __internal_setnetgrent (group
, &ent
->netgrdata
);
329 saved_cursor
= ent
->netgrdata
.cursor
;
330 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
331 &ent
->netgrdata
, buffer
, buflen
);
334 __internal_endnetgrent (&ent
->netgrdata
);
336 give_spwd_free (&ent
->pwd
);
337 return NSS_STATUS_RETURN
;
340 if (user
== NULL
|| user
[0] == '-')
343 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
346 /* If name != NULL, we are called from getpwnam */
348 if (strcmp (user
, name
) != 0)
351 if (yp_match (ypdomain
, "shadow.byname", user
,
352 strlen (user
), &outval
, &outvallen
)
356 p2len
= spwd_need_buflen (&ent
->pwd
);
359 __set_errno (ERANGE
);
360 return NSS_STATUS_TRYAGAIN
;
362 p2
= buffer
+ (buflen
- p2len
);
364 p
= strncpy (buffer
, outval
, buflen
);
368 if ((parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
)) == -1)
370 ent
->netgrdata
.cursor
= saved_cursor
;
371 return NSS_STATUS_TRYAGAIN
;
376 /* Store the User in the blacklist for the "+" at the end of
378 blacklist_store_name (result
->sp_namp
, ent
);
379 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
384 return NSS_STATUS_SUCCESS
;
387 static enum nss_status
388 getspent_next_nisplus_netgr (const char *name
, struct spwd
*result
,
389 ent_t
*ent
, char *group
, char *buffer
,
392 char *ypdomain
, *host
, *user
, *domain
, *p2
;
393 int status
, parse_res
;
397 /* Maybe we should use domainname here ? We need the current
398 domainname for the domain field in netgroups */
399 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
403 give_spwd_free (&ent
->pwd
);
404 return NSS_STATUS_UNAVAIL
;
407 if (ent
->first
== TRUE
)
409 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
410 __internal_setnetgrent (group
, &ent
->netgrdata
);
418 saved_cursor
= ent
->netgrdata
.cursor
;
419 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
420 &ent
->netgrdata
, buffer
, buflen
);
423 __internal_endnetgrent (&ent
->netgrdata
);
425 give_spwd_free (&ent
->pwd
);
426 return NSS_STATUS_RETURN
;
429 if (user
== NULL
|| user
[0] == '-')
432 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
435 /* If name != NULL, we are called from getpwnam */
437 if (strcmp (user
, name
) != 0)
440 p2len
= spwd_need_buflen (&ent
->pwd
);
443 __set_errno (ERANGE
);
444 return NSS_STATUS_TRYAGAIN
;
446 p2
= buffer
+ (buflen
- p2len
);
449 char buf
[strlen (user
) + 30 + pwdtablelen
];
450 sprintf(buf
, "[name=%s],%s", user
, pwdtable
);
451 nisres
= nis_list(buf
, FOLLOW_LINKS
| FOLLOW_PATH
, NULL
, NULL
);
453 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
455 nis_freeresult (nisres
);
458 if ((parse_res
= _nss_nisplus_parse_spent (nisres
, result
, buffer
,
461 nis_freeresult (nisres
);
462 return NSS_STATUS_TRYAGAIN
;
464 nis_freeresult (nisres
);
468 /* Store the User in the blacklist for the "+" at the end of
470 blacklist_store_name (result
->sp_namp
, ent
);
471 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
476 return NSS_STATUS_SUCCESS
;
479 static enum nss_status
480 getspent_next_nisplus (struct spwd
*result
, ent_t
*ent
, char *buffer
,
487 p2len
= spwd_need_buflen (&ent
->pwd
);
490 __set_errno (ERANGE
);
491 return NSS_STATUS_TRYAGAIN
;
493 p2
= buffer
+ (buflen
- p2len
);
498 nis_result
*saved_res
;
503 saved_res
= ent
->result
;
505 ent
->result
= nis_first_entry(pwdtable
);
506 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
509 give_spwd_free (&ent
->pwd
);
510 return niserr2nss (ent
->result
->status
);
519 saved_res
= ent
->result
;
521 res
= nis_next_entry(pwdtable
, &ent
->result
->cookie
);
523 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
525 nis_freeresult (saved_res
);
527 give_spwd_free (&ent
->pwd
);
528 return niserr2nss (ent
->result
->status
);
531 if ((parse_res
= _nss_nisplus_parse_spent (ent
->result
, result
, buffer
,
534 ent
->first
= saved_first
;
535 nis_freeresult (ent
->result
);
536 ent
->result
= saved_res
;
537 __set_errno (ERANGE
);
538 return NSS_STATUS_TRYAGAIN
;
543 nis_freeresult (saved_res
);
546 in_blacklist (result
->sp_namp
, strlen (result
->sp_namp
), ent
))
547 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
551 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
553 return NSS_STATUS_SUCCESS
;
557 static enum nss_status
558 getspent_next_nis (struct spwd
*result
, ent_t
*ent
,
559 char *buffer
, size_t buflen
)
561 struct parser_data
*data
= (void *) buffer
;
562 char *domain
, *outkey
, *outval
, *p
, *p2
;
563 int outkeylen
, outvallen
, parse_res
;
566 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
569 give_spwd_free (&ent
->pwd
);
570 return NSS_STATUS_UNAVAIL
;
573 p2len
= spwd_need_buflen (&ent
->pwd
);
576 __set_errno (ERANGE
);
577 return NSS_STATUS_TRYAGAIN
;
579 p2
= buffer
+ (buflen
- p2len
);
589 if (yp_first (domain
, "shadow.byname", &outkey
, &outkeylen
,
590 &outval
, &outvallen
) != YPERR_SUCCESS
)
593 give_spwd_free (&ent
->pwd
);
594 return NSS_STATUS_UNAVAIL
;
597 saved_oldkey
= ent
->oldkey
;
598 saved_oldlen
= ent
->oldkeylen
;
599 ent
->oldkey
= outkey
;
600 ent
->oldkeylen
= outkeylen
;
605 if (yp_next (domain
, "shadow.byname", ent
->oldkey
, ent
->oldkeylen
,
606 &outkey
, &outkeylen
, &outval
, &outvallen
)
610 give_spwd_free (&ent
->pwd
);
611 return NSS_STATUS_NOTFOUND
;
615 saved_oldkey
= ent
->oldkey
;
616 saved_oldlen
= ent
->oldkeylen
;
617 ent
->oldkey
= outkey
;
618 ent
->oldkeylen
= outkeylen
;
621 /* Copy the found data to our buffer */
622 p
= strncpy (buffer
, outval
, buflen
);
624 /* ...and free the data. */
629 if ((parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
)) == -1)
632 ent
->oldkey
= saved_oldkey
;
633 ent
->oldkeylen
= saved_oldlen
;
634 ent
->first
= saved_first
;
635 __set_errno (ERANGE
);
636 return NSS_STATUS_TRYAGAIN
;
644 in_blacklist (result
->sp_namp
, strlen (result
->sp_namp
), ent
))
649 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
651 return NSS_STATUS_SUCCESS
;
654 /* This function handle the +user entrys in /etc/shadow */
655 static enum nss_status
656 getspnam_plususer (const char *name
, struct spwd
*result
, char *buffer
,
659 struct parser_data
*data
= (void *) buffer
;
665 memset (&pwd
, '\0', sizeof (struct spwd
));
667 copy_spwd_changes (&pwd
, result
, NULL
, 0);
669 plen
= spwd_need_buflen (&pwd
);
672 __set_errno (ERANGE
);
673 return NSS_STATUS_TRYAGAIN
;
675 p
= buffer
+ (buflen
- plen
);
678 if (use_nisplus
) /* Do the NIS+ query here */
681 char buf
[strlen (name
) + 24 + pwdtablelen
];
683 sprintf(buf
, "[name=%s],%s", name
, pwdtable
);
684 res
= nis_list(buf
, 0, NULL
, NULL
);
685 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
687 enum nss_status status
= niserr2nss (res
->status
);
689 nis_freeresult (res
);
692 if ((parse_res
= _nss_nisplus_parse_spent (res
, result
, buffer
,
695 nis_freeresult (res
);
696 return NSS_STATUS_TRYAGAIN
;
698 nis_freeresult (res
);
702 char *domain
, *outval
, *ptr
;
705 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
706 return NSS_STATUS_TRYAGAIN
;
708 if (yp_match (domain
, "shadow.byname", name
, strlen (name
),
711 return NSS_STATUS_TRYAGAIN
;
712 ptr
= strncpy (buffer
, outval
, buflen
< (size_t) outvallen
?
713 buflen
: (size_t) outvallen
);
714 buffer
[buflen
< (size_t) outvallen
? buflen
: (size_t) outvallen
] = '\0';
716 while (isspace (*ptr
))
718 if ((parse_res
= _nss_files_parse_spent (ptr
, result
, data
, buflen
))
721 __set_errno (ERANGE
);
722 return NSS_STATUS_TRYAGAIN
;
728 copy_spwd_changes (result
, &pwd
, p
, plen
);
729 give_spwd_free (&pwd
);
730 /* We found the entry. */
731 return NSS_STATUS_SUCCESS
;
735 /* Give buffer the old len back */
737 give_spwd_free (&pwd
);
739 return NSS_STATUS_RETURN
;
742 static enum nss_status
743 getspent_next_file (struct spwd
*result
, ent_t
*ent
,
744 char *buffer
, size_t buflen
)
746 struct parser_data
*data
= (void *) buffer
;
755 fgetpos (ent
->stream
, &pos
);
756 p
= fgets (buffer
, buflen
, ent
->stream
);
758 return NSS_STATUS_NOTFOUND
;
760 /* Terminate the line for any case. */
761 buffer
[buflen
- 1] = '\0';
763 /* Skip leading blanks. */
767 while (*p
== '\0' || *p
== '#' /* Ignore empty and comment lines. */
768 /* Parse the line. If it is invalid, loop to
769 get the next line of the file to parse. */
770 || !(parse_res
= _nss_files_parse_spent (p
, result
, data
,
775 /* The parser ran out of space. */
776 fsetpos (ent
->stream
, &pos
);
777 __set_errno (ERANGE
);
778 return NSS_STATUS_TRYAGAIN
;
781 if (result
->sp_namp
[0] != '+' && result
->sp_namp
[0] != '-')
782 /* This is a real entry. */
786 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] == '@'
787 && result
->sp_namp
[2] != '\0')
790 char *user
, *host
, *domain
;
791 struct __netgrent netgrdata
;
793 bzero (&netgrdata
, sizeof (struct __netgrent
));
794 __internal_setnetgrent (&result
->sp_namp
[2], &netgrdata
);
795 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
796 &netgrdata
, buf2
, sizeof (buf2
)))
798 if (user
!= NULL
&& user
[0] != '-')
799 blacklist_store_name (user
, ent
);
801 __internal_endnetgrent (&netgrdata
);
806 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '@'
807 && result
->sp_namp
[2] != '\0')
811 ent
->netgroup
= TRUE
;
813 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
816 status
= getspent_next_nisplus_netgr (NULL
, result
, ent
,
820 status
= getspent_next_nis_netgr (NULL
, result
, ent
,
823 if (status
== NSS_STATUS_RETURN
)
830 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] != '\0'
831 && result
->sp_namp
[1] != '@')
833 blacklist_store_name (&result
->sp_namp
[1], ent
);
838 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] != '\0'
839 && result
->sp_namp
[1] != '@')
841 enum nss_status status
;
843 /* Store the User in the blacklist for the "+" at the end of
845 blacklist_store_name (&result
->sp_namp
[1], ent
);
846 status
= getspnam_plususer (&result
->sp_namp
[1], result
, buffer
,
848 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
851 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
858 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '\0')
862 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
865 return getspent_next_nisplus (result
, ent
, buffer
, buflen
);
867 return getspent_next_nis (result
, ent
, buffer
, buflen
);
871 return NSS_STATUS_SUCCESS
;
875 static enum nss_status
876 internal_getspent_r (struct spwd
*pw
, ent_t
*ent
,
877 char *buffer
, size_t buflen
)
883 /* We are searching members in a netgroup */
884 /* Since this is not the first call, we don't need the group name */
886 status
= getspent_next_nisplus_netgr (NULL
, pw
, ent
, NULL
, buffer
,
889 status
= getspent_next_nis_netgr (NULL
, pw
, ent
, NULL
, buffer
, buflen
);
890 if (status
== NSS_STATUS_RETURN
)
891 return getspent_next_file (pw
, ent
, buffer
, buflen
);
899 return getspent_next_nisplus (pw
, ent
, buffer
, buflen
);
901 return getspent_next_nis (pw
, ent
, buffer
, buflen
);
904 return getspent_next_file (pw
, ent
, buffer
, buflen
);
908 _nss_compat_getspent_r (struct spwd
*pwd
, char *buffer
, size_t buflen
)
910 enum nss_status status
= NSS_STATUS_SUCCESS
;
912 __libc_lock_lock (lock
);
916 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
917 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
920 /* Be prepared that the setspent function was not called before. */
921 if (ext_ent
.stream
== NULL
)
922 status
= internal_setspent (&ext_ent
);
924 if (status
== NSS_STATUS_SUCCESS
)
925 status
= internal_getspent_r (pwd
, &ext_ent
, buffer
, buflen
);
927 __libc_lock_unlock (lock
);
932 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
933 static enum nss_status
934 internal_getspnam_r (const char *name
, struct spwd
*result
, ent_t
*ent
,
935 char *buffer
, size_t buflen
)
937 struct parser_data
*data
= (void *) buffer
;
947 fgetpos (ent
->stream
, &pos
);
948 p
= fgets (buffer
, buflen
, ent
->stream
);
950 return NSS_STATUS_NOTFOUND
;
952 /* Terminate the line for any case. */
953 buffer
[buflen
- 1] = '\0';
955 /* Skip leading blanks. */
959 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
960 /* Parse the line. If it is invalid, loop to
961 get the next line of the file to parse. */
962 !(parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
)));
966 /* The parser ran out of space. */
967 fsetpos (ent
->stream
, &pos
);
968 __set_errno (ERANGE
);
969 return NSS_STATUS_TRYAGAIN
;
972 /* This is a real entry. */
973 if (result
->sp_namp
[0] != '+' && result
->sp_namp
[0] != '-')
975 if (strcmp (result
->sp_namp
, name
) == 0)
976 return NSS_STATUS_SUCCESS
;
982 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] == '@'
983 && result
->sp_namp
[2] != '\0')
986 char *user
, *host
, *domain
;
987 struct __netgrent netgrdata
;
989 bzero (&netgrdata
, sizeof (struct __netgrent
));
990 __internal_setnetgrent (&result
->sp_namp
[2], &netgrdata
);
991 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
992 &netgrdata
, buf2
, sizeof (buf2
)))
994 if (user
!= NULL
&& user
[0] != '-')
995 if (strcmp (user
, name
) == 0)
996 return NSS_STATUS_NOTFOUND
;
998 __internal_endnetgrent (&netgrdata
);
1003 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '@'
1004 && result
->sp_namp
[2] != '\0')
1006 char buf
[strlen (result
->sp_namp
)];
1009 strcpy (buf
, &result
->sp_namp
[2]);
1010 ent
->netgroup
= TRUE
;
1012 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
1017 status
= getspent_next_nisplus_netgr (name
, result
, ent
, buf
,
1020 status
= getspent_next_nis_netgr (name
, result
, ent
, buf
,
1022 if (status
== NSS_STATUS_RETURN
)
1025 if (status
== NSS_STATUS_SUCCESS
&&
1026 strcmp (result
->sp_namp
, name
) == 0)
1027 return NSS_STATUS_SUCCESS
;
1028 } while (status
== NSS_STATUS_SUCCESS
);
1033 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] != '\0'
1034 && result
->sp_namp
[1] != '@')
1036 if (strcmp (&result
->sp_namp
[1], name
) == 0)
1037 return NSS_STATUS_NOTFOUND
;
1043 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] != '\0'
1044 && result
->sp_namp
[1] != '@')
1046 if (strcmp (name
, &result
->sp_namp
[1]) == 0)
1048 enum nss_status status
;
1050 status
= getspnam_plususer (name
, result
, buffer
, buflen
);
1051 if (status
== NSS_STATUS_RETURN
)
1052 /* We couldn't parse the entry */
1053 return NSS_STATUS_NOTFOUND
;
1060 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '\0')
1062 enum nss_status status
;
1064 status
= getspnam_plususer (name
, result
, buffer
, buflen
);
1065 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1066 return NSS_STATUS_NOTFOUND
;
1071 return NSS_STATUS_SUCCESS
;
1075 _nss_compat_getspnam_r (const char *name
, struct spwd
*pwd
,
1076 char *buffer
, size_t buflen
)
1078 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1079 {NULL
, NULL
, 0, 0, 0, 0, 0, 0, 0}};
1080 enum nss_status status
;
1082 if (name
[0] == '-' || name
[0] == '+')
1083 return NSS_STATUS_NOTFOUND
;
1087 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
1088 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1091 status
= internal_setspent (&ent
);
1092 if (status
!= NSS_STATUS_SUCCESS
)
1095 status
= internal_getspnam_r (name
, pwd
, &ent
, buffer
, buflen
);
1097 internal_endspent (&ent
);
1102 /* Support routines for remembering -@netgroup and -user entries.
1103 The names are stored in a single string with `|' as separator. */
1105 blacklist_store_name (const char *name
, ent_t
*ent
)
1107 int namelen
= strlen (name
);
1110 /* first call, setup cache */
1111 if (ent
->blacklist
.size
== 0)
1113 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1114 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1115 if (ent
->blacklist
.data
== NULL
)
1117 ent
->blacklist
.data
[0] = '|';
1118 ent
->blacklist
.data
[1] = '\0';
1119 ent
->blacklist
.current
= 1;
1123 if (in_blacklist (name
, namelen
, ent
))
1124 return; /* no duplicates */
1126 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1128 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1129 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1132 free (ent
->blacklist
.data
);
1133 ent
->blacklist
.size
= 0;
1136 ent
->blacklist
.data
= tmp
;
1140 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1143 ent
->blacklist
.current
+= namelen
+ 1;
1148 /* Returns TRUE if ent->blacklist contains name, else FALSE. */
1150 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1152 char buf
[namelen
+ 3];
1155 if (ent
->blacklist
.data
== NULL
)
1159 cp
= stpcpy (&buf
[1], name
);
1162 return strstr (ent
->blacklist
.data
, buf
) != NULL
;