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