2 Unix SMB/CIFS implementation.
4 Windows NT Domain nsswitch module
6 Copyright (C) Tim Potter 2000
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "winbind_client.h"
29 static pthread_mutex_t winbind_nss_mutex
= PTHREAD_MUTEX_INITIALIZER
;
32 /* Maximum number of users to pass back over the unix domain socket
33 per call. This is not a static limit on the total number of users
34 or groups returned in total. */
36 #define MAX_GETPWENT_USERS 250
37 #define MAX_GETGRENT_USERS 250
39 /*************************************************************************
40 ************************************************************************/
43 static const char *nss_err_str(NSS_STATUS ret
)
46 case NSS_STATUS_TRYAGAIN
:
47 return "NSS_STATUS_TRYAGAIN";
48 case NSS_STATUS_SUCCESS
:
49 return "NSS_STATUS_SUCCESS";
50 case NSS_STATUS_NOTFOUND
:
51 return "NSS_STATUS_NOTFOUND";
52 case NSS_STATUS_UNAVAIL
:
53 return "NSS_STATUS_UNAVAIL";
54 #ifdef NSS_STATUS_RETURN
55 case NSS_STATUS_RETURN
:
56 return "NSS_STATUS_RETURN";
59 return "UNKNOWN RETURN CODE!!!!!!!";
64 /* Prototypes from wb_common.c */
66 /* Allocate some space from the nss static buffer. The buffer and buflen
67 are the pointers passed in by the C library to the _nss_ntdom_*
70 static char *get_static(char **buffer
, size_t *buflen
, size_t len
)
74 /* Error check. We return false if things aren't set up right, or
75 there isn't enough buffer space left. */
77 if ((buffer
== NULL
) || (buflen
== NULL
) || (*buflen
< len
)) {
81 /* Return an index into the static buffer */
90 /* I've copied the strtok() replacement function next_token_Xalloc() from
91 lib/util_str.c as I really don't want to have to link in any other
92 objects if I can possibly avoid it. */
94 static bool next_token_alloc(const char **ptr
,
111 /* default to simple separators */
116 /* find the first non sep char */
117 while (*s
&& strchr(sep
,*s
)) {
126 /* When restarting we need to go from here. */
129 /* Work out the length needed. */
130 for (quoted
= false; *s
&&
131 (quoted
|| !strchr(sep
,*s
)); s
++) {
139 /* We started with len = 1 so we have space for the nul. */
140 *pp_buff
= (char *)malloc(len
);
145 /* copy over the token */
148 for (quoted
= false; *s
&&
149 (quoted
|| !strchr(sep
,*s
)); s
++) {
157 *ptr
= (*s
) ? s
+1 : s
;
163 /* Fill a pwent structure from a winbindd_response structure. We use
164 the static data passed to us by libc to put strings and stuff in.
165 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
167 static NSS_STATUS
fill_pwent(struct passwd
*result
,
168 struct winbindd_pw
*pw
,
169 char **buffer
, size_t *buflen
)
174 len
= strlen(pw
->pw_name
) + 1;
176 if ((result
->pw_name
=
177 get_static(buffer
, buflen
, len
)) == NULL
) {
181 return NSS_STATUS_TRYAGAIN
;
184 memcpy(result
->pw_name
, pw
->pw_name
, len
);
187 len
= strlen(pw
->pw_passwd
) + 1;
189 if ((result
->pw_passwd
=
190 get_static(buffer
, buflen
, len
)) == NULL
) {
194 return NSS_STATUS_TRYAGAIN
;
197 memcpy(result
->pw_passwd
, pw
->pw_passwd
, len
);
201 result
->pw_uid
= pw
->pw_uid
;
202 result
->pw_gid
= pw
->pw_gid
;
205 len
= strlen(pw
->pw_gecos
) + 1;
207 if ((result
->pw_gecos
=
208 get_static(buffer
, buflen
, len
)) == NULL
) {
212 return NSS_STATUS_TRYAGAIN
;
215 memcpy(result
->pw_gecos
, pw
->pw_gecos
, len
);
218 len
= strlen(pw
->pw_dir
) + 1;
220 if ((result
->pw_dir
=
221 get_static(buffer
, buflen
, len
)) == NULL
) {
225 return NSS_STATUS_TRYAGAIN
;
228 memcpy(result
->pw_dir
, pw
->pw_dir
, len
);
231 len
= strlen(pw
->pw_shell
) + 1;
233 if ((result
->pw_shell
=
234 get_static(buffer
, buflen
, len
)) == NULL
) {
238 return NSS_STATUS_TRYAGAIN
;
241 memcpy(result
->pw_shell
, pw
->pw_shell
, len
);
243 /* The struct passwd for Solaris has some extra fields which must
244 be initialised or nscd crashes. */
246 #ifdef HAVE_PASSWD_PW_COMMENT
247 result
->pw_comment
= "";
250 #ifdef HAVE_PASSWD_PW_AGE
254 return NSS_STATUS_SUCCESS
;
257 /* Fill a grent structure from a winbindd_response structure. We use
258 the static data passed to us by libc to put strings and stuff in.
259 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
261 static NSS_STATUS
fill_grent(struct group
*result
, struct winbindd_gr
*gr
,
262 const char *gr_mem
, char **buffer
, size_t *buflen
)
270 len
= strlen(gr
->gr_name
) + 1;
272 if ((result
->gr_name
=
273 get_static(buffer
, buflen
, len
)) == NULL
) {
277 return NSS_STATUS_TRYAGAIN
;
280 memcpy(result
->gr_name
, gr
->gr_name
, len
);
283 len
= strlen(gr
->gr_passwd
) + 1;
285 if ((result
->gr_passwd
=
286 get_static(buffer
, buflen
, len
)) == NULL
) {
289 return NSS_STATUS_TRYAGAIN
;
292 memcpy(result
->gr_passwd
, gr
->gr_passwd
, len
);
296 result
->gr_gid
= gr
->gr_gid
;
298 /* Group membership */
304 /* this next value is a pointer to a pointer so let's align it */
306 /* Calculate number of extra bytes needed to align on pointer size boundry */
307 if ((i
= (unsigned long)(*buffer
) % sizeof(char*)) != 0)
308 i
= sizeof(char*) - i
;
310 if ((tst
= get_static(buffer
, buflen
, ((gr
->num_gr_mem
+ 1) *
311 sizeof(char *)+i
))) == NULL
) {
315 return NSS_STATUS_TRYAGAIN
;
317 result
->gr_mem
= (char **)(tst
+ i
);
319 if (gr
->num_gr_mem
== 0) {
323 *(result
->gr_mem
) = NULL
;
324 return NSS_STATUS_SUCCESS
;
327 /* Start looking at extra data */
331 while(next_token_alloc((const char **)&gr_mem
, &name
, ",")) {
332 /* Allocate space for member */
333 len
= strlen(name
) + 1;
335 if (((result
->gr_mem
)[i
] =
336 get_static(buffer
, buflen
, len
)) == NULL
) {
339 return NSS_STATUS_TRYAGAIN
;
341 memcpy((result
->gr_mem
)[i
], name
, len
);
348 (result
->gr_mem
)[i
] = NULL
;
350 return NSS_STATUS_SUCCESS
;
357 static struct winbindd_response getpwent_response
;
359 static int ndx_pw_cache
; /* Current index into pwd cache */
360 static int num_pw_cache
; /* Current size of pwd cache */
362 /* Rewind "file pointer" to start of ntdom password database */
366 _nss_winbind_setpwent(void)
370 fprintf(stderr
, "[%5d]: setpwent\n", getpid());
374 pthread_mutex_lock(&winbind_nss_mutex
);
377 if (num_pw_cache
> 0) {
378 ndx_pw_cache
= num_pw_cache
= 0;
379 winbindd_free_response(&getpwent_response
);
382 winbind_set_client_name("nss_winbind");
383 ret
= winbindd_request_response(NULL
, WINBINDD_SETPWENT
, NULL
, NULL
);
385 fprintf(stderr
, "[%5d]: setpwent returns %s (%d)\n", getpid(),
386 nss_err_str(ret
), ret
);
390 pthread_mutex_unlock(&winbind_nss_mutex
);
395 /* Close ntdom password database "file pointer" */
399 _nss_winbind_endpwent(void)
403 fprintf(stderr
, "[%5d]: endpwent\n", getpid());
407 pthread_mutex_lock(&winbind_nss_mutex
);
410 if (num_pw_cache
> 0) {
411 ndx_pw_cache
= num_pw_cache
= 0;
412 winbindd_free_response(&getpwent_response
);
415 winbind_set_client_name("nss_winbind");
416 ret
= winbindd_request_response(NULL
, WINBINDD_ENDPWENT
, NULL
, NULL
);
418 fprintf(stderr
, "[%5d]: endpwent returns %s (%d)\n", getpid(),
419 nss_err_str(ret
), ret
);
423 pthread_mutex_unlock(&winbind_nss_mutex
);
429 /* Fetch the next password entry from ntdom password database */
433 _nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
434 size_t buflen
, int *errnop
)
437 struct winbindd_request request
;
438 static int called_again
;
441 fprintf(stderr
, "[%5d]: getpwent\n", getpid());
445 pthread_mutex_lock(&winbind_nss_mutex
);
448 /* Return an entry from the cache if we have one, or if we are
449 called again because we exceeded our static buffer. */
451 if ((ndx_pw_cache
< num_pw_cache
) || called_again
) {
455 /* Else call winbindd to get a bunch of entries */
457 if (num_pw_cache
> 0) {
458 winbindd_free_response(&getpwent_response
);
461 ZERO_STRUCT(request
);
462 ZERO_STRUCT(getpwent_response
);
464 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
466 winbind_set_client_name("nss_winbind");
467 ret
= winbindd_request_response(NULL
, WINBINDD_GETPWENT
, &request
,
470 if (ret
== NSS_STATUS_SUCCESS
) {
471 struct winbindd_pw
*pw_cache
;
476 num_pw_cache
= getpwent_response
.data
.num_entries
;
478 /* Return a result */
482 pw_cache
= (struct winbindd_pw
*)
483 getpwent_response
.extra_data
.data
;
485 /* Check data is valid */
487 if (pw_cache
== NULL
) {
488 ret
= NSS_STATUS_NOTFOUND
;
492 ret
= fill_pwent(result
, &pw_cache
[ndx_pw_cache
],
495 /* Out of memory - try again */
497 if (ret
== NSS_STATUS_TRYAGAIN
) {
499 *errnop
= errno
= ERANGE
;
504 called_again
= false;
507 /* If we've finished with this lot of results free cache */
509 if (ndx_pw_cache
== num_pw_cache
) {
510 ndx_pw_cache
= num_pw_cache
= 0;
511 winbindd_free_response(&getpwent_response
);
516 fprintf(stderr
, "[%5d]: getpwent returns %s (%d)\n", getpid(),
517 nss_err_str(ret
), ret
);
521 pthread_mutex_unlock(&winbind_nss_mutex
);
526 /* Return passwd struct from uid */
530 _nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
, char *buffer
,
531 size_t buflen
, int *errnop
)
534 static struct winbindd_response response
;
535 struct winbindd_request request
;
536 static int keep_response
;
539 fprintf(stderr
, "[%5d]: getpwuid_r %d\n", getpid(), (unsigned int)uid
);
543 pthread_mutex_lock(&winbind_nss_mutex
);
546 /* If our static buffer needs to be expanded we are called again */
547 if (!keep_response
|| uid
!= response
.data
.pw
.pw_uid
) {
549 /* Call for the first time */
551 response
= (struct winbindd_response
) {
554 request
= (struct winbindd_request
) {
555 .wb_flags
= WBFLAG_FROM_NSS
,
561 winbind_set_client_name("nss_winbind");
562 ret
= winbindd_request_response(NULL
, WINBINDD_GETPWUID
, &request
, &response
);
564 if (ret
== NSS_STATUS_SUCCESS
) {
565 ret
= fill_pwent(result
, &response
.data
.pw
,
568 if (ret
== NSS_STATUS_TRYAGAIN
) {
569 keep_response
= true;
570 *errnop
= errno
= ERANGE
;
577 /* We've been called again */
579 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
581 if (ret
== NSS_STATUS_TRYAGAIN
) {
582 *errnop
= errno
= ERANGE
;
586 keep_response
= false;
590 winbindd_free_response(&response
);
595 fprintf(stderr
, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
596 (unsigned int)uid
, nss_err_str(ret
), ret
);
600 pthread_mutex_unlock(&winbind_nss_mutex
);
606 /* Return passwd struct from username */
609 _nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
, char *buffer
,
610 size_t buflen
, int *errnop
)
613 static struct winbindd_response response
;
614 struct winbindd_request request
;
615 static int keep_response
;
618 fprintf(stderr
, "[%5d]: getpwnam_r %s\n", getpid(), name
);
622 pthread_mutex_lock(&winbind_nss_mutex
);
625 /* If our static buffer needs to be expanded we are called again */
627 if (!keep_response
|| strcmp(name
,response
.data
.pw
.pw_name
) != 0) {
629 /* Call for the first time */
631 response
= (struct winbindd_response
) {
634 request
= (struct winbindd_request
) {
635 .wb_flags
= WBFLAG_FROM_NSS
,
638 strncpy(request
.data
.username
, name
,
639 sizeof(request
.data
.username
) - 1);
640 request
.data
.username
641 [sizeof(request
.data
.username
) - 1] = '\0';
643 winbind_set_client_name("nss_winbind");
644 ret
= winbindd_request_response(NULL
, WINBINDD_GETPWNAM
, &request
, &response
);
646 if (ret
== NSS_STATUS_SUCCESS
) {
647 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
,
650 if (ret
== NSS_STATUS_TRYAGAIN
) {
651 keep_response
= true;
652 *errnop
= errno
= ERANGE
;
659 /* We've been called again */
661 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
663 if (ret
== NSS_STATUS_TRYAGAIN
) {
664 keep_response
= true;
665 *errnop
= errno
= ERANGE
;
669 keep_response
= false;
673 winbindd_free_response(&response
);
676 fprintf(stderr
, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
677 name
, nss_err_str(ret
), ret
);
681 pthread_mutex_unlock(&winbind_nss_mutex
);
688 * NSS group functions
691 static struct winbindd_response getgrent_response
;
693 static int ndx_gr_cache
; /* Current index into grp cache */
694 static int num_gr_cache
; /* Current size of grp cache */
696 /* Rewind "file pointer" to start of ntdom group database */
700 _nss_winbind_setgrent(void)
704 fprintf(stderr
, "[%5d]: setgrent\n", getpid());
708 pthread_mutex_lock(&winbind_nss_mutex
);
711 if (num_gr_cache
> 0) {
712 ndx_gr_cache
= num_gr_cache
= 0;
713 winbindd_free_response(&getgrent_response
);
716 winbind_set_client_name("nss_winbind");
717 ret
= winbindd_request_response(NULL
, WINBINDD_SETGRENT
, NULL
, NULL
);
719 fprintf(stderr
, "[%5d]: setgrent returns %s (%d)\n", getpid(),
720 nss_err_str(ret
), ret
);
724 pthread_mutex_unlock(&winbind_nss_mutex
);
730 /* Close "file pointer" for ntdom group database */
734 _nss_winbind_endgrent(void)
738 fprintf(stderr
, "[%5d]: endgrent\n", getpid());
742 pthread_mutex_lock(&winbind_nss_mutex
);
745 if (num_gr_cache
> 0) {
746 ndx_gr_cache
= num_gr_cache
= 0;
747 winbindd_free_response(&getgrent_response
);
750 winbind_set_client_name("nss_winbind");
751 ret
= winbindd_request_response(NULL
, WINBINDD_ENDGRENT
, NULL
, NULL
);
753 fprintf(stderr
, "[%5d]: endgrent returns %s (%d)\n", getpid(),
754 nss_err_str(ret
), ret
);
758 pthread_mutex_unlock(&winbind_nss_mutex
);
764 /* Get next entry from ntdom group database */
767 winbind_getgrent(enum winbindd_cmd cmd
,
768 struct group
*result
,
769 char *buffer
, size_t buflen
, int *errnop
)
772 static struct winbindd_request request
;
773 static int called_again
;
777 fprintf(stderr
, "[%5d]: getgrent\n", getpid());
781 pthread_mutex_lock(&winbind_nss_mutex
);
784 /* Return an entry from the cache if we have one, or if we are
785 called again because we exceeded our static buffer. */
787 if ((ndx_gr_cache
< num_gr_cache
) || called_again
) {
791 /* Else call winbindd to get a bunch of entries */
793 if (num_gr_cache
> 0) {
794 winbindd_free_response(&getgrent_response
);
797 ZERO_STRUCT(request
);
798 ZERO_STRUCT(getgrent_response
);
800 request
.data
.num_entries
= MAX_GETGRENT_USERS
;
802 winbind_set_client_name("nss_winbind");
803 ret
= winbindd_request_response(NULL
, cmd
, &request
,
806 if (ret
== NSS_STATUS_SUCCESS
) {
807 struct winbindd_gr
*gr_cache
;
813 num_gr_cache
= getgrent_response
.data
.num_entries
;
815 /* Return a result */
819 gr_cache
= (struct winbindd_gr
*)
820 getgrent_response
.extra_data
.data
;
822 /* Check data is valid */
824 if (gr_cache
== NULL
) {
825 ret
= NSS_STATUS_NOTFOUND
;
829 /* Fill group membership. The offset into the extra data
830 for the group membership is the reported offset plus the
831 size of all the winbindd_gr records returned. */
833 mem_ofs
= gr_cache
[ndx_gr_cache
].gr_mem_ofs
+
834 num_gr_cache
* sizeof(struct winbindd_gr
);
836 ret
= fill_grent(result
, &gr_cache
[ndx_gr_cache
],
837 ((char *)getgrent_response
.extra_data
.data
)+mem_ofs
,
840 /* Out of memory - try again */
842 if (ret
== NSS_STATUS_TRYAGAIN
) {
844 *errnop
= errno
= ERANGE
;
849 called_again
= false;
852 /* If we've finished with this lot of results free cache */
854 if (ndx_gr_cache
== num_gr_cache
) {
855 ndx_gr_cache
= num_gr_cache
= 0;
856 winbindd_free_response(&getgrent_response
);
861 fprintf(stderr
, "[%5d]: getgrent returns %s (%d)\n", getpid(),
862 nss_err_str(ret
), ret
);
866 pthread_mutex_unlock(&winbind_nss_mutex
);
875 _nss_winbind_getgrent_r(struct group
*result
,
876 char *buffer
, size_t buflen
, int *errnop
)
878 return winbind_getgrent(WINBINDD_GETGRENT
, result
, buffer
, buflen
, errnop
);
883 _nss_winbind_getgrlst_r(struct group
*result
,
884 char *buffer
, size_t buflen
, int *errnop
)
886 return winbind_getgrent(WINBINDD_GETGRLST
, result
, buffer
, buflen
, errnop
);
889 /* Return group struct from group name */
893 _nss_winbind_getgrnam_r(const char *name
,
894 struct group
*result
, char *buffer
,
895 size_t buflen
, int *errnop
)
898 static struct winbindd_response response
;
899 struct winbindd_request request
;
900 static int keep_response
;
903 fprintf(stderr
, "[%5d]: getgrnam %s\n", getpid(), name
);
907 pthread_mutex_lock(&winbind_nss_mutex
);
910 /* If our static buffer needs to be expanded we are called again */
911 /* Or if the stored response group name differs from the request. */
913 if (!keep_response
|| strcmp(name
,response
.data
.gr
.gr_name
) != 0) {
915 /* Call for the first time */
917 response
= (struct winbindd_response
) {
920 request
= (struct winbindd_request
) {
921 .wb_flags
= WBFLAG_FROM_NSS
,
924 strncpy(request
.data
.groupname
, name
,
925 sizeof(request
.data
.groupname
));
926 request
.data
.groupname
927 [sizeof(request
.data
.groupname
) - 1] = '\0';
929 winbind_set_client_name("nss_winbind");
930 ret
= winbindd_request_response(NULL
, WINBINDD_GETGRNAM
,
931 &request
, &response
);
933 if (ret
== NSS_STATUS_SUCCESS
) {
934 ret
= fill_grent(result
, &response
.data
.gr
,
935 (char *)response
.extra_data
.data
,
938 if (ret
== NSS_STATUS_TRYAGAIN
) {
939 keep_response
= true;
940 *errnop
= errno
= ERANGE
;
947 /* We've been called again */
949 ret
= fill_grent(result
, &response
.data
.gr
,
950 (char *)response
.extra_data
.data
, &buffer
,
953 if (ret
== NSS_STATUS_TRYAGAIN
) {
954 keep_response
= true;
955 *errnop
= errno
= ERANGE
;
959 keep_response
= false;
963 winbindd_free_response(&response
);
966 fprintf(stderr
, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
967 name
, nss_err_str(ret
), ret
);
971 pthread_mutex_unlock(&winbind_nss_mutex
);
977 /* Return group struct from gid */
981 _nss_winbind_getgrgid_r(gid_t gid
,
982 struct group
*result
, char *buffer
,
983 size_t buflen
, int *errnop
)
986 static struct winbindd_response response
;
987 struct winbindd_request request
;
988 static int keep_response
;
991 fprintf(stderr
, "[%5d]: getgrgid %d\n", getpid(), gid
);
995 pthread_mutex_lock(&winbind_nss_mutex
);
998 /* If our static buffer needs to be expanded we are called again */
999 /* Or if the stored response group name differs from the request. */
1001 if (!keep_response
|| gid
!= response
.data
.gr
.gr_gid
) {
1003 /* Call for the first time */
1005 response
= (struct winbindd_response
) {
1008 request
= (struct winbindd_request
) {
1009 .wb_flags
= WBFLAG_FROM_NSS
,
1013 request
.data
.gid
= gid
;
1015 winbind_set_client_name("nss_winbind");
1016 ret
= winbindd_request_response(NULL
, WINBINDD_GETGRGID
,
1017 &request
, &response
);
1019 if (ret
== NSS_STATUS_SUCCESS
) {
1021 ret
= fill_grent(result
, &response
.data
.gr
,
1022 (char *)response
.extra_data
.data
,
1025 if (ret
== NSS_STATUS_TRYAGAIN
) {
1026 keep_response
= true;
1027 *errnop
= errno
= ERANGE
;
1034 /* We've been called again */
1036 ret
= fill_grent(result
, &response
.data
.gr
,
1037 (char *)response
.extra_data
.data
, &buffer
,
1040 if (ret
== NSS_STATUS_TRYAGAIN
) {
1041 keep_response
= true;
1042 *errnop
= errno
= ERANGE
;
1046 keep_response
= false;
1050 winbindd_free_response(&response
);
1053 fprintf(stderr
, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
1054 (unsigned int)gid
, nss_err_str(ret
), ret
);
1058 pthread_mutex_unlock(&winbind_nss_mutex
);
1063 /* Initialise supplementary groups */
1067 _nss_winbind_initgroups_dyn(const char *user
, gid_t group
, long int *start
,
1068 long int *size
, gid_t
**groups
, long int limit
,
1072 struct winbindd_request request
;
1073 struct winbindd_response response
;
1077 fprintf(stderr
, "[%5d]: initgroups %s (%d)\n", getpid(),
1082 pthread_mutex_lock(&winbind_nss_mutex
);
1085 ZERO_STRUCT(request
);
1086 ZERO_STRUCT(response
);
1088 strncpy(request
.data
.username
, user
,
1089 sizeof(request
.data
.username
) - 1);
1091 winbind_set_client_name("nss_winbind");
1092 ret
= winbindd_request_response(NULL
, WINBINDD_GETGROUPS
,
1093 &request
, &response
);
1095 if (ret
== NSS_STATUS_SUCCESS
) {
1096 int num_gids
= response
.data
.num_entries
;
1097 gid_t
*gid_list
= (gid_t
*)response
.extra_data
.data
;
1100 fprintf(stderr
, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
1101 "and %d gids\n", getpid(),
1104 if (gid_list
== NULL
) {
1105 ret
= NSS_STATUS_NOTFOUND
;
1109 /* Copy group list to client */
1111 for (i
= 0; i
< num_gids
; i
++) {
1114 fprintf(stderr
, "[%5d]: initgroups %s (%d): "
1115 "processing gid %d \n", getpid(),
1116 user
, group
, gid_list
[i
]);
1119 /* Skip primary group */
1121 if (gid_list
[i
] == group
) {
1125 /* Skip groups without a mapping */
1126 if (gid_list
[i
] == (uid_t
)-1) {
1130 /* Filled buffer ? If so, resize. */
1132 if (*start
== *size
) {
1136 newsize
= 2 * (*size
);
1138 if (*size
== limit
) {
1141 if (newsize
> limit
) {
1146 newgroups
= (gid_t
*)
1148 newsize
* sizeof(**groups
));
1151 ret
= NSS_STATUS_NOTFOUND
;
1154 *groups
= newgroups
;
1160 (*groups
)[*start
] = gid_list
[i
];
1165 /* Back to your regularly scheduled programming */
1169 fprintf(stderr
, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
1170 user
, nss_err_str(ret
), ret
);
1174 pthread_mutex_unlock(&winbind_nss_mutex
);