]>
sourceware.org Git - glibc.git/blob - nis/nss_compat/compat-pwd.c
1 /* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
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 ent
->blacklist
.current
= 0;
229 if (ent
->blacklist
.data
!= NULL
)
230 ent
->blacklist
.data
[0] = '\0';
232 if (ent
->stream
== NULL
)
234 ent
->stream
= fopen ("/etc/passwd", "r");
236 if (ent
->stream
== NULL
)
237 status
= errno
== EAGAIN
? NSS_STATUS_TRYAGAIN
: NSS_STATUS_UNAVAIL
;
240 /* We have to make sure the file is `closed on exec'. */
243 result
= flags
= fcntl (fileno (ent
->stream
), F_GETFD
, 0);
247 result
= fcntl (fileno (ent
->stream
), F_SETFD
, flags
);
251 /* Something went wrong. Close the stream and return a
253 fclose (ent
->stream
);
255 status
= NSS_STATUS_UNAVAIL
;
260 rewind (ent
->stream
);
262 give_pwd_free (&ent
->pwd
);
269 _nss_compat_setpwent (void)
271 enum nss_status result
;
273 __libc_lock_lock (lock
);
277 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
278 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
281 result
= internal_setpwent (&ext_ent
);
283 __libc_lock_unlock (lock
);
289 static enum nss_status
290 internal_endpwent (ent_t
*ent
)
292 if (ent
->stream
!= NULL
)
294 fclose (ent
->stream
);
299 __internal_endnetgrent (&ent
->netgrdata
);
301 ent
->nis
= ent
->first
= ent
->netgroup
= 0;
303 if (ent
->oldkey
!= NULL
)
310 if (ent
->result
!= NULL
)
312 nis_freeresult (ent
->result
);
316 ent
->blacklist
.current
= 0;
317 if (ent
->blacklist
.data
!= NULL
)
318 ent
->blacklist
.data
[0] = '\0';
320 give_pwd_free (&ent
->pwd
);
322 return NSS_STATUS_SUCCESS
;
326 _nss_compat_endpwent (void)
328 enum nss_status result
;
330 __libc_lock_lock (lock
);
332 result
= internal_endpwent (&ext_ent
);
334 __libc_lock_unlock (lock
);
339 static enum nss_status
340 getpwent_next_nis_netgr (const char *name
, struct passwd
*result
, ent_t
*ent
,
341 char *group
, char *buffer
, size_t buflen
)
343 struct parser_data
*data
= (void *) buffer
;
344 char *ypdomain
, *host
, *user
, *domain
, *outval
, *p
, *p2
;
345 int status
, outvallen
;
348 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
352 give_pwd_free (&ent
->pwd
);
353 return NSS_STATUS_UNAVAIL
;
356 if (ent
->first
== TRUE
)
358 memset (&ent
->netgrdata
, 0, sizeof (struct __netgrent
));
359 __internal_setnetgrent (group
, &ent
->netgrdata
);
368 saved_cursor
= ent
->netgrdata
.cursor
;
369 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
370 &ent
->netgrdata
, buffer
, buflen
);
373 __internal_endnetgrent (&ent
->netgrdata
);
375 give_pwd_free (&ent
->pwd
);
376 return NSS_STATUS_RETURN
;
379 if (user
== NULL
|| user
[0] == '-')
382 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
385 /* If name != NULL, we are called from getpwnam */
387 if (strcmp (user
, name
) != 0)
390 if (yp_match (ypdomain
, "passwd.byname", user
,
391 strlen (user
), &outval
, &outvallen
)
395 p2len
= pwd_need_buflen (&ent
->pwd
);
398 __set_errno (ERANGE
);
399 return NSS_STATUS_TRYAGAIN
;
401 p2
= buffer
+ (buflen
- p2len
);
403 p
= strncpy (buffer
, outval
, buflen
);
407 if ((parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)) == -1)
409 ent
->netgrdata
.cursor
= saved_cursor
;
410 return NSS_STATUS_TRYAGAIN
;
415 /* Store the User in the blacklist for the "+" at the end of
417 blacklist_store_name (result
->pw_name
, ent
);
418 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
423 return NSS_STATUS_SUCCESS
;
426 static enum nss_status
427 getpwent_next_nisplus_netgr (const char *name
, struct passwd
*result
,
428 ent_t
*ent
, char *group
, char *buffer
,
431 char *ypdomain
, *host
, *user
, *domain
, *p2
;
432 int status
, parse_res
;
436 /* Maybe we should use domainname here ? We need the current
437 domainname for the domain field in netgroups */
438 if (yp_get_default_domain (&ypdomain
) != YPERR_SUCCESS
)
442 give_pwd_free (&ent
->pwd
);
443 return NSS_STATUS_UNAVAIL
;
446 if (ent
->first
== TRUE
)
448 bzero (&ent
->netgrdata
, sizeof (struct __netgrent
));
449 __internal_setnetgrent (group
, &ent
->netgrdata
);
457 saved_cursor
= ent
->netgrdata
.cursor
;
458 status
= __internal_getnetgrent_r (&host
, &user
, &domain
,
459 &ent
->netgrdata
, buffer
, buflen
);
462 __internal_endnetgrent (&ent
->netgrdata
);
464 give_pwd_free (&ent
->pwd
);
465 return NSS_STATUS_RETURN
;
468 if (user
== NULL
|| user
[0] == '-')
471 if (domain
!= NULL
&& strcmp (ypdomain
, domain
) != 0)
474 /* If name != NULL, we are called from getpwnam */
476 if (strcmp (user
, name
) != 0)
479 p2len
= pwd_need_buflen (&ent
->pwd
);
482 __set_errno (ERANGE
);
483 return NSS_STATUS_TRYAGAIN
;
485 p2
= buffer
+ (buflen
- p2len
);
488 char buf
[strlen (user
) + 30 + pwdtablelen
];
489 sprintf(buf
, "[name=%s],%s", user
, pwdtable
);
490 nisres
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
492 if (niserr2nss (nisres
->status
) != NSS_STATUS_SUCCESS
)
494 nis_freeresult (nisres
);
497 if ((parse_res
= _nss_nisplus_parse_pwent (nisres
, result
, buffer
,
500 nis_freeresult (nisres
);
501 ent
->netgrdata
.cursor
= saved_cursor
;
502 return NSS_STATUS_TRYAGAIN
;
504 nis_freeresult (nisres
);
508 /* Store the User in the blacklist for the "+" at the end of
510 blacklist_store_name (result
->pw_name
, ent
);
511 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
516 return NSS_STATUS_SUCCESS
;
519 static enum nss_status
520 getpwent_next_nisplus (struct passwd
*result
, ent_t
*ent
, char *buffer
,
527 p2len
= pwd_need_buflen (&ent
->pwd
);
530 __set_errno (ERANGE
);
531 return NSS_STATUS_TRYAGAIN
;
533 p2
= buffer
+ (buflen
- p2len
);
538 nis_result
*saved_res
;
543 saved_res
= ent
->result
;
545 ent
->result
= nis_first_entry(pwdtable
);
546 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
549 give_pwd_free (&ent
->pwd
);
550 return niserr2nss (ent
->result
->status
);
558 res
= nis_next_entry(pwdtable
, &ent
->result
->cookie
);
559 saved_res
= ent
->result
;
562 if (niserr2nss (ent
->result
->status
) != NSS_STATUS_SUCCESS
)
565 nis_freeresult (saved_res
);
566 give_pwd_free (&ent
->pwd
);
567 return niserr2nss (ent
->result
->status
);
570 if ((parse_res
= _nss_nisplus_parse_pwent (ent
->result
, result
, buffer
,
573 nis_freeresult (ent
->result
);
574 ent
->result
= saved_res
;
575 ent
->first
= saved_first
;
576 __set_errno (ERANGE
);
577 return NSS_STATUS_TRYAGAIN
;
582 nis_freeresult (saved_res
);
586 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
587 parse_res
= 0; /* if result->pw_name in blacklist,search next entry */
591 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
593 return NSS_STATUS_SUCCESS
;
596 static enum nss_status
597 getpwent_next_nis (struct passwd
*result
, ent_t
*ent
, char *buffer
,
600 struct parser_data
*data
= (void *) buffer
;
601 char *domain
, *outkey
, *outval
, *p
, *p2
;
602 int outkeylen
, outvallen
, parse_res
;
605 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
608 give_pwd_free (&ent
->pwd
);
609 return NSS_STATUS_UNAVAIL
;
612 p2len
= pwd_need_buflen (&ent
->pwd
);
615 __set_errno (ERANGE
);
616 return NSS_STATUS_TRYAGAIN
;
618 p2
= buffer
+ (buflen
- p2len
);
628 if (yp_first (domain
, "passwd.byname", &outkey
, &outkeylen
,
629 &outval
, &outvallen
) != YPERR_SUCCESS
)
632 give_pwd_free (&ent
->pwd
);
633 return NSS_STATUS_UNAVAIL
;
637 saved_oldkey
= ent
->oldkey
;
638 saved_oldlen
= ent
->oldkeylen
;
639 ent
->oldkey
= outkey
;
640 ent
->oldkeylen
= outkeylen
;
645 if (yp_next (domain
, "passwd.byname", ent
->oldkey
, ent
->oldkeylen
,
646 &outkey
, &outkeylen
, &outval
, &outvallen
)
650 give_pwd_free (&ent
->pwd
);
651 return NSS_STATUS_NOTFOUND
;
655 saved_oldkey
= ent
->oldkey
;
656 saved_oldlen
= ent
->oldkeylen
;
657 ent
->oldkey
= outkey
;
658 ent
->oldkeylen
= outkeylen
;
661 /* Copy the found data to our buffer */
662 p
= strncpy (buffer
, outval
, buflen
);
664 /* ...and free the data. */
669 if ((parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)) == -1)
672 ent
->oldkey
= saved_oldkey
;
673 ent
->oldkeylen
= saved_oldlen
;
674 ent
->first
= saved_first
;
675 __set_errno (ERANGE
);
676 return NSS_STATUS_TRYAGAIN
;
684 in_blacklist (result
->pw_name
, strlen (result
->pw_name
), ent
))
689 copy_pwd_changes (result
, &ent
->pwd
, p2
, p2len
);
691 return NSS_STATUS_SUCCESS
;
694 /* This function handle the +user entrys in /etc/passwd */
695 static enum nss_status
696 getpwnam_plususer (const char *name
, struct passwd
*result
, char *buffer
,
699 struct parser_data
*data
= (void *) buffer
;
705 memset (&pwd
, '\0', sizeof (struct passwd
));
707 copy_pwd_changes (&pwd
, result
, NULL
, 0);
709 plen
= pwd_need_buflen (&pwd
);
712 __set_errno (ERANGE
);
713 return NSS_STATUS_TRYAGAIN
;
715 p
= buffer
+ (buflen
- plen
);
718 if (use_nisplus
) /* Do the NIS+ query here */
721 char buf
[strlen (name
) + 24 + pwdtablelen
];
723 sprintf(buf
, "[name=%s],%s", name
, pwdtable
);
724 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
725 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
727 enum nss_status status
= niserr2nss (res
->status
);
729 nis_freeresult (res
);
732 if ((parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
735 nis_freeresult (res
);
736 __set_errno (ERANGE
);
737 return NSS_STATUS_TRYAGAIN
;
739 nis_freeresult (res
);
743 char *domain
, *outval
, *ptr
;
746 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
747 return NSS_STATUS_TRYAGAIN
;
749 if (yp_match (domain
, "passwd.byname", name
, strlen (name
),
752 return NSS_STATUS_TRYAGAIN
;
753 ptr
= strncpy (buffer
, outval
, buflen
< (size_t) outvallen
?
754 buflen
: (size_t) outvallen
);
755 buffer
[buflen
< (size_t) outvallen
? buflen
: (size_t) outvallen
] = '\0';
757 while (isspace (*ptr
))
759 if ((parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
))
762 __set_errno (ERANGE
);
763 return NSS_STATUS_TRYAGAIN
;
769 copy_pwd_changes (result
, &pwd
, p
, plen
);
770 give_pwd_free (&pwd
);
771 /* We found the entry. */
772 return NSS_STATUS_SUCCESS
;
776 /* Give buffer the old len back */
778 give_pwd_free (&pwd
);
780 return NSS_STATUS_RETURN
;
783 static enum nss_status
784 getpwent_next_file (struct passwd
*result
, ent_t
*ent
,
785 char *buffer
, size_t buflen
)
787 struct parser_data
*data
= (void *) buffer
;
796 fgetpos (ent
->stream
, &pos
);
797 p
= fgets (buffer
, buflen
, ent
->stream
);
799 return NSS_STATUS_NOTFOUND
;
801 /* Terminate the line for any case. */
802 buffer
[buflen
- 1] = '\0';
804 /* Skip leading blanks. */
808 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
809 /* Parse the line. If it is invalid, loop to
810 get the next line of the file to parse. */
811 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)));
815 /* The parser ran out of space. */
816 fsetpos (ent
->stream
, &pos
);
817 __set_errno (ERANGE
);
818 return NSS_STATUS_TRYAGAIN
;
821 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
822 /* This is a real entry. */
826 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
827 && result
->pw_name
[2] != '\0')
830 char *user
, *host
, *domain
;
831 struct __netgrent netgrdata
;
833 bzero (&netgrdata
, sizeof (struct __netgrent
));
834 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
835 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
836 &netgrdata
, buf2
, sizeof (buf2
)))
838 if (user
!= NULL
&& user
[0] != '-')
839 blacklist_store_name (user
, ent
);
841 __internal_endnetgrent (&netgrdata
);
846 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
847 && result
->pw_name
[2] != '\0')
851 ent
->netgroup
= TRUE
;
853 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
856 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
,
860 status
= getpwent_next_nis_netgr (NULL
, result
, ent
,
863 if (status
== NSS_STATUS_RETURN
)
870 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
871 && result
->pw_name
[1] != '@')
873 blacklist_store_name (&result
->pw_name
[1], ent
);
878 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
879 && result
->pw_name
[1] != '@')
881 enum nss_status status
;
883 /* Store the User in the blacklist for the "+" at the end of
885 blacklist_store_name (&result
->pw_name
[1], ent
);
886 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
888 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
891 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
898 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
902 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
905 return getpwent_next_nisplus (result
, ent
, buffer
, buflen
);
907 return getpwent_next_nis (result
, ent
, buffer
, buflen
);
911 return NSS_STATUS_SUCCESS
;
915 static enum nss_status
916 internal_getpwent_r (struct passwd
*pw
, ent_t
*ent
, char *buffer
,
923 /* We are searching members in a netgroup */
924 /* Since this is not the first call, we don't need the group name */
926 status
= getpwent_next_nisplus_netgr (NULL
, pw
, ent
, NULL
, buffer
,
929 status
= getpwent_next_nis_netgr (NULL
, pw
, ent
, NULL
, buffer
, buflen
);
930 if (status
== NSS_STATUS_RETURN
)
931 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
939 return getpwent_next_nisplus (pw
, ent
, buffer
, buflen
);
941 return getpwent_next_nis (pw
, ent
, buffer
, buflen
);
944 return getpwent_next_file (pw
, ent
, buffer
, buflen
);
948 _nss_compat_getpwent_r (struct passwd
*pwd
, char *buffer
, size_t buflen
)
950 enum nss_status status
= NSS_STATUS_SUCCESS
;
952 __libc_lock_lock (lock
);
956 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
957 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
960 /* Be prepared that the setpwent function was not called before. */
961 if (ext_ent
.stream
== NULL
)
962 status
= internal_setpwent (&ext_ent
);
964 if (status
== NSS_STATUS_SUCCESS
)
965 status
= internal_getpwent_r (pwd
, &ext_ent
, buffer
, buflen
);
967 __libc_lock_unlock (lock
);
972 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
973 static enum nss_status
974 internal_getpwnam_r (const char *name
, struct passwd
*result
, ent_t
*ent
,
975 char *buffer
, size_t buflen
)
977 struct parser_data
*data
= (void *) buffer
;
987 fgetpos (ent
->stream
, &pos
);
988 p
= fgets (buffer
, buflen
, ent
->stream
);
991 if (feof (ent
->stream
))
992 return NSS_STATUS_NOTFOUND
;
995 __set_errno (ERANGE
);
996 return NSS_STATUS_TRYAGAIN
;
1000 /* Terminate the line for any case. */
1001 buffer
[buflen
- 1] = '\0';
1003 /* Skip leading blanks. */
1004 while (isspace (*p
))
1007 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1008 /* Parse the line. If it is invalid, loop to
1009 get the next line of the file to parse. */
1010 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)));
1012 if (parse_res
== -1)
1014 /* The parser ran out of space. */
1015 fsetpos (ent
->stream
, &pos
);
1016 __set_errno (ERANGE
);
1017 return NSS_STATUS_TRYAGAIN
;
1020 /* This is a real entry. */
1021 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1023 if (strcmp (result
->pw_name
, name
) == 0)
1024 return NSS_STATUS_SUCCESS
;
1030 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1031 && result
->pw_name
[2] != '\0')
1034 char *user
, *host
, *domain
;
1035 struct __netgrent netgrdata
;
1037 bzero (&netgrdata
, sizeof (struct __netgrent
));
1038 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1039 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
1040 &netgrdata
, buf2
, sizeof (buf2
)))
1042 if (user
!= NULL
&& user
[0] != '-')
1043 if (strcmp (user
, name
) == 0)
1044 return NSS_STATUS_NOTFOUND
;
1046 __internal_endnetgrent (&netgrdata
);
1051 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1052 && result
->pw_name
[2] != '\0')
1054 char buf
[strlen (result
->pw_name
)];
1057 strcpy (buf
, &result
->pw_name
[2]);
1058 ent
->netgroup
= TRUE
;
1060 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1065 status
= getpwent_next_nisplus_netgr (name
, result
, ent
, buf
,
1068 status
= getpwent_next_nis_netgr (name
, result
, ent
, buf
,
1070 if (status
== NSS_STATUS_RETURN
)
1073 if (status
== NSS_STATUS_SUCCESS
&&
1074 strcmp (result
->pw_name
, name
) == 0)
1075 return NSS_STATUS_SUCCESS
;
1076 } while (status
== NSS_STATUS_SUCCESS
);
1081 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1082 && result
->pw_name
[1] != '@')
1084 if (strcmp (&result
->pw_name
[1], name
) == 0)
1085 return NSS_STATUS_NOTFOUND
;
1091 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1092 && result
->pw_name
[1] != '@')
1094 if (strcmp (name
, &result
->pw_name
[1]) == 0)
1096 enum nss_status status
;
1098 status
= getpwnam_plususer (name
, result
, buffer
, buflen
);
1099 if (status
== NSS_STATUS_RETURN
)
1100 /* We couldn't parse the entry */
1101 return NSS_STATUS_NOTFOUND
;
1108 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1110 enum nss_status status
;
1112 status
= getpwnam_plususer (name
, result
, buffer
, buflen
);
1113 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1116 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1117 return NSS_STATUS_NOTFOUND
;
1122 return NSS_STATUS_SUCCESS
;
1126 _nss_compat_getpwnam_r (const char *name
, struct passwd
*pwd
,
1127 char *buffer
, size_t buflen
)
1129 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1130 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1131 enum nss_status status
;
1133 if (name
[0] == '-' || name
[0] == '+')
1134 return NSS_STATUS_NOTFOUND
;
1136 __libc_lock_lock (lock
);
1140 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1141 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1144 __libc_lock_unlock (lock
);
1146 status
= internal_setpwent (&ent
);
1147 if (status
!= NSS_STATUS_SUCCESS
)
1150 status
= internal_getpwnam_r (name
, pwd
, &ent
, buffer
, buflen
);
1152 internal_endpwent (&ent
);
1157 /* This function handle the + entry in /etc/passwd for getpwuid */
1158 static enum nss_status
1159 getpwuid_plususer (uid_t uid
, struct passwd
*result
, char *buffer
,
1162 struct parser_data
*data
= (void *) buffer
;
1168 memset (&pwd
, '\0', sizeof (struct passwd
));
1170 copy_pwd_changes (&pwd
, result
, NULL
, 0);
1172 plen
= pwd_need_buflen (&pwd
);
1175 __set_errno (ERANGE
);
1176 return NSS_STATUS_TRYAGAIN
;
1178 p
= buffer
+ (buflen
- plen
);
1181 if (use_nisplus
) /* Do the NIS+ query here */
1184 char buf
[1024 + pwdtablelen
];
1186 sprintf(buf
, "[uid=%d],%s", uid
, pwdtable
);
1187 res
= nis_list(buf
, FOLLOW_PATH
| FOLLOW_LINKS
, NULL
, NULL
);
1188 if (niserr2nss (res
->status
) != NSS_STATUS_SUCCESS
)
1190 enum nss_status status
= niserr2nss (res
->status
);
1192 nis_freeresult (res
);
1195 if ((parse_res
= _nss_nisplus_parse_pwent (res
, result
, buffer
,
1198 nis_freeresult (res
);
1199 __set_errno (ERANGE
);
1200 return NSS_STATUS_TRYAGAIN
;
1202 nis_freeresult (res
);
1207 char *domain
, *outval
, *ptr
;
1210 if (yp_get_default_domain (&domain
) != YPERR_SUCCESS
)
1211 return NSS_STATUS_TRYAGAIN
;
1213 sprintf (buf
, "%d", uid
);
1214 if (yp_match (domain
, "passwd.byuid", buf
, strlen (buf
),
1215 &outval
, &outvallen
)
1217 return NSS_STATUS_TRYAGAIN
;
1218 ptr
= strncpy (buffer
, outval
, buflen
< (size_t) outvallen
?
1219 buflen
: (size_t) outvallen
);
1220 buffer
[buflen
< (size_t) outvallen
? buflen
: (size_t) outvallen
] = '\0';
1222 while (isspace (*ptr
))
1224 if ((parse_res
= _nss_files_parse_pwent (ptr
, result
, data
, buflen
))
1227 __set_errno (ERANGE
);
1228 return NSS_STATUS_TRYAGAIN
;
1234 copy_pwd_changes (result
, &pwd
, p
, plen
);
1235 give_pwd_free (&pwd
);
1236 /* We found the entry. */
1237 return NSS_STATUS_SUCCESS
;
1241 /* Give buffer the old len back */
1243 give_pwd_free (&pwd
);
1245 return NSS_STATUS_RETURN
;
1248 /* Searches in /etc/passwd and the NIS/NIS+ map for a special user id */
1249 static enum nss_status
1250 internal_getpwuid_r (uid_t uid
, struct passwd
*result
, ent_t
*ent
,
1251 char *buffer
, size_t buflen
)
1253 struct parser_data
*data
= (void *) buffer
;
1263 fgetpos (ent
->stream
, &pos
);
1264 p
= fgets (buffer
, buflen
, ent
->stream
);
1266 return NSS_STATUS_NOTFOUND
;
1268 /* Terminate the line for any case. */
1269 buffer
[buflen
- 1] = '\0';
1271 /* Skip leading blanks. */
1272 while (isspace (*p
))
1275 while (*p
== '\0' || *p
== '#' || /* Ignore empty and comment lines. */
1276 /* Parse the line. If it is invalid, loop to
1277 get the next line of the file to parse. */
1278 !(parse_res
= _nss_files_parse_pwent (p
, result
, data
, buflen
)));
1280 if (parse_res
== -1)
1282 /* The parser ran out of space. */
1283 fsetpos (ent
->stream
, &pos
);
1284 __set_errno (ERANGE
);
1285 return NSS_STATUS_TRYAGAIN
;
1288 /* This is a real entry. */
1289 if (result
->pw_name
[0] != '+' && result
->pw_name
[0] != '-')
1291 if (result
->pw_uid
== uid
)
1292 return NSS_STATUS_SUCCESS
;
1298 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] == '@'
1299 && result
->pw_name
[2] != '\0')
1302 char *user
, *host
, *domain
;
1303 struct __netgrent netgrdata
;
1305 bzero (&netgrdata
, sizeof (struct __netgrent
));
1306 __internal_setnetgrent (&result
->pw_name
[2], &netgrdata
);
1307 while (__internal_getnetgrent_r (&host
, &user
, &domain
,
1308 &netgrdata
, buf2
, sizeof (buf2
)))
1310 if (user
!= NULL
&& user
[0] != '-')
1311 blacklist_store_name (user
, ent
);
1313 __internal_endnetgrent (&netgrdata
);
1318 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '@'
1319 && result
->pw_name
[2] != '\0')
1321 char buf
[strlen (result
->pw_name
)];
1324 strcpy (buf
, &result
->pw_name
[2]);
1325 ent
->netgroup
= TRUE
;
1327 copy_pwd_changes (&ent
->pwd
, result
, NULL
, 0);
1332 status
= getpwent_next_nisplus_netgr (NULL
, result
, ent
, buf
,
1335 status
= getpwent_next_nis_netgr (NULL
, result
, ent
, buf
,
1337 if (status
== NSS_STATUS_RETURN
)
1340 if (status
== NSS_STATUS_SUCCESS
&& uid
== result
->pw_uid
)
1341 return NSS_STATUS_SUCCESS
;
1342 } while (status
== NSS_STATUS_SUCCESS
);
1347 if (result
->pw_name
[0] == '-' && result
->pw_name
[1] != '\0'
1348 && result
->pw_name
[1] != '@')
1350 blacklist_store_name (&result
->pw_name
[1], ent
);
1355 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] != '\0'
1356 && result
->pw_name
[1] != '@')
1358 enum nss_status status
;
1360 /* Store the User in the blacklist for the "+" at the end of
1362 blacklist_store_name (&result
->pw_name
[1], ent
);
1363 status
= getpwnam_plususer (&result
->pw_name
[1], result
, buffer
,
1365 if (status
== NSS_STATUS_SUCCESS
&& result
->pw_uid
== uid
)
1372 if (result
->pw_name
[0] == '+' && result
->pw_name
[1] == '\0')
1374 enum nss_status status
;
1376 status
= getpwuid_plususer (uid
, result
, buffer
, buflen
);
1377 if (status
== NSS_STATUS_SUCCESS
) /* We found the entry. */
1380 if (status
== NSS_STATUS_RETURN
) /* We couldn't parse the entry */
1381 return NSS_STATUS_NOTFOUND
;
1386 return NSS_STATUS_SUCCESS
;
1390 _nss_compat_getpwuid_r (uid_t uid
, struct passwd
*pwd
,
1391 char *buffer
, size_t buflen
)
1393 ent_t ent
= {0, 0, 0, NULL
, 0, NULL
, NULL
, {NULL
, 0, 0},
1394 {NULL
, NULL
, 0, 0, NULL
, NULL
, NULL
}};
1395 enum nss_status status
;
1397 __libc_lock_lock (lock
);
1401 __nss_database_lookup ("passwd_compat", NULL
, "nis", &ni
);
1402 use_nisplus
= (strcmp (ni
->name
, "nisplus") == 0);
1405 __libc_lock_unlock (lock
);
1407 status
= internal_setpwent (&ent
);
1408 if (status
!= NSS_STATUS_SUCCESS
)
1411 status
= internal_getpwuid_r (uid
, pwd
, &ent
, buffer
, buflen
);
1413 internal_endpwent (&ent
);
1419 /* Support routines for remembering -@netgroup and -user entries.
1420 The names are stored in a single string with `|' as separator. */
1422 blacklist_store_name (const char *name
, ent_t
*ent
)
1424 int namelen
= strlen (name
);
1427 /* first call, setup cache */
1428 if (ent
->blacklist
.size
== 0)
1430 ent
->blacklist
.size
= MAX (BLACKLIST_INITIAL_SIZE
, 2 * namelen
);
1431 ent
->blacklist
.data
= malloc (ent
->blacklist
.size
);
1432 if (ent
->blacklist
.data
== NULL
)
1434 ent
->blacklist
.data
[0] = '|';
1435 ent
->blacklist
.data
[1] = '\0';
1436 ent
->blacklist
.current
= 1;
1440 if (in_blacklist (name
, namelen
, ent
))
1441 return; /* no duplicates */
1443 if (ent
->blacklist
.current
+ namelen
+ 1 >= ent
->blacklist
.size
)
1445 ent
->blacklist
.size
+= MAX (BLACKLIST_INCREMENT
, 2 * namelen
);
1446 tmp
= realloc (ent
->blacklist
.data
, ent
->blacklist
.size
);
1449 free (ent
->blacklist
.data
);
1450 ent
->blacklist
.size
= 0;
1453 ent
->blacklist
.data
= tmp
;
1457 tmp
= stpcpy (ent
->blacklist
.data
+ ent
->blacklist
.current
, name
);
1460 ent
->blacklist
.current
+= namelen
+ 1;
1465 /* returns TRUE if ent->blacklist contains name, else FALSE */
1467 in_blacklist (const char *name
, int namelen
, ent_t
*ent
)
1469 char buf
[namelen
+ 3];
1472 if (ent
->blacklist
.data
== NULL
)
1476 cp
= stpcpy (&buf
[1], name
);
1479 return strstr (ent
->blacklist
.data
, buf
) != NULL
;
This page took 0.111194 seconds and 6 git commands to generate.