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