f8121b25ca417da73889f733f0920c9bead34e5c
[nivanova/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 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 Library 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->base,
64                          LDB_SCOPE_SUBTREE,
65                          _LDB_NSS_GRENT_FILTER,
66                          _ldb_nss_gr_attrs,
67                          &_ldb_nss_ctx->gr_res);
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,
181                          _ldb_nss_ctx->base,
182                          LDB_SCOPE_SUBTREE,
183                          filter,
184                          _ldb_nss_gr_attrs,
185                          &gr_res);
186         if (ret != LDB_SUCCESS) {
187                 /* this is a fatal error */
188                 *errnop = errno = ENOENT;
189                 ret = NSS_STATUS_UNAVAIL;
190                 goto done;
191         }
192
193         talloc_steal(ctx, gr_res);
194
195         /* if none found return */
196         if (gr_res->count == 0) {
197                 *errnop = errno = ENOENT;
198                 ret = NSS_STATUS_NOTFOUND;
199                 goto done;
200         }
201
202         if (gr_res->count != 1) {
203                 /* this is a fatal error */
204                 *errnop = errno = ENOENT;
205                 ret = NSS_STATUS_UNAVAIL;
206                 goto done;
207         }
208
209         mem_res = talloc_zero(ctx, struct ldb_result);
210         if ( ! mem_res) {
211                 errno = *errnop = ENOMEM;
212                 ret = NSS_STATUS_UNAVAIL;
213                 goto done;
214         }
215
216         ret = _ldb_nss_group_request(&mem_res,
217                                         gr_res->msgs[0]->dn,
218                                         _ldb_nss_mem_attrs,
219                                         "member");
220
221         if (ret != NSS_STATUS_SUCCESS) {
222                 *errnop = errno;
223                 goto done;
224         }
225
226         ret = _ldb_nss_fill_group(result_buf,
227                                 buffer,
228                                 buflen,
229                                 errnop,
230                                 gr_res->msgs[0],
231                                 mem_res);
232
233         if (ret != NSS_STATUS_SUCCESS) {
234                 goto done;
235         }
236
237         ret = NSS_STATUS_SUCCESS;
238 done:
239         talloc_free(ctx);
240         return ret;
241 }
242
243 NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop)
244 {
245         int ret;
246         char *filter;
247         TALLOC_CTX *ctx;
248         struct ldb_result *gr_res;
249         struct ldb_result *mem_res;
250
251         if (gid == 0) { /* we don't serve root gid by policy */
252                 *errnop = errno = ENOENT;
253                 return NSS_STATUS_NOTFOUND;
254         }
255
256         ret = _ldb_nss_init();
257         if (ret != NSS_STATUS_SUCCESS) {
258                 return ret;
259         }
260
261         ctx = talloc_new(_ldb_nss_ctx->ldb);
262         if ( ! ctx) {
263                 *errnop = errno = ENOMEM;
264                 return NSS_STATUS_UNAVAIL;
265         }
266
267         /* build the filter for this uid */
268         filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid);
269         if (filter == NULL) {
270                 /* this is a fatal error */
271                 *errnop = errno = ENOMEM;
272                 ret = NSS_STATUS_UNAVAIL;
273                 goto done;
274         }
275
276         /* search the entry */
277         ret = ldb_search(_ldb_nss_ctx->ldb,
278                          _ldb_nss_ctx->base,
279                          LDB_SCOPE_SUBTREE,
280                          filter,
281                          _ldb_nss_gr_attrs,
282                          &gr_res);
283         if (ret != LDB_SUCCESS) {
284                 /* this is a fatal error */
285                 *errnop = errno = ENOENT;
286                 ret = NSS_STATUS_UNAVAIL;
287                 goto done;
288         }
289
290         talloc_steal(ctx, gr_res);
291
292         /* if none found return */
293         if (gr_res->count == 0) {
294                 *errnop = errno = ENOENT;
295                 ret = NSS_STATUS_NOTFOUND;
296                 goto done;
297         }
298
299         if (gr_res->count != 1) {
300                 /* this is a fatal error */
301                 *errnop = errno = ENOENT;
302                 ret = NSS_STATUS_UNAVAIL;
303                 goto done;
304         }
305
306         mem_res = talloc_zero(ctx, struct ldb_result);
307         if ( ! mem_res) {
308                 errno = *errnop = ENOMEM;
309                 ret = NSS_STATUS_UNAVAIL;
310                 goto done;
311         }
312
313         ret = _ldb_nss_group_request(&mem_res,
314                                         gr_res->msgs[0]->dn,
315                                         _ldb_nss_mem_attrs,
316                                         "member");
317
318         if (ret != NSS_STATUS_SUCCESS) {
319                 *errnop = errno;
320                 goto done;
321         }
322
323         ret = _ldb_nss_fill_group(result_buf,
324                                 buffer,
325                                 buflen,
326                                 errnop,
327                                 gr_res->msgs[0],
328                                 mem_res);
329
330         if (ret != NSS_STATUS_SUCCESS) {
331                 goto done;
332         }
333
334         ret = NSS_STATUS_SUCCESS;
335 done:
336         talloc_free(ctx);
337         return ret;
338 }
339
340 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)
341 {
342         int ret;
343         char *filter;
344         const char * attrs[] = { "uidNumber", "gidNumber", NULL };
345         struct ldb_result *uid_res;
346         struct ldb_result *mem_res;
347
348         ret = _ldb_nss_init();
349         if (ret != NSS_STATUS_SUCCESS) {
350                 return ret;
351         }
352
353         mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result);
354         if ( ! mem_res) {
355                 errno = *errnop = ENOMEM;
356                 return NSS_STATUS_UNAVAIL;
357         }
358
359         /* build the filter for this name */
360         filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user);
361         if (filter == NULL) {
362                 /* this is a fatal error */
363                 *errnop = errno = ENOENT;
364                 ret = NSS_STATUS_UNAVAIL;
365                 goto done;
366         }
367
368         /* search the entry */
369         ret = ldb_search(_ldb_nss_ctx->ldb,
370                          _ldb_nss_ctx->base,
371                          LDB_SCOPE_SUBTREE,
372                          filter,
373                          attrs,
374                          &uid_res);
375         if (ret != LDB_SUCCESS) {
376                 /* this is a fatal error */
377                 *errnop = errno = ENOENT;
378                 ret = NSS_STATUS_UNAVAIL;
379                 goto done;
380         }
381
382         talloc_steal(mem_res, uid_res);
383
384         /* if none found return */
385         if (uid_res->count == 0) {
386                 *errnop = errno = ENOENT;
387                 ret = NSS_STATUS_NOTFOUND;
388                 goto done;
389         }
390
391         if (uid_res->count != 1) {
392                 /* this is a fatal error */
393                 *errnop = errno = ENOENT;
394                 ret = NSS_STATUS_UNAVAIL;
395                 goto done;
396         }
397
398         ret = _ldb_nss_group_request(&mem_res,
399                                         uid_res->msgs[0]->dn,
400                                         attrs,
401                                         "memberOf");
402
403         if (ret != NSS_STATUS_SUCCESS) {
404                 *errnop = errno;
405                 goto done;
406         }
407
408         ret = _ldb_nss_fill_initgr(group,
409                                 limit,
410                                 start,
411                                 size,
412                                 groups,
413                                 errnop,
414                                 mem_res);
415
416         if (ret != NSS_STATUS_SUCCESS) {
417                 goto done;
418         }
419
420         ret = NSS_STATUS_SUCCESS;
421
422 done:
423         talloc_free(mem_res);
424         return ret;
425 }