r19725: sync samba3's ldb with samba4
[kai/samba-autobuild/.git] / source3 / lib / ldb / nssldb / ldb-grp.c
1 /* 
2    LDB nsswitch module
3
4    Copyright (C) Simo Sorce 2006
5    
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10    
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15    
16    You should have received a copy of the GNU Library General Public
17    License along with this library; if not, write to the
18    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA  02111-1307, USA.   
20 */
21
22 #include "ldb-nss.h"
23
24 extern struct _ldb_nss_context *_ldb_nss_ctx;
25
26 const char *_ldb_nss_gr_attrs[] = {
27         "cn",
28         "userPassword",
29         "gidNumber",
30         NULL
31 };
32
33 const char *_ldb_nss_mem_attrs[] = {
34         "uid",
35         NULL
36 };
37
38 #define _NSS_LDB_ENOMEM(amem) \
39         do { \
40                 if ( ! amem) { \
41                         errno = ENOMEM; \
42                         talloc_free(memctx); \
43                         return NSS_STATUS_UNAVAIL; \
44                 } \
45         } while(0)
46
47 /* This setgrent, getgrent, endgrent is not very efficient */
48
49 NSS_STATUS _nss_ldb_setgrent(void)
50 {
51         int ret;
52
53         ret = _ldb_nss_init();
54         if (ret != NSS_STATUS_SUCCESS) {
55                 return ret;
56         }
57
58         _ldb_nss_ctx->gr_cur = 0;
59         if (_ldb_nss_ctx->gr_res != NULL) {
60                 talloc_free(_ldb_nss_ctx->gr_res);
61                 _ldb_nss_ctx->gr_res = NULL;
62         }
63
64         ret = ldb_search(_ldb_nss_ctx->ldb,
65                          _ldb_nss_ctx->base,
66                          LDB_SCOPE_SUBTREE,
67                          _LDB_NSS_GRENT_FILTER,
68                          _ldb_nss_gr_attrs,
69                          &_ldb_nss_ctx->gr_res);
70         if (ret != LDB_SUCCESS) {
71                 return NSS_STATUS_UNAVAIL;
72         }
73
74         return NSS_STATUS_SUCCESS;
75 }
76
77 NSS_STATUS _nss_ldb_endgrent(void)
78 {
79         int ret;
80
81         ret = _ldb_nss_init();
82         if (ret != NSS_STATUS_SUCCESS) {
83                 return ret;
84         }
85
86         _ldb_nss_ctx->gr_cur = 0;
87         if (_ldb_nss_ctx->gr_res) {
88                 talloc_free(_ldb_nss_ctx->gr_res);
89                 _ldb_nss_ctx->gr_res = NULL;
90         }
91
92         return NSS_STATUS_SUCCESS;
93 }
94
95 NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop)
96 {
97         int ret;
98         struct ldb_result *res;
99
100         ret = _ldb_nss_init();
101         if (ret != NSS_STATUS_SUCCESS) {
102                 return ret;
103         }
104
105         *errnop = 0;
106
107         if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) {
108                 /* already returned all entries */
109                 return NSS_STATUS_NOTFOUND;
110         }
111
112         res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result);
113         if ( ! res) {
114                 errno = *errnop = ENOMEM;
115                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
116                 return NSS_STATUS_UNAVAIL;
117         }
118
119         ret = _ldb_nss_group_request(&res,
120                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, 
121                                 _ldb_nss_mem_attrs,
122                                 "member");
123
124         if (ret != NSS_STATUS_SUCCESS) {
125                 *errnop = errno;
126                 talloc_free(res);
127                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
128                 return ret;
129         }
130
131         ret = _ldb_nss_fill_group(result_buf,
132                                 buffer,
133                                 buflen,
134                                 errnop,
135                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur],
136                                 res);
137
138         talloc_free(res);
139
140         if (ret != NSS_STATUS_SUCCESS) {
141                 if (ret != NSS_STATUS_TRYAGAIN) {
142                         _ldb_nss_ctx->gr_cur++; /* skip this entry */
143                 }
144                 return ret;
145         }
146
147         /* this entry is ok, increment counter to nex entry */
148         _ldb_nss_ctx->gr_cur++;
149
150         return NSS_STATUS_SUCCESS;
151 }
152
153 NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
154 {
155         int ret;
156         char *filter;
157         TALLOC_CTX *ctx;
158         struct ldb_result *gr_res;
159         struct ldb_result *mem_res;
160
161         ret = _ldb_nss_init();
162         if (ret != NSS_STATUS_SUCCESS) {
163                 return ret;
164         }
165
166         ctx = talloc_new(_ldb_nss_ctx->ldb);
167         if ( ! ctx) {
168                 *errnop = errno = ENOMEM;
169                 return NSS_STATUS_UNAVAIL;
170         }
171
172         /* build the filter for this uid */
173         filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name);
174         if (filter == NULL) {
175                 /* this is a fatal error */
176                 *errnop = errno = ENOMEM;
177                 ret = NSS_STATUS_UNAVAIL;
178                 goto done;
179         }
180
181         /* search the entry */
182         ret = ldb_search(_ldb_nss_ctx->ldb,
183                          _ldb_nss_ctx->base,
184                          LDB_SCOPE_SUBTREE,
185                          filter,
186                          _ldb_nss_gr_attrs,
187                          &gr_res);
188         if (ret != LDB_SUCCESS) {
189                 /* this is a fatal error */
190                 *errnop = errno = ENOENT;
191                 ret = NSS_STATUS_UNAVAIL;
192                 goto done;
193         }
194
195         talloc_steal(ctx, gr_res);
196
197         /* if none found return */
198         if (gr_res->count == 0) {
199                 *errnop = errno = ENOENT;
200                 ret = NSS_STATUS_NOTFOUND;
201                 goto done;
202         }
203
204         if (gr_res->count != 1) {
205                 /* this is a fatal error */
206                 *errnop = errno = ENOENT;
207                 ret = NSS_STATUS_UNAVAIL;
208                 goto done;
209         }
210
211         mem_res = talloc_zero(ctx, struct ldb_result);
212         if ( ! mem_res) {
213                 errno = *errnop = ENOMEM;
214                 ret = NSS_STATUS_UNAVAIL;
215                 goto done;
216         }
217
218         ret = _ldb_nss_group_request(&mem_res,
219                                         gr_res->msgs[0]->dn,
220                                         _ldb_nss_mem_attrs,
221                                         "member");
222
223         if (ret != NSS_STATUS_SUCCESS) {
224                 *errnop = errno;
225                 goto done;
226         }
227
228         ret = _ldb_nss_fill_group(result_buf,
229                                 buffer,
230                                 buflen,
231                                 errnop,
232                                 gr_res->msgs[0],
233                                 mem_res);
234
235         if (ret != NSS_STATUS_SUCCESS) {
236                 goto done;
237         }
238
239         ret = NSS_STATUS_SUCCESS;
240 done:
241         talloc_free(ctx);
242         return ret;
243 }
244
245 NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
246 {
247         int ret;
248         char *filter;
249         TALLOC_CTX *ctx;
250         struct ldb_result *gr_res;
251         struct ldb_result *mem_res;
252
253         if (gid == 0) { /* we don't serve root gid by policy */
254                 *errnop = errno = ENOENT;
255                 return NSS_STATUS_NOTFOUND;
256         }
257
258         ret = _ldb_nss_init();
259         if (ret != NSS_STATUS_SUCCESS) {
260                 return ret;
261         }
262
263         ctx = talloc_new(_ldb_nss_ctx->ldb);
264         if ( ! ctx) {
265                 *errnop = errno = ENOMEM;
266                 return NSS_STATUS_UNAVAIL;
267         }
268
269         /* build the filter for this uid */
270         filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid);
271         if (filter == NULL) {
272                 /* this is a fatal error */
273                 *errnop = errno = ENOMEM;
274                 ret = NSS_STATUS_UNAVAIL;
275                 goto done;
276         }
277
278         /* search the entry */
279         ret = ldb_search(_ldb_nss_ctx->ldb,
280                          _ldb_nss_ctx->base,
281                          LDB_SCOPE_SUBTREE,
282                          filter,
283                          _ldb_nss_gr_attrs,
284                          &gr_res);
285         if (ret != LDB_SUCCESS) {
286                 /* this is a fatal error */
287                 *errnop = errno = ENOENT;
288                 ret = NSS_STATUS_UNAVAIL;
289                 goto done;
290         }
291
292         talloc_steal(ctx, gr_res);
293
294         /* if none found return */
295         if (gr_res->count == 0) {
296                 *errnop = errno = ENOENT;
297                 ret = NSS_STATUS_NOTFOUND;
298                 goto done;
299         }
300
301         if (gr_res->count != 1) {
302                 /* this is a fatal error */
303                 *errnop = errno = ENOENT;
304                 ret = NSS_STATUS_UNAVAIL;
305                 goto done;
306         }
307
308         mem_res = talloc_zero(ctx, struct ldb_result);
309         if ( ! mem_res) {
310                 errno = *errnop = ENOMEM;
311                 ret = NSS_STATUS_UNAVAIL;
312                 goto done;
313         }
314
315         ret = _ldb_nss_group_request(&mem_res,
316                                         gr_res->msgs[0]->dn,
317                                         _ldb_nss_mem_attrs,
318                                         "member");
319
320         if (ret != NSS_STATUS_SUCCESS) {
321                 *errnop = errno;
322                 goto done;
323         }
324
325         ret = _ldb_nss_fill_group(result_buf,
326                                 buffer,
327                                 buflen,
328                                 errnop,
329                                 gr_res->msgs[0],
330                                 mem_res);
331
332         if (ret != NSS_STATUS_SUCCESS) {
333                 goto done;
334         }
335
336         ret = NSS_STATUS_SUCCESS;
337 done:
338         talloc_free(ctx);
339         return ret;
340 }
341
342 NSS_STATUS _nss_ldb_initgroups_dyn(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop)
343 {
344         int ret;
345         char *filter;
346         const char * attrs[] = { "uidNumber", "gidNumber", NULL };
347         struct ldb_result *uid_res;
348         struct ldb_result *mem_res;
349
350         ret = _ldb_nss_init();
351         if (ret != NSS_STATUS_SUCCESS) {
352                 return ret;
353         }
354
355         mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
356         if ( ! mem_res) {
357                 errno = *errnop = ENOMEM;
358                 return NSS_STATUS_UNAVAIL;
359         }
360
361         /* build the filter for this name */
362         filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
363         if (filter == NULL) {
364                 /* this is a fatal error */
365                 *errnop = errno = ENOENT;
366                 ret = NSS_STATUS_UNAVAIL;
367                 goto done;
368         }
369
370         /* search the entry */
371         ret = ldb_search(_ldb_nss_ctx->ldb,
372                          _ldb_nss_ctx->base,
373                          LDB_SCOPE_SUBTREE,
374                          filter,
375                          attrs,
376                          &uid_res);
377         if (ret != LDB_SUCCESS) {
378                 /* this is a fatal error */
379                 *errnop = errno = ENOENT;
380                 ret = NSS_STATUS_UNAVAIL;
381                 goto done;
382         }
383
384         talloc_steal(mem_res, uid_res);
385
386         /* if none found return */
387         if (uid_res->count == 0) {
388                 *errnop = errno = ENOENT;
389                 ret = NSS_STATUS_NOTFOUND;
390                 goto done;
391         }
392
393         if (uid_res->count != 1) {
394                 /* this is a fatal error */
395                 *errnop = errno = ENOENT;
396                 ret = NSS_STATUS_UNAVAIL;
397                 goto done;
398         }
399
400         ret = _ldb_nss_group_request(&mem_res,
401                                         uid_res->msgs[0]->dn,
402                                         attrs,
403                                         "memberOf");
404
405         if (ret != NSS_STATUS_SUCCESS) {
406                 *errnop = errno;
407                 goto done;
408         }
409
410         ret = _ldb_nss_fill_initgr(group,
411                                 limit,
412                                 start,
413                                 size,
414                                 groups,
415                                 errnop,
416                                 mem_res);
417
418         if (ret != NSS_STATUS_SUCCESS) {
419                 goto done;
420         }
421
422         ret = NSS_STATUS_SUCCESS;
423
424 done:
425         talloc_free(mem_res);
426         return ret;
427 }