summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEamon Walsh <ewalsh@tycho.nsa.gov>2008-12-03 17:55:38 -0500
committerEamon Walsh <ewalsh@tycho.nsa.gov>2008-12-03 18:03:44 -0500
commit054e5880666c93a2f7ff1c1600c9e63134ac65a5 (patch)
tree4090acb74e443aa6b8525d9c49f8333e6df8ac02
parente6a37c49a5618ee1dcb27ae6e4b839457bb04eeb (diff)
New branch 'color-ewalsh'.
Contains proposed color translation support by Eamon Walsh.
-rw-r--r--src/Makefile2
-rw-r--r--src/mcscolor.c258
-rw-r--r--src/mcstransd.c92
3 files changed, 296 insertions, 56 deletions
diff --git a/src/Makefile b/src/Makefile
index 4b034db..fb44490 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -18,7 +18,7 @@ PREFIX ?= $(DESTDIR)/usr
SBINDIR ?= $(DESTDIR)/sbin
INITDIR ?= $(DESTDIR)/etc/rc.d/init.d
-PROG_SRC=mcstrans.c mcstransd.c mls_level.c
+PROG_SRC=mcstrans.c mcscolor.c mcstransd.c mls_level.c
PROG_OBJS= $(patsubst %.c,%.o,$(PROG_SRC))
PROG=mcstransd
INITSCRIPT=mcstrans
diff --git a/src/mcscolor.c b/src/mcscolor.c
new file mode 100644
index 0000000..705006e
--- /dev/null
+++ b/src/mcscolor.c
@@ -0,0 +1,258 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <ctype.h>
+#include <alloca.h>
+#include <fnmatch.h>
+#include <syslog.h>
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include "mcstrans.h"
+
+/* Define data structures */
+typedef struct secolor {
+ uint32_t fg;
+ uint32_t bg;
+} secolor_t;
+
+typedef struct setab {
+ char *pattern;
+ secolor_t color;
+ struct setab *next;
+} setab_t;
+
+#define COLOR_USER 0
+#define COLOR_ROLE 1
+#define COLOR_TYPE 2
+#define COLOR_LEVEL 3
+#define COLOR_SENS 4
+#define COLOR_RANGE 5
+#define N_RULES 6
+#define N_COLOR 5
+
+static char *rules[] = { "user", "role", "type",
+ "level", "category", "range" };
+
+static setab_t *clist[N_RULES];
+static setab_t *cend[N_RULES];
+
+void finish_context_colors(void) {
+ setab_t *cur, *next;
+ unsigned i;
+
+ for (i = 0; i < N_RULES; i++) {
+ cur = clist[i];
+ while(cur) {
+ next = cur->next;
+ free(cur->pattern);
+ free(cur);
+ cur = next;
+ }
+ clist[i] = cend[i] = NULL;
+ }
+}
+
+static void print_colors(void) {
+ setab_t *ptr;
+ unsigned i;
+
+ for (i = 0; i < N_RULES; i++) {
+ ptr = clist[i];
+ while (ptr) {
+ printf("%s %s->(fg:%x, bg:%x)\n", rules[i],
+ ptr->pattern, ptr->color.fg, ptr->color.bg);
+ ptr = ptr->next;
+ }
+ }
+}
+
+static const secolor_t *find_color(int idx, const char *raw) {
+ setab_t *ptr = clist[idx];
+
+ if (raw)
+ while(ptr) {
+ if (fnmatch(ptr->pattern, raw, 0) == 0)
+ return &ptr->color;
+ ptr = ptr->next;
+ }
+
+ return NULL;
+}
+
+static int add_secolor(int idx, char *pattern, uint32_t fg, uint32_t bg) {
+ setab_t *cptr;
+
+ cptr = calloc(1, sizeof(setab_t));
+ if (!cptr) return -1;
+
+ cptr->pattern = strdup(pattern);
+ if (!cptr->pattern) {
+ free(cptr);
+ return -1;
+ }
+
+ cptr->color.fg = fg & 0xffffff;
+ cptr->color.bg = bg & 0xffffff;
+
+ if (cend[idx]) {
+ cend[idx]->next = cptr;
+ cend[idx] = cptr;
+ } else {
+ clist[idx] = cptr;
+ cend[idx] = cptr;
+ }
+ return 0;
+}
+
+/* Process line from color file.
+ May modify the data pointed to by the buffer paremeter */
+static int process_color(char *buffer, int line) {
+ char rule[10], pat[256];
+ uint32_t i, fg, bg;
+ int ret;
+
+ while(isspace(*buffer))
+ buffer++;
+ if(buffer[0] == '#' || buffer[0] == '\0') return 0;
+
+ ret = sscanf(buffer, "%8s %255s = %x %x", rule, pat, &fg, &bg);
+ if (ret == 4)
+ for (i = 0; i < N_RULES; i++)
+ if (!strcmp(rule, rules[i]))
+ return add_secolor(i, pat, fg, bg);
+
+ syslog(LOG_WARNING, "Line %d of secolors file is invalid.", line);
+ return 0;
+}
+
+/* Read in color file.
+ */
+int init_colors(void) {
+ FILE *cfg = NULL;
+ size_t size = 0;
+ char *buffer = NULL;
+ int line = 0;
+
+ cfg = fopen("/etc/selinux/refpolicy/secolor.conf", "r");
+ if (!cfg) return 1;
+
+ __fsetlocking(cfg, FSETLOCKING_BYCALLER);
+ while (getline(&buffer, &size, cfg) > 0) {
+ if( process_color(buffer, ++line) < 0 ) break;
+ }
+ free(buffer);
+
+ fclose(cfg);
+ return 0;
+}
+
+static const unsigned precedence[N_COLOR][N_COLOR] = {
+ { COLOR_ROLE, COLOR_TYPE, COLOR_RANGE, COLOR_LEVEL, COLOR_SENS },
+ { COLOR_USER, COLOR_TYPE, COLOR_RANGE, COLOR_LEVEL, COLOR_SENS },
+ { COLOR_USER, COLOR_ROLE, COLOR_RANGE, COLOR_LEVEL, COLOR_SENS },
+ { COLOR_RANGE, COLOR_SENS, COLOR_USER, COLOR_ROLE, COLOR_TYPE },
+ { COLOR_RANGE, COLOR_LEVEL, COLOR_USER, COLOR_ROLE, COLOR_TYPE }
+};
+
+static const secolor_t default_color = { 0x000000, 0xffffff };
+
+static int parse_context(const security_context_t raw, char **components)
+{
+ context_t con;
+ char *range, *tmp;
+
+ components[COLOR_LEVEL] = NULL;
+ components[COLOR_SENS] = NULL;
+ components[COLOR_RANGE] = NULL;
+
+ con = context_new(raw);
+ if (!con)
+ return -1;
+
+ components[COLOR_USER] = (char *)context_user_get(con);
+ components[COLOR_ROLE] = (char *)context_role_get(con);
+ components[COLOR_TYPE] = (char *)context_type_get(con);
+
+ range = (char *)context_range_get(con);
+ if (range) {
+ components[COLOR_RANGE] = strdup(range);
+
+ tmp = strchr(range, '-');
+ if (tmp)
+ *tmp = '\0';
+ tmp = strchr(range, ':');
+ if (tmp) {
+ *tmp = '\0';
+ components[COLOR_SENS] = strdup(tmp + 1);
+ } else
+ components[COLOR_SENS] = strdup("");
+
+ components[COLOR_LEVEL] = strdup(range);
+ }
+
+ context_free(con);
+ return 0;
+}
+
+static void free_context(char **components)
+{
+ free(components[COLOR_RANGE]);
+ free(components[COLOR_LEVEL]);
+ free(components[COLOR_SENS]);
+}
+
+/* Look up colors.
+ */
+int raw_color(const security_context_t raw, char **color_str) {
+ uint32_t i, j, mask = 0;
+ const secolor_t *items[N_RULES];
+ char *result, *components[N_RULES];
+ char buf[20];
+ int rc = -1;
+
+ /* parse context and allocate memory */
+ if (parse_context(raw, components) < 0)
+ goto out;
+
+ result = malloc(N_COLOR * sizeof(buf));
+ if (!result)
+ goto out;
+ result[0] = '\0';
+
+ /* find colors for which we have a match */
+ for (i = 0; i < N_COLOR; i++) {
+ items[i] = find_color(i, components[i]);
+ if (items[i])
+ mask |= (1 << i);
+ }
+ if (mask == 0) {
+ items[0] = &default_color;
+ mask = 1;
+ }
+
+ /* propagate colors according to the precedence rules */
+ for (i = 0; i < N_COLOR; i++)
+ if (!(mask & (1 << i)))
+ for (j = 0; j < N_COLOR; j++)
+ if (mask & (1 << precedence[i][j])) {
+ items[i] = items[precedence[i][j]];
+ break;
+ }
+
+ /* print results into a big long string */
+ for (i = 0; i < N_COLOR; i++) {
+ snprintf(buf, sizeof(buf), "#%06x #%06x ",
+ items[i]->fg, items[i]->bg);
+ strncat(result, buf, sizeof(buf));
+ }
+
+ *color_str = result;
+ rc = 0;
+out:
+ free_context(components);
+ return rc;
+}
diff --git a/src/mcstransd.c b/src/mcstransd.c
index 726b851..4a3feaf 100644
--- a/src/mcstransd.c
+++ b/src/mcstransd.c
@@ -33,6 +33,7 @@
#define SETRANS_INIT 1
#define RAW_TO_TRANS_CONTEXT 2
#define TRANS_TO_RAW_CONTEXT 3
+#define RAW_CONTEXT_TO_COLOR 4
#define MAX_DATA_BUF 4096
#define MAX_DESCRIPTORS 8192
@@ -48,6 +49,10 @@ extern void finish_context_translations(void);
extern int trans_context(const security_context_t, security_context_t *);
extern int untrans_context(const security_context_t, security_context_t *);
+extern int init_colors(void);
+extern void finish_context_colors(void);
+extern int raw_color(const security_context_t, char **);
+
#define SETRANSD_PATHNAME "/sbin/mcstransd"
/* name of program (for error messages) */
@@ -60,6 +65,7 @@ static void cleanup_exit(int ret) __attribute__ ((noreturn));
static void
cleanup_exit(int ret)
{
+ finish_context_colors();
finish_context_translations();
if (sockfd >=0)
(void)unlink(SETRANS_UNIX_SOCKET);
@@ -76,42 +82,6 @@ static __attribute__((noreturn)) void clean_exit(void)
cleanup_exit(0);
}
-/*
- * Convert raw label portion of a security context to translated label
- * Returns: 0 on success, 1 on failure
- */
-static int
-raw_to_trans_context(char *in, char **out, char *UNUSED(pcon))
-{
- log_debug("raw_to_trans_context=%s\n", in);
- *out = NULL;
-
- /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
- * (in "in").
- */
-
- return trans_context(in, out);
-}
-
-
-/*
- * Convert translated label of a security context to raw label
- * Returns: 0 on success, 1 on failure
- */
-static int
-trans_to_raw_context(char *in, char **out, char *UNUSED(pcon))
-{
- log_debug("trans_to_raw_context=%s\n", in);
-
- *out = NULL;
-
- /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
- * (in "in").
- */
-
- return untrans_context(in, out);
-}
-
static int
send_response(int fd, uint32_t function, char *data, int32_t ret_val)
{
@@ -194,41 +164,44 @@ process_request(int fd, uint32_t function, char *data1, char *UNUSED(data2))
char *peercon = NULL;
int ret;
+ ret = get_peer_con(fd, &peercon);
+ if (ret)
+ return ret;
+
+ /* TODO: Check if MLS clearance (in peercon) dominates the MLS label
+ * (in the request input).
+ */
+
switch (function) {
case SETRANS_INIT:
result = 0;
ret = send_response(fd, function, NULL, result);
break;
case RAW_TO_TRANS_CONTEXT:
- ret = get_peer_con(fd, &peercon);
- if (ret)
- return ret;
- result = raw_to_trans_context(data1, &out, peercon);
- if (result) {
- pid_t pid = 0;
- get_peer_pid(fd, &pid);
- syslog(LOG_ERR, "Invalid raw_to_trans_context request from=%u", pid);
- }
+ result = trans_context(data1, &out);
ret = send_response(fd, function, out, result);
break;
case TRANS_TO_RAW_CONTEXT:
- ret = get_peer_con(fd, &peercon);
- if (ret)
- return ret;
- result = trans_to_raw_context(data1, &out, peercon);
- if (result) {
- pid_t pid = 0;
- get_peer_pid(fd, &pid);
- syslog(LOG_ERR, "Invalid trans_to_raw_context request from=%u", pid);
- }
+ result = untrans_context(data1, &out);
+ ret = send_response(fd, function, out, result);
+ break;
+ case RAW_CONTEXT_TO_COLOR:
+ result = raw_color(data1, &out);
ret = send_response(fd, function, out, result);
break;
default:
- syslog(LOG_ERR, "Invalid request func=%d", function);
+ result = -1;
ret = -1;
break;
}
+ if (result) {
+ pid_t pid = 0;
+ get_peer_pid(fd, &pid);
+ syslog(LOG_ERR, "Invalid request func=%d from=%u",
+ function, pid);
+ }
+
free(out);
freecon(peercon);
@@ -446,11 +419,16 @@ process_connections(void)
while (1) {
if (restart_daemon) {
syslog(LOG_NOTICE, "Reload Translations");
+ finish_context_colors();
finish_context_translations();
if (init_translations()) {
syslog(LOG_ERR, "Failed to initialize label translations");
cleanup_exit(1);
}
+ if (init_colors()) {
+ syslog(LOG_ERR, "Failed to initialize color translations");
+ cleanup_exit(1);
+ }
restart_daemon = 0;
}
@@ -497,6 +475,10 @@ initialize(void)
syslog(LOG_ERR, "Failed to initialize label translations");
cleanup_exit(1);
}
+ if (init_colors()) {
+ syslog(LOG_ERR, "Failed to initialize color translations");
+ cleanup_exit(1);
+ }
/* the socket will be unlinked when the daemon terminates */
act.sa_handler = sigterm_handler;