librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/vl.git] / lib / ldb / nssldb / ldb-nss.c
blob92b0635561e71a467a3d6d4e180aaec6693ceabf
1 /*
2 LDB nsswitch module
4 Copyright (C) Simo Sorce 2006
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.
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.
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/>.
20 #include "ldb-nss.h"
22 struct _ldb_nss_context *_ldb_nss_ctx = NULL;
24 NSS_STATUS _ldb_nss_init(void)
26 int ret;
28 pid_t mypid = getpid();
30 if (_ldb_nss_ctx != NULL) {
31 if (_ldb_nss_ctx->pid == mypid) {
32 /* already initialized */
33 return NSS_STATUS_SUCCESS;
34 } else {
35 /* we are in a forked child now, reinitialize */
36 talloc_free(_ldb_nss_ctx);
37 _ldb_nss_ctx = NULL;
41 _ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid);
42 if (_ldb_nss_ctx == NULL) {
43 return NSS_STATUS_UNAVAIL;
46 _ldb_nss_ctx->pid = mypid;
48 _ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx, NULL);
49 if (_ldb_nss_ctx->ldb == NULL) {
50 goto failed;
53 ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
54 if (ret != LDB_SUCCESS) {
55 goto failed;
58 _ldb_nss_ctx->base = ldb_dn_new(_ldb_nss_ctx, _ldb_nss_ctx->ldb, _LDB_NSS_BASEDN);
59 if ( ! ldb_dn_validate(_ldb_nss_ctx->base)) {
60 goto failed;
63 _ldb_nss_ctx->pw_cur = 0;
64 _ldb_nss_ctx->pw_res = NULL;
65 _ldb_nss_ctx->gr_cur = 0;
66 _ldb_nss_ctx->gr_res = NULL;
68 return NSS_STATUS_SUCCESS;
70 failed:
71 /* talloc_free(_ldb_nss_ctx); */
72 _ldb_nss_ctx = NULL;
73 return NSS_STATUS_UNAVAIL;
76 NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
77 char *buffer,
78 int buflen,
79 int *errnop,
80 struct ldb_message *msg)
82 int len;
83 int bufpos;
84 const char *tmp;
86 bufpos = 0;
88 /* get username */
89 tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
90 if (tmp == NULL) {
91 /* this is a fatal error */
92 *errnop = errno = ENOENT;
93 return NSS_STATUS_UNAVAIL;
95 len = strlen(tmp)+1;
96 if (bufpos + len > buflen) {
97 /* buffer too small */
98 *errnop = errno = EAGAIN;
99 return NSS_STATUS_TRYAGAIN;
101 memcpy(&buffer[bufpos], tmp, len);
102 result->pw_name = &buffer[bufpos];
103 bufpos += len;
105 /* get userPassword */
106 tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
107 if (tmp == NULL) {
108 tmp = "LDB";
110 len = strlen(tmp)+1;
111 if (bufpos + len > buflen) {
112 /* buffer too small */
113 *errnop = errno = EAGAIN;
114 return NSS_STATUS_TRYAGAIN;
116 memcpy(&buffer[bufpos], tmp, len);
117 result->pw_passwd = &buffer[bufpos];
118 bufpos += len;
120 /* this backend never serves an uid 0 user */
121 result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
122 if (result->pw_uid == 0) {
123 /* this is a fatal error */
124 *errnop = errno = ENOENT;
125 return NSS_STATUS_UNAVAIL;
128 result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
129 if (result->pw_gid == 0) {
130 /* this is a fatal error */
131 *errnop = errno = ENOENT;
132 return NSS_STATUS_UNAVAIL;
135 /* get gecos */
136 tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
137 if (tmp == NULL) {
138 tmp = "";
140 len = strlen(tmp)+1;
141 if (bufpos + len > buflen) {
142 /* buffer too small */
143 *errnop = errno = EAGAIN;
144 return NSS_STATUS_TRYAGAIN;
146 memcpy(&buffer[bufpos], tmp, len);
147 result->pw_gecos = &buffer[bufpos];
148 bufpos += len;
150 /* get homeDirectory */
151 tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
152 if (tmp == NULL) {
153 tmp = "";
155 len = strlen(tmp)+1;
156 if (bufpos + len > buflen) {
157 /* buffer too small */
158 *errnop = errno = EAGAIN;
159 return NSS_STATUS_TRYAGAIN;
161 memcpy(&buffer[bufpos], tmp, len);
162 result->pw_dir = &buffer[bufpos];
163 bufpos += len;
165 /* get shell */
166 tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
167 if (tmp == NULL) {
168 tmp = "";
170 len = strlen(tmp)+1;
171 if (bufpos + len > buflen) {
172 /* buffer too small */
173 *errnop = errno = EAGAIN;
174 return NSS_STATUS_TRYAGAIN;
176 memcpy(&buffer[bufpos], tmp, len);
177 result->pw_shell = &buffer[bufpos];
178 bufpos += len;
180 return NSS_STATUS_SUCCESS;
183 NSS_STATUS _ldb_nss_fill_group(struct group *result,
184 char *buffer,
185 int buflen,
186 int *errnop,
187 struct ldb_message *group,
188 struct ldb_result *members)
190 const char *tmp;
191 size_t len;
192 size_t bufpos;
193 size_t lsize;
194 unsigned int i;
196 bufpos = 0;
198 /* get group name */
199 tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
200 if (tmp == NULL) {
201 /* this is a fatal error */
202 *errnop = errno = ENOENT;
203 return NSS_STATUS_UNAVAIL;
205 len = strlen(tmp)+1;
206 if (bufpos + len > buflen) {
207 /* buffer too small */
208 *errnop = errno = EAGAIN;
209 return NSS_STATUS_TRYAGAIN;
211 memcpy(&buffer[bufpos], tmp, len);
212 result->gr_name = &buffer[bufpos];
213 bufpos += len;
215 /* get userPassword */
216 tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
217 if (tmp == NULL) {
218 tmp = "LDB";
220 len = strlen(tmp)+1;
221 if (bufpos + len > buflen) {
222 /* buffer too small */
223 *errnop = errno = EAGAIN;
224 return NSS_STATUS_TRYAGAIN;
226 memcpy(&buffer[bufpos], tmp, len);
227 result->gr_passwd = &buffer[bufpos];
228 bufpos += len;
230 result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
231 if (result->gr_gid == 0) {
232 /* this is a fatal error */
233 *errnop = errno = ENOENT;
234 return NSS_STATUS_UNAVAIL;
237 /* check if there is enough memory for the list of pointers */
238 lsize = (members->count + 1) * sizeof(char *);
240 /* align buffer on pointer boundary */
241 bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
242 if ((buflen - bufpos) < lsize) {
243 /* buffer too small */
244 *errnop = errno = EAGAIN;
245 return NSS_STATUS_TRYAGAIN;
248 result->gr_mem = (char **)&buffer[bufpos];
249 bufpos += lsize;
251 for (i = 0; i < members->count; i++) {
252 tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
253 if (tmp == NULL) {
254 /* this is a fatal error */
255 *errnop = errno = ENOENT;
256 return NSS_STATUS_UNAVAIL;
258 len = strlen(tmp)+1;
259 if (bufpos + len > buflen) {
260 /* buffer too small */
261 *errnop = errno = EAGAIN;
262 return NSS_STATUS_TRYAGAIN;
264 memcpy(&buffer[bufpos], tmp, len);
265 result->gr_mem[i] = &buffer[bufpos];
266 bufpos += len;
269 result->gr_mem[i] = NULL;
271 return NSS_STATUS_SUCCESS;
274 NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
275 long int limit,
276 long int *start,
277 long int *size,
278 gid_t **groups,
279 int *errnop,
280 struct ldb_result *grlist)
282 NSS_STATUS ret;
283 unsigned int i;
285 for (i = 0; i < grlist->count; i++) {
287 if (limit && (*start > limit)) {
288 /* TODO: warn no all groups were reported */
289 *errnop = 0;
290 ret = NSS_STATUS_SUCCESS;
291 goto done;
294 if (*start == *size) {
295 /* buffer full, enlarge it */
296 long int gs;
297 gid_t *gm;
299 gs = (*size) + 32;
300 if (limit && (gs > limit)) {
301 gs = limit;
304 gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
305 if ( ! gm) {
306 *errnop = ENOMEM;
307 ret = NSS_STATUS_UNAVAIL;
308 goto done;
311 *groups = gm;
312 *size = gs;
315 (*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
316 if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
317 /* skip root group or primary group */
318 continue;
320 (*start)++;
324 *errnop = 0;
325 ret = NSS_STATUS_SUCCESS;
326 done:
327 return ret;
330 #define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
332 NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
333 struct ldb_dn *group_dn,
334 const char * const *attrs,
335 const char *mattr)
337 struct ldb_control **ctrls;
338 struct ldb_control *ctrl;
339 struct ldb_asq_control *asqc;
340 struct ldb_request *req;
341 int ret;
342 struct ldb_result *res = *_res;
344 ctrls = talloc_array(res, struct ldb_control *, 2);
345 _LDB_NSS_ALLOC_CHECK(ctrls);
347 ctrl = talloc(ctrls, struct ldb_control);
348 _LDB_NSS_ALLOC_CHECK(ctrl);
350 asqc = talloc(ctrl, struct ldb_asq_control);
351 _LDB_NSS_ALLOC_CHECK(asqc);
353 asqc->source_attribute = talloc_strdup(asqc, mattr);
354 _LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
356 asqc->request = 1;
357 asqc->src_attr_len = strlen(asqc->source_attribute);
358 ctrl->oid = LDB_CONTROL_ASQ_OID;
359 ctrl->critical = 1;
360 ctrl->data = asqc;
361 ctrls[0] = ctrl;
362 ctrls[1] = NULL;
364 ret = ldb_build_search_req(
365 &req,
366 _ldb_nss_ctx->ldb,
367 res,
368 group_dn,
369 LDB_SCOPE_BASE,
370 "(objectClass=*)",
371 attrs,
372 ctrls,
373 res,
374 ldb_search_default_callback);
376 if (ret != LDB_SUCCESS) {
377 errno = ENOENT;
378 return NSS_STATUS_UNAVAIL;
381 ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
383 ret = ldb_request(_ldb_nss_ctx->ldb, req);
385 if (ret == LDB_SUCCESS) {
386 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
387 } else {
388 talloc_free(req);
389 return NSS_STATUS_UNAVAIL;
392 talloc_free(req);
393 return NSS_STATUS_SUCCESS;