user_record.c revision 255e72915d4cbddceb435e13d81601755714e9f3
11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <errno.h>
21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <stdlib.h>
31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <string.h>
41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "user_internal.h"
61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "debug.h"
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct sepol_user {
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* This user's name */
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	char *name;
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* This user's mls level (only required for mls) */
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	char *mls_level;
141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* This user's mls range (only required for mls) */
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	char *mls_range;
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* The role array */
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	char **roles;
201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* The number of roles */
221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	unsigned int num_roles;
231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistruct sepol_user_key {
261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	/* This user's name */
271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	const char *name;
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci};
291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint sepol_user_key_create(sepol_handle_t * handle,
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			  const char *name, sepol_user_key_t ** key_ptr)
321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	sepol_user_key_t *tmp_key =
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	    (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t));
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	if (!tmp_key) {
381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		ERR(handle, "out of memory, "
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		    "could not create selinux user key");
401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		return STATUS_ERR;
411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	}
421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	tmp_key->name = name;
441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	*key_ptr = tmp_key;
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	return STATUS_SUCCESS;
47}
48
49hidden_def(sepol_user_key_create)
50
51void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
52{
53
54	*name = key->name;
55}
56
57hidden_def(sepol_user_key_unpack)
58
59int 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
72void sepol_user_key_free(sepol_user_key_t * key)
73{
74	free(key);
75}
76
77int 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
83int 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 */
90const char *sepol_user_get_name(const sepol_user_t * user)
91{
92
93	return user->name;
94}
95
96int 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
110hidden_def(sepol_user_set_name)
111
112/* MLS */
113const char *sepol_user_get_mlslevel(const sepol_user_t * user)
114{
115
116	return user->mls_level;
117}
118
119hidden_def(sepol_user_get_mlslevel)
120
121int 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
136hidden_def(sepol_user_set_mlslevel)
137
138const char *sepol_user_get_mlsrange(const sepol_user_t * user)
139{
140
141	return user->mls_range;
142}
143
144hidden_def(sepol_user_get_mlsrange)
145
146int 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
161hidden_def(sepol_user_set_mlsrange)
162
163/* Roles */
164int sepol_user_get_num_roles(const sepol_user_t * user)
165{
166
167	return user->num_roles;
168}
169
170int 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
200hidden_def(sepol_user_add_role)
201
202int 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
213hidden_def(sepol_user_has_role)
214
215int 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
260int 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
285hidden_def(sepol_user_get_roles)
286
287void 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 */
302int 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
323hidden_def(sepol_user_create)
324
325/* Deep copy clone */
326int 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 */
362void 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
379hidden_def(sepol_user_free)
380