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 Library 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 Library General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "winbind_client.h"
24 /* Maximum number of users to pass back over the unix domain socket
25 per call. This is not a static limit on the total number of users
26 or groups returned in total. */
28 #define MAX_GETPWENT_USERS 250
29 #define MAX_GETGRENT_USERS 250
31 NSS_STATUS
_nss_winbind_setpwent(void);
32 NSS_STATUS
_nss_winbind_endpwent(void);
33 NSS_STATUS
_nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
34 size_t buflen
, int *errnop
);
35 NSS_STATUS
_nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
,
36 char *buffer
, size_t buflen
, int *errnop
);
37 NSS_STATUS
_nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
,
38 char *buffer
, size_t buflen
, int *errnop
);
39 NSS_STATUS
_nss_winbind_setgrent(void);
40 NSS_STATUS
_nss_winbind_endgrent(void);
41 NSS_STATUS
_nss_winbind_getgrent_r(struct group
*result
, char *buffer
,
42 size_t buflen
, int *errnop
);
43 NSS_STATUS
_nss_winbind_getgrlst_r(struct group
*result
, char *buffer
,
44 size_t buflen
, int *errnop
);
45 NSS_STATUS
_nss_winbind_getgrnam_r(const char *name
, struct group
*result
,
46 char *buffer
, size_t buflen
, int *errnop
);
47 NSS_STATUS
_nss_winbind_getgrgid_r(gid_t gid
, struct group
*result
, char *buffer
,
48 size_t buflen
, int *errnop
);
49 NSS_STATUS
_nss_winbind_initgroups_dyn(char *user
, gid_t group
, long int *start
,
50 long int *size
, gid_t
**groups
,
51 long int limit
, int *errnop
);
52 NSS_STATUS
_nss_winbind_getusersids(const char *user_sid
, char **group_sids
,
53 int *num_groups
, char *buffer
, size_t buf_size
,
55 NSS_STATUS
_nss_winbind_nametosid(const char *name
, char **sid
, char *buffer
,
56 size_t buflen
, int *errnop
);
57 NSS_STATUS
_nss_winbind_sidtoname(const char *sid
, char **name
, char *buffer
,
58 size_t buflen
, int *errnop
);
59 NSS_STATUS
_nss_winbind_sidtouid(const char *sid
, uid_t
*uid
, int *errnop
);
60 NSS_STATUS
_nss_winbind_sidtogid(const char *sid
, gid_t
*gid
, int *errnop
);
61 NSS_STATUS
_nss_winbind_uidtosid(uid_t uid
, char **sid
, char *buffer
,
62 size_t buflen
, int *errnop
);
63 NSS_STATUS
_nss_winbind_gidtosid(gid_t gid
, char **sid
, char *buffer
,
64 size_t buflen
, int *errnop
);
66 /* Prototypes from wb_common.c */
68 extern int winbindd_fd
;
71 static const char *nss_err_str(NSS_STATUS ret
) {
73 case NSS_STATUS_TRYAGAIN
:
74 return "NSS_STATUS_TRYAGAIN";
75 case NSS_STATUS_SUCCESS
:
76 return "NSS_STATUS_SUCCESS";
77 case NSS_STATUS_NOTFOUND
:
78 return "NSS_STATUS_NOTFOUND";
79 case NSS_STATUS_UNAVAIL
:
80 return "NSS_STATUS_UNAVAIL";
81 case NSS_STATUS_RETURN
:
82 return "NSS_STATUS_RETURN";
84 return "UNKNOWN RETURN CODE!!!!!!!";
89 /* Allocate some space from the nss static buffer. The buffer and buflen
90 are the pointers passed in by the C library to the _nss_ntdom_*
93 static char *get_static(char **buffer
, size_t *buflen
, size_t len
)
97 /* Error check. We return false if things aren't set up right, or
98 there isn't enough buffer space left. */
100 if ((buffer
== NULL
) || (buflen
== NULL
) || (*buflen
< len
)) {
104 /* Return an index into the static buffer */
113 /* I've copied the strtok() replacement function next_token() from
114 lib/util_str.c as I really don't want to have to link in any other
115 objects if I can possibly avoid it. */
117 static BOOL
next_token(char **ptr
,char *buff
,const char *sep
, size_t bufsize
)
123 if (!ptr
) return(False
);
127 /* default to simple separators */
128 if (!sep
) sep
= " \t\n\r";
130 /* find the first non sep char */
131 while (*s
&& strchr(sep
,*s
)) s
++;
134 if (! *s
) return(False
);
136 /* copy over the token */
137 for (quoted
= False
; len
< bufsize
&& *s
&& (quoted
|| !strchr(sep
,*s
)); s
++) {
146 *ptr
= (*s
) ? s
+1 : s
;
153 /* Fill a pwent structure from a winbindd_response structure. We use
154 the static data passed to us by libc to put strings and stuff in.
155 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
157 static NSS_STATUS
fill_pwent(struct passwd
*result
,
158 struct winbindd_pw
*pw
,
159 char **buffer
, size_t *buflen
)
163 if ((result
->pw_name
=
164 get_static(buffer
, buflen
, strlen(pw
->pw_name
) + 1)) == NULL
) {
168 return NSS_STATUS_TRYAGAIN
;
171 strcpy(result
->pw_name
, pw
->pw_name
);
175 if ((result
->pw_passwd
=
176 get_static(buffer
, buflen
, strlen(pw
->pw_passwd
) + 1)) == NULL
) {
180 return NSS_STATUS_TRYAGAIN
;
183 strcpy(result
->pw_passwd
, pw
->pw_passwd
);
187 result
->pw_uid
= pw
->pw_uid
;
188 result
->pw_gid
= pw
->pw_gid
;
192 if ((result
->pw_gecos
=
193 get_static(buffer
, buflen
, strlen(pw
->pw_gecos
) + 1)) == NULL
) {
197 return NSS_STATUS_TRYAGAIN
;
200 strcpy(result
->pw_gecos
, pw
->pw_gecos
);
204 if ((result
->pw_dir
=
205 get_static(buffer
, buflen
, strlen(pw
->pw_dir
) + 1)) == NULL
) {
209 return NSS_STATUS_TRYAGAIN
;
212 strcpy(result
->pw_dir
, pw
->pw_dir
);
216 if ((result
->pw_shell
=
217 get_static(buffer
, buflen
, strlen(pw
->pw_shell
) + 1)) == NULL
) {
221 return NSS_STATUS_TRYAGAIN
;
224 strcpy(result
->pw_shell
, pw
->pw_shell
);
226 /* The struct passwd for Solaris has some extra fields which must
227 be initialised or nscd crashes. */
229 #if HAVE_PASSWD_PW_COMMENT
230 result
->pw_comment
= "";
233 #if HAVE_PASSWD_PW_AGE
237 return NSS_STATUS_SUCCESS
;
240 /* Fill a grent structure from a winbindd_response structure. We use
241 the static data passed to us by libc to put strings and stuff in.
242 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
244 static NSS_STATUS
fill_grent(struct group
*result
, struct winbindd_gr
*gr
,
245 char *gr_mem
, char **buffer
, size_t *buflen
)
253 if ((result
->gr_name
=
254 get_static(buffer
, buflen
, strlen(gr
->gr_name
) + 1)) == NULL
) {
258 return NSS_STATUS_TRYAGAIN
;
261 strcpy(result
->gr_name
, gr
->gr_name
);
265 if ((result
->gr_passwd
=
266 get_static(buffer
, buflen
, strlen(gr
->gr_passwd
) + 1)) == NULL
) {
270 return NSS_STATUS_TRYAGAIN
;
273 strcpy(result
->gr_passwd
, gr
->gr_passwd
);
277 result
->gr_gid
= gr
->gr_gid
;
279 /* Group membership */
281 if ((gr
->num_gr_mem
< 0) || !gr_mem
) {
285 /* this next value is a pointer to a pointer so let's align it */
287 /* Calculate number of extra bytes needed to align on pointer size boundry */
288 if ((i
= (unsigned long)(*buffer
) % sizeof(char*)) != 0)
289 i
= sizeof(char*) - i
;
291 if ((tst
= get_static(buffer
, buflen
, ((gr
->num_gr_mem
+ 1) *
292 sizeof(char *)+i
))) == NULL
) {
296 return NSS_STATUS_TRYAGAIN
;
298 result
->gr_mem
= (char **)(tst
+ i
);
300 if (gr
->num_gr_mem
== 0) {
304 *(result
->gr_mem
) = NULL
;
305 return NSS_STATUS_SUCCESS
;
308 /* Start looking at extra data */
312 while(next_token((char **)&gr_mem
, name
, ",", sizeof(fstring
))) {
314 /* Allocate space for member */
316 if (((result
->gr_mem
)[i
] =
317 get_static(buffer
, buflen
, strlen(name
) + 1)) == NULL
) {
321 return NSS_STATUS_TRYAGAIN
;
324 strcpy((result
->gr_mem
)[i
], name
);
330 (result
->gr_mem
)[i
] = NULL
;
332 return NSS_STATUS_SUCCESS
;
339 static struct winbindd_response getpwent_response
;
341 static int ndx_pw_cache
; /* Current index into pwd cache */
342 static int num_pw_cache
; /* Current size of pwd cache */
344 /* Rewind "file pointer" to start of ntdom password database */
347 _nss_winbind_setpwent(void)
351 fprintf(stderr
, "[%5d]: setpwent\n", getpid());
354 if (num_pw_cache
> 0) {
355 ndx_pw_cache
= num_pw_cache
= 0;
356 free_response(&getpwent_response
);
359 ret
= winbindd_request_response(WINBINDD_SETPWENT
, NULL
, NULL
);
361 fprintf(stderr
, "[%5d]: setpwent returns %s (%d)\n", getpid(),
362 nss_err_str(ret
), ret
);
367 /* Close ntdom password database "file pointer" */
370 _nss_winbind_endpwent(void)
374 fprintf(stderr
, "[%5d]: endpwent\n", getpid());
377 if (num_pw_cache
> 0) {
378 ndx_pw_cache
= num_pw_cache
= 0;
379 free_response(&getpwent_response
);
382 ret
= winbindd_request_response(WINBINDD_ENDPWENT
, NULL
, NULL
);
384 fprintf(stderr
, "[%5d]: endpwent returns %s (%d)\n", getpid(),
385 nss_err_str(ret
), ret
);
390 /* Fetch the next password entry from ntdom password database */
393 _nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
394 size_t buflen
, int *errnop
)
397 struct winbindd_request request
;
398 static int called_again
;
401 fprintf(stderr
, "[%5d]: getpwent\n", getpid());
404 /* Return an entry from the cache if we have one, or if we are
405 called again because we exceeded our static buffer. */
407 if ((ndx_pw_cache
< num_pw_cache
) || called_again
) {
411 /* Else call winbindd to get a bunch of entries */
413 if (num_pw_cache
> 0) {
414 free_response(&getpwent_response
);
417 ZERO_STRUCT(request
);
418 ZERO_STRUCT(getpwent_response
);
420 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
422 ret
= winbindd_request_response(WINBINDD_GETPWENT
, &request
,
425 if (ret
== NSS_STATUS_SUCCESS
) {
426 struct winbindd_pw
*pw_cache
;
431 num_pw_cache
= getpwent_response
.data
.num_entries
;
433 /* Return a result */
437 pw_cache
= (struct winbindd_pw
*)
438 getpwent_response
.extra_data
.data
;
440 /* Check data is valid */
442 if (pw_cache
== NULL
) {
443 ret
= NSS_STATUS_NOTFOUND
;
447 ret
= fill_pwent(result
, &pw_cache
[ndx_pw_cache
],
450 /* Out of memory - try again */
452 if (ret
== NSS_STATUS_TRYAGAIN
) {
454 *errnop
= errno
= ERANGE
;
459 called_again
= False
;
462 /* If we've finished with this lot of results free cache */
464 if (ndx_pw_cache
== num_pw_cache
) {
465 ndx_pw_cache
= num_pw_cache
= 0;
466 free_response(&getpwent_response
);
471 fprintf(stderr
, "[%5d]: getpwent returns %s (%d)\n", getpid(),
472 nss_err_str(ret
), ret
);
477 /* Return passwd struct from uid */
480 _nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
, char *buffer
,
481 size_t buflen
, int *errnop
)
484 static struct winbindd_response response
;
485 struct winbindd_request request
;
486 static int keep_response
=0;
489 fprintf(stderr
, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid
);
492 /* If our static buffer needs to be expanded we are called again */
493 if (!keep_response
) {
495 /* Call for the first time */
497 ZERO_STRUCT(response
);
498 ZERO_STRUCT(request
);
500 request
.data
.uid
= uid
;
502 ret
= winbindd_request_response(WINBINDD_GETPWUID
, &request
, &response
);
504 if (ret
== NSS_STATUS_SUCCESS
) {
505 ret
= fill_pwent(result
, &response
.data
.pw
,
508 if (ret
== NSS_STATUS_TRYAGAIN
) {
509 keep_response
= True
;
510 *errnop
= errno
= ERANGE
;
517 /* We've been called again */
519 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
521 if (ret
== NSS_STATUS_TRYAGAIN
) {
522 keep_response
= True
;
523 *errnop
= errno
= ERANGE
;
527 keep_response
= False
;
531 free_response(&response
);
535 fprintf(stderr
, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
536 (unsigned int)uid
, nss_err_str(ret
), ret
);
541 /* Return passwd struct from username */
543 _nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
, char *buffer
,
544 size_t buflen
, int *errnop
)
547 static struct winbindd_response response
;
548 struct winbindd_request request
;
549 static int keep_response
;
552 fprintf(stderr
, "[%5d]: getpwnam %s\n", getpid(), name
);
555 /* If our static buffer needs to be expanded we are called again */
557 if (!keep_response
) {
559 /* Call for the first time */
561 ZERO_STRUCT(response
);
562 ZERO_STRUCT(request
);
564 strncpy(request
.data
.username
, name
,
565 sizeof(request
.data
.username
) - 1);
566 request
.data
.username
567 [sizeof(request
.data
.username
) - 1] = '\0';
569 ret
= winbindd_request_response(WINBINDD_GETPWNAM
, &request
, &response
);
571 if (ret
== NSS_STATUS_SUCCESS
) {
572 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
,
575 if (ret
== NSS_STATUS_TRYAGAIN
) {
576 keep_response
= True
;
577 *errnop
= errno
= ERANGE
;
584 /* We've been called again */
586 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
588 if (ret
== NSS_STATUS_TRYAGAIN
) {
589 keep_response
= True
;
590 *errnop
= errno
= ERANGE
;
594 keep_response
= False
;
598 free_response(&response
);
601 fprintf(stderr
, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
602 name
, nss_err_str(ret
), ret
);
608 * NSS group functions
611 static struct winbindd_response getgrent_response
;
613 static int ndx_gr_cache
; /* Current index into grp cache */
614 static int num_gr_cache
; /* Current size of grp cache */
616 /* Rewind "file pointer" to start of ntdom group database */
619 _nss_winbind_setgrent(void)
623 fprintf(stderr
, "[%5d]: setgrent\n", getpid());
626 if (num_gr_cache
> 0) {
627 ndx_gr_cache
= num_gr_cache
= 0;
628 free_response(&getgrent_response
);
631 ret
= winbindd_request_response(WINBINDD_SETGRENT
, NULL
, NULL
);
633 fprintf(stderr
, "[%5d]: setgrent returns %s (%d)\n", getpid(),
634 nss_err_str(ret
), ret
);
639 /* Close "file pointer" for ntdom group database */
642 _nss_winbind_endgrent(void)
646 fprintf(stderr
, "[%5d]: endgrent\n", getpid());
649 if (num_gr_cache
> 0) {
650 ndx_gr_cache
= num_gr_cache
= 0;
651 free_response(&getgrent_response
);
654 ret
= winbindd_request_response(WINBINDD_ENDGRENT
, NULL
, NULL
);
656 fprintf(stderr
, "[%5d]: endgrent returns %s (%d)\n", getpid(),
657 nss_err_str(ret
), ret
);
662 /* Get next entry from ntdom group database */
665 winbind_getgrent(enum winbindd_cmd cmd
,
666 struct group
*result
,
667 char *buffer
, size_t buflen
, int *errnop
)
670 static struct winbindd_request request
;
671 static int called_again
;
675 fprintf(stderr
, "[%5d]: getgrent\n", getpid());
678 /* Return an entry from the cache if we have one, or if we are
679 called again because we exceeded our static buffer. */
681 if ((ndx_gr_cache
< num_gr_cache
) || called_again
) {
685 /* Else call winbindd to get a bunch of entries */
687 if (num_gr_cache
> 0) {
688 free_response(&getgrent_response
);
691 ZERO_STRUCT(request
);
692 ZERO_STRUCT(getgrent_response
);
694 request
.data
.num_entries
= MAX_GETGRENT_USERS
;
696 ret
= winbindd_request_response(cmd
, &request
,
699 if (ret
== NSS_STATUS_SUCCESS
) {
700 struct winbindd_gr
*gr_cache
;
706 num_gr_cache
= getgrent_response
.data
.num_entries
;
708 /* Return a result */
712 gr_cache
= (struct winbindd_gr
*)
713 getgrent_response
.extra_data
.data
;
715 /* Check data is valid */
717 if (gr_cache
== NULL
) {
718 ret
= NSS_STATUS_NOTFOUND
;
722 /* Fill group membership. The offset into the extra data
723 for the group membership is the reported offset plus the
724 size of all the winbindd_gr records returned. */
726 mem_ofs
= gr_cache
[ndx_gr_cache
].gr_mem_ofs
+
727 num_gr_cache
* sizeof(struct winbindd_gr
);
729 ret
= fill_grent(result
, &gr_cache
[ndx_gr_cache
],
730 ((char *)getgrent_response
.extra_data
.data
)+mem_ofs
,
733 /* Out of memory - try again */
735 if (ret
== NSS_STATUS_TRYAGAIN
) {
737 *errnop
= errno
= ERANGE
;
742 called_again
= False
;
745 /* If we've finished with this lot of results free cache */
747 if (ndx_gr_cache
== num_gr_cache
) {
748 ndx_gr_cache
= num_gr_cache
= 0;
749 free_response(&getgrent_response
);
754 fprintf(stderr
, "[%5d]: getgrent returns %s (%d)\n", getpid(),
755 nss_err_str(ret
), ret
);
762 _nss_winbind_getgrent_r(struct group
*result
,
763 char *buffer
, size_t buflen
, int *errnop
)
765 return winbind_getgrent(WINBINDD_GETGRENT
, result
, buffer
, buflen
, errnop
);
769 _nss_winbind_getgrlst_r(struct group
*result
,
770 char *buffer
, size_t buflen
, int *errnop
)
772 return winbind_getgrent(WINBINDD_GETGRLST
, result
, buffer
, buflen
, errnop
);
775 /* Return group struct from group name */
778 _nss_winbind_getgrnam_r(const char *name
,
779 struct group
*result
, char *buffer
,
780 size_t buflen
, int *errnop
)
783 static struct winbindd_response response
;
784 struct winbindd_request request
;
785 static int keep_response
;
788 fprintf(stderr
, "[%5d]: getgrnam %s\n", getpid(), name
);
791 /* If our static buffer needs to be expanded we are called again */
793 if (!keep_response
) {
795 /* Call for the first time */
797 ZERO_STRUCT(request
);
798 ZERO_STRUCT(response
);
800 strncpy(request
.data
.groupname
, name
,
801 sizeof(request
.data
.groupname
));
802 request
.data
.groupname
803 [sizeof(request
.data
.groupname
) - 1] = '\0';
805 ret
= winbindd_request_response(WINBINDD_GETGRNAM
, &request
, &response
);
807 if (ret
== NSS_STATUS_SUCCESS
) {
808 ret
= fill_grent(result
, &response
.data
.gr
,
809 (char *)response
.extra_data
.data
,
812 if (ret
== NSS_STATUS_TRYAGAIN
) {
813 keep_response
= True
;
814 *errnop
= errno
= ERANGE
;
821 /* We've been called again */
823 ret
= fill_grent(result
, &response
.data
.gr
,
824 (char *)response
.extra_data
.data
, &buffer
,
827 if (ret
== NSS_STATUS_TRYAGAIN
) {
828 keep_response
= True
;
829 *errnop
= errno
= ERANGE
;
833 keep_response
= False
;
837 free_response(&response
);
840 fprintf(stderr
, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
841 name
, nss_err_str(ret
), ret
);
846 /* Return group struct from gid */
849 _nss_winbind_getgrgid_r(gid_t gid
,
850 struct group
*result
, char *buffer
,
851 size_t buflen
, int *errnop
)
854 static struct winbindd_response response
;
855 struct winbindd_request request
;
856 static int keep_response
;
859 fprintf(stderr
, "[%5d]: getgrgid %d\n", getpid(), gid
);
862 /* If our static buffer needs to be expanded we are called again */
864 if (!keep_response
) {
866 /* Call for the first time */
868 ZERO_STRUCT(request
);
869 ZERO_STRUCT(response
);
871 request
.data
.gid
= gid
;
873 ret
= winbindd_request_response(WINBINDD_GETGRGID
, &request
, &response
);
875 if (ret
== NSS_STATUS_SUCCESS
) {
877 ret
= fill_grent(result
, &response
.data
.gr
,
878 (char *)response
.extra_data
.data
,
881 if (ret
== NSS_STATUS_TRYAGAIN
) {
882 keep_response
= True
;
883 *errnop
= errno
= ERANGE
;
890 /* We've been called again */
892 ret
= fill_grent(result
, &response
.data
.gr
,
893 (char *)response
.extra_data
.data
, &buffer
,
896 if (ret
== NSS_STATUS_TRYAGAIN
) {
897 keep_response
= True
;
898 *errnop
= errno
= ERANGE
;
902 keep_response
= False
;
906 free_response(&response
);
909 fprintf(stderr
, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
910 (unsigned int)gid
, nss_err_str(ret
), ret
);
915 /* Initialise supplementary groups */
918 _nss_winbind_initgroups_dyn(char *user
, gid_t group
, long int *start
,
919 long int *size
, gid_t
**groups
, long int limit
,
923 struct winbindd_request request
;
924 struct winbindd_response response
;
928 fprintf(stderr
, "[%5d]: initgroups %s (%d)\n", getpid(),
932 ZERO_STRUCT(request
);
933 ZERO_STRUCT(response
);
935 strncpy(request
.data
.username
, user
,
936 sizeof(request
.data
.username
) - 1);
938 ret
= winbindd_request_response(WINBINDD_GETGROUPS
, &request
, &response
);
940 if (ret
== NSS_STATUS_SUCCESS
) {
941 int num_gids
= response
.data
.num_entries
;
942 gid_t
*gid_list
= (gid_t
*)response
.extra_data
.data
;
945 fprintf(stderr
, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
946 "and %d gids\n", getpid(),
949 if (gid_list
== NULL
) {
950 ret
= NSS_STATUS_NOTFOUND
;
954 /* Copy group list to client */
956 for (i
= 0; i
< num_gids
; i
++) {
959 fprintf(stderr
, "[%5d]: initgroups %s (%d): "
960 "processing gid %d \n", getpid(),
961 user
, group
, gid_list
[i
]);
964 /* Skip primary group */
966 if (gid_list
[i
] == group
) {
970 /* Filled buffer ? If so, resize. */
972 if (*start
== *size
) {
976 newsize
= 2 * (*size
);
978 if (*size
== limit
) {
981 if (newsize
> limit
) {
986 newgroups
= (gid_t
*)
988 newsize
* sizeof(**groups
));
991 ret
= NSS_STATUS_NOTFOUND
;
1000 (*groups
)[*start
] = gid_list
[i
];
1005 /* Back to your regularly scheduled programming */
1009 fprintf(stderr
, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
1010 user
, nss_err_str(ret
), ret
);
1016 /* return a list of group SIDs for a user SID */
1018 _nss_winbind_getusersids(const char *user_sid
, char **group_sids
,
1020 char *buffer
, size_t buf_size
, int *errnop
)
1023 struct winbindd_request request
;
1024 struct winbindd_response response
;
1027 fprintf(stderr
, "[%5d]: getusersids %s\n", getpid(), user_sid
);
1030 ZERO_STRUCT(request
);
1031 ZERO_STRUCT(response
);
1033 strncpy(request
.data
.sid
, user_sid
,sizeof(request
.data
.sid
) - 1);
1034 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1036 ret
= winbindd_request_response(WINBINDD_GETUSERSIDS
, &request
, &response
);
1038 if (ret
!= NSS_STATUS_SUCCESS
) {
1042 if (buf_size
< response
.length
- sizeof(response
)) {
1043 ret
= NSS_STATUS_TRYAGAIN
;
1044 errno
= *errnop
= ERANGE
;
1048 *num_groups
= response
.data
.num_entries
;
1049 *group_sids
= buffer
;
1050 memcpy(buffer
, response
.extra_data
.data
, response
.length
- sizeof(response
));
1051 errno
= *errnop
= 0;
1054 free_response(&response
);
1059 /* map a user or group name to a SID string */
1061 _nss_winbind_nametosid(const char *name
, char **sid
, char *buffer
,
1062 size_t buflen
, int *errnop
)
1065 struct winbindd_response response
;
1066 struct winbindd_request request
;
1069 fprintf(stderr
, "[%5d]: nametosid %s\n", getpid(), name
);
1072 ZERO_STRUCT(response
);
1073 ZERO_STRUCT(request
);
1075 strncpy(request
.data
.name
.name
, name
,
1076 sizeof(request
.data
.name
.name
) - 1);
1077 request
.data
.name
.name
[sizeof(request
.data
.name
.name
) - 1] = '\0';
1079 ret
= winbindd_request_response(WINBINDD_LOOKUPNAME
, &request
, &response
);
1080 if (ret
!= NSS_STATUS_SUCCESS
) {
1081 *errnop
= errno
= EINVAL
;
1085 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1086 ret
= NSS_STATUS_TRYAGAIN
;
1087 *errnop
= errno
= ERANGE
;
1091 *errnop
= errno
= 0;
1093 strcpy(*sid
, response
.data
.sid
.sid
);
1096 free_response(&response
);
1100 /* map a sid string to a user or group name */
1102 _nss_winbind_sidtoname(const char *sid
, char **name
, char *buffer
,
1103 size_t buflen
, int *errnop
)
1106 struct winbindd_response response
;
1107 struct winbindd_request request
;
1108 static char sep_char
;
1112 fprintf(stderr
, "[%5d]: sidtoname %s\n", getpid(), sid
);
1115 ZERO_STRUCT(response
);
1116 ZERO_STRUCT(request
);
1118 /* we need to fetch the separator first time through */
1120 ret
= winbindd_request_response(WINBINDD_INFO
, &request
, &response
);
1121 if (ret
!= NSS_STATUS_SUCCESS
) {
1122 *errnop
= errno
= EINVAL
;
1126 sep_char
= response
.data
.info
.winbind_separator
;
1127 free_response(&response
);
1131 strncpy(request
.data
.sid
, sid
,
1132 sizeof(request
.data
.sid
) - 1);
1133 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1135 ret
= winbindd_request_response(WINBINDD_LOOKUPSID
, &request
, &response
);
1136 if (ret
!= NSS_STATUS_SUCCESS
) {
1137 *errnop
= errno
= EINVAL
;
1142 strlen(response
.data
.name
.dom_name
) +
1143 strlen(response
.data
.name
.name
) + 2;
1145 if (buflen
< needed
) {
1146 ret
= NSS_STATUS_TRYAGAIN
;
1147 *errnop
= errno
= ERANGE
;
1151 snprintf(buffer
, needed
, "%s%c%s",
1152 response
.data
.name
.dom_name
,
1154 response
.data
.name
.name
);
1157 *errnop
= errno
= 0;
1160 free_response(&response
);
1164 /* map a sid to a uid */
1166 _nss_winbind_sidtouid(const char *sid
, uid_t
*uid
, int *errnop
)
1169 struct winbindd_response response
;
1170 struct winbindd_request request
;
1173 fprintf(stderr
, "[%5d]: sidtouid %s\n", getpid(), sid
);
1176 ZERO_STRUCT(request
);
1177 ZERO_STRUCT(response
);
1179 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1180 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1182 ret
= winbindd_request_response(WINBINDD_SID_TO_UID
, &request
, &response
);
1183 if (ret
!= NSS_STATUS_SUCCESS
) {
1184 *errnop
= errno
= EINVAL
;
1188 *uid
= response
.data
.uid
;
1194 /* map a sid to a gid */
1196 _nss_winbind_sidtogid(const char *sid
, gid_t
*gid
, int *errnop
)
1199 struct winbindd_response response
;
1200 struct winbindd_request request
;
1203 fprintf(stderr
, "[%5d]: sidtogid %s\n", getpid(), sid
);
1206 ZERO_STRUCT(request
);
1207 ZERO_STRUCT(response
);
1209 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1210 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1212 ret
= winbindd_request_response(WINBINDD_SID_TO_GID
, &request
, &response
);
1213 if (ret
!= NSS_STATUS_SUCCESS
) {
1214 *errnop
= errno
= EINVAL
;
1218 *gid
= response
.data
.gid
;
1224 /* map a uid to a SID string */
1226 _nss_winbind_uidtosid(uid_t uid
, char **sid
, char *buffer
,
1227 size_t buflen
, int *errnop
)
1230 struct winbindd_response response
;
1231 struct winbindd_request request
;
1234 fprintf(stderr
, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid
);
1237 ZERO_STRUCT(response
);
1238 ZERO_STRUCT(request
);
1240 request
.data
.uid
= uid
;
1242 ret
= winbindd_request_response(WINBINDD_UID_TO_SID
, &request
, &response
);
1243 if (ret
!= NSS_STATUS_SUCCESS
) {
1244 *errnop
= errno
= EINVAL
;
1248 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1249 ret
= NSS_STATUS_TRYAGAIN
;
1250 *errnop
= errno
= ERANGE
;
1254 *errnop
= errno
= 0;
1256 strcpy(*sid
, response
.data
.sid
.sid
);
1259 free_response(&response
);
1263 /* map a gid to a SID string */
1265 _nss_winbind_gidtosid(gid_t gid
, char **sid
, char *buffer
,
1266 size_t buflen
, int *errnop
)
1269 struct winbindd_response response
;
1270 struct winbindd_request request
;
1273 fprintf(stderr
, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid
);
1276 ZERO_STRUCT(response
);
1277 ZERO_STRUCT(request
);
1279 request
.data
.gid
= gid
;
1281 ret
= winbindd_request_response(WINBINDD_GID_TO_SID
, &request
, &response
);
1282 if (ret
!= NSS_STATUS_SUCCESS
) {
1283 *errnop
= errno
= EINVAL
;
1287 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1288 ret
= NSS_STATUS_TRYAGAIN
;
1289 *errnop
= errno
= ERANGE
;
1293 *errnop
= errno
= 0;
1295 strcpy(*sid
, response
.data
.sid
.sid
);
1298 free_response(&response
);