source: trunk/samba/source/nsswitch/winbind_nss_irix.c @ 26

Last change on this file since 26 was 26, checked in by Paul Smedley, 14 years ago

Updated source to 3.0.25rc1

File size: 17.5 KB
Line 
1/*
2   Unix SMB/CIFS implementation.
3
4   Windows NT Domain nsswitch module
5
6   Copyright (C) Tim Potter 2000
7   Copyright (C) James Peach 2006
8   
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.
13   
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.
18   
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.   
23*/
24
25#include "winbind_client.h"
26
27#ifndef PRINTF_ATTRIBUTE
28#define PRINTF_ATTRIBUTE(m, n)
29#endif
30
31#ifndef HAVE_ASPRINTF_DECL
32/*PRINTFLIKE2 */
33int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
34#endif
35
36#ifdef HAVE_NS_API_H
37#undef VOLATILE
38#undef STATIC
39#undef DYNAMIC
40#include <ns_daemon.h>
41#endif
42
43/* Maximum number of users to pass back over the unix domain socket
44   per call. This is not a static limit on the total number of users
45   or groups returned in total. */
46
47#define MAX_GETPWENT_USERS 250
48#define MAX_GETGRENT_USERS 250
49
50/* Prototypes from wb_common.c */
51
52extern int winbindd_fd;
53
54#ifdef HAVE_NS_API_H
55
56/* IRIX version */
57
58static int send_next_request(nsd_file_t *, struct winbindd_request *);
59static int do_list(int state, nsd_file_t *rq);
60
61static nsd_file_t *current_rq = NULL;
62static int current_winbind_xid = 0;
63static int next_winbind_xid = 0;
64
65typedef struct winbind_xid {
66        int                     xid;
67        nsd_file_t              *rq;
68        struct winbindd_request *request;
69        struct winbind_xid      *next;
70} winbind_xid_t;
71
72static winbind_xid_t *winbind_xids = (winbind_xid_t *)0;
73
74static int
75winbind_xid_new(int xid, nsd_file_t *rq, struct winbindd_request *request)
76{
77        winbind_xid_t *new;
78
79        nsd_logprintf(NSD_LOG_LOW,
80                "entering winbind_xid_new xid = %d rq = 0x%x, request = 0x%x\n",
81                xid, rq, request);
82        new = (winbind_xid_t *)nsd_calloc(1,sizeof(winbind_xid_t));
83        if (!new) {
84                nsd_logprintf(NSD_LOG_RESOURCE,"winbind_xid_new: failed malloc\n");
85                return NSD_ERROR;
86        }
87
88        new->xid = xid;
89        new->rq = rq;
90        new->request = request;
91        new->next = winbind_xids;
92        winbind_xids = new;
93
94        return NSD_CONTINUE;
95}
96
97/*
98** This routine will look down the xid list and return the request
99** associated with an xid.  We remove the record if it is found.
100*/
101nsd_file_t *
102winbind_xid_lookup(int xid, struct winbindd_request **requestp)
103{
104        winbind_xid_t **last, *dx;
105        nsd_file_t *result=0;
106
107        for (last = &winbind_xids, dx = winbind_xids; dx && (dx->xid != xid);
108            last = &dx->next, dx = dx->next);
109        if (dx) {
110                *last = dx->next;
111                result = dx->rq;
112                *requestp = dx->request;
113                SAFE_FREE(dx);
114        }
115        nsd_logprintf(NSD_LOG_LOW,
116                "entering winbind_xid_lookup xid = %d rq = 0x%x, request = 0x%x\n",
117                xid, result, dx->request);
118
119        return result;
120}
121
122static int
123winbind_startnext_timeout(nsd_file_t **rqp, nsd_times_t *to)
124{
125        nsd_file_t *rq;
126        struct winbindd_request *request;
127
128        nsd_logprintf(NSD_LOG_MIN, "timeout (winbind startnext)\n");
129        rq = to->t_file;
130        *rqp = rq;
131        nsd_timeout_remove(rq);
132        request = to->t_clientdata;
133        return(send_next_request(rq, request));
134}
135
136static void
137dequeue_request(void)
138{
139        nsd_file_t *rq;
140        struct winbindd_request *request;
141
142        /*
143         * Check for queued requests
144         */
145        if (winbind_xids) {
146            nsd_logprintf(NSD_LOG_MIN, "timeout (winbind) unqueue xid %d\n",
147                        current_winbind_xid);
148            rq = winbind_xid_lookup(current_winbind_xid++, &request);
149            /* cause a timeout on the queued request so we can send it */
150            nsd_timeout_new(rq,1,winbind_startnext_timeout,request);
151        }
152}
153
154static int
155do_request(nsd_file_t *rq, struct winbindd_request *request)
156{
157        if (winbind_xids == NULL) {
158                /*
159                 * No outstanding requests.
160                 * Send off the request to winbindd
161                 */
162                nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) sending request\n");
163                return(send_next_request(rq, request));
164        } else {
165                /*
166                 * Just queue it up for now - previous callout or timout
167                 * will start it up
168                 */
169                nsd_logprintf(NSD_LOG_MIN,
170                        "lookup (winbind): queue request xid = %d\n",
171                        next_winbind_xid);
172                return(winbind_xid_new(next_winbind_xid++, rq, request));
173        }
174}
175
176static int 
177winbind_callback(nsd_file_t **rqp, int fd)
178{
179        struct winbindd_response response;
180        nsd_file_t *rq;
181        NSS_STATUS status;
182        char * result = NULL;
183        size_t rlen;
184
185        dequeue_request();
186
187        nsd_logprintf(NSD_LOG_MIN, "entering callback (winbind)\n");
188
189        rq = current_rq;
190        *rqp = rq;
191
192        nsd_timeout_remove(rq);
193        nsd_callback_remove(fd);
194
195        ZERO_STRUCT(response);
196        status = winbindd_get_response(&response);
197
198        if (status != NSS_STATUS_SUCCESS) {
199                /* free any extra data area in response structure */
200                free_response(&response);
201                nsd_logprintf(NSD_LOG_MIN, 
202                        "callback (winbind) returning not found, status = %d\n",
203                        status);
204
205                switch (status) {
206                    case NSS_STATUS_UNAVAIL:
207                        rq->f_status = NS_UNAVAIL;
208                        break;
209                    case NSS_STATUS_TRYAGAIN:
210                        rq->f_status = NS_TRYAGAIN;
211                        break;
212                    case NSS_STATUS_NOTFOUND:
213                        /* FALLTHRU */
214                    default:
215                        rq->f_status = NS_NOTFOUND;
216                }
217
218                return NSD_NEXT;
219        }
220
221        switch ((int)rq->f_cmd_data) {
222            case WINBINDD_WINS_BYNAME:
223            case WINBINDD_WINS_BYIP:
224                nsd_logprintf(NSD_LOG_MIN,
225                        "callback (winbind) WINS_BYNAME | WINS_BYIP\n");
226
227                rlen = asprintf(&result, "%s\n", response.data.winsresp);
228                if (rlen == 0 || result == NULL) {
229                        return NSD_ERROR;
230                }
231               
232                free_response(&response);
233               
234                nsd_logprintf(NSD_LOG_MIN, "    %s\n", result);
235                nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
236                return NSD_OK;
237
238            case WINBINDD_GETPWUID:
239            case WINBINDD_GETPWNAM:
240            {
241                struct winbindd_pw *pw = &response.data.pw;
242           
243                nsd_logprintf(NSD_LOG_MIN,
244                        "callback (winbind) GETPWUID | GETPWUID\n");
245
246                rlen = asprintf(&result,"%s:%s:%d:%d:%s:%s:%s\n",
247                                pw->pw_name,
248                                pw->pw_passwd,
249                                pw->pw_uid,
250                                pw->pw_gid,
251                                pw->pw_gecos,
252                                pw->pw_dir,
253                                pw->pw_shell);
254                if (rlen == 0 || result == NULL)
255                    return NSD_ERROR;
256           
257                free_response(&response);
258           
259                nsd_logprintf(NSD_LOG_MIN, "    %s\n", result);
260                nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
261                return NSD_OK;
262            }
263
264            case WINBINDD_GETGRNAM:
265            case WINBINDD_GETGRGID:
266            {
267                const struct winbindd_gr *gr = &response.data.gr;
268                const char * members;
269           
270                nsd_logprintf(NSD_LOG_MIN,
271                        "callback (winbind) GETGRNAM | GETGRGID\n");
272
273                if (gr->num_gr_mem && response.extra_data.data) {
274                        members = response.extra_data.data;
275                } else {
276                        members = "";
277                }
278           
279                rlen = asprintf(&result, "%s:%s:%d:%s\n",
280                            gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
281                if (rlen == 0 || result == NULL)
282                    return NSD_ERROR;
283           
284                free_response(&response);
285           
286                nsd_logprintf(NSD_LOG_MIN, "    %s\n", result);
287                nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
288                return NSD_OK;
289            }
290
291            case WINBINDD_SETGRENT:
292            case WINBINDD_SETPWENT:
293                nsd_logprintf(NSD_LOG_MIN,
294                        "callback (winbind) SETGRENT | SETPWENT\n");
295                free_response(&response);
296                return(do_list(1,rq));
297
298            case WINBINDD_GETGRENT:
299            case WINBINDD_GETGRLST:
300            {
301                int entries;
302           
303                nsd_logprintf(NSD_LOG_MIN,
304                    "callback (winbind) GETGRENT | GETGRLIST %d responses\n",
305                    response.data.num_entries);
306           
307                if (response.data.num_entries) {
308                    const struct winbindd_gr *gr = &response.data.gr;
309                    const char * members;
310                    fstring grp_name;
311                    int     i;
312           
313                    gr = (struct winbindd_gr *)response.extra_data.data;
314                    if (! gr ) {
315                        nsd_logprintf(NSD_LOG_MIN, "     no extra_data\n");
316                        free_response(&response);
317                        return NSD_ERROR;
318                    }
319           
320                    members = (char *)response.extra_data.data +
321                        (response.data.num_entries * sizeof(struct winbindd_gr));
322           
323                    for (i = 0; i < response.data.num_entries; i++) {
324                        snprintf(grp_name, sizeof(grp_name) - 1, "%s:%s:%d:",
325                                    gr->gr_name, gr->gr_passwd, gr->gr_gid);
326           
327                        nsd_append_element(rq, NS_SUCCESS, result, rlen);
328                        nsd_append_result(rq, NS_SUCCESS,
329                                &members[gr->gr_mem_ofs],
330                                strlen(&members[gr->gr_mem_ofs]));
331           
332                        /* Don't log the whole list, because it might be
333                         * _really_ long and we probably don't want to clobber
334                         * the log with it.
335                         */
336                        nsd_logprintf(NSD_LOG_MIN, "    %s (...)\n", grp_name);
337           
338                        gr++;
339                    }
340                }
341           
342                entries = response.data.num_entries;
343                free_response(&response);
344                if (entries < MAX_GETPWENT_USERS)
345                    return(do_list(2,rq));
346                else
347                    return(do_list(1,rq));
348            }
349
350            case WINBINDD_GETPWENT:
351            {
352                int entries;
353
354                nsd_logprintf(NSD_LOG_MIN,
355                        "callback (winbind) GETPWENT  %d responses\n",
356                        response.data.num_entries);
357
358                if (response.data.num_entries) {
359                    struct winbindd_pw *pw = &response.data.pw;
360                    int i;
361
362                    pw = (struct winbindd_pw *)response.extra_data.data;
363                    if (! pw ) {
364                        nsd_logprintf(NSD_LOG_MIN, "     no extra_data\n");
365                        free_response(&response);
366                        return NSD_ERROR;
367                    }
368                    for (i = 0; i < response.data.num_entries; i++) {
369                        result = NULL;
370                        rlen = asprintf(&result, "%s:%s:%d:%d:%s:%s:%s",
371                                        pw->pw_name,
372                                        pw->pw_passwd,
373                                        pw->pw_uid,
374                                        pw->pw_gid,
375                                        pw->pw_gecos,
376                                        pw->pw_dir,
377                                        pw->pw_shell);
378
379                        if (rlen != 0 && result != NULL) {
380                            nsd_logprintf(NSD_LOG_MIN, "    %s\n",result);
381                            nsd_append_element(rq, NS_SUCCESS, result, rlen);
382                            free(result);
383                        }
384
385                        pw++;
386                    }
387                }
388
389                entries = response.data.num_entries;
390                free_response(&response);
391                if (entries < MAX_GETPWENT_USERS)
392                    return(do_list(2,rq));
393                else
394                    return(do_list(1,rq));
395            }
396
397            case WINBINDD_ENDGRENT:
398            case WINBINDD_ENDPWENT:
399                nsd_logprintf(NSD_LOG_MIN, "callback (winbind) ENDGRENT | ENDPWENT\n");
400                nsd_append_element(rq, NS_SUCCESS, "\n", 1);
401                free_response(&response);
402                return NSD_NEXT;
403
404            default:
405                free_response(&response);
406                nsd_logprintf(NSD_LOG_MIN, "callback (winbind) invalid command %d\n", (int)rq->f_cmd_data);
407                return NSD_NEXT;
408        }
409}
410
411static int 
412winbind_timeout(nsd_file_t **rqp, nsd_times_t *to)
413{
414        nsd_file_t *rq;
415
416        dequeue_request();
417
418        nsd_logprintf(NSD_LOG_MIN, "timeout (winbind)\n");
419
420        rq = to->t_file;
421        *rqp = rq;
422
423        /* Remove the callback and timeout */
424        nsd_callback_remove(winbindd_fd);
425        nsd_timeout_remove(rq);
426
427        rq->f_status = NS_NOTFOUND;
428        return NSD_NEXT;
429}
430
431static int
432send_next_request(nsd_file_t *rq, struct winbindd_request *request)
433{
434        NSS_STATUS status;
435        long timeout;
436
437        switch (rq->f_index) {
438                case LOOKUP:
439                        timeout = nsd_attr_fetch_long(rq->f_attrs,
440                                        "lookup_timeout", 10, 10);
441                        break;
442                case LIST:
443                        timeout = nsd_attr_fetch_long(rq->f_attrs,
444                                        "list_timeout", 10, 10);
445                        break;
446                default:
447                        nsd_logprintf(NSD_LOG_OPER,
448                                "send_next_request (winbind) "
449                                "invalid request type %d\n", rq->f_index);
450                        rq->f_status = NS_BADREQ;
451                        return NSD_NEXT;
452        }
453
454        nsd_logprintf(NSD_LOG_MIN,
455                "send_next_request (winbind) %d, timeout = %d sec\n",
456                        rq->f_cmd_data, timeout);
457        status = winbindd_send_request((int)rq->f_cmd_data,0,request);
458        SAFE_FREE(request);
459
460        if (status != NSS_STATUS_SUCCESS) {
461                nsd_logprintf(NSD_LOG_MIN, 
462                        "send_next_request (winbind) error status = %d\n",
463                        status);
464                rq->f_status = status;
465                return NSD_NEXT;
466        }
467
468        current_rq = rq;
469
470        /*
471         * Set up callback and timeouts
472         */
473        nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) fd = %d\n",
474                winbindd_fd);
475
476        nsd_callback_new(winbindd_fd, winbind_callback, NSD_READ);
477        nsd_timeout_new(rq, timeout * 1000, winbind_timeout, NULL);
478        return NSD_CONTINUE;
479}
480
481int init(void)
482{
483        nsd_logprintf(NSD_LOG_MIN, "entering init (winbind)\n");
484        return(NSD_OK);
485}
486
487int lookup(nsd_file_t *rq)
488{
489        char *map;
490        char *key;
491        struct winbindd_request *request;
492
493        nsd_logprintf(NSD_LOG_MIN, "entering lookup (winbind)\n");
494        if (! rq)
495                return NSD_ERROR;
496
497        map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
498        key = nsd_attr_fetch_string(rq->f_attrs, "key", (char*)0);
499        if (! map || ! key) {
500                nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) table or key not defined\n");
501                rq->f_status = NS_BADREQ;
502                return NSD_ERROR;
503        }
504
505        nsd_logprintf(NSD_LOG_MIN, "lookup (winbind %s)\n",map);
506
507        request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
508        if (! request) {
509                nsd_logprintf(NSD_LOG_RESOURCE,
510                        "lookup (winbind): failed malloc\n");
511                return NSD_ERROR;
512        }
513
514        if (strcasecmp(map,"passwd.byuid") == 0) {
515            request->data.uid = atoi(key);
516            rq->f_cmd_data = (void *)WINBINDD_GETPWUID;
517        } else if (strcasecmp(map,"passwd.byname") == 0) {
518            strncpy(request->data.username, key, 
519                sizeof(request->data.username) - 1);
520            request->data.username[sizeof(request->data.username) - 1] = '\0';
521            rq->f_cmd_data = (void *)WINBINDD_GETPWNAM; 
522        } else if (strcasecmp(map,"group.byname") == 0) {
523            strncpy(request->data.groupname, key, 
524                sizeof(request->data.groupname) - 1);
525            request->data.groupname[sizeof(request->data.groupname) - 1] = '\0';
526            rq->f_cmd_data = (void *)WINBINDD_GETGRNAM; 
527        } else if (strcasecmp(map,"group.bygid") == 0) {
528            request->data.gid = atoi(key);
529            rq->f_cmd_data = (void *)WINBINDD_GETGRGID;
530        } else if (strcasecmp(map,"hosts.byname") == 0) {
531            strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
532            request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
533            rq->f_cmd_data = (void *)WINBINDD_WINS_BYNAME;
534        } else if (strcasecmp(map,"hosts.byaddr") == 0) {
535            strncpy(request->data.winsreq, key, sizeof(request->data.winsreq) - 1);
536            request->data.winsreq[sizeof(request->data.winsreq) - 1] = '\0';
537            rq->f_cmd_data = (void *)WINBINDD_WINS_BYIP;
538        } else {
539                /*
540                 * Don't understand this map - just return not found
541                 */
542                nsd_logprintf(NSD_LOG_MIN, "lookup (winbind) unknown table\n");
543                SAFE_FREE(request);
544                rq->f_status = NS_NOTFOUND;
545                return NSD_NEXT;
546        }
547
548        return(do_request(rq, request));
549}
550
551int list(nsd_file_t *rq)
552{
553        char *map;
554
555        nsd_logprintf(NSD_LOG_MIN, "entering list (winbind)\n");
556        if (! rq)
557                return NSD_ERROR;
558
559        map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
560        if (! map ) {
561                nsd_logprintf(NSD_LOG_MIN, "list (winbind) table not defined\n");
562                rq->f_status = NS_BADREQ;
563                return NSD_ERROR;
564        }
565
566        nsd_logprintf(NSD_LOG_MIN, "list (winbind %s)\n",map);
567
568        return (do_list(0,rq));
569}
570
571static int
572do_list(int state, nsd_file_t *rq)
573{
574        char *map;
575        struct winbindd_request *request;
576
577        nsd_logprintf(NSD_LOG_MIN, "entering do_list (winbind) state = %d\n",state);
578
579        map = nsd_attr_fetch_string(rq->f_attrs, "table", (char*)0);
580        request = (struct winbindd_request *)nsd_calloc(1,sizeof(struct winbindd_request));
581        if (! request) {
582                nsd_logprintf(NSD_LOG_RESOURCE,
583                        "do_list (winbind): failed malloc\n");
584                return NSD_ERROR;
585        }
586
587        if (strcasecmp(map,"passwd.byname") == 0) {
588            switch (state) {
589                case 0:
590                    rq->f_cmd_data = (void *)WINBINDD_SETPWENT;
591                    break;
592                case 1:
593                    request->data.num_entries = MAX_GETPWENT_USERS;
594                    rq->f_cmd_data = (void *)WINBINDD_GETPWENT;
595                    break;
596                case 2:
597                    rq->f_cmd_data = (void *)WINBINDD_ENDPWENT;
598                    break;
599                default:
600                    nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
601                    SAFE_FREE(request);
602                    rq->f_status = NS_NOTFOUND;
603                    return NSD_NEXT;
604            }
605        } else if (strcasecmp(map,"group.byname") == 0) {
606            switch (state) {
607                case 0:
608                    rq->f_cmd_data = (void *)WINBINDD_SETGRENT;
609                    break;
610                case 1:
611                    request->data.num_entries = MAX_GETGRENT_USERS;
612                    rq->f_cmd_data = (void *)WINBINDD_GETGRENT;
613                    break;
614                case 2:
615                    rq->f_cmd_data = (void *)WINBINDD_ENDGRENT;
616                    break;
617                default:
618                    nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown state\n");
619                    SAFE_FREE(request);
620                    rq->f_status = NS_NOTFOUND;
621                    return NSD_NEXT;
622            }
623        } else {
624                /*
625                 * Don't understand this map - just return not found
626                 */
627                nsd_logprintf(NSD_LOG_MIN, "do_list (winbind) unknown table\n");
628                SAFE_FREE(request);
629                rq->f_status = NS_NOTFOUND;
630                return NSD_NEXT;
631        }
632
633        return(do_request(rq, request));
634}
635
636#endif /* HAVE_NS_API_H */
Note: See TracBrowser for help on using the repository browser.