16cd6a6acSopenharmony_ci#include "context_internal.h" 26cd6a6acSopenharmony_ci#include <string.h> 36cd6a6acSopenharmony_ci#include <stdio.h> 46cd6a6acSopenharmony_ci#include <stdlib.h> 56cd6a6acSopenharmony_ci#include <errno.h> 66cd6a6acSopenharmony_ci 76cd6a6acSopenharmony_ci#define COMP_USER 0 86cd6a6acSopenharmony_ci#define COMP_ROLE 1 96cd6a6acSopenharmony_ci#define COMP_TYPE 2 106cd6a6acSopenharmony_ci#define COMP_RANGE 3 116cd6a6acSopenharmony_ci 126cd6a6acSopenharmony_citypedef struct { 136cd6a6acSopenharmony_ci char *current_str; /* This is made up-to-date only when needed */ 146cd6a6acSopenharmony_ci char *(component[4]); 156cd6a6acSopenharmony_ci} context_private_t; 166cd6a6acSopenharmony_ci 176cd6a6acSopenharmony_ci/* 186cd6a6acSopenharmony_ci * Allocate a new context, initialized from str. There must be 3 or 196cd6a6acSopenharmony_ci * 4 colon-separated components and no whitespace in any component other 206cd6a6acSopenharmony_ci * than the MLS component. 216cd6a6acSopenharmony_ci */ 226cd6a6acSopenharmony_cicontext_t context_new(const char *str) 236cd6a6acSopenharmony_ci{ 246cd6a6acSopenharmony_ci int i, count; 256cd6a6acSopenharmony_ci errno = 0; 266cd6a6acSopenharmony_ci context_private_t *n = 276cd6a6acSopenharmony_ci (context_private_t *) malloc(sizeof(context_private_t)); 286cd6a6acSopenharmony_ci context_t result = (context_t) malloc(sizeof(context_s_t)); 296cd6a6acSopenharmony_ci const char *p, *tok; 306cd6a6acSopenharmony_ci 316cd6a6acSopenharmony_ci if (result) 326cd6a6acSopenharmony_ci result->ptr = n; 336cd6a6acSopenharmony_ci else 346cd6a6acSopenharmony_ci free(n); 356cd6a6acSopenharmony_ci if (n == 0 || result == 0) { 366cd6a6acSopenharmony_ci goto err; 376cd6a6acSopenharmony_ci } 386cd6a6acSopenharmony_ci n->current_str = n->component[0] = n->component[1] = n->component[2] = 396cd6a6acSopenharmony_ci n->component[3] = 0; 406cd6a6acSopenharmony_ci for (count = 0, p = str; *p; p++) { 416cd6a6acSopenharmony_ci switch (*p) { 426cd6a6acSopenharmony_ci case ':': 436cd6a6acSopenharmony_ci count++; 446cd6a6acSopenharmony_ci break; 456cd6a6acSopenharmony_ci case '\n': 466cd6a6acSopenharmony_ci case '\t': 476cd6a6acSopenharmony_ci case '\r': 486cd6a6acSopenharmony_ci goto err; /* sanity check */ 496cd6a6acSopenharmony_ci case ' ': 506cd6a6acSopenharmony_ci if (count < 3) 516cd6a6acSopenharmony_ci goto err; /* sanity check */ 526cd6a6acSopenharmony_ci } 536cd6a6acSopenharmony_ci } 546cd6a6acSopenharmony_ci /* 556cd6a6acSopenharmony_ci * Could be anywhere from 2 - 5 566cd6a6acSopenharmony_ci * e.g user:role:type to user:role:type:sens1:cata-sens2:catb 576cd6a6acSopenharmony_ci */ 586cd6a6acSopenharmony_ci if (count < 2 || count > 5) { /* might not have a range */ 596cd6a6acSopenharmony_ci goto err; 606cd6a6acSopenharmony_ci } 616cd6a6acSopenharmony_ci 626cd6a6acSopenharmony_ci n->component[3] = 0; 636cd6a6acSopenharmony_ci for (i = 0, tok = str; *tok; i++) { 646cd6a6acSopenharmony_ci if (i < 3) 656cd6a6acSopenharmony_ci for (p = tok; *p && *p != ':'; p++) { /* empty */ 666cd6a6acSopenharmony_ci } else { 676cd6a6acSopenharmony_ci /* MLS range is one component */ 686cd6a6acSopenharmony_ci for (p = tok; *p; p++) { /* empty */ 696cd6a6acSopenharmony_ci } 706cd6a6acSopenharmony_ci } 716cd6a6acSopenharmony_ci n->component[i] = strndup(tok, p - tok); 726cd6a6acSopenharmony_ci if (n->component[i] == 0) 736cd6a6acSopenharmony_ci goto err; 746cd6a6acSopenharmony_ci tok = *p ? p + 1 : p; 756cd6a6acSopenharmony_ci } 766cd6a6acSopenharmony_ci return result; 776cd6a6acSopenharmony_ci err: 786cd6a6acSopenharmony_ci if (errno == 0) errno = EINVAL; 796cd6a6acSopenharmony_ci context_free(result); 806cd6a6acSopenharmony_ci return 0; 816cd6a6acSopenharmony_ci} 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_ci 846cd6a6acSopenharmony_cistatic void conditional_free(char **v) 856cd6a6acSopenharmony_ci{ 866cd6a6acSopenharmony_ci if (*v) { 876cd6a6acSopenharmony_ci free(*v); 886cd6a6acSopenharmony_ci } 896cd6a6acSopenharmony_ci *v = 0; 906cd6a6acSopenharmony_ci} 916cd6a6acSopenharmony_ci 926cd6a6acSopenharmony_ci/* 936cd6a6acSopenharmony_ci * free all storage used by a context. Safe to call with 946cd6a6acSopenharmony_ci * null pointer. 956cd6a6acSopenharmony_ci */ 966cd6a6acSopenharmony_civoid context_free(context_t context) 976cd6a6acSopenharmony_ci{ 986cd6a6acSopenharmony_ci context_private_t *n; 996cd6a6acSopenharmony_ci int i; 1006cd6a6acSopenharmony_ci if (context) { 1016cd6a6acSopenharmony_ci n = context->ptr; 1026cd6a6acSopenharmony_ci if (n) { 1036cd6a6acSopenharmony_ci conditional_free(&n->current_str); 1046cd6a6acSopenharmony_ci for (i = 0; i < 4; i++) { 1056cd6a6acSopenharmony_ci conditional_free(&n->component[i]); 1066cd6a6acSopenharmony_ci } 1076cd6a6acSopenharmony_ci free(n); 1086cd6a6acSopenharmony_ci } 1096cd6a6acSopenharmony_ci free(context); 1106cd6a6acSopenharmony_ci } 1116cd6a6acSopenharmony_ci} 1126cd6a6acSopenharmony_ci 1136cd6a6acSopenharmony_ci 1146cd6a6acSopenharmony_ci/* 1156cd6a6acSopenharmony_ci * Return a pointer to the string value of the context. 1166cd6a6acSopenharmony_ci */ 1176cd6a6acSopenharmony_ciconst char *context_str(context_t context) 1186cd6a6acSopenharmony_ci{ 1196cd6a6acSopenharmony_ci context_private_t *n = context->ptr; 1206cd6a6acSopenharmony_ci int i; 1216cd6a6acSopenharmony_ci size_t total = 0; 1226cd6a6acSopenharmony_ci conditional_free(&n->current_str); 1236cd6a6acSopenharmony_ci for (i = 0; i < 4; i++) { 1246cd6a6acSopenharmony_ci if (n->component[i]) { 1256cd6a6acSopenharmony_ci total += strlen(n->component[i]) + 1; 1266cd6a6acSopenharmony_ci } 1276cd6a6acSopenharmony_ci } 1286cd6a6acSopenharmony_ci n->current_str = malloc(total); 1296cd6a6acSopenharmony_ci if (n->current_str != 0) { 1306cd6a6acSopenharmony_ci char *cp = n->current_str; 1316cd6a6acSopenharmony_ci 1326cd6a6acSopenharmony_ci cp = stpcpy(cp, n->component[0]); 1336cd6a6acSopenharmony_ci for (i = 1; i < 4; i++) { 1346cd6a6acSopenharmony_ci if (n->component[i]) { 1356cd6a6acSopenharmony_ci *cp++ = ':'; 1366cd6a6acSopenharmony_ci cp = stpcpy(cp, n->component[i]); 1376cd6a6acSopenharmony_ci } 1386cd6a6acSopenharmony_ci } 1396cd6a6acSopenharmony_ci } 1406cd6a6acSopenharmony_ci return n->current_str; 1416cd6a6acSopenharmony_ci} 1426cd6a6acSopenharmony_ci 1436cd6a6acSopenharmony_ci 1446cd6a6acSopenharmony_ci/* Returns nonzero iff failed */ 1456cd6a6acSopenharmony_cistatic int set_comp(context_private_t * n, int idx, const char *str) 1466cd6a6acSopenharmony_ci{ 1476cd6a6acSopenharmony_ci char *t = NULL; 1486cd6a6acSopenharmony_ci const char *p; 1496cd6a6acSopenharmony_ci if (str) { 1506cd6a6acSopenharmony_ci for (p = str; *p; p++) { 1516cd6a6acSopenharmony_ci if (*p == '\t' || *p == '\n' || *p == '\r' || 1526cd6a6acSopenharmony_ci ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) { 1536cd6a6acSopenharmony_ci errno = EINVAL; 1546cd6a6acSopenharmony_ci return -1; 1556cd6a6acSopenharmony_ci } 1566cd6a6acSopenharmony_ci } 1576cd6a6acSopenharmony_ci 1586cd6a6acSopenharmony_ci t = strdup(str); 1596cd6a6acSopenharmony_ci if (!t) { 1606cd6a6acSopenharmony_ci return -1; 1616cd6a6acSopenharmony_ci } 1626cd6a6acSopenharmony_ci } 1636cd6a6acSopenharmony_ci conditional_free(&n->component[idx]); 1646cd6a6acSopenharmony_ci n->component[idx] = t; 1656cd6a6acSopenharmony_ci return 0; 1666cd6a6acSopenharmony_ci} 1676cd6a6acSopenharmony_ci 1686cd6a6acSopenharmony_ci#define def_get(name,tag) \ 1696cd6a6acSopenharmony_ciconst char * context_ ## name ## _get(context_t context) \ 1706cd6a6acSopenharmony_ci{ \ 1716cd6a6acSopenharmony_ci context_private_t *n = context->ptr; \ 1726cd6a6acSopenharmony_ci return n->component[tag]; \ 1736cd6a6acSopenharmony_ci} 1746cd6a6acSopenharmony_ci 1756cd6a6acSopenharmony_cidef_get(type, COMP_TYPE) 1766cd6a6acSopenharmony_ci def_get(user, COMP_USER) 1776cd6a6acSopenharmony_ci def_get(range, COMP_RANGE) 1786cd6a6acSopenharmony_ci def_get(role, COMP_ROLE) 1796cd6a6acSopenharmony_ci#define def_set(name,tag) \ 1806cd6a6acSopenharmony_ciint context_ ## name ## _set(context_t context, const char* str) \ 1816cd6a6acSopenharmony_ci{ \ 1826cd6a6acSopenharmony_ci return set_comp(context->ptr,tag,str);\ 1836cd6a6acSopenharmony_ci} 1846cd6a6acSopenharmony_ci def_set(type, COMP_TYPE) 1856cd6a6acSopenharmony_ci def_set(role, COMP_ROLE) 1866cd6a6acSopenharmony_ci def_set(user, COMP_USER) 1876cd6a6acSopenharmony_ci def_set(range, COMP_RANGE) 188