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