/*
 * sestatus -- displays the status of SELinux
 *
 * Ported to busybox: KaiGai Kohei <kaigai@ak.jp.nec.com>
 *
 * Copyright (C) KaiGai Kohei <kaigai@ak.jp.nec.com>
 *
 * Licensed under GPLv2, see file LICENSE in this source tree.
 */

#include "libbb.h"

extern char *selinux_mnt;

#define OPT_VERBOSE	(1 << 0)
#define OPT_BOOLEAN	(1 << 1)

#define COL_FMT		"%-31s "

static void display_boolean(void)
{
	char **bools;
	int i, active, pending, nbool;

	if (security_get_boolean_names(&bools, &nbool) < 0)
		return;

	puts("\nPolicy booleans:");

	for (i = 0; i < nbool; i++) {
		active = security_get_boolean_active(bools[i]);
		if (active < 0)
			goto skip;
		pending = security_get_boolean_pending(bools[i]);
		if (pending < 0)
			goto skip;
		printf(COL_FMT "%s",
		       bools[i], active == 0 ? "off" : "on");
		if (active != pending)
			printf(" (%sactivate pending)", pending == 0 ? "in" : "");
		bb_putchar('\n');
 skip:
		if (ENABLE_FEATURE_CLEAN_UP)
			free(bools[i]);
	}
	if (ENABLE_FEATURE_CLEAN_UP)
		free(bools);
}

static void read_config(char **pc, int npc, char **fc, int nfc)
{
	char *buf;
	parser_t *parser;
	int pc_ofs = 0, fc_ofs = 0, section = -1;

	pc[0] = fc[0] = NULL;

	parser = config_open("/etc/sestatus.conf");
	while (config_read(parser, &buf, 1, 1, "# \t", PARSE_NORMAL)) {
		if (strcmp(buf, "[process]") == 0) {
			section = 1;
		} else if (strcmp(buf, "[files]") == 0) {
			section = 2;
		} else {
			if (section == 1 && pc_ofs < npc -1) {
				pc[pc_ofs++] = xstrdup(buf);
				pc[pc_ofs] = NULL;
			} else if (section == 2 && fc_ofs < nfc - 1) {
				fc[fc_ofs++] = xstrdup(buf);
				fc[fc_ofs] = NULL;
			}
		}
	}
	config_close(parser);
}

static void display_verbose(void)
{
	security_context_t con, _con;
	char *fc[50], *pc[50], *cterm;
	pid_t *pidList;
	int i;

	read_config(pc, ARRAY_SIZE(pc), fc, ARRAY_SIZE(fc));

	/* process contexts */
	puts("\nProcess contexts:");

	/* current context */
	if (getcon(&con) == 0) {
		printf(COL_FMT "%s\n", "Current context:", con);
		if (ENABLE_FEATURE_CLEAN_UP)
			freecon(con);
	}
	/* /sbin/init context */
	if (getpidcon(1, &con) == 0) {
		printf(COL_FMT "%s\n", "Init context:", con);
		if (ENABLE_FEATURE_CLEAN_UP)
			freecon(con);
	}

	/* [process] context */
	for (i = 0; pc[i] != NULL; i++) {
		pidList = find_pid_by_name(bb_basename(pc[i]));
		if (pidList[0] > 0 && getpidcon(pidList[0], &con) == 0) {
			printf(COL_FMT "%s\n", pc[i], con);
			if (ENABLE_FEATURE_CLEAN_UP)
				freecon(con);
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			free(pidList);
	}

	/* files contexts */
	puts("\nFile contexts:");

	cterm = xmalloc_ttyname(0);
//FIXME: if cterm == NULL, we segfault!??
	puts(cterm);
	if (cterm && lgetfilecon(cterm, &con) >= 0) {
		printf(COL_FMT "%s\n", "Controlling term:", con);
		if (ENABLE_FEATURE_CLEAN_UP)
			freecon(con);
	}

	for (i = 0; fc[i] != NULL; i++) {
		struct stat stbuf;

		if (lgetfilecon(fc[i], &con) < 0)
			continue;
		if (lstat(fc[i], &stbuf) == 0) {
			if (S_ISLNK(stbuf.st_mode)) {
				if (getfilecon(fc[i], &_con) >= 0) {
					printf(COL_FMT "%s -> %s\n", fc[i], _con, con);
					if (ENABLE_FEATURE_CLEAN_UP)
						freecon(_con);
				}
			} else {
				printf(COL_FMT "%s\n", fc[i], con);
			}
		}
		if (ENABLE_FEATURE_CLEAN_UP)
			freecon(con);
	}
}

int sestatus_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int sestatus_main(int argc UNUSED_PARAM, char **argv)
{
	unsigned opts;
	const char *pol_path;
	int rc;

	opt_complementary = "?0";	/* no arguments are required. */
	opts = getopt32(argv, "vb");

	/* SELinux status: line */
	rc = is_selinux_enabled();
	if (rc < 0)
		goto error;
	printf(COL_FMT "%s\n", "SELinux status:",
	       rc == 1 ? "enabled" : "disabled");

	/* SELinuxfs mount: line */
	if (!selinux_mnt)
		goto error;
	printf(COL_FMT "%s\n", "SELinuxfs mount:",
	       selinux_mnt);

	/* Current mode: line */
	rc = security_getenforce();
	if (rc < 0)
		goto error;
	printf(COL_FMT "%s\n", "Current mode:",
	       rc == 0 ? "permissive" : "enforcing");

	/* Mode from config file: line */
	if (selinux_getenforcemode(&rc) != 0)
		goto error;
	printf(COL_FMT "%s\n", "Mode from config file:",
	       rc < 0 ? "disabled" : (rc == 0 ? "permissive" : "enforcing"));

	/* Policy version: line */
	rc = security_policyvers();
	if (rc < 0)
		goto error;
	printf(COL_FMT "%u\n", "Policy version:", rc);

	/* Policy from config file: line */
	pol_path = selinux_policy_root();
	if (!pol_path)
		goto error;
	printf(COL_FMT "%s\n", "Policy from config file:",
	       bb_basename(pol_path));

	if (opts & OPT_BOOLEAN)
		display_boolean();
	if (opts & OPT_VERBOSE)
		display_verbose();

	return 0;

  error:
	bb_perror_msg_and_die("libselinux returns unknown state");
}
