• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #include <stdlib.h>
2  #include <stddef.h>
3  #include <string.h>
4  
5  #include "private.h"
6  #include "debug.h"
7  #include "handle.h"
8  
9  #include <sepol/policydb/policydb.h>
10  #include <sepol/policydb/hashtab.h>
11  #include <sepol/policydb/expand.h>
12  #include "user_internal.h"
13  #include "mls.h"
14  
user_to_record(sepol_handle_t * handle,const policydb_t * policydb,int user_idx,sepol_user_t ** record)15  static int user_to_record(sepol_handle_t * handle,
16  			  const policydb_t * policydb,
17  			  int user_idx, sepol_user_t ** record)
18  {
19  
20  	const char *name = policydb->p_user_val_to_name[user_idx];
21  	user_datum_t *usrdatum = policydb->user_val_to_struct[user_idx];
22  	ebitmap_t *roles;
23  	ebitmap_node_t *rnode;
24  	unsigned bit;
25  
26  	sepol_user_t *tmp_record = NULL;
27  
28  	if (!usrdatum)
29  		goto err;
30  
31  	roles = &(usrdatum->roles.roles);
32  
33  	if (sepol_user_create(handle, &tmp_record) < 0)
34  		goto err;
35  
36  	if (sepol_user_set_name(handle, tmp_record, name) < 0)
37  		goto err;
38  
39  	/* Extract roles */
40  	ebitmap_for_each_bit(roles, rnode, bit) {
41  		if (ebitmap_node_get_bit(rnode, bit)) {
42  			char *role = policydb->p_role_val_to_name[bit];
43  			if (sepol_user_add_role(handle, tmp_record, role) < 0)
44  				goto err;
45  		}
46  	}
47  
48  	/* Extract MLS info */
49  	if (policydb->mls) {
50  		context_struct_t context;
51  		char *str;
52  
53  		context_init(&context);
54  		if (mls_level_cpy(&context.range.level[0],
55  				  &usrdatum->exp_dfltlevel) < 0) {
56  			ERR(handle, "could not copy MLS level");
57  			context_destroy(&context);
58  			goto err;
59  		}
60  		if (mls_level_cpy(&context.range.level[1],
61  				  &usrdatum->exp_dfltlevel) < 0) {
62  			ERR(handle, "could not copy MLS level");
63  			context_destroy(&context);
64  			goto err;
65  		}
66  		if (mls_to_string(handle, policydb, &context, &str) < 0) {
67  			context_destroy(&context);
68  			goto err;
69  		}
70  		context_destroy(&context);
71  
72  		if (sepol_user_set_mlslevel(handle, tmp_record, str) < 0) {
73  			free(str);
74  			goto err;
75  		}
76  		free(str);
77  
78  		context_init(&context);
79  		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
80  			ERR(handle, "could not copy MLS range");
81  			context_destroy(&context);
82  			goto err;
83  		}
84  		if (mls_to_string(handle, policydb, &context, &str) < 0) {
85  			context_destroy(&context);
86  			goto err;
87  		}
88  		context_destroy(&context);
89  
90  		if (sepol_user_set_mlsrange(handle, tmp_record, str) < 0) {
91  			free(str);
92  			goto err;
93  		}
94  		free(str);
95  	}
96  
97  	*record = tmp_record;
98  	return STATUS_SUCCESS;
99  
100        err:
101  	/* FIXME: handle error */
102  	sepol_user_free(tmp_record);
103  	return STATUS_ERR;
104  }
105  
sepol_user_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_user_key_t * key,const sepol_user_t * user)106  int sepol_user_modify(sepol_handle_t * handle,
107  		      sepol_policydb_t * p,
108  		      const sepol_user_key_t * key, const sepol_user_t * user)
109  {
110  
111  	policydb_t *policydb = &p->p;
112  
113  	/* For user data */
114  	const char *cname, *cmls_level, *cmls_range;
115  	char *name = NULL;
116  
117  	const char **roles = NULL;
118  	unsigned int num_roles = 0;
119  
120  	/* Low-level representation */
121  	user_datum_t *usrdatum = NULL;
122  	role_datum_t *roldatum;
123  	unsigned int i;
124  
125  	context_struct_t context;
126  	unsigned bit;
127  	int new = 0;
128  
129  	ebitmap_node_t *rnode;
130  
131  	/* First, extract all the data */
132  	sepol_user_key_unpack(key, &cname);
133  
134  	cmls_level = sepol_user_get_mlslevel(user);
135  	cmls_range = sepol_user_get_mlsrange(user);
136  
137  	/* Make sure that worked properly */
138  	if (sepol_user_get_roles(handle, user, &roles, &num_roles) < 0)
139  		goto err;
140  
141  	/* Now, see if a user exists */
142  	usrdatum = hashtab_search(policydb->p_users.table, cname);
143  
144  	/* If it does, we will modify it */
145  	if (usrdatum) {
146  
147  		int value_cp = usrdatum->s.value;
148  		user_datum_destroy(usrdatum);
149  		user_datum_init(usrdatum);
150  		usrdatum->s.value = value_cp;
151  
152  		/* Otherwise, create a new one */
153  	} else {
154  		usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t));
155  		if (!usrdatum)
156  			goto omem;
157  		user_datum_init(usrdatum);
158  		new = 1;
159  	}
160  
161  	/* For every role */
162  	for (i = 0; i < num_roles; i++) {
163  
164  		/* Search for the role */
165  		roldatum = hashtab_search(policydb->p_roles.table, roles[i]);
166  		if (!roldatum) {
167  			ERR(handle, "undefined role %s for user %s",
168  			    roles[i], cname);
169  			goto err;
170  		}
171  
172  		/* Set the role and every role it dominates */
173  		ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) {
174  			if (ebitmap_node_get_bit(rnode, bit)) {
175  				if (ebitmap_set_bit
176  				    (&(usrdatum->roles.roles), bit, 1))
177  					goto omem;
178  			}
179  		}
180  	}
181  
182  	/* For MLS systems */
183  	if (policydb->mls) {
184  
185  		/* MLS level */
186  		if (cmls_level == NULL) {
187  			ERR(handle, "MLS is enabled, but no MLS "
188  			    "default level was defined for user %s", cname);
189  			goto err;
190  		}
191  
192  		context_init(&context);
193  		if (mls_from_string(handle, policydb, cmls_level, &context) < 0) {
194  			context_destroy(&context);
195  			goto err;
196  		}
197  		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
198  				  &context.range.level[0]) < 0) {
199  			ERR(handle, "could not copy MLS level %s", cmls_level);
200  			context_destroy(&context);
201  			goto err;
202  		}
203  		context_destroy(&context);
204  
205  		/* MLS range */
206  		if (cmls_range == NULL) {
207  			ERR(handle, "MLS is enabled, but no MLS"
208  			    "range was defined for user %s", cname);
209  			goto err;
210  		}
211  
212  		context_init(&context);
213  		if (mls_from_string(handle, policydb, cmls_range, &context) < 0) {
214  			context_destroy(&context);
215  			goto err;
216  		}
217  		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
218  			ERR(handle, "could not copy MLS range %s", cmls_range);
219  			context_destroy(&context);
220  			goto err;
221  		}
222  		context_destroy(&context);
223  	} else if (cmls_level != NULL || cmls_range != NULL) {
224  		ERR(handle, "MLS is disabled, but MLS level/range "
225  		    "was found for user %s", cname);
226  		goto err;
227  	}
228  
229  	/* If there are no errors, and this is a new user, add the user to policy */
230  	if (new) {
231  		void *tmp_ptr;
232  
233  		/* Ensure reverse lookup array has enough space */
234  		tmp_ptr = realloc(policydb->user_val_to_struct,
235  				  (policydb->p_users.nprim +
236  				   1) * sizeof(user_datum_t *));
237  		if (!tmp_ptr)
238  			goto omem;
239  		policydb->user_val_to_struct = tmp_ptr;
240  		policydb->user_val_to_struct[policydb->p_users.nprim] = NULL;
241  
242  		tmp_ptr = realloc(policydb->sym_val_to_name[SYM_USERS],
243  				  (policydb->p_users.nprim +
244  				   1) * sizeof(char *));
245  		if (!tmp_ptr)
246  			goto omem;
247  		policydb->sym_val_to_name[SYM_USERS] = tmp_ptr;
248  		policydb->p_user_val_to_name[policydb->p_users.nprim] = NULL;
249  
250  		/* Need to copy the user name */
251  		name = strdup(cname);
252  		if (!name)
253  			goto omem;
254  
255  		/* Store user */
256  		usrdatum->s.value = ++policydb->p_users.nprim;
257  		if (hashtab_insert(policydb->p_users.table, name,
258  				   (hashtab_datum_t) usrdatum) < 0)
259  			goto omem;
260  
261  		/* Set up reverse entry */
262  		policydb->p_user_val_to_name[usrdatum->s.value - 1] = name;
263  		policydb->user_val_to_struct[usrdatum->s.value - 1] = usrdatum;
264  		name = NULL;
265  
266  		/* Expand roles */
267  		if (role_set_expand(&usrdatum->roles, &usrdatum->cache,
268  				    policydb, NULL, NULL)) {
269  			ERR(handle, "unable to expand role set");
270  			goto err;
271  		}
272  	}
273  
274  	free(roles);
275  	return STATUS_SUCCESS;
276  
277        omem:
278  	ERR(handle, "out of memory");
279  
280        err:
281  	ERR(handle, "could not load %s into policy", name);
282  
283  	free(name);
284  	free(roles);
285  	if (new && usrdatum) {
286  		role_set_destroy(&usrdatum->roles);
287  		free(usrdatum);
288  	}
289  	return STATUS_ERR;
290  }
291  
sepol_user_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_user_key_t * key,int * response)292  int sepol_user_exists(sepol_handle_t * handle __attribute__ ((unused)),
293  		      const sepol_policydb_t * p,
294  		      const sepol_user_key_t * key, int *response)
295  {
296  
297  	const policydb_t *policydb = &p->p;
298  
299  	const char *cname;
300  	sepol_user_key_unpack(key, &cname);
301  
302  	*response = (hashtab_search(policydb->p_users.table, cname) != NULL);
303  
304  	return STATUS_SUCCESS;
305  }
306  
sepol_user_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)307  int sepol_user_count(sepol_handle_t * handle __attribute__ ((unused)),
308  		     const sepol_policydb_t * p, unsigned int *response)
309  {
310  
311  	const policydb_t *policydb = &p->p;
312  	*response = policydb->p_users.nprim;
313  
314  	return STATUS_SUCCESS;
315  }
316  
sepol_user_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_user_key_t * key,sepol_user_t ** response)317  int sepol_user_query(sepol_handle_t * handle,
318  		     const sepol_policydb_t * p,
319  		     const sepol_user_key_t * key, sepol_user_t ** response)
320  {
321  
322  	const policydb_t *policydb = &p->p;
323  	user_datum_t *usrdatum = NULL;
324  
325  	const char *cname;
326  	sepol_user_key_unpack(key, &cname);
327  
328  	usrdatum = hashtab_search(policydb->p_users.table, cname);
329  
330  	if (!usrdatum) {
331  		*response = NULL;
332  		return STATUS_SUCCESS;
333  	}
334  
335  	if (user_to_record(handle, policydb, usrdatum->s.value - 1, response) <
336  	    0)
337  		goto err;
338  
339  	return STATUS_SUCCESS;
340  
341        err:
342  	ERR(handle, "could not query user %s", cname);
343  	return STATUS_ERR;
344  }
345  
sepol_user_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_user_t * user,void * fn_arg),void * arg)346  int sepol_user_iterate(sepol_handle_t * handle,
347  		       const sepol_policydb_t * p,
348  		       int (*fn) (const sepol_user_t * user,
349  				  void *fn_arg), void *arg)
350  {
351  
352  	const policydb_t *policydb = &p->p;
353  	unsigned int nusers = policydb->p_users.nprim;
354  	sepol_user_t *user = NULL;
355  	unsigned int i;
356  
357  	/* For each user */
358  	for (i = 0; i < nusers; i++) {
359  
360  		int status;
361  
362  		if (user_to_record(handle, policydb, i, &user) < 0)
363  			goto err;
364  
365  		/* Invoke handler */
366  		status = fn(user, arg);
367  		if (status < 0)
368  			goto err;
369  
370  		sepol_user_free(user);
371  		user = NULL;
372  
373  		/* Handler requested exit */
374  		if (status > 0)
375  			break;
376  	}
377  
378  	return STATUS_SUCCESS;
379  
380        err:
381  	ERR(handle, "could not iterate over users");
382  	sepol_user_free(user);
383  	return STATUS_ERR;
384  }
385