1 /* Copyright (C) 2005 Red Hat, Inc. */
2 
3 /* Object: semanage_user_t (SELinux User/Class)
4  * Object: semanage_user_key_t (SELinux User/Class Key)
5  * Implements: record_t (Database Record)
6  * Implements: record_key_t (Database Record Key)
7  */
8 
9 #include <sepol/user_record.h>
10 
11 typedef sepol_user_key_t semanage_user_key_t;
12 #define _SEMANAGE_USER_KEY_DEFINED_
13 
14 struct semanage_user;
15 typedef struct semanage_user record_t;
16 typedef semanage_user_key_t record_key_t;
17 #define DBASE_RECORD_DEFINED
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include "user_internal.h"
22 #include "handle.h"
23 #include "database.h"
24 #include "debug.h"
25 
26 struct semanage_user {
27 	char *name;
28 	semanage_user_base_t *base;
29 	semanage_user_extra_t *extra;
30 };
31 
32 /* Key */
semanage_user_key_create(semanage_handle_t * handle,const char * name,semanage_user_key_t ** key)33 int semanage_user_key_create(semanage_handle_t * handle,
34 			     const char *name, semanage_user_key_t ** key)
35 {
36 
37 	return sepol_user_key_create(handle->sepolh, name, key);
38 }
39 
hidden_def(semanage_user_key_create)40 hidden_def(semanage_user_key_create)
41 
42 int semanage_user_key_extract(semanage_handle_t * handle,
43 			      const semanage_user_t * user,
44 			      semanage_user_key_t ** key)
45 {
46 
47 	return semanage_user_base_key_extract(handle, user->base, key);
48 }
49 
hidden_def(semanage_user_key_extract)50 hidden_def(semanage_user_key_extract)
51 
52 void semanage_user_key_free(semanage_user_key_t * key)
53 {
54 
55 	sepol_user_key_free(key);
56 }
57 
hidden_def(semanage_user_key_free)58 hidden_def(semanage_user_key_free)
59 
60 hidden void semanage_user_key_unpack(const semanage_user_key_t * key,
61 				     const char **name)
62 {
63 
64 	sepol_user_key_unpack(key, name);
65 }
66 
semanage_user_compare(const semanage_user_t * user,const semanage_user_key_t * key)67 int semanage_user_compare(const semanage_user_t * user,
68 			  const semanage_user_key_t * key)
69 {
70 
71 	const char *name;
72 	sepol_user_key_unpack(key, &name);
73 	return strcmp(user->name, name);
74 }
75 
hidden_def(semanage_user_compare)76 hidden_def(semanage_user_compare)
77 
78 int semanage_user_compare2(const semanage_user_t * user,
79 			   const semanage_user_t * user2)
80 {
81 
82 	return strcmp(user->name, user2->name);
83 }
84 
hidden_def(semanage_user_compare2)85 hidden_def(semanage_user_compare2)
86 
87 static int semanage_user_compare2_qsort(const semanage_user_t ** user,
88 					const semanage_user_t ** user2)
89 {
90 
91 	return strcmp((*user)->name, (*user2)->name);
92 }
93 
94 /* Name */
semanage_user_get_name(const semanage_user_t * user)95 const char *semanage_user_get_name(const semanage_user_t * user)
96 {
97 	return user->name;
98 }
99 
hidden_def(semanage_user_get_name)100 hidden_def(semanage_user_get_name)
101 
102 int semanage_user_set_name(semanage_handle_t * handle,
103 			   semanage_user_t * user, const char *name)
104 {
105 
106 	char *tmp_name = strdup(name);
107 	if (!tmp_name)
108 		goto omem;
109 
110 	if (semanage_user_base_set_name(handle, user->base, name) < 0)
111 		goto err;
112 
113 	if (semanage_user_extra_set_name(handle, user->extra, name) < 0)
114 		goto err;
115 
116 	free(user->name);
117 	user->name = tmp_name;
118 	return STATUS_SUCCESS;
119 
120       omem:
121 	ERR(handle, "out of memory");
122 
123       err:
124 	ERR(handle, "could not set user name to %s", name);
125 	free(tmp_name);
126 	return STATUS_ERR;
127 }
128 
hidden_def(semanage_user_set_name)129 hidden_def(semanage_user_set_name)
130 
131 /* Labeling prefix */
132 const char *semanage_user_get_prefix(const semanage_user_t * user)
133 {
134 
135 	return semanage_user_extra_get_prefix(user->extra);
136 }
137 
semanage_user_set_prefix(semanage_handle_t * handle,semanage_user_t * user,const char * name)138 int semanage_user_set_prefix(semanage_handle_t * handle,
139 			     semanage_user_t * user, const char *name)
140 {
141 
142 	return semanage_user_extra_set_prefix(handle, user->extra, name);
143 }
144 
145 /* MLS */
semanage_user_get_mlslevel(const semanage_user_t * user)146 const char *semanage_user_get_mlslevel(const semanage_user_t * user)
147 {
148 
149 	return semanage_user_base_get_mlslevel(user->base);
150 }
151 
hidden_def(semanage_user_get_mlslevel)152 hidden_def(semanage_user_get_mlslevel)
153 
154 int semanage_user_set_mlslevel(semanage_handle_t * handle,
155 			       semanage_user_t * user, const char *mls_level)
156 {
157 
158 	return semanage_user_base_set_mlslevel(handle, user->base, mls_level);
159 }
160 
hidden_def(semanage_user_set_mlslevel)161 hidden_def(semanage_user_set_mlslevel)
162 
163 const char *semanage_user_get_mlsrange(const semanage_user_t * user)
164 {
165 
166 	return semanage_user_base_get_mlsrange(user->base);
167 }
168 
hidden_def(semanage_user_get_mlsrange)169 hidden_def(semanage_user_get_mlsrange)
170 
171 int semanage_user_set_mlsrange(semanage_handle_t * handle,
172 			       semanage_user_t * user, const char *mls_range)
173 {
174 
175 	return semanage_user_base_set_mlsrange(handle, user->base, mls_range);
176 }
177 
hidden_def(semanage_user_set_mlsrange)178 hidden_def(semanage_user_set_mlsrange)
179 
180 /* Role management */
181 int semanage_user_get_num_roles(const semanage_user_t * user)
182 {
183 
184 	return semanage_user_base_get_num_roles(user->base);
185 }
186 
semanage_user_add_role(semanage_handle_t * handle,semanage_user_t * user,const char * role)187 int semanage_user_add_role(semanage_handle_t * handle,
188 			   semanage_user_t * user, const char *role)
189 {
190 
191 	return semanage_user_base_add_role(handle, user->base, role);
192 }
193 
hidden_def(semanage_user_add_role)194 hidden_def(semanage_user_add_role)
195 
196 void semanage_user_del_role(semanage_user_t * user, const char *role)
197 {
198 
199 	semanage_user_base_del_role(user->base, role);
200 }
201 
semanage_user_has_role(const semanage_user_t * user,const char * role)202 int semanage_user_has_role(const semanage_user_t * user, const char *role)
203 {
204 
205 	return semanage_user_base_has_role(user->base, role);
206 }
207 
semanage_user_get_roles(semanage_handle_t * handle,const semanage_user_t * user,const char *** roles_arr,unsigned int * num_roles)208 int semanage_user_get_roles(semanage_handle_t * handle,
209 			    const semanage_user_t * user,
210 			    const char ***roles_arr, unsigned int *num_roles)
211 {
212 
213 	return semanage_user_base_get_roles(handle, user->base, roles_arr,
214 					    num_roles);
215 }
216 
hidden_def(semanage_user_get_roles)217 hidden_def(semanage_user_get_roles)
218 
219 int semanage_user_set_roles(semanage_handle_t * handle,
220 			    semanage_user_t * user,
221 			    const char **roles_arr, unsigned int num_roles)
222 {
223 
224 	return semanage_user_base_set_roles(handle, user->base, roles_arr,
225 					    num_roles);
226 }
227 
228 /* Create/Clone/Destroy */
semanage_user_create(semanage_handle_t * handle,semanage_user_t ** user_ptr)229 int semanage_user_create(semanage_handle_t * handle,
230 			 semanage_user_t ** user_ptr)
231 {
232 
233 	semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t));
234 	if (!tmp_user)
235 		goto omem;
236 
237 	if (semanage_user_base_create(handle, &tmp_user->base) < 0)
238 		goto err;
239 	if (semanage_user_extra_create(handle, &tmp_user->extra) < 0)
240 		goto err;
241 
242 	/* Initialize the prefix for migration purposes */
243 	if (semanage_user_extra_set_prefix(handle, tmp_user->extra, "user") < 0)
244 		goto err;
245 
246 	*user_ptr = tmp_user;
247 	return STATUS_SUCCESS;
248 
249       omem:
250 	ERR(handle, "out of memory");
251 
252       err:
253 	ERR(handle, "could not create user record");
254 	semanage_user_free(tmp_user);
255 	return STATUS_ERR;
256 }
257 
hidden_def(semanage_user_create)258 hidden_def(semanage_user_create)
259 
260 int semanage_user_clone(semanage_handle_t * handle,
261 			const semanage_user_t * user,
262 			semanage_user_t ** user_ptr)
263 {
264 
265 	semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t));
266 	if (!tmp_user)
267 		goto omem;
268 
269 	/* Clone base and extra records */
270 	if (semanage_user_base_clone(handle, user->base, &tmp_user->base) < 0)
271 		goto err;
272 	if (semanage_user_extra_clone(handle, user->extra, &tmp_user->extra) <
273 	    0)
274 		goto err;
275 
276 	/* Set the shared name */
277 	if (semanage_user_set_name(handle, tmp_user, user->name) < 0)
278 		goto err;
279 
280 	*user_ptr = tmp_user;
281 	return STATUS_SUCCESS;
282 
283       omem:
284 	ERR(handle, "out of memory");
285 
286       err:
287 	ERR(handle, "could not clone user record");
288 	semanage_user_free(tmp_user);
289 	return STATUS_ERR;
290 }
291 
hidden_def(semanage_user_clone)292 hidden_def(semanage_user_clone)
293 
294 void semanage_user_free(semanage_user_t * user)
295 {
296 
297 	if (!user)
298 		return;
299 
300 	semanage_user_base_free(user->base);
301 	semanage_user_extra_free(user->extra);
302 	free(user->name);
303 	free(user);
304 }
305 
hidden_def(semanage_user_free)306 hidden_def(semanage_user_free)
307 
308 /* Join properties */
309 hidden int semanage_user_join(semanage_handle_t * handle,
310 			      const semanage_user_base_t * record1,
311 			      const semanage_user_extra_t * record2,
312 			      semanage_user_t ** result)
313 {
314 
315 	const char *name;
316 	semanage_user_t *tmp_user = calloc(1, sizeof(semanage_user_t));
317 	if (!tmp_user)
318 		goto omem;
319 
320 	/* Set the shared name from one of the records
321 	 * (at least one is available) */
322 	if (record1 == NULL)
323 		name = semanage_user_extra_get_name(record2);
324 	else
325 		name = semanage_user_base_get_name(record1);
326 
327 	/* Join base record if it exists, create a blank one otherwise */
328 	if (record1) {
329 		if (semanage_user_base_clone(handle, record1, &tmp_user->base) <
330 		    0)
331 			goto err;
332 	} else {
333 		if (semanage_user_base_create(handle, &tmp_user->base) < 0)
334 			goto err;
335 		if (semanage_user_base_set_name(handle, tmp_user->base, name) <
336 		    0)
337 			goto err;
338 	}
339 
340 	/* Join extra record if it exists, create a blank one otherwise */
341 	if (record2) {
342 		if (semanage_user_extra_clone(handle, record2, &tmp_user->extra)
343 		    < 0)
344 			goto err;
345 	} else {
346 		if (semanage_user_extra_create(handle, &tmp_user->extra) < 0)
347 			goto err;
348 		if (semanage_user_extra_set_name(handle, tmp_user->extra, name)
349 		    < 0)
350 			goto err;
351 		if (semanage_user_extra_set_prefix
352 		    (handle, tmp_user->extra, "user") < 0)
353 			goto err;
354 	}
355 
356 	if (semanage_user_set_name(handle, tmp_user, name) < 0)
357 		goto err;
358 
359 	*result = tmp_user;
360 	return STATUS_SUCCESS;
361 
362       omem:
363 	ERR(handle, "out of memory");
364 
365       err:
366 	ERR(handle, "could not join data records for user %s",
367 	    semanage_user_base_get_name(record1));
368 	semanage_user_free(tmp_user);
369 	return STATUS_ERR;
370 }
371 
semanage_user_split(semanage_handle_t * handle,const semanage_user_t * record,semanage_user_base_t ** split1,semanage_user_extra_t ** split2)372 hidden int semanage_user_split(semanage_handle_t * handle,
373 			       const semanage_user_t * record,
374 			       semanage_user_base_t ** split1,
375 			       semanage_user_extra_t ** split2)
376 {
377 
378 	semanage_user_base_t *tmp_base_user = NULL;
379 	semanage_user_extra_t *tmp_extra_user = NULL;
380 
381 	if (semanage_user_base_clone(handle, record->base, &tmp_base_user) < 0)
382 		goto err;
383 
384 	if (semanage_user_extra_clone(handle, record->extra, &tmp_extra_user) <
385 	    0)
386 		goto err;
387 
388 	*split1 = tmp_base_user;
389 	*split2 = tmp_extra_user;
390 	return STATUS_SUCCESS;
391 
392       err:
393 	ERR(handle, "could not split data records for user %s",
394 	    semanage_user_get_name(record));
395 	semanage_user_base_free(tmp_base_user);
396 	semanage_user_extra_free(tmp_extra_user);
397 	return STATUS_ERR;
398 }
399 
400 /* Record base functions */
401 record_table_t SEMANAGE_USER_RTABLE = {
402 	.create = semanage_user_create,
403 	.key_extract = semanage_user_key_extract,
404 	.key_free = semanage_user_key_free,
405 	.clone = semanage_user_clone,
406 	.compare = semanage_user_compare,
407 	.compare2 = semanage_user_compare2,
408 	.compare2_qsort = semanage_user_compare2_qsort,
409 	.free = semanage_user_free,
410 };
411