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 22extern struct _ldb_nss_context *_ldb_nss_ctx; 23 24const char *_ldb_nss_gr_attrs[] = { 25 "cn", 26 "userPassword", 27 "gidNumber", 28 NULL 29}; 30 31const char *_ldb_nss_mem_attrs[] = { 32 "uid", 33 NULL 34}; 35 36#define _NSS_LDB_ENOMEM(amem) \ 37 do { \ 38 if ( ! amem) { \ 39 errno = ENOMEM; \ 40 talloc_free(memctx); \ 41 return NSS_STATUS_UNAVAIL; \ 42 } \ 43 } while(0) 44 45/* This setgrent, getgrent, endgrent is not very efficient */ 46 47NSS_STATUS _nss_ldb_setgrent(void) 48{ 49 int ret; 50 51 ret = _ldb_nss_init(); 52 if (ret != NSS_STATUS_SUCCESS) { 53 return ret; 54 } 55 56 _ldb_nss_ctx->gr_cur = 0; 57 if (_ldb_nss_ctx->gr_res != NULL) { 58 talloc_free(_ldb_nss_ctx->gr_res); 59 _ldb_nss_ctx->gr_res = NULL; 60 } 61 62 ret = ldb_search(_ldb_nss_ctx->ldb, 63 _ldb_nss_ctx->ldb, 64 &_ldb_nss_ctx->gr_res, 65 _ldb_nss_ctx->base, 66 LDB_SCOPE_SUBTREE, 67 _ldb_nss_gr_attrs, 68 _LDB_NSS_GRENT_FILTER); 69 if (ret != LDB_SUCCESS) { 70 return NSS_STATUS_UNAVAIL; 71 } 72 73 return NSS_STATUS_SUCCESS; 74} 75 76NSS_STATUS _nss_ldb_endgrent(void) 77{ 78 int ret; 79 80 ret = _ldb_nss_init(); 81 if (ret != NSS_STATUS_SUCCESS) { 82 return ret; 83 } 84 85 _ldb_nss_ctx->gr_cur = 0; 86 if (_ldb_nss_ctx->gr_res) { 87 talloc_free(_ldb_nss_ctx->gr_res); 88 _ldb_nss_ctx->gr_res = NULL; 89 } 90 91 return NSS_STATUS_SUCCESS; 92} 93 94NSS_STATUS _nss_ldb_getgrent_r(struct group *result_buf, char *buffer, size_t buflen, int *errnop) 95{ 96 int ret; 97 struct ldb_result *res; 98 99 ret = _ldb_nss_init(); 100 if (ret != NSS_STATUS_SUCCESS) { 101 return ret; 102 } 103 104 *errnop = 0; 105 106 if (_ldb_nss_ctx->gr_cur >= _ldb_nss_ctx->gr_res->count) { 107 /* already returned all entries */ 108 return NSS_STATUS_NOTFOUND; 109 } 110 111 res = talloc_zero(_ldb_nss_ctx->gr_res, struct ldb_result); 112 if ( ! res) { 113 errno = *errnop = ENOMEM; 114 _ldb_nss_ctx->gr_cur++; /* skip this entry */ 115 return NSS_STATUS_UNAVAIL; 116 } 117 118 ret = _ldb_nss_group_request(&res, 119 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur]->dn, 120 _ldb_nss_mem_attrs, 121 "member"); 122 123 if (ret != NSS_STATUS_SUCCESS) { 124 *errnop = errno; 125 talloc_free(res); 126 _ldb_nss_ctx->gr_cur++; /* skip this entry */ 127 return ret; 128 } 129 130 ret = _ldb_nss_fill_group(result_buf, 131 buffer, 132 buflen, 133 errnop, 134 _ldb_nss_ctx->gr_res->msgs[_ldb_nss_ctx->gr_cur], 135 res); 136 137 talloc_free(res); 138 139 if (ret != NSS_STATUS_SUCCESS) { 140 if (ret != NSS_STATUS_TRYAGAIN) { 141 _ldb_nss_ctx->gr_cur++; /* skip this entry */ 142 } 143 return ret; 144 } 145 146 /* this entry is ok, increment counter to nex entry */ 147 _ldb_nss_ctx->gr_cur++; 148 149 return NSS_STATUS_SUCCESS; 150} 151 152NSS_STATUS _nss_ldb_getgrnam_r(const char *name, struct group *result_buf, char *buffer, size_t buflen, int *errnop) 153{ 154 int ret; 155 char *filter; 156 TALLOC_CTX *ctx; 157 struct ldb_result *gr_res; 158 struct ldb_result *mem_res; 159 160 ret = _ldb_nss_init(); 161 if (ret != NSS_STATUS_SUCCESS) { 162 return ret; 163 } 164 165 ctx = talloc_new(_ldb_nss_ctx->ldb); 166 if ( ! ctx) { 167 *errnop = errno = ENOMEM; 168 return NSS_STATUS_UNAVAIL; 169 } 170 171 /* build the filter for this uid */ 172 filter = talloc_asprintf(ctx, _LDB_NSS_GRNAM_FILTER, name); 173 if (filter == NULL) { 174 /* this is a fatal error */ 175 *errnop = errno = ENOMEM; 176 ret = NSS_STATUS_UNAVAIL; 177 goto done; 178 } 179 180 /* search the entry */ 181 ret = ldb_search(_ldb_nss_ctx->ldb, 182 _ldb_nss_ctx->ldb, 183 &gr_res, 184 _ldb_nss_ctx->base, 185 LDB_SCOPE_SUBTREE, 186 _ldb_nss_gr_attrs, 187 filter); 188 if (ret != LDB_SUCCESS) { 189 /* this is a fatal error */ 190 *errnop = errno = ENOENT; 191 ret = NSS_STATUS_UNAVAIL; 192 goto done; 193 } 194 195 talloc_steal(ctx, gr_res); 196 197 /* if none found return */ 198 if (gr_res->count == 0) { 199 *errnop = errno = ENOENT; 200 ret = NSS_STATUS_NOTFOUND; 201 goto done; 202 } 203 204 if (gr_res->count != 1) { 205 /* this is a fatal error */ 206 *errnop = errno = ENOENT; 207 ret = NSS_STATUS_UNAVAIL; 208 goto done; 209 } 210 211 mem_res = talloc_zero(ctx, struct ldb_result); 212 if ( ! mem_res) { 213 errno = *errnop = ENOMEM; 214 ret = NSS_STATUS_UNAVAIL; 215 goto done; 216 } 217 218 ret = _ldb_nss_group_request(&mem_res, 219 gr_res->msgs[0]->dn, 220 _ldb_nss_mem_attrs, 221 "member"); 222 223 if (ret != NSS_STATUS_SUCCESS) { 224 *errnop = errno; 225 goto done; 226 } 227 228 ret = _ldb_nss_fill_group(result_buf, 229 buffer, 230 buflen, 231 errnop, 232 gr_res->msgs[0], 233 mem_res); 234 235 if (ret != NSS_STATUS_SUCCESS) { 236 goto done; 237 } 238 239 ret = NSS_STATUS_SUCCESS; 240done: 241 talloc_free(ctx); 242 return ret; 243} 244 245NSS_STATUS _nss_ldb_getgrgid_r(gid_t gid, struct group *result_buf, char *buffer, size_t buflen, int *errnop) 246{ 247 int ret; 248 char *filter; 249 TALLOC_CTX *ctx; 250 struct ldb_result *gr_res; 251 struct ldb_result *mem_res; 252 253 if (gid == 0) { /* we don't serve root gid by policy */ 254 *errnop = errno = ENOENT; 255 return NSS_STATUS_NOTFOUND; 256 } 257 258 ret = _ldb_nss_init(); 259 if (ret != NSS_STATUS_SUCCESS) { 260 return ret; 261 } 262 263 ctx = talloc_new(_ldb_nss_ctx->ldb); 264 if ( ! ctx) { 265 *errnop = errno = ENOMEM; 266 return NSS_STATUS_UNAVAIL; 267 } 268 269 /* build the filter for this uid */ 270 filter = talloc_asprintf(ctx, _LDB_NSS_GRGID_FILTER, gid); 271 if (filter == NULL) { 272 /* this is a fatal error */ 273 *errnop = errno = ENOMEM; 274 ret = NSS_STATUS_UNAVAIL; 275 goto done; 276 } 277 278 /* search the entry */ 279 ret = ldb_search(_ldb_nss_ctx->ldb, 280 _ldb_nss_ctx->ldb, 281 &gr_res, 282 _ldb_nss_ctx->base, 283 LDB_SCOPE_SUBTREE, 284 _ldb_nss_gr_attrs, 285 filter); 286 if (ret != LDB_SUCCESS) { 287 /* this is a fatal error */ 288 *errnop = errno = ENOENT; 289 ret = NSS_STATUS_UNAVAIL; 290 goto done; 291 } 292 293 talloc_steal(ctx, gr_res); 294 295 /* if none found return */ 296 if (gr_res->count == 0) { 297 *errnop = errno = ENOENT; 298 ret = NSS_STATUS_NOTFOUND; 299 goto done; 300 } 301 302 if (gr_res->count != 1) { 303 /* this is a fatal error */ 304 *errnop = errno = ENOENT; 305 ret = NSS_STATUS_UNAVAIL; 306 goto done; 307 } 308 309 mem_res = talloc_zero(ctx, struct ldb_result); 310 if ( ! mem_res) { 311 errno = *errnop = ENOMEM; 312 ret = NSS_STATUS_UNAVAIL; 313 goto done; 314 } 315 316 ret = _ldb_nss_group_request(&mem_res, 317 gr_res->msgs[0]->dn, 318 _ldb_nss_mem_attrs, 319 "member"); 320 321 if (ret != NSS_STATUS_SUCCESS) { 322 *errnop = errno; 323 goto done; 324 } 325 326 ret = _ldb_nss_fill_group(result_buf, 327 buffer, 328 buflen, 329 errnop, 330 gr_res->msgs[0], 331 mem_res); 332 333 if (ret != NSS_STATUS_SUCCESS) { 334 goto done; 335 } 336 337 ret = NSS_STATUS_SUCCESS; 338done: 339 talloc_free(ctx); 340 return ret; 341} 342 343NSS_STATUS _nss_ldb_initgroups_dyn(const char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop) 344{ 345 int ret; 346 char *filter; 347 const char * attrs[] = { "uidNumber", "gidNumber", NULL }; 348 struct ldb_result *uid_res; 349 struct ldb_result *mem_res; 350 351 ret = _ldb_nss_init(); 352 if (ret != NSS_STATUS_SUCCESS) { 353 return ret; 354 } 355 356 mem_res = talloc_zero(_ldb_nss_ctx, struct ldb_result); 357 if ( ! mem_res) { 358 errno = *errnop = ENOMEM; 359 return NSS_STATUS_UNAVAIL; 360 } 361 362 /* build the filter for this name */ 363 filter = talloc_asprintf(mem_res, _LDB_NSS_PWNAM_FILTER, user); 364 if (filter == NULL) { 365 /* this is a fatal error */ 366 *errnop = errno = ENOENT; 367 ret = NSS_STATUS_UNAVAIL; 368 goto done; 369 } 370 371 /* search the entry */ 372 ret = ldb_search(_ldb_nss_ctx->ldb, 373 _ldb_nss_ctx->ldb, 374 &uid_res, 375 _ldb_nss_ctx->base, 376 LDB_SCOPE_SUBTREE, 377 attrs, 378 filter); 379 if (ret != LDB_SUCCESS) { 380 /* this is a fatal error */ 381 *errnop = errno = ENOENT; 382 ret = NSS_STATUS_UNAVAIL; 383 goto done; 384 } 385 386 talloc_steal(mem_res, uid_res); 387 388 /* if none found return */ 389 if (uid_res->count == 0) { 390 *errnop = errno = ENOENT; 391 ret = NSS_STATUS_NOTFOUND; 392 goto done; 393 } 394 395 if (uid_res->count != 1) { 396 /* this is a fatal error */ 397 *errnop = errno = ENOENT; 398 ret = NSS_STATUS_UNAVAIL; 399 goto done; 400 } 401 402 ret = _ldb_nss_group_request(&mem_res, 403 uid_res->msgs[0]->dn, 404 attrs, 405 "memberOf"); 406 407 if (ret != NSS_STATUS_SUCCESS) { 408 *errnop = errno; 409 goto done; 410 } 411 412 ret = _ldb_nss_fill_initgr(group, 413 limit, 414 start, 415 size, 416 groups, 417 errnop, 418 mem_res); 419 420 if (ret != NSS_STATUS_SUCCESS) { 421 goto done; 422 } 423 424 ret = NSS_STATUS_SUCCESS; 425 426done: 427 talloc_free(mem_res); 428 return ret; 429} 430