1 #include <errno.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdio.h>
5
6 #include "context_internal.h"
7 #include "debug.h"
8
9 struct sepol_context {
10
11 /* Selinux user */
12 char *user;
13
14 /* Selinux role */
15 char *role;
16
17 /* Selinux type */
18 char *type;
19
20 /* MLS */
21 char *mls;
22 };
23
24 /* User */
sepol_context_get_user(const sepol_context_t * con)25 const char *sepol_context_get_user(const sepol_context_t * con)
26 {
27
28 return con->user;
29 }
30
hidden_def(sepol_context_get_user)31 hidden_def(sepol_context_get_user)
32
33 int sepol_context_set_user(sepol_handle_t * handle,
34 sepol_context_t * con, const char *user)
35 {
36
37 char *tmp_user = strdup(user);
38 if (!tmp_user) {
39 ERR(handle, "out of memory, could not set "
40 "context user to %s", user);
41 return STATUS_ERR;
42 }
43
44 free(con->user);
45 con->user = tmp_user;
46 return STATUS_SUCCESS;
47 }
48
hidden_def(sepol_context_set_user)49 hidden_def(sepol_context_set_user)
50
51 /* Role */
52 const char *sepol_context_get_role(const sepol_context_t * con)
53 {
54
55 return con->role;
56 }
57
hidden_def(sepol_context_get_role)58 hidden_def(sepol_context_get_role)
59
60 int sepol_context_set_role(sepol_handle_t * handle,
61 sepol_context_t * con, const char *role)
62 {
63
64 char *tmp_role = strdup(role);
65 if (!tmp_role) {
66 ERR(handle, "out of memory, could not set "
67 "context role to %s", role);
68 return STATUS_ERR;
69 }
70 free(con->role);
71 con->role = tmp_role;
72 return STATUS_SUCCESS;
73 }
74
hidden_def(sepol_context_set_role)75 hidden_def(sepol_context_set_role)
76
77 /* Type */
78 const char *sepol_context_get_type(const sepol_context_t * con)
79 {
80
81 return con->type;
82 }
83
hidden_def(sepol_context_get_type)84 hidden_def(sepol_context_get_type)
85
86 int sepol_context_set_type(sepol_handle_t * handle,
87 sepol_context_t * con, const char *type)
88 {
89
90 char *tmp_type = strdup(type);
91 if (!tmp_type) {
92 ERR(handle, "out of memory, could not set "
93 "context type to %s", type);
94 return STATUS_ERR;
95 }
96 free(con->type);
97 con->type = tmp_type;
98 return STATUS_SUCCESS;
99 }
100
hidden_def(sepol_context_set_type)101 hidden_def(sepol_context_set_type)
102
103 /* MLS */
104 const char *sepol_context_get_mls(const sepol_context_t * con)
105 {
106
107 return con->mls;
108 }
109
hidden_def(sepol_context_get_mls)110 hidden_def(sepol_context_get_mls)
111
112 int sepol_context_set_mls(sepol_handle_t * handle,
113 sepol_context_t * con, const char *mls)
114 {
115
116 char *tmp_mls = strdup(mls);
117 if (!tmp_mls) {
118 ERR(handle, "out of memory, could not set "
119 "MLS fields to %s", mls);
120 return STATUS_ERR;
121 }
122 free(con->mls);
123 con->mls = tmp_mls;
124 return STATUS_SUCCESS;
125 }
126
hidden_def(sepol_context_set_mls)127 hidden_def(sepol_context_set_mls)
128
129 /* Create */
130 int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr)
131 {
132
133 sepol_context_t *con =
134 (sepol_context_t *) malloc(sizeof(sepol_context_t));
135
136 if (!con) {
137 ERR(handle, "out of memory, could not " "create context\n");
138 return STATUS_ERR;
139 }
140
141 con->user = NULL;
142 con->role = NULL;
143 con->type = NULL;
144 con->mls = NULL;
145 *con_ptr = con;
146 return STATUS_SUCCESS;
147 }
148
hidden_def(sepol_context_create)149 hidden_def(sepol_context_create)
150
151 /* Deep copy clone */
152 int sepol_context_clone(sepol_handle_t * handle,
153 const sepol_context_t * con, sepol_context_t ** con_ptr)
154 {
155
156 sepol_context_t *new_con = NULL;
157
158 if (!con) {
159 *con_ptr = NULL;
160 return 0;
161 }
162
163 if (sepol_context_create(handle, &new_con) < 0)
164 goto err;
165
166 if (!(new_con->user = strdup(con->user)))
167 goto omem;
168
169 if (!(new_con->role = strdup(con->role)))
170 goto omem;
171
172 if (!(new_con->type = strdup(con->type)))
173 goto omem;
174
175 if (con->mls && !(new_con->mls = strdup(con->mls)))
176 goto omem;
177
178 *con_ptr = new_con;
179 return STATUS_SUCCESS;
180
181 omem:
182 ERR(handle, "out of memory");
183
184 err:
185 ERR(handle, "could not clone context record");
186 sepol_context_free(new_con);
187 return STATUS_ERR;
188 }
189
hidden_def(sepol_context_clone)190 hidden_def(sepol_context_clone)
191
192 /* Destroy */
193 void sepol_context_free(sepol_context_t * con)
194 {
195
196 if (!con)
197 return;
198
199 free(con->user);
200 free(con->role);
201 free(con->type);
202 free(con->mls);
203 free(con);
204 }
205
hidden_def(sepol_context_free)206 hidden_def(sepol_context_free)
207
208 int sepol_context_from_string(sepol_handle_t * handle,
209 const char *str, sepol_context_t ** con)
210 {
211
212 char *tmp = NULL, *low, *high;
213 sepol_context_t *tmp_con = NULL;
214
215 if (!strcmp(str, "<<none>>")) {
216 *con = NULL;
217 return STATUS_SUCCESS;
218 }
219
220 if (sepol_context_create(handle, &tmp_con) < 0)
221 goto err;
222
223 /* Working copy context */
224 tmp = strdup(str);
225 if (!tmp) {
226 ERR(handle, "out of memory");
227 goto err;
228 }
229 low = tmp;
230
231 /* Then, break it into its components */
232
233 /* User */
234 if (!(high = strchr(low, ':')))
235 goto mcontext;
236 else
237 *high++ = '\0';
238 if (sepol_context_set_user(handle, tmp_con, low) < 0)
239 goto err;
240 low = high;
241
242 /* Role */
243 if (!(high = strchr(low, ':')))
244 goto mcontext;
245 else
246 *high++ = '\0';
247 if (sepol_context_set_role(handle, tmp_con, low) < 0)
248 goto err;
249 low = high;
250
251 /* Type, and possibly MLS */
252 if (!(high = strchr(low, ':'))) {
253 if (sepol_context_set_type(handle, tmp_con, low) < 0)
254 goto err;
255 } else {
256 *high++ = '\0';
257 if (sepol_context_set_type(handle, tmp_con, low) < 0)
258 goto err;
259 low = high;
260 if (sepol_context_set_mls(handle, tmp_con, low) < 0)
261 goto err;
262 }
263
264 free(tmp);
265 *con = tmp_con;
266
267 return STATUS_SUCCESS;
268
269 mcontext:
270 errno = EINVAL;
271 ERR(handle, "malformed context \"%s\"", str);
272
273 err:
274 ERR(handle, "could not construct context from string");
275 free(tmp);
276 sepol_context_free(tmp_con);
277 return STATUS_ERR;
278 }
279
hidden_def(sepol_context_from_string)280 hidden_def(sepol_context_from_string)
281
282 int sepol_context_to_string(sepol_handle_t * handle,
283 const sepol_context_t * con, char **str_ptr)
284 {
285
286 int rc;
287 const int user_sz = strlen(con->user);
288 const int role_sz = strlen(con->role);
289 const int type_sz = strlen(con->type);
290 const int mls_sz = (con->mls) ? strlen(con->mls) : 0;
291 const int total_sz = user_sz + role_sz + type_sz +
292 mls_sz + ((con->mls) ? 3 : 2);
293
294 char *str = (char *)malloc(total_sz + 1);
295 if (!str)
296 goto omem;
297
298 if (con->mls) {
299 rc = snprintf(str, total_sz + 1, "%s:%s:%s:%s",
300 con->user, con->role, con->type, con->mls);
301 if (rc < 0 || (rc >= total_sz + 1)) {
302 ERR(handle, "print error");
303 goto err;
304 }
305 } else {
306 rc = snprintf(str, total_sz + 1, "%s:%s:%s",
307 con->user, con->role, con->type);
308 if (rc < 0 || (rc >= total_sz + 1)) {
309 ERR(handle, "print error");
310 goto err;
311 }
312 }
313
314 *str_ptr = str;
315 return STATUS_SUCCESS;
316
317 omem:
318 ERR(handle, "out of memory");
319
320 err:
321 ERR(handle, "could not convert context to string");
322 free(str);
323 return STATUS_ERR;
324 }
325