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
11typedef sepol_user_key_t semanage_user_key_t;
12#define _SEMANAGE_USER_KEY_DEFINED_
13
14struct semanage_user;
15typedef struct semanage_user record_t;
16typedef 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
26struct semanage_user {
27	char *name;
28	semanage_user_base_t *base;
29	semanage_user_extra_t *extra;
30};
31
32/* Key */
33int 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
40hidden_def(semanage_user_key_create)
41
42int 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
50hidden_def(semanage_user_key_extract)
51
52void semanage_user_key_free(semanage_user_key_t * key)
53{
54
55	sepol_user_key_free(key);
56}
57
58hidden_def(semanage_user_key_free)
59
60hidden 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
67int 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
76hidden_def(semanage_user_compare)
77
78int 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
85hidden_def(semanage_user_compare2)
86
87static 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 */
95const char *semanage_user_get_name(const semanage_user_t * user)
96{
97	return user->name;
98}
99
100hidden_def(semanage_user_get_name)
101
102int 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
129hidden_def(semanage_user_set_name)
130
131/* Labeling prefix */
132const char *semanage_user_get_prefix(const semanage_user_t * user)
133{
134
135	return semanage_user_extra_get_prefix(user->extra);
136}
137
138int 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 */
146const char *semanage_user_get_mlslevel(const semanage_user_t * user)
147{
148
149	return semanage_user_base_get_mlslevel(user->base);
150}
151
152hidden_def(semanage_user_get_mlslevel)
153
154int 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
161hidden_def(semanage_user_set_mlslevel)
162
163const char *semanage_user_get_mlsrange(const semanage_user_t * user)
164{
165
166	return semanage_user_base_get_mlsrange(user->base);
167}
168
169hidden_def(semanage_user_get_mlsrange)
170
171int 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
178hidden_def(semanage_user_set_mlsrange)
179
180/* Role management */
181int semanage_user_get_num_roles(const semanage_user_t * user)
182{
183
184	return semanage_user_base_get_num_roles(user->base);
185}
186
187int 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
194hidden_def(semanage_user_add_role)
195
196void semanage_user_del_role(semanage_user_t * user, const char *role)
197{
198
199	semanage_user_base_del_role(user->base, role);
200}
201
202int 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
208int 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
217hidden_def(semanage_user_get_roles)
218
219int 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 */
229int 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
258hidden_def(semanage_user_create)
259
260int 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
292hidden_def(semanage_user_clone)
293
294void 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
306hidden_def(semanage_user_free)
307
308/* Join properties */
309hidden 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
372hidden 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 */
401record_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