• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/lib/ldb/nssldb/
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
22struct _ldb_nss_context *_ldb_nss_ctx = NULL;
23
24NSS_STATUS _ldb_nss_init(void)
25{
26	int ret;
27
28	pid_t mypid = getpid();
29
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;
38		}
39	}
40
41	_ldb_nss_ctx = talloc_named(NULL, 0, "_ldb_nss_ctx(%u)", mypid);
42	if (_ldb_nss_ctx == NULL) {
43		return NSS_STATUS_UNAVAIL;
44	}
45
46	_ldb_nss_ctx->pid = mypid;
47
48	ret = ldb_global_init();
49	if (ret != 0) {
50		goto failed;
51	}
52
53	_ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx);
54	if (_ldb_nss_ctx->ldb == NULL) {
55		goto failed;
56	}
57
58	ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
59	if (ret != LDB_SUCCESS) {
60		goto failed;
61	}
62
63	_ldb_nss_ctx->base = ldb_dn_explode(_ldb_nss_ctx, _LDB_NSS_BASEDN);
64	if (_ldb_nss_ctx->base == NULL) {
65		goto failed;
66	}
67
68	_ldb_nss_ctx->pw_cur = 0;
69	_ldb_nss_ctx->pw_res = NULL;
70	_ldb_nss_ctx->gr_cur = 0;
71	_ldb_nss_ctx->gr_res = NULL;
72
73	return NSS_STATUS_SUCCESS;
74
75failed:
76	/* talloc_free(_ldb_nss_ctx); */
77	_ldb_nss_ctx = NULL;
78	return NSS_STATUS_UNAVAIL;
79}
80
81NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
82				char *buffer,
83				int buflen,
84				int *errnop,
85				struct ldb_message *msg)
86{
87	int len;
88	int bufpos;
89	const char *tmp;
90
91	bufpos = 0;
92
93	/* get username */
94	tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
95	if (tmp == NULL) {
96		/* this is a fatal error */
97		*errnop = errno = ENOENT;
98		return NSS_STATUS_UNAVAIL;
99	}
100	len = strlen(tmp)+1;
101	if (bufpos + len > buflen) {
102		/* buffer too small */
103		*errnop = errno = EAGAIN;
104		return NSS_STATUS_TRYAGAIN;
105	}
106	memcpy(&buffer[bufpos], tmp, len);
107	result->pw_name = &buffer[bufpos];
108	bufpos += len;
109
110	/* get userPassword */
111	tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
112	if (tmp == NULL) {
113		tmp = "LDB";
114	}
115	len = strlen(tmp)+1;
116	if (bufpos + len > buflen) {
117		/* buffer too small */
118		*errnop = errno = EAGAIN;
119		return NSS_STATUS_TRYAGAIN;
120	}
121	memcpy(&buffer[bufpos], tmp, len);
122	result->pw_passwd = &buffer[bufpos];
123	bufpos += len;
124
125	/* this backend never serves an uid 0 user */
126	result->pw_uid = ldb_msg_find_attr_as_int(msg, "uidNumber", 0);
127	if (result->pw_uid == 0) {
128		/* this is a fatal error */
129		*errnop = errno = ENOENT;
130		return NSS_STATUS_UNAVAIL;
131	}
132
133	result->pw_gid = ldb_msg_find_attr_as_int(msg, "gidNumber", 0);
134	if (result->pw_gid == 0) {
135		/* this is a fatal error */
136		*errnop = errno = ENOENT;
137		return NSS_STATUS_UNAVAIL;
138	}
139
140	/* get gecos */
141	tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
142	if (tmp == NULL) {
143		tmp = "";
144	}
145	len = strlen(tmp)+1;
146	if (bufpos + len > buflen) {
147		/* buffer too small */
148		*errnop = errno = EAGAIN;
149		return NSS_STATUS_TRYAGAIN;
150	}
151	memcpy(&buffer[bufpos], tmp, len);
152	result->pw_gecos = &buffer[bufpos];
153	bufpos += len;
154
155	/* get homeDirectory */
156	tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
157	if (tmp == NULL) {
158		tmp = "";
159	}
160	len = strlen(tmp)+1;
161	if (bufpos + len > buflen) {
162		/* buffer too small */
163		*errnop = errno = EAGAIN;
164		return NSS_STATUS_TRYAGAIN;
165	}
166	memcpy(&buffer[bufpos], tmp, len);
167	result->pw_dir = &buffer[bufpos];
168	bufpos += len;
169
170	/* get shell */
171	tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
172	if (tmp == NULL) {
173		tmp = "";
174	}
175	len = strlen(tmp)+1;
176	if (bufpos + len > buflen) {
177		/* buffer too small */
178		*errnop = errno = EAGAIN;
179		return NSS_STATUS_TRYAGAIN;
180	}
181	memcpy(&buffer[bufpos], tmp, len);
182	result->pw_shell = &buffer[bufpos];
183	bufpos += len;
184
185	return NSS_STATUS_SUCCESS;
186}
187
188NSS_STATUS _ldb_nss_fill_group(struct group *result,
189				char *buffer,
190				int buflen,
191				int *errnop,
192				struct ldb_message *group,
193				struct ldb_result *members)
194{
195	const char *tmp;
196	size_t len;
197	size_t bufpos;
198	size_t lsize;
199	int i;
200
201	bufpos = 0;
202
203	/* get group name */
204	tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
205	if (tmp == NULL) {
206		/* this is a fatal error */
207		*errnop = errno = ENOENT;
208		return NSS_STATUS_UNAVAIL;
209	}
210	len = strlen(tmp)+1;
211	if (bufpos + len > buflen) {
212		/* buffer too small */
213		*errnop = errno = EAGAIN;
214		return NSS_STATUS_TRYAGAIN;
215	}
216	memcpy(&buffer[bufpos], tmp, len);
217	result->gr_name = &buffer[bufpos];
218	bufpos += len;
219
220	/* get userPassword */
221	tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
222	if (tmp == NULL) {
223		tmp = "LDB";
224	}
225	len = strlen(tmp)+1;
226	if (bufpos + len > buflen) {
227		/* buffer too small */
228		*errnop = errno = EAGAIN;
229		return NSS_STATUS_TRYAGAIN;
230	}
231	memcpy(&buffer[bufpos], tmp, len);
232	result->gr_passwd = &buffer[bufpos];
233	bufpos += len;
234
235	result->gr_gid = ldb_msg_find_attr_as_int(group, "gidNumber", 0);
236	if (result->gr_gid == 0) {
237		/* this is a fatal error */
238		*errnop = errno = ENOENT;
239		return NSS_STATUS_UNAVAIL;
240	}
241
242	/* check if there is enough memory for the list of pointers */
243	lsize = (members->count + 1) * sizeof(char *);
244
245	/* align buffer on pointer boundary */
246	bufpos += (sizeof(char*) - ((unsigned long)(buffer) % sizeof(char*)));
247	if ((buflen - bufpos) < lsize) {
248		/* buffer too small */
249		*errnop = errno = EAGAIN;
250		return NSS_STATUS_TRYAGAIN;
251	}
252
253	result->gr_mem = (char **)&buffer[bufpos];
254	bufpos += lsize;
255
256	for (i = 0; i < members->count; i++) {
257		tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
258		if (tmp == NULL) {
259			/* this is a fatal error */
260			*errnop = errno = ENOENT;
261			return NSS_STATUS_UNAVAIL;
262		}
263		len = strlen(tmp)+1;
264		if (bufpos + len > buflen) {
265			/* buffer too small */
266			*errnop = errno = EAGAIN;
267			return NSS_STATUS_TRYAGAIN;
268		}
269		memcpy(&buffer[bufpos], tmp, len);
270		result->gr_mem[i] = &buffer[bufpos];
271		bufpos += len;
272	}
273
274	result->gr_mem[i] = NULL;
275
276	return NSS_STATUS_SUCCESS;
277}
278
279NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
280				long int limit,
281				long int *start,
282				long int *size,
283				gid_t **groups,
284				int *errnop,
285				struct ldb_result *grlist)
286{
287	NSS_STATUS ret;
288	int i;
289
290	for (i = 0; i < grlist->count; i++) {
291
292		if (limit && (*start > limit)) {
293			/* TODO: warn no all groups were reported */
294			*errnop = 0;
295			ret = NSS_STATUS_SUCCESS;
296			goto done;
297		}
298
299		if (*start == *size) {
300			/* buffer full, enlarge it */
301			long int gs;
302			gid_t *gm;
303
304			gs = (*size) + 32;
305			if (limit && (gs > limit)) {
306				gs = limit;
307			}
308
309			gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
310			if ( ! gm) {
311				*errnop = ENOMEM;
312				ret = NSS_STATUS_UNAVAIL;
313				goto done;
314			}
315
316			*groups = gm;
317			*size = gs;
318		}
319
320		(*groups)[*start] = ldb_msg_find_attr_as_int(grlist->msgs[i], "gidNumber", 0);
321		if ((*groups)[*start] == 0 || (*groups)[*start] == group) {
322			/* skip root group or primary group */
323			continue;
324		}
325		(*start)++;
326
327	}
328
329	*errnop = 0;
330	ret = NSS_STATUS_SUCCESS;
331done:
332	return ret;
333}
334
335#define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
336
337NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
338					struct ldb_dn *group_dn,
339					const char * const *attrs,
340					const char *mattr)
341{
342	struct ldb_control **ctrls;
343	struct ldb_control *ctrl;
344	struct ldb_asq_control *asqc;
345	struct ldb_request *req;
346	int ret;
347	struct ldb_result *res = *_res;
348
349	ctrls = talloc_array(res, struct ldb_control *, 2);
350	_LDB_NSS_ALLOC_CHECK(ctrls);
351
352	ctrl = talloc(ctrls, struct ldb_control);
353	_LDB_NSS_ALLOC_CHECK(ctrl);
354
355	asqc = talloc(ctrl, struct ldb_asq_control);
356	_LDB_NSS_ALLOC_CHECK(asqc);
357
358	asqc->source_attribute = talloc_strdup(asqc, mattr);
359	_LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
360
361	asqc->request = 1;
362	asqc->src_attr_len = strlen(asqc->source_attribute);
363	ctrl->oid = LDB_CONTROL_ASQ_OID;
364	ctrl->critical = 1;
365	ctrl->data = asqc;
366	ctrls[0] = ctrl;
367	ctrls[1] = NULL;
368
369	ret = ldb_build_search_req(
370				&req,
371				_ldb_nss_ctx->ldb,
372				res,
373				group_dn,
374				LDB_SCOPE_BASE,
375				"(objectClass=*)",
376				attrs,
377				ctrls,
378				res,
379				ldb_search_default_callback);
380
381	if (ret != LDB_SUCCESS) {
382		errno = ENOENT;
383		return NSS_STATUS_UNAVAIL;
384	}
385
386	ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
387
388	ret = ldb_request(_ldb_nss_ctx->ldb, req);
389
390	if (ret == LDB_SUCCESS) {
391		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
392	} else {
393		talloc_free(req);
394		return NSS_STATUS_UNAVAIL;
395	}
396
397	talloc_free(req);
398	return NSS_STATUS_SUCCESS;
399}
400
401