842a668d2f2c1eb29fdaa80d1322f5f1f49fcd89
[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 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, _ldb_nss_ctx->ldb,
63                          &_ldb_nss_ctx->gr_res,
64                          _ldb_nss_ctx->base,
65                          LDB_SCOPE_SUBTREE, 
66                          _ldb_nss_gr_attrs,
67                          _LDB_NSS_GRENT_FILTER);
68         if (ret != LDB_SUCCESS) {
69                 return NSS_STATUS_UNAVAIL;
70         }
71
72         return NSS_STATUS_SUCCESS;
73 }
74
75 NSS_STATUS _nss_ldb_endgrent(void)
76 {
77         int ret;
78
79         ret = _ldb_nss_init();
80         if (ret != NSS_STATUS_SUCCESS) {
81                 return ret;
82         }
83
84         _ldb_nss_ctx->gr_cur = 0;
85         if (_ldb_nss_ctx->gr_res) {
86                 talloc_free(_ldb_nss_ctx->gr_res);
87                 _ldb_nss_ctx->gr_res = NULL;
88         }
89
90         return NSS_STATUS_SUCCESS;
91 }
92
93 NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop)
94 {
95         int ret;
96         struct ldb_result *res;
97
98         ret = _ldb_nss_init();
99         if (ret != NSS_STATUS_SUCCESS) {
100                 return ret;
101         }
102
103         *errnop = 0;
104
105         if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) {
106                 /* already returned all entries */
107                 return NSS_STATUS_NOTFOUND;
108         }
109
110         res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result);
111         if ( ! res) {
112                 errno = *errnop = ENOMEM;
113                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
114                 return NSS_STATUS_UNAVAIL;
115         }
116
117         ret = _ldb_nss_group_request(&res,
118                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, 
119                                 _ldb_nss_mem_attrs,
120                                 "member");
121
122         if (ret != NSS_STATUS_SUCCESS) {
123                 *errnop = errno;
124                 talloc_free(res);
125                 _ldb_nss_ctx->gr_cur++; /* skip this entry */
126                 return ret;
127         }
128
129         ret = _ldb_nss_fill_group(result_buf,
130                                 buffer,
131                                 buflen,
132                                 errnop,
133                                 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur],
134                                 res);
135
136         talloc_free(res);
137
138         if (ret != NSS_STATUS_SUCCESS) {
139                 if (ret != NSS_STATUS_TRYAGAIN) {
140                         _ldb_nss_ctx->gr_cur++; /* skip this entry */
141                 }
142                 return ret;
143         }
144
145         /* this entry is ok, increment counter to nex entry */
146         _ldb_nss_ctx->gr_cur++;
147
148         return NSS_STATUS_SUCCESS;
149 }
150
151 NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
152 {
153         int ret;
154         char *filter;
155         TALLOC_CTX *ctx;
156         struct ldb_result *gr_res;
157         struct ldb_result *mem_res;
158
159         ret = _ldb_nss_init();
160         if (ret != NSS_STATUS_SUCCESS) {
161                 return ret;
162         }
163
164         ctx = talloc_new(_ldb_nss_ctx->ldb);
165         if ( ! ctx) {
166                 *errnop = errno = ENOMEM;
167                 return NSS_STATUS_UNAVAIL;
168         }
169
170         /* build the filter for this uid */
171         filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name);
172         if (filter == NULL) {
173                 /* this is a fatal error */
174                 *errnop = errno = ENOMEM;
175                 ret = NSS_STATUS_UNAVAIL;
176                 goto done;
177         }
178
179         /* search the entry */
180         ret = ldb_search(_ldb_nss_ctx->ldb, _ldb_nss_ctx->ldb, &gr_res,
181                          _ldb_nss_ctx->base,
182                          LDB_SCOPE_SUBTREE,
183                          _ldb_nss_gr_attrs,
184                          filter);
185         if (ret != LDB_SUCCESS) {
186                 /* this is a fatal error */
187                 *errnop = errno = ENOENT;
188                 ret = NSS_STATUS_UNAVAIL;
189                 goto done;
190         }
191
192         talloc_steal(ctx, gr_res);
193
194         /* if none found return */
195         if (gr_res->count == 0) {
196                 *errnop = errno = ENOENT;
197                 ret = NSS_STATUS_NOTFOUND;
198                 goto done;
199         }
200
201         if (gr_res->count != 1) {
202                 /* this is a fatal error */
203                 *errnop = errno = ENOENT;
204                 ret = NSS_STATUS_UNAVAIL;
205                 goto done;
206         }
207
208         mem_res = talloc_zero(ctx, struct ldb_result);
209         if ( ! mem_res) {
210                 errno = *errnop = ENOMEM;
211                 ret = NSS_STATUS_UNAVAIL;
212                 goto done;
213         }
214
215         ret = _ldb_nss_group_request(&mem_res,
216                                         gr_res->msgs[0]->dn,
217                                         _ldb_nss_mem_attrs,
218                                         "member");
219
220         if (ret != NSS_STATUS_SUCCESS) {
221                 *errnop = errno;
222                 goto done;
223         }
224
225         ret = _ldb_nss_fill_group(result_buf,
226                                 buffer,
227                                 buflen,
228                                 errnop,
229                                 gr_res->msgs[0],
230                                 mem_res);
231
232         if (ret != NSS_STATUS_SUCCESS) {
233                 goto done;
234         }
235
236         ret = NSS_STATUS_SUCCESS;
237 done:
238         talloc_free(ctx);
239         return ret;
240 }
241
242 NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
243 {
244         int ret;
245         char *filter;
246         TALLOC_CTX *ctx;
247         struct ldb_result *gr_res;
248         struct ldb_result *mem_res;
249
250         if (gid == 0) { /* we don't serve root gid by policy */
251                 *errnop = errno = ENOENT;
252                 return NSS_STATUS_NOTFOUND;
253         }
254
255         ret = _ldb_nss_init();
256         if (ret != NSS_STATUS_SUCCESS) {
257                 return ret;
258         }
259
260         ctx = talloc_new(_ldb_nss_ctx->ldb);
261         if ( ! ctx) {
262                 *errnop = errno = ENOMEM;
263                 return NSS_STATUS_UNAVAIL;
264         }
265
266         /* build the filter for this uid */
267         filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid);
268         if (filter == NULL) {
269                 /* this is a fatal error */
270                 *errnop = errno = ENOMEM;
271                 ret = NSS_STATUS_UNAVAIL;
272                 goto done;
273         }
274
275         /* search the entry */
276         ret = ldb_search(_ldb_nss_ctx->ldb, _ldb_nss_ctx->ldb, &gr_res,
277                          _ldb_nss_ctx->base,
278                          LDB_SCOPE_SUBTREE,
279                          _ldb_nss_gr_attrs,
280                          filter);
281         if (ret != LDB_SUCCESS) {
282                 /* this is a fatal error */
283                 *errnop = errno = ENOENT;
284                 ret = NSS_STATUS_UNAVAIL;
285                 goto done;
286         }
287
288         talloc_steal(ctx, gr_res);
289
290         /* if none found return */
291         if (gr_res->count == 0) {
292                 *errnop = errno = ENOENT;
293                 ret = NSS_STATUS_NOTFOUND;
294                 goto done;
295         }
296
297         if (gr_res->count != 1) {
298                 /* this is a fatal error */
299                 *errnop = errno = ENOENT;
300                 ret = NSS_STATUS_UNAVAIL;
301                 goto done;
302         }
303
304         mem_res = talloc_zero(ctx, struct ldb_result);
305         if ( ! mem_res) {
306                 errno = *errnop = ENOMEM;
307                 ret = NSS_STATUS_UNAVAIL;
308                 goto done;
309         }
310
311         ret = _ldb_nss_group_request(&mem_res,
312                                         gr_res->msgs[0]->dn,
313                                         _ldb_nss_mem_attrs,
314                                         "member");
315
316         if (ret != NSS_STATUS_SUCCESS) {
317                 *errnop = errno;
318                 goto done;
319         }
320
321         ret = _ldb_nss_fill_group(result_buf,
322                                 buffer,
323                                 buflen,
324                                 errnop,
325                                 gr_res->msgs[0],
326                                 mem_res);
327
328         if (ret != NSS_STATUS_SUCCESS) {
329                 goto done;
330         }
331
332         ret = NSS_STATUS_SUCCESS;
333 done:
334         talloc_free(ctx);
335         return ret;
336 }
337
338 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)
339 {
340         int ret;
341         char *filter;
342         const char * attrs[] = { "uidNumber", "gidNumber", NULL };
343         struct ldb_result *uid_res;
344         struct ldb_result *mem_res;
345
346         ret = _ldb_nss_init();
347         if (ret != NSS_STATUS_SUCCESS) {
348                 return ret;
349         }
350
351         mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
352         if ( ! mem_res) {
353                 errno = *errnop = ENOMEM;
354                 return NSS_STATUS_UNAVAIL;
355         }
356
357         /* build the filter for this name */
358         filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
359         if (filter == NULL) {
360                 /* this is a fatal error */
361                 *errnop = errno = ENOENT;
362                 ret = NSS_STATUS_UNAVAIL;
363                 goto done;
364         }
365
366         /* search the entry */
367         ret = ldb_search(_ldb_nss_ctx->ldb, _ldb_nss_ctx->ldb, &uid_res,
368                          _ldb_nss_ctx->base,
369                          LDB_SCOPE_SUBTREE,
370                          attrs,
371                          filter);
372         if (ret != LDB_SUCCESS) {
373                 /* this is a fatal error */
374                 *errnop = errno = ENOENT;
375                 ret = NSS_STATUS_UNAVAIL;
376                 goto done;
377         }
378
379         talloc_steal(mem_res, uid_res);
380
381         /* if none found return */
382         if (uid_res->count == 0) {
383                 *errnop = errno = ENOENT;
384                 ret = NSS_STATUS_NOTFOUND;
385                 goto done;
386         }
387
388         if (uid_res->count != 1) {
389                 /* this is a fatal error */
390                 *errnop = errno = ENOENT;
391                 ret = NSS_STATUS_UNAVAIL;
392                 goto done;
393         }
394
395         ret = _ldb_nss_group_request(&mem_res,
396                                         uid_res->msgs[0]->dn,
397                                         attrs,
398                                         "memberOf");
399
400         if (ret != NSS_STATUS_SUCCESS) {
401                 *errnop = errno;
402                 goto done;
403         }
404
405         ret = _ldb_nss_fill_initgr(group,
406                                 limit,
407                                 start,
408                                 size,
409                                 groups,
410                                 errnop,
411                                 mem_res);
412
413         if (ret != NSS_STATUS_SUCCESS) {
414                 goto done;
415         }
416
417         ret = NSS_STATUS_SUCCESS;
418
419 done:
420         talloc_free(mem_res);
421         return ret;
422 }