aboutsummaryrefslogtreecommitdiffstats
path: root/libselinux/src/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'libselinux/src/context.c')
-rw-r--r--libselinux/src/context.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/libselinux/src/context.c b/libselinux/src/context.c
new file mode 100644
index 00000000..81641041
--- /dev/null
+++ b/libselinux/src/context.c
@@ -0,0 +1,193 @@
+#include "context_internal.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#define COMP_USER 0
+#define COMP_ROLE 1
+#define COMP_TYPE 2
+#define COMP_RANGE 3
+
+typedef struct {
+ char *current_str; /* This is made up-to-date only when needed */
+ char *(component[4]);
+} context_private_t;
+
+/*
+ * Allocate a new context, initialized from str. There must be 3 or
+ * 4 colon-separated components and no whitespace in any component other
+ * than the MLS component.
+ */
+context_t context_new(const char *str)
+{
+ int i, count;
+ context_private_t *n =
+ (context_private_t *) malloc(sizeof(context_private_t));
+ context_t result = (context_t) malloc(sizeof(context_s_t));
+ const char *p, *tok;
+
+ if (result)
+ result->ptr = n;
+ else
+ free(n);
+ if (n == 0 || result == 0) {
+ goto err;
+ }
+ n->current_str = n->component[0] = n->component[1] = n->component[2] =
+ n->component[3] = 0;
+ for (i = count = 0, p = str; *p; p++) {
+ switch (*p) {
+ case ':':
+ count++;
+ break;
+ case '\n':
+ case '\t':
+ case '\r':
+ goto err; /* sanity check */
+ case ' ':
+ if (count < 3)
+ goto err; /* sanity check */
+ }
+ }
+ /*
+ * Could be anywhere from 2 - 5
+ * e.g user:role:type to user:role:type:sens1:cata-sens2:catb
+ */
+ if (count < 2 || count > 5) { /* might not have a range */
+ goto err;
+ }
+
+ n->component[3] = 0;
+ for (i = 0, tok = str; *tok; i++) {
+ if (i < 3)
+ for (p = tok; *p && *p != ':'; p++) { /* empty */
+ } else {
+ /* MLS range is one component */
+ for (p = tok; *p; p++) { /* empty */
+ }
+ }
+ n->component[i] = (char *)malloc(p - tok + 1);
+ if (n->component[i] == 0)
+ goto err;
+ strncpy(n->component[i], tok, p - tok);
+ n->component[i][p - tok] = '\0';
+ tok = *p ? p + 1 : p;
+ }
+ return result;
+ err:
+ context_free(result);
+ return 0;
+}
+
+hidden_def(context_new)
+
+static void conditional_free(char **v)
+{
+ if (*v) {
+ free(*v);
+ }
+ *v = 0;
+}
+
+/*
+ * free all storage used by a context. Safe to call with
+ * null pointer.
+ */
+void context_free(context_t context)
+{
+ context_private_t *n;
+ int i;
+ if (context) {
+ n = context->ptr;
+ if (n) {
+ conditional_free(&n->current_str);
+ for (i = 0; i < 4; i++) {
+ conditional_free(&n->component[i]);
+ }
+ free(n);
+ }
+ free(context);
+ }
+}
+
+hidden_def(context_free)
+
+/*
+ * Return a pointer to the string value of the context.
+ */
+char *context_str(context_t context)
+{
+ context_private_t *n = context->ptr;
+ int i;
+ size_t total = 0;
+ conditional_free(&n->current_str);
+ for (i = 0; i < 4; i++) {
+ if (n->component[i]) {
+ total += strlen(n->component[i]) + 1;
+ }
+ }
+ n->current_str = malloc(total);
+ if (n->current_str != 0) {
+ char *cp = n->current_str;
+
+ cp = stpcpy(cp, n->component[0]);
+ for (i = 1; i < 4; i++) {
+ if (n->component[i]) {
+ *cp++ = ':';
+ cp = stpcpy(cp, n->component[i]);
+ }
+ }
+ }
+ return n->current_str;
+}
+
+hidden_def(context_str)
+
+/* Returns nonzero iff failed */
+static int set_comp(context_private_t * n, int idx, const char *str)
+{
+ char *t = NULL;
+ const char *p;
+ if (str) {
+ t = (char *)malloc(strlen(str) + 1);
+ if (!t) {
+ return 1;
+ }
+ for (p = str; *p; p++) {
+ if (*p == '\t' || *p == '\n' || *p == '\r' ||
+ ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
+ free(t);
+ errno = EINVAL;
+ return 1;
+ }
+ }
+ strcpy(t, str);
+ }
+ conditional_free(&n->component[idx]);
+ n->component[idx] = t;
+ return 0;
+}
+
+#define def_get(name,tag) \
+const char * context_ ## name ## _get(context_t context) \
+{ \
+ context_private_t *n = context->ptr; \
+ return n->component[tag]; \
+} \
+hidden_def(context_ ## name ## _get)
+
+def_get(type, COMP_TYPE)
+ def_get(user, COMP_USER)
+ def_get(range, COMP_RANGE)
+ def_get(role, COMP_ROLE)
+#define def_set(name,tag) \
+int context_ ## name ## _set(context_t context, const char* str) \
+{ \
+ return set_comp(context->ptr,tag,str);\
+} \
+hidden_def(context_ ## name ## _set)
+ def_set(type, COMP_TYPE)
+ def_set(role, COMP_ROLE)
+ def_set(user, COMP_USER)
+ def_set(range, COMP_RANGE)