113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio_ext.h>
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <ctype.h>
8dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh#include <errno.h>
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <selinux/selinux.h>
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <selinux/context.h>
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h"
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Process line from seusers.conf and split into its fields.
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle   Returns 0 on success, -1 on comments, and -2 on error. */
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int process_seusers(const char *buffer,
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   char **luserp,
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			   char **seuserp, char **levelp, int mls_enabled)
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *newbuf = strdup(buffer);
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *luser = NULL, *seuser = NULL, *level = NULL;
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *start, *end;
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int mls_found = 1;
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!newbuf)
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	start = newbuf;
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (isspace(*start))
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		start++;
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (*start == '#' || *start == 0) {
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(newbuf);
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;	/* Comment or empty line, skip over */
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	end = strchr(start, ':');
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!end)
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*end = 0;
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	luser = strdup(start);
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!luser)
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	start = end + 1;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	end = strchr(start, ':');
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!end) {
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		mls_found = 0;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		end = start;
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		while (*end && !isspace(*end))
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			end++;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*end = 0;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	seuser = strdup(start);
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!seuser)
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!strcmp(seuser, ""))
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Skip MLS if disabled, or missing. */
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!mls_enabled || !mls_found)
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	start = ++end;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (*end && !isspace(*end))
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		end++;
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*end = 0;
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	level = strdup(start);
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!level)
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!strcmp(level, ""))
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto err;
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(newbuf);
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*luserp = luser;
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*seuserp = seuser;
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*levelp = level;
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      err:
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(newbuf);
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(luser);
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(seuser);
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(level);
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return -2;		/* error */
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint require_seusers hidden = 0;
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <pwd.h>
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <grp.h>
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic gid_t get_default_gid(const char *name) {
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct passwd pwstorage, *pwent = NULL;
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	gid_t gid = -1;
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Allocate space for the getpwnam_r buffer */
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	long rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rbuflen <= 0) return -1;
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *rbuf = malloc(rbuflen);
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rbuf == NULL) return -1;
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int retval = getpwnam_r(name, &pwstorage, rbuf, rbuflen, &pwent);
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (retval == 0 && pwent) {
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		gid = pwent->pw_gid;
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(rbuf);
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return gid;
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int check_group(const char *group, const char *name, const gid_t gid) {
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int match = 0;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int i, ng = 0;
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	gid_t *groups = NULL;
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct group gbuf, *grent = NULL;
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	long rbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rbuflen <= 0)
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
122dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh	char *rbuf;
123dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh
124dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh	while(1) {
125dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		rbuf = malloc(rbuflen);
126dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		if (rbuf == NULL)
127dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh			return 0;
128dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		int retval = getgrnam_r(group, &gbuf, rbuf,
129dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh				rbuflen, &grent);
130dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		if ( retval == ERANGE )
131dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		{
132dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh			free(rbuf);
133dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh			rbuflen = rbuflen * 2;
134dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		} else if ( retval != 0 || grent == NULL )
135dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		{
136dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh			goto done;
137dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		} else
138dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		{
139dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh			break;
140dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh		}
141dd563b35e1f6918e5c96de29ea255b04ad34e891Dan Walsh	}
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (getgrouplist(name, gid, NULL, &ng) < 0) {
144aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		if (ng == 0)
145aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris			goto done;
146aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		groups = calloc(ng, sizeof(*groups));
147aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		if (!groups)
148aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris			goto done;
149aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		if (getgrouplist(name, gid, groups, &ng) < 0)
150aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris			goto done;
151aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris	} else {
152aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		/* WTF?  ng was 0 and we didn't fail? Are we in 0 groups? */
153aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris		goto done;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < ng; i++) {
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (grent->gr_gid == groups[i]) {
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			match = 1;
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			goto done;
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle done:
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(groups);
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(rbuf);
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return match;
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint getseuserbyname(const char *name, char **r_seuser, char **r_level)
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *cfg = NULL;
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	size_t size = 0;
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *buffer = NULL;
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc;
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned long lineno = 0;
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int mls_enabled = is_selinux_mls_enabled();
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *username = NULL;
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *seuser = NULL;
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *level = NULL;
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *groupseuser = NULL;
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *grouplevel = NULL;
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *defaultseuser = NULL;
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *defaultlevel = NULL;
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	gid_t gid = get_default_gid(name);
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	cfg = fopen(selinux_usersconf_path(), "r");
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!cfg)
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto nomatch;
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	__fsetlocking(cfg, FSETLOCKING_BYCALLER);
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (getline(&buffer, &size, cfg) > 0) {
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		++lineno;
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rc = process_seusers(buffer, &username, &seuser, &level,
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				     mls_enabled);
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc == -1)
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;	/* comment, skip */
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (rc == -2) {
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fprintf(stderr, "%s:  error on line %lu, skipping...\n",
20113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				selinux_usersconf_path(), lineno);
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			continue;
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (!strcmp(username, name))
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (username[0] == '%' &&
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    !groupseuser &&
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		    check_group(&username[1], name, gid)) {
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				groupseuser = seuser;
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				grouplevel = level;
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		} else {
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			if (!defaultseuser &&
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			    !strcmp(username, "__default__")) {
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				defaultseuser = seuser;
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				defaultlevel = level;
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			} else {
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(seuser);
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				free(level);
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(username);
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		username = NULL;
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		seuser = NULL;
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(buffer);
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(cfg);
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (seuser) {
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(username);
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(defaultseuser);
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(defaultlevel);
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(groupseuser);
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(grouplevel);
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_seuser = seuser;
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_level = level;
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (groupseuser) {
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(defaultseuser);
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(defaultlevel);
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_seuser = groupseuser;
24613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_level = grouplevel;
24713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
24813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
24913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (defaultseuser) {
25113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_seuser = defaultseuser;
25213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*r_level = defaultlevel;
25313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
25413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
25513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
25613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      nomatch:
25713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (require_seusers)
25813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
25913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
26013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* Fall back to the Linux username and no level. */
26113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*r_seuser = strdup(name);
26213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!(*r_seuser))
26313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
26413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*r_level = NULL;
26513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
26613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
267532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
268532bd9a8926b4123c9444660041f4e9961543577Daniel J Walshint getseuser(const char *username, const char *service,
269532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	      char **r_seuser, char **r_level) {
270532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	int ret = -1;
271532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	int len = 0;
272532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	char *seuser = NULL;
273532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	char *level = NULL;
274532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	char *buffer = NULL;
275532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	size_t size = 0;
276532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	char *rec = NULL;
277532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	char *path=NULL;
278c87df3493d9550429193a8dc7d78a6bfc4c234d3Daniel P. Berrange	FILE *fp = NULL;
279532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (asprintf(&path,"%s/logins/%s", selinux_policy_root(), username) <  0)
280532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		goto err;
281c87df3493d9550429193a8dc7d78a6bfc4c234d3Daniel P. Berrange	fp = fopen(path, "r");
282532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	free(path);
283532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (fp == NULL) goto err;
284532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	__fsetlocking(fp, FSETLOCKING_BYCALLER);
285532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	while (getline(&buffer, &size, fp) > 0) {
286532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		if (strncmp(buffer, "*:", 2) == 0) {
287532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			free(rec);
288532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			rec = strdup(buffer);
289532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			continue;
290532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		}
2915e3171f658d1d2f1e0068f485b3fff7c164e05e4Eric Paris		if (!service)
2925e3171f658d1d2f1e0068f485b3fff7c164e05e4Eric Paris			continue;
293532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		len = strlen(service);
294532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		if ((strncmp(buffer, service, len) == 0) &&
295532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		    (buffer[len] == ':')) {
296532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			free(rec);
297532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			rec = strdup(buffer);
298532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh			break;
299532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		}
300532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	}
301532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
302532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (! rec)  goto err;
303532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	seuser = strchr(rec, ':');
304532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (! seuser) goto err;
305532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
306532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	seuser++;
307532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	level = strchr(seuser, ':');
308bd8ea2eb6caf103398fef80e41e0ef86ba3892b7Dan Walsh	if (! level) goto err;
309532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	*level = 0;
310532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	level++;
311532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	*r_seuser = strdup(seuser);
312532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (! *r_seuser) goto err;
313532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
314532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	len = strlen(level);
315532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (len && level[len-1] == '\n')
316532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		level[len-1] = 0;
317532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
318532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	*r_level = strdup(level);
319532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (! *r_level) {
320532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		free(*r_seuser);
321532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh		goto err;
322532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	}
323532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	ret = 0;
324532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
325532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	err:
326532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	free(buffer);
327532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	if (fp) fclose(fp);
328532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	free(rec);
329532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh
330532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh	return (ret ? getseuserbyname(username, r_seuser, r_level) : ret);
331532bd9a8926b4123c9444660041f4e9961543577Daniel J Walsh}
332