1 #include <errno.h>
2 #include <stdlib.h>
3 #include <string.h>
4 
5 #include "user_internal.h"
6 #include "debug.h"
7 
8 struct sepol_user {
9 	/* This user's name */
10 	char *name;
11 
12 	/* This user's mls level (only required for mls) */
13 	char *mls_level;
14 
15 	/* This user's mls range (only required for mls) */
16 	char *mls_range;
17 
18 	/* The role array */
19 	char **roles;
20 
21 	/* The number of roles */
22 	unsigned int num_roles;
23 };
24 
25 struct sepol_user_key {
26 	/* This user's name */
27 	char *name;
28 };
29 
sepol_user_key_create(sepol_handle_t * handle,const char * name,sepol_user_key_t ** key_ptr)30 int sepol_user_key_create(sepol_handle_t * handle,
31 			  const char *name, sepol_user_key_t ** key_ptr)
32 {
33 
34 	sepol_user_key_t *tmp_key =
35 	    (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t));
36 
37 	if (!tmp_key) {
38 		ERR(handle, "out of memory, "
39 		    "could not create selinux user key");
40 		return STATUS_ERR;
41 	}
42 
43 	tmp_key->name = strdup(name);
44 	if (!tmp_key->name) {
45 		ERR(handle, "out of memory, could not create selinux user key");
46 		free(tmp_key);
47 		return STATUS_ERR;
48 	}
49 
50 	*key_ptr = tmp_key;
51 	return STATUS_SUCCESS;
52 }
53 
hidden_def(sepol_user_key_create)54 hidden_def(sepol_user_key_create)
55 
56 void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
57 {
58 
59 	*name = key->name;
60 }
61 
hidden_def(sepol_user_key_unpack)62 hidden_def(sepol_user_key_unpack)
63 
64 int sepol_user_key_extract(sepol_handle_t * handle,
65 			   const sepol_user_t * user,
66 			   sepol_user_key_t ** key_ptr)
67 {
68 
69 	if (sepol_user_key_create(handle, user->name, key_ptr) < 0) {
70 		ERR(handle, "could not extract key from user %s", user->name);
71 		return STATUS_ERR;
72 	}
73 
74 	return STATUS_SUCCESS;
75 }
76 
sepol_user_key_free(sepol_user_key_t * key)77 void sepol_user_key_free(sepol_user_key_t * key)
78 {
79 	free(key->name);
80 	free(key);
81 }
82 
sepol_user_compare(const sepol_user_t * user,const sepol_user_key_t * key)83 int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key)
84 {
85 
86 	return strcmp(user->name, key->name);
87 }
88 
sepol_user_compare2(const sepol_user_t * user,const sepol_user_t * user2)89 int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2)
90 {
91 
92 	return strcmp(user->name, user2->name);
93 }
94 
95 /* Name */
sepol_user_get_name(const sepol_user_t * user)96 const char *sepol_user_get_name(const sepol_user_t * user)
97 {
98 
99 	return user->name;
100 }
101 
sepol_user_set_name(sepol_handle_t * handle,sepol_user_t * user,const char * name)102 int sepol_user_set_name(sepol_handle_t * handle,
103 			sepol_user_t * user, const char *name)
104 {
105 
106 	char *tmp_name = strdup(name);
107 	if (!tmp_name) {
108 		ERR(handle, "out of memory, could not set name");
109 		return STATUS_ERR;
110 	}
111 	free(user->name);
112 	user->name = tmp_name;
113 	return STATUS_SUCCESS;
114 }
115 
hidden_def(sepol_user_set_name)116 hidden_def(sepol_user_set_name)
117 
118 /* MLS */
119 const char *sepol_user_get_mlslevel(const sepol_user_t * user)
120 {
121 
122 	return user->mls_level;
123 }
124 
hidden_def(sepol_user_get_mlslevel)125 hidden_def(sepol_user_get_mlslevel)
126 
127 int sepol_user_set_mlslevel(sepol_handle_t * handle,
128 			    sepol_user_t * user, const char *mls_level)
129 {
130 
131 	char *tmp_mls_level = strdup(mls_level);
132 	if (!tmp_mls_level) {
133 		ERR(handle, "out of memory, "
134 		    "could not set MLS default level");
135 		return STATUS_ERR;
136 	}
137 	free(user->mls_level);
138 	user->mls_level = tmp_mls_level;
139 	return STATUS_SUCCESS;
140 }
141 
hidden_def(sepol_user_set_mlslevel)142 hidden_def(sepol_user_set_mlslevel)
143 
144 const char *sepol_user_get_mlsrange(const sepol_user_t * user)
145 {
146 
147 	return user->mls_range;
148 }
149 
hidden_def(sepol_user_get_mlsrange)150 hidden_def(sepol_user_get_mlsrange)
151 
152 int sepol_user_set_mlsrange(sepol_handle_t * handle,
153 			    sepol_user_t * user, const char *mls_range)
154 {
155 
156 	char *tmp_mls_range = strdup(mls_range);
157 	if (!tmp_mls_range) {
158 		ERR(handle, "out of memory, "
159 		    "could not set MLS allowed range");
160 		return STATUS_ERR;
161 	}
162 	free(user->mls_range);
163 	user->mls_range = tmp_mls_range;
164 	return STATUS_SUCCESS;
165 }
166 
hidden_def(sepol_user_set_mlsrange)167 hidden_def(sepol_user_set_mlsrange)
168 
169 /* Roles */
170 int sepol_user_get_num_roles(const sepol_user_t * user)
171 {
172 
173 	return user->num_roles;
174 }
175 
sepol_user_add_role(sepol_handle_t * handle,sepol_user_t * user,const char * role)176 int sepol_user_add_role(sepol_handle_t * handle,
177 			sepol_user_t * user, const char *role)
178 {
179 
180 	char *role_cp;
181 	char **roles_realloc;
182 
183 	if (sepol_user_has_role(user, role))
184 		return STATUS_SUCCESS;
185 
186 	role_cp = strdup(role);
187 	roles_realloc = realloc(user->roles,
188 				sizeof(char *) * (user->num_roles + 1));
189 
190 	if (!role_cp || !roles_realloc)
191 		goto omem;
192 
193 	user->num_roles++;
194 	user->roles = roles_realloc;
195 	user->roles[user->num_roles - 1] = role_cp;
196 
197 	return STATUS_SUCCESS;
198 
199       omem:
200 	ERR(handle, "out of memory, could not add role %s", role);
201 	free(role_cp);
202 	free(roles_realloc);
203 	return STATUS_ERR;
204 }
205 
hidden_def(sepol_user_add_role)206 hidden_def(sepol_user_add_role)
207 
208 int sepol_user_has_role(const sepol_user_t * user, const char *role)
209 {
210 
211 	unsigned int i;
212 
213 	for (i = 0; i < user->num_roles; i++)
214 		if (!strcmp(user->roles[i], role))
215 			return 1;
216 	return 0;
217 }
218 
hidden_def(sepol_user_has_role)219 hidden_def(sepol_user_has_role)
220 
221 int sepol_user_set_roles(sepol_handle_t * handle,
222 			 sepol_user_t * user,
223 			 const char **roles_arr, unsigned int num_roles)
224 {
225 
226 	unsigned int i;
227 	char **tmp_roles = NULL;
228 
229 	if (num_roles > 0) {
230 
231 		/* First, make a copy */
232 		tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles);
233 		if (!tmp_roles)
234 			goto omem;
235 
236 		for (i = 0; i < num_roles; i++) {
237 			tmp_roles[i] = strdup(roles_arr[i]);
238 			if (!tmp_roles[i])
239 				goto omem;
240 		}
241 	}
242 
243 	/* Apply other changes */
244 	for (i = 0; i < user->num_roles; i++)
245 		free(user->roles[i]);
246 	free(user->roles);
247 	user->roles = tmp_roles;
248 	user->num_roles = num_roles;
249 	return STATUS_SUCCESS;
250 
251       omem:
252 	ERR(handle, "out of memory, could not allocate roles array for"
253 	    "user %s", user->name);
254 
255 	if (tmp_roles) {
256 		for (i = 0; i < num_roles; i++) {
257 			if (!tmp_roles[i])
258 				break;
259 			free(tmp_roles[i]);
260 		}
261 	}
262 	free(tmp_roles);
263 	return STATUS_ERR;
264 }
265 
sepol_user_get_roles(sepol_handle_t * handle,const sepol_user_t * user,const char *** roles_arr,unsigned int * num_roles)266 int sepol_user_get_roles(sepol_handle_t * handle,
267 			 const sepol_user_t * user,
268 			 const char ***roles_arr, unsigned int *num_roles)
269 {
270 
271 	unsigned int i;
272 	const char **tmp_roles =
273 	    (const char **)malloc(sizeof(char *) * user->num_roles);
274 	if (!tmp_roles)
275 		goto omem;
276 
277 	for (i = 0; i < user->num_roles; i++)
278 		tmp_roles[i] = user->roles[i];
279 
280 	*roles_arr = tmp_roles;
281 	*num_roles = user->num_roles;
282 	return STATUS_SUCCESS;
283 
284       omem:
285 	ERR(handle, "out of memory, could not "
286 	    "allocate roles array for user %s", user->name);
287 	free(tmp_roles);
288 	return STATUS_ERR;
289 }
290 
hidden_def(sepol_user_get_roles)291 hidden_def(sepol_user_get_roles)
292 
293 void sepol_user_del_role(sepol_user_t * user, const char *role)
294 {
295 
296 	unsigned int i;
297 	for (i = 0; i < user->num_roles; i++) {
298 		if (!strcmp(user->roles[i], role)) {
299 			free(user->roles[i]);
300 			user->roles[i] = NULL;
301 			user->roles[i] = user->roles[user->num_roles - 1];
302 			user->num_roles--;
303 		}
304 	}
305 }
306 
307 /* Create */
sepol_user_create(sepol_handle_t * handle,sepol_user_t ** user_ptr)308 int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr)
309 {
310 
311 	sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t));
312 
313 	if (!user) {
314 		ERR(handle, "out of memory, "
315 		    "could not create selinux user record");
316 		return STATUS_ERR;
317 	}
318 
319 	user->roles = NULL;
320 	user->num_roles = 0;
321 	user->name = NULL;
322 	user->mls_level = NULL;
323 	user->mls_range = NULL;
324 
325 	*user_ptr = user;
326 	return STATUS_SUCCESS;
327 }
328 
hidden_def(sepol_user_create)329 hidden_def(sepol_user_create)
330 
331 /* Deep copy clone */
332 int sepol_user_clone(sepol_handle_t * handle,
333 		     const sepol_user_t * user, sepol_user_t ** user_ptr)
334 {
335 
336 	sepol_user_t *new_user = NULL;
337 	unsigned int i;
338 
339 	if (sepol_user_create(handle, &new_user) < 0)
340 		goto err;
341 
342 	if (sepol_user_set_name(handle, new_user, user->name) < 0)
343 		goto err;
344 
345 	for (i = 0; i < user->num_roles; i++) {
346 		if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0)
347 			goto err;
348 	}
349 
350 	if (user->mls_level &&
351 	    (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0))
352 		goto err;
353 
354 	if (user->mls_range &&
355 	    (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0))
356 		goto err;
357 
358 	*user_ptr = new_user;
359 	return STATUS_SUCCESS;
360 
361       err:
362 	ERR(handle, "could not clone selinux user record");
363 	sepol_user_free(new_user);
364 	return STATUS_ERR;
365 }
366 
367 /* Destroy */
sepol_user_free(sepol_user_t * user)368 void sepol_user_free(sepol_user_t * user)
369 {
370 
371 	unsigned int i;
372 
373 	if (!user)
374 		return;
375 
376 	free(user->name);
377 	for (i = 0; i < user->num_roles; i++)
378 		free(user->roles[i]);
379 	free(user->roles);
380 	free(user->mls_level);
381 	free(user->mls_range);
382 	free(user);
383 }
384 
385 hidden_def(sepol_user_free)
386