]>
sourceware.org Git - glibc.git/blob - nis/nss_compat/compat-pwd.c
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
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 pwd table */
40 static size_t pwdtablelen
= 0;
42 /* Get the declaration of the parser function. */
44 #define STRUCTURE passwd
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, NULL
, NULL
, NULL
}};
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_pwd_free (struct passwd
*pwd
)
86 if (pwd
->pw_name
!= NULL
)
88 if (pwd
->pw_passwd
!= NULL
)
89 free (pwd
->pw_passwd
);
90 if (pwd
->pw_gecos
!= NULL
)
92 if (pwd
->pw_dir
!= NULL
)
94 if (pwd
->pw_shell
!= NULL
)
97 memset (pwd
, '\0', sizeof (struct passwd
));
101 pwd_need_buflen (struct passwd
*pwd
)
105 if (pwd
->pw_passwd
!= NULL
)
106 len
+= strlen (pwd
->pw_passwd
) + 1;
108 if (pwd
->pw_gecos
!= NULL
)
109 len
+= strlen (pwd
->pw_gecos
) + 1;
111 if (pwd
->pw_dir
!= NULL
)
112 len
+= strlen (pwd
->pw_dir
) + 1;
114 if (pwd
->pw_shell
!= NULL
)
115 len
+= strlen (pwd
->pw_shell
) + 1;
121 copy_pwd_changes (struct passwd
*dest
, struct passwd
*src
,
122 char *buffer
, size_t buflen
)
124 if (src
->pw_passwd
!= NULL
&& strlen (src
->pw_passwd
))
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
);
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);
140 if (src
->pw_gecos
!= NULL
&& strlen (src
->pw_gecos
))
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
);
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);
155 if (src
->pw_dir
!= NULL
&& strlen (src
->pw_dir
))
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
);
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);
171 if (src
->pw_shell
!= NULL
&& strlen (src
->pw_shell
))
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
);
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);
188 static enum nss_status
189 internal_setpwent (ent_t
*ent
)
191 enum nss_status status
= NSS_STATUS_SUCCESS
;
193 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
195 /* If something was left over free it. */
197 __internal_endnetgrent (&ent
->netgrdata
);
199 if (ent
->oldkey
!= NULL
)
206 if (ent
->result
!= NULL
)
208 nis_freeresult (ent
->result
);
212 if (pwdtable
== NULL
)
214 static const char key
[] = "passwd.org_dir.";
215 const char *local_dir
= nis_local_directory ();
216 size_t len_local_dir
= strlen (local_dir
);
218 pwdtable
= malloc (sizeof (key
) + len_local_dir
);
219 if (pwdtable
== NULL
)
220 return NSS_STATUS_TRYAGAIN
;
222 pwdtablelen
= ((char *) mempcpy (mempcpy (pwdtable
,
223 key
, sizeof (key
) - 1),
224 local_dir
, len_local_dir
+ 1)
228 if (ent
->blacklist
.data
!= NULL
)
230 ent
->blacklist
.current
= 1;
231 ent
->blacklist
.data
[0] = '|';
232 ent
->blacklist
.data
[1] = '\0';
235 ent
->blacklist
.current
= 0;
237 if (ent
->stream
== NULL
)
239 ent
->stream
= fopen ("/etc/passwd", "r");
241 if (ent
->stream
== NULL
)
242 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
245 /* We have to make sure the file is `closed on exec'. */
248 result
= flags
= fcntl (fileno (ent
->stream
), F_GETFD
, 0);
252 result
= fcntl (fileno (ent
->stream
), F_SETFD
, flags
);
256 /* Something went wrong. Close the stream and return a
258 fclose (ent
->stream
);
260 status
= NSS_STATUS_UNAVAIL
;
265 rewind (ent
->stream
);
267 give_pwd_free (&ent
->pwd
);
274 _nss_compat_setpwent (void)
276 enum nss_status result
;
278 __libc_lock_lock (lock
);
282 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
283 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
286 result
= internal_setpwent (&ext_ent
);
288 __libc_lock_unlock (lock
);
294 static enum nss_status
295 internal_endpwent (ent_t
*ent
)
297 if (ent
->stream
!= NULL
)
299 fclose (ent
->stream
);
304 __internal_endnetgrent (&ent
->netgrdata
);
306 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
308 if (ent
->oldkey
!= NULL
)
315 if (ent
->result
!= NULL
)
317 nis_freeresult (ent
->result
);
321 if (ent
->blacklist
.data
!= NULL
)
323 ent
->blacklist
.current
= 1;
324 ent
->blacklist
.data
[0] = '|';
325 ent
->blacklist
.data
[1] = '\0';
328 ent
->blacklist
.current
= 0;
330 give_pwd_free (&ent
->pwd
);
332 return NSS_STATUS_SUCCESS
;
336 _nss_compat_endpwent (void)
338 enum nss_status result
;
340 __libc_lock_lock (lock
);
342 result
= internal_endpwent (&ext_ent
);
344 __libc_lock_unlock (lock
);
349 static enum nss_status
350 getpwent_next_nis_netgr (const char *name
, struct passwd
*result
, ent_t
*ent
,
351 char *group
, char *buffer
, size_t buflen
, int *errnop
)
353 struct parser_data
*data
= (void *) buffer
;
354 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
355 int status
, outvallen
;
358 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
362 give_pwd_free (&ent
->pwd
);
363 return NSS_STATUS_UNAVAIL
;
366 if (ent
->first
== TRUE
)
368 memset (&ent
->netgrdata
, 0, sizeof (struct __netgrent
));
369 __internal_setnetgrent (group
, &ent
->netgrdata
);
378 saved_cursor
= ent
->netgrdata
.cursor
;
379 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
380 &ent
->netgrdata
, buffer
, buflen
,
384 __internal_endnetgrent (&ent
->netgrdata
);
386 give_pwd_free (&ent
->pwd
);
387 return NSS_STATUS_RETURN
;
390 if (user
== NULL
|| user
[0] == '-')
393 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
396 /* If name != NULL, we are called from getpwnam. */
398 if (strcmp (user
, name
) != 0)
401 if (yp_match (ypdomain
, "passwd.byname", user
,
402 strlen (user
), &outval
, &outvallen
)
406 p2len
= pwd_need_buflen (&ent
->pwd
);
411 return NSS_STATUS_TRYAGAIN
;
413 p2
= buffer
+ (buflen
- p2len
);
416 if (buflen
< ((size_t) outvallen
+ 1))
420 return NSS_STATUS_TRYAGAIN
;
422 p
= strncpy (buffer
, outval
, buflen
);
427 parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
, errnop
);
430 ent
->netgrdata
.cursor
= saved_cursor
;
431 return NSS_STATUS_TRYAGAIN
;
436 /* Store the User in the blacklist for the "+" at the end of
438 blacklist_store_name (result
->pw_name
, ent
);
439 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
444 return NSS_STATUS_SUCCESS
;
447 static enum nss_status
448 getpwent_next_nisplus_netgr (const char *name
, struct passwd
*result
,
449 ent_t
*ent
, char *group
, char *buffer
,
450 size_t buflen
, int *errnop
)
452 char *ypdomain
, *host
, *user
, *domain
, *p2
;
453 int status
, parse_res
;
457 /* Maybe we should use domainname here ? We need the current
458 domainname for the domain field in netgroups */
459 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
463 give_pwd_free (&ent
->pwd
);
464 return NSS_STATUS_UNAVAIL
;
467 if (ent
->first
== TRUE
)
469 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
470 __internal_setnetgrent (group
, &ent
->netgrdata
);
478 saved_cursor
= ent
->netgrdata
.cursor
;
479 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
480 &ent
->netgrdata
, buffer
, buflen
,
484 __internal_endnetgrent (&ent
->netgrdata
);
486 give_pwd_free (&ent
->pwd
);
487 return NSS_STATUS_RETURN
;
490 if (user
== NULL
|| user
[0] == '-')
493 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
496 /* If name != NULL, we are called from getpwnam */
498 if (strcmp (user
, name
) != 0)
501 p2len
= pwd_need_buflen (&ent
->pwd
);
505 return NSS_STATUS_TRYAGAIN
;
507 p2
= buffer
+ (buflen
- p2len
);
510 char buf
[strlen (user
) + 30 + pwdtablelen
];
511 sprintf(buf
, "[name=%s],%s", user
, pwdtable
);
512 nisres
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
514 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
516 nis_freeresult (nisres
);
519 parse_res
= _nss_nisplus_parse_pwent (nisres
, result
, buffer
,
523 nis_freeresult (nisres
);
524 ent
->netgrdata
.cursor
= saved_cursor
;
526 return NSS_STATUS_TRYAGAIN
;
528 nis_freeresult (nisres
);
532 /* Store the User in the blacklist for the "+" at the end of
534 blacklist_store_name (result
->pw_name
, ent
);
535 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
540 return NSS_STATUS_SUCCESS
;
543 /* get the next user from NIS+ (+ entry) */
544 static enum nss_status
545 getpwent_next_nisplus (struct passwd
*result
, ent_t
*ent
, char *buffer
,
546 size_t buflen
, int *errnop
)
552 p2len
= pwd_need_buflen (&ent
->pwd
);
556 return NSS_STATUS_TRYAGAIN
;
558 p2
= buffer
+ (buflen
- p2len
);
563 nis_result
*saved_res
;
568 saved_res
= ent
->result
;
570 ent
->result
= nis_first_entry (pwdtable
);
571 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
574 give_pwd_free (&ent
->pwd
);
575 return niserr2nss (ent
->result
->status
);
583 res
= nis_next_entry (pwdtable
, &ent
->result
->cookie
);
584 saved_res
= ent
->result
;
587 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
590 nis_freeresult (saved_res
);
591 give_pwd_free (&ent
->pwd
);
592 return niserr2nss (ent
->result
->status
);
595 parse_res
= _nss_nisplus_parse_pwent (ent
->result
, result
, buffer
,
599 nis_freeresult (ent
->result
);
600 ent
->result
= saved_res
;
601 ent
->first
= saved_first
;
603 return NSS_STATUS_TRYAGAIN
;
608 nis_freeresult (saved_res
);
612 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
613 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
617 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
619 return NSS_STATUS_SUCCESS
;
622 static enum nss_status
623 getpwent_next_nis (struct passwd
*result
, ent_t
*ent
, char *buffer
,
624 size_t buflen
, int *errnop
)
626 struct parser_data
*data
= (void *) buffer
;
627 char *domain
, *outkey
, *outval
, *p
, *p2
;
628 int outkeylen
, outvallen
, parse_res
;
631 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
634 give_pwd_free (&ent
->pwd
);
635 return NSS_STATUS_UNAVAIL
;
638 p2len
= pwd_need_buflen (&ent
->pwd
);
642 return NSS_STATUS_TRYAGAIN
;
644 p2
= buffer
+ (buflen
- p2len
);
654 if (yp_first (domain
, "passwd.byname", &outkey
, &outkeylen
,
655 &outval
, &outvallen
) != YPERR_SUCCESS
)
658 give_pwd_free (&ent
->pwd
);
659 return NSS_STATUS_UNAVAIL
;
662 if (buflen
< ((size_t) outvallen
+ 1))
666 return NSS_STATUS_TRYAGAIN
;
670 saved_oldkey
= ent
->oldkey
;
671 saved_oldlen
= ent
->oldkeylen
;
672 ent
->oldkey
= outkey
;
673 ent
->oldkeylen
= outkeylen
;
678 if (yp_next (domain
, "passwd.byname", ent
->oldkey
, ent
->oldkeylen
,
679 &outkey
, &outkeylen
, &outval
, &outvallen
)
683 give_pwd_free (&ent
->pwd
);
685 return NSS_STATUS_NOTFOUND
;
688 if (buflen
< ((size_t) outvallen
+ 1))
692 return NSS_STATUS_TRYAGAIN
;
696 saved_oldkey
= ent
->oldkey
;
697 saved_oldlen
= ent
->oldkeylen
;
698 ent
->oldkey
= outkey
;
699 ent
->oldkeylen
= outkeylen
;
702 /* Copy the found data to our buffer */
703 p
= strncpy (buffer
, outval
, buflen
);
705 /* ...and free the data. */
710 parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
, errnop
);
714 ent
->oldkey
= saved_oldkey
;
715 ent
->oldkeylen
= saved_oldlen
;
716 ent
->first
= saved_first
;
718 return NSS_STATUS_TRYAGAIN
;
726 && in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
731 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
733 return NSS_STATUS_SUCCESS
;
736 /* This function handle the +user entrys in /etc/passwd */
737 static enum nss_status
738 getpwnam_plususer (const char *name
, struct passwd
*result
, char *buffer
,
739 size_t buflen
, int *errnop
)
741 struct parser_data
*data
= (void *) buffer
;
747 memset (&pwd
, '\0', sizeof (struct passwd
));
749 copy_pwd_changes (&pwd
, result
, NULL
, 0);
751 plen
= pwd_need_buflen (&pwd
);
755 return NSS_STATUS_TRYAGAIN
;
757 p
= buffer
+ (buflen
- plen
);
760 if (use_nisplus
) /* Do the NIS+ query here */
763 char buf
[strlen (name
) + 24 + pwdtablelen
];
765 sprintf(buf
, "[name=%s],%s", name
, pwdtable
);
766 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
767 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
769 enum nss_status status
= niserr2nss (res
->status
);
771 nis_freeresult (res
);
774 parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
778 nis_freeresult (res
);
780 return NSS_STATUS_TRYAGAIN
;
782 nis_freeresult (res
);
786 char *domain
, *outval
, *ptr
;
789 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
790 return NSS_STATUS_NOTFOUND
;
792 if (yp_match (domain
, "passwd.byname", name
, strlen (name
),
793 &outval
, &outvallen
) != YPERR_SUCCESS
)
796 return NSS_STATUS_NOTFOUND
;
799 if (buflen
< ((size_t) outvallen
+ 1))
803 return NSS_STATUS_TRYAGAIN
;
805 ptr
= strncpy (buffer
, outval
, buflen
);
807 while (isspace (*ptr
))
809 parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
, errnop
);
811 return NSS_STATUS_TRYAGAIN
;
816 copy_pwd_changes (result
, &pwd
, p
, plen
);
817 give_pwd_free (&pwd
);
818 /* We found the entry. */
819 return NSS_STATUS_SUCCESS
;
823 /* Give buffer the old len back */
825 give_pwd_free (&pwd
);
827 return NSS_STATUS_RETURN
;
830 static enum nss_status
831 getpwent_next_file (struct passwd
*result
, ent_t
*ent
,
832 char *buffer
, size_t buflen
, int *errnop
)
834 struct parser_data
*data
= (void *) buffer
;
843 fgetpos (ent
->stream
, &pos
);
844 buffer
[buflen
- 1] = '\xff';
845 p
= fgets (buffer
, buflen
, ent
->stream
);
846 if (p
== NULL
&& feof (ent
->stream
))
849 return NSS_STATUS_NOTFOUND
;
851 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
853 fsetpos (ent
->stream
, &pos
);
855 return NSS_STATUS_TRYAGAIN
;
858 /* Terminate the line for any case. */
859 buffer
[buflen
- 1] = '\0';
861 /* Skip leading blanks. */
865 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
866 /* Parse the line. If it is invalid, loop to
867 get the next line of the file to parse. */
868 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
873 /* The parser ran out of space. */
874 fsetpos (ent
->stream
, &pos
);
876 return NSS_STATUS_TRYAGAIN
;
879 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
880 /* This is a real entry. */
884 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
885 && result
->pw_name
[2] != '\0')
887 /* XXX Do not use fixed length buffer. */
889 char *user
, *host
, *domain
;
890 struct __netgrent netgrdata
;
892 bzero (&netgrdata
, sizeof (struct __netgrent
));
893 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
894 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
895 buf2
, sizeof (buf2
), errnop
))
897 if (user
!= NULL
&& user
[0] != '-')
898 blacklist_store_name (user
, ent
);
900 __internal_endnetgrent (&netgrdata
);
905 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
906 && result
->pw_name
[2] != '\0')
910 ent
->netgroup
= TRUE
;
912 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
915 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
,
917 buffer
, buflen
, errnop
);
919 status
= getpwent_next_nis_netgr (NULL
, result
, ent
,
921 buffer
, buflen
, errnop
);
922 if (status
== NSS_STATUS_RETURN
)
926 if (status
== NSS_STATUS_NOTFOUND
)
933 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
934 && result
->pw_name
[1] != '@')
936 blacklist_store_name (&result
->pw_name
[1], ent
);
941 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
942 && result
->pw_name
[1] != '@')
944 enum nss_status status
;
946 /* Store the User in the blacklist for the "+" at the end of
948 blacklist_store_name (&result
->pw_name
[1], ent
);
949 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
951 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
954 if (status
== NSS_STATUS_RETURN
/* We couldn't parse the entry */
955 || status
== NSS_STATUS_NOTFOUND
) /* entry doesn't exist */
959 if (status
== NSS_STATUS_TRYAGAIN
)
961 /* The parser ran out of space */
962 fsetpos (ent
->stream
, &pos
);
970 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
974 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
977 return getpwent_next_nisplus (result
, ent
, buffer
, buflen
, errnop
);
979 return getpwent_next_nis (result
, ent
, buffer
, buflen
, errnop
);
983 return NSS_STATUS_SUCCESS
;
987 static enum nss_status
988 internal_getpwent_r (struct passwd
*pw
, ent_t
*ent
, char *buffer
,
989 size_t buflen
, int *errnop
)
995 /* We are searching members in a netgroup */
996 /* Since this is not the first call, we don't need the group name */
998 status
= getpwent_next_nisplus_netgr (NULL
, pw
, ent
, NULL
, buffer
,
1001 status
= getpwent_next_nis_netgr (NULL
, pw
, ent
, NULL
, buffer
, buflen
,
1003 if (status
== NSS_STATUS_RETURN
)
1004 return getpwent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
1012 return getpwent_next_nisplus (pw
, ent
, buffer
, buflen
, errnop
);
1014 return getpwent_next_nis (pw
, ent
, buffer
, buflen
, errnop
);
1017 return getpwent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
1021 _nss_compat_getpwent_r (struct passwd
*pwd
, char *buffer
, size_t buflen
,
1024 enum nss_status status
= NSS_STATUS_SUCCESS
;
1026 __libc_lock_lock (lock
);
1030 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1031 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1034 /* Be prepared that the setpwent function was not called before. */
1035 if (ext_ent
.stream
== NULL
)
1036 status
= internal_setpwent (&ext_ent
);
1038 if (status
== NSS_STATUS_SUCCESS
)
1039 status
= internal_getpwent_r (pwd
, &ext_ent
, buffer
, buflen
, errnop
);
1041 __libc_lock_unlock (lock
);
1046 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
1047 static enum nss_status
1048 internal_getpwnam_r (const char *name
, struct passwd
*result
, ent_t
*ent
,
1049 char *buffer
, size_t buflen
, int *errnop
)
1051 struct parser_data
*data
= (void *) buffer
;
1061 fgetpos (ent
->stream
, &pos
);
1062 buffer
[buflen
- 1] = '\xff';
1063 p
= fgets (buffer
, buflen
, ent
->stream
);
1064 if (p
== NULL
&& feof (ent
->stream
))
1067 return NSS_STATUS_NOTFOUND
;
1069 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
1071 fsetpos (ent
->stream
, &pos
);
1073 return NSS_STATUS_TRYAGAIN
;
1076 /* Terminate the line for any case. */
1077 buffer
[buflen
- 1] = '\0';
1079 /* Skip leading blanks. */
1080 while (isspace (*p
))
1083 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1084 /* Parse the line. If it is invalid, loop to
1085 get the next line of the file to parse. */
1086 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
1089 if (parse_res
== -1)
1091 /* The parser ran out of space. */
1092 fsetpos (ent
->stream
, &pos
);
1094 return NSS_STATUS_TRYAGAIN
;
1097 /* This is a real entry. */
1098 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1100 if (strcmp (result
->pw_name
, name
) == 0)
1101 return NSS_STATUS_SUCCESS
;
1107 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1108 && result
->pw_name
[2] != '\0')
1110 /* XXX Do not use fixed length buffers. */
1112 char *user
, *host
, *domain
;
1113 struct __netgrent netgrdata
;
1115 bzero (&netgrdata
, sizeof (struct __netgrent
));
1116 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1117 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
1118 buf2
, sizeof (buf2
), errnop
))
1120 if (user
!= NULL
&& user
[0] != '-')
1121 if (strcmp (user
, name
) == 0)
1122 return NSS_STATUS_NOTFOUND
;
1124 __internal_endnetgrent (&netgrdata
);
1129 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1130 && result
->pw_name
[2] != '\0')
1132 char buf
[strlen (result
->pw_name
)];
1135 strcpy (buf
, &result
->pw_name
[2]);
1136 ent
->netgroup
= TRUE
;
1138 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1143 status
= getpwent_next_nisplus_netgr (name
, result
, ent
, buf
,
1144 buffer
, buflen
, errnop
);
1146 status
= getpwent_next_nis_netgr (name
, result
, ent
, buf
,
1147 buffer
, buflen
, errnop
);
1148 if (status
== NSS_STATUS_RETURN
)
1151 if (status
== NSS_STATUS_SUCCESS
&&
1152 strcmp (result
->pw_name
, name
) == 0)
1153 return NSS_STATUS_SUCCESS
;
1154 } while (status
== NSS_STATUS_SUCCESS
);
1159 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1160 && result
->pw_name
[1] != '@')
1162 if (strcmp (&result
->pw_name
[1], name
) == 0)
1165 return NSS_STATUS_NOTFOUND
;
1172 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1173 && result
->pw_name
[1] != '@')
1175 if (strcmp (name
, &result
->pw_name
[1]) == 0)
1177 enum nss_status status
;
1179 status
= getpwnam_plususer (name
, result
, buffer
, buflen
,
1181 if (status
== NSS_STATUS_RETURN
)
1182 /* We couldn't parse the entry */
1183 return NSS_STATUS_NOTFOUND
;
1190 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1192 enum nss_status status
;
1194 status
= getpwnam_plususer (name
, result
, buffer
, buflen
, errnop
);
1195 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1198 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1199 return NSS_STATUS_NOTFOUND
;
1204 return NSS_STATUS_SUCCESS
;
1208 _nss_compat_getpwnam_r (const char *name
, struct passwd
*pwd
,
1209 char *buffer
, size_t buflen
, int *errnop
)
1211 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1212 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1213 enum nss_status status
;
1215 if (name
[0] == '-' || name
[0] == '+')
1218 return NSS_STATUS_NOTFOUND
;
1221 __libc_lock_lock (lock
);
1225 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1226 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1229 __libc_lock_unlock (lock
);
1231 status
= internal_setpwent (&ent
);
1232 if (status
!= NSS_STATUS_SUCCESS
)
1235 status
= internal_getpwnam_r (name
, pwd
, &ent
, buffer
, buflen
, errnop
);
1237 internal_endpwent (&ent
);
1242 /* This function handle the + entry in /etc/passwd for getpwuid */
1243 static enum nss_status
1244 getpwuid_plususer (uid_t uid
, struct passwd
*result
, char *buffer
,
1245 size_t buflen
, int *errnop
)
1247 struct parser_data
*data
= (void *) buffer
;
1253 memset (&pwd
, '\0', sizeof (struct passwd
));
1255 copy_pwd_changes (&pwd
, result
, NULL
, 0);
1257 plen
= pwd_need_buflen (&pwd
);
1261 return NSS_STATUS_TRYAGAIN
;
1263 p
= buffer
+ (buflen
- plen
);
1266 if (use_nisplus
) /* Do the NIS+ query here */
1269 char buf
[1024 + pwdtablelen
];
1271 snprintf(buf
, sizeof (buf
), "[uid=%d],%s", uid
, pwdtable
);
1272 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
1273 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
1275 enum nss_status status
= niserr2nss (res
->status
);
1277 nis_freeresult (res
);
1280 if ((parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
1281 buflen
, errnop
)) == -1)
1283 nis_freeresult (res
);
1285 return NSS_STATUS_TRYAGAIN
;
1287 nis_freeresult (res
);
1292 char *domain
, *outval
, *ptr
;
1295 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
1298 return NSS_STATUS_TRYAGAIN
;
1301 sprintf (buf
, "%d", uid
);
1302 if (yp_match (domain
, "passwd.byuid", buf
, strlen (buf
),
1303 &outval
, &outvallen
)
1307 return NSS_STATUS_TRYAGAIN
;
1310 if ( buflen
< ((size_t) outvallen
+ 1))
1314 return NSS_STATUS_TRYAGAIN
;
1317 ptr
= strncpy (buffer
, outval
, buflen
);
1320 while (isspace (*ptr
))
1322 parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
, errnop
);
1323 if (parse_res
== -1)
1324 return NSS_STATUS_TRYAGAIN
;
1329 copy_pwd_changes (result
, &pwd
, p
, plen
);
1330 give_pwd_free (&pwd
);
1331 /* We found the entry. */
1332 return NSS_STATUS_SUCCESS
;
1336 /* Give buffer the old len back */
1338 give_pwd_free (&pwd
);
1340 return NSS_STATUS_RETURN
;
1343 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
1344 static enum nss_status
1345 internal_getpwuid_r (uid_t uid
, struct passwd
*result
, ent_t
*ent
,
1346 char *buffer
, size_t buflen
, int *errnop
)
1348 struct parser_data
*data
= (void *) buffer
;
1358 fgetpos (ent
->stream
, &pos
);
1359 buffer
[buflen
- 1] = '\xff';
1360 p
= fgets (buffer
, buflen
, ent
->stream
);
1361 if (p
== NULL
&& feof (ent
->stream
))
1362 return NSS_STATUS_NOTFOUND
;
1363 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
1365 fsetpos (ent
->stream
, &pos
);
1367 return NSS_STATUS_TRYAGAIN
;
1370 /* Terminate the line for any case. */
1371 buffer
[buflen
- 1] = '\0';
1373 /* Skip leading blanks. */
1374 while (isspace (*p
))
1377 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1378 /* Parse the line. If it is invalid, loop to
1379 get the next line of the file to parse. */
1380 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
1383 if (parse_res
== -1)
1385 /* The parser ran out of space. */
1386 fsetpos (ent
->stream
, &pos
);
1388 return NSS_STATUS_TRYAGAIN
;
1391 /* This is a real entry. */
1392 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1394 if (result
->pw_uid
== uid
)
1395 return NSS_STATUS_SUCCESS
;
1401 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1402 && result
->pw_name
[2] != '\0')
1404 /* XXX Do not use fixed length buffers. */
1406 char *user
, *host
, *domain
;
1407 struct __netgrent netgrdata
;
1409 bzero (&netgrdata
, sizeof (struct __netgrent
));
1410 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1411 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
1412 buf2
, sizeof (buf2
), errnop
))
1414 if (user
!= NULL
&& user
[0] != '-')
1415 blacklist_store_name (user
, ent
);
1417 __internal_endnetgrent (&netgrdata
);
1422 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1423 && result
->pw_name
[2] != '\0')
1425 char buf
[strlen (result
->pw_name
)];
1428 strcpy (buf
, &result
->pw_name
[2]);
1429 ent
->netgroup
= TRUE
;
1431 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1436 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
, buf
,
1437 buffer
, buflen
, errnop
);
1439 status
= getpwent_next_nis_netgr (NULL
, result
, ent
, buf
,
1440 buffer
, buflen
, errnop
);
1441 if (status
== NSS_STATUS_RETURN
)
1444 if (status
== NSS_STATUS_SUCCESS
&& uid
== result
->pw_uid
)
1445 return NSS_STATUS_SUCCESS
;
1446 } while (status
== NSS_STATUS_SUCCESS
);
1451 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1452 && result
->pw_name
[1] != '@')
1454 blacklist_store_name (&result
->pw_name
[1], ent
);
1459 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1460 && result
->pw_name
[1] != '@')
1462 enum nss_status status
;
1464 /* Store the User in the blacklist for the "+" at the end of
1466 blacklist_store_name (&result
->pw_name
[1], ent
);
1467 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
1469 if (status
== NSS_STATUS_SUCCESS
&& result
->pw_uid
== uid
)
1476 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1478 enum nss_status status
;
1480 status
= getpwuid_plususer (uid
, result
, buffer
, buflen
, errnop
);
1481 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1484 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1485 return NSS_STATUS_NOTFOUND
;
1490 return NSS_STATUS_SUCCESS
;
1494 _nss_compat_getpwuid_r (uid_t uid
, struct passwd
*pwd
,
1495 char *buffer
, size_t buflen
, int *errnop
)
1497 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1498 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1499 enum nss_status status
;
1501 __libc_lock_lock (lock
);
1505 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1506 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1509 __libc_lock_unlock (lock
);
1511 status
= internal_setpwent (&ent
);
1512 if (status
!= NSS_STATUS_SUCCESS
)
1515 status
= internal_getpwuid_r (uid
, pwd
, &ent
, buffer
, buflen
, errnop
);
1517 internal_endpwent (&ent
);
1523 /* Support routines for remembering -@netgroup and -user entries.
1524 The names are stored in a single string with `|' as separator. */
1526 blacklist_store_name (const char *name
, ent_t
*ent
)
1528 int namelen
= strlen (name
);
1531 /* first call, setup cache */
1532 if (ent
->blacklist
.size
== 0)
1534 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1535 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1536 if (ent
->blacklist
.data
== NULL
)
1538 ent
->blacklist
.data
[0] = '|';
1539 ent
->blacklist
.data
[1] = '\0';
1540 ent
->blacklist
.current
= 1;
1544 if (in_blacklist (name
, namelen
, ent
))
1545 return; /* no duplicates */
1547 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1549 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1550 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1553 free (ent
->blacklist
.data
);
1554 ent
->blacklist
.size
= 0;
1557 ent
->blacklist
.data
= tmp
;
1561 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1564 ent
->blacklist
.current
+= namelen
+ 1;
1569 /* returns TRUE if ent->blacklist contains name, else FALSE */
1571 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1573 char buf
[namelen
+ 3];
1576 if (ent
->blacklist
.data
== NULL
)
1580 cp
= stpcpy (&buf
[1], name
);
1583 return strstr (ent
->blacklist
.data
, buf
) != NULL
;
This page took 0.109011 seconds and 6 git commands to generate.