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