]>
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
);
684 return NSS_STATUS_NOTFOUND
;
687 if (buflen
< ((size_t) outvallen
+ 1))
691 return NSS_STATUS_TRYAGAIN
;
695 saved_oldkey
= ent
->oldkey
;
696 saved_oldlen
= ent
->oldkeylen
;
697 ent
->oldkey
= outkey
;
698 ent
->oldkeylen
= outkeylen
;
701 /* Copy the found data to our buffer */
702 p
= strncpy (buffer
, outval
, buflen
);
704 /* ...and free the data. */
709 parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
, errnop
);
713 ent
->oldkey
= saved_oldkey
;
714 ent
->oldkeylen
= saved_oldlen
;
715 ent
->first
= saved_first
;
717 return NSS_STATUS_TRYAGAIN
;
725 && in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
730 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
732 return NSS_STATUS_SUCCESS
;
735 /* This function handle the +user entrys in /etc/passwd */
736 static enum nss_status
737 getpwnam_plususer (const char *name
, struct passwd
*result
, char *buffer
,
738 size_t buflen
, int *errnop
)
740 struct parser_data
*data
= (void *) buffer
;
746 memset (&pwd
, '\0', sizeof (struct passwd
));
748 copy_pwd_changes (&pwd
, result
, NULL
, 0);
750 plen
= pwd_need_buflen (&pwd
);
754 return NSS_STATUS_TRYAGAIN
;
756 p
= buffer
+ (buflen
- plen
);
759 if (use_nisplus
) /* Do the NIS+ query here */
762 char buf
[strlen (name
) + 24 + pwdtablelen
];
764 sprintf(buf
, "[name=%s],%s", name
, pwdtable
);
765 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
766 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
768 enum nss_status status
= niserr2nss (res
->status
);
770 nis_freeresult (res
);
773 parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
777 nis_freeresult (res
);
779 return NSS_STATUS_TRYAGAIN
;
781 nis_freeresult (res
);
785 char *domain
, *outval
, *ptr
;
788 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
789 return NSS_STATUS_NOTFOUND
;
791 if (yp_match (domain
, "passwd.byname", name
, strlen (name
),
792 &outval
, &outvallen
) != YPERR_SUCCESS
)
793 return NSS_STATUS_NOTFOUND
;
795 if (buflen
< ((size_t) outvallen
+ 1))
799 return NSS_STATUS_TRYAGAIN
;
801 ptr
= strncpy (buffer
, outval
, buflen
);
803 while (isspace (*ptr
))
805 parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
, errnop
);
807 return NSS_STATUS_TRYAGAIN
;
812 copy_pwd_changes (result
, &pwd
, p
, plen
);
813 give_pwd_free (&pwd
);
814 /* We found the entry. */
815 return NSS_STATUS_SUCCESS
;
819 /* Give buffer the old len back */
821 give_pwd_free (&pwd
);
823 return NSS_STATUS_RETURN
;
826 static enum nss_status
827 getpwent_next_file (struct passwd
*result
, ent_t
*ent
,
828 char *buffer
, size_t buflen
, int *errnop
)
830 struct parser_data
*data
= (void *) buffer
;
839 fgetpos (ent
->stream
, &pos
);
840 buffer
[buflen
- 1] = '\xff';
841 p
= fgets (buffer
, buflen
, ent
->stream
);
842 if (p
== NULL
&& feof (ent
->stream
))
843 return NSS_STATUS_NOTFOUND
;
844 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
846 fsetpos (ent
->stream
, &pos
);
848 return NSS_STATUS_TRYAGAIN
;
851 /* Terminate the line for any case. */
852 buffer
[buflen
- 1] = '\0';
854 /* Skip leading blanks. */
858 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
859 /* Parse the line. If it is invalid, loop to
860 get the next line of the file to parse. */
861 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
866 /* The parser ran out of space. */
867 fsetpos (ent
->stream
, &pos
);
869 return NSS_STATUS_TRYAGAIN
;
872 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
873 /* This is a real entry. */
877 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
878 && result
->pw_name
[2] != '\0')
880 /* XXX Do not use fixed length buffer. */
882 char *user
, *host
, *domain
;
883 struct __netgrent netgrdata
;
885 bzero (&netgrdata
, sizeof (struct __netgrent
));
886 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
887 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
888 buf2
, sizeof (buf2
), errnop
))
890 if (user
!= NULL
&& user
[0] != '-')
891 blacklist_store_name (user
, ent
);
893 __internal_endnetgrent (&netgrdata
);
898 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
899 && result
->pw_name
[2] != '\0')
903 ent
->netgroup
= TRUE
;
905 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
908 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
,
910 buffer
, buflen
, errnop
);
912 status
= getpwent_next_nis_netgr (NULL
, result
, ent
,
914 buffer
, buflen
, errnop
);
915 if (status
== NSS_STATUS_RETURN
)
922 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
923 && result
->pw_name
[1] != '@')
925 blacklist_store_name (&result
->pw_name
[1], ent
);
930 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
931 && result
->pw_name
[1] != '@')
933 enum nss_status status
;
935 /* Store the User in the blacklist for the "+" at the end of
937 blacklist_store_name (&result
->pw_name
[1], ent
);
938 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
940 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
943 if (status
== NSS_STATUS_RETURN
/* We couldn't parse the entry */
944 || status
== NSS_STATUS_NOTFOUND
) /* entry doesn't exist */
948 if (status
== NSS_STATUS_TRYAGAIN
)
950 /* The parser ran out of space */
951 fsetpos (ent
->stream
, &pos
);
959 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
963 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
966 return getpwent_next_nisplus (result
, ent
, buffer
, buflen
, errnop
);
968 return getpwent_next_nis (result
, ent
, buffer
, buflen
, errnop
);
972 return NSS_STATUS_SUCCESS
;
976 static enum nss_status
977 internal_getpwent_r (struct passwd
*pw
, ent_t
*ent
, char *buffer
,
978 size_t buflen
, int *errnop
)
984 /* We are searching members in a netgroup */
985 /* Since this is not the first call, we don't need the group name */
987 status
= getpwent_next_nisplus_netgr (NULL
, pw
, ent
, NULL
, buffer
,
990 status
= getpwent_next_nis_netgr (NULL
, pw
, ent
, NULL
, buffer
, buflen
,
992 if (status
== NSS_STATUS_RETURN
)
993 return getpwent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
1001 return getpwent_next_nisplus (pw
, ent
, buffer
, buflen
, errnop
);
1003 return getpwent_next_nis (pw
, ent
, buffer
, buflen
, errnop
);
1006 return getpwent_next_file (pw
, ent
, buffer
, buflen
, errnop
);
1010 _nss_compat_getpwent_r (struct passwd
*pwd
, char *buffer
, size_t buflen
,
1013 enum nss_status status
= NSS_STATUS_SUCCESS
;
1015 __libc_lock_lock (lock
);
1019 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1020 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1023 /* Be prepared that the setpwent function was not called before. */
1024 if (ext_ent
.stream
== NULL
)
1025 status
= internal_setpwent (&ext_ent
);
1027 if (status
== NSS_STATUS_SUCCESS
)
1028 status
= internal_getpwent_r (pwd
, &ext_ent
, buffer
, buflen
, errnop
);
1030 __libc_lock_unlock (lock
);
1035 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
1036 static enum nss_status
1037 internal_getpwnam_r (const char *name
, struct passwd
*result
, ent_t
*ent
,
1038 char *buffer
, size_t buflen
, int *errnop
)
1040 struct parser_data
*data
= (void *) buffer
;
1050 fgetpos (ent
->stream
, &pos
);
1051 buffer
[buflen
- 1] = '\xff';
1052 p
= fgets (buffer
, buflen
, ent
->stream
);
1053 if (p
== NULL
&& feof (ent
->stream
))
1054 return NSS_STATUS_NOTFOUND
;
1055 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
1057 fsetpos (ent
->stream
, &pos
);
1059 return NSS_STATUS_TRYAGAIN
;
1062 /* Terminate the line for any case. */
1063 buffer
[buflen
- 1] = '\0';
1065 /* Skip leading blanks. */
1066 while (isspace (*p
))
1069 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1070 /* Parse the line. If it is invalid, loop to
1071 get the next line of the file to parse. */
1072 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
1075 if (parse_res
== -1)
1077 /* The parser ran out of space. */
1078 fsetpos (ent
->stream
, &pos
);
1080 return NSS_STATUS_TRYAGAIN
;
1083 /* This is a real entry. */
1084 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1086 if (strcmp (result
->pw_name
, name
) == 0)
1087 return NSS_STATUS_SUCCESS
;
1093 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1094 && result
->pw_name
[2] != '\0')
1096 /* XXX Do not use fixed length buffers. */
1098 char *user
, *host
, *domain
;
1099 struct __netgrent netgrdata
;
1101 bzero (&netgrdata
, sizeof (struct __netgrent
));
1102 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1103 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
1104 buf2
, sizeof (buf2
), errnop
))
1106 if (user
!= NULL
&& user
[0] != '-')
1107 if (strcmp (user
, name
) == 0)
1108 return NSS_STATUS_NOTFOUND
;
1110 __internal_endnetgrent (&netgrdata
);
1115 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1116 && result
->pw_name
[2] != '\0')
1118 char buf
[strlen (result
->pw_name
)];
1121 strcpy (buf
, &result
->pw_name
[2]);
1122 ent
->netgroup
= TRUE
;
1124 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1129 status
= getpwent_next_nisplus_netgr (name
, result
, ent
, buf
,
1130 buffer
, buflen
, errnop
);
1132 status
= getpwent_next_nis_netgr (name
, result
, ent
, buf
,
1133 buffer
, buflen
, errnop
);
1134 if (status
== NSS_STATUS_RETURN
)
1137 if (status
== NSS_STATUS_SUCCESS
&&
1138 strcmp (result
->pw_name
, name
) == 0)
1139 return NSS_STATUS_SUCCESS
;
1140 } while (status
== NSS_STATUS_SUCCESS
);
1145 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1146 && result
->pw_name
[1] != '@')
1148 if (strcmp (&result
->pw_name
[1], name
) == 0)
1149 return NSS_STATUS_NOTFOUND
;
1155 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1156 && result
->pw_name
[1] != '@')
1158 if (strcmp (name
, &result
->pw_name
[1]) == 0)
1160 enum nss_status status
;
1162 status
= getpwnam_plususer (name
, result
, buffer
, buflen
,
1164 if (status
== NSS_STATUS_RETURN
)
1165 /* We couldn't parse the entry */
1166 return NSS_STATUS_NOTFOUND
;
1173 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1175 enum nss_status status
;
1177 status
= getpwnam_plususer (name
, result
, buffer
, buflen
, errnop
);
1178 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1181 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1182 return NSS_STATUS_NOTFOUND
;
1187 return NSS_STATUS_SUCCESS
;
1191 _nss_compat_getpwnam_r (const char *name
, struct passwd
*pwd
,
1192 char *buffer
, size_t buflen
, int *errnop
)
1194 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1195 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1196 enum nss_status status
;
1198 if (name
[0] == '-' || name
[0] == '+')
1199 return NSS_STATUS_NOTFOUND
;
1201 __libc_lock_lock (lock
);
1205 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1206 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1209 __libc_lock_unlock (lock
);
1211 status
= internal_setpwent (&ent
);
1212 if (status
!= NSS_STATUS_SUCCESS
)
1215 status
= internal_getpwnam_r (name
, pwd
, &ent
, buffer
, buflen
, errnop
);
1217 internal_endpwent (&ent
);
1222 /* This function handle the + entry in /etc/passwd for getpwuid */
1223 static enum nss_status
1224 getpwuid_plususer (uid_t uid
, struct passwd
*result
, char *buffer
,
1225 size_t buflen
, int *errnop
)
1227 struct parser_data
*data
= (void *) buffer
;
1233 memset (&pwd
, '\0', sizeof (struct passwd
));
1235 copy_pwd_changes (&pwd
, result
, NULL
, 0);
1237 plen
= pwd_need_buflen (&pwd
);
1241 return NSS_STATUS_TRYAGAIN
;
1243 p
= buffer
+ (buflen
- plen
);
1246 if (use_nisplus
) /* Do the NIS+ query here */
1249 char buf
[1024 + pwdtablelen
];
1251 snprintf(buf
, sizeof (buf
), "[uid=%d],%s", uid
, pwdtable
);
1252 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
1253 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
1255 enum nss_status status
= niserr2nss (res
->status
);
1257 nis_freeresult (res
);
1260 if ((parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
1261 buflen
, errnop
)) == -1)
1263 nis_freeresult (res
);
1265 return NSS_STATUS_TRYAGAIN
;
1267 nis_freeresult (res
);
1272 char *domain
, *outval
, *ptr
;
1275 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
1278 return NSS_STATUS_TRYAGAIN
;
1281 sprintf (buf
, "%d", uid
);
1282 if (yp_match (domain
, "passwd.byuid", buf
, strlen (buf
),
1283 &outval
, &outvallen
)
1287 return NSS_STATUS_TRYAGAIN
;
1290 if ( buflen
< ((size_t) outvallen
+ 1))
1294 return NSS_STATUS_TRYAGAIN
;
1297 ptr
= strncpy (buffer
, outval
, buflen
);
1300 while (isspace (*ptr
))
1302 parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
, errnop
);
1303 if (parse_res
== -1)
1304 return NSS_STATUS_TRYAGAIN
;
1309 copy_pwd_changes (result
, &pwd
, p
, plen
);
1310 give_pwd_free (&pwd
);
1311 /* We found the entry. */
1312 return NSS_STATUS_SUCCESS
;
1316 /* Give buffer the old len back */
1318 give_pwd_free (&pwd
);
1320 return NSS_STATUS_RETURN
;
1323 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
1324 static enum nss_status
1325 internal_getpwuid_r (uid_t uid
, struct passwd
*result
, ent_t
*ent
,
1326 char *buffer
, size_t buflen
, int *errnop
)
1328 struct parser_data
*data
= (void *) buffer
;
1338 fgetpos (ent
->stream
, &pos
);
1339 buffer
[buflen
- 1] = '\xff';
1340 p
= fgets (buffer
, buflen
, ent
->stream
);
1341 if (p
== NULL
&& feof (ent
->stream
))
1342 return NSS_STATUS_NOTFOUND
;
1343 if (p
== NULL
|| buffer
[buflen
- 1] != '\xff')
1345 fsetpos (ent
->stream
, &pos
);
1347 return NSS_STATUS_TRYAGAIN
;
1350 /* Terminate the line for any case. */
1351 buffer
[buflen
- 1] = '\0';
1353 /* Skip leading blanks. */
1354 while (isspace (*p
))
1357 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1358 /* Parse the line. If it is invalid, loop to
1359 get the next line of the file to parse. */
1360 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
,
1363 if (parse_res
== -1)
1365 /* The parser ran out of space. */
1366 fsetpos (ent
->stream
, &pos
);
1368 return NSS_STATUS_TRYAGAIN
;
1371 /* This is a real entry. */
1372 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1374 if (result
->pw_uid
== uid
)
1375 return NSS_STATUS_SUCCESS
;
1381 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1382 && result
->pw_name
[2] != '\0')
1384 /* XXX Do not use fixed length buffers. */
1386 char *user
, *host
, *domain
;
1387 struct __netgrent netgrdata
;
1389 bzero (&netgrdata
, sizeof (struct __netgrent
));
1390 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1391 while (__internal_getnetgrent_r (&host
, &user
, &domain
, &netgrdata
,
1392 buf2
, sizeof (buf2
), errnop
))
1394 if (user
!= NULL
&& user
[0] != '-')
1395 blacklist_store_name (user
, ent
);
1397 __internal_endnetgrent (&netgrdata
);
1402 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1403 && result
->pw_name
[2] != '\0')
1405 char buf
[strlen (result
->pw_name
)];
1408 strcpy (buf
, &result
->pw_name
[2]);
1409 ent
->netgroup
= TRUE
;
1411 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1416 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
, buf
,
1417 buffer
, buflen
, errnop
);
1419 status
= getpwent_next_nis_netgr (NULL
, result
, ent
, buf
,
1420 buffer
, buflen
, errnop
);
1421 if (status
== NSS_STATUS_RETURN
)
1424 if (status
== NSS_STATUS_SUCCESS
&& uid
== result
->pw_uid
)
1425 return NSS_STATUS_SUCCESS
;
1426 } while (status
== NSS_STATUS_SUCCESS
);
1431 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1432 && result
->pw_name
[1] != '@')
1434 blacklist_store_name (&result
->pw_name
[1], ent
);
1439 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1440 && result
->pw_name
[1] != '@')
1442 enum nss_status status
;
1444 /* Store the User in the blacklist for the "+" at the end of
1446 blacklist_store_name (&result
->pw_name
[1], ent
);
1447 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
1449 if (status
== NSS_STATUS_SUCCESS
&& result
->pw_uid
== uid
)
1456 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1458 enum nss_status status
;
1460 status
= getpwuid_plususer (uid
, result
, buffer
, buflen
, errnop
);
1461 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1464 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1465 return NSS_STATUS_NOTFOUND
;
1470 return NSS_STATUS_SUCCESS
;
1474 _nss_compat_getpwuid_r (uid_t uid
, struct passwd
*pwd
,
1475 char *buffer
, size_t buflen
, int *errnop
)
1477 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1478 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1479 enum nss_status status
;
1481 __libc_lock_lock (lock
);
1485 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1486 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1489 __libc_lock_unlock (lock
);
1491 status
= internal_setpwent (&ent
);
1492 if (status
!= NSS_STATUS_SUCCESS
)
1495 status
= internal_getpwuid_r (uid
, pwd
, &ent
, buffer
, buflen
, errnop
);
1497 internal_endpwent (&ent
);
1503 /* Support routines for remembering -@netgroup and -user entries.
1504 The names are stored in a single string with `|' as separator. */
1506 blacklist_store_name (const char *name
, ent_t
*ent
)
1508 int namelen
= strlen (name
);
1511 /* first call, setup cache */
1512 if (ent
->blacklist
.size
== 0)
1514 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1515 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1516 if (ent
->blacklist
.data
== NULL
)
1518 ent
->blacklist
.data
[0] = '|';
1519 ent
->blacklist
.data
[1] = '\0';
1520 ent
->blacklist
.current
= 1;
1524 if (in_blacklist (name
, namelen
, ent
))
1525 return; /* no duplicates */
1527 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1529 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1530 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1533 free (ent
->blacklist
.data
);
1534 ent
->blacklist
.size
= 0;
1537 ent
->blacklist
.data
= tmp
;
1541 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1544 ent
->blacklist
.current
+= namelen
+ 1;
1549 /* returns TRUE if ent->blacklist contains name, else FALSE */
1551 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1553 char buf
[namelen
+ 3];
1556 if (ent
->blacklist
.data
== NULL
)
1560 cp
= stpcpy (&buf
[1], name
);
1563 return strstr (ent
->blacklist
.data
, buf
) != NULL
;
This page took 0.11104 seconds and 6 git commands to generate.