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 2 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
19 License along with this library; if not, write to the
20 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.
24 #include "winbind_client.h"
26 /* Maximum number of users to pass back over the unix domain socket
27 per call. This is not a static limit on the total number of users
28 or groups returned in total. */
30 #define MAX_GETPWENT_USERS 250
31 #define MAX_GETGRENT_USERS 250
33 NSS_STATUS
_nss_winbind_setpwent(void);
34 NSS_STATUS
_nss_winbind_endpwent(void);
35 NSS_STATUS
_nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
36 size_t buflen
, int *errnop
);
37 NSS_STATUS
_nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
,
38 char *buffer
, size_t buflen
, int *errnop
);
39 NSS_STATUS
_nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
,
40 char *buffer
, size_t buflen
, int *errnop
);
41 NSS_STATUS
_nss_winbind_setgrent(void);
42 NSS_STATUS
_nss_winbind_endgrent(void);
43 NSS_STATUS
_nss_winbind_getgrent_r(struct group
*result
, char *buffer
,
44 size_t buflen
, int *errnop
);
45 NSS_STATUS
_nss_winbind_getgrlst_r(struct group
*result
, char *buffer
,
46 size_t buflen
, int *errnop
);
47 NSS_STATUS
_nss_winbind_getgrnam_r(const char *name
, struct group
*result
,
48 char *buffer
, size_t buflen
, int *errnop
);
49 NSS_STATUS
_nss_winbind_getgrgid_r(gid_t gid
, struct group
*result
, char *buffer
,
50 size_t buflen
, int *errnop
);
51 NSS_STATUS
_nss_winbind_initgroups_dyn(char *user
, gid_t group
, long int *start
,
52 long int *size
, gid_t
**groups
,
53 long int limit
, int *errnop
);
54 NSS_STATUS
_nss_winbind_getusersids(const char *user_sid
, char **group_sids
,
55 int *num_groups
, char *buffer
, size_t buf_size
,
57 NSS_STATUS
_nss_winbind_nametosid(const char *name
, char **sid
, char *buffer
,
58 size_t buflen
, int *errnop
);
59 NSS_STATUS
_nss_winbind_sidtoname(const char *sid
, char **name
, char *buffer
,
60 size_t buflen
, int *errnop
);
61 NSS_STATUS
_nss_winbind_sidtouid(const char *sid
, uid_t
*uid
, int *errnop
);
62 NSS_STATUS
_nss_winbind_sidtogid(const char *sid
, gid_t
*gid
, int *errnop
);
63 NSS_STATUS
_nss_winbind_uidtosid(uid_t uid
, char **sid
, char *buffer
,
64 size_t buflen
, int *errnop
);
65 NSS_STATUS
_nss_winbind_gidtosid(gid_t gid
, char **sid
, char *buffer
,
66 size_t buflen
, int *errnop
);
68 /* Prototypes from wb_common.c */
70 extern int winbindd_fd
;
73 static const char *nss_err_str(NSS_STATUS ret
) {
75 case NSS_STATUS_TRYAGAIN
:
76 return "NSS_STATUS_TRYAGAIN";
77 case NSS_STATUS_SUCCESS
:
78 return "NSS_STATUS_SUCCESS";
79 case NSS_STATUS_NOTFOUND
:
80 return "NSS_STATUS_NOTFOUND";
81 case NSS_STATUS_UNAVAIL
:
82 return "NSS_STATUS_UNAVAIL";
83 case NSS_STATUS_RETURN
:
84 return "NSS_STATUS_RETURN";
86 return "UNKNOWN RETURN CODE!!!!!!!";
91 /* Allocate some space from the nss static buffer. The buffer and buflen
92 are the pointers passed in by the C library to the _nss_ntdom_*
95 static char *get_static(char **buffer
, size_t *buflen
, size_t len
)
99 /* Error check. We return false if things aren't set up right, or
100 there isn't enough buffer space left. */
102 if ((buffer
== NULL
) || (buflen
== NULL
) || (*buflen
< len
)) {
106 /* Return an index into the static buffer */
115 /* I've copied the strtok() replacement function next_token() from
116 lib/util_str.c as I really don't want to have to link in any other
117 objects if I can possibly avoid it. */
119 static BOOL
next_token(char **ptr
,char *buff
,const char *sep
, size_t bufsize
)
125 if (!ptr
) return(False
);
129 /* default to simple separators */
130 if (!sep
) sep
= " \t\n\r";
132 /* find the first non sep char */
133 while (*s
&& strchr(sep
,*s
)) s
++;
136 if (! *s
) return(False
);
138 /* copy over the token */
139 for (quoted
= False
; len
< bufsize
&& *s
&& (quoted
|| !strchr(sep
,*s
)); s
++) {
148 *ptr
= (*s
) ? s
+1 : s
;
155 /* Fill a pwent structure from a winbindd_response structure. We use
156 the static data passed to us by libc to put strings and stuff in.
157 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
159 static NSS_STATUS
fill_pwent(struct passwd
*result
,
160 struct winbindd_pw
*pw
,
161 char **buffer
, size_t *buflen
)
165 if ((result
->pw_name
=
166 get_static(buffer
, buflen
, strlen(pw
->pw_name
) + 1)) == NULL
) {
170 return NSS_STATUS_TRYAGAIN
;
173 strcpy(result
->pw_name
, pw
->pw_name
);
177 if ((result
->pw_passwd
=
178 get_static(buffer
, buflen
, strlen(pw
->pw_passwd
) + 1)) == NULL
) {
182 return NSS_STATUS_TRYAGAIN
;
185 strcpy(result
->pw_passwd
, pw
->pw_passwd
);
189 result
->pw_uid
= pw
->pw_uid
;
190 result
->pw_gid
= pw
->pw_gid
;
194 if ((result
->pw_gecos
=
195 get_static(buffer
, buflen
, strlen(pw
->pw_gecos
) + 1)) == NULL
) {
199 return NSS_STATUS_TRYAGAIN
;
202 strcpy(result
->pw_gecos
, pw
->pw_gecos
);
206 if ((result
->pw_dir
=
207 get_static(buffer
, buflen
, strlen(pw
->pw_dir
) + 1)) == NULL
) {
211 return NSS_STATUS_TRYAGAIN
;
214 strcpy(result
->pw_dir
, pw
->pw_dir
);
218 if ((result
->pw_shell
=
219 get_static(buffer
, buflen
, strlen(pw
->pw_shell
) + 1)) == NULL
) {
223 return NSS_STATUS_TRYAGAIN
;
226 strcpy(result
->pw_shell
, pw
->pw_shell
);
228 /* The struct passwd for Solaris has some extra fields which must
229 be initialised or nscd crashes. */
231 #if HAVE_PASSWD_PW_COMMENT
232 result
->pw_comment
= "";
235 #if HAVE_PASSWD_PW_AGE
239 return NSS_STATUS_SUCCESS
;
242 /* Fill a grent structure from a winbindd_response structure. We use
243 the static data passed to us by libc to put strings and stuff in.
244 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
246 static NSS_STATUS
fill_grent(struct group
*result
, struct winbindd_gr
*gr
,
247 char *gr_mem
, char **buffer
, size_t *buflen
)
255 if ((result
->gr_name
=
256 get_static(buffer
, buflen
, strlen(gr
->gr_name
) + 1)) == NULL
) {
260 return NSS_STATUS_TRYAGAIN
;
263 strcpy(result
->gr_name
, gr
->gr_name
);
267 if ((result
->gr_passwd
=
268 get_static(buffer
, buflen
, strlen(gr
->gr_passwd
) + 1)) == NULL
) {
272 return NSS_STATUS_TRYAGAIN
;
275 strcpy(result
->gr_passwd
, gr
->gr_passwd
);
279 result
->gr_gid
= gr
->gr_gid
;
281 /* Group membership */
283 if ((gr
->num_gr_mem
< 0) || !gr_mem
) {
287 /* this next value is a pointer to a pointer so let's align it */
289 /* Calculate number of extra bytes needed to align on pointer size boundry */
290 if ((i
= (unsigned long)(*buffer
) % sizeof(char*)) != 0)
291 i
= sizeof(char*) - i
;
293 if ((tst
= get_static(buffer
, buflen
, ((gr
->num_gr_mem
+ 1) *
294 sizeof(char *)+i
))) == NULL
) {
298 return NSS_STATUS_TRYAGAIN
;
300 result
->gr_mem
= (char **)(tst
+ i
);
302 if (gr
->num_gr_mem
== 0) {
306 *(result
->gr_mem
) = NULL
;
307 return NSS_STATUS_SUCCESS
;
310 /* Start looking at extra data */
314 while(next_token((char **)&gr_mem
, name
, ",", sizeof(fstring
))) {
316 /* Allocate space for member */
318 if (((result
->gr_mem
)[i
] =
319 get_static(buffer
, buflen
, strlen(name
) + 1)) == NULL
) {
323 return NSS_STATUS_TRYAGAIN
;
326 strcpy((result
->gr_mem
)[i
], name
);
332 (result
->gr_mem
)[i
] = NULL
;
334 return NSS_STATUS_SUCCESS
;
341 static struct winbindd_response getpwent_response
;
343 static int ndx_pw_cache
; /* Current index into pwd cache */
344 static int num_pw_cache
; /* Current size of pwd cache */
346 /* Rewind "file pointer" to start of ntdom password database */
349 _nss_winbind_setpwent(void)
353 fprintf(stderr
, "[%5d]: setpwent\n", getpid());
356 if (num_pw_cache
> 0) {
357 ndx_pw_cache
= num_pw_cache
= 0;
358 free_response(&getpwent_response
);
361 ret
= winbindd_request_response(WINBINDD_SETPWENT
, NULL
, NULL
);
363 fprintf(stderr
, "[%5d]: setpwent returns %s (%d)\n", getpid(),
364 nss_err_str(ret
), ret
);
369 /* Close ntdom password database "file pointer" */
372 _nss_winbind_endpwent(void)
376 fprintf(stderr
, "[%5d]: endpwent\n", getpid());
379 if (num_pw_cache
> 0) {
380 ndx_pw_cache
= num_pw_cache
= 0;
381 free_response(&getpwent_response
);
384 ret
= winbindd_request_response(WINBINDD_ENDPWENT
, NULL
, NULL
);
386 fprintf(stderr
, "[%5d]: endpwent returns %s (%d)\n", getpid(),
387 nss_err_str(ret
), ret
);
392 /* Fetch the next password entry from ntdom password database */
395 _nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
396 size_t buflen
, int *errnop
)
399 struct winbindd_request request
;
400 static int called_again
;
403 fprintf(stderr
, "[%5d]: getpwent\n", getpid());
406 /* Return an entry from the cache if we have one, or if we are
407 called again because we exceeded our static buffer. */
409 if ((ndx_pw_cache
< num_pw_cache
) || called_again
) {
413 /* Else call winbindd to get a bunch of entries */
415 if (num_pw_cache
> 0) {
416 free_response(&getpwent_response
);
419 ZERO_STRUCT(request
);
420 ZERO_STRUCT(getpwent_response
);
422 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
424 ret
= winbindd_request_response(WINBINDD_GETPWENT
, &request
,
427 if (ret
== NSS_STATUS_SUCCESS
) {
428 struct winbindd_pw
*pw_cache
;
433 num_pw_cache
= getpwent_response
.data
.num_entries
;
435 /* Return a result */
439 pw_cache
= (struct winbindd_pw
*)
440 getpwent_response
.extra_data
.data
;
442 /* Check data is valid */
444 if (pw_cache
== NULL
) {
445 ret
= NSS_STATUS_NOTFOUND
;
449 ret
= fill_pwent(result
, &pw_cache
[ndx_pw_cache
],
452 /* Out of memory - try again */
454 if (ret
== NSS_STATUS_TRYAGAIN
) {
456 *errnop
= errno
= ERANGE
;
461 called_again
= False
;
464 /* If we've finished with this lot of results free cache */
466 if (ndx_pw_cache
== num_pw_cache
) {
467 ndx_pw_cache
= num_pw_cache
= 0;
468 free_response(&getpwent_response
);
473 fprintf(stderr
, "[%5d]: getpwent returns %s (%d)\n", getpid(),
474 nss_err_str(ret
), ret
);
479 /* Return passwd struct from uid */
482 _nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
, char *buffer
,
483 size_t buflen
, int *errnop
)
486 static struct winbindd_response response
;
487 struct winbindd_request request
;
488 static int keep_response
=0;
491 fprintf(stderr
, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid
);
494 /* If our static buffer needs to be expanded we are called again */
495 if (!keep_response
) {
497 /* Call for the first time */
499 ZERO_STRUCT(response
);
500 ZERO_STRUCT(request
);
502 request
.data
.uid
= uid
;
504 ret
= winbindd_request_response(WINBINDD_GETPWUID
, &request
, &response
);
506 if (ret
== NSS_STATUS_SUCCESS
) {
507 ret
= fill_pwent(result
, &response
.data
.pw
,
510 if (ret
== NSS_STATUS_TRYAGAIN
) {
511 keep_response
= True
;
512 *errnop
= errno
= ERANGE
;
519 /* We've been called again */
521 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
523 if (ret
== NSS_STATUS_TRYAGAIN
) {
524 keep_response
= True
;
525 *errnop
= errno
= ERANGE
;
529 keep_response
= False
;
533 free_response(&response
);
537 fprintf(stderr
, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
538 (unsigned int)uid
, nss_err_str(ret
), ret
);
543 /* Return passwd struct from username */
545 _nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
, char *buffer
,
546 size_t buflen
, int *errnop
)
549 static struct winbindd_response response
;
550 struct winbindd_request request
;
551 static int keep_response
;
554 fprintf(stderr
, "[%5d]: getpwnam %s\n", getpid(), name
);
557 /* If our static buffer needs to be expanded we are called again */
559 if (!keep_response
) {
561 /* Call for the first time */
563 ZERO_STRUCT(response
);
564 ZERO_STRUCT(request
);
566 strncpy(request
.data
.username
, name
,
567 sizeof(request
.data
.username
) - 1);
568 request
.data
.username
569 [sizeof(request
.data
.username
) - 1] = '\0';
571 ret
= winbindd_request_response(WINBINDD_GETPWNAM
, &request
, &response
);
573 if (ret
== NSS_STATUS_SUCCESS
) {
574 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
,
577 if (ret
== NSS_STATUS_TRYAGAIN
) {
578 keep_response
= True
;
579 *errnop
= errno
= ERANGE
;
586 /* We've been called again */
588 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
590 if (ret
== NSS_STATUS_TRYAGAIN
) {
591 keep_response
= True
;
592 *errnop
= errno
= ERANGE
;
596 keep_response
= False
;
600 free_response(&response
);
603 fprintf(stderr
, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
604 name
, nss_err_str(ret
), ret
);
610 * NSS group functions
613 static struct winbindd_response getgrent_response
;
615 static int ndx_gr_cache
; /* Current index into grp cache */
616 static int num_gr_cache
; /* Current size of grp cache */
618 /* Rewind "file pointer" to start of ntdom group database */
621 _nss_winbind_setgrent(void)
625 fprintf(stderr
, "[%5d]: setgrent\n", getpid());
628 if (num_gr_cache
> 0) {
629 ndx_gr_cache
= num_gr_cache
= 0;
630 free_response(&getgrent_response
);
633 ret
= winbindd_request_response(WINBINDD_SETGRENT
, NULL
, NULL
);
635 fprintf(stderr
, "[%5d]: setgrent returns %s (%d)\n", getpid(),
636 nss_err_str(ret
), ret
);
641 /* Close "file pointer" for ntdom group database */
644 _nss_winbind_endgrent(void)
648 fprintf(stderr
, "[%5d]: endgrent\n", getpid());
651 if (num_gr_cache
> 0) {
652 ndx_gr_cache
= num_gr_cache
= 0;
653 free_response(&getgrent_response
);
656 ret
= winbindd_request_response(WINBINDD_ENDGRENT
, NULL
, NULL
);
658 fprintf(stderr
, "[%5d]: endgrent returns %s (%d)\n", getpid(),
659 nss_err_str(ret
), ret
);
664 /* Get next entry from ntdom group database */
667 winbind_getgrent(enum winbindd_cmd cmd
,
668 struct group
*result
,
669 char *buffer
, size_t buflen
, int *errnop
)
672 static struct winbindd_request request
;
673 static int called_again
;
677 fprintf(stderr
, "[%5d]: getgrent\n", getpid());
680 /* Return an entry from the cache if we have one, or if we are
681 called again because we exceeded our static buffer. */
683 if ((ndx_gr_cache
< num_gr_cache
) || called_again
) {
687 /* Else call winbindd to get a bunch of entries */
689 if (num_gr_cache
> 0) {
690 free_response(&getgrent_response
);
693 ZERO_STRUCT(request
);
694 ZERO_STRUCT(getgrent_response
);
696 request
.data
.num_entries
= MAX_GETGRENT_USERS
;
698 ret
= winbindd_request_response(cmd
, &request
,
701 if (ret
== NSS_STATUS_SUCCESS
) {
702 struct winbindd_gr
*gr_cache
;
708 num_gr_cache
= getgrent_response
.data
.num_entries
;
710 /* Return a result */
714 gr_cache
= (struct winbindd_gr
*)
715 getgrent_response
.extra_data
.data
;
717 /* Check data is valid */
719 if (gr_cache
== NULL
) {
720 ret
= NSS_STATUS_NOTFOUND
;
724 /* Fill group membership. The offset into the extra data
725 for the group membership is the reported offset plus the
726 size of all the winbindd_gr records returned. */
728 mem_ofs
= gr_cache
[ndx_gr_cache
].gr_mem_ofs
+
729 num_gr_cache
* sizeof(struct winbindd_gr
);
731 ret
= fill_grent(result
, &gr_cache
[ndx_gr_cache
],
732 ((char *)getgrent_response
.extra_data
.data
)+mem_ofs
,
735 /* Out of memory - try again */
737 if (ret
== NSS_STATUS_TRYAGAIN
) {
739 *errnop
= errno
= ERANGE
;
744 called_again
= False
;
747 /* If we've finished with this lot of results free cache */
749 if (ndx_gr_cache
== num_gr_cache
) {
750 ndx_gr_cache
= num_gr_cache
= 0;
751 free_response(&getgrent_response
);
756 fprintf(stderr
, "[%5d]: getgrent returns %s (%d)\n", getpid(),
757 nss_err_str(ret
), ret
);
764 _nss_winbind_getgrent_r(struct group
*result
,
765 char *buffer
, size_t buflen
, int *errnop
)
767 return winbind_getgrent(WINBINDD_GETGRENT
, result
, buffer
, buflen
, errnop
);
771 _nss_winbind_getgrlst_r(struct group
*result
,
772 char *buffer
, size_t buflen
, int *errnop
)
774 return winbind_getgrent(WINBINDD_GETGRLST
, result
, buffer
, buflen
, errnop
);
777 /* Return group struct from group name */
780 _nss_winbind_getgrnam_r(const char *name
,
781 struct group
*result
, char *buffer
,
782 size_t buflen
, int *errnop
)
785 static struct winbindd_response response
;
786 struct winbindd_request request
;
787 static int keep_response
;
790 fprintf(stderr
, "[%5d]: getgrnam %s\n", getpid(), name
);
793 /* If our static buffer needs to be expanded we are called again */
795 if (!keep_response
) {
797 /* Call for the first time */
799 ZERO_STRUCT(request
);
800 ZERO_STRUCT(response
);
802 strncpy(request
.data
.groupname
, name
,
803 sizeof(request
.data
.groupname
));
804 request
.data
.groupname
805 [sizeof(request
.data
.groupname
) - 1] = '\0';
807 ret
= winbindd_request_response(WINBINDD_GETGRNAM
, &request
, &response
);
809 if (ret
== NSS_STATUS_SUCCESS
) {
810 ret
= fill_grent(result
, &response
.data
.gr
,
811 (char *)response
.extra_data
.data
,
814 if (ret
== NSS_STATUS_TRYAGAIN
) {
815 keep_response
= True
;
816 *errnop
= errno
= ERANGE
;
823 /* We've been called again */
825 ret
= fill_grent(result
, &response
.data
.gr
,
826 (char *)response
.extra_data
.data
, &buffer
,
829 if (ret
== NSS_STATUS_TRYAGAIN
) {
830 keep_response
= True
;
831 *errnop
= errno
= ERANGE
;
835 keep_response
= False
;
839 free_response(&response
);
842 fprintf(stderr
, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
843 name
, nss_err_str(ret
), ret
);
848 /* Return group struct from gid */
851 _nss_winbind_getgrgid_r(gid_t gid
,
852 struct group
*result
, char *buffer
,
853 size_t buflen
, int *errnop
)
856 static struct winbindd_response response
;
857 struct winbindd_request request
;
858 static int keep_response
;
861 fprintf(stderr
, "[%5d]: getgrgid %d\n", getpid(), gid
);
864 /* If our static buffer needs to be expanded we are called again */
866 if (!keep_response
) {
868 /* Call for the first time */
870 ZERO_STRUCT(request
);
871 ZERO_STRUCT(response
);
873 request
.data
.gid
= gid
;
875 ret
= winbindd_request_response(WINBINDD_GETGRGID
, &request
, &response
);
877 if (ret
== NSS_STATUS_SUCCESS
) {
879 ret
= fill_grent(result
, &response
.data
.gr
,
880 (char *)response
.extra_data
.data
,
883 if (ret
== NSS_STATUS_TRYAGAIN
) {
884 keep_response
= True
;
885 *errnop
= errno
= ERANGE
;
892 /* We've been called again */
894 ret
= fill_grent(result
, &response
.data
.gr
,
895 (char *)response
.extra_data
.data
, &buffer
,
898 if (ret
== NSS_STATUS_TRYAGAIN
) {
899 keep_response
= True
;
900 *errnop
= errno
= ERANGE
;
904 keep_response
= False
;
908 free_response(&response
);
911 fprintf(stderr
, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
912 (unsigned int)gid
, nss_err_str(ret
), ret
);
917 /* Initialise supplementary groups */
920 _nss_winbind_initgroups_dyn(char *user
, gid_t group
, long int *start
,
921 long int *size
, gid_t
**groups
, long int limit
,
925 struct winbindd_request request
;
926 struct winbindd_response response
;
930 fprintf(stderr
, "[%5d]: initgroups %s (%d)\n", getpid(),
934 ZERO_STRUCT(request
);
935 ZERO_STRUCT(response
);
937 strncpy(request
.data
.username
, user
,
938 sizeof(request
.data
.username
) - 1);
940 ret
= winbindd_request_response(WINBINDD_GETGROUPS
, &request
, &response
);
942 if (ret
== NSS_STATUS_SUCCESS
) {
943 int num_gids
= response
.data
.num_entries
;
944 gid_t
*gid_list
= (gid_t
*)response
.extra_data
.data
;
947 fprintf(stderr
, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
948 "and %d gids\n", getpid(),
951 if (gid_list
== NULL
) {
952 ret
= NSS_STATUS_NOTFOUND
;
956 /* Copy group list to client */
958 for (i
= 0; i
< num_gids
; i
++) {
961 fprintf(stderr
, "[%5d]: initgroups %s (%d): "
962 "processing gid %d \n", getpid(),
963 user
, group
, gid_list
[i
]);
966 /* Skip primary group */
968 if (gid_list
[i
] == group
) {
972 /* Filled buffer ? If so, resize. */
974 if (*start
== *size
) {
978 newsize
= 2 * (*size
);
980 if (*size
== limit
) {
983 if (newsize
> limit
) {
988 newgroups
= (gid_t
*)
990 newsize
* sizeof(**groups
));
993 ret
= NSS_STATUS_NOTFOUND
;
1002 (*groups
)[*start
] = gid_list
[i
];
1007 /* Back to your regularly scheduled programming */
1011 fprintf(stderr
, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
1012 user
, nss_err_str(ret
), ret
);
1018 /* return a list of group SIDs for a user SID */
1020 _nss_winbind_getusersids(const char *user_sid
, char **group_sids
,
1022 char *buffer
, size_t buf_size
, int *errnop
)
1025 struct winbindd_request request
;
1026 struct winbindd_response response
;
1029 fprintf(stderr
, "[%5d]: getusersids %s\n", getpid(), user_sid
);
1032 ZERO_STRUCT(request
);
1033 ZERO_STRUCT(response
);
1035 strncpy(request
.data
.sid
, user_sid
,sizeof(request
.data
.sid
) - 1);
1036 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1038 ret
= winbindd_request_response(WINBINDD_GETUSERSIDS
, &request
, &response
);
1040 if (ret
!= NSS_STATUS_SUCCESS
) {
1044 if (buf_size
< response
.length
- sizeof(response
)) {
1045 ret
= NSS_STATUS_TRYAGAIN
;
1046 errno
= *errnop
= ERANGE
;
1050 *num_groups
= response
.data
.num_entries
;
1051 *group_sids
= buffer
;
1052 memcpy(buffer
, response
.extra_data
.data
, response
.length
- sizeof(response
));
1053 errno
= *errnop
= 0;
1056 free_response(&response
);
1061 /* map a user or group name to a SID string */
1063 _nss_winbind_nametosid(const char *name
, char **sid
, char *buffer
,
1064 size_t buflen
, int *errnop
)
1067 struct winbindd_response response
;
1068 struct winbindd_request request
;
1071 fprintf(stderr
, "[%5d]: nametosid %s\n", getpid(), name
);
1074 ZERO_STRUCT(response
);
1075 ZERO_STRUCT(request
);
1077 strncpy(request
.data
.name
.name
, name
,
1078 sizeof(request
.data
.name
.name
) - 1);
1079 request
.data
.name
.name
[sizeof(request
.data
.name
.name
) - 1] = '\0';
1081 ret
= winbindd_request_response(WINBINDD_LOOKUPNAME
, &request
, &response
);
1082 if (ret
!= NSS_STATUS_SUCCESS
) {
1083 *errnop
= errno
= EINVAL
;
1087 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1088 ret
= NSS_STATUS_TRYAGAIN
;
1089 *errnop
= errno
= ERANGE
;
1093 *errnop
= errno
= 0;
1095 strcpy(*sid
, response
.data
.sid
.sid
);
1098 free_response(&response
);
1102 /* map a sid string to a user or group name */
1104 _nss_winbind_sidtoname(const char *sid
, char **name
, char *buffer
,
1105 size_t buflen
, int *errnop
)
1108 struct winbindd_response response
;
1109 struct winbindd_request request
;
1110 static char sep_char
;
1114 fprintf(stderr
, "[%5d]: sidtoname %s\n", getpid(), sid
);
1117 ZERO_STRUCT(response
);
1118 ZERO_STRUCT(request
);
1120 /* we need to fetch the separator first time through */
1122 ret
= winbindd_request_response(WINBINDD_INFO
, &request
, &response
);
1123 if (ret
!= NSS_STATUS_SUCCESS
) {
1124 *errnop
= errno
= EINVAL
;
1128 sep_char
= response
.data
.info
.winbind_separator
;
1129 free_response(&response
);
1133 strncpy(request
.data
.sid
, sid
,
1134 sizeof(request
.data
.sid
) - 1);
1135 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1137 ret
= winbindd_request_response(WINBINDD_LOOKUPSID
, &request
, &response
);
1138 if (ret
!= NSS_STATUS_SUCCESS
) {
1139 *errnop
= errno
= EINVAL
;
1144 strlen(response
.data
.name
.dom_name
) +
1145 strlen(response
.data
.name
.name
) + 2;
1147 if (buflen
< needed
) {
1148 ret
= NSS_STATUS_TRYAGAIN
;
1149 *errnop
= errno
= ERANGE
;
1153 snprintf(buffer
, needed
, "%s%c%s",
1154 response
.data
.name
.dom_name
,
1156 response
.data
.name
.name
);
1159 *errnop
= errno
= 0;
1162 free_response(&response
);
1166 /* map a sid to a uid */
1168 _nss_winbind_sidtouid(const char *sid
, uid_t
*uid
, int *errnop
)
1171 struct winbindd_response response
;
1172 struct winbindd_request request
;
1175 fprintf(stderr
, "[%5d]: sidtouid %s\n", getpid(), sid
);
1178 ZERO_STRUCT(request
);
1179 ZERO_STRUCT(response
);
1181 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1182 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1184 ret
= winbindd_request_response(WINBINDD_SID_TO_UID
, &request
, &response
);
1185 if (ret
!= NSS_STATUS_SUCCESS
) {
1186 *errnop
= errno
= EINVAL
;
1190 *uid
= response
.data
.uid
;
1196 /* map a sid to a gid */
1198 _nss_winbind_sidtogid(const char *sid
, gid_t
*gid
, int *errnop
)
1201 struct winbindd_response response
;
1202 struct winbindd_request request
;
1205 fprintf(stderr
, "[%5d]: sidtogid %s\n", getpid(), sid
);
1208 ZERO_STRUCT(request
);
1209 ZERO_STRUCT(response
);
1211 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1212 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1214 ret
= winbindd_request_response(WINBINDD_SID_TO_GID
, &request
, &response
);
1215 if (ret
!= NSS_STATUS_SUCCESS
) {
1216 *errnop
= errno
= EINVAL
;
1220 *gid
= response
.data
.gid
;
1226 /* map a uid to a SID string */
1228 _nss_winbind_uidtosid(uid_t uid
, char **sid
, char *buffer
,
1229 size_t buflen
, int *errnop
)
1232 struct winbindd_response response
;
1233 struct winbindd_request request
;
1236 fprintf(stderr
, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid
);
1239 ZERO_STRUCT(response
);
1240 ZERO_STRUCT(request
);
1242 request
.data
.uid
= uid
;
1244 ret
= winbindd_request_response(WINBINDD_UID_TO_SID
, &request
, &response
);
1245 if (ret
!= NSS_STATUS_SUCCESS
) {
1246 *errnop
= errno
= EINVAL
;
1250 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1251 ret
= NSS_STATUS_TRYAGAIN
;
1252 *errnop
= errno
= ERANGE
;
1256 *errnop
= errno
= 0;
1258 strcpy(*sid
, response
.data
.sid
.sid
);
1261 free_response(&response
);
1265 /* map a gid to a SID string */
1267 _nss_winbind_gidtosid(gid_t gid
, char **sid
, char *buffer
,
1268 size_t buflen
, int *errnop
)
1271 struct winbindd_response response
;
1272 struct winbindd_request request
;
1275 fprintf(stderr
, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid
);
1278 ZERO_STRUCT(response
);
1279 ZERO_STRUCT(request
);
1281 request
.data
.gid
= gid
;
1283 ret
= winbindd_request_response(WINBINDD_GID_TO_SID
, &request
, &response
);
1284 if (ret
!= NSS_STATUS_SUCCESS
) {
1285 *errnop
= errno
= EINVAL
;
1289 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1290 ret
= NSS_STATUS_TRYAGAIN
;
1291 *errnop
= errno
= ERANGE
;
1295 *errnop
= errno
= 0;
1297 strcpy(*sid
, response
.data
.sid
.sid
);
1300 free_response(&response
);