1 /*
2 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 * The views and conclusions contained in the software and documentation are those
26 * of the authors and should not be interpreted as representing official policies,
27 * either expressed or implied, of Tresys Technology, LLC.
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <inttypes.h>
36
37 #include <sepol/policydb/conditional.h>
38 #include <sepol/errcodes.h>
39
40 #include "cil_internal.h"
41 #include "cil_flavor.h"
42 #include "cil_log.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_policy.h"
47 #include "cil_symtab.h"
48 #include "cil_strpool.h"
49
50 #define SEPOL_DONE 555
51
52 #define CLASS_DECL 0
53 #define ISIDS 1
54 #define COMMONS 2
55 #define CLASSES 3
56 #define INTERFACES 4
57 #define SENS 5
58 #define CATS 6
59 #define LEVELS 7
60 #define CONSTRAINS 8
61 #define TYPEATTRTYPES 9
62 #define ALIASES 10
63 #define ALLOWS 11
64 #define CONDS 12
65 #define USERROLES 13
66 #define SIDS 14
67 #define NETIFCONS 15
68
69 #define BUFFER 1024
70 #define NUM_POLICY_FILES 16
71
72 struct cil_args_genpolicy {
73 struct cil_list *users;
74 struct cil_list *sens;
75 struct cil_list *cats;
76 FILE **file_arr;
77 };
78
79 struct cil_args_booleanif {
80 FILE **file_arr;
81 uint32_t *file_index;
82 };
83
84
85 int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr);
86
cil_combine_policy(FILE ** file_arr,FILE * policy_file)87 int cil_combine_policy(FILE **file_arr, FILE *policy_file)
88 {
89 char temp[BUFFER];
90 int i, rc, rc_read, rc_write;
91
92 for(i=0; i<NUM_POLICY_FILES; i++) {
93 fseek(file_arr[i], 0, SEEK_SET);
94 while (!feof(file_arr[i])) {
95 rc_read = fread(temp, 1, BUFFER, file_arr[i]);
96 if (rc_read == 0 && ferror(file_arr[i])) {
97 cil_log(CIL_ERR, "Error reading temp policy file\n");
98 return SEPOL_ERR;
99 }
100 rc_write = 0;
101 while (rc_read > rc_write) {
102 rc = fwrite(temp+rc_write, 1, rc_read-rc_write, policy_file);
103 rc_write += rc;
104 if (rc == 0 && ferror(file_arr[i])) {
105 cil_log(CIL_ERR, "Error writing to policy.conf\n");
106 return SEPOL_ERR;
107 }
108 }
109 }
110 }
111
112 return SEPOL_OK;
113 }
114
cil_portcon_to_policy(FILE ** file_arr,struct cil_sort * sort)115 int cil_portcon_to_policy(FILE **file_arr, struct cil_sort *sort)
116 {
117 uint32_t i = 0;
118
119 for (i=0; i<sort->count; i++) {
120 struct cil_portcon *portcon = (struct cil_portcon*)sort->array[i];
121 fprintf(file_arr[NETIFCONS], "portcon ");
122 if (portcon->proto == CIL_PROTOCOL_UDP) {
123 fprintf(file_arr[NETIFCONS], "udp ");
124 } else if (portcon->proto == CIL_PROTOCOL_TCP) {
125 fprintf(file_arr[NETIFCONS], "tcp ");
126 }
127 fprintf(file_arr[NETIFCONS], "%d ", portcon->port_low);
128 fprintf(file_arr[NETIFCONS], "%d ", portcon->port_high);
129 cil_context_to_policy(file_arr, NETIFCONS, portcon->context);
130 fprintf(file_arr[NETIFCONS], ";\n");
131 }
132
133 return SEPOL_OK;
134 }
135
cil_genfscon_to_policy(FILE ** file_arr,struct cil_sort * sort)136 int cil_genfscon_to_policy(FILE **file_arr, struct cil_sort *sort)
137 {
138 uint32_t i = 0;
139
140 for (i=0; i<sort->count; i++) {
141 struct cil_genfscon *genfscon = (struct cil_genfscon*)sort->array[i];
142 fprintf(file_arr[NETIFCONS], "genfscon %s ", genfscon->fs_str);
143 fprintf(file_arr[NETIFCONS], "%s ", genfscon->path_str);
144 cil_context_to_policy(file_arr, NETIFCONS, genfscon->context);
145 fprintf(file_arr[NETIFCONS], ";\n");
146 }
147
148 return SEPOL_OK;
149 }
150
cil_netifcon_to_policy(FILE ** file_arr,struct cil_sort * sort)151 int cil_netifcon_to_policy(FILE **file_arr, struct cil_sort *sort)
152 {
153 uint32_t i = 0;
154
155 for (i=0; i<sort->count; i++) {
156 struct cil_netifcon *netifcon = (struct cil_netifcon*)sort->array[i];
157 fprintf(file_arr[NETIFCONS], "netifcon %s ", netifcon->interface_str);
158 cil_context_to_policy(file_arr, NETIFCONS, netifcon->if_context);
159 fprintf(file_arr[NETIFCONS], " ");
160 cil_context_to_policy(file_arr, NETIFCONS, netifcon->packet_context);
161 fprintf(file_arr[NETIFCONS], ";\n");
162 }
163
164 return SEPOL_OK;
165 }
166
cil_nodecon_to_policy(FILE ** file_arr,struct cil_sort * sort)167 int cil_nodecon_to_policy(FILE **file_arr, struct cil_sort *sort)
168 {
169 uint32_t i = 0;
170 int rc = SEPOL_ERR;
171
172 for (i=0; i<sort->count; i++) {
173 struct cil_nodecon *nodecon = (struct cil_nodecon*)sort->array[i];
174 char *buf = NULL;
175 errno = 0;
176 if (nodecon->addr->family == AF_INET) {
177 buf = cil_malloc(INET_ADDRSTRLEN);
178 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, buf, INET_ADDRSTRLEN);
179 } else if (nodecon->addr->family == AF_INET6) {
180 buf = cil_malloc(INET6_ADDRSTRLEN);
181 inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, buf, INET6_ADDRSTRLEN);
182 }
183
184 if (errno != 0) {
185 cil_log(CIL_INFO, "Failed to convert ip address to string\n");
186 rc = SEPOL_ERR;
187 goto exit;
188 }
189
190 fprintf(file_arr[NETIFCONS], "nodecon %s ", buf);
191 free(buf);
192
193 if (nodecon->mask->family == AF_INET) {
194 buf = cil_malloc(INET_ADDRSTRLEN);
195 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, buf, INET_ADDRSTRLEN);
196 } else if (nodecon->mask->family == AF_INET6) {
197 buf = cil_malloc(INET6_ADDRSTRLEN);
198 inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, buf, INET6_ADDRSTRLEN);
199 }
200
201 if (errno != 0) {
202 cil_log(CIL_INFO, "Failed to convert mask to string\n");
203 rc = SEPOL_ERR;
204 goto exit;
205 }
206
207 fprintf(file_arr[NETIFCONS], "%s ", buf);
208 free(buf);
209
210 cil_context_to_policy(file_arr, NETIFCONS, nodecon->context);
211 fprintf(file_arr[NETIFCONS], ";\n");
212 }
213
214 return SEPOL_OK;
215
216 exit:
217 return rc;
218 }
219
220
cil_pirqcon_to_policy(FILE ** file_arr,struct cil_sort * sort)221 int cil_pirqcon_to_policy(FILE **file_arr, struct cil_sort *sort)
222 {
223 uint32_t i = 0;
224
225 for (i = 0; i < sort->count; i++) {
226 struct cil_pirqcon *pirqcon = (struct cil_pirqcon*)sort->array[i];
227 fprintf(file_arr[NETIFCONS], "pirqcon %d ", pirqcon->pirq);
228 cil_context_to_policy(file_arr, NETIFCONS, pirqcon->context);
229 fprintf(file_arr[NETIFCONS], ";\n");
230 }
231
232 return SEPOL_OK;
233 }
cil_iomemcon_to_policy(FILE ** file_arr,struct cil_sort * sort)234 int cil_iomemcon_to_policy(FILE **file_arr, struct cil_sort *sort)
235 {
236 uint32_t i = 0;
237
238 for (i = 0; i < sort->count; i++) {
239 struct cil_iomemcon *iomemcon = (struct cil_iomemcon*)sort->array[i];
240 fprintf(file_arr[NETIFCONS], "iomemcon %"PRId64"-%"PRId64" ", iomemcon->iomem_low, iomemcon->iomem_high);
241 cil_context_to_policy(file_arr, NETIFCONS, iomemcon->context);
242 fprintf(file_arr[NETIFCONS], ";\n");
243 }
244
245 return SEPOL_OK;
246 }
247
cil_ioportcon_to_policy(FILE ** file_arr,struct cil_sort * sort)248 int cil_ioportcon_to_policy(FILE **file_arr, struct cil_sort *sort)
249 {
250 uint32_t i = 0;
251
252 for (i = 0; i < sort->count; i++) {
253 struct cil_ioportcon *ioportcon = (struct cil_ioportcon*)sort->array[i];
254 fprintf(file_arr[NETIFCONS], "ioportcon %d-%d ", ioportcon->ioport_low, ioportcon->ioport_high);
255 cil_context_to_policy(file_arr, NETIFCONS, ioportcon->context);
256 fprintf(file_arr[NETIFCONS], ";\n");
257 }
258
259 return SEPOL_OK;
260 }
261
cil_pcidevicecon_to_policy(FILE ** file_arr,struct cil_sort * sort)262 int cil_pcidevicecon_to_policy(FILE **file_arr, struct cil_sort *sort)
263 {
264 uint32_t i = 0;
265
266 for (i = 0; i < sort->count; i++) {
267 struct cil_pcidevicecon *pcidevicecon = (struct cil_pcidevicecon*)sort->array[i];
268 fprintf(file_arr[NETIFCONS], "pcidevicecon %d ", pcidevicecon->dev);
269 cil_context_to_policy(file_arr, NETIFCONS, pcidevicecon->context);
270 fprintf(file_arr[NETIFCONS], ";\n");
271 }
272
273 return SEPOL_OK;
274 }
275
cil_fsuse_to_policy(FILE ** file_arr,struct cil_sort * sort)276 int cil_fsuse_to_policy(FILE **file_arr, struct cil_sort *sort)
277 {
278 uint32_t i = 0;
279
280 for (i=0; i<sort->count; i++) {
281 struct cil_fsuse *fsuse = (struct cil_fsuse*)sort->array[i];
282 if (fsuse->type == CIL_FSUSE_XATTR) {
283 fprintf(file_arr[NETIFCONS], "fs_use_xattr ");
284 } else if (fsuse->type == CIL_FSUSE_TASK) {
285 fprintf(file_arr[NETIFCONS], "fs_use_task ");
286 } else if (fsuse->type == CIL_FSUSE_TRANS) {
287 fprintf(file_arr[NETIFCONS], "fs_use_trans ");
288 } else {
289 return SEPOL_ERR;
290 }
291 fprintf(file_arr[NETIFCONS], "%s ", fsuse->fs_str);
292 cil_context_to_policy(file_arr, NETIFCONS, fsuse->context);
293 fprintf(file_arr[NETIFCONS], ";\n");
294 }
295
296 return SEPOL_OK;
297 }
298
cil_multimap_insert(struct cil_list * list,struct cil_symtab_datum * key,struct cil_symtab_datum * value,uint32_t key_flavor,uint32_t val_flavor)299 int cil_multimap_insert(struct cil_list *list, struct cil_symtab_datum *key, struct cil_symtab_datum *value, uint32_t key_flavor, uint32_t val_flavor)
300 {
301 struct cil_list_item *curr_key;
302 struct cil_multimap_item *new_data;
303
304 if (list == NULL || key == NULL) {
305 return SEPOL_ERR;
306 }
307
308 cil_list_for_each(curr_key, list) {
309 struct cil_multimap_item *curr_multimap_item = curr_key->data;
310 if (curr_multimap_item != NULL) {
311 if (curr_multimap_item->key != NULL && curr_multimap_item->key == key) {
312 struct cil_list_item *curr_value;
313 cil_list_for_each(curr_value, curr_multimap_item->values) {
314 if (curr_value == (struct cil_list_item*)value) {
315 return SEPOL_OK;;
316 }
317 }
318 cil_list_append(curr_multimap_item->values, val_flavor, value);
319 }
320 } else {
321 cil_log(CIL_INFO, "No data in list item\n");
322 return SEPOL_ERR;
323 }
324 }
325
326 new_data = cil_malloc(sizeof(*new_data));
327 new_data->key = key;
328 cil_list_init(&new_data->values, CIL_LIST_ITEM);
329 if (value != NULL) {
330 cil_list_append(new_data->values, val_flavor, value);
331 }
332 cil_list_append(list, key_flavor, new_data);
333
334 return SEPOL_OK;
335 }
336
cil_userrole_to_policy(FILE ** file_arr,struct cil_list * userroles)337 int cil_userrole_to_policy(FILE **file_arr, struct cil_list *userroles)
338 {
339 struct cil_list_item *current_user;
340
341 if (userroles == NULL) {
342 return SEPOL_OK;
343 }
344
345 cil_list_for_each(current_user, userroles) {
346 struct cil_multimap_item *user_multimap_item = current_user->data;
347 struct cil_list_item *current_role;
348 if (user_multimap_item->values->head == NULL) {
349 cil_log(CIL_INFO, "No roles associated with user %s\n",
350 user_multimap_item->key->name);
351 return SEPOL_ERR;
352 }
353
354 fprintf(file_arr[USERROLES], "user %s roles {", user_multimap_item->key->name);
355
356 cil_list_for_each(current_role, user_multimap_item->values) {
357 fprintf(file_arr[USERROLES], " %s", ((struct cil_role*)current_role->data)->datum.name);
358 }
359 fprintf(file_arr[USERROLES], " };\n");
360 }
361
362 return SEPOL_OK;
363 }
364
cil_cat_to_policy(FILE ** file_arr,struct cil_list * cats)365 int cil_cat_to_policy(FILE **file_arr, struct cil_list *cats)
366 {
367 struct cil_list_item *curr_cat;
368
369 if (cats == NULL) {
370 return SEPOL_OK;
371 }
372
373 cil_list_for_each(curr_cat, cats) {
374 struct cil_multimap_item *cat_multimap_item = curr_cat->data;
375 fprintf(file_arr[CATS], "category %s", cat_multimap_item->key->name);
376 if (cat_multimap_item->values->head == NULL) {
377 fprintf(file_arr[CATS], ";\n");
378 } else {
379 struct cil_list_item *curr_catalias;
380 fprintf(file_arr[CATS], " alias");
381 cil_list_for_each(curr_catalias, cat_multimap_item->values) {
382 fprintf(file_arr[CATS], " %s", ((struct cil_cat*)curr_catalias->data)->datum.name);
383 }
384 fprintf(file_arr[CATS], ";\n");
385 }
386 }
387
388 return SEPOL_OK;
389 }
390
cil_sens_to_policy(FILE ** file_arr,struct cil_list * sens)391 int cil_sens_to_policy(FILE **file_arr, struct cil_list *sens)
392 {
393 struct cil_list_item *curr_sens;
394
395 if (sens == NULL) {
396 return SEPOL_OK;
397 }
398
399 cil_list_for_each(curr_sens, sens) {
400 struct cil_multimap_item *sens_multimap_item = curr_sens->data;
401 fprintf(file_arr[SENS], "sensitivity %s", sens_multimap_item->key->name);
402 if (sens_multimap_item->values->head == NULL)
403 fprintf(file_arr[SENS], ";\n");
404 else {
405 struct cil_list_item *curr_sensalias;
406 fprintf(file_arr[SENS], " alias");
407 cil_list_for_each(curr_sensalias, sens_multimap_item->values) {
408 fprintf(file_arr[SENS], " %s", ((struct cil_sens*)curr_sensalias->data)->datum.name);
409 }
410 fprintf(file_arr[SENS], ";\n");
411 }
412 }
413
414 return SEPOL_OK;
415 }
416
cil_cats_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_cats * cats)417 void cil_cats_to_policy(FILE **file_arr, uint32_t file_index, struct cil_cats *cats)
418 {
419 cil_expr_to_policy(file_arr, file_index, cats->datum_expr);
420 }
421
cil_level_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_level * level)422 void cil_level_to_policy(FILE **file_arr, uint32_t file_index, struct cil_level *level)
423 {
424 char *sens_str = level->sens->datum.name;
425
426 fprintf(file_arr[file_index], "%s", sens_str);
427 if (level->cats != NULL) {
428 fprintf(file_arr[file_index], ":");
429 cil_cats_to_policy(file_arr, file_index, level->cats);
430 }
431 }
432
cil_levelrange_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_levelrange * lvlrange)433 void cil_levelrange_to_policy(FILE **file_arr, uint32_t file_index, struct cil_levelrange *lvlrange)
434 {
435 struct cil_level *low = lvlrange->low;
436 struct cil_level *high = lvlrange->high;
437
438 cil_level_to_policy(file_arr, file_index, low);
439 fprintf(file_arr[file_index], "-");
440 cil_level_to_policy(file_arr, file_index, high);
441 }
442
cil_context_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_context * context)443 void cil_context_to_policy(FILE **file_arr, uint32_t file_index, struct cil_context *context)
444 {
445 char *user_str = ((struct cil_symtab_datum*)context->user)->name;
446 char *role_str = ((struct cil_symtab_datum*)context->role)->name;
447 char *type_str = ((struct cil_symtab_datum*)context->type)->name;
448 struct cil_levelrange *lvlrange = context->range;
449
450 fprintf(file_arr[file_index], "%s:%s:%s:", user_str, role_str, type_str);
451 cil_levelrange_to_policy(file_arr, file_index, lvlrange);
452 }
453
cil_perms_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_list * list)454 void cil_perms_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *list)
455 {
456 struct cil_list_item *curr;
457
458 fprintf(file_arr[file_index], " {");
459 cil_list_for_each(curr, list) {
460 switch (curr->flavor) {
461 case CIL_LIST:
462 cil_perms_to_policy(file_arr, file_index, curr->data);
463 break;
464 case CIL_STRING:
465 fprintf(file_arr[file_index], " %s", (char *)curr->data);
466 break;
467 case CIL_DATUM:
468 fprintf(file_arr[file_index], " %s", ((struct cil_symtab_datum *)curr->data)->name);
469 break;
470 case CIL_OP: {
471 enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
472 char *op_str = NULL;
473
474 switch (op_flavor) {
475 case CIL_AND:
476 op_str = CIL_KEY_AND;
477 break;
478 case CIL_OR:
479 op_str = CIL_KEY_OR;
480 break;
481 case CIL_NOT:
482 op_str = CIL_KEY_NOT;
483 break;
484 case CIL_ALL:
485 op_str = CIL_KEY_ALL;
486 break;
487 case CIL_XOR:
488 op_str = CIL_KEY_XOR;
489 break;
490 default:
491 cil_log(CIL_ERR, "Unknown operator in expression\n");
492 break;
493 }
494 fprintf(file_arr[file_index], " %s", op_str);
495 break;
496 }
497 default:
498 cil_log(CIL_ERR, "Unknown flavor in expression\n");
499 break;
500 }
501 }
502 fprintf(file_arr[file_index], " }");
503 }
504
cil_constrain_to_policy_helper(FILE ** file_arr,char * kind,struct cil_list * classperms,struct cil_list * expr)505 void cil_constrain_to_policy_helper(FILE **file_arr, char *kind, struct cil_list *classperms, struct cil_list *expr)
506 {
507 struct cil_list_item *curr;
508
509 cil_list_for_each(curr, classperms) {
510 if (curr->flavor == CIL_CLASSPERMS) {
511 struct cil_classperms *cp = curr->data;
512 if (FLAVOR(cp->class) == CIL_CLASS) {
513 fprintf(file_arr[CONSTRAINS], "%s %s", kind, cp->class->datum.name);
514 cil_perms_to_policy(file_arr, CONSTRAINS, cp->perms);
515 fprintf(file_arr[CONSTRAINS], "\n\t");
516 cil_expr_to_policy(file_arr, CONSTRAINS, expr);
517 fprintf(file_arr[CONSTRAINS], ";\n");
518 } else { /* MAP */
519 struct cil_list_item *i = NULL;
520 cil_list_for_each(i, cp->perms) {
521 struct cil_perm *cmp = i->data;
522 cil_constrain_to_policy_helper(file_arr, kind, cmp->classperms, expr);
523 }
524 }
525 } else { /* SET */
526 struct cil_classperms_set *cp_set = curr->data;
527 struct cil_classpermission *cp = cp_set->set;
528 cil_constrain_to_policy_helper(file_arr, kind, cp->classperms, expr);
529 }
530 }
531 }
532
cil_constrain_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_constrain * cons,enum cil_flavor flavor)533 void cil_constrain_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_constrain *cons, enum cil_flavor flavor)
534 {
535 char *kind = NULL;
536
537 if (flavor == CIL_CONSTRAIN) {
538 kind = CIL_KEY_CONSTRAIN;
539 } else if (flavor == CIL_MLSCONSTRAIN) {
540 kind = CIL_KEY_MLSCONSTRAIN;
541 }
542
543 cil_constrain_to_policy_helper(file_arr, kind, cons->classperms, cons->datum_expr);
544 }
545
cil_avrule_to_policy_helper(FILE ** file_arr,uint32_t file_index,const char * kind,const char * src,const char * tgt,struct cil_list * classperms)546 void cil_avrule_to_policy_helper(FILE **file_arr, uint32_t file_index, const char *kind, const char *src, const char *tgt, struct cil_list *classperms)
547 {
548 struct cil_list_item *i;
549
550 cil_list_for_each(i, classperms) {
551 if (i->flavor == CIL_CLASSPERMS) {
552 struct cil_classperms *cp = i->data;
553 if (FLAVOR(cp->class) == CIL_CLASS) {
554 fprintf(file_arr[file_index], "%s %s %s: %s", kind, src, tgt, cp->class->datum.name);
555 cil_perms_to_policy(file_arr, file_index, cp->perms);
556 fprintf(file_arr[file_index], ";\n");
557 } else { /* MAP */
558 struct cil_list_item *j = NULL;
559 cil_list_for_each(j, cp->perms) {
560 struct cil_perm *cmp = j->data;
561 cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, cmp->classperms);
562 }
563 }
564 } else { /* SET */
565 struct cil_list_item *j;
566 struct cil_classperms_set *cp_set = i->data;
567 struct cil_classpermission *cp = cp_set->set;
568 cil_list_for_each(j, cp->classperms) {
569 cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, j->data);
570 }
571 }
572 }
573 }
574
cil_avrule_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_avrule * rule)575 int cil_avrule_to_policy(FILE **file_arr, uint32_t file_index, struct cil_avrule *rule)
576 {
577 const char *kind_str = NULL;
578 const char *src_str = DATUM(rule->src)->name;
579 const char *tgt_str = DATUM(rule->tgt)->name;
580
581
582 switch (rule->rule_kind) {
583 case CIL_AVRULE_ALLOWED:
584 kind_str = "allow";
585 break;
586 case CIL_AVRULE_AUDITALLOW:
587 kind_str = "auditallow";
588 break;
589 case CIL_AVRULE_DONTAUDIT:
590 kind_str = "dontaudit";
591 break;
592 case CIL_AVRULE_NEVERALLOW:
593 kind_str = "neverallow";
594 break;
595 default :
596 cil_log(CIL_INFO, "Unknown avrule with kind=%d src=%s tgt=%s\n",
597 rule->rule_kind, src_str, tgt_str);
598 return SEPOL_ERR;
599 }
600
601 cil_avrule_to_policy_helper(file_arr, file_index, kind_str, src_str, tgt_str, rule->classperms);
602
603 return SEPOL_OK;
604 }
605
cil_typerule_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_type_rule * rule)606 int cil_typerule_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_type_rule *rule)
607 {
608 char *src_str = ((struct cil_symtab_datum*)rule->src)->name;
609 char *tgt_str = ((struct cil_symtab_datum*)rule->tgt)->name;
610 char *obj_str = ((struct cil_symtab_datum*)rule->obj)->name;
611 char *result_str = ((struct cil_symtab_datum*)rule->result)->name;
612
613 switch (rule->rule_kind) {
614 case CIL_TYPE_TRANSITION:
615 fprintf(file_arr[ALLOWS], "type_transition %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
616 break;
617 case CIL_TYPE_CHANGE:
618 fprintf(file_arr[ALLOWS], "type_change %s %s : %s %s\n;", src_str, tgt_str, obj_str, result_str);
619 break;
620 case CIL_TYPE_MEMBER:
621 fprintf(file_arr[ALLOWS], "type_member %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
622 break;
623 default:
624 cil_log(CIL_INFO, "Unknown type_rule\n");
625 return SEPOL_ERR;
626 }
627
628 return SEPOL_OK;
629 }
630
cil_nametypetransition_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_nametypetransition * nametypetrans)631 int cil_nametypetransition_to_policy(FILE **file_arr, uint32_t file_index, struct cil_nametypetransition *nametypetrans)
632 {
633 char *src_str = ((struct cil_symtab_datum*)nametypetrans->src)->name;
634 char *tgt_str = ((struct cil_symtab_datum*)nametypetrans->tgt)->name;
635 char *obj_str = ((struct cil_symtab_datum*)nametypetrans->obj)->name;
636 char *result_str = ((struct cil_symtab_datum*)nametypetrans->result)->name;
637
638 fprintf(file_arr[file_index], "type_transition %s %s : %s %s %s;\n", src_str, tgt_str, obj_str, result_str, nametypetrans->name_str);
639 return SEPOL_OK;
640 }
641
cil_expr_to_string(struct cil_list * expr,char ** out)642 static int cil_expr_to_string(struct cil_list *expr, char **out)
643 {
644 int rc = SEPOL_ERR;
645 struct cil_list_item *curr;
646 char *stack[COND_EXPR_MAXDEPTH] = {};
647 int pos = 0;
648 int i;
649
650 cil_list_for_each(curr, expr) {
651 if (pos > COND_EXPR_MAXDEPTH) {
652 rc = SEPOL_ERR;
653 goto exit;
654 }
655 switch (curr->flavor) {
656 case CIL_LIST:
657 rc = cil_expr_to_string(curr->data, &stack[pos]);
658 if (rc != SEPOL_OK) {
659 goto exit;
660 }
661 pos++;
662 break;
663 case CIL_STRING:
664 stack[pos] = curr->data;
665 pos++;
666 break;
667 case CIL_DATUM:
668 stack[pos] = ((struct cil_symtab_datum *)curr->data)->name;
669 pos++;
670 break;
671 case CIL_OP: {
672 int len;
673 char *expr_str;
674 enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
675 char *op_str = NULL;
676
677 if (pos == 0) {
678 rc = SEPOL_ERR;
679 goto exit;
680 }
681 switch (op_flavor) {
682 case CIL_AND:
683 op_str = CIL_KEY_AND;
684 break;
685 case CIL_OR:
686 op_str = CIL_KEY_OR;
687 break;
688 case CIL_NOT:
689 op_str = CIL_KEY_NOT;
690 break;
691 case CIL_ALL:
692 op_str = CIL_KEY_ALL;
693 break;
694 case CIL_EQ:
695 op_str = CIL_KEY_EQ;
696 break;
697 case CIL_NEQ:
698 op_str = CIL_KEY_NEQ;
699 break;
700 case CIL_XOR:
701 op_str = CIL_KEY_XOR;
702 break;
703 case CIL_CONS_DOM:
704 op_str = CIL_KEY_CONS_DOM;
705 break;
706 case CIL_CONS_DOMBY:
707 op_str = CIL_KEY_CONS_DOMBY;
708 break;
709 case CIL_CONS_INCOMP:
710 op_str = CIL_KEY_CONS_INCOMP;
711 break;
712 default:
713 cil_log(CIL_ERR, "Unknown operator in expression\n");
714 goto exit;
715 break;
716 }
717 if (op_flavor == CIL_NOT) {
718 len = strlen(stack[pos-1]) + strlen(op_str) + 4;
719 expr_str = cil_malloc(len);
720 snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]);
721 free(stack[pos-1]);
722 stack[pos-1] = NULL;
723 pos--;
724 } else {
725 if (pos < 2) {
726 rc = SEPOL_ERR;
727 goto exit;
728 }
729 len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5;
730 expr_str = cil_malloc(len);
731 snprintf(expr_str, len, "(%s %s %s)", stack[pos-1], op_str, stack[pos-2]);
732 free(stack[pos-2]);
733 free(stack[pos-1]);
734 stack[pos-2] = NULL;
735 stack[pos-1] = NULL;
736 pos -= 2;
737 }
738 stack[pos] = expr_str;
739 pos++;
740 break;
741 }
742 case CIL_CONS_OPERAND: {
743 enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data);
744 char *operand_str = NULL;
745 switch (operand_flavor) {
746 case CIL_CONS_U1:
747 operand_str = CIL_KEY_CONS_U1;
748 break;
749 case CIL_CONS_U2:
750 operand_str = CIL_KEY_CONS_U2;
751 break;
752 case CIL_CONS_U3:
753 operand_str = CIL_KEY_CONS_U3;
754 break;
755 case CIL_CONS_T1:
756 operand_str = CIL_KEY_CONS_T1;
757 break;
758 case CIL_CONS_T2:
759 operand_str = CIL_KEY_CONS_T2;
760 break;
761 case CIL_CONS_T3:
762 operand_str = CIL_KEY_CONS_T3;
763 break;
764 case CIL_CONS_R1:
765 operand_str = CIL_KEY_CONS_R1;
766 break;
767 case CIL_CONS_R2:
768 operand_str = CIL_KEY_CONS_R2;
769 break;
770 case CIL_CONS_R3:
771 operand_str = CIL_KEY_CONS_R3;
772 break;
773 case CIL_CONS_L1:
774 operand_str = CIL_KEY_CONS_L1;
775 break;
776 case CIL_CONS_L2:
777 operand_str = CIL_KEY_CONS_L2;
778 break;
779 case CIL_CONS_H1:
780 operand_str = CIL_KEY_CONS_H1;
781 break;
782 case CIL_CONS_H2:
783 operand_str = CIL_KEY_CONS_H2;
784 break;
785 default:
786 cil_log(CIL_ERR, "Unknown operand in expression\n");
787 goto exit;
788 break;
789 }
790 stack[pos] = operand_str;
791 pos++;
792 break;
793 }
794 default:
795 cil_log(CIL_ERR, "Unknown flavor in expression\n");
796 goto exit;
797 break;
798 }
799 }
800
801 *out = stack[0];
802
803 return SEPOL_OK;
804
805 exit:
806 for (i = 0; i < pos; i++) {
807 free(stack[i]);
808 }
809 return rc;
810 }
811
cil_expr_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_list * expr)812 int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr)
813 {
814 int rc = SEPOL_ERR;
815 char *str_out;
816
817 rc = cil_expr_to_string(expr, &str_out);
818 if (rc != SEPOL_OK) {
819 goto out;
820 }
821 fprintf(file_arr[file_index], "%s", str_out);
822 free(str_out);
823
824 return SEPOL_OK;
825
826 out:
827 return rc;
828 }
829
__cil_booleanif_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)830 int __cil_booleanif_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
831 {
832 int rc = SEPOL_ERR;
833 struct cil_args_booleanif *args;
834 FILE **file_arr;
835 uint32_t *file_index;
836
837 args = extra_args;
838 file_arr = args->file_arr;
839 file_index = args->file_index;
840
841 switch (node->flavor) {
842 case CIL_AVRULE:
843 rc = cil_avrule_to_policy(file_arr, *file_index, (struct cil_avrule*)node->data);
844 if (rc != SEPOL_OK) {
845 cil_log(CIL_INFO, "cil_avrule_to_policy failed, rc: %d\n", rc);
846 return rc;
847 }
848 break;
849 case CIL_TYPE_RULE:
850 rc = cil_typerule_to_policy(file_arr, *file_index, (struct cil_type_rule*)node->data);
851 if (rc != SEPOL_OK) {
852 cil_log(CIL_INFO, "cil_typerule_to_policy failed, rc: %d\n", rc);
853 return rc;
854 }
855 break;
856 case CIL_FALSE:
857 fprintf(file_arr[*file_index], "else {\n");
858 break;
859 case CIL_TRUE:
860 break;
861 default:
862 return SEPOL_ERR;
863 }
864
865 return SEPOL_OK;
866 }
867
__cil_booleanif_last_child_helper(struct cil_tree_node * node,void * extra_args)868 int __cil_booleanif_last_child_helper(struct cil_tree_node *node, void *extra_args)
869 {
870 struct cil_args_booleanif *args;
871 FILE **file_arr;
872 uint32_t *file_index;
873
874 args = extra_args;
875 file_arr = args->file_arr;
876 file_index = args->file_index;
877
878 if (node->parent->flavor == CIL_FALSE) {
879 fprintf(file_arr[*file_index], "}\n");
880 }
881
882 return SEPOL_OK;
883 }
884
cil_booleanif_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_tree_node * node)885 int cil_booleanif_to_policy(FILE **file_arr, uint32_t file_index, struct cil_tree_node *node)
886 {
887 int rc = SEPOL_ERR;
888 struct cil_booleanif *bif = node->data;
889 struct cil_list *expr = bif->datum_expr;
890 struct cil_args_booleanif extra_args;
891 struct cil_tree_node *true_node = NULL;
892 struct cil_tree_node *false_node = NULL;
893 struct cil_condblock *cb = NULL;
894
895 extra_args.file_arr = file_arr;
896 extra_args.file_index = &file_index;;
897
898 fprintf(file_arr[file_index], "if ");
899
900 rc = cil_expr_to_policy(file_arr, file_index, expr);
901 if (rc != SEPOL_OK) {
902 cil_log(CIL_ERR, "Failed to write expression\n");
903 return rc;
904 }
905
906 if (node->cl_head != NULL && node->cl_head->flavor == CIL_CONDBLOCK) {
907 cb = node->cl_head->data;
908 if (cb->flavor == CIL_CONDTRUE) {
909 true_node = node->cl_head;
910 } else if (cb->flavor == CIL_CONDFALSE) {
911 false_node = node->cl_head;
912 }
913 }
914
915 if (node->cl_head != NULL && node->cl_head->next != NULL && node->cl_head->next->flavor == CIL_CONDBLOCK) {
916 cb = node->cl_head->next->data;
917 if (cb->flavor == CIL_CONDTRUE) {
918 true_node = node->cl_head->next;
919 } else if (cb->flavor == CIL_CONDFALSE) {
920 false_node = node->cl_head->next;
921 }
922 }
923
924 fprintf(file_arr[file_index], "{\n");
925 if (true_node != NULL) {
926 rc = cil_tree_walk(true_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
927 if (rc != SEPOL_OK) {
928 cil_log(CIL_INFO, "Failed to write booleanif content to file, rc: %d\n", rc);
929 return rc;
930 }
931 }
932 fprintf(file_arr[file_index], "}\n");
933
934 if (false_node != NULL) {
935 fprintf(file_arr[file_index], "else {\n");
936 rc = cil_tree_walk(false_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
937 if (rc != SEPOL_OK) {
938 cil_log(CIL_INFO, "Failed to write booleanif false content to file, rc: %d\n", rc);
939 return rc;
940 }
941 fprintf(file_arr[file_index], "}\n");
942 }
943
944 return SEPOL_OK;
945 }
946
cil_name_to_policy(FILE ** file_arr,struct cil_tree_node * current)947 int cil_name_to_policy(FILE **file_arr, struct cil_tree_node *current)
948 {
949 uint32_t flavor = current->flavor;
950 int rc = SEPOL_ERR;
951
952 switch(flavor) {
953 case CIL_TYPEATTRIBUTE:
954 fprintf(file_arr[TYPEATTRTYPES], "attribute %s;\n", ((struct cil_symtab_datum*)current->data)->name);
955 break;
956 case CIL_TYPE:
957 fprintf(file_arr[TYPEATTRTYPES], "type %s;\n", ((struct cil_symtab_datum*)current->data)->name);
958 break;
959 case CIL_TYPEALIAS: {
960 struct cil_alias *alias = current->data;
961 fprintf(file_arr[ALIASES], "typealias %s alias %s;\n", ((struct cil_symtab_datum*)alias->actual)->name, ((struct cil_symtab_datum*)current->data)->name);
962 break;
963 }
964 case CIL_TYPEBOUNDS: {
965 struct cil_bounds *bnds = current->data;
966 fprintf(file_arr[ALLOWS], "typebounds %s %s;\n", bnds->parent_str, bnds->child_str);
967 break;
968 }
969 case CIL_TYPEPERMISSIVE: {
970 struct cil_typepermissive *typeperm = (struct cil_typepermissive*)current->data;
971 fprintf(file_arr[TYPEATTRTYPES], "permissive %s;\n", ((struct cil_symtab_datum*)typeperm->type)->name);
972 break;
973 }
974 case CIL_ROLE:
975 fprintf(file_arr[TYPEATTRTYPES], "role %s;\n", ((struct cil_symtab_datum*)current->data)->name);
976 break;
977 case CIL_BOOL: {
978 const char *boolean = ((struct cil_bool*)current->data)->value ? "true" : "false";
979 fprintf(file_arr[TYPEATTRTYPES], "bool %s %s;\n", ((struct cil_symtab_datum*)current->data)->name, boolean);
980 break;
981 }
982 case CIL_COMMON:
983 fprintf(file_arr[COMMONS], "common %s", ((struct cil_symtab_datum*)current->data)->name);
984
985 if (current->cl_head != NULL) {
986 current = current->cl_head;
987 fprintf(file_arr[COMMONS], " {");
988 } else {
989 cil_log(CIL_INFO, "No permissions given\n");
990 return SEPOL_ERR;
991 }
992
993 while (current != NULL) {
994 if (current->flavor == CIL_PERM) {
995 fprintf(file_arr[COMMONS], "%s ", ((struct cil_symtab_datum*)current->data)->name);
996 } else {
997 cil_log(CIL_INFO, "Improper data type found in common permissions: %d\n", current->flavor);
998 return SEPOL_ERR;
999 }
1000 current = current->next;
1001 }
1002 fprintf(file_arr[COMMONS], "}\n");
1003
1004 return SEPOL_DONE;
1005 case CIL_AVRULE: {
1006 struct cil_avrule *avrule = (struct cil_avrule*)current->data;
1007 rc = cil_avrule_to_policy(file_arr, ALLOWS, avrule);
1008 if (rc != SEPOL_OK) {
1009 cil_log(CIL_INFO, "Failed to write avrule to policy\n");
1010 return rc;
1011 }
1012 break;
1013 }
1014 case CIL_TYPE_RULE: {
1015 struct cil_type_rule *rule = (struct cil_type_rule*)current->data;
1016 rc = cil_typerule_to_policy(file_arr, ALLOWS, rule);
1017 if (rc != SEPOL_OK) {
1018 cil_log(CIL_INFO, "Failed to write type rule to policy\n");
1019 return rc;
1020 }
1021 break;
1022 }
1023 case CIL_NAMETYPETRANSITION: {
1024 struct cil_nametypetransition *nametypetrans = (struct cil_nametypetransition*)current->data;
1025 rc = cil_nametypetransition_to_policy(file_arr, ALLOWS, nametypetrans);
1026 if (rc != SEPOL_OK) {
1027 cil_log(CIL_INFO, "Failed to write nametypetransition to policy\n");
1028 return rc;
1029 }
1030 }
1031 case CIL_ROLETRANSITION: {
1032 struct cil_roletransition *roletrans = (struct cil_roletransition*)current->data;
1033 char *src_str = ((struct cil_symtab_datum*)roletrans->src)->name;
1034 char *tgt_str = ((struct cil_symtab_datum*)roletrans->tgt)->name;
1035 char *obj_str = ((struct cil_symtab_datum*)roletrans->obj)->name;
1036 char *result_str = ((struct cil_symtab_datum*)roletrans->result)->name;
1037
1038 fprintf(file_arr[ALLOWS], "role_transition %s %s:%s %s;\n", src_str, tgt_str, obj_str, result_str);
1039 break;
1040 }
1041 case CIL_ROLEALLOW: {
1042 struct cil_roleallow *roleallow = (struct cil_roleallow*)current->data;
1043 char *src_str = ((struct cil_symtab_datum*)roleallow->src)->name;
1044 char *tgt_str = ((struct cil_symtab_datum*)roleallow->tgt)->name;
1045
1046 fprintf(file_arr[ALLOWS], "roleallow %s %s;\n", src_str, tgt_str);
1047 break;
1048 }
1049 case CIL_ROLETYPE: {
1050 struct cil_roletype *roletype = (struct cil_roletype*)current->data;
1051 char *role_str = ((struct cil_symtab_datum*)roletype->role)->name;
1052 char *type_str = ((struct cil_symtab_datum*)roletype->type)->name;
1053
1054 fprintf(file_arr[ALIASES], "role %s types %s\n", role_str, type_str);
1055 break;
1056 }
1057 case CIL_LEVEL:
1058 fprintf(file_arr[LEVELS], "level ");
1059 cil_level_to_policy(file_arr, LEVELS, (struct cil_level*)current->data);
1060 fprintf(file_arr[LEVELS], ";\n");
1061 break;
1062 case CIL_CONSTRAIN:
1063 cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
1064 break;
1065 case CIL_MLSCONSTRAIN:
1066 cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
1067 break;
1068 case CIL_VALIDATETRANS: {
1069 struct cil_validatetrans *vt = current->data;
1070 fprintf(file_arr[CONSTRAINS], "validatetrans");
1071 fprintf(file_arr[CONSTRAINS], " %s ", ((struct cil_class*)vt->class)->datum.name);
1072 cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
1073 fprintf(file_arr[CONSTRAINS], ";\n");
1074 break;
1075 }
1076 case CIL_MLSVALIDATETRANS: {
1077 struct cil_validatetrans *vt = current->data;
1078 fprintf(file_arr[CONSTRAINS], "mlsvalidatetrans");
1079 fprintf(file_arr[CONSTRAINS], " %s " , ((struct cil_class*)vt->class)->datum.name);
1080 cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
1081 fprintf(file_arr[CONSTRAINS], ";\n");
1082 break;
1083 }
1084 case CIL_SID:
1085 fprintf(file_arr[ISIDS], "sid %s\n", ((struct cil_symtab_datum*)current->data)->name);
1086 break;
1087 case CIL_SIDCONTEXT: {
1088 struct cil_sidcontext *sidcon = (struct cil_sidcontext*)current->data;
1089 fprintf(file_arr[SIDS], "sid %s ", sidcon->sid_str);
1090 cil_context_to_policy(file_arr, SIDS, sidcon->context);
1091 fprintf(file_arr[SIDS], "\n");
1092 break;
1093 }
1094 case CIL_POLICYCAP:
1095 fprintf(file_arr[TYPEATTRTYPES], "policycap %s;\n", ((struct cil_symtab_datum*)current->data)->name);
1096 break;
1097 default:
1098 break;
1099 }
1100
1101 return SEPOL_OK;
1102 }
1103
__cil_gen_policy_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1104 int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1105 {
1106 int rc = SEPOL_ERR;
1107 struct cil_args_genpolicy *args = NULL;
1108 struct cil_list *users = NULL;
1109 struct cil_list *sens = NULL;
1110 struct cil_list *cats = NULL;
1111 FILE **file_arr = NULL;
1112
1113 if (extra_args == NULL) {
1114 return SEPOL_ERR;
1115 }
1116
1117 *finished = CIL_TREE_SKIP_NOTHING;
1118
1119 args = extra_args;
1120 users = args->users;
1121 sens = args->sens;
1122 cats = args->cats;
1123 file_arr = args->file_arr;
1124
1125 if (node->cl_head != NULL) {
1126 if (node->flavor == CIL_MACRO) {
1127 *finished = CIL_TREE_SKIP_HEAD;
1128 return SEPOL_OK;
1129 }
1130
1131 if (node->flavor == CIL_BOOLEANIF) {
1132 rc = cil_booleanif_to_policy(file_arr, CONDS, node);
1133 if (rc != SEPOL_OK) {
1134 cil_log(CIL_INFO, "Failed to write booleanif contents to file\n");
1135 return rc;
1136 }
1137 *finished = CIL_TREE_SKIP_HEAD;
1138 return SEPOL_OK;
1139 }
1140
1141 if (node->flavor == CIL_BLOCK && ((struct cil_block*)node->data)->is_abstract == CIL_TRUE) {
1142 *finished = CIL_TREE_SKIP_HEAD;
1143 return SEPOL_OK;
1144 }
1145
1146 if (node->flavor != CIL_ROOT) {
1147 rc = cil_name_to_policy(file_arr, node);
1148 if (rc != SEPOL_OK && rc != SEPOL_DONE) {
1149 cil_log(CIL_ERR, "Error converting node to policy %d\n", node->flavor);
1150 return SEPOL_ERR;
1151 }
1152 }
1153 } else {
1154 switch (node->flavor) {
1155 case CIL_USER:
1156 cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE);
1157 break;
1158 case CIL_USERROLE: {
1159 struct cil_userrole *userrole = node->data;
1160 cil_multimap_insert(users, &userrole->user->datum, (struct cil_symtab_datum *)userrole->role, CIL_USERROLE, CIL_ROLE);
1161 }
1162 break;
1163 case CIL_CATALIAS: {
1164 struct cil_alias *alias = node->data;
1165 struct cil_symtab_datum *datum = alias->actual;
1166 cil_multimap_insert(cats, datum, node->data, CIL_CAT, CIL_CATALIAS);
1167 }
1168 break;
1169 case CIL_SENSALIAS: {
1170 struct cil_alias *alias = node->data;
1171 struct cil_symtab_datum *datum = alias->actual;
1172 cil_multimap_insert(sens, datum, node->data, CIL_SENS, CIL_SENSALIAS);
1173 }
1174 break;
1175 default:
1176 rc = cil_name_to_policy(file_arr, node);
1177 if (rc != SEPOL_OK && rc != SEPOL_DONE) {
1178 cil_log(CIL_ERR, "Error converting node to policy %d\n", rc);
1179 return SEPOL_ERR;
1180 }
1181 break;
1182 }
1183 }
1184
1185 return SEPOL_OK;
1186 }
1187
cil_gen_policy(struct cil_db * db)1188 int cil_gen_policy(struct cil_db *db)
1189 {
1190 struct cil_tree_node *curr = db->ast->root;
1191 struct cil_list_item *item;
1192 int rc = SEPOL_ERR;
1193 FILE *policy_file;
1194 FILE **file_arr = cil_malloc(sizeof(FILE*) * NUM_POLICY_FILES);
1195 char *file_path_arr[NUM_POLICY_FILES];
1196 char temp[32];
1197
1198 struct cil_list *users = NULL;
1199 struct cil_list *cats = NULL;
1200 struct cil_list *sens = NULL;
1201 struct cil_args_genpolicy extra_args;
1202
1203 cil_list_init(&users, CIL_LIST_ITEM);
1204 cil_list_init(&cats, CIL_LIST_ITEM);
1205 cil_list_init(&sens, CIL_LIST_ITEM);
1206
1207 strcpy(temp, "/tmp/cil_classdecl-XXXXXX");
1208 file_arr[CLASS_DECL] = fdopen(mkstemp(temp), "w+");
1209 file_path_arr[CLASS_DECL] = cil_strpool_add(temp);
1210
1211 strcpy(temp, "/tmp/cil_isids-XXXXXX");
1212 file_arr[ISIDS] = fdopen(mkstemp(temp), "w+");
1213 file_path_arr[ISIDS] = cil_strpool_add(temp);
1214
1215 strcpy(temp,"/tmp/cil_common-XXXXXX");
1216 file_arr[COMMONS] = fdopen(mkstemp(temp), "w+");
1217 file_path_arr[COMMONS] = cil_strpool_add(temp);
1218
1219 strcpy(temp, "/tmp/cil_class-XXXXXX");
1220 file_arr[CLASSES] = fdopen(mkstemp(temp), "w+");
1221 file_path_arr[CLASSES] = cil_strpool_add(temp);
1222
1223 strcpy(temp, "/tmp/cil_interf-XXXXXX");
1224 file_arr[INTERFACES] = fdopen(mkstemp(temp), "w+");
1225 file_path_arr[INTERFACES] = cil_strpool_add(temp);
1226
1227 strcpy(temp, "/tmp/cil_sens-XXXXXX");
1228 file_arr[SENS] = fdopen(mkstemp(temp), "w+");
1229 file_path_arr[SENS] = cil_strpool_add(temp);
1230
1231 strcpy(temp, "/tmp/cil_cats-XXXXXX");
1232 file_arr[CATS] = fdopen(mkstemp(temp), "w+");
1233 file_path_arr[CATS] = cil_strpool_add(temp);
1234
1235 strcpy(temp, "/tmp/cil_levels-XXXXXX");
1236 file_arr[LEVELS] = fdopen(mkstemp(temp), "w+");
1237 file_path_arr[LEVELS] = cil_strpool_add(temp);
1238
1239 strcpy(temp, "/tmp/cil_mlscon-XXXXXX");
1240 file_arr[CONSTRAINS] = fdopen(mkstemp(temp), "w+");
1241 file_path_arr[CONSTRAINS] = cil_strpool_add(temp);
1242
1243 strcpy(temp, "/tmp/cil_attrtypes-XXXXXX");
1244 file_arr[TYPEATTRTYPES] = fdopen(mkstemp(temp), "w+");
1245 file_path_arr[TYPEATTRTYPES] = cil_strpool_add(temp);
1246
1247 strcpy(temp, "/tmp/cil_aliases-XXXXXX");
1248 file_arr[ALIASES] = fdopen(mkstemp(temp), "w+");
1249 file_path_arr[ALIASES] = cil_strpool_add(temp);
1250
1251 strcpy(temp, "/tmp/cil_allows-XXXXXX");
1252 file_arr[ALLOWS] = fdopen(mkstemp(temp), "w+");
1253 file_path_arr[ALLOWS] = cil_strpool_add(temp);
1254
1255 strcpy(temp, "/tmp/cil_conds-XXXXXX");
1256 file_arr[CONDS] = fdopen(mkstemp(temp), "w+");
1257 file_path_arr[CONDS] = cil_strpool_add(temp);
1258
1259 strcpy(temp, "/tmp/cil_userroles-XXXXXX");
1260 file_arr[USERROLES] = fdopen(mkstemp(temp), "w+");
1261 file_path_arr[USERROLES] = cil_strpool_add(temp);
1262
1263 strcpy(temp, "/tmp/cil_sids-XXXXXX");
1264 file_arr[SIDS] = fdopen(mkstemp(temp), "w+");
1265 file_path_arr[SIDS] = cil_strpool_add(temp);
1266
1267 strcpy(temp, "/tmp/cil_netifcons-XXXXXX");
1268 file_arr[NETIFCONS] = fdopen(mkstemp(temp), "w+");
1269 file_path_arr[NETIFCONS] = cil_strpool_add(temp);
1270
1271 policy_file = fopen("policy.conf", "w+");
1272
1273 cil_list_for_each(item, db->sidorder) {
1274 fprintf(file_arr[ISIDS], "sid %s ", ((struct cil_sid*)item->data)->datum.name);
1275 }
1276
1277 cil_list_for_each(item, db->classorder) {
1278 struct cil_class *class = item->data;
1279 struct cil_tree_node *node = class->datum.nodes->head->data;
1280
1281 fprintf(file_arr[CLASS_DECL], "class %s\n", class->datum.name);
1282
1283 fprintf(file_arr[CLASSES], "class %s ", class->datum.name);
1284 if (class->common != NULL) {
1285 fprintf(file_arr[CLASSES], "inherits %s ", class->common->datum.name);
1286 }
1287 if (node->cl_head != NULL) {
1288 struct cil_tree_node *curr_perm = node->cl_head;
1289 fprintf(file_arr[CLASSES], "{ ");
1290 while (curr_perm != NULL) {
1291 fprintf(file_arr[CLASSES], "%s ", ((struct cil_symtab_datum*)curr_perm->data)->name);
1292 curr_perm = curr_perm->next;
1293 }
1294 fprintf(file_arr[CLASSES], "}");
1295 }
1296 fprintf(file_arr[CLASSES], "\n");
1297 }
1298
1299 if (db->catorder->head != NULL) {
1300 cil_list_for_each(item, db->catorder) {
1301 cil_multimap_insert(cats, item->data, NULL, CIL_CAT, 0);
1302 }
1303 }
1304
1305 if (db->sensitivityorder->head != NULL) {
1306 fprintf(file_arr[SENS], "sensitivityorder { ");
1307 cil_list_for_each(item, db->sensitivityorder) {
1308 fprintf(file_arr[SENS], "%s ", ((struct cil_sens*)item->data)->datum.name);
1309 }
1310 fprintf(file_arr[SENS], "};\n");
1311 }
1312
1313 extra_args.users = users;
1314 extra_args.sens = sens;
1315 extra_args.cats = cats;
1316 extra_args.file_arr= file_arr;
1317
1318 rc = cil_tree_walk(curr, __cil_gen_policy_node_helper, NULL, NULL, &extra_args);
1319 if (rc != SEPOL_OK) {
1320 cil_log(CIL_ERR, "Error walking tree\n");
1321 return rc;
1322 }
1323
1324 rc = cil_netifcon_to_policy(file_arr, db->netifcon);
1325 if (rc != SEPOL_OK) {
1326 cil_log(CIL_ERR, "Error creating policy.conf\n");
1327 return rc;
1328 }
1329
1330 rc = cil_genfscon_to_policy(file_arr, db->genfscon);
1331 if (rc != SEPOL_OK) {
1332 cil_log(CIL_ERR, "Error creating policy.conf\n");
1333 return rc;
1334 }
1335
1336 rc = cil_portcon_to_policy(file_arr, db->portcon);
1337 if (rc != SEPOL_OK) {
1338 cil_log(CIL_ERR, "Error creating policy.conf\n");
1339 return rc;
1340 }
1341
1342 rc = cil_nodecon_to_policy(file_arr, db->nodecon);
1343 if (rc != SEPOL_OK) {
1344 cil_log(CIL_ERR, "Error creating policy.conf\n");
1345 return rc;
1346 }
1347
1348 rc = cil_fsuse_to_policy(file_arr, db->fsuse);
1349 if (rc != SEPOL_OK) {
1350 cil_log(CIL_ERR, "Error creating policy.conf\n");
1351 return rc;
1352 }
1353
1354 rc = cil_pirqcon_to_policy(file_arr, db->pirqcon);
1355 if (rc != SEPOL_OK) {
1356 cil_log(CIL_ERR, "Error creating policy.conf\n");
1357 return rc;
1358 }
1359
1360 rc = cil_iomemcon_to_policy(file_arr, db->iomemcon);
1361 if (rc != SEPOL_OK) {
1362 cil_log(CIL_ERR, "Error creating policy.conf\n");
1363 return rc;
1364 }
1365
1366 rc = cil_ioportcon_to_policy(file_arr, db->ioportcon);
1367 if (rc != SEPOL_OK) {
1368 cil_log(CIL_ERR, "Error creating policy.conf\n");
1369 return rc;
1370 }
1371
1372 rc = cil_pcidevicecon_to_policy(file_arr, db->pcidevicecon);
1373 if (rc != SEPOL_OK) {
1374 cil_log(CIL_ERR, "Error creating policy.conf\n");
1375 return rc;
1376 }
1377
1378 rc = cil_userrole_to_policy(file_arr, users);
1379 if (rc != SEPOL_OK) {
1380 cil_log(CIL_ERR, "Error creating policy.conf\n");
1381 return SEPOL_ERR;
1382 }
1383
1384 rc = cil_sens_to_policy(file_arr, sens);
1385 if (rc != SEPOL_OK) {
1386 cil_log(CIL_ERR, "Error creating policy.conf\n");
1387 return SEPOL_ERR;
1388 }
1389
1390 rc = cil_cat_to_policy(file_arr, cats);
1391 if (rc != SEPOL_OK) {
1392 cil_log(CIL_ERR, "Error creating policy.conf\n");
1393 return SEPOL_ERR;
1394 }
1395
1396 rc = cil_combine_policy(file_arr, policy_file);
1397 if (rc != SEPOL_OK) {
1398 cil_log(CIL_ERR, "Error creating policy.conf\n");
1399 return SEPOL_ERR;
1400 }
1401
1402 // Remove temp files
1403 int i;
1404 for (i=0; i<NUM_POLICY_FILES; i++) {
1405 rc = fclose(file_arr[i]);
1406 if (rc != 0) {
1407 cil_log(CIL_ERR, "Error closing temporary file\n");
1408 return SEPOL_ERR;
1409 }
1410 rc = unlink(file_path_arr[i]);
1411 if (rc != 0) {
1412 cil_log(CIL_ERR, "Error unlinking temporary files\n");
1413 return SEPOL_ERR;
1414 }
1415 }
1416
1417 rc = fclose(policy_file);
1418 if (rc != 0) {
1419 cil_log(CIL_ERR, "Error closing policy.conf\n");
1420 return SEPOL_ERR;
1421 }
1422 free(file_arr);
1423
1424 cil_list_destroy(&users, CIL_FALSE);
1425 cil_list_destroy(&cats, CIL_FALSE);
1426 cil_list_destroy(&sens, CIL_FALSE);
1427
1428 return SEPOL_OK;
1429 }
1430