Converted to call lib/wins_srv.c:wins_srv_ip() instead of lp_wins_server()
[Samba.git] / source3 / nsswitch / winbind_nss.c
blob78485aa05e3620f82e7ac691556573853ac4bcf2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.0
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_*
36 functions. */
38 static char *get_static(char **buffer, int *buflen, int len)
40 char *result;
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)) {
46 return NULL;
49 /* Return an index into the static buffer */
51 result = *buffer;
52 *buffer += len;
53 *buflen -= len;
55 return result;
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(). )-: */
63 #undef strchr
64 #endif
66 static char *last_ptr = NULL;
68 BOOL next_token(char **ptr, char *buff, char *sep, size_t bufsize)
70 char *s;
71 BOOL quoted;
72 size_t len=1;
74 if (!ptr) ptr = &last_ptr;
75 if (!ptr) return(False);
77 s = *ptr;
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++;
85 /* nothing left? */
86 if (! *s) return(False);
88 /* copy over the token */
89 for (quoted = False;
90 len < bufsize && *s && (quoted || !strchr(sep,*s));
91 s++) {
93 if (*s == '\"') {
94 quoted = !quoted;
95 } else {
96 len++;
97 *buff++ = *s;
101 *ptr = (*s) ? s+1 : s;
102 *buff = 0;
103 last_ptr = *ptr;
105 return(True);
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;
127 /* Wait for reply */
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
143 memory. */
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;
151 /* User name */
153 if ((result->pw_name =
154 get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) {
156 /* Out of memory */
158 *errnop = ERANGE;
159 return NSS_STATUS_TRYAGAIN;
162 strcpy(result->pw_name, pw->pw_name);
164 /* Password */
166 if ((result->pw_passwd =
167 get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) {
169 /* Out of memory */
171 *errnop = ERANGE;
172 return NSS_STATUS_TRYAGAIN;
175 strcpy(result->pw_passwd, pw->pw_passwd);
177 /* [ug]id */
179 result->pw_uid = pw->pw_uid;
180 result->pw_gid = pw->pw_gid;
182 /* GECOS */
184 if ((result->pw_gecos =
185 get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) {
187 /* Out of memory */
189 *errnop = ERANGE;
190 return NSS_STATUS_TRYAGAIN;
193 strcpy(result->pw_gecos, pw->pw_gecos);
195 /* Home directory */
197 if ((result->pw_dir =
198 get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) {
200 /* Out of memory */
202 *errnop = ERANGE;
203 return NSS_STATUS_TRYAGAIN;
206 strcpy(result->pw_dir, pw->pw_dir);
208 /* Logon shell */
210 if ((result->pw_shell =
211 get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) {
213 /* Out of memory */
215 *errnop = ERANGE;
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
227 memory. */
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;
234 fstring name;
235 int i;
237 /* Group name */
239 if ((result->gr_name =
240 get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) {
242 /* Out of memory */
244 *errnop = ERANGE;
245 return NSS_STATUS_TRYAGAIN;
248 strcpy(result->gr_name, gr->gr_name);
250 /* Password */
252 if ((result->gr_passwd =
253 get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) {
255 /* Out of memory */
257 *errnop = ERANGE;
258 return NSS_STATUS_TRYAGAIN;
261 strcpy(result->gr_passwd, gr->gr_passwd);
263 /* gid */
265 result->gr_gid = gr->gr_gid;
267 /* Group membership */
269 if ((gr->num_gr_mem < 0) || !response->extra_data) {
270 gr->num_gr_mem = 0;
273 if ((result->gr_mem =
274 (char **)get_static(buffer, buflen, (gr->num_gr_mem + 1) *
275 sizeof(char *))) == NULL) {
277 /* Out of memory */
279 *errnop = ERANGE;
280 return NSS_STATUS_TRYAGAIN;
283 if (gr->num_gr_mem == 0) {
285 /* Group is empty */
287 *(result->gr_mem) = NULL;
288 return NSS_STATUS_SUCCESS;
291 /* Start looking at extra data */
293 i = 0;
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) {
302 /* Out of memory */
304 *errnop = ERANGE;
305 return NSS_STATUS_TRYAGAIN;
308 strcpy((result->gr_mem)[i], name);
309 i++;
312 /* Terminate list */
314 (result->gr_mem)[i] = NULL;
316 return NSS_STATUS_SUCCESS;
320 * NSS user functions
323 /* Rewind "file pointer" to start of ntdom password database */
325 enum nss_status
326 _nss_winbind_setpwent(void)
328 return generic_request(WINBINDD_SETPWENT, NULL, NULL);
331 /* Close ntdom password database "file pointer" */
333 enum nss_status
334 _nss_winbind_endpwent(void)
336 return generic_request(WINBINDD_ENDPWENT, NULL, NULL);
339 /* Fetch the next password entry from ntdom password database */
341 enum nss_status
342 _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
343 size_t buflen, int *errnop)
345 enum nss_status ret;
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 */
356 enum nss_status
357 _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer,
358 size_t buflen, int *errnop)
360 enum nss_status ret;
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 */
374 enum nss_status
375 _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer,
376 size_t buflen, int *errnop)
378 enum nss_status ret;
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 */
397 enum nss_status
398 _nss_winbind_setgrent(void)
400 return generic_request(WINBINDD_SETGRENT, NULL, NULL);
403 /* Close "file pointer" for ntdom group database */
405 enum nss_status
406 _nss_winbind_endgrent(void)
408 return generic_request(WINBINDD_ENDGRENT, NULL, NULL);
413 /* Get next entry from ntdom group database */
415 enum nss_status
416 _nss_winbind_getgrent_r(struct group *result,
417 char *buffer, size_t buflen, int *errnop)
419 enum nss_status ret;
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 */
430 enum nss_status
431 _nss_winbind_getgrnam_r(const char *name,
432 struct group *result, char *buffer,
433 size_t buflen, int *errnop)
435 enum nss_status ret;
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 */
450 enum nss_status
451 _nss_winbind_getgrgid_r(gid_t gid,
452 struct group *result, char *buffer,
453 size_t buflen, int *errnop)
455 enum nss_status ret;
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);