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