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"
28 #include <ns_daemon.h>
31 /* Maximum number of users to pass back over the unix domain socket
32 per call. This is not a static limit on the total number of users
33 or groups returned in total. */
35 #define MAX_GETPWENT_USERS 250
36 #define MAX_GETGRENT_USERS 250
38 /* Prototypes from wb_common.c */
40 extern int winbindd_fd;
46 static int send_next_request(nsd_file_t *, struct winbindd_request *);
47 static int do_list(int state, nsd_file_t *rq);
49 static nsd_file_t *current_rq = NULL;
50 static int current_winbind_xid = 0;
51 static int next_winbind_xid = 0;
53 typedef struct winbind_xid {
56 struct winbindd_request *request;
57 struct winbind_xid *next;
60 static winbind_xid_t *winbind_xids = (winbind_xid_t *)0;
63 winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request)
67 nsd_logprintf(NSD_LOG_LOW,
68 "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n",
70 new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t));
72 nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n");
78 new->request = request;
79 new->next = winbind_xids;
86 ** This routine will look down the xid list and return the request
87 ** associated with an xid. We remove the record if it is found.
90 winbind_xid_lookup(int xid, struct winbindd_request **requestp)
92 winbind_xid_t **last, *dx;
95 for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid);
96 last = &dx->next, dx = dx->next);
100 *requestp = dx->request;
103 nsd_logprintf(NSD_LOG_LOW,
104 "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n",
105 xid, result, dx->request);
111 winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to)
114 struct winbindd_request *request;
116 nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n");
119 nsd_timeout_remove(rq);
120 request = to->t_clientdata;
121 return(send_next_request(rq, request));
125 dequeue_request(void)
128 struct winbindd_request *request;
131 * Check for queued requests
134 nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n",
135 current_winbind_xid);
136 rq = winbind_xid_lookup(current_winbind_xid++, &request);
137 /* cause a timeout on the queued request so we can send it */
138 nsd_timeout_new(rq,1,winbind_startnext_timeout,request);
143 do_request(nsd_file_t *rq, struct winbindd_request *request)
145 if (winbind_xids == NULL) {
147 * No outstanding requests.
148 * Send off the request to winbindd
150 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n");
151 return(send_next_request(rq, request));
154 * Just queue it up for now - previous callout or timout
157 nsd_logprintf(NSD_LOG_MIN,
158 "lookup (winbind): queue request xid = %d\n",
160 return(winbind_xid_new(next_winbind_xid++, rq, request));
165 winbind_callback(nsd_file_t **rqp, int fd)
167 struct winbindd_response response;
168 struct winbindd_pw *pw = &response.data.pw;
169 struct winbindd_gr *gr = &response.data.gr;
178 nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n");
183 nsd_timeout_remove(rq);
184 nsd_callback_remove(fd);
186 ZERO_STRUCT(response);
187 status = winbindd_get_response(&response);
189 if (status != NSS_STATUS_SUCCESS) {
190 /* free any extra data area in response structure */
191 free_response(&response);
192 nsd_logprintf(NSD_LOG_MIN,
193 "callback (winbind) returning not found, status = %d\n",
195 rq->f_status = NS_NOTFOUND;
199 maxlen = sizeof(result) - 1;
201 switch ((int)rq->f_cmd_data) {
202 case WINBINDD_WINS_BYNAME:
203 case WINBINDD_WINS_BYIP:
204 snprintf(result,maxlen,"%s\n",response.data.winsresp);
206 case WINBINDD_GETPWUID:
207 case WINBINDD_GETPWNAM:
208 snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n",
217 case WINBINDD_GETGRNAM:
218 case WINBINDD_GETGRGID:
219 if (gr->num_gr_mem && response.extra_data)
220 members = response.extra_data;
223 snprintf(result,maxlen,"%s:%s:%d:%s\n",
224 gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
226 case WINBINDD_SETGRENT:
227 case WINBINDD_SETPWENT:
228 nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - SETPWENT/SETGRENT\n");
229 free_response(&response);
230 return(do_list(1,rq));
231 case WINBINDD_GETGRENT:
232 case WINBINDD_GETGRLST:
233 nsd_logprintf(NSD_LOG_MIN,
234 "callback (winbind) - %d GETGRENT responses\n",
235 response.data.num_entries);
236 if (response.data.num_entries) {
237 gr = (struct winbindd_gr *)response.extra_data;
239 nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
240 free_response(&response);
243 members = (char *)response.extra_data +
244 (response.data.num_entries * sizeof(struct winbindd_gr));
245 for (i = 0; i < response.data.num_entries; i++) {
246 snprintf(result,maxlen,"%s:%s:%d:%s\n",
247 gr->gr_name, gr->gr_passwd, gr->gr_gid,
248 &members[gr->gr_mem_ofs]);
249 nsd_logprintf(NSD_LOG_MIN, " GETGRENT %s\n",result);
250 nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
254 i = response.data.num_entries;
255 free_response(&response);
256 if (i < MAX_GETPWENT_USERS)
257 return(do_list(2,rq));
259 return(do_list(1,rq));
260 case WINBINDD_GETPWENT:
261 nsd_logprintf(NSD_LOG_MIN,
262 "callback (winbind) - %d GETPWENT responses\n",
263 response.data.num_entries);
264 if (response.data.num_entries) {
265 pw = (struct winbindd_pw *)response.extra_data;
267 nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
268 free_response(&response);
271 for (i = 0; i < response.data.num_entries; i++) {
272 snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s",
280 nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result);
281 nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
285 i = response.data.num_entries;
286 free_response(&response);
287 if (i < MAX_GETPWENT_USERS)
288 return(do_list(2,rq));
290 return(do_list(1,rq));
291 case WINBINDD_ENDGRENT:
292 case WINBINDD_ENDPWENT:
293 nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - ENDPWENT/ENDGRENT\n");
294 nsd_append_element(rq,NS_SUCCESS,"\n",1);
295 free_response(&response);
298 free_response(&response);
299 nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n");
302 nsd_logprintf(NSD_LOG_MIN, "callback (winbind) %s\n", result);
303 /* free any extra data area in response structure */
304 free_response(&response);
305 nsd_set_result(rq,NS_SUCCESS,result,strlen(result),VOLATILE);
310 winbind_timeout(nsd_file_t **rqp, nsd_times_t *to)
316 nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n");
321 /* Remove the callback and timeout */
322 nsd_callback_remove(winbindd_fd);
323 nsd_timeout_remove(rq);
325 rq->f_status = NS_NOTFOUND;
330 send_next_request(nsd_file_t *rq, struct winbindd_request *request)
335 switch (rq->f_index) {
337 timeout = nsd_attr_fetch_long(rq->f_attrs,
338 "lookup_timeout", 10, 10 * 1000);
341 timeout = nsd_attr_fetch_long(rq->f_attrs,
342 "list_timeout", 10, 10 * 1000);
345 nsd_logprintf(NSD_LOG_OPER,
346 "send_next_request (winbind) "
347 "invalid request type %d\n", rq->f_index);
348 rq->f_status = NS_BADREQ;
352 nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n",
353 rq->f_cmd_data, timeout);
354 status = winbindd_send_request((int)rq->f_cmd_data,request);
357 if (status != NSS_STATUS_SUCCESS) {
358 nsd_logprintf(NSD_LOG_MIN,
359 "send_next_request (winbind) error status = %d\n",status);
360 rq->f_status = status;
367 * Set up callback and timeouts
369 nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",winbindd_fd);
370 nsd_callback_new(winbindd_fd,winbind_callback,NSD_READ);
371 nsd_timeout_new(rq,timeout,winbind_timeout,(void *)0);
377 nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n");
381 int lookup(nsd_file_t *rq)
385 struct winbindd_request *request;
387 nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n");
391 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
392 key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0);
393 if (! map || ! key) {
394 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n");
395 rq->f_status = NS_BADREQ;
399 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map);
401 request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
403 nsd_logprintf(NSD_LOG_RESOURCE,
404 "lookup (winbind): failed malloc\n");
408 if (strcasecmp(map,"passwd.byuid") == 0) {
409 request->data.uid = atoi(key);
410 rq->f_cmd_data = (void *)WINBINDD_GETPWUID;
411 } else if (strcasecmp(map,"passwd.byname") == 0) {
412 strncpy(request->data.username, key,
413 sizeof(request->data.username) - 1);
414 request->data.username[sizeof(request->data.username) - 1] = '\0';
415 rq->f_cmd_data = (void *)WINBINDD_GETPWNAM;
416 } else if (strcasecmp(map,"group.byname") == 0) {
417 strncpy(request->data.groupname, key,
418 sizeof(request->data.groupname) - 1);
419 request->data.groupname[sizeof(request->data.groupname) - 1] = '\0';
420 rq->f_cmd_data = (void *)WINBINDD_GETGRNAM;
421 } else if (strcasecmp(map,"group.bygid") == 0) {
422 request->data.gid = atoi(key);
423 rq->f_cmd_data = (void *)WINBINDD_GETGRGID;
424 } else if (strcasecmp(map,"hosts.byname") == 0) {
425 strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
426 request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
427 rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME;
428 } else if (strcasecmp(map,"hosts.byaddr") == 0) {
429 strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
430 request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
431 rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP;
434 * Don't understand this map - just return not found
436 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n");
438 rq->f_status = NS_NOTFOUND;
442 return(do_request(rq, request));
445 int list(nsd_file_t *rq)
449 nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n");
453 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
455 nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n");
456 rq->f_status = NS_BADREQ;
460 nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map);
462 return (do_list(0,rq));
466 do_list(int state, nsd_file_t *rq)
469 struct winbindd_request *request;
471 nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state);
473 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
474 request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
476 nsd_logprintf(NSD_LOG_RESOURCE,
477 "do_list (winbind): failed malloc\n");
481 if (strcasecmp(map,"passwd.byname") == 0) {
484 rq->f_cmd_data = (void *)WINBINDD_SETPWENT;
487 request->data.num_entries = MAX_GETPWENT_USERS;
488 rq->f_cmd_data = (void *)WINBINDD_GETPWENT;
491 rq->f_cmd_data = (void *)WINBINDD_ENDPWENT;
494 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
496 rq->f_status = NS_NOTFOUND;
499 } else if (strcasecmp(map,"group.byname") == 0) {
502 rq->f_cmd_data = (void *)WINBINDD_SETGRENT;
505 request->data.num_entries = MAX_GETGRENT_USERS;
506 rq->f_cmd_data = (void *)WINBINDD_GETGRENT;
509 rq->f_cmd_data = (void *)WINBINDD_ENDGRENT;
512 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
514 rq->f_status = NS_NOTFOUND;
519 * Don't understand this map - just return not found
521 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n");
523 rq->f_status = NS_NOTFOUND;
527 return(do_request(rq, request));
530 #endif /* HAVE_NS_API_H */