/*
 * String representation support for classes and permissions.
 */
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include "selinux_internal.h"
#include "policy.h"
#include "mapping.h"

#define MAXVECTORS 8*sizeof(access_vector_t)

struct discover_class_node {
	char *name;
	security_class_t value;
	char **perms;

	struct discover_class_node *next;
};

static struct discover_class_node *discover_class_cache = NULL;

static struct discover_class_node * get_class_cache_entry_name(const char *s)
{
	struct discover_class_node *node = discover_class_cache;

	for (; node != NULL && strcmp(s,node->name) != 0; node = node->next);

	return node;
}

static struct discover_class_node * get_class_cache_entry_value(security_class_t c)
{
	struct discover_class_node *node = discover_class_cache;

	for (; node != NULL && c != node->value; node = node->next);

	return node;
}

static struct discover_class_node * discover_class(const char *s)
{
	int fd, ret;
	char path[PATH_MAX];
	char buf[20];
	DIR *dir;
	struct dirent *dentry;
	size_t i;

	struct discover_class_node *node;

	if (!selinux_mnt) {
		errno = ENOENT;
		return NULL;
	}

	/* allocate a node */
	node = malloc(sizeof(struct discover_class_node));
	if (node == NULL)
		return NULL;

	/* allocate array for perms */
	node->perms = calloc(MAXVECTORS,sizeof(char*));
	if (node->perms == NULL)
		goto err1;

	/* load up the name */
	node->name = strdup(s);
	if (node->name == NULL)
		goto err2;

	/* load up class index */
	snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s);
	fd = open(path, O_RDONLY | O_CLOEXEC);
	if (fd < 0)
		goto err3;

	memset(buf, 0, sizeof(buf));
	ret = read(fd, buf, sizeof(buf) - 1);
	close(fd);
	if (ret < 0)
		goto err3;

	if (sscanf(buf, "%hu", &node->value) != 1)
		goto err3;

	/* load up permission indices */
	snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s);
	dir = opendir(path);
	if (dir == NULL)
		goto err3;

	dentry = readdir(dir);
	while (dentry != NULL) {
		unsigned int value;
		struct stat m;

		snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name);
		fd = open(path, O_RDONLY | O_CLOEXEC);
		if (fd < 0)
			goto err4;

		if (fstat(fd, &m) < 0) {
			close(fd);
			goto err4;
		}

		if (m.st_mode & S_IFDIR) {
			close(fd);
			dentry = readdir(dir);
			continue;
		}

		memset(buf, 0, sizeof(buf));
		ret = read(fd, buf, sizeof(buf) - 1);
		close(fd);
		if (ret < 0)
			goto err4;

		if (sscanf(buf, "%u", &value) != 1)
			goto err4;

		if (value == 0 || value > MAXVECTORS)
			goto err4;

		node->perms[value-1] = strdup(dentry->d_name);
		if (node->perms[value-1] == NULL)
			goto err4;

		dentry = readdir(dir);
	}
	closedir(dir);

	node->next = discover_class_cache;
	discover_class_cache = node;

	return node;

err4:
	closedir(dir);
	for (i = 0; i < MAXVECTORS; i++)
		free(node->perms[i]);
err3:
	free(node->name);
err2:
	free(node->perms);
err1:
	free(node);
	return NULL;
}

void selinux_flush_class_cache(void)
{
	struct discover_class_node *cur = discover_class_cache, *prev = NULL;
	size_t i;

	while (cur != NULL) {
		free(cur->name);

		for (i = 0; i < MAXVECTORS; i++)
			free(cur->perms[i]);

		free(cur->perms);

		prev = cur;
		cur = cur->next;

		free(prev);
	}

	discover_class_cache = NULL;
}

hidden_def(selinux_flush_class_cache)

security_class_t string_to_security_class(const char *s)
{
	struct discover_class_node *node;

	node = get_class_cache_entry_name(s);
	if (node == NULL) {
		node = discover_class(s);

		if (node == NULL) {
			errno = EINVAL;
			return 0;
		}
	}

	return map_class(node->value);
}

security_class_t mode_to_security_class(mode_t m) {

	if (S_ISREG(m))
		return string_to_security_class("file");
	if (S_ISDIR(m))
		return string_to_security_class("dir");
	if (S_ISCHR(m))
		return string_to_security_class("chr_file");
	if (S_ISBLK(m))
		return string_to_security_class("blk_file");
	if (S_ISFIFO(m))
		return string_to_security_class("fifo_file");
	if (S_ISLNK(m))
		return string_to_security_class("lnk_file");
	if (S_ISSOCK(m))
		return string_to_security_class("sock_file");

	errno = EINVAL;
	return 0;
}

access_vector_t string_to_av_perm(security_class_t tclass, const char *s)
{
	struct discover_class_node *node;
	security_class_t kclass = unmap_class(tclass);

	node = get_class_cache_entry_value(kclass);
	if (node != NULL) {
		size_t i;
		for (i = 0; i < MAXVECTORS && node->perms[i] != NULL; i++)
			if (strcmp(node->perms[i],s) == 0)
				return map_perm(tclass, 1<<i);
	}

	errno = EINVAL;
	return 0;
}

const char *security_class_to_string(security_class_t tclass)
{
	struct discover_class_node *node;

	tclass = unmap_class(tclass);

	node = get_class_cache_entry_value(tclass);
	if (node == NULL)
		return NULL;
	else
		return node->name;
}

const char *security_av_perm_to_string(security_class_t tclass,
				       access_vector_t av)
{
	struct discover_class_node *node;
	size_t i;

	av = unmap_perm(tclass, av);
	tclass = unmap_class(tclass);

	node = get_class_cache_entry_value(tclass);
	if (av && node)
		for (i = 0; i<MAXVECTORS; i++)
			if ((1<<i) & av)
				return node->perms[i];

	return NULL;
}

int security_av_string(security_class_t tclass, access_vector_t av, char **res)
{
	unsigned int i;
	size_t len = 5;
	access_vector_t tmp = av;
	int rc = 0;
	const char *str;
	char *ptr;

	/* first pass computes the required length */
	for (i = 0; tmp; tmp >>= 1, i++) {
		if (tmp & 1) {
			str = security_av_perm_to_string(tclass, av & (1<<i));
			if (str)
				len += strlen(str) + 1;
		}
	}

	*res = malloc(len);
	if (!*res) {
		rc = -1;
		goto out;
	}

	/* second pass constructs the string */
	tmp = av;
	ptr = *res;

	if (!av) {
		sprintf(ptr, "null");
		goto out;
	}

	ptr += sprintf(ptr, "{ ");
	for (i = 0; tmp; tmp >>= 1, i++) {
		if (tmp & 1) {
			str = security_av_perm_to_string(tclass, av & (1<<i));
			if (str)
				ptr += sprintf(ptr, "%s ", str);
		}
	}
	sprintf(ptr, "}");
out:
	return rc;
}

void print_access_vector(security_class_t tclass, access_vector_t av)
{
	const char *permstr;
	access_vector_t bit = 1;

	if (av == 0) {
		printf(" null");
		return;
	}

	printf(" {");

	while (av) {
		if (av & bit) {
			permstr = security_av_perm_to_string(tclass, bit);
			if (!permstr)
				break;
			printf(" %s", permstr);
			av &= ~bit;
		}
		bit <<= 1;
	}

	if (av)
		printf(" 0x%x", av);
	printf(" }");
}
