r59: revert session key problem
[Samba/gebeck_regimport.git] / source / nsswitch / winbind_nss_irix.c
blob3a9d6c01ab5b4f73e7cbbac924bc1a0bde122e0e
1 /*
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 #ifdef HAVE_NS_API_H
27 #undef VOLATILE
28 #include <ns_daemon.h>
29 #endif
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;
42 #ifdef HAVE_NS_API_H
44 /* IRIX version */
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 {
54 int xid;
55 nsd_file_t *rq;
56 struct winbindd_request *request;
57 struct winbind_xid *next;
58 } winbind_xid_t;
60 static winbind_xid_t *winbind_xids = (winbind_xid_t *)0;
62 static int
63 winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request)
65 winbind_xid_t *new;
67 nsd_logprintf(NSD_LOG_LOW,
68 "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n",
69 xid, rq, request);
70 new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t));
71 if (!new) {
72 nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n");
73 return NSD_ERROR;
76 new->xid = xid;
77 new->rq = rq;
78 new->request = request;
79 new->next = winbind_xids;
80 winbind_xids = new;
82 return NSD_CONTINUE;
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.
89 nsd_file_t *
90 winbind_xid_lookup(int xid, struct winbindd_request **requestp)
92 winbind_xid_t **last, *dx;
93 nsd_file_t *result=0;
95 for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid);
96 last = &dx->next, dx = dx->next);
97 if (dx) {
98 *last = dx->next;
99 result = dx->rq;
100 *requestp = dx->request;
101 SAFE_FREE(dx);
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);
107 return result;
110 static int
111 winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to)
113 nsd_file_t *rq;
114 struct winbindd_request *request;
116 nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n");
117 rq = to->t_file;
118 *rqp = rq;
119 nsd_timeout_remove(rq);
120 request = to->t_clientdata;
121 return(send_next_request(rq, request));
124 static void
125 dequeue_request()
127 nsd_file_t *rq;
128 struct winbindd_request *request;
131 * Check for queued requests
133 if (winbind_xids) {
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);
142 static int
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));
152 } else {
154 * Just queue it up for now - previous callout or timout
155 * will start it up
157 nsd_logprintf(NSD_LOG_MIN,
158 "lookup (winbind): queue request xid = %d\n",
159 next_winbind_xid);
160 return(winbind_xid_new(next_winbind_xid++, rq, request));
164 static int
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;
170 nsd_file_t *rq;
171 NSS_STATUS status;
172 fstring result;
173 char *members;
174 int i, maxlen;
176 dequeue_request();
178 nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n");
180 rq = current_rq;
181 *rqp = rq;
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",
194 status);
195 rq->f_status = NS_NOTFOUND;
196 return NSD_NEXT;
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);
205 break;
206 case WINBINDD_GETPWUID:
207 case WINBINDD_GETPWNAM:
208 snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n",
209 pw->pw_name,
210 pw->pw_passwd,
211 pw->pw_uid,
212 pw->pw_gid,
213 pw->pw_gecos,
214 pw->pw_dir,
215 pw->pw_shell);
216 break;
217 case WINBINDD_GETGRNAM:
218 case WINBINDD_GETGRGID:
219 if (gr->num_gr_mem && response.extra_data)
220 members = response.extra_data;
221 else
222 members = "";
223 snprintf(result,maxlen,"%s:%s:%d:%s\n",
224 gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
225 break;
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;
238 if (! gr ) {
239 nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
240 free_response(&response);
241 return NSD_ERROR;
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));
251 gr++;
254 i = response.data.num_entries;
255 free_response(&response);
256 if (i < MAX_GETPWENT_USERS)
257 return(do_list(2,rq));
258 else
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;
266 if (! pw ) {
267 nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
268 free_response(&response);
269 return NSD_ERROR;
271 for (i = 0; i < response.data.num_entries; i++) {
272 snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s",
273 pw->pw_name,
274 pw->pw_passwd,
275 pw->pw_uid,
276 pw->pw_gid,
277 pw->pw_gecos,
278 pw->pw_dir,
279 pw->pw_shell);
280 nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result);
281 nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
282 pw++;
285 i = response.data.num_entries;
286 free_response(&response);
287 if (i < MAX_GETPWENT_USERS)
288 return(do_list(2,rq));
289 else
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);
296 return NSD_NEXT;
297 default:
298 free_response(&response);
299 nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n");
300 return NSD_NEXT;
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);
306 return NSD_OK;
309 static int
310 winbind_timeout(nsd_file_t **rqp, nsd_times_t *to)
312 nsd_file_t *rq;
314 dequeue_request();
316 nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n");
318 rq = to->t_file;
319 *rqp = rq;
321 /* Remove the callback and timeout */
322 nsd_callback_remove(winbindd_fd);
323 nsd_timeout_remove(rq);
325 rq->f_status = NS_NOTFOUND;
326 return NSD_NEXT;
329 static int
330 send_next_request(nsd_file_t *rq, struct winbindd_request *request)
332 NSS_STATUS status;
333 long timeout;
335 timeout = 1000;
337 nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n",
338 rq->f_cmd_data, timeout);
339 status = winbindd_send_request((int)rq->f_cmd_data,request);
340 SAFE_FREE(request);
342 if (status != NSS_STATUS_SUCCESS) {
343 nsd_logprintf(NSD_LOG_MIN,
344 "send_next_request (winbind) error status = %d\n",status);
345 rq->f_status = status;
346 return NSD_NEXT;
349 current_rq = rq;
352 * Set up callback and timeouts
354 nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",winbindd_fd);
355 nsd_callback_new(winbindd_fd,winbind_callback,NSD_READ);
356 nsd_timeout_new(rq,timeout,winbind_timeout,(void *)0);
357 return NSD_CONTINUE;
360 int init(void)
362 nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n");
363 return(NSD_OK);
366 int lookup(nsd_file_t *rq)
368 char *map;
369 char *key;
370 struct winbindd_request *request;
372 nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n");
373 if (! rq)
374 return NSD_ERROR;
376 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
377 key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0);
378 if (! map || ! key) {
379 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n");
380 rq->f_status = NS_BADREQ;
381 return NSD_ERROR;
384 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map);
386 request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
387 if (! request) {
388 nsd_logprintf(NSD_LOG_RESOURCE,
389 "lookup (winbind): failed malloc\n");
390 return NSD_ERROR;
393 if (strcasecmp(map,"passwd.byuid") == 0) {
394 request->data.uid = atoi(key);
395 rq->f_cmd_data = (void *)WINBINDD_GETPWUID;
396 } else if (strcasecmp(map,"passwd.byname") == 0) {
397 strncpy(request->data.username, key,
398 sizeof(request->data.username) - 1);
399 request->data.username[sizeof(request->data.username) - 1] = '\0';
400 rq->f_cmd_data = (void *)WINBINDD_GETPWNAM;
401 } else if (strcasecmp(map,"group.byname") == 0) {
402 strncpy(request->data.groupname, key,
403 sizeof(request->data.groupname) - 1);
404 request->data.groupname[sizeof(request->data.groupname) - 1] = '\0';
405 rq->f_cmd_data = (void *)WINBINDD_GETGRNAM;
406 } else if (strcasecmp(map,"group.bygid") == 0) {
407 request->data.gid = atoi(key);
408 rq->f_cmd_data = (void *)WINBINDD_GETGRGID;
409 } else if (strcasecmp(map,"hosts.byname") == 0) {
410 strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
411 request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
412 rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME;
413 } else if (strcasecmp(map,"hosts.byaddr") == 0) {
414 strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
415 request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
416 rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP;
417 } else {
419 * Don't understand this map - just return not found
421 nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n");
422 SAFE_FREE(request);
423 rq->f_status = NS_NOTFOUND;
424 return NSD_NEXT;
427 return(do_request(rq, request));
430 int list(nsd_file_t *rq)
432 char *map;
434 nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n");
435 if (! rq)
436 return NSD_ERROR;
438 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
439 if (! map ) {
440 nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n");
441 rq->f_status = NS_BADREQ;
442 return NSD_ERROR;
445 nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map);
447 return (do_list(0,rq));
450 static int
451 do_list(int state, nsd_file_t *rq)
453 char *map;
454 struct winbindd_request *request;
456 nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state);
458 map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
459 request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
460 if (! request) {
461 nsd_logprintf(NSD_LOG_RESOURCE,
462 "do_list (winbind): failed malloc\n");
463 return NSD_ERROR;
466 if (strcasecmp(map,"passwd.byname") == 0) {
467 switch (state) {
468 case 0:
469 rq->f_cmd_data = (void *)WINBINDD_SETPWENT;
470 break;
471 case 1:
472 request->data.num_entries = MAX_GETPWENT_USERS;
473 rq->f_cmd_data = (void *)WINBINDD_GETPWENT;
474 break;
475 case 2:
476 rq->f_cmd_data = (void *)WINBINDD_ENDPWENT;
477 break;
478 default:
479 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
480 SAFE_FREE(request);
481 rq->f_status = NS_NOTFOUND;
482 return NSD_NEXT;
484 } else if (strcasecmp(map,"group.byname") == 0) {
485 switch (state) {
486 case 0:
487 rq->f_cmd_data = (void *)WINBINDD_SETGRENT;
488 break;
489 case 1:
490 request->data.num_entries = MAX_GETGRENT_USERS;
491 rq->f_cmd_data = (void *)WINBINDD_GETGRENT;
492 break;
493 case 2:
494 rq->f_cmd_data = (void *)WINBINDD_ENDGRENT;
495 break;
496 default:
497 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
498 SAFE_FREE(request);
499 rq->f_status = NS_NOTFOUND;
500 return NSD_NEXT;
502 } else {
504 * Don't understand this map - just return not found
506 nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n");
507 SAFE_FREE(request);
508 rq->f_status = NS_NOTFOUND;
509 return NSD_NEXT;
512 return(do_request(rq, request));
515 #endif /* HAVE_NS_API_H */