Chris PeBenito 473ea7
#include <unistd.h>
Chris PeBenito 473ea7
#include <fcntl.h>
Chris PeBenito 473ea7
#include <stdlib.h>
Chris PeBenito 473ea7
#include <string.h>
Chris PeBenito 473ea7
#include <stdio.h>
Chris PeBenito 473ea7
#include <ctype.h>
Chris PeBenito 473ea7
#include <selinux/selinux.h>
Chris PeBenito 473ea7
#include <selinux/context.h>
Chris PeBenito 473ea7
#include "selinux_internal.h"
Chris PeBenito 473ea7
Chris PeBenito 473ea7
/* Process line from seusers.conf and split into its fields.
Chris PeBenito 473ea7
   Returns 0 on success, -1 on comments, and -2 on error. */
Chris PeBenito 473ea7
static int process_seusers(const char *buffer, 
Chris PeBenito 473ea7
			   char **luserp, 
Chris PeBenito 473ea7
			   char **seuserp, 
Chris PeBenito 473ea7
			   char **levelp,
Chris PeBenito 473ea7
			   int mls_enabled)
Chris PeBenito 473ea7
{
Chris PeBenito 473ea7
	char *newbuf = strdup(buffer);
Chris PeBenito 473ea7
	char *luser = NULL, *seuser = NULL, *level = NULL;
Chris PeBenito 473ea7
	char *start, *end;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	if (!newbuf)
Chris PeBenito 473ea7
		goto err;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	start = newbuf;
Chris PeBenito 473ea7
	while (isspace(*start))
Chris PeBenito 473ea7
		start++;
Chris PeBenito 5a3b36
	if (*start == '#' || *start == 0) {
Chris PeBenito 473ea7
		free(newbuf);
Chris PeBenito 5a3b36
		return -1; /* Comment or empty line, skip over */
Chris PeBenito 473ea7
	}
Chris PeBenito 473ea7
	end = strchr(start, ':');
Chris PeBenito 473ea7
	if (!end)
Chris PeBenito 473ea7
		goto err;
Chris PeBenito 473ea7
	*end = 0;
Chris PeBenito 473ea7
	
Chris PeBenito 473ea7
	luser = strdup(start);
Chris PeBenito 473ea7
	if (!luser)
Chris PeBenito 473ea7
		goto err;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	start = end+1;
Chris PeBenito 473ea7
	end = strchr(start, ':');
Chris PeBenito 473ea7
	if (!end) {
Chris PeBenito 473ea7
		if (mls_enabled)
Chris PeBenito 473ea7
			goto err; /* no MLS level and MLS is enabled */
Chris PeBenito 473ea7
		/* MLS is disabled, so :level suffix not required. */
Chris PeBenito 473ea7
		end = start;
Chris PeBenito 473ea7
		while (*end && !isspace(*end))
Chris PeBenito 473ea7
			end++;
Chris PeBenito 473ea7
	}
Chris PeBenito 473ea7
	*end = 0;
Chris PeBenito 473ea7
	
Chris PeBenito 473ea7
	seuser = strdup(start);
Chris PeBenito 473ea7
	if (!seuser)
Chris PeBenito 473ea7
		goto err;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	if (!mls_enabled)
Chris PeBenito 473ea7
		goto out; /* skip any MLS level */
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	start = ++end;
Chris PeBenito 473ea7
	while (*end && !isspace(*end))
Chris PeBenito 473ea7
		end++;
Chris PeBenito 473ea7
	*end = 0;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	level = strdup(start);
Chris PeBenito 473ea7
	if (!level)
Chris PeBenito 473ea7
		goto err;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
out:
Chris PeBenito 473ea7
	free(newbuf);
Chris PeBenito 473ea7
	*luserp = luser;
Chris PeBenito 473ea7
	*seuserp = seuser;
Chris PeBenito 473ea7
	*levelp = level;
Chris PeBenito 473ea7
	return 0;
Chris PeBenito 473ea7
err:
Chris PeBenito 473ea7
	free(newbuf);
Chris PeBenito 473ea7
	free(luser);
Chris PeBenito 473ea7
	free(seuser);
Chris PeBenito 473ea7
	free(level);
Chris PeBenito 473ea7
	return -2; /* error */
Chris PeBenito 473ea7
}
Chris PeBenito 473ea7
Chris PeBenito 473ea7
int require_seusers hidden = 0;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
int getseuserbyname(const char *name, char **r_seuser, char **r_level) {
Chris PeBenito 473ea7
	FILE *cfg=NULL;
Chris PeBenito 473ea7
	size_t size=0;
Chris PeBenito 473ea7
	char *buffer=NULL;
Chris PeBenito 473ea7
	int rc;
Chris PeBenito 473ea7
	unsigned long lineno = 0;
Chris PeBenito 473ea7
	int mls_enabled = is_selinux_mls_enabled();
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	char *username=NULL;
Chris PeBenito 473ea7
        char *seuser=NULL;
Chris PeBenito 473ea7
        char *level=NULL;
Chris PeBenito 473ea7
        char *defaultseuser=NULL;
Chris PeBenito 473ea7
        char *defaultlevel=NULL;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	cfg = fopen(selinux_usersconf_path(), "r");
Chris PeBenito 5a3b36
	if (!cfg)
Chris PeBenito 5a3b36
		goto nomatch;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	while (getline(&buffer, &size, cfg) > 0) {
Chris PeBenito 473ea7
		++lineno;
Chris PeBenito 473ea7
		rc = process_seusers(buffer, &username, &seuser, &level, mls_enabled);
Chris PeBenito 473ea7
		if (rc == -1)
Chris PeBenito 473ea7
			continue; /* comment, skip */
Chris PeBenito 473ea7
		if (rc == -2) {
Chris PeBenito 473ea7
			fprintf(stderr, "%s:  error on line %lu, skipping...\n",
Chris PeBenito 473ea7
				selinux_usersconf_path(), lineno);
Chris PeBenito 473ea7
			continue;
Chris PeBenito 473ea7
		}
Chris PeBenito 473ea7
Chris PeBenito 473ea7
		if (!strcmp(username, name))
Chris PeBenito 473ea7
			break;
Chris PeBenito 473ea7
Chris PeBenito 473ea7
		if (!defaultseuser && !strcmp(username,"default")) {
Chris PeBenito 473ea7
			free(username);
Chris PeBenito 473ea7
			defaultseuser = seuser;
Chris PeBenito 473ea7
			defaultlevel = level;
Chris PeBenito 473ea7
		} else {
Chris PeBenito 473ea7
			free(username);
Chris PeBenito 473ea7
			free(seuser);
Chris PeBenito 473ea7
			free(level);
Chris PeBenito 473ea7
		}
Chris PeBenito 473ea7
		seuser=NULL;
Chris PeBenito 473ea7
	}
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	if (buffer) 
Chris PeBenito 473ea7
		free(buffer);
Chris PeBenito 473ea7
	fclose(cfg);
Chris PeBenito 5a3b36
Chris PeBenito 473ea7
	if (seuser) {
Chris PeBenito 473ea7
		free(username);
Chris PeBenito 473ea7
		free(defaultseuser);
Chris PeBenito 473ea7
		free(defaultlevel);
Chris PeBenito 473ea7
		*r_seuser = seuser;
Chris PeBenito 473ea7
		*r_level = level;
Chris PeBenito 473ea7
		return 0;
Chris PeBenito 473ea7
	}
Chris PeBenito 473ea7
Chris PeBenito 473ea7
	if (defaultseuser) {
Chris PeBenito 473ea7
		*r_seuser = defaultseuser;
Chris PeBenito 473ea7
		*r_level = defaultlevel;
Chris PeBenito 473ea7
		return 0;
Chris PeBenito 473ea7
	}
Chris PeBenito 5a3b36
Chris PeBenito 5a3b36
nomatch:
Chris PeBenito 5a3b36
	if (require_seusers)
Chris PeBenito 5a3b36
		return -1;
Chris PeBenito 5a3b36
Chris PeBenito 5a3b36
	/* Fall back to the Linux username and no level. */
Chris PeBenito 5a3b36
	*r_seuser = strdup(name);
Chris PeBenito 5a3b36
	if (!(*r_seuser))
Chris PeBenito 5a3b36
		return -1;
Chris PeBenito 5a3b36
	*r_level = NULL;
Chris PeBenito 5a3b36
	return 0;
Chris PeBenito 473ea7
}