2 * SPDX-License-Identifier: ISC
4 * Copyright (c) 2005, 2008, 2010-2015
5 * Todd C. Miller <Todd.Miller@sudo.ws>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * This is an open source non-commercial project. Dear PVS-Studio, please check it.
22 * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
26 * Trivial replacements for the libc get{gr,pw}{uid,nam}() routines
27 * for use by testsudoers in the sudo test harness.
28 * We need our own since many platforms don't provide set{pw,gr}file().
33 #include <sys/types.h>
38 #endif /* HAVE_STRING_H */
41 #endif /* HAVE_STRINGS_H */
47 #include "tsgetgrpw.h"
54 # define UID_MAX 0xffffffffU
58 # define GID_MAX UID_MAX
62 static const char *pwfile = "/etc/passwd";
63 static int pw_stayopen;
66 static const char *grfile = "/etc/group";
67 static int gr_stayopen;
69 void setgrfile(const char *);
72 struct group *getgrent(void);
73 struct group *getgrnam(const char *);
74 struct group *getgrgid(gid_t);
76 void setpwfile(const char *);
79 struct passwd *getpwent(void);
80 struct passwd *getpwnam(const char *);
81 struct passwd *getpwuid(uid_t);
84 setpwfile(const char *file)
95 pwf = fopen(pwfile, "r");
97 (void)fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
117 static struct passwd pw;
118 static char pwbuf[LINE_MAX];
125 if ((colon = fgets(pwbuf, sizeof(pwbuf), pwf)) == NULL)
128 memset(&pw, 0, sizeof(pw));
129 if ((colon = strchr(cp = colon, ':')) == NULL)
133 if ((colon = strchr(cp = colon, ':')) == NULL)
137 if ((colon = strchr(cp = colon, ':')) == NULL)
140 id = sudo_strtoid(cp, NULL, NULL, &errstr);
143 pw.pw_uid = (uid_t)id;
144 if ((colon = strchr(cp = colon, ':')) == NULL)
147 id = sudo_strtoid(cp, NULL, NULL, &errstr);
150 pw.pw_gid = (gid_t)id;
151 if ((colon = strchr(cp = colon, ':')) == NULL)
155 if ((colon = strchr(cp = colon, ':')) == NULL)
161 if (len > 0 && colon[len - 1] == '\n')
162 colon[len - 1] = '\0';
167 getpwnam(const char *name)
172 if ((pwf = fopen(pwfile, "r")) == NULL)
174 (void)fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
178 while ((pw = getpwent()) != NULL) {
179 if (strcmp(pw->pw_name, name) == 0)
195 if ((pwf = fopen(pwfile, "r")) == NULL)
197 (void)fcntl(fileno(pwf), F_SETFD, FD_CLOEXEC);
201 while ((pw = getpwent()) != NULL) {
202 if (pw->pw_uid == uid)
213 setgrfile(const char *file)
224 grf = fopen(grfile, "r");
226 (void)fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
246 static struct group gr;
247 static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1];
255 if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL)
258 memset(&gr, 0, sizeof(gr));
259 if ((colon = strchr(cp = colon, ':')) == NULL)
263 if ((colon = strchr(cp = colon, ':')) == NULL)
267 if ((colon = strchr(cp = colon, ':')) == NULL)
270 id = sudo_strtoid(cp, NULL, NULL, &errstr);
273 gr.gr_gid = (gid_t)id;
275 if (len > 0 && colon[len - 1] == '\n')
276 colon[len - 1] = '\0';
277 if (*colon != '\0') {
281 cp = strtok_r(colon, ",", &last);
282 for (n = 0; cp != NULL && n < GRMEM_MAX; n++) {
284 cp = strtok_r(NULL, ",", &last);
286 gr.gr_mem[n++] = NULL;
293 getgrnam(const char *name)
298 if ((grf = fopen(grfile, "r")) == NULL)
300 (void)fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
304 while ((gr = getgrent()) != NULL) {
305 if (strcmp(gr->gr_name, name) == 0)
321 if ((grf = fopen(grfile, "r")) == NULL)
323 (void)fcntl(fileno(grf), F_SETFD, FD_CLOEXEC);
327 while ((gr = getgrent()) != NULL) {
328 if (gr->gr_gid == gid)
339 * Copied from getgrouplist.c
342 sudo_getgrouplist2_v1(const char *name, GETGROUPS_T basegid,
343 GETGROUPS_T **groupsp, int *ngroupsp)
345 GETGROUPS_T *groups = *groupsp;
346 int grpsize = *ngroupsp;
351 if (groups == NULL) {
352 /* Dynamically-sized group vector. */
353 grpsize = (int)sysconf(_SC_NGROUPS_MAX);
355 grpsize = NGROUPS_MAX;
356 groups = reallocarray(NULL, grpsize, 4 * sizeof(*groups));
361 /* Static group vector. */
366 /* We support BSD semantics where the first element is the base gid */
370 while ((grp = getgrent()) != NULL) {
371 if (grp->gr_gid == basegid || grp->gr_mem == NULL)
374 for (i = 0; grp->gr_mem[i] != NULL; i++) {
375 if (strcmp(name, grp->gr_mem[i]) == 0)
378 if (grp->gr_mem[i] == NULL)
379 continue; /* user not found */
381 /* Only add if it is not the same as an existing gid */
382 for (i = 0; i < ngroups; i++) {
383 if (grp->gr_gid == groups[i])
387 if (ngroups == grpsize) {
390 if (*groupsp != NULL) {
391 /* Static group vector. */
394 tmp = reallocarray(groups, grpsize, 2 * sizeof(*groups));
404 groups[ngroups++] = grp->gr_gid;