• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
54 
sepol_user_key_unpack(const sepol_user_key_t * key,const char ** name)55 void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
56 {
57 
58 	*name = key->name;
59 }
60 
61 
sepol_user_key_extract(sepol_handle_t * handle,const sepol_user_t * user,sepol_user_key_t ** key_ptr)62 int sepol_user_key_extract(sepol_handle_t * handle,
63 			   const sepol_user_t * user,
64 			   sepol_user_key_t ** key_ptr)
65 {
66 
67 	if (sepol_user_key_create(handle, user->name, key_ptr) < 0) {
68 		ERR(handle, "could not extract key from user %s", user->name);
69 		return STATUS_ERR;
70 	}
71 
72 	return STATUS_SUCCESS;
73 }
74 
sepol_user_key_free(sepol_user_key_t * key)75 void sepol_user_key_free(sepol_user_key_t * key)
76 {
77 	if (!key)
78 		return;
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 
116 
117 /* MLS */
sepol_user_get_mlslevel(const sepol_user_t * user)118 const char *sepol_user_get_mlslevel(const sepol_user_t * user)
119 {
120 
121 	return user->mls_level;
122 }
123 
124 
sepol_user_set_mlslevel(sepol_handle_t * handle,sepol_user_t * user,const char * mls_level)125 int sepol_user_set_mlslevel(sepol_handle_t * handle,
126 			    sepol_user_t * user, const char *mls_level)
127 {
128 
129 	char *tmp_mls_level = strdup(mls_level);
130 	if (!tmp_mls_level) {
131 		ERR(handle, "out of memory, "
132 		    "could not set MLS default level");
133 		return STATUS_ERR;
134 	}
135 	free(user->mls_level);
136 	user->mls_level = tmp_mls_level;
137 	return STATUS_SUCCESS;
138 }
139 
140 
sepol_user_get_mlsrange(const sepol_user_t * user)141 const char *sepol_user_get_mlsrange(const sepol_user_t * user)
142 {
143 
144 	return user->mls_range;
145 }
146 
147 
sepol_user_set_mlsrange(sepol_handle_t * handle,sepol_user_t * user,const char * mls_range)148 int sepol_user_set_mlsrange(sepol_handle_t * handle,
149 			    sepol_user_t * user, const char *mls_range)
150 {
151 
152 	char *tmp_mls_range = strdup(mls_range);
153 	if (!tmp_mls_range) {
154 		ERR(handle, "out of memory, "
155 		    "could not set MLS allowed range");
156 		return STATUS_ERR;
157 	}
158 	free(user->mls_range);
159 	user->mls_range = tmp_mls_range;
160 	return STATUS_SUCCESS;
161 }
162 
163 
164 /* Roles */
sepol_user_get_num_roles(const sepol_user_t * user)165 int sepol_user_get_num_roles(const sepol_user_t * user)
166 {
167 
168 	return user->num_roles;
169 }
170 
sepol_user_add_role(sepol_handle_t * handle,sepol_user_t * user,const char * role)171 int sepol_user_add_role(sepol_handle_t * handle,
172 			sepol_user_t * user, const char *role)
173 {
174 
175 	char *role_cp;
176 	char **roles_realloc = NULL;
177 
178 	if (sepol_user_has_role(user, role))
179 		return STATUS_SUCCESS;
180 
181 	role_cp = strdup(role);
182 	if (!role_cp)
183 		goto omem;
184 
185 	roles_realloc = realloc(user->roles,
186 				sizeof(char *) * (user->num_roles + 1));
187 	if (!roles_realloc)
188 		goto omem;
189 
190 	user->num_roles++;
191 	user->roles = roles_realloc;
192 	user->roles[user->num_roles - 1] = role_cp;
193 
194 	return STATUS_SUCCESS;
195 
196       omem:
197 	ERR(handle, "out of memory, could not add role %s", role);
198 	free(role_cp);
199 	free(roles_realloc);
200 	return STATUS_ERR;
201 }
202 
203 
sepol_user_has_role(const sepol_user_t * user,const char * role)204 int sepol_user_has_role(const sepol_user_t * user, const char *role)
205 {
206 
207 	unsigned int i;
208 
209 	for (i = 0; i < user->num_roles; i++)
210 		if (!strcmp(user->roles[i], role))
211 			return 1;
212 	return 0;
213 }
214 
215 
sepol_user_set_roles(sepol_handle_t * handle,sepol_user_t * user,const char ** roles_arr,unsigned int num_roles)216 int sepol_user_set_roles(sepol_handle_t * handle,
217 			 sepol_user_t * user,
218 			 const char **roles_arr, unsigned int num_roles)
219 {
220 
221 	unsigned int i;
222 	char **tmp_roles = NULL;
223 
224 	if (num_roles > 0) {
225 
226 		/* First, make a copy */
227 		tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles);
228 		if (!tmp_roles)
229 			goto omem;
230 
231 		for (i = 0; i < num_roles; i++) {
232 			tmp_roles[i] = strdup(roles_arr[i]);
233 			if (!tmp_roles[i])
234 				goto omem;
235 		}
236 	}
237 
238 	/* Apply other changes */
239 	for (i = 0; i < user->num_roles; i++)
240 		free(user->roles[i]);
241 	free(user->roles);
242 	user->roles = tmp_roles;
243 	user->num_roles = num_roles;
244 	return STATUS_SUCCESS;
245 
246       omem:
247 	ERR(handle, "out of memory, could not allocate roles array for"
248 	    "user %s", user->name);
249 
250 	if (tmp_roles) {
251 		for (i = 0; i < num_roles; i++) {
252 			if (!tmp_roles[i])
253 				break;
254 			free(tmp_roles[i]);
255 		}
256 	}
257 	free(tmp_roles);
258 	return STATUS_ERR;
259 }
260 
sepol_user_get_roles(sepol_handle_t * handle,const sepol_user_t * user,const char *** roles_arr,unsigned int * num_roles)261 int sepol_user_get_roles(sepol_handle_t * handle,
262 			 const sepol_user_t * user,
263 			 const char ***roles_arr, unsigned int *num_roles)
264 {
265 
266 	unsigned int i;
267 	const char **tmp_roles =
268 	    (const char **)malloc(sizeof(char *) * user->num_roles);
269 	if (!tmp_roles)
270 		goto omem;
271 
272 	for (i = 0; i < user->num_roles; i++)
273 		tmp_roles[i] = user->roles[i];
274 
275 	*roles_arr = tmp_roles;
276 	*num_roles = user->num_roles;
277 	return STATUS_SUCCESS;
278 
279       omem:
280 	ERR(handle, "out of memory, could not "
281 	    "allocate roles array for user %s", user->name);
282 	free(tmp_roles);
283 	return STATUS_ERR;
284 }
285 
286 
sepol_user_del_role(sepol_user_t * user,const char * role)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 
323 
324 /* Deep copy clone */
sepol_user_clone(sepol_handle_t * handle,const sepol_user_t * user,sepol_user_t ** user_ptr)325 int sepol_user_clone(sepol_handle_t * handle,
326 		     const sepol_user_t * user, sepol_user_t ** user_ptr)
327 {
328 
329 	sepol_user_t *new_user = NULL;
330 	unsigned int i;
331 
332 	if (sepol_user_create(handle, &new_user) < 0)
333 		goto err;
334 
335 	if (sepol_user_set_name(handle, new_user, user->name) < 0)
336 		goto err;
337 
338 	for (i = 0; i < user->num_roles; i++) {
339 		if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0)
340 			goto err;
341 	}
342 
343 	if (user->mls_level &&
344 	    (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0))
345 		goto err;
346 
347 	if (user->mls_range &&
348 	    (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0))
349 		goto err;
350 
351 	*user_ptr = new_user;
352 	return STATUS_SUCCESS;
353 
354       err:
355 	ERR(handle, "could not clone selinux user record");
356 	sepol_user_free(new_user);
357 	return STATUS_ERR;
358 }
359 
360 /* Destroy */
sepol_user_free(sepol_user_t * user)361 void sepol_user_free(sepol_user_t * user)
362 {
363 
364 	unsigned int i;
365 
366 	if (!user)
367 		return;
368 
369 	free(user->name);
370 	for (i = 0; i < user->num_roles; i++)
371 		free(user->roles[i]);
372 	free(user->roles);
373 	free(user->mls_level);
374 	free(user->mls_range);
375 	free(user);
376 }
377 
378