source: vendor/current/lib/ldb/nssldb/ldb-nss.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 8.8 KB
Line 
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 unsigned 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 unsigned 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
Note: See TracBrowser for help on using the repository browser.