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