diff options
author | Eamon Walsh <ewalsh@tycho.nsa.gov> | 2008-12-03 17:55:38 -0500 |
---|---|---|
committer | Eamon Walsh <ewalsh@tycho.nsa.gov> | 2008-12-03 18:03:44 -0500 |
commit | 054e5880666c93a2f7ff1c1600c9e63134ac65a5 (patch) | |
tree | 4090acb74e443aa6b8525d9c49f8333e6df8ac02 | |
parent | e6a37c49a5618ee1dcb27ae6e4b839457bb04eeb (diff) |
New branch 'color-ewalsh'.
Contains proposed color translation support by Eamon Walsh.
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/mcscolor.c | 258 | ||||
-rw-r--r-- | src/mcstransd.c | 92 |
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; |