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/>.
22
struct _ldb_nss_context *_ldb_nss_ctx = NULL;
24
NSS_STATUS _ldb_nss_init(void)
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;
35
/* we are in a forked child now, reinitialize */
36
talloc_free(_ldb_nss_ctx);
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) {
53
ret = ldb_connect(_ldb_nss_ctx->ldb, _LDB_NSS_URL, LDB_FLG_RDONLY, NULL);
54
if (ret != LDB_SUCCESS) {
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)) {
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;
71
/* talloc_free(_ldb_nss_ctx); */
73
return NSS_STATUS_UNAVAIL;
76
NSS_STATUS _ldb_nss_fill_passwd(struct passwd *result,
80
struct ldb_message *msg)
89
tmp = ldb_msg_find_attr_as_string(msg, "uid", NULL);
91
/* this is a fatal error */
92
*errnop = errno = ENOENT;
93
return NSS_STATUS_UNAVAIL;
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];
105
/* get userPassword */
106
tmp = ldb_msg_find_attr_as_string(msg, "userPassword", NULL);
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];
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;
136
tmp = ldb_msg_find_attr_as_string(msg, "gecos", NULL);
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];
150
/* get homeDirectory */
151
tmp = ldb_msg_find_attr_as_string(msg, "homeDirectory", NULL);
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];
166
tmp = ldb_msg_find_attr_as_string(msg, "loginShell", NULL);
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];
180
return NSS_STATUS_SUCCESS;
183
NSS_STATUS _ldb_nss_fill_group(struct group *result,
187
struct ldb_message *group,
188
struct ldb_result *members)
199
tmp = ldb_msg_find_attr_as_string(group, "cn", NULL);
201
/* this is a fatal error */
202
*errnop = errno = ENOENT;
203
return NSS_STATUS_UNAVAIL;
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];
215
/* get userPassword */
216
tmp = ldb_msg_find_attr_as_string(group, "userPassword", NULL);
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];
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];
251
for (i = 0; i < members->count; i++) {
252
tmp = ldb_msg_find_attr_as_string(members->msgs[i], "uid", NULL);
254
/* this is a fatal error */
255
*errnop = errno = ENOENT;
256
return NSS_STATUS_UNAVAIL;
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];
269
result->gr_mem[i] = NULL;
271
return NSS_STATUS_SUCCESS;
274
NSS_STATUS _ldb_nss_fill_initgr(gid_t group,
280
struct ldb_result *grlist)
285
for (i = 0; i < grlist->count; i++) {
287
if (limit && (*start > limit)) {
288
/* TODO: warn no all groups were reported */
290
ret = NSS_STATUS_SUCCESS;
294
if (*start == *size) {
295
/* buffer full, enlarge it */
300
if (limit && (gs > limit)) {
304
gm = (gid_t *)realloc((*groups), gs * sizeof(gid_t));
307
ret = NSS_STATUS_UNAVAIL;
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 */
325
ret = NSS_STATUS_SUCCESS;
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,
337
struct ldb_control **ctrls;
338
struct ldb_control *ctrl;
339
struct ldb_asq_control *asqc;
340
struct ldb_request *req;
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);
357
asqc->src_attr_len = strlen(asqc->source_attribute);
358
ctrl->oid = LDB_CONTROL_ASQ_OID;
364
ret = ldb_build_search_req(
374
ldb_search_default_callback);
376
if (ret != LDB_SUCCESS) {
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);
389
return NSS_STATUS_UNAVAIL;
393
return NSS_STATUS_SUCCESS;