root/lib/nss_wrapper/nss_wrapper.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nwrap_init
  2. nwrap_enabled
  3. nwrap_parse_file
  4. nwrap_cache_unload
  5. nwrap_cache_reload
  6. nwrap_pw_parse_line
  7. nwrap_pw_unload
  8. nwrap_pw_copy_r
  9. nwrap_gr_parse_line
  10. nwrap_gr_unload
  11. nwrap_gr_copy_r
  12. nwrap_files_getpwnam
  13. nwrap_getpwnam
  14. nwrap_files_getpwnam_r
  15. nwrap_getpwnam_r
  16. nwrap_files_getpwuid
  17. nwrap_getpwuid
  18. nwrap_files_getpwuid_r
  19. nwrap_getpwuid_r
  20. nwrap_files_setpwent
  21. nwrap_setpwent
  22. nwrap_files_getpwent
  23. nwrap_getpwent
  24. nwrap_files_getpwent_r
  25. nwrap_getpwent_r
  26. nwrap_files_endpwent
  27. nwrap_endpwent
  28. nwrap_files_initgroups
  29. nwrap_initgroups
  30. nwrap_files_getgrnam
  31. nwrap_getgrnam
  32. nwrap_files_getgrnam_r
  33. nwrap_getgrnam_r
  34. nwrap_files_getgrgid
  35. nwrap_getgrgid
  36. nwrap_files_getgrgid_r
  37. nwrap_getgrgid_r
  38. nwrap_files_setgrent
  39. nwrap_setgrent
  40. nwrap_files_getgrent
  41. nwrap_getgrent
  42. nwrap_files_getgrent_r
  43. nwrap_getgrent_r
  44. nwrap_files_endgrent
  45. nwrap_endgrent

   1 /*
   2  * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
   3  *
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * 1. Redistributions of source code must retain the above copyright
  11  *    notice, this list of conditions and the following disclaimer.
  12  *
  13  * 2. Redistributions in binary form must reproduce the above copyright
  14  *    notice, this list of conditions and the following disclaimer in the
  15  *    documentation and/or other materials provided with the distribution.
  16  *
  17  * 3. Neither the name of the author nor the names of its contributors
  18  *    may be used to endorse or promote products derived from this software
  19  *    without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31  * SUCH DAMAGE.
  32  */
  33 
  34 #ifdef _SAMBA_BUILD_
  35 
  36 #define NSS_WRAPPER_NOT_REPLACE
  37 #include "../replace/replace.h"
  38 #include "system/passwd.h"
  39 #include "system/filesys.h"
  40 
  41 #else /* _SAMBA_BUILD_ */
  42 
  43 #error nss_wrapper_only_supported_in_samba_yet
  44 
  45 #endif
  46 
  47 #ifndef _PUBLIC_
  48 #define _PUBLIC_
  49 #endif
  50 
  51 /* not all systems have _r functions... */
  52 #ifndef HAVE_GETPWNAM_R
  53 #define getpwnam_r(name, pwdst, buf, buflen, pwdstp)    ENOSYS
  54 #endif
  55 #ifndef HAVE_GETPWUID_R
  56 #define getpwuid_r(uid, pwdst, buf, buflen, pwdstp)     ENOSYS
  57 #endif
  58 #ifndef HAVE_GETPWENT_R
  59 #define getpwent_r(pwdst, buf, buflen, pwdstp)          ENOSYS
  60 #endif
  61 #ifndef HAVE_GETGRNAM_R
  62 #define getgrnam_r(name, grdst, buf, buflen, grdstp)    ENOSYS
  63 #endif
  64 #ifndef HAVE_GETGRUID_R
  65 #define getgrgid_r(uid, grdst, buf, buflen, grdstp)     ENOSYS
  66 #endif
  67 #ifndef HAVE_GETGRENT_R
  68 #define getgrent_r(grdst, buf, buflen, grdstp)          ENOSYS
  69 #endif
  70 
  71 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
  72  * for now */
  73 #define REWRITE_CALLS
  74 
  75 #ifdef REWRITE_CALLS
  76 
  77 #define real_getpwnam           getpwnam
  78 #define real_getpwnam_r         getpwnam_r
  79 #define real_getpwuid           getpwuid
  80 #define real_getpwuid_r         getpwuid_r
  81 
  82 #define real_setpwent           setpwent
  83 #define real_getpwent           getpwent
  84 #define real_getpwent_r         getpwent_r
  85 #define real_endpwent           endpwent
  86 
  87 /*
  88 #define real_getgrlst           getgrlst
  89 #define real_getgrlst_r         getgrlst_r
  90 #define real_initgroups_dyn     initgroups_dyn
  91 */
  92 #define real_initgroups         initgroups
  93 
  94 #define real_getgrnam           getgrnam
  95 #define real_getgrnam_r         getgrnam_r
  96 #define real_getgrgid           getgrgid
  97 #define real_getgrgid_r         getgrgid_r
  98 
  99 #define real_setgrent           setgrent
 100 #define real_getgrent           getgrent
 101 #define real_getgrent_r         getgrent_r
 102 #define real_endgrent           endgrent
 103 
 104 #endif
 105 
 106 #if 0
 107 # ifdef DEBUG
 108 # define NWRAP_ERROR(args)      DEBUG(0, args)
 109 # else
 110 # define NWRAP_ERROR(args)      printf args
 111 # endif
 112 #else
 113 #define NWRAP_ERROR(args)
 114 #endif
 115 
 116 #if 0
 117 # ifdef DEBUG
 118 # define NWRAP_DEBUG(args)      DEBUG(0, args)
 119 # else
 120 # define NWRAP_DEBUG(args)      printf args
 121 # endif
 122 #else
 123 #define NWRAP_DEBUG(args)
 124 #endif
 125 
 126 #if 0
 127 # ifdef DEBUG
 128 # define NWRAP_VERBOSE(args)    DEBUG(0, args)
 129 # else
 130 # define NWRAP_VERBOSE(args)    printf args
 131 # endif
 132 #else
 133 #define NWRAP_VERBOSE(args)
 134 #endif
 135 
 136 struct nwrap_cache {
 137         const char *path;
 138         int fd;
 139         struct stat st;
 140         uint8_t *buf;
 141         void *private_data;
 142         bool (*parse_line)(struct nwrap_cache *, char *line);
 143         void (*unload)(struct nwrap_cache *);
 144 };
 145 
 146 struct nwrap_pw {
 147         struct nwrap_cache *cache;
 148 
 149         struct passwd *list;
 150         int num;
 151         int idx;
 152 };
 153 
 154 struct nwrap_cache __nwrap_cache_pw;
 155 struct nwrap_pw nwrap_pw_global;
 156 
 157 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
 158 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
 159 
 160 struct nwrap_gr {
 161         struct nwrap_cache *cache;
 162 
 163         struct group *list;
 164         int num;
 165         int idx;
 166 };
 167 
 168 struct nwrap_cache __nwrap_cache_gr;
 169 struct nwrap_gr nwrap_gr_global;
 170 
 171 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
 172 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
 173 
 174 static void nwrap_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 175 {
 176         static bool initialized;
 177 
 178         if (initialized) return;
 179         initialized = true;
 180 
 181         nwrap_pw_global.cache = &__nwrap_cache_pw;
 182 
 183         nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
 184         nwrap_pw_global.cache->fd = -1;
 185         nwrap_pw_global.cache->private_data = &nwrap_pw_global;
 186         nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
 187         nwrap_pw_global.cache->unload = nwrap_pw_unload;
 188 
 189         nwrap_gr_global.cache = &__nwrap_cache_gr;
 190 
 191         nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
 192         nwrap_gr_global.cache->fd = -1;
 193         nwrap_gr_global.cache->private_data = &nwrap_gr_global;
 194         nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
 195         nwrap_gr_global.cache->unload = nwrap_gr_unload;
 196 }
 197 
 198 static bool nwrap_enabled(void)
     /* [<][>][^][v][top][bottom][index][help] */
 199 {
 200         nwrap_init();
 201 
 202         if (!nwrap_pw_global.cache->path) {
 203                 return false;
 204         }
 205         if (nwrap_pw_global.cache->path[0] == '\0') {
 206                 return false;
 207         }
 208         if (!nwrap_gr_global.cache->path) {
 209                 return false;
 210         }
 211         if (nwrap_gr_global.cache->path[0] == '\0') {
 212                 return false;
 213         }
 214 
 215         return true;
 216 }
 217 
 218 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
     /* [<][>][^][v][top][bottom][index][help] */
 219 {
 220         int ret;
 221         uint8_t *buf = NULL;
 222         char *nline;
 223 
 224         if (nwrap->st.st_size == 0) {
 225                 NWRAP_DEBUG(("%s: size == 0\n",
 226                              __location__));
 227                 goto done;
 228         }
 229 
 230         if (nwrap->st.st_size > INT32_MAX) {
 231                 NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n",
 232                              __location__, (unsigned)nwrap->st.st_size));
 233                 goto failed;
 234         }
 235 
 236         ret = lseek(nwrap->fd, 0, SEEK_SET);
 237         if (ret != 0) {
 238                 NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret));
 239                 goto failed;
 240         }
 241 
 242         buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
 243         if (!buf) {
 244                 NWRAP_ERROR(("%s: malloc failed\n",__location__));
 245                 goto failed;
 246         }
 247 
 248         ret = read(nwrap->fd, buf, nwrap->st.st_size);
 249         if (ret != nwrap->st.st_size) {
 250                 NWRAP_ERROR(("%s: read(%u) gave %d\n",
 251                              __location__, (unsigned)nwrap->st.st_size, ret));
 252                 goto failed;
 253         }
 254 
 255         buf[nwrap->st.st_size] = '\0';
 256 
 257         nline = (char *)buf;
 258         while (nline && nline[0]) {
 259                 char *line;
 260                 char *e;
 261                 bool ok;
 262 
 263                 line = nline;
 264                 nline = NULL;
 265 
 266                 e = strchr(line, '\n');
 267                 if (e) {
 268                         e[0] = '\0';
 269                         e++;
 270                         if (e[0] == '\r') {
 271                                 e[0] = '\0';
 272                                 e++;
 273                         }
 274                         nline = e;
 275                 }
 276 
 277                 NWRAP_VERBOSE(("%s:'%s'\n",__location__, line));
 278 
 279                 if (strlen(line) == 0) {
 280                         continue;
 281                 }
 282 
 283                 ok = nwrap->parse_line(nwrap, line);
 284                 if (!ok) {
 285                         goto failed;
 286                 }
 287         }
 288 
 289 done:
 290         nwrap->buf = buf;
 291         return true;
 292 
 293 failed:
 294         if (buf) free(buf);
 295         return false;
 296 }
 297 
 298 static void nwrap_cache_unload(struct nwrap_cache *nwrap)
     /* [<][>][^][v][top][bottom][index][help] */
 299 {
 300         nwrap->unload(nwrap);
 301 
 302         if (nwrap->buf) free(nwrap->buf);
 303 
 304         nwrap->buf = NULL;
 305 }
 306 
 307 static void nwrap_cache_reload(struct nwrap_cache *nwrap)
     /* [<][>][^][v][top][bottom][index][help] */
 308 {
 309         struct stat st;
 310         int ret;
 311         bool ok;
 312         bool retried = false;
 313 
 314 reopen:
 315         if (nwrap->fd < 0) {
 316                 nwrap->fd = open(nwrap->path, O_RDONLY);
 317                 if (nwrap->fd < 0) {
 318                         NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n",
 319                                      __location__,
 320                                      nwrap->path, nwrap->fd,
 321                                      strerror(errno)));
 322                         return;
 323                 }
 324                 NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path));
 325         }
 326 
 327         ret = fstat(nwrap->fd, &st);
 328         if (ret != 0) {
 329                 NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n",
 330                              __location__,
 331                              nwrap->path,
 332                              ret, strerror(errno)));
 333                 return;
 334         }
 335 
 336         if (retried == false && st.st_nlink == 0) {
 337                 /* maybe someone has replaced the file... */
 338                 NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n",
 339                              __location__, nwrap->path));
 340                 retried = true;
 341                 memset(&nwrap->st, 0, sizeof(nwrap->st));
 342                 close(nwrap->fd);
 343                 nwrap->fd = -1;
 344                 goto reopen;
 345         }
 346 
 347         if (st.st_mtime == nwrap->st.st_mtime) {
 348                 NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n",
 349                                __location__, (unsigned)st.st_mtime));
 350                 return;
 351         }
 352         NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n",
 353                      __location__, (unsigned)st.st_mtime,
 354                      (unsigned)nwrap->st.st_mtime));
 355 
 356         nwrap->st = st;
 357 
 358         nwrap_cache_unload(nwrap);
 359 
 360         ok = nwrap_parse_file(nwrap);
 361         if (!ok) {
 362                 NWRAP_ERROR(("%s: failed to reload %s\n",
 363                              __location__, nwrap->path));
 364                 nwrap_cache_unload(nwrap);
 365         }
 366         NWRAP_DEBUG(("%s: reloaded %s\n",
 367                      __location__, nwrap->path));
 368 }
 369 
 370 /*
 371  * the caller has to call nwrap_unload() on failure
 372  */
 373 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
     /* [<][>][^][v][top][bottom][index][help] */
 374 {
 375         struct nwrap_pw *nwrap_pw;
 376         char *c;
 377         char *p;
 378         char *e;
 379         struct passwd *pw;
 380         size_t list_size;
 381 
 382         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
 383 
 384         list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
 385         pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
 386         if (!pw) {
 387                 NWRAP_ERROR(("%s:realloc(%u) failed\n",
 388                              __location__, list_size));
 389                 return false;
 390         }
 391         nwrap_pw->list = pw;
 392 
 393         pw = &nwrap_pw->list[nwrap_pw->num];
 394 
 395         c = line;
 396 
 397         /* name */
 398         p = strchr(c, ':');
 399         if (!p) {
 400                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 401                              __location__, line, c));
 402                 return false;
 403         }
 404         *p = '\0';
 405         p++;
 406         pw->pw_name = c;
 407         c = p;
 408 
 409         NWRAP_VERBOSE(("name[%s]\n", pw->pw_name));
 410 
 411         /* password */
 412         p = strchr(c, ':');
 413         if (!p) {
 414                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 415                              __location__, line, c));
 416                 return false;
 417         }
 418         *p = '\0';
 419         p++;
 420         pw->pw_passwd = c;
 421         c = p;
 422 
 423         NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd));
 424 
 425         /* uid */
 426         p = strchr(c, ':');
 427         if (!p) {
 428                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 429                              __location__, line, c));
 430                 return false;
 431         }
 432         *p = '\0';
 433         p++;
 434         e = NULL;
 435         pw->pw_uid = (uid_t)strtoul(c, &e, 10);
 436         if (c == e) {
 437                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 438                              __location__, line, c, strerror(errno)));
 439                 return false;
 440         }
 441         if (e == NULL) {
 442                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 443                              __location__, line, c, strerror(errno)));
 444                 return false;
 445         }
 446         if (e[0] != '\0') {
 447                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 448                              __location__, line, c, strerror(errno)));
 449                 return false;
 450         }
 451         c = p;
 452 
 453         NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid));
 454 
 455         /* gid */
 456         p = strchr(c, ':');
 457         if (!p) {
 458                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 459                              __location__, line, c));
 460                 return false;
 461         }
 462         *p = '\0';
 463         p++;
 464         e = NULL;
 465         pw->pw_gid = (gid_t)strtoul(c, &e, 10);
 466         if (c == e) {
 467                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 468                              __location__, line, c, strerror(errno)));
 469                 return false;
 470         }
 471         if (e == NULL) {
 472                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 473                              __location__, line, c, strerror(errno)));
 474                 return false;
 475         }
 476         if (e[0] != '\0') {
 477                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 478                              __location__, line, c, strerror(errno)));
 479                 return false;
 480         }
 481         c = p;
 482 
 483         NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid));
 484 
 485         /* gecos */
 486         p = strchr(c, ':');
 487         if (!p) {
 488                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 489                              __location__, line, c));
 490                 return false;
 491         }
 492         *p = '\0';
 493         p++;
 494         pw->pw_gecos = c;
 495         c = p;
 496 
 497         NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos));
 498 
 499         /* dir */
 500         p = strchr(c, ':');
 501         if (!p) {
 502                 NWRAP_ERROR(("%s:'%s'\n",__location__,c));
 503                 return false;
 504         }
 505         *p = '\0';
 506         p++;
 507         pw->pw_dir = c;
 508         c = p;
 509 
 510         NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir));
 511 
 512         /* shell */
 513         pw->pw_shell = c;
 514         NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell));
 515 
 516         NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n",
 517                      pw->pw_name, pw->pw_passwd,
 518                      pw->pw_uid, pw->pw_gid,
 519                      pw->pw_gecos, pw->pw_dir, pw->pw_shell));
 520 
 521         nwrap_pw->num++;
 522         return true;
 523 }
 524 
 525 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
     /* [<][>][^][v][top][bottom][index][help] */
 526 {
 527         struct nwrap_pw *nwrap_pw;
 528         nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
 529 
 530         if (nwrap_pw->list) free(nwrap_pw->list);
 531 
 532         nwrap_pw->list = NULL;
 533         nwrap_pw->num = 0;
 534         nwrap_pw->idx = 0;
 535 }
 536 
 537 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
     /* [<][>][^][v][top][bottom][index][help] */
 538                            char *buf, size_t buflen, struct passwd **dstp)
 539 {
 540         char *first;
 541         char *last;
 542         off_t ofs;
 543 
 544         first = src->pw_name;
 545 
 546         last = src->pw_shell;
 547         while (*last) last++;
 548 
 549         ofs = PTR_DIFF(last + 1, first);
 550 
 551         if (ofs > buflen) {
 552                 return ERANGE;
 553         }
 554 
 555         memcpy(buf, first, ofs);
 556 
 557         ofs = PTR_DIFF(src->pw_name, first);
 558         dst->pw_name = buf + ofs;
 559         ofs = PTR_DIFF(src->pw_passwd, first);
 560         dst->pw_passwd = buf + ofs;
 561         dst->pw_uid = src->pw_uid;
 562         dst->pw_gid = src->pw_gid;
 563         ofs = PTR_DIFF(src->pw_gecos, first);
 564         dst->pw_gecos = buf + ofs;
 565         ofs = PTR_DIFF(src->pw_dir, first);
 566         dst->pw_dir = buf + ofs;
 567         ofs = PTR_DIFF(src->pw_shell, first);
 568         dst->pw_shell = buf + ofs;
 569 
 570         if (dstp) {
 571                 *dstp = dst;
 572         }
 573 
 574         return 0;
 575 }
 576 
 577 /*
 578  * the caller has to call nwrap_unload() on failure
 579  */
 580 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
     /* [<][>][^][v][top][bottom][index][help] */
 581 {
 582         struct nwrap_gr *nwrap_gr;
 583         char *c;
 584         char *p;
 585         char *e;
 586         struct group *gr;
 587         size_t list_size;
 588         unsigned nummem;
 589 
 590         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
 591 
 592         list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
 593         gr = (struct group *)realloc(nwrap_gr->list, list_size);
 594         if (!gr) {
 595                 NWRAP_ERROR(("%s:realloc failed\n",__location__));
 596                 return false;
 597         }
 598         nwrap_gr->list = gr;
 599 
 600         gr = &nwrap_gr->list[nwrap_gr->num];
 601 
 602         c = line;
 603 
 604         /* name */
 605         p = strchr(c, ':');
 606         if (!p) {
 607                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 608                              __location__, line, c));
 609                 return false;
 610         }
 611         *p = '\0';
 612         p++;
 613         gr->gr_name = c;
 614         c = p;
 615 
 616         NWRAP_VERBOSE(("name[%s]\n", gr->gr_name));
 617 
 618         /* password */
 619         p = strchr(c, ':');
 620         if (!p) {
 621                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 622                              __location__, line, c));
 623                 return false;
 624         }
 625         *p = '\0';
 626         p++;
 627         gr->gr_passwd = c;
 628         c = p;
 629 
 630         NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd));
 631 
 632         /* gid */
 633         p = strchr(c, ':');
 634         if (!p) {
 635                 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
 636                              __location__, line, c));
 637                 return false;
 638         }
 639         *p = '\0';
 640         p++;
 641         e = NULL;
 642         gr->gr_gid = (gid_t)strtoul(c, &e, 10);
 643         if (c == e) {
 644                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 645                              __location__, line, c, strerror(errno)));
 646                 return false;
 647         }
 648         if (e == NULL) {
 649                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 650                              __location__, line, c, strerror(errno)));
 651                 return false;
 652         }
 653         if (e[0] != '\0') {
 654                 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
 655                              __location__, line, c, strerror(errno)));
 656                 return false;
 657         }
 658         c = p;
 659 
 660         NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid));
 661 
 662         /* members */
 663         gr->gr_mem = (char **)malloc(sizeof(char *));
 664         if (!gr->gr_mem) {
 665                 NWRAP_ERROR(("%s:calloc failed\n",__location__));
 666                 return false;
 667         }
 668         gr->gr_mem[0] = NULL;
 669 
 670         for(nummem=0; p; nummem++) {
 671                 char **m;
 672                 size_t m_size;
 673                 c = p;
 674                 p = strchr(c, ',');
 675                 if (p) {
 676                         *p = '\0';
 677                         p++;
 678                 }
 679 
 680                 if (strlen(c) == 0) {
 681                         break;
 682                 }
 683 
 684                 m_size = sizeof(char *) * (nummem+2);
 685                 m = (char **)realloc(gr->gr_mem, m_size);
 686                 if (!m) {
 687                         NWRAP_ERROR(("%s:realloc(%u) failed\n",
 688                                       __location__, m_size));
 689                         return false;
 690                 }
 691                 gr->gr_mem = m;
 692                 gr->gr_mem[nummem] = c;
 693                 gr->gr_mem[nummem+1] = NULL;
 694 
 695                 NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem]));
 696         }
 697 
 698         NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n",
 699                      gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem));
 700 
 701         nwrap_gr->num++;
 702         return true;
 703 }
 704 
 705 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
     /* [<][>][^][v][top][bottom][index][help] */
 706 {
 707         int i;
 708         struct nwrap_gr *nwrap_gr;
 709         nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
 710 
 711         if (nwrap_gr->list) {
 712                 for (i=0; i < nwrap_gr->num; i++) {
 713                         if (nwrap_gr->list[i].gr_mem) {
 714                                 free(nwrap_gr->list[i].gr_mem);
 715                         }
 716                 }
 717                 free(nwrap_gr->list);
 718         }
 719 
 720         nwrap_gr->list = NULL;
 721         nwrap_gr->num = 0;
 722         nwrap_gr->idx = 0;
 723 }
 724 
 725 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
     /* [<][>][^][v][top][bottom][index][help] */
 726                            char *buf, size_t buflen, struct group **dstp)
 727 {
 728         char *first;
 729         char **lastm;
 730         char *last;
 731         off_t ofsb;
 732         off_t ofsm;
 733         off_t ofs;
 734         unsigned i;
 735 
 736         first = src->gr_name;
 737 
 738         lastm = src->gr_mem;
 739         while (*lastm) lastm++;
 740 
 741         last = *lastm;
 742         while (*last) last++;
 743 
 744         ofsb = PTR_DIFF(last + 1, first);
 745         ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
 746 
 747         if ((ofsb + ofsm) > buflen) {
 748                 return ERANGE;
 749         }
 750 
 751         memcpy(buf, first, ofsb);
 752         memcpy(buf + ofsb, src->gr_mem, ofsm);
 753 
 754         ofs = PTR_DIFF(src->gr_name, first);
 755         dst->gr_name = buf + ofs;
 756         ofs = PTR_DIFF(src->gr_passwd, first);
 757         dst->gr_passwd = buf + ofs;
 758         dst->gr_gid = src->gr_gid;
 759 
 760         dst->gr_mem = (char **)(buf + ofsb);
 761         for (i=0; src->gr_mem[i]; i++) {
 762                 ofs = PTR_DIFF(src->gr_mem[i], first);
 763                 dst->gr_mem[i] = buf + ofs;
 764         }
 765 
 766         if (dstp) {
 767                 *dstp = dst;
 768         }
 769 
 770         return 0;
 771 }
 772 
 773 /* user functions */
 774 
 775 static struct passwd *nwrap_files_getpwnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 776 {
 777         int i;
 778 
 779         nwrap_cache_reload(nwrap_pw_global.cache);
 780 
 781         for (i=0; i<nwrap_pw_global.num; i++) {
 782                 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
 783                         NWRAP_DEBUG(("%s: user[%s] found\n",
 784                                      __location__, name));
 785                         return &nwrap_pw_global.list[i];
 786                 }
 787                 NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n",
 788                                __location__, name,
 789                                nwrap_pw_global.list[i].pw_name));
 790         }
 791 
 792         NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name));
 793 
 794         errno = ENOENT;
 795         return NULL;
 796 }
 797 
 798 _PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
 799 {
 800         if (!nwrap_enabled()) {
 801                 return real_getpwnam(name);
 802         }
 803 
 804         return nwrap_files_getpwnam(name);
 805 }
 806 
 807 static int nwrap_files_getpwnam_r(const char *name, struct passwd *pwdst,
     /* [<][>][^][v][top][bottom][index][help] */
 808                                   char *buf, size_t buflen, struct passwd **pwdstp)
 809 {
 810         struct passwd *pw;
 811 
 812         pw = nwrap_getpwnam(name);
 813         if (!pw) {
 814                 if (errno == 0) {
 815                         return ENOENT;
 816                 }
 817                 return errno;
 818         }
 819 
 820         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 821 }
 822 
 823 _PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
     /* [<][>][^][v][top][bottom][index][help] */
 824                               char *buf, size_t buflen, struct passwd **pwdstp)
 825 {
 826         if (!nwrap_enabled()) {
 827                 return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
 828         }
 829 
 830         return nwrap_files_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
 831 }
 832 
 833 static struct passwd *nwrap_files_getpwuid(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
 834 {
 835         int i;
 836 
 837         nwrap_cache_reload(nwrap_pw_global.cache);
 838 
 839         for (i=0; i<nwrap_pw_global.num; i++) {
 840                 if (nwrap_pw_global.list[i].pw_uid == uid) {
 841                         NWRAP_DEBUG(("%s: uid[%u] found\n",
 842                                      __location__, uid));
 843                         return &nwrap_pw_global.list[i];
 844                 }
 845                 NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n",
 846                                __location__, uid,
 847                                nwrap_pw_global.list[i].pw_uid));
 848         }
 849 
 850         NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid));
 851 
 852         errno = ENOENT;
 853         return NULL;
 854 }
 855 
 856 _PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
     /* [<][>][^][v][top][bottom][index][help] */
 857 {
 858         if (!nwrap_enabled()) {
 859                 return real_getpwuid(uid);
 860         }
 861 
 862         return nwrap_files_getpwuid(uid);
 863 }
 864 
 865 static int nwrap_files_getpwuid_r(uid_t uid, struct passwd *pwdst,
     /* [<][>][^][v][top][bottom][index][help] */
 866                                   char *buf, size_t buflen, struct passwd **pwdstp)
 867 {
 868         struct passwd *pw;
 869 
 870         pw = nwrap_getpwuid(uid);
 871         if (!pw) {
 872                 if (errno == 0) {
 873                         return ENOENT;
 874                 }
 875                 return errno;
 876         }
 877 
 878         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 879 }
 880 
 881 _PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
     /* [<][>][^][v][top][bottom][index][help] */
 882                               char *buf, size_t buflen, struct passwd **pwdstp)
 883 {
 884         if (!nwrap_enabled()) {
 885                 return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
 886         }
 887 
 888         return nwrap_files_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
 889 }
 890 
 891 /* user enum functions */
 892 static void nwrap_files_setpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 893 {
 894         nwrap_pw_global.idx = 0;
 895 }
 896 
 897 _PUBLIC_ void nwrap_setpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 898 {
 899         if (!nwrap_enabled()) {
 900                 real_setpwent();
 901         }
 902 
 903         nwrap_files_setpwent();
 904 }
 905 
 906 static struct passwd *nwrap_files_getpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 907 {
 908         struct passwd *pw;
 909 
 910         if (nwrap_pw_global.idx == 0) {
 911                 nwrap_cache_reload(nwrap_pw_global.cache);
 912         }
 913 
 914         if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
 915                 errno = ENOENT;
 916                 return NULL;
 917         }
 918 
 919         pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
 920 
 921         NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n",
 922                        __location__, pw->pw_name, pw->pw_uid));
 923 
 924         return pw;
 925 }
 926 
 927 _PUBLIC_ struct passwd *nwrap_getpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 928 {
 929         if (!nwrap_enabled()) {
 930                 return real_getpwent();
 931         }
 932 
 933         return nwrap_files_getpwent();
 934 }
 935 
 936 static int nwrap_files_getpwent_r(struct passwd *pwdst, char *buf,
     /* [<][>][^][v][top][bottom][index][help] */
 937                                   size_t buflen, struct passwd **pwdstp)
 938 {
 939         struct passwd *pw;
 940 
 941         pw = nwrap_getpwent();
 942         if (!pw) {
 943                 if (errno == 0) {
 944                         return ENOENT;
 945                 }
 946                 return errno;
 947         }
 948 
 949         return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
 950 }
 951 
 952 _PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
     /* [<][>][^][v][top][bottom][index][help] */
 953                               size_t buflen, struct passwd **pwdstp)
 954 {
 955         if (!nwrap_enabled()) {
 956 #ifdef SOLARIS_GETPWENT_R
 957                 struct passwd *pw;
 958                 pw = real_getpwent_r(pwdst, buf, buflen);
 959                 if (!pw) {
 960                         if (errno == 0) {
 961                                 return ENOENT;
 962                         }
 963                         return errno;
 964                 }
 965                 if (pwdstp) {
 966                         *pwdstp = pw;
 967                 }
 968                 return 0;
 969 #else
 970                 return real_getpwent_r(pwdst, buf, buflen, pwdstp);
 971 #endif
 972         }
 973 
 974         return nwrap_files_getpwent_r(pwdst, buf, buflen, pwdstp);
 975 }
 976 
 977 static void nwrap_files_endpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 978 {
 979         nwrap_pw_global.idx = 0;
 980 }
 981 
 982 _PUBLIC_ void nwrap_endpwent(void)
     /* [<][>][^][v][top][bottom][index][help] */
 983 {
 984         if (!nwrap_enabled()) {
 985                 real_endpwent();
 986         }
 987 
 988         nwrap_files_endpwent();
 989 }
 990 
 991 /* misc functions */
 992 static int nwrap_files_initgroups(const char *user, gid_t group)
     /* [<][>][^][v][top][bottom][index][help] */
 993 {
 994         /* TODO: maybe we should also fake this... */
 995         return EPERM;
 996 }
 997 
 998 _PUBLIC_ int nwrap_initgroups(const char *user, gid_t group)
     /* [<][>][^][v][top][bottom][index][help] */
 999 {
1000         if (!nwrap_enabled()) {
1001                 return real_initgroups(user, group);
1002         }
1003 
1004         return nwrap_files_initgroups(user, group);
1005 }
1006 
1007 /* group functions */
1008 static struct group *nwrap_files_getgrnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1009 {
1010         int i;
1011 
1012         nwrap_cache_reload(nwrap_gr_global.cache);
1013 
1014         for (i=0; i<nwrap_gr_global.num; i++) {
1015                 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
1016                         NWRAP_DEBUG(("%s: group[%s] found\n",
1017                                      __location__, name));
1018                         return &nwrap_gr_global.list[i];
1019                 }
1020                 NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n",
1021                                __location__, name,
1022                                nwrap_gr_global.list[i].gr_name));
1023         }
1024 
1025         NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name));
1026 
1027         errno = ENOENT;
1028         return NULL;
1029 }
1030 
1031 _PUBLIC_ struct group *nwrap_getgrnam(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
1032 {
1033         if (!nwrap_enabled()) {
1034                 return real_getgrnam(name);
1035         }
1036 
1037         return nwrap_files_getgrnam(name);
1038 }
1039 
1040 static int nwrap_files_getgrnam_r(const char *name, struct group *grdst,
     /* [<][>][^][v][top][bottom][index][help] */
1041                                   char *buf, size_t buflen, struct group **grdstp)
1042 {
1043         struct group *gr;
1044 
1045         gr = nwrap_getgrnam(name);
1046         if (!gr) {
1047                 if (errno == 0) {
1048                         return ENOENT;
1049                 }
1050                 return errno;
1051         }
1052 
1053         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1054 }
1055 
1056 _PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
     /* [<][>][^][v][top][bottom][index][help] */
1057                               char *buf, size_t buflen, struct group **grdstp)
1058 {
1059         if (!nwrap_enabled()) {
1060                 return real_getgrnam_r(name, grdst, buf, buflen, grdstp);
1061         }
1062 
1063         return nwrap_files_getgrnam_r(name, grdst, buf, buflen, grdstp);
1064 }
1065 
1066 static struct group *nwrap_files_getgrgid(gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1067 {
1068         int i;
1069 
1070         nwrap_cache_reload(nwrap_gr_global.cache);
1071 
1072         for (i=0; i<nwrap_gr_global.num; i++) {
1073                 if (nwrap_gr_global.list[i].gr_gid == gid) {
1074                         NWRAP_DEBUG(("%s: gid[%u] found\n",
1075                                      __location__, gid));
1076                         return &nwrap_gr_global.list[i];
1077                 }
1078                 NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n",
1079                                __location__, gid,
1080                                nwrap_gr_global.list[i].gr_gid));
1081         }
1082 
1083         NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid));
1084 
1085         errno = ENOENT;
1086         return NULL;
1087 }
1088 
1089 _PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
     /* [<][>][^][v][top][bottom][index][help] */
1090 {
1091         if (!nwrap_enabled()) {
1092                 return real_getgrgid(gid);
1093         }
1094 
1095         return nwrap_files_getgrgid(gid);
1096 }
1097 
1098 static int nwrap_files_getgrgid_r(gid_t gid, struct group *grdst,
     /* [<][>][^][v][top][bottom][index][help] */
1099                                   char *buf, size_t buflen, struct group **grdstp)
1100 {
1101         struct group *gr;
1102 
1103         gr = nwrap_getgrgid(gid);
1104         if (!gr) {
1105                 if (errno == 0) {
1106                         return ENOENT;
1107                 }
1108                 return errno;
1109         }
1110 
1111         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1112 
1113         return ENOENT;
1114 }
1115 
1116 _PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
     /* [<][>][^][v][top][bottom][index][help] */
1117                               char *buf, size_t buflen, struct group **grdstp)
1118 {
1119         if (!nwrap_enabled()) {
1120                 return real_getgrgid_r(gid, grdst, buf, buflen, grdstp);
1121         }
1122 
1123         return nwrap_files_getgrgid_r(gid, grdst, buf, buflen, grdstp);
1124 }
1125 
1126 /* group enum functions */
1127 static void nwrap_files_setgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1128 {
1129         nwrap_gr_global.idx = 0;
1130 }
1131 
1132 _PUBLIC_ void nwrap_setgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1133 {
1134         if (!nwrap_enabled()) {
1135                 real_setgrent();
1136         }
1137 
1138         nwrap_files_setgrent();
1139 }
1140 
1141 static struct group *nwrap_files_getgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1142 {
1143         struct group *gr;
1144 
1145         if (nwrap_gr_global.idx == 0) {
1146                 nwrap_cache_reload(nwrap_gr_global.cache);
1147         }
1148 
1149         if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
1150                 errno = ENOENT;
1151                 return NULL;
1152         }
1153 
1154         gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
1155 
1156         NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n",
1157                        __location__, gr->gr_name, gr->gr_gid));
1158 
1159         return gr;
1160 }
1161 
1162 _PUBLIC_ struct group *nwrap_getgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1163 {
1164         if (!nwrap_enabled()) {
1165                 return real_getgrent();
1166         }
1167 
1168         return nwrap_files_getgrent();
1169 }
1170 
1171 static int nwrap_files_getgrent_r(struct group *grdst, char *buf,
     /* [<][>][^][v][top][bottom][index][help] */
1172                                   size_t buflen, struct group **grdstp)
1173 {
1174         struct group *gr;
1175 
1176         gr = nwrap_getgrent();
1177         if (!gr) {
1178                 if (errno == 0) {
1179                         return ENOENT;
1180                 }
1181                 return errno;
1182         }
1183 
1184         return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1185 }
1186 
1187 _PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
     /* [<][>][^][v][top][bottom][index][help] */
1188                               size_t buflen, struct group **grdstp)
1189 {
1190         if (!nwrap_enabled()) {
1191 #ifdef SOLARIS_GETGRENT_R
1192                 struct group *gr;
1193                 gr = real_getgrent_r(grdst, buf, buflen);
1194                 if (!gr) {
1195                         if (errno == 0) {
1196                                 return ENOENT;
1197                         }
1198                         return errno;
1199                 }
1200                 if (grdstp) {
1201                         *grdstp = gr;
1202                 }
1203                 return 0;
1204 #else
1205                 return real_getgrent_r(grdst, buf, buflen, grdstp);
1206 #endif
1207         }
1208 
1209         return nwrap_files_getgrent_r(grdst, buf, buflen, grdstp);
1210 }
1211 
1212 static void nwrap_files_endgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1213 {
1214         nwrap_gr_global.idx = 0;
1215 }
1216 
1217 _PUBLIC_ void nwrap_endgrent(void)
     /* [<][>][^][v][top][bottom][index][help] */
1218 {
1219         if (!nwrap_enabled()) {
1220                 real_endgrent();
1221         }
1222 
1223         nwrap_files_endgrent();
1224 }

/* [<][>][^][v][top][bottom][index][help] */