• 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/source4/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	_ldb_nss_ctx->ldb = ldb_init(_ldb_nss_ctx, NULL);
49	if (_ldb_nss_ctx->ldb == NULL) {
50		goto failed;
51	}
52
53	ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
54	if (ret != LDB_SUCCESS) {
55		goto failed;
56	}
57
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;
61	}
62
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;
67
68	return NSS_STATUS_SUCCESS;
69
70failed:
71	/* talloc_free(_ldb_nss_ctx); */
72	_ldb_nss_ctx = NULL;
73	return NSS_STATUS_UNAVAIL;
74}
75
76NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
77				char *buffer,
78				int buflen,
79				int *errnop,
80				struct ldb_message *msg)
81{
82	int len;
83	int bufpos;
84	const char *tmp;
85
86	bufpos = 0;
87
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;
94	}
95	len = strlen(tmp)+1;
96	if (bufpos + len > buflen) {
97		/* buffer too small */
98		*errnop = errno = EAGAIN;
99		return NSS_STATUS_TRYAGAIN;
100	}
101	memcpy(&buffer[bufpos], tmp, len);
102	result->pw_name = &buffer[bufpos];
103	bufpos += len;
104
105	/* get userPassword */
106	tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
107	if (tmp == NULL) {
108		tmp = "LDB";
109	}
110	len = strlen(tmp)+1;
111	if (bufpos + len > buflen) {
112		/* buffer too small */
113		*errnop = errno = EAGAIN;
114		return NSS_STATUS_TRYAGAIN;
115	}
116	memcpy(&buffer[bufpos], tmp, len);
117	result->pw_passwd = &buffer[bufpos];
118	bufpos += len;
119
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;
126	}
127
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;
133	}
134
135	/* get gecos */
136	tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
137	if (tmp == NULL) {
138		tmp = "";
139	}
140	len = strlen(tmp)+1;
141	if (bufpos + len > buflen) {
142		/* buffer too small */
143		*errnop = errno = EAGAIN;
144		return NSS_STATUS_TRYAGAIN;
145	}
146	memcpy(&buffer[bufpos], tmp, len);
147	result->pw_gecos = &buffer[bufpos];
148	bufpos += len;
149
150	/* get homeDirectory */
151	tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
152	if (tmp == NULL) {
153		tmp = "";
154	}
155	len = strlen(tmp)+1;
156	if (bufpos + len > buflen) {
157		/* buffer too small */
158		*errnop = errno = EAGAIN;
159		return NSS_STATUS_TRYAGAIN;
160	}
161	memcpy(&buffer[bufpos], tmp, len);
162	result->pw_dir = &buffer[bufpos];
163	bufpos += len;
164
165	/* get shell */
166	tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
167	if (tmp == NULL) {
168		tmp = "";
169	}
170	len = strlen(tmp)+1;
171	if (bufpos + len > buflen) {
172		/* buffer too small */
173		*errnop = errno = EAGAIN;
174		return NSS_STATUS_TRYAGAIN;
175	}
176	memcpy(&buffer[bufpos], tmp, len);
177	result->pw_shell = &buffer[bufpos];
178	bufpos += len;
179
180	return NSS_STATUS_SUCCESS;
181}
182
183NSS_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)
189{
190	const char *tmp;
191	size_t len;
192	size_t bufpos;
193	size_t lsize;
194	int i;
195
196	bufpos = 0;
197
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;
204	}
205	len = strlen(tmp)+1;
206	if (bufpos + len > buflen) {
207		/* buffer too small */
208		*errnop = errno = EAGAIN;
209		return NSS_STATUS_TRYAGAIN;
210	}
211	memcpy(&buffer[bufpos], tmp, len);
212	result->gr_name = &buffer[bufpos];
213	bufpos += len;
214
215	/* get userPassword */
216	tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
217	if (tmp == NULL) {
218		tmp = "LDB";
219	}
220	len = strlen(tmp)+1;
221	if (bufpos + len > buflen) {
222		/* buffer too small */
223		*errnop = errno = EAGAIN;
224		return NSS_STATUS_TRYAGAIN;
225	}
226	memcpy(&buffer[bufpos], tmp, len);
227	result->gr_passwd = &buffer[bufpos];
228	bufpos += len;
229
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;
235	}
236
237	/* check if there is enough memory for the list of pointers */
238	lsize = (members->count + 1) * sizeof(char *);
239
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;
246	}
247
248	result->gr_mem = (char **)&buffer[bufpos];
249	bufpos += lsize;
250
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;
257		}
258		len = strlen(tmp)+1;
259		if (bufpos + len > buflen) {
260			/* buffer too small */
261			*errnop = errno = EAGAIN;
262			return NSS_STATUS_TRYAGAIN;
263		}
264		memcpy(&buffer[bufpos], tmp, len);
265		result->gr_mem[i] = &buffer[bufpos];
266		bufpos += len;
267	}
268
269	result->gr_mem[i] = NULL;
270
271	return NSS_STATUS_SUCCESS;
272}
273
274NSS_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)
281{
282	NSS_STATUS ret;
283	int i;
284
285	for (i = 0; i < grlist->count; i++) {
286
287		if (limit && (*start > limit)) {
288			/* TODO: warn no all groups were reported */
289			*errnop = 0;
290			ret = NSS_STATUS_SUCCESS;
291			goto done;
292		}
293
294		if (*start == *size) {
295			/* buffer full, enlarge it */
296			long int gs;
297			gid_t *gm;
298
299			gs = (*size) + 32;
300			if (limit && (gs > limit)) {
301				gs = limit;
302			}
303
304			gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
305			if ( ! gm) {
306				*errnop = ENOMEM;
307				ret = NSS_STATUS_UNAVAIL;
308				goto done;
309			}
310
311			*groups = gm;
312			*size = gs;
313		}
314
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;
319		}
320		(*start)++;
321
322	}
323
324	*errnop = 0;
325	ret = NSS_STATUS_SUCCESS;
326done:
327	return ret;
328}
329
330#define _LDB_NSS_ALLOC_CHECK(mem) do { if (!mem) { errno = ENOMEM; return NSS_STATUS_UNAVAIL; } } while(0)
331
332NSS_STATUS _ldb_nss_group_request(struct ldb_result **_res,
333					struct ldb_dn *group_dn,
334					const char * const *attrs,
335					const char *mattr)
336{
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;
343
344	ctrls = talloc_array(res, struct ldb_control *, 2);
345	_LDB_NSS_ALLOC_CHECK(ctrls);
346
347	ctrl = talloc(ctrls, struct ldb_control);
348	_LDB_NSS_ALLOC_CHECK(ctrl);
349
350	asqc = talloc(ctrl, struct ldb_asq_control);
351	_LDB_NSS_ALLOC_CHECK(asqc);
352
353	asqc->source_attribute = talloc_strdup(asqc, mattr);
354	_LDB_NSS_ALLOC_CHECK(asqc->source_attribute);
355
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;
363
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);
375
376	if (ret != LDB_SUCCESS) {
377		errno = ENOENT;
378		return NSS_STATUS_UNAVAIL;
379	}
380
381	ldb_set_timeout(_ldb_nss_ctx->ldb, req, 0);
382
383	ret = ldb_request(_ldb_nss_ctx->ldb, req);
384
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;
390	}
391
392	talloc_free(req);
393	return NSS_STATUS_SUCCESS;
394}
395
396