2 Unix SMB/Netbios implementation.
5 Windows NT Domain nsswitch module
7 Copyright (C) Tim Potter 2000
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with this library; if not, write to the
21 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
25 #include "winbind_nss_config.h"
26 #include "winbindd_nss.h"
28 /* prototypes from common.c */
29 void init_request(struct winbindd_request
*req
,int rq_type
);
30 int write_sock(void *buffer
, int count
);
31 int read_reply(struct winbindd_response
*response
);
34 /* Allocate some space from the nss static buffer. The buffer and buflen
35 are the pointers passed in by the C library to the _nss_ntdom_*
38 static char *get_static(char **buffer
, int *buflen
, int len
)
42 /* Error check. We return false if things aren't set up right, or
43 there isn't enough buffer space left. */
45 if ((buffer
== NULL
) || (buflen
== NULL
) || (*buflen
< len
)) {
49 /* Return an index into the static buffer */
58 /* I've copied the strtok() replacement function next_token() from
59 lib/util_str.c as I really don't want to have to link in any other
60 objects if I can possibly avoid it. */
62 #ifdef strchr /* Aargh! This points at multibyte_strchr(). )-: */
66 static char *last_ptr
= NULL
;
68 BOOL
next_token(char **ptr
, char *buff
, char *sep
, size_t bufsize
)
74 if (!ptr
) ptr
= &last_ptr
;
75 if (!ptr
) return(False
);
79 /* default to simple separators */
80 if (!sep
) sep
= " \t\n\r";
82 /* find the first non sep char */
83 while(*s
&& strchr(sep
,*s
)) s
++;
86 if (! *s
) return(False
);
88 /* copy over the token */
90 len
< bufsize
&& *s
&& (quoted
|| !strchr(sep
,*s
));
101 *ptr
= (*s
) ? s
+1 : s
;
109 /* handle simple types of requests */
110 static enum nss_status
generic_request(int req_type
,
111 struct winbindd_request
*request
,
112 struct winbindd_response
*response
)
114 struct winbindd_request lrequest
;
115 struct winbindd_response lresponse
;
117 if (!response
) response
= &lresponse
;
118 if (!request
) request
= &lrequest
;
120 /* Fill in request and send down pipe */
121 init_request(request
, req_type
);
123 if (write_sock(request
, sizeof(*request
)) == -1) {
124 return NSS_STATUS_UNAVAIL
;
128 if (read_reply(response
) == -1) {
129 return NSS_STATUS_UNAVAIL
;
132 /* Copy reply data from socket */
133 if (response
->result
!= WINBINDD_OK
) {
134 return NSS_STATUS_NOTFOUND
;
137 return NSS_STATUS_SUCCESS
;
140 /* Fill a pwent structure from a winbindd_response structure. We use
141 the static data passed to us by libc to put strings and stuff in.
142 Return errno = ERANGE and NSS_STATUS_TRYAGAIN if we run out of
145 static enum nss_status
fill_pwent(struct passwd
*result
,
146 struct winbindd_response
*response
,
147 char **buffer
, int *buflen
, int *errnop
)
149 struct winbindd_pw
*pw
= &response
->data
.pw
;
153 if ((result
->pw_name
=
154 get_static(buffer
, buflen
, strlen(pw
->pw_name
) + 1)) == NULL
) {
159 return NSS_STATUS_TRYAGAIN
;
162 strcpy(result
->pw_name
, pw
->pw_name
);
166 if ((result
->pw_passwd
=
167 get_static(buffer
, buflen
, strlen(pw
->pw_passwd
) + 1)) == NULL
) {
172 return NSS_STATUS_TRYAGAIN
;
175 strcpy(result
->pw_passwd
, pw
->pw_passwd
);
179 result
->pw_uid
= pw
->pw_uid
;
180 result
->pw_gid
= pw
->pw_gid
;
184 if ((result
->pw_gecos
=
185 get_static(buffer
, buflen
, strlen(pw
->pw_gecos
) + 1)) == NULL
) {
190 return NSS_STATUS_TRYAGAIN
;
193 strcpy(result
->pw_gecos
, pw
->pw_gecos
);
197 if ((result
->pw_dir
=
198 get_static(buffer
, buflen
, strlen(pw
->pw_dir
) + 1)) == NULL
) {
203 return NSS_STATUS_TRYAGAIN
;
206 strcpy(result
->pw_dir
, pw
->pw_dir
);
210 if ((result
->pw_shell
=
211 get_static(buffer
, buflen
, strlen(pw
->pw_shell
) + 1)) == NULL
) {
216 return NSS_STATUS_TRYAGAIN
;
219 strcpy(result
->pw_shell
, pw
->pw_shell
);
221 return NSS_STATUS_SUCCESS
;
224 /* Fill a grent structure from a winbindd_response structure. We use
225 the static data passed to us by libc to put strings and stuff in.
226 Return errno = ERANGE and NSS_STATUS_TRYAGAIN if we run out of
229 static int fill_grent(struct group
*result
,
230 struct winbindd_response
*response
,
231 char **buffer
, int *buflen
, int *errnop
)
233 struct winbindd_gr
*gr
= &response
->data
.gr
;
239 if ((result
->gr_name
=
240 get_static(buffer
, buflen
, strlen(gr
->gr_name
) + 1)) == NULL
) {
245 return NSS_STATUS_TRYAGAIN
;
248 strcpy(result
->gr_name
, gr
->gr_name
);
252 if ((result
->gr_passwd
=
253 get_static(buffer
, buflen
, strlen(gr
->gr_passwd
) + 1)) == NULL
) {
258 return NSS_STATUS_TRYAGAIN
;
261 strcpy(result
->gr_passwd
, gr
->gr_passwd
);
265 result
->gr_gid
= gr
->gr_gid
;
267 /* Group membership */
269 if ((gr
->num_gr_mem
< 0) || !response
->extra_data
) {
273 if ((result
->gr_mem
=
274 (char **)get_static(buffer
, buflen
, (gr
->num_gr_mem
+ 1) *
275 sizeof(char *))) == NULL
) {
280 return NSS_STATUS_TRYAGAIN
;
283 if (gr
->num_gr_mem
== 0) {
287 *(result
->gr_mem
) = NULL
;
288 return NSS_STATUS_SUCCESS
;
291 /* Start looking at extra data */
295 while(next_token(&response
->extra_data
, name
, ",", sizeof(fstring
))) {
297 /* Allocate space for member */
299 if (((result
->gr_mem
)[i
] =
300 get_static(buffer
, buflen
, strlen(name
) + 1)) == NULL
) {
305 return NSS_STATUS_TRYAGAIN
;
308 strcpy((result
->gr_mem
)[i
], name
);
314 (result
->gr_mem
)[i
] = NULL
;
316 return NSS_STATUS_SUCCESS
;
323 /* Rewind "file pointer" to start of ntdom password database */
326 _nss_winbind_setpwent(void)
328 return generic_request(WINBINDD_SETPWENT
, NULL
, NULL
);
331 /* Close ntdom password database "file pointer" */
334 _nss_winbind_endpwent(void)
336 return generic_request(WINBINDD_ENDPWENT
, NULL
, NULL
);
339 /* Fetch the next password entry from ntdom password database */
342 _nss_winbind_getpwent_r(struct passwd
*result
, char *buffer
,
343 size_t buflen
, int *errnop
)
346 struct winbindd_response response
;
348 ret
= generic_request(WINBINDD_GETPWENT
, NULL
, &response
);
349 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
351 return fill_pwent(result
, &response
, &buffer
, &buflen
, errnop
);
354 /* Return passwd struct from uid */
357 _nss_winbind_getpwuid_r(uid_t uid
, struct passwd
*result
, char *buffer
,
358 size_t buflen
, int *errnop
)
361 struct winbindd_response response
;
362 struct winbindd_request request
;
364 request
.data
.uid
= uid
;
366 ret
= generic_request(WINBINDD_GETPWNAM_FROM_UID
, &request
, &response
);
367 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
369 return fill_pwent(result
, &response
, &buffer
, &buflen
, errnop
);
372 /* Return passwd struct from username */
375 _nss_winbind_getpwnam_r(const char *name
, struct passwd
*result
, char *buffer
,
376 size_t buflen
, int *errnop
)
379 struct winbindd_response response
;
380 struct winbindd_request request
;
382 strncpy(request
.data
.username
, name
, sizeof(request
.data
.username
) - 1);
383 request
.data
.username
[sizeof(request
.data
.username
) - 1] = '\0';
385 ret
= generic_request(WINBINDD_GETPWNAM_FROM_USER
, &request
, &response
);
386 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
388 return fill_pwent(result
, &response
, &buffer
, &buflen
, errnop
);
392 * NSS group functions
395 /* Rewind "file pointer" to start of ntdom group database */
398 _nss_winbind_setgrent(void)
400 return generic_request(WINBINDD_SETGRENT
, NULL
, NULL
);
403 /* Close "file pointer" for ntdom group database */
406 _nss_winbind_endgrent(void)
408 return generic_request(WINBINDD_ENDGRENT
, NULL
, NULL
);
413 /* Get next entry from ntdom group database */
416 _nss_winbind_getgrent_r(struct group
*result
,
417 char *buffer
, size_t buflen
, int *errnop
)
420 struct winbindd_response response
;
422 ret
= generic_request(WINBINDD_GETGRENT
, NULL
, &response
);
423 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
425 return fill_grent(result
, &response
, &buffer
, &buflen
, errnop
);
428 /* Return group struct from group name */
431 _nss_winbind_getgrnam_r(const char *name
,
432 struct group
*result
, char *buffer
,
433 size_t buflen
, int *errnop
)
436 struct winbindd_response response
;
437 struct winbindd_request request
;
439 strncpy(request
.data
.groupname
, name
, sizeof(request
.data
.groupname
));
440 request
.data
.groupname
[sizeof(request
.data
.groupname
) - 1] = '\0';
442 ret
= generic_request(WINBINDD_GETGRNAM_FROM_GROUP
, &request
, &response
);
443 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
445 return fill_grent(result
, &response
, &buffer
, &buflen
, errnop
);
448 /* Return group struct from gid */
451 _nss_winbind_getgrgid_r(gid_t gid
,
452 struct group
*result
, char *buffer
,
453 size_t buflen
, int *errnop
)
456 struct winbindd_response response
;
457 struct winbindd_request request
;
459 request
.data
.gid
= gid
;
461 ret
= generic_request(WINBINDD_GETGRNAM_FROM_GID
, &request
, &response
);
462 if (ret
!= NSS_STATUS_SUCCESS
) return ret
;
464 return fill_grent(result
, &response
, &buffer
, &buflen
, errnop
);