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 		strcpy(cp, n->component[0]);
    137 		cp += strlen(cp);
    138 		for (i = 1; i < 4; i++) {
    139 			if (n->component[i]) {
    140 				*cp++ = ':';
    141 				strcpy(cp, n->component[i]);
    142 				cp += strlen(cp);
    143 			}
    144 		}
    145 	}
    146 	return n->current_str;
    147 }
    148 
    149 hidden_def(context_str)
    150 
    151 /* Returns nonzero iff failed */
    152 static int set_comp(context_private_t * n, int idx, const char *str)
    153 {
    154 	char *t = NULL;
    155 	const char *p;
    156 	if (str) {
    157 		t = (char *)malloc(strlen(str) + 1);
    158 		if (!t) {
    159 			return 1;
    160 		}
    161 		for (p = str; *p; p++) {
    162 			if (*p == '\t' || *p == '\n' || *p == '\r' ||
    163 			    ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
    164 				free(t);
    165 				errno = EINVAL;
    166 				return 1;
    167 			}
    168 		}
    169 		strcpy(t, str);
    170 	}
    171 	conditional_free(&n->component[idx]);
    172 	n->component[idx] = t;
    173 	return 0;
    174 }
    175 
    176 #define def_get(name,tag) \
    177 const char * context_ ## name ## _get(context_t context) \
    178 { \
    179         context_private_t *n = context->ptr; \
    180         return n->component[tag]; \
    181 } \
    182 hidden_def(context_ ## name ## _get)
    183 
    184 def_get(type, COMP_TYPE)
    185     def_get(user, COMP_USER)
    186     def_get(range, COMP_RANGE)
    187     def_get(role, COMP_ROLE)
    188 #define def_set(name,tag) \
    189 int context_ ## name ## _set(context_t context, const char* str) \
    190 { \
    191         return set_comp(context->ptr,tag,str);\
    192 } \
    193 hidden_def(context_ ## name ## _set)
    194     def_set(type, COMP_TYPE)
    195     def_set(role, COMP_ROLE)
    196     def_set(user, COMP_USER)
    197     def_set(range, COMP_RANGE)
    198