1/* 2 * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org> 3 * Copyright (C) Guenther Deschner 2009 <gd@samba.org> 4 * 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of the author nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35#ifdef _SAMBA_BUILD_ 36 37#define NSS_WRAPPER_NOT_REPLACE 38#include "../replace/replace.h" 39#include "system/passwd.h" 40#include "system/filesys.h" 41#include "../nsswitch/nsstest.h" 42 43#else /* _SAMBA_BUILD_ */ 44 45#error nss_wrapper_only_supported_in_samba_yet 46 47#endif 48 49#ifndef _PUBLIC_ 50#define _PUBLIC_ 51#endif 52 53/* not all systems have _r functions... */ 54#ifndef HAVE_GETPWNAM_R 55#define getpwnam_r(name, pwdst, buf, buflen, pwdstp) ENOSYS 56#endif 57#ifndef HAVE_GETPWUID_R 58#define getpwuid_r(uid, pwdst, buf, buflen, pwdstp) ENOSYS 59#endif 60#ifndef HAVE_GETPWENT_R 61#define getpwent_r(pwdst, buf, buflen, pwdstp) ENOSYS 62#endif 63#ifndef HAVE_GETGRNAM_R 64#define getgrnam_r(name, grdst, buf, buflen, grdstp) ENOSYS 65#endif 66#ifndef HAVE_GETGRGID_R 67#define getgrgid_r(gid, grdst, buf, buflen, grdstp) ENOSYS 68#endif 69#ifndef HAVE_GETGRENT_R 70#define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS 71#endif 72 73/* not all systems have getgrouplist */ 74#ifndef HAVE_GETGROUPLIST 75#define getgrouplist(user, group, groups, ngroups) 0 76#endif 77 78/* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support 79 * for now */ 80#define REWRITE_CALLS 81 82#ifdef REWRITE_CALLS 83 84#define real_getpwnam getpwnam 85#define real_getpwnam_r getpwnam_r 86#define real_getpwuid getpwuid 87#define real_getpwuid_r getpwuid_r 88 89#define real_setpwent setpwent 90#define real_getpwent getpwent 91#define real_getpwent_r getpwent_r 92#define real_endpwent endpwent 93 94/* 95#define real_getgrlst getgrlst 96#define real_getgrlst_r getgrlst_r 97#define real_initgroups_dyn initgroups_dyn 98*/ 99#define real_initgroups initgroups 100#define real_getgrouplist getgrouplist 101 102#define real_getgrnam getgrnam 103#define real_getgrnam_r getgrnam_r 104#define real_getgrgid getgrgid 105#define real_getgrgid_r getgrgid_r 106 107#define real_setgrent setgrent 108#define real_getgrent getgrent 109#define real_getgrent_r getgrent_r 110#define real_endgrent endgrent 111 112#endif 113 114#if 0 115# ifdef DEBUG 116# define NWRAP_ERROR(args) DEBUG(0, args) 117# else 118# define NWRAP_ERROR(args) printf args 119# endif 120#else 121#define NWRAP_ERROR(args) 122#endif 123 124#if 0 125# ifdef DEBUG 126# define NWRAP_DEBUG(args) DEBUG(0, args) 127# else 128# define NWRAP_DEBUG(args) printf args 129# endif 130#else 131#define NWRAP_DEBUG(args) 132#endif 133 134#if 0 135# ifdef DEBUG 136# define NWRAP_VERBOSE(args) DEBUG(0, args) 137# else 138# define NWRAP_VERBOSE(args) printf args 139# endif 140#else 141#define NWRAP_VERBOSE(args) 142#endif 143 144struct nwrap_module_nss_fns { 145 NSS_STATUS (*_nss_getpwnam_r)(const char *name, struct passwd *result, char *buffer, 146 size_t buflen, int *errnop); 147 NSS_STATUS (*_nss_getpwuid_r)(uid_t uid, struct passwd *result, char *buffer, 148 size_t buflen, int *errnop); 149 NSS_STATUS (*_nss_setpwent)(void); 150 NSS_STATUS (*_nss_getpwent_r)(struct passwd *result, char *buffer, 151 size_t buflen, int *errnop); 152 NSS_STATUS (*_nss_endpwent)(void); 153 NSS_STATUS (*_nss_initgroups)(const char *user, gid_t group, long int *start, 154 long int *size, gid_t **groups, long int limit, int *errnop); 155 NSS_STATUS (*_nss_getgrnam_r)(const char *name, struct group *result, char *buffer, 156 size_t buflen, int *errnop); 157 NSS_STATUS (*_nss_getgrgid_r)(gid_t gid, struct group *result, char *buffer, 158 size_t buflen, int *errnop); 159 NSS_STATUS (*_nss_setgrent)(void); 160 NSS_STATUS (*_nss_getgrent_r)(struct group *result, char *buffer, 161 size_t buflen, int *errnop); 162 NSS_STATUS (*_nss_endgrent)(void); 163}; 164 165struct nwrap_backend { 166 const char *name; 167 const char *so_path; 168 void *so_handle; 169 struct nwrap_ops *ops; 170 struct nwrap_module_nss_fns *fns; 171}; 172 173struct nwrap_ops { 174 struct passwd * (*nw_getpwnam)(struct nwrap_backend *b, 175 const char *name); 176 int (*nw_getpwnam_r)(struct nwrap_backend *b, 177 const char *name, struct passwd *pwdst, 178 char *buf, size_t buflen, struct passwd **pwdstp); 179 struct passwd * (*nw_getpwuid)(struct nwrap_backend *b, 180 uid_t uid); 181 int (*nw_getpwuid_r)(struct nwrap_backend *b, 182 uid_t uid, struct passwd *pwdst, 183 char *buf, size_t buflen, struct passwd **pwdstp); 184 void (*nw_setpwent)(struct nwrap_backend *b); 185 struct passwd * (*nw_getpwent)(struct nwrap_backend *b); 186 int (*nw_getpwent_r)(struct nwrap_backend *b, 187 struct passwd *pwdst, char *buf, 188 size_t buflen, struct passwd **pwdstp); 189 void (*nw_endpwent)(struct nwrap_backend *b); 190 int (*nw_initgroups)(struct nwrap_backend *b, 191 const char *user, gid_t group); 192 struct group * (*nw_getgrnam)(struct nwrap_backend *b, 193 const char *name); 194 int (*nw_getgrnam_r)(struct nwrap_backend *b, 195 const char *name, struct group *grdst, 196 char *buf, size_t buflen, struct group **grdstp); 197 struct group * (*nw_getgrgid)(struct nwrap_backend *b, 198 gid_t gid); 199 int (*nw_getgrgid_r)(struct nwrap_backend *b, 200 gid_t gid, struct group *grdst, 201 char *buf, size_t buflen, struct group **grdstp); 202 void (*nw_setgrent)(struct nwrap_backend *b); 203 struct group * (*nw_getgrent)(struct nwrap_backend *b); 204 int (*nw_getgrent_r)(struct nwrap_backend *b, 205 struct group *grdst, char *buf, 206 size_t buflen, struct group **grdstp); 207 void (*nw_endgrent)(struct nwrap_backend *b); 208}; 209 210/* protoypes for files backend */ 211 212 213static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, 214 const char *name); 215static int nwrap_files_getpwnam_r(struct nwrap_backend *b, 216 const char *name, struct passwd *pwdst, 217 char *buf, size_t buflen, struct passwd **pwdstp); 218static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b, 219 uid_t uid); 220static int nwrap_files_getpwuid_r(struct nwrap_backend *b, 221 uid_t uid, struct passwd *pwdst, 222 char *buf, size_t buflen, struct passwd **pwdstp); 223static void nwrap_files_setpwent(struct nwrap_backend *b); 224static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b); 225static int nwrap_files_getpwent_r(struct nwrap_backend *b, 226 struct passwd *pwdst, char *buf, 227 size_t buflen, struct passwd **pwdstp); 228static void nwrap_files_endpwent(struct nwrap_backend *b); 229static int nwrap_files_initgroups(struct nwrap_backend *b, 230 const char *user, gid_t group); 231static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, 232 const char *name); 233static int nwrap_files_getgrnam_r(struct nwrap_backend *b, 234 const char *name, struct group *grdst, 235 char *buf, size_t buflen, struct group **grdstp); 236static struct group *nwrap_files_getgrgid(struct nwrap_backend *b, 237 gid_t gid); 238static int nwrap_files_getgrgid_r(struct nwrap_backend *b, 239 gid_t gid, struct group *grdst, 240 char *buf, size_t buflen, struct group **grdstp); 241static void nwrap_files_setgrent(struct nwrap_backend *b); 242static struct group *nwrap_files_getgrent(struct nwrap_backend *b); 243static int nwrap_files_getgrent_r(struct nwrap_backend *b, 244 struct group *grdst, char *buf, 245 size_t buflen, struct group **grdstp); 246static void nwrap_files_endgrent(struct nwrap_backend *b); 247 248/* protoypes for module backend */ 249 250static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b); 251static int nwrap_module_getpwent_r(struct nwrap_backend *b, 252 struct passwd *pwdst, char *buf, 253 size_t buflen, struct passwd **pwdstp); 254static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, 255 const char *name); 256static int nwrap_module_getpwnam_r(struct nwrap_backend *b, 257 const char *name, struct passwd *pwdst, 258 char *buf, size_t buflen, struct passwd **pwdstp); 259static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, 260 uid_t uid); 261static int nwrap_module_getpwuid_r(struct nwrap_backend *b, 262 uid_t uid, struct passwd *pwdst, 263 char *buf, size_t buflen, struct passwd **pwdstp); 264static void nwrap_module_setpwent(struct nwrap_backend *b); 265static void nwrap_module_endpwent(struct nwrap_backend *b); 266static struct group *nwrap_module_getgrent(struct nwrap_backend *b); 267static int nwrap_module_getgrent_r(struct nwrap_backend *b, 268 struct group *grdst, char *buf, 269 size_t buflen, struct group **grdstp); 270static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, 271 const char *name); 272static int nwrap_module_getgrnam_r(struct nwrap_backend *b, 273 const char *name, struct group *grdst, 274 char *buf, size_t buflen, struct group **grdstp); 275static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, 276 gid_t gid); 277static int nwrap_module_getgrgid_r(struct nwrap_backend *b, 278 gid_t gid, struct group *grdst, 279 char *buf, size_t buflen, struct group **grdstp); 280static void nwrap_module_setgrent(struct nwrap_backend *b); 281static void nwrap_module_endgrent(struct nwrap_backend *b); 282static int nwrap_module_initgroups(struct nwrap_backend *b, 283 const char *user, gid_t group); 284 285struct nwrap_ops nwrap_files_ops = { 286 .nw_getpwnam = nwrap_files_getpwnam, 287 .nw_getpwnam_r = nwrap_files_getpwnam_r, 288 .nw_getpwuid = nwrap_files_getpwuid, 289 .nw_getpwuid_r = nwrap_files_getpwuid_r, 290 .nw_setpwent = nwrap_files_setpwent, 291 .nw_getpwent = nwrap_files_getpwent, 292 .nw_getpwent_r = nwrap_files_getpwent_r, 293 .nw_endpwent = nwrap_files_endpwent, 294 .nw_initgroups = nwrap_files_initgroups, 295 .nw_getgrnam = nwrap_files_getgrnam, 296 .nw_getgrnam_r = nwrap_files_getgrnam_r, 297 .nw_getgrgid = nwrap_files_getgrgid, 298 .nw_getgrgid_r = nwrap_files_getgrgid_r, 299 .nw_setgrent = nwrap_files_setgrent, 300 .nw_getgrent = nwrap_files_getgrent, 301 .nw_getgrent_r = nwrap_files_getgrent_r, 302 .nw_endgrent = nwrap_files_endgrent, 303}; 304 305struct nwrap_ops nwrap_module_ops = { 306 .nw_getpwnam = nwrap_module_getpwnam, 307 .nw_getpwnam_r = nwrap_module_getpwnam_r, 308 .nw_getpwuid = nwrap_module_getpwuid, 309 .nw_getpwuid_r = nwrap_module_getpwuid_r, 310 .nw_setpwent = nwrap_module_setpwent, 311 .nw_getpwent = nwrap_module_getpwent, 312 .nw_getpwent_r = nwrap_module_getpwent_r, 313 .nw_endpwent = nwrap_module_endpwent, 314 .nw_initgroups = nwrap_module_initgroups, 315 .nw_getgrnam = nwrap_module_getgrnam, 316 .nw_getgrnam_r = nwrap_module_getgrnam_r, 317 .nw_getgrgid = nwrap_module_getgrgid, 318 .nw_getgrgid_r = nwrap_module_getgrgid_r, 319 .nw_setgrent = nwrap_module_setgrent, 320 .nw_getgrent = nwrap_module_getgrent, 321 .nw_getgrent_r = nwrap_module_getgrent_r, 322 .nw_endgrent = nwrap_module_endgrent, 323}; 324 325struct nwrap_main { 326 const char *nwrap_switch; 327 int num_backends; 328 struct nwrap_backend *backends; 329}; 330 331struct nwrap_main *nwrap_main_global; 332struct nwrap_main __nwrap_main_global; 333 334struct nwrap_cache { 335 const char *path; 336 int fd; 337 struct stat st; 338 uint8_t *buf; 339 void *private_data; 340 bool (*parse_line)(struct nwrap_cache *, char *line); 341 void (*unload)(struct nwrap_cache *); 342}; 343 344struct nwrap_pw { 345 struct nwrap_cache *cache; 346 347 struct passwd *list; 348 int num; 349 int idx; 350}; 351 352struct nwrap_cache __nwrap_cache_pw; 353struct nwrap_pw nwrap_pw_global; 354 355static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line); 356static void nwrap_pw_unload(struct nwrap_cache *nwrap); 357 358struct nwrap_gr { 359 struct nwrap_cache *cache; 360 361 struct group *list; 362 int num; 363 int idx; 364}; 365 366struct nwrap_cache __nwrap_cache_gr; 367struct nwrap_gr nwrap_gr_global; 368 369static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line); 370static void nwrap_gr_unload(struct nwrap_cache *nwrap); 371 372static void *nwrap_load_module_fn(struct nwrap_backend *b, 373 const char *fn_name) 374{ 375 void *res; 376 char *s; 377 378 if (!b->so_handle) { 379 NWRAP_ERROR(("%s: no handle\n", 380 __location__)); 381 return NULL; 382 } 383 384 if (asprintf(&s, "_nss_%s_%s", b->name, fn_name) == -1) { 385 NWRAP_ERROR(("%s: out of memory\n", 386 __location__)); 387 return NULL; 388 } 389 390 res = dlsym(b->so_handle, s); 391 if (!res) { 392 NWRAP_ERROR(("%s: cannot find function %s in %s\n", 393 __location__, s, b->so_path)); 394 } 395 free(s); 396 s = NULL; 397 return res; 398} 399 400static struct nwrap_module_nss_fns *nwrap_load_module_fns(struct nwrap_backend *b) 401{ 402 struct nwrap_module_nss_fns *fns; 403 404 if (!b->so_handle) { 405 return NULL; 406 } 407 408 fns = (struct nwrap_module_nss_fns *)malloc(sizeof(struct nwrap_module_nss_fns)); 409 if (!fns) { 410 return NULL; 411 } 412 413 fns->_nss_getpwnam_r = (NSS_STATUS (*)(const char *, struct passwd *, char *, size_t, int *)) 414 nwrap_load_module_fn(b, "getpwnam_r"); 415 fns->_nss_getpwuid_r = (NSS_STATUS (*)(uid_t, struct passwd *, char *, size_t, int *)) 416 nwrap_load_module_fn(b, "getpwuid_r"); 417 fns->_nss_setpwent = (NSS_STATUS(*)(void)) 418 nwrap_load_module_fn(b, "setpwent"); 419 fns->_nss_getpwent_r = (NSS_STATUS (*)(struct passwd *, char *, size_t, int *)) 420 nwrap_load_module_fn(b, "getpwent_r"); 421 fns->_nss_endpwent = (NSS_STATUS(*)(void)) 422 nwrap_load_module_fn(b, "endpwent"); 423 fns->_nss_initgroups = (NSS_STATUS (*)(const char *, gid_t, long int *, long int *, gid_t **, long int, int *)) 424 nwrap_load_module_fn(b, "initgroups_dyn"); 425 fns->_nss_getgrnam_r = (NSS_STATUS (*)(const char *, struct group *, char *, size_t, int *)) 426 nwrap_load_module_fn(b, "getgrnam_r"); 427 fns->_nss_getgrgid_r = (NSS_STATUS (*)(gid_t, struct group *, char *, size_t, int *)) 428 nwrap_load_module_fn(b, "getgrgid_r"); 429 fns->_nss_setgrent = (NSS_STATUS(*)(void)) 430 nwrap_load_module_fn(b, "setgrent"); 431 fns->_nss_getgrent_r = (NSS_STATUS (*)(struct group *, char *, size_t, int *)) 432 nwrap_load_module_fn(b, "getgrent_r"); 433 fns->_nss_endgrent = (NSS_STATUS(*)(void)) 434 nwrap_load_module_fn(b, "endgrent"); 435 436 return fns; 437} 438 439static void *nwrap_load_module(const char *so_path) 440{ 441 void *h; 442 443 if (!so_path || !strlen(so_path)) { 444 return NULL; 445 } 446 447 h = dlopen(so_path, RTLD_LAZY); 448 if (!h) { 449 NWRAP_ERROR(("%s: cannot open shared library %s\n", 450 __location__, so_path)); 451 return NULL; 452 } 453 454 return h; 455} 456 457static bool nwrap_module_init(const char *name, 458 struct nwrap_ops *ops, 459 const char *so_path, 460 int *num_backends, 461 struct nwrap_backend **backends) 462{ 463 *backends = (struct nwrap_backend *)realloc(*backends, 464 sizeof(struct nwrap_backend) * ((*num_backends) + 1)); 465 if (!*backends) { 466 NWRAP_ERROR(("%s: out of memory\n", 467 __location__)); 468 return false; 469 } 470 471 (*backends)[*num_backends].name = name; 472 (*backends)[*num_backends].ops = ops; 473 (*backends)[*num_backends].so_path = so_path; 474 (*backends)[*num_backends].so_handle = nwrap_load_module(so_path); 475 (*backends)[*num_backends].fns = nwrap_load_module_fns(&((*backends)[*num_backends])); 476 477 (*num_backends)++; 478 479 return true; 480} 481 482static void nwrap_backend_init(struct nwrap_main *r) 483{ 484 const char *winbind_so_path = getenv("NSS_WRAPPER_WINBIND_SO_PATH"); 485 486 r->num_backends = 0; 487 r->backends = NULL; 488 489 if (!nwrap_module_init("files", &nwrap_files_ops, NULL, 490 &r->num_backends, 491 &r->backends)) { 492 NWRAP_ERROR(("%s: failed to initialize 'files' backend\n", 493 __location__)); 494 return; 495 } 496 497 if (winbind_so_path && strlen(winbind_so_path)) { 498 if (!nwrap_module_init("winbind", &nwrap_module_ops, winbind_so_path, 499 &r->num_backends, 500 &r->backends)) { 501 NWRAP_ERROR(("%s: failed to initialize 'winbind' backend\n", 502 __location__)); 503 return; 504 } 505 } 506} 507 508static void nwrap_init(void) 509{ 510 static bool initialized; 511 512 if (initialized) return; 513 initialized = true; 514 515 nwrap_main_global = &__nwrap_main_global; 516 517 nwrap_backend_init(nwrap_main_global); 518 519 nwrap_pw_global.cache = &__nwrap_cache_pw; 520 521 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD"); 522 nwrap_pw_global.cache->fd = -1; 523 nwrap_pw_global.cache->private_data = &nwrap_pw_global; 524 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line; 525 nwrap_pw_global.cache->unload = nwrap_pw_unload; 526 527 nwrap_gr_global.cache = &__nwrap_cache_gr; 528 529 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP"); 530 nwrap_gr_global.cache->fd = -1; 531 nwrap_gr_global.cache->private_data = &nwrap_gr_global; 532 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line; 533 nwrap_gr_global.cache->unload = nwrap_gr_unload; 534} 535 536static bool nwrap_enabled(void) 537{ 538 nwrap_init(); 539 540 if (!nwrap_pw_global.cache->path) { 541 return false; 542 } 543 if (nwrap_pw_global.cache->path[0] == '\0') { 544 return false; 545 } 546 if (!nwrap_gr_global.cache->path) { 547 return false; 548 } 549 if (nwrap_gr_global.cache->path[0] == '\0') { 550 return false; 551 } 552 553 return true; 554} 555 556static bool nwrap_parse_file(struct nwrap_cache *nwrap) 557{ 558 int ret; 559 uint8_t *buf = NULL; 560 char *nline; 561 562 if (nwrap->st.st_size == 0) { 563 NWRAP_DEBUG(("%s: size == 0\n", 564 __location__)); 565 goto done; 566 } 567 568 if (nwrap->st.st_size > INT32_MAX) { 569 NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n", 570 __location__, (unsigned)nwrap->st.st_size)); 571 goto failed; 572 } 573 574 ret = lseek(nwrap->fd, 0, SEEK_SET); 575 if (ret != 0) { 576 NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret)); 577 goto failed; 578 } 579 580 buf = (uint8_t *)malloc(nwrap->st.st_size + 1); 581 if (!buf) { 582 NWRAP_ERROR(("%s: malloc failed\n",__location__)); 583 goto failed; 584 } 585 586 ret = read(nwrap->fd, buf, nwrap->st.st_size); 587 if (ret != nwrap->st.st_size) { 588 NWRAP_ERROR(("%s: read(%u) gave %d\n", 589 __location__, (unsigned)nwrap->st.st_size, ret)); 590 goto failed; 591 } 592 593 buf[nwrap->st.st_size] = '\0'; 594 595 nline = (char *)buf; 596 while (nline && nline[0]) { 597 char *line; 598 char *e; 599 bool ok; 600 601 line = nline; 602 nline = NULL; 603 604 e = strchr(line, '\n'); 605 if (e) { 606 e[0] = '\0'; 607 e++; 608 if (e[0] == '\r') { 609 e[0] = '\0'; 610 e++; 611 } 612 nline = e; 613 } 614 615 NWRAP_VERBOSE(("%s:'%s'\n",__location__, line)); 616 617 if (strlen(line) == 0) { 618 continue; 619 } 620 621 ok = nwrap->parse_line(nwrap, line); 622 if (!ok) { 623 goto failed; 624 } 625 } 626 627done: 628 nwrap->buf = buf; 629 return true; 630 631failed: 632 if (buf) free(buf); 633 return false; 634} 635 636static void nwrap_files_cache_unload(struct nwrap_cache *nwrap) 637{ 638 nwrap->unload(nwrap); 639 640 if (nwrap->buf) free(nwrap->buf); 641 642 nwrap->buf = NULL; 643} 644 645static void nwrap_files_cache_reload(struct nwrap_cache *nwrap) 646{ 647 struct stat st; 648 int ret; 649 bool ok; 650 bool retried = false; 651 652reopen: 653 if (nwrap->fd < 0) { 654 nwrap->fd = open(nwrap->path, O_RDONLY); 655 if (nwrap->fd < 0) { 656 NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n", 657 __location__, 658 nwrap->path, nwrap->fd, 659 strerror(errno))); 660 return; 661 } 662 NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path)); 663 } 664 665 ret = fstat(nwrap->fd, &st); 666 if (ret != 0) { 667 NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n", 668 __location__, 669 nwrap->path, 670 ret, strerror(errno))); 671 return; 672 } 673 674 if (retried == false && st.st_nlink == 0) { 675 /* maybe someone has replaced the file... */ 676 NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n", 677 __location__, nwrap->path)); 678 retried = true; 679 memset(&nwrap->st, 0, sizeof(nwrap->st)); 680 close(nwrap->fd); 681 nwrap->fd = -1; 682 goto reopen; 683 } 684 685 if (st.st_mtime == nwrap->st.st_mtime) { 686 NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n", 687 __location__, (unsigned)st.st_mtime)); 688 return; 689 } 690 NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n", 691 __location__, (unsigned)st.st_mtime, 692 (unsigned)nwrap->st.st_mtime)); 693 694 nwrap->st = st; 695 696 nwrap_files_cache_unload(nwrap); 697 698 ok = nwrap_parse_file(nwrap); 699 if (!ok) { 700 NWRAP_ERROR(("%s: failed to reload %s\n", 701 __location__, nwrap->path)); 702 nwrap_files_cache_unload(nwrap); 703 } 704 NWRAP_DEBUG(("%s: reloaded %s\n", 705 __location__, nwrap->path)); 706} 707 708/* 709 * the caller has to call nwrap_unload() on failure 710 */ 711static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line) 712{ 713 struct nwrap_pw *nwrap_pw; 714 char *c; 715 char *p; 716 char *e; 717 struct passwd *pw; 718 size_t list_size; 719 720 nwrap_pw = (struct nwrap_pw *)nwrap->private_data; 721 722 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1); 723 pw = (struct passwd *)realloc(nwrap_pw->list, list_size); 724 if (!pw) { 725 NWRAP_ERROR(("%s:realloc(%u) failed\n", 726 __location__, list_size)); 727 return false; 728 } 729 nwrap_pw->list = pw; 730 731 pw = &nwrap_pw->list[nwrap_pw->num]; 732 733 c = line; 734 735 /* name */ 736 p = strchr(c, ':'); 737 if (!p) { 738 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 739 __location__, line, c)); 740 return false; 741 } 742 *p = '\0'; 743 p++; 744 pw->pw_name = c; 745 c = p; 746 747 NWRAP_VERBOSE(("name[%s]\n", pw->pw_name)); 748 749 /* password */ 750 p = strchr(c, ':'); 751 if (!p) { 752 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 753 __location__, line, c)); 754 return false; 755 } 756 *p = '\0'; 757 p++; 758 pw->pw_passwd = c; 759 c = p; 760 761 NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd)); 762 763 /* uid */ 764 p = strchr(c, ':'); 765 if (!p) { 766 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 767 __location__, line, c)); 768 return false; 769 } 770 *p = '\0'; 771 p++; 772 e = NULL; 773 pw->pw_uid = (uid_t)strtoul(c, &e, 10); 774 if (c == e) { 775 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 776 __location__, line, c, strerror(errno))); 777 return false; 778 } 779 if (e == NULL) { 780 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 781 __location__, line, c, strerror(errno))); 782 return false; 783 } 784 if (e[0] != '\0') { 785 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 786 __location__, line, c, strerror(errno))); 787 return false; 788 } 789 c = p; 790 791 NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid)); 792 793 /* gid */ 794 p = strchr(c, ':'); 795 if (!p) { 796 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 797 __location__, line, c)); 798 return false; 799 } 800 *p = '\0'; 801 p++; 802 e = NULL; 803 pw->pw_gid = (gid_t)strtoul(c, &e, 10); 804 if (c == e) { 805 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 806 __location__, line, c, strerror(errno))); 807 return false; 808 } 809 if (e == NULL) { 810 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 811 __location__, line, c, strerror(errno))); 812 return false; 813 } 814 if (e[0] != '\0') { 815 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 816 __location__, line, c, strerror(errno))); 817 return false; 818 } 819 c = p; 820 821 NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid)); 822 823 /* gecos */ 824 p = strchr(c, ':'); 825 if (!p) { 826 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 827 __location__, line, c)); 828 return false; 829 } 830 *p = '\0'; 831 p++; 832 pw->pw_gecos = c; 833 c = p; 834 835 NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos)); 836 837 /* dir */ 838 p = strchr(c, ':'); 839 if (!p) { 840 NWRAP_ERROR(("%s:'%s'\n",__location__,c)); 841 return false; 842 } 843 *p = '\0'; 844 p++; 845 pw->pw_dir = c; 846 c = p; 847 848 NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir)); 849 850 /* shell */ 851 pw->pw_shell = c; 852 NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell)); 853 854 NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n", 855 pw->pw_name, pw->pw_passwd, 856 pw->pw_uid, pw->pw_gid, 857 pw->pw_gecos, pw->pw_dir, pw->pw_shell)); 858 859 nwrap_pw->num++; 860 return true; 861} 862 863static void nwrap_pw_unload(struct nwrap_cache *nwrap) 864{ 865 struct nwrap_pw *nwrap_pw; 866 nwrap_pw = (struct nwrap_pw *)nwrap->private_data; 867 868 if (nwrap_pw->list) free(nwrap_pw->list); 869 870 nwrap_pw->list = NULL; 871 nwrap_pw->num = 0; 872 nwrap_pw->idx = 0; 873} 874 875static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst, 876 char *buf, size_t buflen, struct passwd **dstp) 877{ 878 char *first; 879 char *last; 880 off_t ofs; 881 882 first = src->pw_name; 883 884 last = src->pw_shell; 885 while (*last) last++; 886 887 ofs = PTR_DIFF(last + 1, first); 888 889 if (ofs > buflen) { 890 return ERANGE; 891 } 892 893 memcpy(buf, first, ofs); 894 895 ofs = PTR_DIFF(src->pw_name, first); 896 dst->pw_name = buf + ofs; 897 ofs = PTR_DIFF(src->pw_passwd, first); 898 dst->pw_passwd = buf + ofs; 899 dst->pw_uid = src->pw_uid; 900 dst->pw_gid = src->pw_gid; 901 ofs = PTR_DIFF(src->pw_gecos, first); 902 dst->pw_gecos = buf + ofs; 903 ofs = PTR_DIFF(src->pw_dir, first); 904 dst->pw_dir = buf + ofs; 905 ofs = PTR_DIFF(src->pw_shell, first); 906 dst->pw_shell = buf + ofs; 907 908 if (dstp) { 909 *dstp = dst; 910 } 911 912 return 0; 913} 914 915/* 916 * the caller has to call nwrap_unload() on failure 917 */ 918static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line) 919{ 920 struct nwrap_gr *nwrap_gr; 921 char *c; 922 char *p; 923 char *e; 924 struct group *gr; 925 size_t list_size; 926 unsigned nummem; 927 928 nwrap_gr = (struct nwrap_gr *)nwrap->private_data; 929 930 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1); 931 gr = (struct group *)realloc(nwrap_gr->list, list_size); 932 if (!gr) { 933 NWRAP_ERROR(("%s:realloc failed\n",__location__)); 934 return false; 935 } 936 nwrap_gr->list = gr; 937 938 gr = &nwrap_gr->list[nwrap_gr->num]; 939 940 c = line; 941 942 /* name */ 943 p = strchr(c, ':'); 944 if (!p) { 945 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 946 __location__, line, c)); 947 return false; 948 } 949 *p = '\0'; 950 p++; 951 gr->gr_name = c; 952 c = p; 953 954 NWRAP_VERBOSE(("name[%s]\n", gr->gr_name)); 955 956 /* password */ 957 p = strchr(c, ':'); 958 if (!p) { 959 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 960 __location__, line, c)); 961 return false; 962 } 963 *p = '\0'; 964 p++; 965 gr->gr_passwd = c; 966 c = p; 967 968 NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd)); 969 970 /* gid */ 971 p = strchr(c, ':'); 972 if (!p) { 973 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n", 974 __location__, line, c)); 975 return false; 976 } 977 *p = '\0'; 978 p++; 979 e = NULL; 980 gr->gr_gid = (gid_t)strtoul(c, &e, 10); 981 if (c == e) { 982 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 983 __location__, line, c, strerror(errno))); 984 return false; 985 } 986 if (e == NULL) { 987 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 988 __location__, line, c, strerror(errno))); 989 return false; 990 } 991 if (e[0] != '\0') { 992 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n", 993 __location__, line, c, strerror(errno))); 994 return false; 995 } 996 c = p; 997 998 NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid)); 999 1000 /* members */ 1001 gr->gr_mem = (char **)malloc(sizeof(char *)); 1002 if (!gr->gr_mem) { 1003 NWRAP_ERROR(("%s:calloc failed\n",__location__)); 1004 return false; 1005 } 1006 gr->gr_mem[0] = NULL; 1007 1008 for(nummem=0; p; nummem++) { 1009 char **m; 1010 size_t m_size; 1011 c = p; 1012 p = strchr(c, ','); 1013 if (p) { 1014 *p = '\0'; 1015 p++; 1016 } 1017 1018 if (strlen(c) == 0) { 1019 break; 1020 } 1021 1022 m_size = sizeof(char *) * (nummem+2); 1023 m = (char **)realloc(gr->gr_mem, m_size); 1024 if (!m) { 1025 NWRAP_ERROR(("%s:realloc(%u) failed\n", 1026 __location__, m_size)); 1027 return false; 1028 } 1029 gr->gr_mem = m; 1030 gr->gr_mem[nummem] = c; 1031 gr->gr_mem[nummem+1] = NULL; 1032 1033 NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem])); 1034 } 1035 1036 NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n", 1037 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem)); 1038 1039 nwrap_gr->num++; 1040 return true; 1041} 1042 1043static void nwrap_gr_unload(struct nwrap_cache *nwrap) 1044{ 1045 int i; 1046 struct nwrap_gr *nwrap_gr; 1047 nwrap_gr = (struct nwrap_gr *)nwrap->private_data; 1048 1049 if (nwrap_gr->list) { 1050 for (i=0; i < nwrap_gr->num; i++) { 1051 if (nwrap_gr->list[i].gr_mem) { 1052 free(nwrap_gr->list[i].gr_mem); 1053 } 1054 } 1055 free(nwrap_gr->list); 1056 } 1057 1058 nwrap_gr->list = NULL; 1059 nwrap_gr->num = 0; 1060 nwrap_gr->idx = 0; 1061} 1062 1063static int nwrap_gr_copy_r(const struct group *src, struct group *dst, 1064 char *buf, size_t buflen, struct group **dstp) 1065{ 1066 char *first; 1067 char **lastm; 1068 char *last = NULL; 1069 off_t ofsb; 1070 off_t ofsm; 1071 off_t ofs; 1072 unsigned i; 1073 1074 first = src->gr_name; 1075 1076 lastm = src->gr_mem; 1077 while (*lastm) { 1078 last = *lastm; 1079 lastm++; 1080 } 1081 1082 if (last == NULL) { 1083 last = src->gr_passwd; 1084 } 1085 while (*last) last++; 1086 1087 ofsb = PTR_DIFF(last + 1, first); 1088 ofsm = PTR_DIFF(lastm + 1, src->gr_mem); 1089 1090 if ((ofsb + ofsm) > buflen) { 1091 return ERANGE; 1092 } 1093 1094 memcpy(buf, first, ofsb); 1095 memcpy(buf + ofsb, src->gr_mem, ofsm); 1096 1097 ofs = PTR_DIFF(src->gr_name, first); 1098 dst->gr_name = buf + ofs; 1099 ofs = PTR_DIFF(src->gr_passwd, first); 1100 dst->gr_passwd = buf + ofs; 1101 dst->gr_gid = src->gr_gid; 1102 1103 dst->gr_mem = (char **)(buf + ofsb); 1104 for (i=0; src->gr_mem[i]; i++) { 1105 ofs = PTR_DIFF(src->gr_mem[i], first); 1106 dst->gr_mem[i] = buf + ofs; 1107 } 1108 1109 if (dstp) { 1110 *dstp = dst; 1111 } 1112 1113 return 0; 1114} 1115 1116/* user functions */ 1117static struct passwd *nwrap_files_getpwnam(struct nwrap_backend *b, 1118 const char *name) 1119{ 1120 int i; 1121 1122 nwrap_files_cache_reload(nwrap_pw_global.cache); 1123 1124 for (i=0; i<nwrap_pw_global.num; i++) { 1125 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) { 1126 NWRAP_DEBUG(("%s: user[%s] found\n", 1127 __location__, name)); 1128 return &nwrap_pw_global.list[i]; 1129 } 1130 NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n", 1131 __location__, name, 1132 nwrap_pw_global.list[i].pw_name)); 1133 } 1134 1135 NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name)); 1136 1137 errno = ENOENT; 1138 return NULL; 1139} 1140 1141static int nwrap_files_getpwnam_r(struct nwrap_backend *b, 1142 const char *name, struct passwd *pwdst, 1143 char *buf, size_t buflen, struct passwd **pwdstp) 1144{ 1145 struct passwd *pw; 1146 1147 pw = nwrap_files_getpwnam(b, name); 1148 if (!pw) { 1149 if (errno == 0) { 1150 return ENOENT; 1151 } 1152 return errno; 1153 } 1154 1155 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp); 1156} 1157 1158static struct passwd *nwrap_files_getpwuid(struct nwrap_backend *b, 1159 uid_t uid) 1160{ 1161 int i; 1162 1163 nwrap_files_cache_reload(nwrap_pw_global.cache); 1164 1165 for (i=0; i<nwrap_pw_global.num; i++) { 1166 if (nwrap_pw_global.list[i].pw_uid == uid) { 1167 NWRAP_DEBUG(("%s: uid[%u] found\n", 1168 __location__, uid)); 1169 return &nwrap_pw_global.list[i]; 1170 } 1171 NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n", 1172 __location__, uid, 1173 nwrap_pw_global.list[i].pw_uid)); 1174 } 1175 1176 NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid)); 1177 1178 errno = ENOENT; 1179 return NULL; 1180} 1181 1182static int nwrap_files_getpwuid_r(struct nwrap_backend *b, 1183 uid_t uid, struct passwd *pwdst, 1184 char *buf, size_t buflen, struct passwd **pwdstp) 1185{ 1186 struct passwd *pw; 1187 1188 pw = nwrap_files_getpwuid(b, uid); 1189 if (!pw) { 1190 if (errno == 0) { 1191 return ENOENT; 1192 } 1193 return errno; 1194 } 1195 1196 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp); 1197} 1198 1199/* user enum functions */ 1200static void nwrap_files_setpwent(struct nwrap_backend *b) 1201{ 1202 nwrap_pw_global.idx = 0; 1203} 1204 1205static struct passwd *nwrap_files_getpwent(struct nwrap_backend *b) 1206{ 1207 struct passwd *pw; 1208 1209 if (nwrap_pw_global.idx == 0) { 1210 nwrap_files_cache_reload(nwrap_pw_global.cache); 1211 } 1212 1213 if (nwrap_pw_global.idx >= nwrap_pw_global.num) { 1214 errno = ENOENT; 1215 return NULL; 1216 } 1217 1218 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++]; 1219 1220 NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n", 1221 __location__, pw->pw_name, pw->pw_uid)); 1222 1223 return pw; 1224} 1225 1226static int nwrap_files_getpwent_r(struct nwrap_backend *b, 1227 struct passwd *pwdst, char *buf, 1228 size_t buflen, struct passwd **pwdstp) 1229{ 1230 struct passwd *pw; 1231 1232 pw = nwrap_files_getpwent(b); 1233 if (!pw) { 1234 if (errno == 0) { 1235 return ENOENT; 1236 } 1237 return errno; 1238 } 1239 1240 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp); 1241} 1242 1243static void nwrap_files_endpwent(struct nwrap_backend *b) 1244{ 1245 nwrap_pw_global.idx = 0; 1246} 1247 1248/* misc functions */ 1249static int nwrap_files_initgroups(struct nwrap_backend *b, 1250 const char *user, gid_t group) 1251{ 1252 /* TODO: maybe we should also fake this... */ 1253 return EPERM; 1254} 1255 1256/* group functions */ 1257static struct group *nwrap_files_getgrnam(struct nwrap_backend *b, 1258 const char *name) 1259{ 1260 int i; 1261 1262 nwrap_files_cache_reload(nwrap_gr_global.cache); 1263 1264 for (i=0; i<nwrap_gr_global.num; i++) { 1265 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) { 1266 NWRAP_DEBUG(("%s: group[%s] found\n", 1267 __location__, name)); 1268 return &nwrap_gr_global.list[i]; 1269 } 1270 NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n", 1271 __location__, name, 1272 nwrap_gr_global.list[i].gr_name)); 1273 } 1274 1275 NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name)); 1276 1277 errno = ENOENT; 1278 return NULL; 1279} 1280 1281static int nwrap_files_getgrnam_r(struct nwrap_backend *b, 1282 const char *name, struct group *grdst, 1283 char *buf, size_t buflen, struct group **grdstp) 1284{ 1285 struct group *gr; 1286 1287 gr = nwrap_files_getgrnam(b, name); 1288 if (!gr) { 1289 if (errno == 0) { 1290 return ENOENT; 1291 } 1292 return errno; 1293 } 1294 1295 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp); 1296} 1297 1298static struct group *nwrap_files_getgrgid(struct nwrap_backend *b, 1299 gid_t gid) 1300{ 1301 int i; 1302 1303 nwrap_files_cache_reload(nwrap_gr_global.cache); 1304 1305 for (i=0; i<nwrap_gr_global.num; i++) { 1306 if (nwrap_gr_global.list[i].gr_gid == gid) { 1307 NWRAP_DEBUG(("%s: gid[%u] found\n", 1308 __location__, gid)); 1309 return &nwrap_gr_global.list[i]; 1310 } 1311 NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n", 1312 __location__, gid, 1313 nwrap_gr_global.list[i].gr_gid)); 1314 } 1315 1316 NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid)); 1317 1318 errno = ENOENT; 1319 return NULL; 1320} 1321 1322static int nwrap_files_getgrgid_r(struct nwrap_backend *b, 1323 gid_t gid, struct group *grdst, 1324 char *buf, size_t buflen, struct group **grdstp) 1325{ 1326 struct group *gr; 1327 1328 gr = nwrap_files_getgrgid(b, gid); 1329 if (!gr) { 1330 if (errno == 0) { 1331 return ENOENT; 1332 } 1333 return errno; 1334 } 1335 1336 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp); 1337} 1338 1339/* group enum functions */ 1340static void nwrap_files_setgrent(struct nwrap_backend *b) 1341{ 1342 nwrap_gr_global.idx = 0; 1343} 1344 1345static struct group *nwrap_files_getgrent(struct nwrap_backend *b) 1346{ 1347 struct group *gr; 1348 1349 if (nwrap_gr_global.idx == 0) { 1350 nwrap_files_cache_reload(nwrap_gr_global.cache); 1351 } 1352 1353 if (nwrap_gr_global.idx >= nwrap_gr_global.num) { 1354 errno = ENOENT; 1355 return NULL; 1356 } 1357 1358 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++]; 1359 1360 NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n", 1361 __location__, gr->gr_name, gr->gr_gid)); 1362 1363 return gr; 1364} 1365 1366static int nwrap_files_getgrent_r(struct nwrap_backend *b, 1367 struct group *grdst, char *buf, 1368 size_t buflen, struct group **grdstp) 1369{ 1370 struct group *gr; 1371 1372 gr = nwrap_files_getgrent(b); 1373 if (!gr) { 1374 if (errno == 0) { 1375 return ENOENT; 1376 } 1377 return errno; 1378 } 1379 1380 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp); 1381} 1382 1383static void nwrap_files_endgrent(struct nwrap_backend *b) 1384{ 1385 nwrap_gr_global.idx = 0; 1386} 1387 1388/* 1389 * module backend 1390 */ 1391 1392#ifndef SAFE_FREE 1393#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0) 1394#endif 1395 1396static struct passwd *nwrap_module_getpwnam(struct nwrap_backend *b, 1397 const char *name) 1398{ 1399 static struct passwd pwd; 1400 static char buf[1000]; 1401 NSS_STATUS status; 1402 1403 if (!b->fns->_nss_getpwnam_r) { 1404 return NULL; 1405 } 1406 1407 status = b->fns->_nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &errno); 1408 if (status == NSS_STATUS_NOTFOUND) { 1409 return NULL; 1410 } 1411 if (status != NSS_STATUS_SUCCESS) { 1412 return NULL; 1413 } 1414 return &pwd; 1415} 1416 1417static int nwrap_module_getpwnam_r(struct nwrap_backend *b, 1418 const char *name, struct passwd *pwdst, 1419 char *buf, size_t buflen, struct passwd **pwdstp) 1420{ 1421 int ret; 1422 1423 if (!b->fns->_nss_getpwnam_r) { 1424 return NSS_STATUS_NOTFOUND; 1425 } 1426 1427 ret = b->fns->_nss_getpwnam_r(name, pwdst, buf, buflen, &errno); 1428 switch (ret) { 1429 case NSS_STATUS_SUCCESS: 1430 return 0; 1431 case NSS_STATUS_NOTFOUND: 1432 if (errno != 0) { 1433 return errno; 1434 } 1435 return ENOENT; 1436 case NSS_STATUS_TRYAGAIN: 1437 if (errno != 0) { 1438 return errno; 1439 } 1440 return ERANGE; 1441 default: 1442 if (errno != 0) { 1443 return errno; 1444 } 1445 return ret; 1446 } 1447} 1448 1449static struct passwd *nwrap_module_getpwuid(struct nwrap_backend *b, 1450 uid_t uid) 1451{ 1452 static struct passwd pwd; 1453 static char buf[1000]; 1454 NSS_STATUS status; 1455 1456 if (!b->fns->_nss_getpwuid_r) { 1457 return NULL; 1458 } 1459 1460 status = b->fns->_nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &errno); 1461 if (status == NSS_STATUS_NOTFOUND) { 1462 return NULL; 1463 } 1464 if (status != NSS_STATUS_SUCCESS) { 1465 return NULL; 1466 } 1467 return &pwd; 1468} 1469 1470static int nwrap_module_getpwuid_r(struct nwrap_backend *b, 1471 uid_t uid, struct passwd *pwdst, 1472 char *buf, size_t buflen, struct passwd **pwdstp) 1473{ 1474 int ret; 1475 1476 if (!b->fns->_nss_getpwuid_r) { 1477 return ENOENT; 1478 } 1479 1480 ret = b->fns->_nss_getpwuid_r(uid, pwdst, buf, buflen, &errno); 1481 switch (ret) { 1482 case NSS_STATUS_SUCCESS: 1483 return 0; 1484 case NSS_STATUS_NOTFOUND: 1485 if (errno != 0) { 1486 return errno; 1487 } 1488 return ENOENT; 1489 case NSS_STATUS_TRYAGAIN: 1490 if (errno != 0) { 1491 return errno; 1492 } 1493 return ERANGE; 1494 default: 1495 if (errno != 0) { 1496 return errno; 1497 } 1498 return ret; 1499 } 1500} 1501 1502static void nwrap_module_setpwent(struct nwrap_backend *b) 1503{ 1504 if (!b->fns->_nss_setpwent) { 1505 return; 1506 } 1507 1508 b->fns->_nss_setpwent(); 1509} 1510 1511static struct passwd *nwrap_module_getpwent(struct nwrap_backend *b) 1512{ 1513 static struct passwd pwd; 1514 static char buf[1000]; 1515 NSS_STATUS status; 1516 1517 if (!b->fns->_nss_getpwent_r) { 1518 return NULL; 1519 } 1520 1521 status = b->fns->_nss_getpwent_r(&pwd, buf, sizeof(buf), &errno); 1522 if (status == NSS_STATUS_NOTFOUND) { 1523 return NULL; 1524 } 1525 if (status != NSS_STATUS_SUCCESS) { 1526 return NULL; 1527 } 1528 return &pwd; 1529} 1530 1531static int nwrap_module_getpwent_r(struct nwrap_backend *b, 1532 struct passwd *pwdst, char *buf, 1533 size_t buflen, struct passwd **pwdstp) 1534{ 1535 int ret; 1536 1537 if (!b->fns->_nss_getpwent_r) { 1538 return ENOENT; 1539 } 1540 1541 ret = b->fns->_nss_getpwent_r(pwdst, buf, buflen, &errno); 1542 switch (ret) { 1543 case NSS_STATUS_SUCCESS: 1544 return 0; 1545 case NSS_STATUS_NOTFOUND: 1546 if (errno != 0) { 1547 return errno; 1548 } 1549 return ENOENT; 1550 case NSS_STATUS_TRYAGAIN: 1551 if (errno != 0) { 1552 return errno; 1553 } 1554 return ERANGE; 1555 default: 1556 if (errno != 0) { 1557 return errno; 1558 } 1559 return ret; 1560 } 1561} 1562 1563static void nwrap_module_endpwent(struct nwrap_backend *b) 1564{ 1565 if (!b->fns->_nss_endpwent) { 1566 return; 1567 } 1568 1569 b->fns->_nss_endpwent(); 1570} 1571 1572static int nwrap_module_initgroups(struct nwrap_backend *b, 1573 const char *user, gid_t group) 1574{ 1575 gid_t *groups; 1576 long int start; 1577 long int size; 1578 1579 if (!b->fns->_nss_initgroups) { 1580 return NSS_STATUS_UNAVAIL; 1581 } 1582 1583 return b->fns->_nss_initgroups(user, group, &start, &size, &groups, 0, &errno); 1584} 1585 1586static struct group *nwrap_module_getgrnam(struct nwrap_backend *b, 1587 const char *name) 1588{ 1589 static struct group grp; 1590 static char *buf; 1591 static int buflen = 1000; 1592 NSS_STATUS status; 1593 1594 if (!b->fns->_nss_getgrnam_r) { 1595 return NULL; 1596 } 1597 1598 if (!buf) { 1599 buf = (char *)malloc(buflen); 1600 } 1601again: 1602 status = b->fns->_nss_getgrnam_r(name, &grp, buf, buflen, &errno); 1603 if (status == NSS_STATUS_TRYAGAIN) { 1604 buflen *= 2; 1605 buf = (char *)realloc(buf, buflen); 1606 if (!buf) { 1607 return NULL; 1608 } 1609 goto again; 1610 } 1611 if (status == NSS_STATUS_NOTFOUND) { 1612 SAFE_FREE(buf); 1613 return NULL; 1614 } 1615 if (status != NSS_STATUS_SUCCESS) { 1616 SAFE_FREE(buf); 1617 return NULL; 1618 } 1619 return &grp; 1620} 1621 1622static int nwrap_module_getgrnam_r(struct nwrap_backend *b, 1623 const char *name, struct group *grdst, 1624 char *buf, size_t buflen, struct group **grdstp) 1625{ 1626 int ret; 1627 1628 if (!b->fns->_nss_getgrnam_r) { 1629 return ENOENT; 1630 } 1631 1632 ret = b->fns->_nss_getgrnam_r(name, grdst, buf, buflen, &errno); 1633 switch (ret) { 1634 case NSS_STATUS_SUCCESS: 1635 return 0; 1636 case NSS_STATUS_NOTFOUND: 1637 if (errno != 0) { 1638 return errno; 1639 } 1640 return ENOENT; 1641 case NSS_STATUS_TRYAGAIN: 1642 if (errno != 0) { 1643 return errno; 1644 } 1645 return ERANGE; 1646 default: 1647 if (errno != 0) { 1648 return errno; 1649 } 1650 return ret; 1651 } 1652} 1653 1654static struct group *nwrap_module_getgrgid(struct nwrap_backend *b, 1655 gid_t gid) 1656{ 1657 static struct group grp; 1658 static char *buf; 1659 static int buflen = 1000; 1660 NSS_STATUS status; 1661 1662 if (!b->fns->_nss_getgrgid_r) { 1663 return NULL; 1664 } 1665 1666 if (!buf) { 1667 buf = (char *)malloc(buflen); 1668 } 1669 1670again: 1671 status = b->fns->_nss_getgrgid_r(gid, &grp, buf, buflen, &errno); 1672 if (status == NSS_STATUS_TRYAGAIN) { 1673 buflen *= 2; 1674 buf = (char *)realloc(buf, buflen); 1675 if (!buf) { 1676 return NULL; 1677 } 1678 goto again; 1679 } 1680 if (status == NSS_STATUS_NOTFOUND) { 1681 SAFE_FREE(buf); 1682 return NULL; 1683 } 1684 if (status != NSS_STATUS_SUCCESS) { 1685 SAFE_FREE(buf); 1686 return NULL; 1687 } 1688 return &grp; 1689} 1690 1691static int nwrap_module_getgrgid_r(struct nwrap_backend *b, 1692 gid_t gid, struct group *grdst, 1693 char *buf, size_t buflen, struct group **grdstp) 1694{ 1695 int ret; 1696 1697 if (!b->fns->_nss_getgrgid_r) { 1698 return ENOENT; 1699 } 1700 1701 ret = b->fns->_nss_getgrgid_r(gid, grdst, buf, buflen, &errno); 1702 switch (ret) { 1703 case NSS_STATUS_SUCCESS: 1704 return 0; 1705 case NSS_STATUS_NOTFOUND: 1706 if (errno != 0) { 1707 return errno; 1708 } 1709 return ENOENT; 1710 case NSS_STATUS_TRYAGAIN: 1711 if (errno != 0) { 1712 return errno; 1713 } 1714 return ERANGE; 1715 default: 1716 if (errno != 0) { 1717 return errno; 1718 } 1719 return ret; 1720 } 1721} 1722 1723static void nwrap_module_setgrent(struct nwrap_backend *b) 1724{ 1725 if (!b->fns->_nss_setgrent) { 1726 return; 1727 } 1728 1729 b->fns->_nss_setgrent(); 1730} 1731 1732static struct group *nwrap_module_getgrent(struct nwrap_backend *b) 1733{ 1734 static struct group grp; 1735 static char *buf; 1736 static int buflen = 1024; 1737 NSS_STATUS status; 1738 1739 if (!b->fns->_nss_getgrent_r) { 1740 return NULL; 1741 } 1742 1743 if (!buf) { 1744 buf = (char *)malloc(buflen); 1745 } 1746 1747again: 1748 status = b->fns->_nss_getgrent_r(&grp, buf, buflen, &errno); 1749 if (status == NSS_STATUS_TRYAGAIN) { 1750 buflen *= 2; 1751 buf = (char *)realloc(buf, buflen); 1752 if (!buf) { 1753 return NULL; 1754 } 1755 goto again; 1756 } 1757 if (status == NSS_STATUS_NOTFOUND) { 1758 SAFE_FREE(buf); 1759 return NULL; 1760 } 1761 if (status != NSS_STATUS_SUCCESS) { 1762 SAFE_FREE(buf); 1763 return NULL; 1764 } 1765 return &grp; 1766} 1767 1768static int nwrap_module_getgrent_r(struct nwrap_backend *b, 1769 struct group *grdst, char *buf, 1770 size_t buflen, struct group **grdstp) 1771{ 1772 int ret; 1773 1774 if (!b->fns->_nss_getgrent_r) { 1775 return ENOENT; 1776 } 1777 1778 ret = b->fns->_nss_getgrent_r(grdst, buf, buflen, &errno); 1779 switch (ret) { 1780 case NSS_STATUS_SUCCESS: 1781 return 0; 1782 case NSS_STATUS_NOTFOUND: 1783 if (errno != 0) { 1784 return errno; 1785 } 1786 return ENOENT; 1787 case NSS_STATUS_TRYAGAIN: 1788 if (errno != 0) { 1789 return errno; 1790 } 1791 return ERANGE; 1792 default: 1793 if (errno != 0) { 1794 return errno; 1795 } 1796 return ret; 1797 } 1798} 1799 1800static void nwrap_module_endgrent(struct nwrap_backend *b) 1801{ 1802 if (!b->fns->_nss_endgrent) { 1803 return; 1804 } 1805 1806 b->fns->_nss_endgrent(); 1807} 1808 1809/* 1810 * PUBLIC interface 1811 */ 1812 1813_PUBLIC_ struct passwd *nwrap_getpwnam(const char *name) 1814{ 1815 int i; 1816 struct passwd *pwd; 1817 1818 if (!nwrap_enabled()) { 1819 return real_getpwnam(name); 1820 } 1821 1822 for (i=0; i < nwrap_main_global->num_backends; i++) { 1823 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1824 pwd = b->ops->nw_getpwnam(b, name); 1825 if (pwd) { 1826 return pwd; 1827 } 1828 } 1829 1830 return NULL; 1831} 1832 1833_PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst, 1834 char *buf, size_t buflen, struct passwd **pwdstp) 1835{ 1836 int i,ret; 1837 1838 if (!nwrap_enabled()) { 1839 return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp); 1840 } 1841 1842 for (i=0; i < nwrap_main_global->num_backends; i++) { 1843 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1844 ret = b->ops->nw_getpwnam_r(b, name, pwdst, buf, buflen, pwdstp); 1845 if (ret == ENOENT) { 1846 continue; 1847 } 1848 return ret; 1849 } 1850 1851 return ENOENT; 1852} 1853 1854_PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid) 1855{ 1856 int i; 1857 struct passwd *pwd; 1858 1859 if (!nwrap_enabled()) { 1860 return real_getpwuid(uid); 1861 } 1862 1863 for (i=0; i < nwrap_main_global->num_backends; i++) { 1864 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1865 pwd = b->ops->nw_getpwuid(b, uid); 1866 if (pwd) { 1867 return pwd; 1868 } 1869 } 1870 1871 return NULL; 1872} 1873 1874_PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst, 1875 char *buf, size_t buflen, struct passwd **pwdstp) 1876{ 1877 int i,ret; 1878 1879 if (!nwrap_enabled()) { 1880 return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp); 1881 } 1882 1883 for (i=0; i < nwrap_main_global->num_backends; i++) { 1884 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1885 ret = b->ops->nw_getpwuid_r(b, uid, pwdst, buf, buflen, pwdstp); 1886 if (ret == ENOENT) { 1887 continue; 1888 } 1889 return ret; 1890 } 1891 1892 return ENOENT; 1893} 1894 1895_PUBLIC_ void nwrap_setpwent(void) 1896{ 1897 int i; 1898 1899 if (!nwrap_enabled()) { 1900 real_setpwent(); 1901 return; 1902 } 1903 1904 for (i=0; i < nwrap_main_global->num_backends; i++) { 1905 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1906 b->ops->nw_setpwent(b); 1907 } 1908} 1909 1910_PUBLIC_ struct passwd *nwrap_getpwent(void) 1911{ 1912 int i; 1913 struct passwd *pwd; 1914 1915 if (!nwrap_enabled()) { 1916 return real_getpwent(); 1917 } 1918 1919 for (i=0; i < nwrap_main_global->num_backends; i++) { 1920 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1921 pwd = b->ops->nw_getpwent(b); 1922 if (pwd) { 1923 return pwd; 1924 } 1925 } 1926 1927 return NULL; 1928} 1929 1930_PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf, 1931 size_t buflen, struct passwd **pwdstp) 1932{ 1933 int i,ret; 1934 1935 if (!nwrap_enabled()) { 1936#ifdef SOLARIS_GETPWENT_R 1937 struct passwd *pw; 1938 pw = real_getpwent_r(pwdst, buf, buflen); 1939 if (!pw) { 1940 if (errno == 0) { 1941 return ENOENT; 1942 } 1943 return errno; 1944 } 1945 if (pwdstp) { 1946 *pwdstp = pw; 1947 } 1948 return 0; 1949#else 1950 return real_getpwent_r(pwdst, buf, buflen, pwdstp); 1951#endif 1952 } 1953 1954 for (i=0; i < nwrap_main_global->num_backends; i++) { 1955 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1956 ret = b->ops->nw_getpwent_r(b, pwdst, buf, buflen, pwdstp); 1957 if (ret == ENOENT) { 1958 continue; 1959 } 1960 return ret; 1961 } 1962 1963 return ENOENT; 1964} 1965 1966_PUBLIC_ void nwrap_endpwent(void) 1967{ 1968 int i; 1969 1970 if (!nwrap_enabled()) { 1971 real_endpwent(); 1972 return; 1973 } 1974 1975 for (i=0; i < nwrap_main_global->num_backends; i++) { 1976 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1977 b->ops->nw_endpwent(b); 1978 } 1979} 1980 1981_PUBLIC_ int nwrap_initgroups(const char *user, gid_t group) 1982{ 1983 int i; 1984 1985 if (!nwrap_enabled()) { 1986 return real_initgroups(user, group); 1987 } 1988 1989 for (i=0; i < nwrap_main_global->num_backends; i++) { 1990 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 1991 return b->ops->nw_initgroups(b, user, group); 1992 } 1993 1994 errno = ENOENT; 1995 return -1; 1996} 1997 1998_PUBLIC_ struct group *nwrap_getgrnam(const char *name) 1999{ 2000 int i; 2001 struct group *grp; 2002 2003 if (!nwrap_enabled()) { 2004 return real_getgrnam(name); 2005 } 2006 2007 for (i=0; i < nwrap_main_global->num_backends; i++) { 2008 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2009 grp = b->ops->nw_getgrnam(b, name); 2010 if (grp) { 2011 return grp; 2012 } 2013 } 2014 2015 return NULL; 2016} 2017 2018_PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst, 2019 char *buf, size_t buflen, struct group **grdstp) 2020{ 2021 int i,ret; 2022 2023 if (!nwrap_enabled()) { 2024 return real_getgrnam_r(name, grdst, buf, buflen, grdstp); 2025 } 2026 2027 for (i=0; i < nwrap_main_global->num_backends; i++) { 2028 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2029 ret = b->ops->nw_getgrnam_r(b, name, grdst, buf, buflen, grdstp); 2030 if (ret == ENOENT) { 2031 continue; 2032 } 2033 return ret; 2034 } 2035 2036 return ENOENT; 2037} 2038 2039_PUBLIC_ struct group *nwrap_getgrgid(gid_t gid) 2040{ 2041 int i; 2042 struct group *grp; 2043 2044 if (!nwrap_enabled()) { 2045 return real_getgrgid(gid); 2046 } 2047 2048 for (i=0; i < nwrap_main_global->num_backends; i++) { 2049 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2050 grp = b->ops->nw_getgrgid(b, gid); 2051 if (grp) { 2052 return grp; 2053 } 2054 } 2055 2056 return NULL; 2057} 2058 2059_PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst, 2060 char *buf, size_t buflen, struct group **grdstp) 2061{ 2062 int i,ret; 2063 2064 if (!nwrap_enabled()) { 2065 return real_getgrgid_r(gid, grdst, buf, buflen, grdstp); 2066 } 2067 2068 for (i=0; i < nwrap_main_global->num_backends; i++) { 2069 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2070 ret = b->ops->nw_getgrgid_r(b, gid, grdst, buf, buflen, grdstp); 2071 if (ret == ENOENT) { 2072 continue; 2073 } 2074 return ret; 2075 } 2076 2077 return ENOENT; 2078} 2079 2080_PUBLIC_ void nwrap_setgrent(void) 2081{ 2082 int i; 2083 2084 if (!nwrap_enabled()) { 2085 real_setgrent(); 2086 return; 2087 } 2088 2089 for (i=0; i < nwrap_main_global->num_backends; i++) { 2090 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2091 b->ops->nw_setgrent(b); 2092 } 2093} 2094 2095_PUBLIC_ struct group *nwrap_getgrent(void) 2096{ 2097 int i; 2098 struct group *grp; 2099 2100 if (!nwrap_enabled()) { 2101 return real_getgrent(); 2102 } 2103 2104 for (i=0; i < nwrap_main_global->num_backends; i++) { 2105 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2106 grp = b->ops->nw_getgrent(b); 2107 if (grp) { 2108 return grp; 2109 } 2110 } 2111 2112 return NULL; 2113} 2114 2115_PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf, 2116 size_t buflen, struct group **grdstp) 2117{ 2118 int i,ret; 2119 2120 if (!nwrap_enabled()) { 2121#ifdef SOLARIS_GETGRENT_R 2122 struct group *gr; 2123 gr = real_getgrent_r(grdst, buf, buflen); 2124 if (!gr) { 2125 if (errno == 0) { 2126 return ENOENT; 2127 } 2128 return errno; 2129 } 2130 if (grdstp) { 2131 *grdstp = gr; 2132 } 2133 return 0; 2134#else 2135 return real_getgrent_r(grdst, buf, buflen, grdstp); 2136#endif 2137 } 2138 2139 for (i=0; i < nwrap_main_global->num_backends; i++) { 2140 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2141 ret = b->ops->nw_getgrent_r(b, grdst, buf, buflen, grdstp); 2142 if (ret == ENOENT) { 2143 continue; 2144 } 2145 return ret; 2146 } 2147 2148 return ENOENT; 2149} 2150 2151_PUBLIC_ void nwrap_endgrent(void) 2152{ 2153 int i; 2154 2155 if (!nwrap_enabled()) { 2156 real_endgrent(); 2157 return; 2158 } 2159 2160 for (i=0; i < nwrap_main_global->num_backends; i++) { 2161 struct nwrap_backend *b = &nwrap_main_global->backends[i]; 2162 b->ops->nw_endgrent(b); 2163 } 2164} 2165 2166_PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) 2167{ 2168 struct group *grp; 2169 gid_t *groups_tmp; 2170 int count = 1; 2171 const char *name_of_group = NULL; 2172 2173 if (!nwrap_enabled()) { 2174 return real_getgrouplist(user, group, groups, ngroups); 2175 } 2176 2177 NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user)); 2178 2179 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t)); 2180 if (!groups_tmp) { 2181 NWRAP_ERROR(("%s:calloc failed\n",__location__)); 2182 errno = ENOMEM; 2183 return -1; 2184 } 2185 2186 memcpy(groups_tmp, &group, sizeof(gid_t)); 2187 2188 grp = nwrap_getgrgid(group); 2189 if (grp) { 2190 name_of_group = grp->gr_name; 2191 } 2192 2193 nwrap_setgrent(); 2194 while ((grp = nwrap_getgrent()) != NULL) { 2195 int i = 0; 2196 2197 NWRAP_VERBOSE(("%s: inspecting %s for group membership\n", 2198 __location__, grp->gr_name)); 2199 2200 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) { 2201 2202 if ((strcmp(user, grp->gr_mem[i]) == 0) && 2203 (strcmp(name_of_group, grp->gr_name) != 0)) { 2204 2205 NWRAP_DEBUG(("%s: %s is member of %s\n", 2206 __location__, user, grp->gr_name)); 2207 2208 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t)); 2209 if (!groups_tmp) { 2210 NWRAP_ERROR(("%s:calloc failed\n",__location__)); 2211 errno = ENOMEM; 2212 return -1; 2213 } 2214 2215 memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t)); 2216 count++; 2217 } 2218 } 2219 } 2220 2221 nwrap_endgrent(); 2222 2223 NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n", 2224 __location__, user, *ngroups)); 2225 2226 if (*ngroups < count) { 2227 *ngroups = count; 2228 free(groups_tmp); 2229 return -1; 2230 } 2231 2232 *ngroups = count; 2233 memcpy(groups, groups_tmp, count * sizeof(gid_t)); 2234 free(groups_tmp); 2235 2236 return count; 2237} 2238