blob: b673733e1f483ade073a51a29dd86efa0e01b420 [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001#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
12typedef 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 */
22context_t context_new(const char *str)
23{
24 int i, count;
Daniel J Walsh7dcf27a2010-03-24 09:17:03 -040025 errno = 0;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040026 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:
Daniel J Walsh7dcf27a2010-03-24 09:17:03 -040080 if (errno == 0) errno = EINVAL;
Joshua Brindle13cd4c82008-08-19 15:30:36 -040081 context_free(result);
82 return 0;
83}
84
85hidden_def(context_new)
86
87static 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 */
99void 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
116hidden_def(context_free)
117
118/*
119 * Return a pointer to the string value of the context.
120 */
121char *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
147hidden_def(context_str)
148
149/* Returns nonzero iff failed */
150static 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) \
175const char * context_ ## name ## _get(context_t context) \
176{ \
177 context_private_t *n = context->ptr; \
178 return n->component[tag]; \
179} \
180hidden_def(context_ ## name ## _get)
181
182def_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) \
187int context_ ## name ## _set(context_t context, const char* str) \
188{ \
189 return set_comp(context->ptr,tag,str);\
190} \
191hidden_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)