ldb: version 1.2.1
[samba.git] / nsswitch / winbind_nss_netbsd.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    NetBSD loadable authentication module, providing identification
5    routines against Samba winbind/Windows NT Domain
6
7    Copyright (C) Luke Mewburn 2004-2005
8
9    This library is free software; you can redistribute it and/or
10    modify it under the terms of the GNU Lesser General Public
11    License as published by the Free Software Foundation; either
12    version 3 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 Lesser General Public
20    License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 */
22
23
24 #include "winbind_client.h"
25
26 #include <sys/param.h>
27 #include <stdarg.h>
28 #include <syslog.h>
29
30         /* dynamic nsswitch with "new" getpw* nsdispatch API available */
31 #if defined(NSS_MODULE_INTERFACE_VERSION) && defined(HAVE_GETPWENT_R)
32
33 /*
34         group functions
35         ---------------
36 */
37
38 static struct group     _winbind_group;
39 static char             _winbind_groupbuf[1024];
40
41 /*
42  * We need a proper prototype for this :-)
43  */
44
45 NSS_STATUS _nss_winbind_setpwent(void);
46 NSS_STATUS _nss_winbind_endpwent(void);
47 NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer,
48                                    size_t buflen, int *errnop);
49 NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result,
50                                    char *buffer, size_t buflen, int *errnop);
51 NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result,
52                                    char *buffer, size_t buflen, int *errnop);
53 NSS_STATUS _nss_winbind_setgrent(void);
54 NSS_STATUS _nss_winbind_endgrent(void);
55 NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer,
56                                    size_t buflen, int *errnop);
57 NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer,
58                                    size_t buflen, int *errnop);
59 NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result,
60                                    char *buffer, size_t buflen, int *errnop);
61 NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer,
62                                    size_t buflen, int *errnop);
63 NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start,
64                                        long int *size, gid_t **groups,
65                                        long int limit, int *errnop);
66
67 int
68 netbsdwinbind_endgrent(void *nsrv, void *nscb, va_list ap)
69 {
70         int     rv;
71
72         rv = _nss_winbind_endgrent();
73         return rv;
74 }
75
76 int
77 netbsdwinbind_setgrent(void *nsrv, void *nscb, va_list ap)
78 {
79         int     rv;
80
81         rv = _nss_winbind_setgrent();
82         return rv;
83 }
84
85 int
86 netbsdwinbind_getgrent(void *nsrv, void *nscb, va_list ap)
87 {
88         struct group   **retval = va_arg(ap, struct group **);
89
90         int     rv, rerrno;
91
92         *retval = NULL;
93         rv = _nss_winbind_getgrent_r(&_winbind_group,
94             _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
95         if (rv == NS_SUCCESS)
96                 *retval = &_winbind_group;
97         return rv;
98 }
99
100 int
101 netbsdwinbind_getgrent_r(void *nsrv, void *nscb, va_list ap)
102 {
103         int             *retval = va_arg(ap, int *);
104         struct group    *grp    = va_arg(ap, struct group *);
105         char            *buffer = va_arg(ap, char *);
106         size_t           buflen = va_arg(ap, size_t);
107         struct group   **result = va_arg(ap, struct group **);
108
109         int     rv, rerrno;
110
111         *result = NULL;
112         rerrno = 0;
113
114         rv = _nss_winbind_getgrent_r(grp, buffer, buflen, &rerrno);
115         if (rv == NS_SUCCESS)
116                 *result = grp;
117         else
118                 *retval = rerrno;
119         return rv;
120 }
121
122 int
123 netbsdwinbind_getgrgid(void *nsrv, void *nscb, va_list ap)
124 {
125         struct group   **retval = va_arg(ap, struct group **);
126         gid_t            gid    = va_arg(ap, gid_t);
127
128         int     rv, rerrno;
129
130         *retval = NULL;
131         rv = _nss_winbind_getgrgid_r(gid, &_winbind_group,
132             _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
133         if (rv == NS_SUCCESS)
134                 *retval = &_winbind_group;
135         return rv;
136 }
137
138 int
139 netbsdwinbind_getgrgid_r(void *nsrv, void *nscb, va_list ap)
140 {
141         int             *retval = va_arg(ap, int *);
142         gid_t            gid    = va_arg(ap, gid_t);
143         struct group    *grp    = va_arg(ap, struct group *);
144         char            *buffer = va_arg(ap, char *);
145         size_t           buflen = va_arg(ap, size_t);
146         struct group   **result = va_arg(ap, struct group **);
147
148         int     rv, rerrno;
149
150         *result = NULL;
151         rerrno = 0;
152
153         rv = _nss_winbind_getgrgid_r(gid, grp, buffer, buflen, &rerrno);
154         if (rv == NS_SUCCESS)
155                 *result = grp;
156         else
157                 *retval = rerrno;
158         return rv;
159 }
160
161 int
162 netbsdwinbind_getgrnam(void *nsrv, void *nscb, va_list ap)
163 {
164         struct group   **retval = va_arg(ap, struct group **);
165         const char      *name   = va_arg(ap, const char *);
166
167         int     rv, rerrno;
168
169         *retval = NULL;
170         rv = _nss_winbind_getgrnam_r(name, &_winbind_group,
171             _winbind_groupbuf, sizeof(_winbind_groupbuf), &rerrno);
172         if (rv == NS_SUCCESS)
173                 *retval = &_winbind_group;
174         return rv;
175 }
176
177 int
178 netbsdwinbind_getgrnam_r(void *nsrv, void *nscb, va_list ap)
179 {
180         int             *retval = va_arg(ap, int *);
181         const char      *name   = va_arg(ap, const char *);
182         struct group    *grp    = va_arg(ap, struct group *);
183         char            *buffer = va_arg(ap, char *);
184         size_t           buflen = va_arg(ap, size_t);
185         struct group   **result = va_arg(ap, struct group **);
186
187         int     rv, rerrno;
188
189         *result = NULL;
190         rerrno = 0;
191
192         rv = _nss_winbind_getgrnam_r(name, grp, buffer, buflen, &rerrno);
193         if (rv == NS_SUCCESS)
194                 *result = grp;
195         else
196                 *retval = rerrno;
197         return rv;
198 }
199
200 int
201 netbsdwinbind_getgroupmembership(void *nsrv, void *nscb, va_list ap)
202 {
203         int             *result = va_arg(ap, int *);
204         const char      *uname  = va_arg(ap, const char *);
205         gid_t           *groups = va_arg(ap, gid_t *);
206         int              maxgrp = va_arg(ap, int);
207         int             *groupc = va_arg(ap, int *);
208
209         struct winbindd_request request;
210         struct winbindd_response response;
211         gid_t   *wblistv;
212         int     wblistc, i, isdup, dupc;
213
214         ZERO_STRUCT(request);
215         ZERO_STRUCT(response);
216         strncpy(request.data.username, uname,
217                                 sizeof(request.data.username) - 1);
218         i = winbindd_request_response(NULL, WINBINDD_GETGROUPS,
219                                       &request, &response);
220         if (i != NSS_STATUS_SUCCESS)
221                 return NS_NOTFOUND;
222         wblistv = (gid_t *)response.extra_data.data;
223         wblistc = response.data.num_entries;
224
225         for (i = 0; i < wblistc; i++) {                 /* add winbind gids */
226                 isdup = 0;                              /* skip duplicates */
227                 for (dupc = 0; dupc < MIN(maxgrp, *groupc); dupc++) {
228                         if (groups[dupc] == wblistv[i]) {
229                                 isdup = 1;
230                                 break;
231                         }
232                 }
233                 if (isdup)
234                         continue;
235                 if (*groupc < maxgrp)                   /* add this gid */
236                         groups[*groupc] = wblistv[i];
237                 else
238                         *result = -1;
239                 (*groupc)++;
240         }
241         SAFE_FREE(wblistv);
242         return NS_NOTFOUND;
243 }
244
245
246 /*
247         passwd functions
248         ----------------
249 */
250
251 static struct passwd    _winbind_passwd;
252 static char             _winbind_passwdbuf[1024];
253
254 int
255 netbsdwinbind_endpwent(void *nsrv, void *nscb, va_list ap)
256 {
257         int     rv;
258
259         rv = _nss_winbind_endpwent();
260         return rv;
261 }
262
263 int
264 netbsdwinbind_setpwent(void *nsrv, void *nscb, va_list ap)
265 {
266         int     rv;
267
268         rv = _nss_winbind_setpwent();
269         return rv;
270 }
271
272 int
273 netbsdwinbind_getpwent(void *nsrv, void *nscb, va_list ap)
274 {
275         struct passwd  **retval = va_arg(ap, struct passwd **);
276
277         int     rv, rerrno;
278
279         *retval = NULL;
280
281         rv = _nss_winbind_getpwent_r(&_winbind_passwd,
282             _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
283         if (rv == NS_SUCCESS)
284                 *retval = &_winbind_passwd;
285         return rv;
286 }
287
288 int
289 netbsdwinbind_getpwent_r(void *nsrv, void *nscb, va_list ap)
290 {
291         int             *retval = va_arg(ap, int *);
292         struct passwd   *pw     = va_arg(ap, struct passwd *);
293         char            *buffer = va_arg(ap, char *);
294         size_t           buflen = va_arg(ap, size_t);
295         struct passwd  **result = va_arg(ap, struct passwd **);
296
297         int     rv, rerrno;
298
299         *result = NULL;
300         rerrno = 0;
301
302         rv = _nss_winbind_getpwent_r(pw, buffer, buflen, &rerrno);
303         if (rv == NS_SUCCESS)
304                 *result = pw;
305         else
306                 *retval = rerrno;
307         return rv;
308 }
309
310 int
311 netbsdwinbind_getpwnam(void *nsrv, void *nscb, va_list ap)
312 {
313         struct passwd  **retval = va_arg(ap, struct passwd **);
314         const char      *name   = va_arg(ap, const char *);
315
316         int     rv, rerrno;
317
318         *retval = NULL;
319         rv = _nss_winbind_getpwnam_r(name, &_winbind_passwd,
320             _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
321         if (rv == NS_SUCCESS)
322                 *retval = &_winbind_passwd;
323         return rv;
324 }
325
326 int
327 netbsdwinbind_getpwnam_r(void *nsrv, void *nscb, va_list ap)
328 {
329         int             *retval = va_arg(ap, int *);
330         const char      *name   = va_arg(ap, const char *);
331         struct passwd   *pw     = va_arg(ap, struct passwd *);
332         char            *buffer = va_arg(ap, char *);
333         size_t           buflen = va_arg(ap, size_t);
334         struct passwd  **result = va_arg(ap, struct passwd **);
335
336         int     rv, rerrno;
337
338         *result = NULL;
339         rerrno = 0;
340
341         rv = _nss_winbind_getpwnam_r(name, pw, buffer, buflen, &rerrno);
342         if (rv == NS_SUCCESS)
343                 *result = pw;
344         else
345                 *retval = rerrno;
346         return rv;
347 }
348
349 int
350 netbsdwinbind_getpwuid(void *nsrv, void *nscb, va_list ap)
351 {
352         struct passwd  **retval = va_arg(ap, struct passwd **);
353         uid_t            uid    = va_arg(ap, uid_t);
354
355         int     rv, rerrno;
356
357         *retval = NULL;
358         rv = _nss_winbind_getpwuid_r(uid, &_winbind_passwd,
359             _winbind_passwdbuf, sizeof(_winbind_passwdbuf), &rerrno);
360         if (rv == NS_SUCCESS)
361                 *retval = &_winbind_passwd;
362         return rv;
363 }
364
365 int
366 netbsdwinbind_getpwuid_r(void *nsrv, void *nscb, va_list ap)
367 {
368         int             *retval = va_arg(ap, int *);
369         uid_t            uid    = va_arg(ap, uid_t);
370         struct passwd   *pw     = va_arg(ap, struct passwd *);
371         char            *buffer = va_arg(ap, char *);
372         size_t           buflen = va_arg(ap, size_t);
373         struct passwd  **result = va_arg(ap, struct passwd **);
374
375         int     rv, rerrno;
376
377         *result = NULL;
378         rerrno = 0;
379
380         rv = _nss_winbind_getpwuid_r(uid, pw, buffer, buflen, &rerrno);
381         if (rv == NS_SUCCESS)
382                 *result = pw;
383         else
384                 *retval = rerrno;
385         return rv;
386 }
387
388
389 /*
390         nsswitch module setup
391         ---------------------
392 */
393
394
395 static ns_mtab winbind_methods[] = {
396
397 { NSDB_GROUP, "endgrent",       netbsdwinbind_endgrent,         NULL },
398 { NSDB_GROUP, "getgrent",       netbsdwinbind_getgrent,         NULL },
399 { NSDB_GROUP, "getgrent_r",     netbsdwinbind_getgrent_r,       NULL },
400 { NSDB_GROUP, "getgrgid",       netbsdwinbind_getgrgid,         NULL },
401 { NSDB_GROUP, "getgrgid_r",     netbsdwinbind_getgrgid_r,       NULL },
402 { NSDB_GROUP, "getgrnam",       netbsdwinbind_getgrnam,         NULL },
403 { NSDB_GROUP, "getgrnam_r",     netbsdwinbind_getgrnam_r,       NULL },
404 { NSDB_GROUP, "setgrent",       netbsdwinbind_setgrent,         NULL },
405 { NSDB_GROUP, "setgroupent",    netbsdwinbind_setgrent,         NULL },
406 { NSDB_GROUP, "getgroupmembership", netbsdwinbind_getgroupmembership, NULL },
407
408 { NSDB_PASSWD, "endpwent",      netbsdwinbind_endpwent,         NULL },
409 { NSDB_PASSWD, "getpwent",      netbsdwinbind_getpwent,         NULL },
410 { NSDB_PASSWD, "getpwent_r",    netbsdwinbind_getpwent_r,       NULL },
411 { NSDB_PASSWD, "getpwnam",      netbsdwinbind_getpwnam,         NULL },
412 { NSDB_PASSWD, "getpwnam_r",    netbsdwinbind_getpwnam_r,       NULL },
413 { NSDB_PASSWD, "getpwuid",      netbsdwinbind_getpwuid,         NULL },
414 { NSDB_PASSWD, "getpwuid_r",    netbsdwinbind_getpwuid_r,       NULL },
415 { NSDB_PASSWD, "setpassent",    netbsdwinbind_setpwent,         NULL },
416 { NSDB_PASSWD, "setpwent",      netbsdwinbind_setpwent,         NULL },
417
418 };
419
420 ns_mtab *
421 nss_module_register(const char *source, unsigned int *mtabsize,
422     nss_module_unregister_fn *unreg)
423 {
424         *mtabsize = sizeof(winbind_methods)/sizeof(winbind_methods[0]);
425         *unreg = NULL;
426         return (winbind_methods);
427 }
428
429 #endif /* NSS_MODULE_INTERFACE_VERSION && HAVE_GETPWENT_R */