xref: /freebsd/usr.sbin/pw/pw_vpw.c (revision eba230afba4932f02a1ca44efc797cf7499a5cb0)
15f12594aSDavid Nugent /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
45f12594aSDavid Nugent  * Copyright (C) 1996
55f12594aSDavid Nugent  *	David L. Nugent.  All rights reserved.
65f12594aSDavid Nugent  *
75f12594aSDavid Nugent  * Redistribution and use in source and binary forms, with or without
85f12594aSDavid Nugent  * modification, are permitted provided that the following conditions
95f12594aSDavid Nugent  * are met:
105f12594aSDavid Nugent  * 1. Redistributions of source code must retain the above copyright
115f12594aSDavid Nugent  *    notice, this list of conditions and the following disclaimer.
125f12594aSDavid Nugent  * 2. Redistributions in binary form must reproduce the above copyright
135f12594aSDavid Nugent  *    notice, this list of conditions and the following disclaimer in the
145f12594aSDavid Nugent  *    documentation and/or other materials provided with the distribution.
155f12594aSDavid Nugent  *
165f12594aSDavid Nugent  * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND
175f12594aSDavid Nugent  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
185f12594aSDavid Nugent  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
195f12594aSDavid Nugent  * ARE DISCLAIMED.  IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE
205f12594aSDavid Nugent  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
215f12594aSDavid Nugent  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
225f12594aSDavid Nugent  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
235f12594aSDavid Nugent  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
245f12594aSDavid Nugent  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
255f12594aSDavid Nugent  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
265f12594aSDavid Nugent  * SUCH DAMAGE.
275f12594aSDavid Nugent  *
285f12594aSDavid Nugent  */
295f12594aSDavid Nugent 
30b3075010SBaptiste Daroussin #include <pwd.h>
31b3075010SBaptiste Daroussin #include <grp.h>
32b3075010SBaptiste Daroussin #include <libutil.h>
335f12594aSDavid Nugent #include <stdio.h>
345f12594aSDavid Nugent #include <string.h>
355f12594aSDavid Nugent #include <stdlib.h>
3659856c7dSBaptiste Daroussin #include <err.h>
373196b508SIan Lepore #include <unistd.h>
385f12594aSDavid Nugent 
395f12594aSDavid Nugent #include "pwupd.h"
405f12594aSDavid Nugent 
415f12594aSDavid Nugent static FILE * pwd_fp = NULL;
423196b508SIan Lepore static int pwd_scanflag;
433196b508SIan Lepore static const char *pwd_filename;
445f12594aSDavid Nugent 
455f12594aSDavid Nugent void
vendpwent(void)465f12594aSDavid Nugent vendpwent(void)
475f12594aSDavid Nugent {
485f12594aSDavid Nugent 	if (pwd_fp != NULL) {
495f12594aSDavid Nugent 		fclose(pwd_fp);
505f12594aSDavid Nugent 		pwd_fp = NULL;
515f12594aSDavid Nugent 	}
525f12594aSDavid Nugent }
535f12594aSDavid Nugent 
545f12594aSDavid Nugent void
vsetpwent(void)555f12594aSDavid Nugent vsetpwent(void)
565f12594aSDavid Nugent {
575f12594aSDavid Nugent 	vendpwent();
585f12594aSDavid Nugent }
595f12594aSDavid Nugent 
605f12594aSDavid Nugent static struct passwd *
vnextpwent(char const * nam,uid_t uid,int doclose)615f12594aSDavid Nugent vnextpwent(char const *nam, uid_t uid, int doclose)
625f12594aSDavid Nugent {
63b3075010SBaptiste Daroussin 	struct passwd *pw;
64b3075010SBaptiste Daroussin 	char *line;
65b3075010SBaptiste Daroussin 	size_t linecap;
66b3075010SBaptiste Daroussin 	ssize_t linelen;
675f12594aSDavid Nugent 
68b3075010SBaptiste Daroussin 	pw = NULL;
69b3075010SBaptiste Daroussin 	line = NULL;
70b3075010SBaptiste Daroussin 	linecap = 0;
715f12594aSDavid Nugent 
723196b508SIan Lepore 	if (pwd_fp == NULL) {
733196b508SIan Lepore 		if (geteuid() == 0) {
743196b508SIan Lepore 			pwd_filename = _MASTERPASSWD;
753196b508SIan Lepore 			pwd_scanflag = PWSCAN_MASTER;
763196b508SIan Lepore 		} else {
773196b508SIan Lepore 			pwd_filename = _PASSWD;
783196b508SIan Lepore 			pwd_scanflag = 0;
793196b508SIan Lepore 		}
803196b508SIan Lepore 		pwd_fp = fopen(getpwpath(pwd_filename), "r");
813196b508SIan Lepore 	}
823196b508SIan Lepore 
833196b508SIan Lepore 	if (pwd_fp != NULL) {
84b3075010SBaptiste Daroussin 		while ((linelen = getline(&line, &linecap, pwd_fp)) > 0) {
85b3075010SBaptiste Daroussin 			/* Skip comments and empty lines */
86b3075010SBaptiste Daroussin 			if (*line == '\n' || *line == '#')
875f12594aSDavid Nugent 				continue;
88b3075010SBaptiste Daroussin 			/* trim latest \n */
89b3075010SBaptiste Daroussin 			if (line[linelen - 1 ] == '\n')
90b3075010SBaptiste Daroussin 				line[linelen - 1] = '\0';
913196b508SIan Lepore 			pw = pw_scan(line, pwd_scanflag);
9259856c7dSBaptiste Daroussin 			if (pw == NULL)
9359856c7dSBaptiste Daroussin 				errx(EXIT_FAILURE, "Invalid user entry in '%s':"
943196b508SIan Lepore 				    " '%s'", getpwpath(pwd_filename), line);
955f12594aSDavid Nugent 			if (uid != (uid_t)-1) {
96b3075010SBaptiste Daroussin 				if (uid == pw->pw_uid)
975f12594aSDavid Nugent 					break;
98b3075010SBaptiste Daroussin 			} else if (nam != NULL) {
99b3075010SBaptiste Daroussin 				if (strcmp(nam, pw->pw_name) == 0)
1005f12594aSDavid Nugent 					break;
101b3075010SBaptiste Daroussin 			} else
1025f12594aSDavid Nugent 				break;
103b3075010SBaptiste Daroussin 			free(pw);
104b3075010SBaptiste Daroussin 			pw = NULL;
1055f12594aSDavid Nugent 		}
1065f12594aSDavid Nugent 		if (doclose)
1075f12594aSDavid Nugent 			vendpwent();
108b3075010SBaptiste Daroussin 	}
109b3075010SBaptiste Daroussin 	free(line);
1105f12594aSDavid Nugent 
111b3075010SBaptiste Daroussin 	return (pw);
1125f12594aSDavid Nugent }
1135f12594aSDavid Nugent 
1145f12594aSDavid Nugent struct passwd *
vgetpwent(void)1155f12594aSDavid Nugent vgetpwent(void)
1165f12594aSDavid Nugent {
1175f12594aSDavid Nugent   return vnextpwent(NULL, -1, 0);
1185f12594aSDavid Nugent }
1195f12594aSDavid Nugent 
1205f12594aSDavid Nugent struct passwd *
vgetpwuid(uid_t uid)1215f12594aSDavid Nugent vgetpwuid(uid_t uid)
1225f12594aSDavid Nugent {
1235f12594aSDavid Nugent   return vnextpwent(NULL, uid, 1);
1245f12594aSDavid Nugent }
1255f12594aSDavid Nugent 
1265f12594aSDavid Nugent struct passwd *
vgetpwnam(const char * nam)1275f12594aSDavid Nugent vgetpwnam(const char * nam)
1285f12594aSDavid Nugent {
1295f12594aSDavid Nugent   return vnextpwent(nam, -1, 1);
1305f12594aSDavid Nugent }
1315f12594aSDavid Nugent 
1325f12594aSDavid Nugent 
1335f12594aSDavid Nugent static FILE * grp_fp = NULL;
1345f12594aSDavid Nugent 
1355f12594aSDavid Nugent void
vendgrent(void)1365f12594aSDavid Nugent vendgrent(void)
1375f12594aSDavid Nugent {
1385f12594aSDavid Nugent 	if (grp_fp != NULL) {
1395f12594aSDavid Nugent 		fclose(grp_fp);
1405f12594aSDavid Nugent 		grp_fp = NULL;
1415f12594aSDavid Nugent 	}
1425f12594aSDavid Nugent }
1435f12594aSDavid Nugent 
1449c242913SEd Schouten void
vsetgrent(void)1455f12594aSDavid Nugent vsetgrent(void)
1465f12594aSDavid Nugent {
1475f12594aSDavid Nugent 	vendgrent();
1485f12594aSDavid Nugent }
1495f12594aSDavid Nugent 
1505f12594aSDavid Nugent static struct group *
vnextgrent(char const * nam,gid_t gid,int doclose)1515f12594aSDavid Nugent vnextgrent(char const *nam, gid_t gid, int doclose)
1525f12594aSDavid Nugent {
153b3075010SBaptiste Daroussin 	struct group *gr;
154b3075010SBaptiste Daroussin 	char *line;
155b3075010SBaptiste Daroussin 	size_t linecap;
156b3075010SBaptiste Daroussin 	ssize_t linelen;
1575f12594aSDavid Nugent 
158b3075010SBaptiste Daroussin 	gr = NULL;
159b3075010SBaptiste Daroussin 	line = NULL;
160b3075010SBaptiste Daroussin 	linecap = 0;
1615f12594aSDavid Nugent 
162b3075010SBaptiste Daroussin 	if (grp_fp != NULL || (grp_fp = fopen(getgrpath(_GROUP), "r")) != NULL) {
163b3075010SBaptiste Daroussin 		while ((linelen = getline(&line, &linecap, grp_fp)) > 0) {
1645f12594aSDavid Nugent 			/* Skip comments and empty lines */
165b3075010SBaptiste Daroussin 			if (*line == '\n' || *line == '#')
1665f12594aSDavid Nugent 				continue;
167b3075010SBaptiste Daroussin 			/* trim latest \n */
168b3075010SBaptiste Daroussin 			if (line[linelen - 1 ] == '\n')
169b3075010SBaptiste Daroussin 				line[linelen - 1] = '\0';
170b3075010SBaptiste Daroussin 			gr = gr_scan(line);
17159856c7dSBaptiste Daroussin 			if (gr == NULL)
17259856c7dSBaptiste Daroussin 				errx(EXIT_FAILURE, "Invalid group entry in '%s':"
17359856c7dSBaptiste Daroussin 				    " '%s'", getgrpath(_GROUP), line);
1745f12594aSDavid Nugent 			if (gid != (gid_t)-1) {
175b3075010SBaptiste Daroussin 				if (gid == gr->gr_gid)
1765f12594aSDavid Nugent 					break;
177b3075010SBaptiste Daroussin 			} else if (nam != NULL) {
178b3075010SBaptiste Daroussin 				if (strcmp(nam, gr->gr_name) == 0)
1795f12594aSDavid Nugent 					break;
180b3075010SBaptiste Daroussin 			} else
1815f12594aSDavid Nugent 				break;
182b3075010SBaptiste Daroussin 			free(gr);
183b3075010SBaptiste Daroussin 			gr = NULL;
1845f12594aSDavid Nugent 		}
1855f12594aSDavid Nugent 		if (doclose)
1865f12594aSDavid Nugent 			vendgrent();
187b3075010SBaptiste Daroussin 	}
188b3075010SBaptiste Daroussin 	free(line);
1895f12594aSDavid Nugent 
190b3075010SBaptiste Daroussin 	return (gr);
1915f12594aSDavid Nugent }
1925f12594aSDavid Nugent 
1935f12594aSDavid Nugent struct group *
vgetgrent(void)1945f12594aSDavid Nugent vgetgrent(void)
1955f12594aSDavid Nugent {
1965f12594aSDavid Nugent   return vnextgrent(NULL, -1, 0);
1975f12594aSDavid Nugent }
1985f12594aSDavid Nugent 
1995f12594aSDavid Nugent 
2005f12594aSDavid Nugent struct group *
vgetgrgid(gid_t gid)2015f12594aSDavid Nugent vgetgrgid(gid_t gid)
2025f12594aSDavid Nugent {
2035f12594aSDavid Nugent   return vnextgrent(NULL, gid, 1);
2045f12594aSDavid Nugent }
2055f12594aSDavid Nugent 
2065f12594aSDavid Nugent struct group *
vgetgrnam(const char * nam)2075f12594aSDavid Nugent vgetgrnam(const char * nam)
2085f12594aSDavid Nugent {
2095f12594aSDavid Nugent   return vnextgrent(nam, -1, 1);
2105f12594aSDavid Nugent }
2115f12594aSDavid Nugent 
212