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