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.
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>
34 #include "nss-nisplus.h"
35 #include "nisplus-parser.h"
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 password table */
40 static size_t pwdtablelen
= 0;
42 /* Get the declaration of the parser function. */
44 #define STRUCTURE spwd
46 #include <nss/nss_files/files-parse.c>
48 /* Structure for remembering -@netgroup and -user members ... */
49 #define BLACKLIST_INITIAL_SIZE 512
50 #define BLACKLIST_INCREMENT 256
67 struct blacklist_t blacklist
;
69 struct __netgrent netgrdata
;
71 typedef struct ent_t ent_t
;
73 static ent_t ext_ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
74 {NULL
, NULL
, 0, 0, 0, 0, 0, 0, 0}};
76 /* Protect global state against multiple changers. */
77 __libc_lock_define_initialized (static, lock
)
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
*);
84 give_spwd_free (struct spwd
*pwd
)
86 if (pwd
->sp_namp
!= NULL
)
88 if (pwd
->sp_pwdp
!= NULL
)
91 memset (pwd
, '\0', sizeof (struct spwd
));
95 spwd_need_buflen (struct spwd
*pwd
)
99 if (pwd
->sp_pwdp
!= NULL
)
100 len
+= strlen (pwd
->sp_pwdp
) + 1;
106 copy_spwd_changes (struct spwd
*dest
, struct spwd
*src
,
107 char *buffer
, size_t buflen
)
109 if (src
->sp_pwdp
!= NULL
&& strlen (src
->sp_pwdp
))
112 dest
->sp_pwdp
= strdup (src
->sp_pwdp
);
113 else if (dest
->sp_pwdp
&&
114 strlen (dest
->sp_pwdp
) >= strlen (src
->sp_pwdp
))
115 strcpy (dest
->sp_pwdp
, src
->sp_pwdp
);
118 dest
->sp_pwdp
= buffer
;
119 strcpy (dest
->sp_pwdp
, src
->sp_pwdp
);
120 buffer
+= strlen (dest
->sp_pwdp
) + 1;
121 buflen
= buflen
- (strlen (dest
->sp_pwdp
) + 1);
124 if (src
->sp_lstchg
!= 0)
125 dest
->sp_lstchg
= src
->sp_lstchg
;
126 if (src
->sp_min
!= 0)
127 dest
->sp_min
= src
->sp_min
;
128 if (src
->sp_max
!= 0)
129 dest
->sp_max
= src
->sp_max
;
130 if (src
->sp_warn
!= 0)
131 dest
->sp_warn
= src
->sp_warn
;
132 if (src
->sp_inact
!= 0)
133 dest
->sp_inact
= src
->sp_inact
;
134 if (src
->sp_expire
!= 0)
135 dest
->sp_expire
= src
->sp_expire
;
136 if (src
->sp_flag
!= 0)
137 dest
->sp_flag
= src
->sp_flag
;
140 static enum nss_status
141 internal_setspent (ent_t
*ent
)
143 enum nss_status status
= NSS_STATUS_SUCCESS
;
145 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
147 /* If something was left over free it. */
149 __internal_endnetgrent (&ent
->netgrdata
);
151 if (ent
->oldkey
!= NULL
)
158 if (ent
->result
!= NULL
)
160 nis_freeresult (ent
->result
);
164 if (pwdtable
== NULL
)
166 static const char key
[] = "passwd.org_dir.";
167 const char *local_dir
= nis_local_directory ();
168 size_t len_local_dir
= strlen (local_dir
);
170 pwdtable
= malloc (sizeof (key
) + len_local_dir
);
171 if (pwdtable
== NULL
)
172 return NSS_STATUS_TRYAGAIN
;
174 pwdtablelen
= ((char *) mempcpy (mempcpy (pwdtable
,
175 key
, sizeof (key
) - 1),
176 local_dir
, len_local_dir
+ 1)
180 if (ent
->blacklist
.data
!= NULL
)
182 ent
->blacklist
.current
= 1;
183 ent
->blacklist
.data
[0] = '|';
184 ent
->blacklist
.data
[1] = '\0';
187 ent
->blacklist
.current
= 0;
189 if (ent
->stream
== NULL
)
191 ent
->stream
= fopen ("/etc/shadow", "r");
193 if (ent
->stream
== NULL
)
194 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
197 /* We have to make sure the file is `closed on exec'. */
200 result
= flags
= fcntl (fileno (ent
->stream
), F_GETFD
, 0);
204 result
= fcntl (fileno (ent
->stream
), F_SETFD
, flags
);
208 /* Something went wrong. Close the stream and return a
210 fclose (ent
->stream
);
212 status
= NSS_STATUS_UNAVAIL
;
217 rewind (ent
->stream
);
219 give_spwd_free (&ent
->pwd
);
226 _nss_compat_setspent (void)
228 enum nss_status result
;
230 __libc_lock_lock (lock
);
234 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
235 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
238 result
= internal_setspent (&ext_ent
);
240 __libc_lock_unlock (lock
);
246 static enum nss_status
247 internal_endspent (ent_t
*ent
)
249 if (ent
->stream
!= NULL
)
251 fclose (ent
->stream
);
256 __internal_endnetgrent (&ent
->netgrdata
);
258 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
260 if (ent
->oldkey
!= NULL
)
267 if (ent
->result
!= NULL
)
269 nis_freeresult (ent
->result
);
273 if (ent
->blacklist
.data
!= NULL
)
275 ent
->blacklist
.current
= 1;
276 ent
->blacklist
.data
[0] = '|';
277 ent
->blacklist
.data
[1] = '\0';
280 ent
->blacklist
.current
= 0;
282 give_spwd_free (&ent
->pwd
);
284 return NSS_STATUS_SUCCESS
;
288 _nss_compat_endspent (void)
290 enum nss_status result
;
292 __libc_lock_lock (lock
);
294 result
= internal_endspent (&ext_ent
);
296 __libc_lock_unlock (lock
);
302 static enum nss_status
303 getspent_next_nis_netgr (const char *name
, struct spwd
*result
, ent_t
*ent
,
304 char *group
, char *buffer
, size_t buflen
, int *errnop
)
306 struct parser_data
*data
= (void *) buffer
;
307 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
308 int status
, outvallen
;
311 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
315 give_spwd_free (&ent
->pwd
);
316 return NSS_STATUS_UNAVAIL
;
319 if (ent
->first
== TRUE
)
321 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
322 __internal_setnetgrent (group
, &ent
->netgrdata
);
331 saved_cursor
= ent
->netgrdata
.cursor
;
332 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
333 &ent
->netgrdata
, buffer
, buflen
,
337 __internal_endnetgrent (&ent
->netgrdata
);
339 give_spwd_free (&ent
->pwd
);
340 return NSS_STATUS_RETURN
;
343 if (user
== NULL
|| user
[0] == '-')
346 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
349 /* If name != NULL, we are called from getpwnam */
351 if (strcmp (user
, name
) != 0)
354 if (yp_match (ypdomain
, "shadow.byname", user
,
355 strlen (user
), &outval
, &outvallen
)
359 p2len
= spwd_need_buflen (&ent
->pwd
);
364 return NSS_STATUS_TRYAGAIN
;
366 p2
= buffer
+ (buflen
- p2len
);
368 if (buflen
< ((size_t) outval
+ 1))
372 return NSS_STATUS_TRYAGAIN
;
374 p
= strncpy (buffer
, outval
, buflen
);
378 parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
, errnop
);
381 ent
->netgrdata
.cursor
= saved_cursor
;
382 return NSS_STATUS_TRYAGAIN
;
387 /* Store the User in the blacklist for the "+" at the end of
389 blacklist_store_name (result
->sp_namp
, ent
);
390 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
395 return NSS_STATUS_SUCCESS
;
398 static enum nss_status
399 getspent_next_nisplus_netgr (const char *name
, struct spwd
*result
,
400 ent_t
*ent
, char *group
, char *buffer
,
401 size_t buflen
, int *errnop
)
403 char *ypdomain
, *host
, *user
, *domain
, *p2
;
404 int status
, parse_res
;
408 /* Maybe we should use domainname here ? We need the current
409 domainname for the domain field in netgroups */
410 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
414 give_spwd_free (&ent
->pwd
);
415 return NSS_STATUS_UNAVAIL
;
418 if (ent
->first
== TRUE
)
420 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
421 __internal_setnetgrent (group
, &ent
->netgrdata
);
429 saved_cursor
= ent
->netgrdata
.cursor
;
430 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
431 &ent
->netgrdata
, buffer
, buflen
,
435 __internal_endnetgrent (&ent
->netgrdata
);
437 give_spwd_free (&ent
->pwd
);
438 return NSS_STATUS_RETURN
;
441 if (user
== NULL
|| user
[0] == '-')
444 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
447 /* If name != NULL, we are called from getpwnam */
449 if (strcmp (user
, name
) != 0)
452 p2len
= spwd_need_buflen (&ent
->pwd
);
456 return NSS_STATUS_TRYAGAIN
;
458 p2
= buffer
+ (buflen
- p2len
);
461 char buf
[strlen (user
) + 30 + pwdtablelen
];
462 sprintf (buf
, "[name=%s],%s", user
, pwdtable
);
463 nisres
= nis_list (buf
, FOLLOW_LINKS
| FOLLOW_PATH
, NULL
, NULL
);
465 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
467 nis_freeresult (nisres
);
470 parse_res
= _nss_nisplus_parse_spent (nisres
, result
, buffer
,
474 nis_freeresult (nisres
);
476 return NSS_STATUS_TRYAGAIN
;
478 nis_freeresult (nisres
);
482 /* Store the User in the blacklist for the "+" at the end of
484 blacklist_store_name (result
->sp_namp
, ent
);
485 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
490 return NSS_STATUS_SUCCESS
;
493 static enum nss_status
494 getspent_next_nisplus (struct spwd
*result
, ent_t
*ent
, char *buffer
,
495 size_t buflen
, int *errnop
)
501 p2len
= spwd_need_buflen (&ent
->pwd
);
505 return NSS_STATUS_TRYAGAIN
;
507 p2
= buffer
+ (buflen
- p2len
);
512 nis_result
*saved_res
;
517 saved_res
= ent
->result
;
519 ent
->result
= nis_first_entry (pwdtable
);
520 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
523 give_spwd_free (&ent
->pwd
);
524 return niserr2nss (ent
->result
->status
);
533 saved_res
= ent
->result
;
535 res
= nis_next_entry (pwdtable
, &ent
->result
->cookie
);
537 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
539 nis_freeresult (saved_res
);
541 give_spwd_free (&ent
->pwd
);
542 return niserr2nss (ent
->result
->status
);
545 parse_res
= _nss_nisplus_parse_spent (ent
->result
, result
, buffer
,
549 ent
->first
= saved_first
;
550 nis_freeresult (ent
->result
);
551 ent
->result
= saved_res
;
553 return NSS_STATUS_TRYAGAIN
;
558 nis_freeresult (saved_res
);
561 in_blacklist (result
->sp_namp
, strlen (result
->sp_namp
), ent
))
562 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
566 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
568 return NSS_STATUS_SUCCESS
;
572 static enum nss_status
573 getspent_next_nis (struct spwd
*result
, ent_t
*ent
,
574 char *buffer
, size_t buflen
, int *errnop
)
576 struct parser_data
*data
= (void *) buffer
;
577 char *domain
, *outkey
, *outval
, *p
, *p2
;
578 int outkeylen
, outvallen
, parse_res
;
581 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
584 give_spwd_free (&ent
->pwd
);
585 return NSS_STATUS_UNAVAIL
;
588 p2len
= spwd_need_buflen (&ent
->pwd
);
592 return NSS_STATUS_TRYAGAIN
;
594 p2
= buffer
+ (buflen
- p2len
);
604 if (yp_first (domain
, "shadow.byname", &outkey
, &outkeylen
,
605 &outval
, &outvallen
) != YPERR_SUCCESS
)
608 give_spwd_free (&ent
->pwd
);
609 return NSS_STATUS_UNAVAIL
;
612 if (buflen
< ((size_t) outvallen
+ 1))
616 return NSS_STATUS_TRYAGAIN
;
620 saved_oldkey
= ent
->oldkey
;
621 saved_oldlen
= ent
->oldkeylen
;
622 ent
->oldkey
= outkey
;
623 ent
->oldkeylen
= outkeylen
;
628 if (yp_next (domain
, "shadow.byname", ent
->oldkey
, ent
->oldkeylen
,
629 &outkey
, &outkeylen
, &outval
, &outvallen
)
633 give_spwd_free (&ent
->pwd
);
634 return NSS_STATUS_NOTFOUND
;
637 if (buflen
< ((size_t) outvallen
+ 1))
641 return NSS_STATUS_TRYAGAIN
;
645 saved_oldkey
= ent
->oldkey
;
646 saved_oldlen
= ent
->oldkeylen
;
647 ent
->oldkey
= outkey
;
648 ent
->oldkeylen
= outkeylen
;
651 /* Copy the found data to our buffer */
652 p
= strncpy (buffer
, outval
, buflen
);
654 /* ...and free the data. */
659 parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
, errnop
);
663 ent
->oldkey
= saved_oldkey
;
664 ent
->oldkeylen
= saved_oldlen
;
665 ent
->first
= saved_first
;
667 return NSS_STATUS_TRYAGAIN
;
675 in_blacklist (result
->sp_namp
, strlen (result
->sp_namp
), ent
))
680 copy_spwd_changes (result
, &ent
->pwd
, p2
, p2len
);
682 return NSS_STATUS_SUCCESS
;
685 /* This function handle the +user entrys in /etc/shadow */
686 static enum nss_status
687 getspnam_plususer (const char *name
, struct spwd
*result
, char *buffer
,
688 size_t buflen
, int *errnop
)
690 struct parser_data
*data
= (void *) buffer
;
696 memset (&pwd
, '\0', sizeof (struct spwd
));
698 copy_spwd_changes (&pwd
, result
, NULL
, 0);
700 plen
= spwd_need_buflen (&pwd
);
704 return NSS_STATUS_TRYAGAIN
;
706 p
= buffer
+ (buflen
- plen
);
709 if (use_nisplus
) /* Do the NIS+ query here */
712 char buf
[strlen (name
) + 24 + pwdtablelen
];
714 sprintf(buf
, "[name=%s],%s", name
, pwdtable
);
715 res
= nis_list(buf
, 0, NULL
, NULL
);
716 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
718 enum nss_status status
= niserr2nss (res
->status
);
720 nis_freeresult (res
);
723 parse_res
= _nss_nisplus_parse_spent (res
, result
, buffer
,
727 nis_freeresult (res
);
729 return NSS_STATUS_TRYAGAIN
;
731 nis_freeresult (res
);
735 char *domain
, *outval
, *ptr
;
738 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
739 return NSS_STATUS_NOTFOUND
;
741 if (yp_match (domain
, "shadow.byname", name
, strlen (name
),
742 &outval
, &outvallen
) != YPERR_SUCCESS
)
743 return NSS_STATUS_NOTFOUND
;
745 if (buflen
< ((size_t) outvallen
+ 1))
749 return NSS_STATUS_TRYAGAIN
;
752 ptr
= strncpy (buffer
, outval
, buflen
);
754 while (isspace (*ptr
))
756 parse_res
= _nss_files_parse_spent (ptr
, result
, data
, buflen
, errnop
);
758 return NSS_STATUS_TRYAGAIN
;
763 copy_spwd_changes (result
, &pwd
, p
, plen
);
764 give_spwd_free (&pwd
);
765 /* We found the entry. */
766 return NSS_STATUS_SUCCESS
;
770 /* Give buffer the old len back */
772 give_spwd_free (&pwd
);
774 return NSS_STATUS_RETURN
;
777 static enum nss_status
778 getspent_next_file (struct spwd
*result
, ent_t
*ent
,
779 char *buffer
, size_t buflen
, int *errnop
)
781 struct parser_data
*data
= (void *) buffer
;
790 fgetpos (ent
->stream
, &pos
);
791 buffer
[buflen
- 1] = '\xff';
792 p
= fgets (buffer
, buflen
, ent
->stream
);
793 if (p
== NULL
&& feof (ent
->stream
))
794 return NSS_STATUS_NOTFOUND
;
795 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
797 fsetpos (ent
->stream
, &pos
);
799 return NSS_STATUS_TRYAGAIN
;
802 /* Skip leading blanks. */
806 while (*p
== '\0' || *p
== '#' /* Ignore empty and comment lines. */
807 /* Parse the line. If it is invalid, loop to
808 get the next line of the file to parse. */
809 || !(parse_res
= _nss_files_parse_spent (p
, result
, data
,
814 /* The parser ran out of space. */
815 fsetpos (ent
->stream
, &pos
);
817 return NSS_STATUS_TRYAGAIN
;
820 if (result
->sp_namp
[0] != '+' && result
->sp_namp
[0] != '-')
821 /* This is a real entry. */
825 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] == '@'
826 && result
->sp_namp
[2] != '\0')
828 /* XXX Do not use fixed length buffers. */
830 char *user
, *host
, *domain
;
831 struct __netgrent netgrdata
;
833 bzero (&netgrdata
, sizeof (struct __netgrent
));
834 __internal_setnetgrent (&result
->sp_namp
[2], &netgrdata
);
835 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
836 &netgrdata
, buf2
, sizeof (buf2
),
839 if (user
!= NULL
&& user
[0] != '-')
840 blacklist_store_name (user
, ent
);
842 __internal_endnetgrent (&netgrdata
);
847 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '@'
848 && result
->sp_namp
[2] != '\0')
852 ent
->netgroup
= TRUE
;
854 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
857 status
= getspent_next_nisplus_netgr (NULL
, result
, ent
,
859 buffer
, buflen
, errnop
);
861 status
= getspent_next_nis_netgr (NULL
, result
, ent
,
863 buffer
, buflen
, errnop
);
864 if (status
== NSS_STATUS_RETURN
)
871 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] != '\0'
872 && result
->sp_namp
[1] != '@')
874 blacklist_store_name (&result
->sp_namp
[1], ent
);
879 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] != '\0'
880 && result
->sp_namp
[1] != '@')
882 enum nss_status status
;
884 /* Store the User in the blacklist for the "+" at the end of
886 blacklist_store_name (&result
->sp_namp
[1], ent
);
887 status
= getspnam_plususer (&result
->sp_namp
[1], result
, buffer
,
889 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
892 if (status
== NSS_STATUS_RETURN
/* We couldn't parse the entry */
893 || status
== NSS_STATUS_NOTFOUND
) /* entry doesn't exist */
897 if (status
== NSS_STATUS_TRYAGAIN
)
899 fsetpos (ent
->stream
, &pos
);
907 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '\0')
911 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
914 return getspent_next_nisplus (result
, ent
, buffer
, buflen
, errnop
);
916 return getspent_next_nis (result
, ent
, buffer
, buflen
, errnop
);
920 return NSS_STATUS_SUCCESS
;
924 static enum nss_status
925 internal_getspent_r (struct spwd
*pw
, ent_t
*ent
,
926 char *buffer
, size_t buflen
, int *errnop
)
932 /* We are searching members in a netgroup */
933 /* Since this is not the first call, we don't need the group name */
935 status
= getspent_next_nisplus_netgr (NULL
, pw
, ent
, NULL
, buffer
,
938 status
= getspent_next_nis_netgr (NULL
, pw
, ent
, NULL
, buffer
, buflen
,
940 if (status
== NSS_STATUS_RETURN
)
941 return getspent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
949 return getspent_next_nisplus (pw
, ent
, buffer
, buflen
, errnop
);
951 return getspent_next_nis (pw
, ent
, buffer
, buflen
, errnop
);
954 return getspent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
958 _nss_compat_getspent_r (struct spwd
*pwd
, char *buffer
, size_t buflen
,
961 enum nss_status status
= NSS_STATUS_SUCCESS
;
963 __libc_lock_lock (lock
);
967 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
968 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
971 /* Be prepared that the setspent function was not called before. */
972 if (ext_ent
.stream
== NULL
)
973 status
= internal_setspent (&ext_ent
);
975 if (status
== NSS_STATUS_SUCCESS
)
976 status
= internal_getspent_r (pwd
, &ext_ent
, buffer
, buflen
, errnop
);
978 __libc_lock_unlock (lock
);
983 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
984 static enum nss_status
985 internal_getspnam_r (const char *name
, struct spwd
*result
, ent_t
*ent
,
986 char *buffer
, size_t buflen
, int *errnop
)
988 struct parser_data
*data
= (void *) buffer
;
998 fgetpos (ent
->stream
, &pos
);
999 buffer
[buflen
- 1] = '\xff';
1000 p
= fgets (buffer
, buflen
, ent
->stream
);
1001 if (p
== NULL
&& feof (ent
->stream
))
1002 return NSS_STATUS_NOTFOUND
;
1003 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
1005 fsetpos (ent
->stream
, &pos
);
1007 return NSS_STATUS_TRYAGAIN
;
1010 /* Skip leading blanks. */
1011 while (isspace (*p
))
1014 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1015 /* Parse the line. If it is invalid, loop to
1016 get the next line of the file to parse. */
1017 !(parse_res
= _nss_files_parse_spent (p
, result
, data
, buflen
,
1020 if (parse_res
== -1)
1022 /* The parser ran out of space. */
1023 fsetpos (ent
->stream
, &pos
);
1025 return NSS_STATUS_TRYAGAIN
;
1028 /* This is a real entry. */
1029 if (result
->sp_namp
[0] != '+' && result
->sp_namp
[0] != '-')
1031 if (strcmp (result
->sp_namp
, name
) == 0)
1032 return NSS_STATUS_SUCCESS
;
1038 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] == '@'
1039 && result
->sp_namp
[2] != '\0')
1041 /* XXX Do not use fixed length buffers. */
1043 char *user
, *host
, *domain
;
1044 struct __netgrent netgrdata
;
1046 bzero (&netgrdata
, sizeof (struct __netgrent
));
1047 __internal_setnetgrent (&result
->sp_namp
[2], &netgrdata
);
1048 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
1049 buf2
, sizeof (buf2
), errnop
))
1051 if (user
!= NULL
&& user
[0] != '-')
1052 if (strcmp (user
, name
) == 0)
1053 return NSS_STATUS_NOTFOUND
;
1055 __internal_endnetgrent (&netgrdata
);
1060 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '@'
1061 && result
->sp_namp
[2] != '\0')
1063 char *buf
= strdupa (&result
->sp_namp
[2]);
1066 ent
->netgroup
= TRUE
;
1068 copy_spwd_changes (&ent
->pwd
, result
, NULL
, 0);
1073 status
= getspent_next_nisplus_netgr (name
, result
, ent
, buf
,
1074 buffer
, buflen
, errnop
);
1076 status
= getspent_next_nis_netgr (name
, result
, ent
, buf
,
1077 buffer
, buflen
, errnop
);
1078 if (status
== NSS_STATUS_RETURN
)
1081 if (status
== NSS_STATUS_SUCCESS
1082 && strcmp (result
->sp_namp
, name
) == 0)
1083 return NSS_STATUS_SUCCESS
;
1084 } while (status
== NSS_STATUS_SUCCESS
);
1089 if (result
->sp_namp
[0] == '-' && result
->sp_namp
[1] != '\0'
1090 && result
->sp_namp
[1] != '@')
1092 if (strcmp (&result
->sp_namp
[1], name
) == 0)
1093 return NSS_STATUS_NOTFOUND
;
1099 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] != '\0'
1100 && result
->sp_namp
[1] != '@')
1102 if (strcmp (name
, &result
->sp_namp
[1]) == 0)
1104 enum nss_status status
;
1106 status
= getspnam_plususer (name
, result
, buffer
, buflen
,
1108 if (status
== NSS_STATUS_RETURN
)
1109 /* We couldn't parse the entry */
1110 return NSS_STATUS_NOTFOUND
;
1117 if (result
->sp_namp
[0] == '+' && result
->sp_namp
[1] == '\0')
1119 enum nss_status status
;
1121 status
= getspnam_plususer (name
, result
, buffer
, buflen
, errnop
);
1122 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1123 return NSS_STATUS_NOTFOUND
;
1128 return NSS_STATUS_SUCCESS
;
1132 _nss_compat_getspnam_r (const char *name
, struct spwd
*pwd
,
1133 char *buffer
, size_t buflen
, int *errnop
)
1135 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1136 {NULL
, NULL
, 0, 0, 0, 0, 0, 0, 0}};
1137 enum nss_status status
;
1139 if (name
[0] == '-' || name
[0] == '+')
1140 return NSS_STATUS_NOTFOUND
;
1144 __nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni
);
1145 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1148 status
= internal_setspent (&ent
);
1149 if (status
!= NSS_STATUS_SUCCESS
)
1152 status
= internal_getspnam_r (name
, pwd
, &ent
, buffer
, buflen
, errnop
);
1154 internal_endspent (&ent
);
1159 /* Support routines for remembering -@netgroup and -user entries.
1160 The names are stored in a single string with `|' as separator. */
1162 blacklist_store_name (const char *name
, ent_t
*ent
)
1164 int namelen
= strlen (name
);
1167 /* first call, setup cache */
1168 if (ent
->blacklist
.size
== 0)
1170 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1171 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1172 if (ent
->blacklist
.data
== NULL
)
1174 ent
->blacklist
.data
[0] = '|';
1175 ent
->blacklist
.data
[1] = '\0';
1176 ent
->blacklist
.current
= 1;
1180 if (in_blacklist (name
, namelen
, ent
))
1181 return; /* no duplicates */
1183 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1185 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1186 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1189 free (ent
->blacklist
.data
);
1190 ent
->blacklist
.size
= 0;
1193 ent
->blacklist
.data
= tmp
;
1197 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1200 ent
->blacklist
.current
+= namelen
+ 1;
1205 /* Returns TRUE if ent->blacklist contains name, else FALSE. */
1207 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1209 char buf
[namelen
+ 3];
1212 if (ent
->blacklist
.data
== NULL
)
1216 cp
= stpcpy (&buf
[1], name
);
1219 return strstr (ent
->blacklist
.data
, buf
) != NULL
;