2 * Copyright (C) Stefan Metzmacher 2007 <metze@samba.org>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
36 #define NSS_WRAPPER_NOT_REPLACE
37 #include "../replace/replace.h"
38 #include "system/passwd.h"
39 #include "system/filesys.h"
41 #else /* _SAMBA_BUILD_ */
43 #error nss_wrapper_only_supported_in_samba_yet
51 /* not all systems have _r functions... */
52 #ifndef HAVE_GETPWNAM_R
53 #define getpwnam_r(name, pwdst, buf, buflen, pwdstp) ENOSYS
55 #ifndef HAVE_GETPWUID_R
56 #define getpwuid_r(uid, pwdst, buf, buflen, pwdstp) ENOSYS
58 #ifndef HAVE_GETPWENT_R
59 #define getpwent_r(pwdst, buf, buflen, pwdstp) ENOSYS
61 #ifndef HAVE_GETGRNAM_R
62 #define getgrnam_r(name, grdst, buf, buflen, grdstp) ENOSYS
64 #ifndef HAVE_GETGRUID_R
65 #define getgrgid_r(uid, grdst, buf, buflen, grdstp) ENOSYS
67 #ifndef HAVE_GETGRENT_R
68 #define getgrent_r(grdst, buf, buflen, grdstp) ENOSYS
71 /* not all systems have getgrouplist */
72 #ifndef HAVE_GETGROUPLIST
73 #define getgrouplist(user, group, groups, ngroups) 0
76 /* LD_PRELOAD doesn't work yet, so REWRITE_CALLS is all we support
82 #define real_getpwnam getpwnam
83 #define real_getpwnam_r getpwnam_r
84 #define real_getpwuid getpwuid
85 #define real_getpwuid_r getpwuid_r
87 #define real_setpwent setpwent
88 #define real_getpwent getpwent
89 #define real_getpwent_r getpwent_r
90 #define real_endpwent endpwent
93 #define real_getgrlst getgrlst
94 #define real_getgrlst_r getgrlst_r
95 #define real_initgroups_dyn initgroups_dyn
97 #define real_initgroups initgroups
98 #define real_getgrouplist getgrouplist
100 #define real_getgrnam getgrnam
101 #define real_getgrnam_r getgrnam_r
102 #define real_getgrgid getgrgid
103 #define real_getgrgid_r getgrgid_r
105 #define real_setgrent setgrent
106 #define real_getgrent getgrent
107 #define real_getgrent_r getgrent_r
108 #define real_endgrent endgrent
114 # define NWRAP_ERROR(args) DEBUG(0, args)
116 # define NWRAP_ERROR(args) printf args
119 #define NWRAP_ERROR(args)
124 # define NWRAP_DEBUG(args) DEBUG(0, args)
126 # define NWRAP_DEBUG(args) printf args
129 #define NWRAP_DEBUG(args)
134 # define NWRAP_VERBOSE(args) DEBUG(0, args)
136 # define NWRAP_VERBOSE(args) printf args
139 #define NWRAP_VERBOSE(args)
148 bool (*parse_line)(struct nwrap_cache *, char *line);
149 void (*unload)(struct nwrap_cache *);
153 struct nwrap_cache *cache;
160 struct nwrap_cache __nwrap_cache_pw;
161 struct nwrap_pw nwrap_pw_global;
163 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line);
164 static void nwrap_pw_unload(struct nwrap_cache *nwrap);
167 struct nwrap_cache *cache;
174 struct nwrap_cache __nwrap_cache_gr;
175 struct nwrap_gr nwrap_gr_global;
177 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line);
178 static void nwrap_gr_unload(struct nwrap_cache *nwrap);
180 static void nwrap_init(void)
182 static bool initialized;
184 if (initialized) return;
187 nwrap_pw_global.cache = &__nwrap_cache_pw;
189 nwrap_pw_global.cache->path = getenv("NSS_WRAPPER_PASSWD");
190 nwrap_pw_global.cache->fd = -1;
191 nwrap_pw_global.cache->private_data = &nwrap_pw_global;
192 nwrap_pw_global.cache->parse_line = nwrap_pw_parse_line;
193 nwrap_pw_global.cache->unload = nwrap_pw_unload;
195 nwrap_gr_global.cache = &__nwrap_cache_gr;
197 nwrap_gr_global.cache->path = getenv("NSS_WRAPPER_GROUP");
198 nwrap_gr_global.cache->fd = -1;
199 nwrap_gr_global.cache->private_data = &nwrap_gr_global;
200 nwrap_gr_global.cache->parse_line = nwrap_gr_parse_line;
201 nwrap_gr_global.cache->unload = nwrap_gr_unload;
204 static bool nwrap_enabled(void)
208 if (!nwrap_pw_global.cache->path) {
211 if (nwrap_pw_global.cache->path[0] == '\0') {
214 if (!nwrap_gr_global.cache->path) {
217 if (nwrap_gr_global.cache->path[0] == '\0') {
224 static bool nwrap_parse_file(struct nwrap_cache *nwrap)
230 if (nwrap->st.st_size == 0) {
231 NWRAP_DEBUG(("%s: size == 0\n",
236 if (nwrap->st.st_size > INT32_MAX) {
237 NWRAP_ERROR(("%s: size[%u] larger than INT32_MAX\n",
238 __location__, (unsigned)nwrap->st.st_size));
242 ret = lseek(nwrap->fd, 0, SEEK_SET);
244 NWRAP_ERROR(("%s: lseek - %d\n",__location__,ret));
248 buf = (uint8_t *)malloc(nwrap->st.st_size + 1);
250 NWRAP_ERROR(("%s: malloc failed\n",__location__));
254 ret = read(nwrap->fd, buf, nwrap->st.st_size);
255 if (ret != nwrap->st.st_size) {
256 NWRAP_ERROR(("%s: read(%u) gave %d\n",
257 __location__, (unsigned)nwrap->st.st_size, ret));
261 buf[nwrap->st.st_size] = '\0';
264 while (nline && nline[0]) {
272 e = strchr(line, '\n');
283 NWRAP_VERBOSE(("%s:'%s'\n",__location__, line));
285 if (strlen(line) == 0) {
289 ok = nwrap->parse_line(nwrap, line);
304 static void nwrap_cache_unload(struct nwrap_cache *nwrap)
306 nwrap->unload(nwrap);
308 if (nwrap->buf) free(nwrap->buf);
313 static void nwrap_cache_reload(struct nwrap_cache *nwrap)
318 bool retried = false;
322 nwrap->fd = open(nwrap->path, O_RDONLY);
324 NWRAP_ERROR(("%s: unable to open '%s' readonly %d:%s\n",
326 nwrap->path, nwrap->fd,
330 NWRAP_VERBOSE(("%s: open '%s'\n", __location__, nwrap->path));
333 ret = fstat(nwrap->fd, &st);
335 NWRAP_ERROR(("%s: fstat(%s) - %d:%s\n",
338 ret, strerror(errno)));
342 if (retried == false && st.st_nlink == 0) {
343 /* maybe someone has replaced the file... */
344 NWRAP_DEBUG(("%s: st_nlink == 0, reopen %s\n",
345 __location__, nwrap->path));
347 memset(&nwrap->st, 0, sizeof(nwrap->st));
353 if (st.st_mtime == nwrap->st.st_mtime) {
354 NWRAP_VERBOSE(("%s: st_mtime[%u] hasn't changed, skip reload\n",
355 __location__, (unsigned)st.st_mtime));
358 NWRAP_DEBUG(("%s: st_mtime has changed [%u] => [%u], start reload\n",
359 __location__, (unsigned)st.st_mtime,
360 (unsigned)nwrap->st.st_mtime));
364 nwrap_cache_unload(nwrap);
366 ok = nwrap_parse_file(nwrap);
368 NWRAP_ERROR(("%s: failed to reload %s\n",
369 __location__, nwrap->path));
370 nwrap_cache_unload(nwrap);
372 NWRAP_DEBUG(("%s: reloaded %s\n",
373 __location__, nwrap->path));
377 * the caller has to call nwrap_unload() on failure
379 static bool nwrap_pw_parse_line(struct nwrap_cache *nwrap, char *line)
381 struct nwrap_pw *nwrap_pw;
388 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
390 list_size = sizeof(*nwrap_pw->list) * (nwrap_pw->num+1);
391 pw = (struct passwd *)realloc(nwrap_pw->list, list_size);
393 NWRAP_ERROR(("%s:realloc(%u) failed\n",
394 __location__, list_size));
399 pw = &nwrap_pw->list[nwrap_pw->num];
406 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
407 __location__, line, c));
415 NWRAP_VERBOSE(("name[%s]\n", pw->pw_name));
420 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
421 __location__, line, c));
429 NWRAP_VERBOSE(("password[%s]\n", pw->pw_passwd));
434 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
435 __location__, line, c));
441 pw->pw_uid = (uid_t)strtoul(c, &e, 10);
443 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
444 __location__, line, c, strerror(errno)));
448 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
449 __location__, line, c, strerror(errno)));
453 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
454 __location__, line, c, strerror(errno)));
459 NWRAP_VERBOSE(("uid[%u]\n", pw->pw_uid));
464 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
465 __location__, line, c));
471 pw->pw_gid = (gid_t)strtoul(c, &e, 10);
473 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
474 __location__, line, c, strerror(errno)));
478 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
479 __location__, line, c, strerror(errno)));
483 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
484 __location__, line, c, strerror(errno)));
489 NWRAP_VERBOSE(("gid[%u]\n", pw->pw_gid));
494 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
495 __location__, line, c));
503 NWRAP_VERBOSE(("gecos[%s]\n", pw->pw_gecos));
508 NWRAP_ERROR(("%s:'%s'\n",__location__,c));
516 NWRAP_VERBOSE(("dir[%s]\n", pw->pw_dir));
520 NWRAP_VERBOSE(("shell[%s]\n", pw->pw_shell));
522 NWRAP_DEBUG(("add user[%s:%s:%u:%u:%s:%s:%s]\n",
523 pw->pw_name, pw->pw_passwd,
524 pw->pw_uid, pw->pw_gid,
525 pw->pw_gecos, pw->pw_dir, pw->pw_shell));
531 static void nwrap_pw_unload(struct nwrap_cache *nwrap)
533 struct nwrap_pw *nwrap_pw;
534 nwrap_pw = (struct nwrap_pw *)nwrap->private_data;
536 if (nwrap_pw->list) free(nwrap_pw->list);
538 nwrap_pw->list = NULL;
543 static int nwrap_pw_copy_r(const struct passwd *src, struct passwd *dst,
544 char *buf, size_t buflen, struct passwd **dstp)
550 first = src->pw_name;
552 last = src->pw_shell;
553 while (*last) last++;
555 ofs = PTR_DIFF(last + 1, first);
561 memcpy(buf, first, ofs);
563 ofs = PTR_DIFF(src->pw_name, first);
564 dst->pw_name = buf + ofs;
565 ofs = PTR_DIFF(src->pw_passwd, first);
566 dst->pw_passwd = buf + ofs;
567 dst->pw_uid = src->pw_uid;
568 dst->pw_gid = src->pw_gid;
569 ofs = PTR_DIFF(src->pw_gecos, first);
570 dst->pw_gecos = buf + ofs;
571 ofs = PTR_DIFF(src->pw_dir, first);
572 dst->pw_dir = buf + ofs;
573 ofs = PTR_DIFF(src->pw_shell, first);
574 dst->pw_shell = buf + ofs;
584 * the caller has to call nwrap_unload() on failure
586 static bool nwrap_gr_parse_line(struct nwrap_cache *nwrap, char *line)
588 struct nwrap_gr *nwrap_gr;
596 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
598 list_size = sizeof(*nwrap_gr->list) * (nwrap_gr->num+1);
599 gr = (struct group *)realloc(nwrap_gr->list, list_size);
601 NWRAP_ERROR(("%s:realloc failed\n",__location__));
606 gr = &nwrap_gr->list[nwrap_gr->num];
613 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
614 __location__, line, c));
622 NWRAP_VERBOSE(("name[%s]\n", gr->gr_name));
627 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
628 __location__, line, c));
636 NWRAP_VERBOSE(("password[%s]\n", gr->gr_passwd));
641 NWRAP_ERROR(("%s:invalid line[%s]: '%s'\n",
642 __location__, line, c));
648 gr->gr_gid = (gid_t)strtoul(c, &e, 10);
650 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
651 __location__, line, c, strerror(errno)));
655 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
656 __location__, line, c, strerror(errno)));
660 NWRAP_ERROR(("%s:invalid line[%s]: '%s' - %s\n",
661 __location__, line, c, strerror(errno)));
666 NWRAP_VERBOSE(("gid[%u]\n", gr->gr_gid));
669 gr->gr_mem = (char **)malloc(sizeof(char *));
671 NWRAP_ERROR(("%s:calloc failed\n",__location__));
674 gr->gr_mem[0] = NULL;
676 for(nummem=0; p; nummem++) {
686 if (strlen(c) == 0) {
690 m_size = sizeof(char *) * (nummem+2);
691 m = (char **)realloc(gr->gr_mem, m_size);
693 NWRAP_ERROR(("%s:realloc(%u) failed\n",
694 __location__, m_size));
698 gr->gr_mem[nummem] = c;
699 gr->gr_mem[nummem+1] = NULL;
701 NWRAP_VERBOSE(("member[%u]: '%s'\n", nummem, gr->gr_mem[nummem]));
704 NWRAP_DEBUG(("add group[%s:%s:%u:] with %u members\n",
705 gr->gr_name, gr->gr_passwd, gr->gr_gid, nummem));
711 static void nwrap_gr_unload(struct nwrap_cache *nwrap)
714 struct nwrap_gr *nwrap_gr;
715 nwrap_gr = (struct nwrap_gr *)nwrap->private_data;
717 if (nwrap_gr->list) {
718 for (i=0; i < nwrap_gr->num; i++) {
719 if (nwrap_gr->list[i].gr_mem) {
720 free(nwrap_gr->list[i].gr_mem);
723 free(nwrap_gr->list);
726 nwrap_gr->list = NULL;
731 static int nwrap_gr_copy_r(const struct group *src, struct group *dst,
732 char *buf, size_t buflen, struct group **dstp)
742 first = src->gr_name;
745 while (*lastm) lastm++;
748 while (*last) last++;
750 ofsb = PTR_DIFF(last + 1, first);
751 ofsm = PTR_DIFF(lastm + 1, src->gr_mem);
753 if ((ofsb + ofsm) > buflen) {
757 memcpy(buf, first, ofsb);
758 memcpy(buf + ofsb, src->gr_mem, ofsm);
760 ofs = PTR_DIFF(src->gr_name, first);
761 dst->gr_name = buf + ofs;
762 ofs = PTR_DIFF(src->gr_passwd, first);
763 dst->gr_passwd = buf + ofs;
764 dst->gr_gid = src->gr_gid;
766 dst->gr_mem = (char **)(buf + ofsb);
767 for (i=0; src->gr_mem[i]; i++) {
768 ofs = PTR_DIFF(src->gr_mem[i], first);
769 dst->gr_mem[i] = buf + ofs;
781 static struct passwd *nwrap_files_getpwnam(const char *name)
785 nwrap_cache_reload(nwrap_pw_global.cache);
787 for (i=0; i<nwrap_pw_global.num; i++) {
788 if (strcmp(nwrap_pw_global.list[i].pw_name, name) == 0) {
789 NWRAP_DEBUG(("%s: user[%s] found\n",
790 __location__, name));
791 return &nwrap_pw_global.list[i];
793 NWRAP_VERBOSE(("%s: user[%s] does not match [%s]\n",
795 nwrap_pw_global.list[i].pw_name));
798 NWRAP_DEBUG(("%s: user[%s] not found\n", __location__, name));
804 _PUBLIC_ struct passwd *nwrap_getpwnam(const char *name)
806 if (!nwrap_enabled()) {
807 return real_getpwnam(name);
810 return nwrap_files_getpwnam(name);
813 static int nwrap_files_getpwnam_r(const char *name, struct passwd *pwdst,
814 char *buf, size_t buflen, struct passwd **pwdstp)
818 pw = nwrap_getpwnam(name);
826 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
829 _PUBLIC_ int nwrap_getpwnam_r(const char *name, struct passwd *pwdst,
830 char *buf, size_t buflen, struct passwd **pwdstp)
832 if (!nwrap_enabled()) {
833 return real_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
836 return nwrap_files_getpwnam_r(name, pwdst, buf, buflen, pwdstp);
839 static struct passwd *nwrap_files_getpwuid(uid_t uid)
843 nwrap_cache_reload(nwrap_pw_global.cache);
845 for (i=0; i<nwrap_pw_global.num; i++) {
846 if (nwrap_pw_global.list[i].pw_uid == uid) {
847 NWRAP_DEBUG(("%s: uid[%u] found\n",
849 return &nwrap_pw_global.list[i];
851 NWRAP_VERBOSE(("%s: uid[%u] does not match [%u]\n",
853 nwrap_pw_global.list[i].pw_uid));
856 NWRAP_DEBUG(("%s: uid[%u] not found\n", __location__, uid));
862 _PUBLIC_ struct passwd *nwrap_getpwuid(uid_t uid)
864 if (!nwrap_enabled()) {
865 return real_getpwuid(uid);
868 return nwrap_files_getpwuid(uid);
871 static int nwrap_files_getpwuid_r(uid_t uid, struct passwd *pwdst,
872 char *buf, size_t buflen, struct passwd **pwdstp)
876 pw = nwrap_getpwuid(uid);
884 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
887 _PUBLIC_ int nwrap_getpwuid_r(uid_t uid, struct passwd *pwdst,
888 char *buf, size_t buflen, struct passwd **pwdstp)
890 if (!nwrap_enabled()) {
891 return real_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
894 return nwrap_files_getpwuid_r(uid, pwdst, buf, buflen, pwdstp);
897 /* user enum functions */
898 static void nwrap_files_setpwent(void)
900 nwrap_pw_global.idx = 0;
903 _PUBLIC_ void nwrap_setpwent(void)
905 if (!nwrap_enabled()) {
909 nwrap_files_setpwent();
912 static struct passwd *nwrap_files_getpwent(void)
916 if (nwrap_pw_global.idx == 0) {
917 nwrap_cache_reload(nwrap_pw_global.cache);
920 if (nwrap_pw_global.idx >= nwrap_pw_global.num) {
925 pw = &nwrap_pw_global.list[nwrap_pw_global.idx++];
927 NWRAP_VERBOSE(("%s: return user[%s] uid[%u]\n",
928 __location__, pw->pw_name, pw->pw_uid));
933 _PUBLIC_ struct passwd *nwrap_getpwent(void)
935 if (!nwrap_enabled()) {
936 return real_getpwent();
939 return nwrap_files_getpwent();
942 static int nwrap_files_getpwent_r(struct passwd *pwdst, char *buf,
943 size_t buflen, struct passwd **pwdstp)
947 pw = nwrap_getpwent();
955 return nwrap_pw_copy_r(pw, pwdst, buf, buflen, pwdstp);
958 _PUBLIC_ int nwrap_getpwent_r(struct passwd *pwdst, char *buf,
959 size_t buflen, struct passwd **pwdstp)
961 if (!nwrap_enabled()) {
962 #ifdef SOLARIS_GETPWENT_R
964 pw = real_getpwent_r(pwdst, buf, buflen);
976 return real_getpwent_r(pwdst, buf, buflen, pwdstp);
980 return nwrap_files_getpwent_r(pwdst, buf, buflen, pwdstp);
983 static void nwrap_files_endpwent(void)
985 nwrap_pw_global.idx = 0;
988 _PUBLIC_ void nwrap_endpwent(void)
990 if (!nwrap_enabled()) {
994 nwrap_files_endpwent();
998 static int nwrap_files_initgroups(const char *user, gid_t group)
1000 /* TODO: maybe we should also fake this... */
1004 _PUBLIC_ int nwrap_initgroups(const char *user, gid_t group)
1006 if (!nwrap_enabled()) {
1007 return real_initgroups(user, group);
1010 return nwrap_files_initgroups(user, group);
1013 /* group functions */
1014 static struct group *nwrap_files_getgrnam(const char *name)
1018 nwrap_cache_reload(nwrap_gr_global.cache);
1020 for (i=0; i<nwrap_gr_global.num; i++) {
1021 if (strcmp(nwrap_gr_global.list[i].gr_name, name) == 0) {
1022 NWRAP_DEBUG(("%s: group[%s] found\n",
1023 __location__, name));
1024 return &nwrap_gr_global.list[i];
1026 NWRAP_VERBOSE(("%s: group[%s] does not match [%s]\n",
1028 nwrap_gr_global.list[i].gr_name));
1031 NWRAP_DEBUG(("%s: group[%s] not found\n", __location__, name));
1037 _PUBLIC_ struct group *nwrap_getgrnam(const char *name)
1039 if (!nwrap_enabled()) {
1040 return real_getgrnam(name);
1043 return nwrap_files_getgrnam(name);
1046 static int nwrap_files_getgrnam_r(const char *name, struct group *grdst,
1047 char *buf, size_t buflen, struct group **grdstp)
1051 gr = nwrap_getgrnam(name);
1059 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1062 _PUBLIC_ int nwrap_getgrnam_r(const char *name, struct group *grdst,
1063 char *buf, size_t buflen, struct group **grdstp)
1065 if (!nwrap_enabled()) {
1066 return real_getgrnam_r(name, grdst, buf, buflen, grdstp);
1069 return nwrap_files_getgrnam_r(name, grdst, buf, buflen, grdstp);
1072 static struct group *nwrap_files_getgrgid(gid_t gid)
1076 nwrap_cache_reload(nwrap_gr_global.cache);
1078 for (i=0; i<nwrap_gr_global.num; i++) {
1079 if (nwrap_gr_global.list[i].gr_gid == gid) {
1080 NWRAP_DEBUG(("%s: gid[%u] found\n",
1081 __location__, gid));
1082 return &nwrap_gr_global.list[i];
1084 NWRAP_VERBOSE(("%s: gid[%u] does not match [%u]\n",
1086 nwrap_gr_global.list[i].gr_gid));
1089 NWRAP_DEBUG(("%s: gid[%u] not found\n", __location__, gid));
1095 _PUBLIC_ struct group *nwrap_getgrgid(gid_t gid)
1097 if (!nwrap_enabled()) {
1098 return real_getgrgid(gid);
1101 return nwrap_files_getgrgid(gid);
1104 static int nwrap_files_getgrgid_r(gid_t gid, struct group *grdst,
1105 char *buf, size_t buflen, struct group **grdstp)
1109 gr = nwrap_getgrgid(gid);
1117 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1122 _PUBLIC_ int nwrap_getgrgid_r(gid_t gid, struct group *grdst,
1123 char *buf, size_t buflen, struct group **grdstp)
1125 if (!nwrap_enabled()) {
1126 return real_getgrgid_r(gid, grdst, buf, buflen, grdstp);
1129 return nwrap_files_getgrgid_r(gid, grdst, buf, buflen, grdstp);
1132 /* group enum functions */
1133 static void nwrap_files_setgrent(void)
1135 nwrap_gr_global.idx = 0;
1138 _PUBLIC_ void nwrap_setgrent(void)
1140 if (!nwrap_enabled()) {
1144 nwrap_files_setgrent();
1147 static struct group *nwrap_files_getgrent(void)
1151 if (nwrap_gr_global.idx == 0) {
1152 nwrap_cache_reload(nwrap_gr_global.cache);
1155 if (nwrap_gr_global.idx >= nwrap_gr_global.num) {
1160 gr = &nwrap_gr_global.list[nwrap_gr_global.idx++];
1162 NWRAP_VERBOSE(("%s: return group[%s] gid[%u]\n",
1163 __location__, gr->gr_name, gr->gr_gid));
1168 _PUBLIC_ struct group *nwrap_getgrent(void)
1170 if (!nwrap_enabled()) {
1171 return real_getgrent();
1174 return nwrap_files_getgrent();
1177 static int nwrap_files_getgrent_r(struct group *grdst, char *buf,
1178 size_t buflen, struct group **grdstp)
1182 gr = nwrap_getgrent();
1190 return nwrap_gr_copy_r(gr, grdst, buf, buflen, grdstp);
1193 _PUBLIC_ int nwrap_getgrent_r(struct group *grdst, char *buf,
1194 size_t buflen, struct group **grdstp)
1196 if (!nwrap_enabled()) {
1197 #ifdef SOLARIS_GETGRENT_R
1199 gr = real_getgrent_r(grdst, buf, buflen);
1211 return real_getgrent_r(grdst, buf, buflen, grdstp);
1215 return nwrap_files_getgrent_r(grdst, buf, buflen, grdstp);
1218 static void nwrap_files_endgrent(void)
1220 nwrap_gr_global.idx = 0;
1223 _PUBLIC_ void nwrap_endgrent(void)
1225 if (!nwrap_enabled()) {
1229 nwrap_files_endgrent();
1232 static int nwrap_files_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
1237 const char *name_of_group = NULL;
1239 NWRAP_DEBUG(("%s: getgrouplist called for %s\n", __location__, user));
1241 groups_tmp = (gid_t *)malloc(count * sizeof(gid_t));
1243 NWRAP_ERROR(("%s:calloc failed\n",__location__));
1248 memcpy(groups_tmp, &group, sizeof(gid_t));
1250 grp = nwrap_getgrgid(group);
1252 name_of_group = grp->gr_name;
1255 nwrap_files_setgrent();
1256 while ((grp = nwrap_files_getgrent()) != NULL) {
1259 NWRAP_VERBOSE(("%s: inspecting %s for group membership\n",
1260 __location__, grp->gr_name));
1262 for (i=0; grp->gr_mem && grp->gr_mem[i] != NULL; i++) {
1264 if ((strcmp(user, grp->gr_mem[i]) == 0) &&
1265 (strcmp(name_of_group, grp->gr_name) != 0)) {
1267 NWRAP_DEBUG(("%s: %s is member of %s\n",
1268 __location__, user, grp->gr_name));
1270 groups_tmp = (gid_t *)realloc(groups_tmp, (count + 1) * sizeof(gid_t));
1272 NWRAP_ERROR(("%s:calloc failed\n",__location__));
1277 memcpy(&groups_tmp[count], &grp->gr_gid, sizeof(gid_t));
1282 nwrap_files_endgrent();
1284 NWRAP_VERBOSE(("%s: %s is member of %d groups: %d\n",
1285 __location__, user, *ngroups));
1287 if (*ngroups < count) {
1294 memcpy(groups, groups_tmp, count * sizeof(gid_t));
1300 _PUBLIC_ int nwrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
1302 if (!nwrap_enabled()) {
1303 return real_getgrouplist(user, group, groups, ngroups);
1306 return nwrap_files_getgrouplist(user, group, groups, ngroups);