s4-dbcheck: support the 'none' option for prompts
[garming/samba-autobuild/.git] / source4 / 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 Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 3 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 Lesser General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "ldb-nss.h"
21
22 extern struct _ldb_nss_context *_ldb_nss_ctx;
23
24 const char *_ldb_nss_gr_attrs[] = {
25         "cn",
26         "userPassword",
27         "gidNumber",
28         NULL
29 };
30
31 const char *_ldb_nss_mem_attrs[] = {
32         "uid",
33         NULL
34 };
35
36 #define _NSS_LDB_ENOMEM(amem) \
37         do { \
38                 if ( ! amem) { \
39                         errno = ENOMEM; \
40                         talloc_free(memctx); \
41                         return NSS_STATUS_UNAVAIL; \
42                 } \
43         } while(0)
44
45 /* This setgrent, getgrent, endgrent is not very efficient */
46
47 NSS_STATUS _nss_ldb_setgrent(void)
48 {
49         int ret;
50
51         ret = _ldb_nss_init();
52         if (ret != NSS_STATUS_SUCCESS) {
53                 return ret;
54         }
55
56         _ldb_nss_ctx->gr_cur = 0;
57         if (_ldb_nss_ctx->gr_res != NULL) {
58                 talloc_free(_ldb_nss_ctx->gr_res);
59                 _ldb_nss_ctx->gr_res = NULL;
60         }
61
62         ret = ldb_search(_ldb_nss_ctx->ldb,
63                          _ldb_nss_ctx->ldb,
64                          &_ldb_nss_ctx->gr_res,
65                          _ldb_nss_ctx->base,
66                          LDB_SCOPE_SUBTREE,
67                          _ldb_nss_gr_attrs,
68                          _LDB_NSS_GRENT_FILTER);
69         if (ret != LDB_SUCCESS) {
70                 return NSS_STATUS_UNAVAIL;
71         }
72
73         return NSS_STATUS_SUCCESS;
74 }
75
76 NSS_STATUS _nss_ldb_endgrent(void)
77 {
78         int ret;
79
80         ret = _ldb_nss_init();
81         if (ret != NSS_STATUS_SUCCESS) {
82                 return ret;
83         }
84
85         _ldb_nss_ctx->gr_cur = 0;
86         if (_ldb_nss_ctx->gr_res) {
87                 talloc_free(_ldb_nss_ctx->gr_res);
88                 _ldb_nss_ctx->gr_res = NULL;
89         }
90
91         return NSS_STATUS_SUCCESS;
92 }
93
94 NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop)
95 {
96         int ret;
97         struct ldb_result *res;
98
99         ret = _ldb_nss_init();
100         if (ret != NSS_STATUS_SUCCESS) {
101                 return ret;
102         }
103
104         *errnop = 0;
105
106         if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) {
107                 /* already returned all entries */
108                 return NSS_STATUS_NOTFOUND;
109         }
110
111         res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result);
112         if ( ! res) {
113                 errno = *errnop = ENOMEM;
114                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
115                 return NSS_STATUS_UNAVAIL;
116         }
117
118         ret = _ldb_nss_group_request(&res,
119                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, 
120                                 _ldb_nss_mem_attrs,
121                                 "member");
122
123         if (ret != NSS_STATUS_SUCCESS) {
124                 *errnop = errno;
125                 talloc_free(res);
126                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
127                 return ret;
128         }
129
130         ret = _ldb_nss_fill_group(result_buf,
131                                 buffer,
132                                 buflen,
133                                 errnop,
134                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur],
135                                 res);
136
137         talloc_free(res);
138
139         if (ret != NSS_STATUS_SUCCESS) {
140                 if (ret != NSS_STATUS_TRYAGAIN) {
141                         _ldb_nss_ctx->gr_cur++; /* skip this entry */
142                 }
143                 return ret;
144         }
145
146         /* this entry is ok, increment counter to nex entry */
147         _ldb_nss_ctx->gr_cur++;
148
149         return NSS_STATUS_SUCCESS;
150 }
151
152 NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
153 {
154         int ret;
155         char *filter;
156         TALLOC_CTX *ctx;
157         struct ldb_result *gr_res;
158         struct ldb_result *mem_res;
159
160         ret = _ldb_nss_init();
161         if (ret != NSS_STATUS_SUCCESS) {
162                 return ret;
163         }
164
165         ctx = talloc_new(_ldb_nss_ctx->ldb);
166         if ( ! ctx) {
167                 *errnop = errno = ENOMEM;
168                 return NSS_STATUS_UNAVAIL;
169         }
170
171         /* build the filter for this uid */
172         filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name);
173         if (filter == NULL) {
174                 /* this is a fatal error */
175                 *errnop = errno = ENOMEM;
176                 ret = NSS_STATUS_UNAVAIL;
177                 goto done;
178         }
179
180         /* search the entry */
181         ret = ldb_search(_ldb_nss_ctx->ldb,
182                          _ldb_nss_ctx->ldb,
183                          &gr_res,
184                          _ldb_nss_ctx->base,
185                          LDB_SCOPE_SUBTREE,
186                          _ldb_nss_gr_attrs,
187                          filter);
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->ldb,
281                          &gr_res,
282                          _ldb_nss_ctx->base,
283                          LDB_SCOPE_SUBTREE,
284                          _ldb_nss_gr_attrs,
285                          filter);
286         if (ret != LDB_SUCCESS) {
287                 /* this is a fatal error */
288                 *errnop = errno = ENOENT;
289                 ret = NSS_STATUS_UNAVAIL;
290                 goto done;
291         }
292
293         talloc_steal(ctx, gr_res);
294
295         /* if none found return */
296         if (gr_res->count == 0) {
297                 *errnop = errno = ENOENT;
298                 ret = NSS_STATUS_NOTFOUND;
299                 goto done;
300         }
301
302         if (gr_res->count != 1) {
303                 /* this is a fatal error */
304                 *errnop = errno = ENOENT;
305                 ret = NSS_STATUS_UNAVAIL;
306                 goto done;
307         }
308
309         mem_res = talloc_zero(ctx, struct ldb_result);
310         if ( ! mem_res) {
311                 errno = *errnop = ENOMEM;
312                 ret = NSS_STATUS_UNAVAIL;
313                 goto done;
314         }
315
316         ret = _ldb_nss_group_request(&mem_res,
317                                         gr_res->msgs[0]->dn,
318                                         _ldb_nss_mem_attrs,
319                                         "member");
320
321         if (ret != NSS_STATUS_SUCCESS) {
322                 *errnop = errno;
323                 goto done;
324         }
325
326         ret = _ldb_nss_fill_group(result_buf,
327                                 buffer,
328                                 buflen,
329                                 errnop,
330                                 gr_res->msgs[0],
331                                 mem_res);
332
333         if (ret != NSS_STATUS_SUCCESS) {
334                 goto done;
335         }
336
337         ret = NSS_STATUS_SUCCESS;
338 done:
339         talloc_free(ctx);
340         return ret;
341 }
342
343 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)
344 {
345         int ret;
346         char *filter;
347         const char * attrs[] = { "uidNumber", "gidNumber", NULL };
348         struct ldb_result *uid_res;
349         struct ldb_result *mem_res;
350
351         ret = _ldb_nss_init();
352         if (ret != NSS_STATUS_SUCCESS) {
353                 return ret;
354         }
355
356         mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
357         if ( ! mem_res) {
358                 errno = *errnop = ENOMEM;
359                 return NSS_STATUS_UNAVAIL;
360         }
361
362         /* build the filter for this name */
363         filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
364         if (filter == NULL) {
365                 /* this is a fatal error */
366                 *errnop = errno = ENOENT;
367                 ret = NSS_STATUS_UNAVAIL;
368                 goto done;
369         }
370
371         /* search the entry */
372         ret = ldb_search(_ldb_nss_ctx->ldb,
373                          _ldb_nss_ctx->ldb,
374                          &uid_res,
375                          _ldb_nss_ctx->base,
376                          LDB_SCOPE_SUBTREE,
377                          attrs,
378                          filter);
379         if (ret != LDB_SUCCESS) {
380                 /* this is a fatal error */
381                 *errnop = errno = ENOENT;
382                 ret = NSS_STATUS_UNAVAIL;
383                 goto done;
384         }
385
386         talloc_steal(mem_res, uid_res);
387
388         /* if none found return */
389         if (uid_res->count == 0) {
390                 *errnop = errno = ENOENT;
391                 ret = NSS_STATUS_NOTFOUND;
392                 goto done;
393         }
394
395         if (uid_res->count != 1) {
396                 /* this is a fatal error */
397                 *errnop = errno = ENOENT;
398                 ret = NSS_STATUS_UNAVAIL;
399                 goto done;
400         }
401
402         ret = _ldb_nss_group_request(&mem_res,
403                                         uid_res->msgs[0]->dn,
404                                         attrs,
405                                         "memberOf");
406
407         if (ret != NSS_STATUS_SUCCESS) {
408                 *errnop = errno;
409                 goto done;
410         }
411
412         ret = _ldb_nss_fill_initgr(group,
413                                 limit,
414                                 start,
415                                 size,
416                                 groups,
417                                 errnop,
418                                 mem_res);
419
420         if (ret != NSS_STATUS_SUCCESS) {
421                 goto done;
422         }
423
424         ret = NSS_STATUS_SUCCESS;
425
426 done:
427         talloc_free(mem_res);
428         return ret;
429 }