xref: /aosp_15_r20/external/selinux/libselinux/src/seusers.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
2*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
3*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
4*2d543d20SAndroid Build Coastguard Worker #include <string.h>
5*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
6*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
7*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
8*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
9*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
10*2d543d20SAndroid Build Coastguard Worker 
11*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
12*2d543d20SAndroid Build Coastguard Worker #include <selinux/context.h>
13*2d543d20SAndroid Build Coastguard Worker 
14*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
15*2d543d20SAndroid Build Coastguard Worker #include "callbacks.h"
16*2d543d20SAndroid Build Coastguard Worker 
17*2d543d20SAndroid Build Coastguard Worker /* Process line from seusers.conf and split into its fields.
18*2d543d20SAndroid Build Coastguard Worker    Returns 0 on success, -1 on comments, and -2 on error. */
process_seusers(const char * buffer,char ** luserp,char ** seuserp,char ** levelp,int mls_enabled)19*2d543d20SAndroid Build Coastguard Worker static int process_seusers(const char *buffer,
20*2d543d20SAndroid Build Coastguard Worker 			   char **luserp,
21*2d543d20SAndroid Build Coastguard Worker 			   char **seuserp, char **levelp, int mls_enabled)
22*2d543d20SAndroid Build Coastguard Worker {
23*2d543d20SAndroid Build Coastguard Worker 	char *newbuf = strdup(buffer);
24*2d543d20SAndroid Build Coastguard Worker 	char *luser = NULL, *seuser = NULL, *level = NULL;
25*2d543d20SAndroid Build Coastguard Worker 	char *start, *end;
26*2d543d20SAndroid Build Coastguard Worker 	int mls_found = 1;
27*2d543d20SAndroid Build Coastguard Worker 
28*2d543d20SAndroid Build Coastguard Worker 	if (!newbuf)
29*2d543d20SAndroid Build Coastguard Worker 		goto err;
30*2d543d20SAndroid Build Coastguard Worker 
31*2d543d20SAndroid Build Coastguard Worker 	start = newbuf;
32*2d543d20SAndroid Build Coastguard Worker 	while (isspace((unsigned char)*start))
33*2d543d20SAndroid Build Coastguard Worker 		start++;
34*2d543d20SAndroid Build Coastguard Worker 	if (*start == '#' || *start == 0) {
35*2d543d20SAndroid Build Coastguard Worker 		free(newbuf);
36*2d543d20SAndroid Build Coastguard Worker 		return -1;	/* Comment or empty line, skip over */
37*2d543d20SAndroid Build Coastguard Worker 	}
38*2d543d20SAndroid Build Coastguard Worker 	end = strchr(start, ':');
39*2d543d20SAndroid Build Coastguard Worker 	if (!end)
40*2d543d20SAndroid Build Coastguard Worker 		goto err;
41*2d543d20SAndroid Build Coastguard Worker 	*end = 0;
42*2d543d20SAndroid Build Coastguard Worker 
43*2d543d20SAndroid Build Coastguard Worker 	luser = strdup(start);
44*2d543d20SAndroid Build Coastguard Worker 	if (!luser)
45*2d543d20SAndroid Build Coastguard Worker 		goto err;
46*2d543d20SAndroid Build Coastguard Worker 
47*2d543d20SAndroid Build Coastguard Worker 	start = end + 1;
48*2d543d20SAndroid Build Coastguard Worker 	end = strchr(start, ':');
49*2d543d20SAndroid Build Coastguard Worker 	if (!end) {
50*2d543d20SAndroid Build Coastguard Worker 		mls_found = 0;
51*2d543d20SAndroid Build Coastguard Worker 
52*2d543d20SAndroid Build Coastguard Worker 		end = start;
53*2d543d20SAndroid Build Coastguard Worker 		while (*end && !isspace((unsigned char)*end))
54*2d543d20SAndroid Build Coastguard Worker 			end++;
55*2d543d20SAndroid Build Coastguard Worker 	}
56*2d543d20SAndroid Build Coastguard Worker 	*end = 0;
57*2d543d20SAndroid Build Coastguard Worker 
58*2d543d20SAndroid Build Coastguard Worker 	seuser = strdup(start);
59*2d543d20SAndroid Build Coastguard Worker 	if (!seuser)
60*2d543d20SAndroid Build Coastguard Worker 		goto err;
61*2d543d20SAndroid Build Coastguard Worker 
62*2d543d20SAndroid Build Coastguard Worker 	if (!strcmp(seuser, ""))
63*2d543d20SAndroid Build Coastguard Worker 		goto err;
64*2d543d20SAndroid Build Coastguard Worker 
65*2d543d20SAndroid Build Coastguard Worker 	/* Skip MLS if disabled, or missing. */
66*2d543d20SAndroid Build Coastguard Worker 	if (!mls_enabled || !mls_found)
67*2d543d20SAndroid Build Coastguard Worker 		goto out;
68*2d543d20SAndroid Build Coastguard Worker 
69*2d543d20SAndroid Build Coastguard Worker 	start = ++end;
70*2d543d20SAndroid Build Coastguard Worker 	while (*end && !isspace((unsigned char)*end))
71*2d543d20SAndroid Build Coastguard Worker 		end++;
72*2d543d20SAndroid Build Coastguard Worker 	*end = 0;
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker 	level = strdup(start);
75*2d543d20SAndroid Build Coastguard Worker 	if (!level)
76*2d543d20SAndroid Build Coastguard Worker 		goto err;
77*2d543d20SAndroid Build Coastguard Worker 
78*2d543d20SAndroid Build Coastguard Worker 	if (!strcmp(level, ""))
79*2d543d20SAndroid Build Coastguard Worker 		goto err;
80*2d543d20SAndroid Build Coastguard Worker 
81*2d543d20SAndroid Build Coastguard Worker       out:
82*2d543d20SAndroid Build Coastguard Worker 	free(newbuf);
83*2d543d20SAndroid Build Coastguard Worker 	*luserp = luser;
84*2d543d20SAndroid Build Coastguard Worker 	*seuserp = seuser;
85*2d543d20SAndroid Build Coastguard Worker 	*levelp = level;
86*2d543d20SAndroid Build Coastguard Worker 	return 0;
87*2d543d20SAndroid Build Coastguard Worker       err:
88*2d543d20SAndroid Build Coastguard Worker 	free(newbuf);
89*2d543d20SAndroid Build Coastguard Worker 	free(luser);
90*2d543d20SAndroid Build Coastguard Worker 	free(seuser);
91*2d543d20SAndroid Build Coastguard Worker 	free(level);
92*2d543d20SAndroid Build Coastguard Worker 	return -2;		/* error */
93*2d543d20SAndroid Build Coastguard Worker }
94*2d543d20SAndroid Build Coastguard Worker 
95*2d543d20SAndroid Build Coastguard Worker int require_seusers  = 0;
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker #include <pwd.h>
98*2d543d20SAndroid Build Coastguard Worker #include <grp.h>
99*2d543d20SAndroid Build Coastguard Worker 
get_default_gid(const char * name)100*2d543d20SAndroid Build Coastguard Worker static gid_t get_default_gid(const char *name) {
101*2d543d20SAndroid Build Coastguard Worker 	struct passwd pwstorage, *pwent = NULL;
102*2d543d20SAndroid Build Coastguard Worker 	gid_t gid = (gid_t)-1;
103*2d543d20SAndroid Build Coastguard Worker 	/* Allocate space for the getpwnam_r buffer */
104*2d543d20SAndroid Build Coastguard Worker 	char *rbuf = NULL;
105*2d543d20SAndroid Build Coastguard Worker 	long rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
106*2d543d20SAndroid Build Coastguard Worker 	if (rbuflen <= 0)
107*2d543d20SAndroid Build Coastguard Worker 		rbuflen = 1024;
108*2d543d20SAndroid Build Coastguard Worker 
109*2d543d20SAndroid Build Coastguard Worker 	for (;;) {
110*2d543d20SAndroid Build Coastguard Worker 		int rc;
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker 		rbuf = malloc(rbuflen);
113*2d543d20SAndroid Build Coastguard Worker 		if (rbuf == NULL)
114*2d543d20SAndroid Build Coastguard Worker 			break;
115*2d543d20SAndroid Build Coastguard Worker 
116*2d543d20SAndroid Build Coastguard Worker 		rc = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
117*2d543d20SAndroid Build Coastguard Worker 		if (rc == ERANGE && rbuflen < LONG_MAX / 2) {
118*2d543d20SAndroid Build Coastguard Worker 			free(rbuf);
119*2d543d20SAndroid Build Coastguard Worker 			rbuflen *= 2;
120*2d543d20SAndroid Build Coastguard Worker 			continue;
121*2d543d20SAndroid Build Coastguard Worker 		}
122*2d543d20SAndroid Build Coastguard Worker 		if (rc == 0 && pwent)
123*2d543d20SAndroid Build Coastguard Worker 			gid = pwent->pw_gid;
124*2d543d20SAndroid Build Coastguard Worker 
125*2d543d20SAndroid Build Coastguard Worker 		break;
126*2d543d20SAndroid Build Coastguard Worker 	}
127*2d543d20SAndroid Build Coastguard Worker 
128*2d543d20SAndroid Build Coastguard Worker 	free(rbuf);
129*2d543d20SAndroid Build Coastguard Worker 	return gid;
130*2d543d20SAndroid Build Coastguard Worker }
131*2d543d20SAndroid Build Coastguard Worker 
check_group(const char * group,const char * name,const gid_t gid)132*2d543d20SAndroid Build Coastguard Worker static int check_group(const char *group, const char *name, const gid_t gid) {
133*2d543d20SAndroid Build Coastguard Worker 	int match = 0;
134*2d543d20SAndroid Build Coastguard Worker 	int i, ng = 0;
135*2d543d20SAndroid Build Coastguard Worker 	gid_t *groups = NULL;
136*2d543d20SAndroid Build Coastguard Worker 	struct group gbuf, *grent = NULL;
137*2d543d20SAndroid Build Coastguard Worker 
138*2d543d20SAndroid Build Coastguard Worker 	long rbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
139*2d543d20SAndroid Build Coastguard Worker 	if (rbuflen <= 0)
140*2d543d20SAndroid Build Coastguard Worker 		rbuflen = 1024;
141*2d543d20SAndroid Build Coastguard Worker 	char *rbuf;
142*2d543d20SAndroid Build Coastguard Worker 
143*2d543d20SAndroid Build Coastguard Worker 	while(1) {
144*2d543d20SAndroid Build Coastguard Worker 		rbuf = malloc(rbuflen);
145*2d543d20SAndroid Build Coastguard Worker 		if (rbuf == NULL)
146*2d543d20SAndroid Build Coastguard Worker 			return 0;
147*2d543d20SAndroid Build Coastguard Worker 		int retval = getgrnam_r(group, &gbuf, rbuf,
148*2d543d20SAndroid Build Coastguard Worker 				rbuflen, &grent);
149*2d543d20SAndroid Build Coastguard Worker 		if (retval == ERANGE && rbuflen < LONG_MAX / 2)
150*2d543d20SAndroid Build Coastguard Worker 		{
151*2d543d20SAndroid Build Coastguard Worker 			free(rbuf);
152*2d543d20SAndroid Build Coastguard Worker 			rbuflen = rbuflen * 2;
153*2d543d20SAndroid Build Coastguard Worker 		} else if ( retval != 0 || grent == NULL )
154*2d543d20SAndroid Build Coastguard Worker 		{
155*2d543d20SAndroid Build Coastguard Worker 			goto done;
156*2d543d20SAndroid Build Coastguard Worker 		} else
157*2d543d20SAndroid Build Coastguard Worker 		{
158*2d543d20SAndroid Build Coastguard Worker 			break;
159*2d543d20SAndroid Build Coastguard Worker 		}
160*2d543d20SAndroid Build Coastguard Worker 	}
161*2d543d20SAndroid Build Coastguard Worker 
162*2d543d20SAndroid Build Coastguard Worker 	if (getgrouplist(name, gid, NULL, &ng) < 0) {
163*2d543d20SAndroid Build Coastguard Worker 		if (ng == 0)
164*2d543d20SAndroid Build Coastguard Worker 			goto done;
165*2d543d20SAndroid Build Coastguard Worker 		groups = calloc(ng, sizeof(*groups));
166*2d543d20SAndroid Build Coastguard Worker 		if (!groups)
167*2d543d20SAndroid Build Coastguard Worker 			goto done;
168*2d543d20SAndroid Build Coastguard Worker 		if (getgrouplist(name, gid, groups, &ng) < 0)
169*2d543d20SAndroid Build Coastguard Worker 			goto done;
170*2d543d20SAndroid Build Coastguard Worker 	} else {
171*2d543d20SAndroid Build Coastguard Worker 		/* WTF?  ng was 0 and we didn't fail? Are we in 0 groups? */
172*2d543d20SAndroid Build Coastguard Worker 		goto done;
173*2d543d20SAndroid Build Coastguard Worker 	}
174*2d543d20SAndroid Build Coastguard Worker 
175*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < ng; i++) {
176*2d543d20SAndroid Build Coastguard Worker 		if (grent->gr_gid == groups[i]) {
177*2d543d20SAndroid Build Coastguard Worker 			match = 1;
178*2d543d20SAndroid Build Coastguard Worker 			goto done;
179*2d543d20SAndroid Build Coastguard Worker 		}
180*2d543d20SAndroid Build Coastguard Worker 	}
181*2d543d20SAndroid Build Coastguard Worker 
182*2d543d20SAndroid Build Coastguard Worker  done:
183*2d543d20SAndroid Build Coastguard Worker 	free(groups);
184*2d543d20SAndroid Build Coastguard Worker 	free(rbuf);
185*2d543d20SAndroid Build Coastguard Worker 	return match;
186*2d543d20SAndroid Build Coastguard Worker }
187*2d543d20SAndroid Build Coastguard Worker 
getseuserbyname(const char * name,char ** r_seuser,char ** r_level)188*2d543d20SAndroid Build Coastguard Worker int getseuserbyname(const char *name, char **r_seuser, char **r_level)
189*2d543d20SAndroid Build Coastguard Worker {
190*2d543d20SAndroid Build Coastguard Worker 	FILE *cfg = NULL;
191*2d543d20SAndroid Build Coastguard Worker 	size_t size = 0;
192*2d543d20SAndroid Build Coastguard Worker 	char *buffer = NULL;
193*2d543d20SAndroid Build Coastguard Worker 	int rc;
194*2d543d20SAndroid Build Coastguard Worker 	unsigned long lineno = 0;
195*2d543d20SAndroid Build Coastguard Worker 	int mls_enabled = is_selinux_mls_enabled();
196*2d543d20SAndroid Build Coastguard Worker 
197*2d543d20SAndroid Build Coastguard Worker 	char *username = NULL;
198*2d543d20SAndroid Build Coastguard Worker 	char *seuser = NULL;
199*2d543d20SAndroid Build Coastguard Worker 	char *level = NULL;
200*2d543d20SAndroid Build Coastguard Worker 	char *groupseuser = NULL;
201*2d543d20SAndroid Build Coastguard Worker 	char *grouplevel = NULL;
202*2d543d20SAndroid Build Coastguard Worker 	char *defaultseuser = NULL;
203*2d543d20SAndroid Build Coastguard Worker 	char *defaultlevel = NULL;
204*2d543d20SAndroid Build Coastguard Worker 
205*2d543d20SAndroid Build Coastguard Worker 	gid_t gid = get_default_gid(name);
206*2d543d20SAndroid Build Coastguard Worker 
207*2d543d20SAndroid Build Coastguard Worker 	cfg = fopen(selinux_usersconf_path(), "re");
208*2d543d20SAndroid Build Coastguard Worker 	if (!cfg)
209*2d543d20SAndroid Build Coastguard Worker 		goto nomatch;
210*2d543d20SAndroid Build Coastguard Worker 
211*2d543d20SAndroid Build Coastguard Worker 	__fsetlocking(cfg, FSETLOCKING_BYCALLER);
212*2d543d20SAndroid Build Coastguard Worker 	while (getline(&buffer, &size, cfg) > 0) {
213*2d543d20SAndroid Build Coastguard Worker 		++lineno;
214*2d543d20SAndroid Build Coastguard Worker 		rc = process_seusers(buffer, &username, &seuser, &level,
215*2d543d20SAndroid Build Coastguard Worker 				     mls_enabled);
216*2d543d20SAndroid Build Coastguard Worker 		if (rc == -1)
217*2d543d20SAndroid Build Coastguard Worker 			continue;	/* comment, skip */
218*2d543d20SAndroid Build Coastguard Worker 		if (rc == -2) {
219*2d543d20SAndroid Build Coastguard Worker 			selinux_log(SELINUX_ERROR, "%s:  error on line %lu, skipping...\n",
220*2d543d20SAndroid Build Coastguard Worker 						   selinux_usersconf_path(), lineno);
221*2d543d20SAndroid Build Coastguard Worker 			continue;
222*2d543d20SAndroid Build Coastguard Worker 		}
223*2d543d20SAndroid Build Coastguard Worker 
224*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(username, name))
225*2d543d20SAndroid Build Coastguard Worker 			break;
226*2d543d20SAndroid Build Coastguard Worker 
227*2d543d20SAndroid Build Coastguard Worker 		if (username[0] == '%' &&
228*2d543d20SAndroid Build Coastguard Worker 		    !groupseuser &&
229*2d543d20SAndroid Build Coastguard Worker 		    check_group(&username[1], name, gid)) {
230*2d543d20SAndroid Build Coastguard Worker 				groupseuser = seuser;
231*2d543d20SAndroid Build Coastguard Worker 				grouplevel = level;
232*2d543d20SAndroid Build Coastguard Worker 		} else {
233*2d543d20SAndroid Build Coastguard Worker 			if (!defaultseuser &&
234*2d543d20SAndroid Build Coastguard Worker 			    !strcmp(username, "__default__")) {
235*2d543d20SAndroid Build Coastguard Worker 				defaultseuser = seuser;
236*2d543d20SAndroid Build Coastguard Worker 				defaultlevel = level;
237*2d543d20SAndroid Build Coastguard Worker 			} else {
238*2d543d20SAndroid Build Coastguard Worker 				free(seuser);
239*2d543d20SAndroid Build Coastguard Worker 				free(level);
240*2d543d20SAndroid Build Coastguard Worker 			}
241*2d543d20SAndroid Build Coastguard Worker 		}
242*2d543d20SAndroid Build Coastguard Worker 		free(username);
243*2d543d20SAndroid Build Coastguard Worker 		username = NULL;
244*2d543d20SAndroid Build Coastguard Worker 		seuser = NULL;
245*2d543d20SAndroid Build Coastguard Worker 	}
246*2d543d20SAndroid Build Coastguard Worker 
247*2d543d20SAndroid Build Coastguard Worker 	free(buffer);
248*2d543d20SAndroid Build Coastguard Worker 	fclose(cfg);
249*2d543d20SAndroid Build Coastguard Worker 
250*2d543d20SAndroid Build Coastguard Worker 	if (seuser) {
251*2d543d20SAndroid Build Coastguard Worker 		free(username);
252*2d543d20SAndroid Build Coastguard Worker 		free(defaultseuser);
253*2d543d20SAndroid Build Coastguard Worker 		free(defaultlevel);
254*2d543d20SAndroid Build Coastguard Worker 		free(groupseuser);
255*2d543d20SAndroid Build Coastguard Worker 		free(grouplevel);
256*2d543d20SAndroid Build Coastguard Worker 		*r_seuser = seuser;
257*2d543d20SAndroid Build Coastguard Worker 		*r_level = level;
258*2d543d20SAndroid Build Coastguard Worker 		return 0;
259*2d543d20SAndroid Build Coastguard Worker 	}
260*2d543d20SAndroid Build Coastguard Worker 
261*2d543d20SAndroid Build Coastguard Worker 	if (groupseuser) {
262*2d543d20SAndroid Build Coastguard Worker 		free(defaultseuser);
263*2d543d20SAndroid Build Coastguard Worker 		free(defaultlevel);
264*2d543d20SAndroid Build Coastguard Worker 		*r_seuser = groupseuser;
265*2d543d20SAndroid Build Coastguard Worker 		*r_level = grouplevel;
266*2d543d20SAndroid Build Coastguard Worker 		return 0;
267*2d543d20SAndroid Build Coastguard Worker 	}
268*2d543d20SAndroid Build Coastguard Worker 
269*2d543d20SAndroid Build Coastguard Worker 	if (defaultseuser) {
270*2d543d20SAndroid Build Coastguard Worker 		*r_seuser = defaultseuser;
271*2d543d20SAndroid Build Coastguard Worker 		*r_level = defaultlevel;
272*2d543d20SAndroid Build Coastguard Worker 		return 0;
273*2d543d20SAndroid Build Coastguard Worker 	}
274*2d543d20SAndroid Build Coastguard Worker 
275*2d543d20SAndroid Build Coastguard Worker       nomatch:
276*2d543d20SAndroid Build Coastguard Worker 	if (require_seusers)
277*2d543d20SAndroid Build Coastguard Worker 		return -1;
278*2d543d20SAndroid Build Coastguard Worker 
279*2d543d20SAndroid Build Coastguard Worker 	/* Fall back to the Linux username and no level. */
280*2d543d20SAndroid Build Coastguard Worker 	*r_seuser = strdup(name);
281*2d543d20SAndroid Build Coastguard Worker 	if (!(*r_seuser))
282*2d543d20SAndroid Build Coastguard Worker 		return -1;
283*2d543d20SAndroid Build Coastguard Worker 	*r_level = NULL;
284*2d543d20SAndroid Build Coastguard Worker 	return 0;
285*2d543d20SAndroid Build Coastguard Worker }
286*2d543d20SAndroid Build Coastguard Worker 
getseuser(const char * username,const char * service,char ** r_seuser,char ** r_level)287*2d543d20SAndroid Build Coastguard Worker int getseuser(const char *username, const char *service,
288*2d543d20SAndroid Build Coastguard Worker 	      char **r_seuser, char **r_level) {
289*2d543d20SAndroid Build Coastguard Worker 	int ret = -1;
290*2d543d20SAndroid Build Coastguard Worker 	int len = 0;
291*2d543d20SAndroid Build Coastguard Worker 	char *seuser = NULL;
292*2d543d20SAndroid Build Coastguard Worker 	char *level = NULL;
293*2d543d20SAndroid Build Coastguard Worker 	char *buffer = NULL;
294*2d543d20SAndroid Build Coastguard Worker 	size_t size = 0;
295*2d543d20SAndroid Build Coastguard Worker 	char *rec = NULL;
296*2d543d20SAndroid Build Coastguard Worker 	char *path = NULL;
297*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
298*2d543d20SAndroid Build Coastguard Worker 	if (asprintf(&path,"%s/logins/%s", selinux_policy_root(), username) <  0)
299*2d543d20SAndroid Build Coastguard Worker 		goto err;
300*2d543d20SAndroid Build Coastguard Worker 	fp = fopen(path, "re");
301*2d543d20SAndroid Build Coastguard Worker 	free(path);
302*2d543d20SAndroid Build Coastguard Worker 	if (fp == NULL) goto err;
303*2d543d20SAndroid Build Coastguard Worker 	__fsetlocking(fp, FSETLOCKING_BYCALLER);
304*2d543d20SAndroid Build Coastguard Worker 	while (getline(&buffer, &size, fp) > 0) {
305*2d543d20SAndroid Build Coastguard Worker 		if (strncmp(buffer, "*:", 2) == 0) {
306*2d543d20SAndroid Build Coastguard Worker 			free(rec);
307*2d543d20SAndroid Build Coastguard Worker 			rec = strdup(buffer);
308*2d543d20SAndroid Build Coastguard Worker 			continue;
309*2d543d20SAndroid Build Coastguard Worker 		}
310*2d543d20SAndroid Build Coastguard Worker 		if (!service)
311*2d543d20SAndroid Build Coastguard Worker 			continue;
312*2d543d20SAndroid Build Coastguard Worker 		len = strlen(service);
313*2d543d20SAndroid Build Coastguard Worker 		if ((strncmp(buffer, service, len) == 0) &&
314*2d543d20SAndroid Build Coastguard Worker 		    (buffer[len] == ':')) {
315*2d543d20SAndroid Build Coastguard Worker 			free(rec);
316*2d543d20SAndroid Build Coastguard Worker 			rec = strdup(buffer);
317*2d543d20SAndroid Build Coastguard Worker 			break;
318*2d543d20SAndroid Build Coastguard Worker 		}
319*2d543d20SAndroid Build Coastguard Worker 	}
320*2d543d20SAndroid Build Coastguard Worker 
321*2d543d20SAndroid Build Coastguard Worker 	if (! rec)  goto err;
322*2d543d20SAndroid Build Coastguard Worker 	seuser = strchr(rec, ':');
323*2d543d20SAndroid Build Coastguard Worker 	if (! seuser) goto err;
324*2d543d20SAndroid Build Coastguard Worker 
325*2d543d20SAndroid Build Coastguard Worker 	seuser++;
326*2d543d20SAndroid Build Coastguard Worker 	level = strchr(seuser, ':');
327*2d543d20SAndroid Build Coastguard Worker 	if (! level) goto err;
328*2d543d20SAndroid Build Coastguard Worker 	*level = 0;
329*2d543d20SAndroid Build Coastguard Worker 	level++;
330*2d543d20SAndroid Build Coastguard Worker 	*r_seuser = strdup(seuser);
331*2d543d20SAndroid Build Coastguard Worker 	if (! *r_seuser) goto err;
332*2d543d20SAndroid Build Coastguard Worker 
333*2d543d20SAndroid Build Coastguard Worker 	len = strlen(level);
334*2d543d20SAndroid Build Coastguard Worker 	if (len && level[len-1] == '\n')
335*2d543d20SAndroid Build Coastguard Worker 		level[len-1] = 0;
336*2d543d20SAndroid Build Coastguard Worker 
337*2d543d20SAndroid Build Coastguard Worker 	*r_level = strdup(level);
338*2d543d20SAndroid Build Coastguard Worker 	if (! *r_level) {
339*2d543d20SAndroid Build Coastguard Worker 		free(*r_seuser);
340*2d543d20SAndroid Build Coastguard Worker 		goto err;
341*2d543d20SAndroid Build Coastguard Worker 	}
342*2d543d20SAndroid Build Coastguard Worker 	ret = 0;
343*2d543d20SAndroid Build Coastguard Worker 
344*2d543d20SAndroid Build Coastguard Worker 	err:
345*2d543d20SAndroid Build Coastguard Worker 	free(buffer);
346*2d543d20SAndroid Build Coastguard Worker 	if (fp) fclose(fp);
347*2d543d20SAndroid Build Coastguard Worker 	free(rec);
348*2d543d20SAndroid Build Coastguard Worker 
349*2d543d20SAndroid Build Coastguard Worker 	return (ret ? getseuserbyname(username, r_seuser, r_level) : ret);
350*2d543d20SAndroid Build Coastguard Worker }
351