Home | History | Annotate | Download | only in src
      1 #include "context_internal.h"
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <errno.h>
      6 
      7 #define COMP_USER  0
      8 #define COMP_ROLE  1
      9 #define COMP_TYPE  2
     10 #define COMP_RANGE 3
     11 
     12 typedef struct {
     13 	char *current_str;	/* This is made up-to-date only when needed */
     14 	char *(component[4]);
     15 } context_private_t;
     16 
     17 /*
     18  * Allocate a new context, initialized from str.  There must be 3 or
     19  * 4 colon-separated components and no whitespace in any component other
     20  * than the MLS component.
     21  */
     22 context_t context_new(const char *str)
     23 {
     24 	int i, count;
     25 	errno = 0;
     26 	context_private_t *n =
     27 	    (context_private_t *) malloc(sizeof(context_private_t));
     28 	context_t result = (context_t) malloc(sizeof(context_s_t));
     29 	const char *p, *tok;
     30 
     31 	if (result)
     32 		result->ptr = n;
     33 	else
     34 		free(n);
     35 	if (n == 0 || result == 0) {
     36 		goto err;
     37 	}
     38 	n->current_str = n->component[0] = n->component[1] = n->component[2] =
     39 	    n->component[3] = 0;
     40 	for (i = count = 0, p = str; *p; p++) {
     41 		switch (*p) {
     42 		case ':':
     43 			count++;
     44 			break;
     45 		case '\n':
     46 		case '\t':
     47 		case '\r':
     48 			goto err;	/* sanity check */
     49 		case ' ':
     50 			if (count < 3)
     51 				goto err;	/* sanity check */
     52 		}
     53 	}
     54 	/*
     55 	 * Could be anywhere from 2 - 5
     56 	 * e.g user:role:type to user:role:type:sens1:cata-sens2:catb
     57 	 */
     58 	if (count < 2 || count > 5) {	/* might not have a range */
     59 		goto err;
     60 	}
     61 
     62 	n->component[3] = 0;
     63 	for (i = 0, tok = str; *tok; i++) {
     64 		if (i < 3)
     65 			for (p = tok; *p && *p != ':'; p++) {	/* empty */
     66 		} else {
     67 			/* MLS range is one component */
     68 			for (p = tok; *p; p++) {	/* empty */
     69 			}
     70 		}
     71 		n->component[i] = (char *)malloc(p - tok + 1);
     72 		if (n->component[i] == 0)
     73 			goto err;
     74 		strncpy(n->component[i], tok, p - tok);
     75 		n->component[i][p - tok] = '\0';
     76 		tok = *p ? p + 1 : p;
     77 	}
     78 	return result;
     79       err:
     80 	if (errno == 0) errno = EINVAL;
     81 	context_free(result);
     82 	return 0;
     83 }
     84 
     85 hidden_def(context_new)
     86 
     87 static void conditional_free(char **v)
     88 {
     89 	if (*v) {
     90 		free(*v);
     91 	}
     92 	*v = 0;
     93 }
     94 
     95 /*
     96  * free all storage used by a context.  Safe to call with
     97  * null pointer.
     98  */
     99 void context_free(context_t context)
    100 {
    101 	context_private_t *n;
    102 	int i;
    103 	if (context) {
    104 		n = context->ptr;
    105 		if (n) {
    106 			conditional_free(&n->current_str);
    107 			for (i = 0; i < 4; i++) {
    108 				conditional_free(&n->component[i]);
    109 			}
    110 			free(n);
    111 		}
    112 		free(context);
    113 	}
    114 }
    115 
    116 hidden_def(context_free)
    117 
    118 /*
    119  * Return a pointer to the string value of the context.
    120  */
    121 char *context_str(context_t context)
    122 {
    123 	context_private_t *n = context->ptr;
    124 	int i;
    125 	size_t total = 0;
    126 	conditional_free(&n->current_str);
    127 	for (i = 0; i < 4; i++) {
    128 		if (n->component[i]) {
    129 			total += strlen(n->component[i]) + 1;
    130 		}
    131 	}
    132 	n->current_str = malloc(total);
    133 	if (n->current_str != 0) {
    134 		char *cp = n->current_str;
    135 
    136 		cp = stpcpy(cp, n->component[0]);
    137 		for (i = 1; i < 4; i++) {
    138 			if (n->component[i]) {
    139 				*cp++ = ':';
    140 				cp = stpcpy(cp, n->component[i]);
    141 			}
    142 		}
    143 	}
    144 	return n->current_str;
    145 }
    146 
    147 hidden_def(context_str)
    148 
    149 /* Returns nonzero iff failed */
    150 static int set_comp(context_private_t * n, int idx, const char *str)
    151 {
    152 	char *t = NULL;
    153 	const char *p;
    154 	if (str) {
    155 		t = (char *)malloc(strlen(str) + 1);
    156 		if (!t) {
    157 			return 1;
    158 		}
    159 		for (p = str; *p; p++) {
    160 			if (*p == '\t' || *p == '\n' || *p == '\r' ||
    161 			    ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
    162 				free(t);
    163 				errno = EINVAL;
    164 				return 1;
    165 			}
    166 		}
    167 		strcpy(t, str);
    168 	}
    169 	conditional_free(&n->component[idx]);
    170 	n->component[idx] = t;
    171 	return 0;
    172 }
    173 
    174 #define def_get(name,tag) \
    175 const char * context_ ## name ## _get(context_t context) \
    176 { \
    177         context_private_t *n = context->ptr; \
    178         return n->component[tag]; \
    179 } \
    180 hidden_def(context_ ## name ## _get)
    181 
    182 def_get(type, COMP_TYPE)
    183     def_get(user, COMP_USER)
    184     def_get(range, COMP_RANGE)
    185     def_get(role, COMP_ROLE)
    186 #define def_set(name,tag) \
    187 int context_ ## name ## _set(context_t context, const char* str) \
    188 { \
    189         return set_comp(context->ptr,tag,str);\
    190 } \
    191 hidden_def(context_ ## name ## _set)
    192     def_set(type, COMP_TYPE)
    193     def_set(role, COMP_ROLE)
    194     def_set(user, COMP_USER)
    195     def_set(range, COMP_RANGE)
    196