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"
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
;
70 /* Allocate some space from the nss static buffer. The buffer and buflen
71 are the pointers passed in by the C library to the _nss_ntdom_*
74 static char *get_static(char **buffer
, size_t *buflen
, size_t len
)
78 /* Error check. We return false if things aren't set up right, or
79 there isn't enough buffer space left. */
81 if ((buffer
== NULL
) || (buflen
== NULL
) || (*buflen
< len
)) {
85 /* Return an index into the static buffer */
94 /* I've copied the strtok() replacement function next_token() from
95 lib/util_str.c as I really don't want to have to link in any other
96 objects if I can possibly avoid it. */
98 static bool next_token(char **ptr
,char *buff
,const char *sep
, size_t bufsize
)
104 if (!ptr
) return false;
108 /* default to simple separators */
109 if (!sep
) sep
= " \t\n\r";
111 /* find the first non sep char */
112 while (*s
&& strchr(sep
,*s
)) s
++;
115 if (! *s
) return false;
117 /* copy over the token */
118 for (quoted
= false; len
< bufsize
&& *s
&& (quoted
|| !strchr(sep
,*s
)); s
++) {
127 *ptr
= (*s
) ? s
+1 : s
;
134 /* Fill a pwent structure from a winbindd_response structure. We use
135 the static data passed to us by libc to put strings and stuff in.
136 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
138 static NSS_STATUS
fill_pwent(struct passwd
*result
,
139 struct winbindd_pw
*pw
,
140 char **buffer
, size_t *buflen
)
144 if ((result
->pw_name
=
145 get_static(buffer
, buflen
, strlen(pw
->pw_name
) + 1)) == NULL
) {
149 return NSS_STATUS_TRYAGAIN
;
152 strcpy(result
->pw_name
, pw
->pw_name
);
156 if ((result
->pw_passwd
=
157 get_static(buffer
, buflen
, strlen(pw
->pw_passwd
) + 1)) == NULL
) {
161 return NSS_STATUS_TRYAGAIN
;
164 strcpy(result
->pw_passwd
, pw
->pw_passwd
);
168 result
->pw_uid
= pw
->pw_uid
;
169 result
->pw_gid
= pw
->pw_gid
;
173 if ((result
->pw_gecos
=
174 get_static(buffer
, buflen
, strlen(pw
->pw_gecos
) + 1)) == NULL
) {
178 return NSS_STATUS_TRYAGAIN
;
181 strcpy(result
->pw_gecos
, pw
->pw_gecos
);
185 if ((result
->pw_dir
=
186 get_static(buffer
, buflen
, strlen(pw
->pw_dir
) + 1)) == NULL
) {
190 return NSS_STATUS_TRYAGAIN
;
193 strcpy(result
->pw_dir
, pw
->pw_dir
);
197 if ((result
->pw_shell
=
198 get_static(buffer
, buflen
, strlen(pw
->pw_shell
) + 1)) == NULL
) {
202 return NSS_STATUS_TRYAGAIN
;
205 strcpy(result
->pw_shell
, pw
->pw_shell
);
207 /* The struct passwd for Solaris has some extra fields which must
208 be initialised or nscd crashes. */
210 #if HAVE_PASSWD_PW_COMMENT
211 result
->pw_comment
= "";
214 #if HAVE_PASSWD_PW_AGE
218 return NSS_STATUS_SUCCESS
;
221 /* Fill a grent structure from a winbindd_response structure. We use
222 the static data passed to us by libc to put strings and stuff in.
223 Return NSS_STATUS_TRYAGAIN if we run out of memory. */
225 static NSS_STATUS
fill_grent(struct group
*result
, struct winbindd_gr
*gr
,
226 char *gr_mem
, char **buffer
, size_t *buflen
)
234 if ((result
->gr_name
=
235 get_static(buffer
, buflen
, strlen(gr
->gr_name
) + 1)) == NULL
) {
239 return NSS_STATUS_TRYAGAIN
;
242 strcpy(result
->gr_name
, gr
->gr_name
);
246 if ((result
->gr_passwd
=
247 get_static(buffer
, buflen
, strlen(gr
->gr_passwd
) + 1)) == NULL
) {
251 return NSS_STATUS_TRYAGAIN
;
254 strcpy(result
->gr_passwd
, gr
->gr_passwd
);
258 result
->gr_gid
= gr
->gr_gid
;
260 /* Group membership */
262 if ((gr
->num_gr_mem
< 0) || !gr_mem
) {
266 /* this next value is a pointer to a pointer so let's align it */
268 /* Calculate number of extra bytes needed to align on pointer size boundry */
269 if ((i
= (unsigned long)(*buffer
) % sizeof(char*)) != 0)
270 i
= sizeof(char*) - i
;
272 if ((tst
= get_static(buffer
, buflen
, ((gr
->num_gr_mem
+ 1) *
273 sizeof(char *)+i
))) == NULL
) {
277 return NSS_STATUS_TRYAGAIN
;
279 result
->gr_mem
= (char **)(tst
+ i
);
281 if (gr
->num_gr_mem
== 0) {
285 *(result
->gr_mem
) = NULL
;
286 return NSS_STATUS_SUCCESS
;
289 /* Start looking at extra data */
293 while(next_token((char **)&gr_mem
, name
, ",", sizeof(fstring
))) {
295 /* Allocate space for member */
297 if (((result
->gr_mem
)[i
] =
298 get_static(buffer
, buflen
, strlen(name
) + 1)) == NULL
) {
302 return NSS_STATUS_TRYAGAIN
;
305 strcpy((result
->gr_mem
)[i
], name
);
311 (result
->gr_mem
)[i
] = NULL
;
313 return NSS_STATUS_SUCCESS
;
320 static struct winbindd_response getpwent_response
;
322 static int ndx_pw_cache
; /* Current index into pwd cache */
323 static int num_pw_cache
; /* Current size of pwd cache */
325 /* Rewind "file pointer" to start of ntdom password database */
328 _nss_winbind_setpwent(void)
332 fprintf(stderr
, "[%5d]: setpwent\n", getpid());
335 if (num_pw_cache
> 0) {
336 ndx_pw_cache
= num_pw_cache
= 0;
337 winbindd_free_response(&getpwent_response
);
340 ret
= winbindd_request_response(WINBINDD_SETPWENT
, NULL
, NULL
);
342 fprintf(stderr
, "[%5d]: setpwent returns %s (%d)\n", getpid(),
343 nss_err_str(ret
), ret
);
348 /* Close ntdom password database "file pointer" */
351 _nss_winbind_endpwent(void)
355 fprintf(stderr
, "[%5d]: endpwent\n", getpid());
358 if (num_pw_cache
> 0) {
359 ndx_pw_cache
= num_pw_cache
= 0;
360 winbindd_free_response(&getpwent_response
);
363 ret
= winbindd_request_response(WINBINDD_ENDPWENT
, NULL
, NULL
);
365 fprintf(stderr
, "[%5d]: endpwent returns %s (%d)\n", getpid(),
366 nss_err_str(ret
), ret
);
371 /* Fetch the next password entry from ntdom password database */
374 _nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
375 size_t buflen
, int *errnop
)
378 struct winbindd_request request
;
379 static int called_again
;
382 fprintf(stderr
, "[%5d]: getpwent\n", getpid());
385 /* Return an entry from the cache if we have one, or if we are
386 called again because we exceeded our static buffer. */
388 if ((ndx_pw_cache
< num_pw_cache
) || called_again
) {
392 /* Else call winbindd to get a bunch of entries */
394 if (num_pw_cache
> 0) {
395 winbindd_free_response(&getpwent_response
);
398 ZERO_STRUCT(request
);
399 ZERO_STRUCT(getpwent_response
);
401 request
.data
.num_entries
= MAX_GETPWENT_USERS
;
403 ret
= winbindd_request_response(WINBINDD_GETPWENT
, &request
,
406 if (ret
== NSS_STATUS_SUCCESS
) {
407 struct winbindd_pw
*pw_cache
;
412 num_pw_cache
= getpwent_response
.data
.num_entries
;
414 /* Return a result */
418 pw_cache
= (struct winbindd_pw
*)
419 getpwent_response
.extra_data
.data
;
421 /* Check data is valid */
423 if (pw_cache
== NULL
) {
424 ret
= NSS_STATUS_NOTFOUND
;
428 ret
= fill_pwent(result
, &pw_cache
[ndx_pw_cache
],
431 /* Out of memory - try again */
433 if (ret
== NSS_STATUS_TRYAGAIN
) {
435 *errnop
= errno
= ERANGE
;
440 called_again
= false;
443 /* If we've finished with this lot of results free cache */
445 if (ndx_pw_cache
== num_pw_cache
) {
446 ndx_pw_cache
= num_pw_cache
= 0;
447 winbindd_free_response(&getpwent_response
);
452 fprintf(stderr
, "[%5d]: getpwent returns %s (%d)\n", getpid(),
453 nss_err_str(ret
), ret
);
458 /* Return passwd struct from uid */
461 _nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
, char *buffer
,
462 size_t buflen
, int *errnop
)
465 static struct winbindd_response response
;
466 struct winbindd_request request
;
467 static int keep_response
=0;
470 fprintf(stderr
, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid
);
473 /* If our static buffer needs to be expanded we are called again */
474 if (!keep_response
) {
476 /* Call for the first time */
478 ZERO_STRUCT(response
);
479 ZERO_STRUCT(request
);
481 request
.data
.uid
= uid
;
483 ret
= winbindd_request_response(WINBINDD_GETPWUID
, &request
, &response
);
485 if (ret
== NSS_STATUS_SUCCESS
) {
486 ret
= fill_pwent(result
, &response
.data
.pw
,
489 if (ret
== NSS_STATUS_TRYAGAIN
) {
490 keep_response
= true;
491 *errnop
= errno
= ERANGE
;
498 /* We've been called again */
500 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
502 if (ret
== NSS_STATUS_TRYAGAIN
) {
503 keep_response
= true;
504 *errnop
= errno
= ERANGE
;
508 keep_response
= false;
512 winbindd_free_response(&response
);
516 fprintf(stderr
, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(),
517 (unsigned int)uid
, nss_err_str(ret
), ret
);
522 /* Return passwd struct from username */
524 _nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
, char *buffer
,
525 size_t buflen
, int *errnop
)
528 static struct winbindd_response response
;
529 struct winbindd_request request
;
530 static int keep_response
;
533 fprintf(stderr
, "[%5d]: getpwnam %s\n", getpid(), name
);
536 /* If our static buffer needs to be expanded we are called again */
538 if (!keep_response
) {
540 /* Call for the first time */
542 ZERO_STRUCT(response
);
543 ZERO_STRUCT(request
);
545 strncpy(request
.data
.username
, name
,
546 sizeof(request
.data
.username
) - 1);
547 request
.data
.username
548 [sizeof(request
.data
.username
) - 1] = '\0';
550 ret
= winbindd_request_response(WINBINDD_GETPWNAM
, &request
, &response
);
552 if (ret
== NSS_STATUS_SUCCESS
) {
553 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
,
556 if (ret
== NSS_STATUS_TRYAGAIN
) {
557 keep_response
= true;
558 *errnop
= errno
= ERANGE
;
565 /* We've been called again */
567 ret
= fill_pwent(result
, &response
.data
.pw
, &buffer
, &buflen
);
569 if (ret
== NSS_STATUS_TRYAGAIN
) {
570 keep_response
= true;
571 *errnop
= errno
= ERANGE
;
575 keep_response
= false;
579 winbindd_free_response(&response
);
582 fprintf(stderr
, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(),
583 name
, nss_err_str(ret
), ret
);
589 * NSS group functions
592 static struct winbindd_response getgrent_response
;
594 static int ndx_gr_cache
; /* Current index into grp cache */
595 static int num_gr_cache
; /* Current size of grp cache */
597 /* Rewind "file pointer" to start of ntdom group database */
600 _nss_winbind_setgrent(void)
604 fprintf(stderr
, "[%5d]: setgrent\n", getpid());
607 if (num_gr_cache
> 0) {
608 ndx_gr_cache
= num_gr_cache
= 0;
609 winbindd_free_response(&getgrent_response
);
612 ret
= winbindd_request_response(WINBINDD_SETGRENT
, NULL
, NULL
);
614 fprintf(stderr
, "[%5d]: setgrent returns %s (%d)\n", getpid(),
615 nss_err_str(ret
), ret
);
620 /* Close "file pointer" for ntdom group database */
623 _nss_winbind_endgrent(void)
627 fprintf(stderr
, "[%5d]: endgrent\n", getpid());
630 if (num_gr_cache
> 0) {
631 ndx_gr_cache
= num_gr_cache
= 0;
632 winbindd_free_response(&getgrent_response
);
635 ret
= winbindd_request_response(WINBINDD_ENDGRENT
, NULL
, NULL
);
637 fprintf(stderr
, "[%5d]: endgrent returns %s (%d)\n", getpid(),
638 nss_err_str(ret
), ret
);
643 /* Get next entry from ntdom group database */
646 winbind_getgrent(enum winbindd_cmd cmd
,
647 struct group
*result
,
648 char *buffer
, size_t buflen
, int *errnop
)
651 static struct winbindd_request request
;
652 static int called_again
;
656 fprintf(stderr
, "[%5d]: getgrent\n", getpid());
659 /* Return an entry from the cache if we have one, or if we are
660 called again because we exceeded our static buffer. */
662 if ((ndx_gr_cache
< num_gr_cache
) || called_again
) {
666 /* Else call winbindd to get a bunch of entries */
668 if (num_gr_cache
> 0) {
669 winbindd_free_response(&getgrent_response
);
672 ZERO_STRUCT(request
);
673 ZERO_STRUCT(getgrent_response
);
675 request
.data
.num_entries
= MAX_GETGRENT_USERS
;
677 ret
= winbindd_request_response(cmd
, &request
,
680 if (ret
== NSS_STATUS_SUCCESS
) {
681 struct winbindd_gr
*gr_cache
;
687 num_gr_cache
= getgrent_response
.data
.num_entries
;
689 /* Return a result */
693 gr_cache
= (struct winbindd_gr
*)
694 getgrent_response
.extra_data
.data
;
696 /* Check data is valid */
698 if (gr_cache
== NULL
) {
699 ret
= NSS_STATUS_NOTFOUND
;
703 /* Fill group membership. The offset into the extra data
704 for the group membership is the reported offset plus the
705 size of all the winbindd_gr records returned. */
707 mem_ofs
= gr_cache
[ndx_gr_cache
].gr_mem_ofs
+
708 num_gr_cache
* sizeof(struct winbindd_gr
);
710 ret
= fill_grent(result
, &gr_cache
[ndx_gr_cache
],
711 ((char *)getgrent_response
.extra_data
.data
)+mem_ofs
,
714 /* Out of memory - try again */
716 if (ret
== NSS_STATUS_TRYAGAIN
) {
718 *errnop
= errno
= ERANGE
;
723 called_again
= false;
726 /* If we've finished with this lot of results free cache */
728 if (ndx_gr_cache
== num_gr_cache
) {
729 ndx_gr_cache
= num_gr_cache
= 0;
730 winbindd_free_response(&getgrent_response
);
735 fprintf(stderr
, "[%5d]: getgrent returns %s (%d)\n", getpid(),
736 nss_err_str(ret
), ret
);
743 _nss_winbind_getgrent_r(struct group
*result
,
744 char *buffer
, size_t buflen
, int *errnop
)
746 return winbind_getgrent(WINBINDD_GETGRENT
, result
, buffer
, buflen
, errnop
);
750 _nss_winbind_getgrlst_r(struct group
*result
,
751 char *buffer
, size_t buflen
, int *errnop
)
753 return winbind_getgrent(WINBINDD_GETGRLST
, result
, buffer
, buflen
, errnop
);
756 /* Return group struct from group name */
759 _nss_winbind_getgrnam_r(const char *name
,
760 struct group
*result
, char *buffer
,
761 size_t buflen
, int *errnop
)
764 static struct winbindd_response response
;
765 struct winbindd_request request
;
766 static int keep_response
;
769 fprintf(stderr
, "[%5d]: getgrnam %s\n", getpid(), name
);
772 /* If our static buffer needs to be expanded we are called again */
774 if (!keep_response
) {
776 /* Call for the first time */
778 ZERO_STRUCT(request
);
779 ZERO_STRUCT(response
);
781 strncpy(request
.data
.groupname
, name
,
782 sizeof(request
.data
.groupname
));
783 request
.data
.groupname
784 [sizeof(request
.data
.groupname
) - 1] = '\0';
786 ret
= winbindd_request_response(WINBINDD_GETGRNAM
, &request
, &response
);
788 if (ret
== NSS_STATUS_SUCCESS
) {
789 ret
= fill_grent(result
, &response
.data
.gr
,
790 (char *)response
.extra_data
.data
,
793 if (ret
== NSS_STATUS_TRYAGAIN
) {
794 keep_response
= true;
795 *errnop
= errno
= ERANGE
;
802 /* We've been called again */
804 ret
= fill_grent(result
, &response
.data
.gr
,
805 (char *)response
.extra_data
.data
, &buffer
,
808 if (ret
== NSS_STATUS_TRYAGAIN
) {
809 keep_response
= true;
810 *errnop
= errno
= ERANGE
;
814 keep_response
= false;
818 winbindd_free_response(&response
);
821 fprintf(stderr
, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(),
822 name
, nss_err_str(ret
), ret
);
827 /* Return group struct from gid */
830 _nss_winbind_getgrgid_r(gid_t gid
,
831 struct group
*result
, char *buffer
,
832 size_t buflen
, int *errnop
)
835 static struct winbindd_response response
;
836 struct winbindd_request request
;
837 static int keep_response
;
840 fprintf(stderr
, "[%5d]: getgrgid %d\n", getpid(), gid
);
843 /* If our static buffer needs to be expanded we are called again */
845 if (!keep_response
) {
847 /* Call for the first time */
849 ZERO_STRUCT(request
);
850 ZERO_STRUCT(response
);
852 request
.data
.gid
= gid
;
854 ret
= winbindd_request_response(WINBINDD_GETGRGID
, &request
, &response
);
856 if (ret
== NSS_STATUS_SUCCESS
) {
858 ret
= fill_grent(result
, &response
.data
.gr
,
859 (char *)response
.extra_data
.data
,
862 if (ret
== NSS_STATUS_TRYAGAIN
) {
863 keep_response
= true;
864 *errnop
= errno
= ERANGE
;
871 /* We've been called again */
873 ret
= fill_grent(result
, &response
.data
.gr
,
874 (char *)response
.extra_data
.data
, &buffer
,
877 if (ret
== NSS_STATUS_TRYAGAIN
) {
878 keep_response
= true;
879 *errnop
= errno
= ERANGE
;
883 keep_response
= false;
887 winbindd_free_response(&response
);
890 fprintf(stderr
, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(),
891 (unsigned int)gid
, nss_err_str(ret
), ret
);
896 /* Initialise supplementary groups */
899 _nss_winbind_initgroups_dyn(char *user
, gid_t group
, long int *start
,
900 long int *size
, gid_t
**groups
, long int limit
,
904 struct winbindd_request request
;
905 struct winbindd_response response
;
909 fprintf(stderr
, "[%5d]: initgroups %s (%d)\n", getpid(),
913 ZERO_STRUCT(request
);
914 ZERO_STRUCT(response
);
916 strncpy(request
.data
.username
, user
,
917 sizeof(request
.data
.username
) - 1);
919 ret
= winbindd_request_response(WINBINDD_GETGROUPS
, &request
, &response
);
921 if (ret
== NSS_STATUS_SUCCESS
) {
922 int num_gids
= response
.data
.num_entries
;
923 gid_t
*gid_list
= (gid_t
*)response
.extra_data
.data
;
926 fprintf(stderr
, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS "
927 "and %d gids\n", getpid(),
930 if (gid_list
== NULL
) {
931 ret
= NSS_STATUS_NOTFOUND
;
935 /* Copy group list to client */
937 for (i
= 0; i
< num_gids
; i
++) {
940 fprintf(stderr
, "[%5d]: initgroups %s (%d): "
941 "processing gid %d \n", getpid(),
942 user
, group
, gid_list
[i
]);
945 /* Skip primary group */
947 if (gid_list
[i
] == group
) {
951 /* Filled buffer ? If so, resize. */
953 if (*start
== *size
) {
957 newsize
= 2 * (*size
);
959 if (*size
== limit
) {
962 if (newsize
> limit
) {
967 newgroups
= (gid_t
*)
969 newsize
* sizeof(**groups
));
972 ret
= NSS_STATUS_NOTFOUND
;
981 (*groups
)[*start
] = gid_list
[i
];
986 /* Back to your regularly scheduled programming */
990 fprintf(stderr
, "[%5d]: initgroups %s returns %s (%d)\n", getpid(),
991 user
, nss_err_str(ret
), ret
);
997 /* return a list of group SIDs for a user SID */
999 _nss_winbind_getusersids(const char *user_sid
, char **group_sids
,
1001 char *buffer
, size_t buf_size
, int *errnop
)
1004 struct winbindd_request request
;
1005 struct winbindd_response response
;
1008 fprintf(stderr
, "[%5d]: getusersids %s\n", getpid(), user_sid
);
1011 ZERO_STRUCT(request
);
1012 ZERO_STRUCT(response
);
1014 strncpy(request
.data
.sid
, user_sid
,sizeof(request
.data
.sid
) - 1);
1015 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1017 ret
= winbindd_request_response(WINBINDD_GETUSERSIDS
, &request
, &response
);
1019 if (ret
!= NSS_STATUS_SUCCESS
) {
1023 if (buf_size
< response
.length
- sizeof(response
)) {
1024 ret
= NSS_STATUS_TRYAGAIN
;
1025 errno
= *errnop
= ERANGE
;
1029 *num_groups
= response
.data
.num_entries
;
1030 *group_sids
= buffer
;
1031 memcpy(buffer
, response
.extra_data
.data
, response
.length
- sizeof(response
));
1032 errno
= *errnop
= 0;
1035 winbindd_free_response(&response
);
1040 /* map a user or group name to a SID string */
1042 _nss_winbind_nametosid(const char *name
, char **sid
, char *buffer
,
1043 size_t buflen
, int *errnop
)
1046 struct winbindd_response response
;
1047 struct winbindd_request request
;
1050 fprintf(stderr
, "[%5d]: nametosid %s\n", getpid(), name
);
1053 ZERO_STRUCT(response
);
1054 ZERO_STRUCT(request
);
1056 strncpy(request
.data
.name
.name
, name
,
1057 sizeof(request
.data
.name
.name
) - 1);
1058 request
.data
.name
.name
[sizeof(request
.data
.name
.name
) - 1] = '\0';
1060 ret
= winbindd_request_response(WINBINDD_LOOKUPNAME
, &request
, &response
);
1061 if (ret
!= NSS_STATUS_SUCCESS
) {
1062 *errnop
= errno
= EINVAL
;
1066 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1067 ret
= NSS_STATUS_TRYAGAIN
;
1068 *errnop
= errno
= ERANGE
;
1072 *errnop
= errno
= 0;
1074 strcpy(*sid
, response
.data
.sid
.sid
);
1077 winbindd_free_response(&response
);
1081 /* map a sid string to a user or group name */
1083 _nss_winbind_sidtoname(const char *sid
, char **name
, char *buffer
,
1084 size_t buflen
, int *errnop
)
1087 struct winbindd_response response
;
1088 struct winbindd_request request
;
1089 static char sep_char
;
1093 fprintf(stderr
, "[%5d]: sidtoname %s\n", getpid(), sid
);
1096 ZERO_STRUCT(response
);
1097 ZERO_STRUCT(request
);
1099 /* we need to fetch the separator first time through */
1101 ret
= winbindd_request_response(WINBINDD_INFO
, &request
, &response
);
1102 if (ret
!= NSS_STATUS_SUCCESS
) {
1103 *errnop
= errno
= EINVAL
;
1107 sep_char
= response
.data
.info
.winbind_separator
;
1108 winbindd_free_response(&response
);
1112 strncpy(request
.data
.sid
, sid
,
1113 sizeof(request
.data
.sid
) - 1);
1114 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1116 ret
= winbindd_request_response(WINBINDD_LOOKUPSID
, &request
, &response
);
1117 if (ret
!= NSS_STATUS_SUCCESS
) {
1118 *errnop
= errno
= EINVAL
;
1123 strlen(response
.data
.name
.dom_name
) +
1124 strlen(response
.data
.name
.name
) + 2;
1126 if (buflen
< needed
) {
1127 ret
= NSS_STATUS_TRYAGAIN
;
1128 *errnop
= errno
= ERANGE
;
1132 snprintf(buffer
, needed
, "%s%c%s",
1133 response
.data
.name
.dom_name
,
1135 response
.data
.name
.name
);
1138 *errnop
= errno
= 0;
1141 winbindd_free_response(&response
);
1145 /* map a sid to a uid */
1147 _nss_winbind_sidtouid(const char *sid
, uid_t
*uid
, int *errnop
)
1150 struct winbindd_response response
;
1151 struct winbindd_request request
;
1154 fprintf(stderr
, "[%5d]: sidtouid %s\n", getpid(), sid
);
1157 ZERO_STRUCT(request
);
1158 ZERO_STRUCT(response
);
1160 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1161 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1163 ret
= winbindd_request_response(WINBINDD_SID_TO_UID
, &request
, &response
);
1164 if (ret
!= NSS_STATUS_SUCCESS
) {
1165 *errnop
= errno
= EINVAL
;
1169 *uid
= response
.data
.uid
;
1175 /* map a sid to a gid */
1177 _nss_winbind_sidtogid(const char *sid
, gid_t
*gid
, int *errnop
)
1180 struct winbindd_response response
;
1181 struct winbindd_request request
;
1184 fprintf(stderr
, "[%5d]: sidtogid %s\n", getpid(), sid
);
1187 ZERO_STRUCT(request
);
1188 ZERO_STRUCT(response
);
1190 strncpy(request
.data
.sid
, sid
, sizeof(request
.data
.sid
) - 1);
1191 request
.data
.sid
[sizeof(request
.data
.sid
) - 1] = '\0';
1193 ret
= winbindd_request_response(WINBINDD_SID_TO_GID
, &request
, &response
);
1194 if (ret
!= NSS_STATUS_SUCCESS
) {
1195 *errnop
= errno
= EINVAL
;
1199 *gid
= response
.data
.gid
;
1205 /* map a uid to a SID string */
1207 _nss_winbind_uidtosid(uid_t uid
, char **sid
, char *buffer
,
1208 size_t buflen
, int *errnop
)
1211 struct winbindd_response response
;
1212 struct winbindd_request request
;
1215 fprintf(stderr
, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid
);
1218 ZERO_STRUCT(response
);
1219 ZERO_STRUCT(request
);
1221 request
.data
.uid
= uid
;
1223 ret
= winbindd_request_response(WINBINDD_UID_TO_SID
, &request
, &response
);
1224 if (ret
!= NSS_STATUS_SUCCESS
) {
1225 *errnop
= errno
= EINVAL
;
1229 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1230 ret
= NSS_STATUS_TRYAGAIN
;
1231 *errnop
= errno
= ERANGE
;
1235 *errnop
= errno
= 0;
1237 strcpy(*sid
, response
.data
.sid
.sid
);
1240 winbindd_free_response(&response
);
1244 /* map a gid to a SID string */
1246 _nss_winbind_gidtosid(gid_t gid
, char **sid
, char *buffer
,
1247 size_t buflen
, int *errnop
)
1250 struct winbindd_response response
;
1251 struct winbindd_request request
;
1254 fprintf(stderr
, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid
);
1257 ZERO_STRUCT(response
);
1258 ZERO_STRUCT(request
);
1260 request
.data
.gid
= gid
;
1262 ret
= winbindd_request_response(WINBINDD_GID_TO_SID
, &request
, &response
);
1263 if (ret
!= NSS_STATUS_SUCCESS
) {
1264 *errnop
= errno
= EINVAL
;
1268 if (buflen
< strlen(response
.data
.sid
.sid
)+1) {
1269 ret
= NSS_STATUS_TRYAGAIN
;
1270 *errnop
= errno
= ERANGE
;
1274 *errnop
= errno
= 0;
1276 strcpy(*sid
, response
.data
.sid
.sid
);
1279 winbindd_free_response(&response
);