00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "policy-query-internal.h"
00027 #include "domain-trans-analysis-internal.h"
00028 #include <apol/domain-trans-analysis.h>
00029 #include <apol/bst.h>
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <errno.h>
00034 #include <string.h>
00035 #include <stdbool.h>
00036
00037
00038 struct apol_domain_trans_table
00039 {
00040 apol_bst_t *domain_table;
00041 apol_bst_t *entrypoint_table;
00042 };
00043
00044 typedef struct dom_node
00045 {
00046 const qpol_type_t *type;
00047 apol_bst_t *process_transition_tree;
00048 apol_bst_t *entrypoint_tree;
00049 apol_vector_t *setexec_rules;
00050 } dom_node_t;
00051
00052 typedef struct ep_node
00053 {
00054 const qpol_type_t *type;
00055 apol_bst_t *execute_tree;
00056 apol_bst_t *type_transition_tree;
00057 } ep_node_t;
00058
00059 typedef struct avrule_node
00060 {
00061 const qpol_type_t *type;
00062 const qpol_avrule_t *rule;
00063 bool used;
00064 } avrule_node_t;
00065
00066 typedef struct terule_node
00067 {
00068 const qpol_type_t *src;
00069 const qpol_type_t *dflt;
00070 const qpol_terule_t *rule;
00071 bool used;
00072 } terule_node_t;
00073
00074
00075 struct apol_domain_trans_analysis
00076 {
00077 unsigned char direction;
00078 unsigned char valid;
00079 char *start_type;
00080 char *result;
00081 apol_vector_t *access_types;
00082 apol_vector_t *access_classes;
00083 apol_vector_t *access_perms;
00084 regex_t *result_regex;
00085 };
00086
00087 struct apol_domain_trans_result
00088 {
00089 const qpol_type_t *start_type;
00090 const qpol_type_t *ep_type;
00091 const qpol_type_t *end_type;
00092 apol_vector_t *proc_trans_rules;
00093 apol_vector_t *ep_rules;
00094 apol_vector_t *exec_rules;
00095 apol_vector_t *setexec_rules;
00096 apol_vector_t *type_trans_rules;
00097 bool valid;
00098
00099
00100 apol_vector_t *access_rules;
00101 };
00102
00103
00104
00105 static int avrule_node_cmp(const void *a, const void *b, void *data __attribute__ ((unused)))
00106 {
00107 const avrule_node_t *an = a;
00108 const avrule_node_t *bn = b;
00109 ssize_t retv = (const char *)an->type - (const char *)bn->type;
00110 if (retv > 0)
00111 return 1;
00112 else if (retv < 0)
00113 return -1;
00114 retv = (const char *)an->rule - (const char *)bn->rule;
00115 if (retv > 0)
00116 return 1;
00117 else if (retv < 0)
00118 return -1;
00119 return 0;
00120 }
00121
00122 static int avrule_node_reset(void *a, void *b __attribute__ ((unused)))
00123 {
00124 avrule_node_t *an = a;
00125 if (!a)
00126 return -1;
00127 an->used = false;
00128 return 0;
00129 }
00130
00131 static avrule_node_t *avrule_node_create(const qpol_type_t * type, const qpol_avrule_t * rule)
00132 {
00133 avrule_node_t *n = calloc(1, sizeof(*n));
00134 if (!n)
00135 return NULL;
00136
00137 n->type = type;
00138 n->rule = rule;
00139
00140 return n;
00141 }
00142
00143
00144 static int terule_node_cmp(const void *a, const void *b, void *data __attribute__ ((unused)))
00145 {
00146 const terule_node_t *an = a;
00147 const terule_node_t *bn = b;
00148 ssize_t retv = (const char *)an->src - (const char *)bn->src;
00149 if (retv > 0)
00150 return 1;
00151 else if (retv < 0)
00152 return -1;
00153 retv = (const char *)an->dflt - (const char *)bn->dflt;
00154 if (retv > 0)
00155 return 1;
00156 else if (retv < 0)
00157 return -1;
00158 retv = (const char *)an->rule - (const char *)bn->rule;
00159 if (retv > 0)
00160 return 1;
00161 else if (retv < 0)
00162 return -1;
00163 return 0;
00164 }
00165
00166 static int terule_node_reset(void *a, void *b __attribute__ ((unused)))
00167 {
00168 terule_node_t *an = a;
00169 if (!a)
00170 return -1;
00171 an->used = false;
00172 return 0;
00173 }
00174
00175 static terule_node_t *terule_node_create(const qpol_type_t * src, const qpol_type_t * dflt, const qpol_terule_t * rule)
00176 {
00177 terule_node_t *n = calloc(1, sizeof(*n));
00178 if (!n)
00179 return NULL;
00180
00181 n->src = src;
00182 n->dflt = dflt;
00183 n->rule = rule;
00184
00185 return n;
00186 }
00187
00188
00189 static int dom_node_cmp(const void *a, const void *b, void *data __attribute__ ((unused)))
00190 {
00191 const dom_node_t *an = a;
00192 const dom_node_t *bn = b;
00193
00194 if ((const char *)(an->type) < (const char *)(bn->type))
00195 return -1;
00196 else if ((const char *)(an->type) > (const char *)(bn->type))
00197 return 1;
00198 return 0;
00199 }
00200
00201 static void dom_node_free(void *x)
00202 {
00203 if (!x)
00204 return;
00205 apol_bst_destroy(&(((dom_node_t *) x)->process_transition_tree));
00206 apol_bst_destroy(&(((dom_node_t *) x)->entrypoint_tree));
00207 apol_vector_destroy(&(((dom_node_t *) x)->setexec_rules));
00208 free(x);
00209 }
00210
00211 static int dom_node_reset(void *a, void *b __attribute__ ((unused)))
00212 {
00213 dom_node_t *an = a;
00214 if (!a)
00215 return -1;
00216
00217 if (apol_bst_inorder_map(an->process_transition_tree, avrule_node_reset, NULL) < 0)
00218 return -1;
00219 if (apol_bst_inorder_map(an->entrypoint_tree, avrule_node_reset, NULL) < 0)
00220 return -1;
00221
00222 return 0;
00223 }
00224
00225 static dom_node_t *dom_node_create(const qpol_type_t * type)
00226 {
00227 dom_node_t *n = calloc(1, sizeof(*n));
00228 if (!n)
00229 return NULL;
00230
00231 n->type = type;
00232 if (!(n->process_transition_tree = apol_bst_create(avrule_node_cmp, free)) ||
00233 !(n->entrypoint_tree = apol_bst_create(avrule_node_cmp, free)) || !(n->setexec_rules = apol_vector_create(NULL))) {
00234 apol_bst_destroy(&n->process_transition_tree);
00235 apol_bst_destroy(&n->entrypoint_tree);
00236 apol_vector_destroy(&n->setexec_rules);
00237 free(n);
00238 return NULL;
00239 }
00240
00241 return n;
00242 }
00243
00244
00245 static int ep_node_cmp(const void *a, const void *b, void *data __attribute__ ((unused)))
00246 {
00247 const ep_node_t *an = a;
00248 const ep_node_t *bn = b;
00249
00250 if ((const char *)(an->type) < (const char *)(bn->type))
00251 return -1;
00252 else if ((const char *)(an->type) > (const char *)(bn->type))
00253 return 1;
00254 return 0;
00255 }
00256
00257 static void ep_node_free(void *x)
00258 {
00259 if (!x)
00260 return;
00261 apol_bst_destroy(&(((ep_node_t *) x)->type_transition_tree));
00262 apol_bst_destroy(&(((ep_node_t *) x)->execute_tree));
00263 free(x);
00264 }
00265
00266 static int ep_node_reset(void *a, void *b __attribute__ ((unused)))
00267 {
00268 ep_node_t *an = a;
00269 if (!a)
00270 return -1;
00271
00272 if (apol_bst_inorder_map(an->execute_tree, avrule_node_reset, NULL) < 0)
00273 return -1;
00274 if (apol_bst_inorder_map(an->type_transition_tree, terule_node_reset, NULL) < 0)
00275 return -1;
00276 return 0;
00277 }
00278
00279 static ep_node_t *ep_node_create(const qpol_type_t * type)
00280 {
00281 ep_node_t *n = calloc(1, sizeof(*n));
00282 if (!n)
00283 return NULL;
00284
00285 n->type = type;
00286 if (!(n->execute_tree = apol_bst_create(avrule_node_cmp, free)) ||
00287 !(n->type_transition_tree = apol_bst_create(terule_node_cmp, free))) {
00288 apol_bst_destroy(&n->execute_tree);
00289 apol_bst_destroy(&n->type_transition_tree);
00290 free(n);
00291 return NULL;
00292 }
00293
00294 return n;
00295 }
00296
00297
00298 static apol_domain_trans_table_t *apol_domain_trans_table_new(apol_policy_t * policy)
00299 {
00300 apol_domain_trans_table_t *new_table = NULL;
00301 int error;
00302
00303 if (!policy) {
00304 ERR(policy, "%s", strerror(EINVAL));
00305 errno = EINVAL;
00306 return NULL;
00307 }
00308
00309 new_table = (apol_domain_trans_table_t *) calloc(1, sizeof(apol_domain_trans_table_t));
00310 if (!new_table) {
00311 ERR(policy, "%s", strerror(ENOMEM));
00312 error = ENOMEM;
00313 goto cleanup;
00314 }
00315
00316 if (!(new_table->domain_table = apol_bst_create(dom_node_cmp, dom_node_free))) {
00317 ERR(policy, "%s", strerror(ENOMEM));
00318 error = ENOMEM;
00319 goto cleanup;
00320 }
00321 if (!(new_table->entrypoint_table = apol_bst_create(ep_node_cmp, ep_node_free))) {
00322 ERR(policy, "%s", strerror(ENOMEM));
00323 error = ENOMEM;
00324 goto cleanup;
00325 }
00326
00327 return new_table;
00328 cleanup:
00329 domain_trans_table_destroy(&new_table);
00330 errno = error;
00331 return NULL;
00332 }
00333
00334 static int table_add_avrule(apol_policy_t * policy, apol_domain_trans_table_t * dta_table, const qpol_avrule_t * rule)
00335 {
00336 qpol_policy_t *qp = apol_policy_get_qpol(policy);
00337 const qpol_type_t *src;
00338 const qpol_type_t *tgt;
00339 qpol_avrule_get_source_type(qp, rule, &src);
00340 qpol_avrule_get_target_type(qp, rule, &tgt);
00341 apol_vector_t *sources = apol_query_expand_type(policy, src);
00342 apol_vector_t *targets = apol_query_expand_type(policy, tgt);
00343 bool exec = false, ep = false, proc_trans = false, setexec = false;
00344 qpol_iterator_t *iter = NULL;
00345 int error = 0;
00346 qpol_avrule_get_perm_iter(qp, rule, &iter);
00347 if (!iter || !sources || !targets) {
00348 error = errno;
00349 goto err;
00350 }
00351
00352 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00353 void *x;
00354 qpol_iterator_get_item(iter, &x);
00355 char *perm = x;
00356 if (!strcmp("execute", perm))
00357 exec = true;
00358 if (!strcmp("entrypoint", perm))
00359 ep = true;
00360 if (!strcmp("transition", perm))
00361 proc_trans = true;
00362 if (!strcmp("setexec", perm))
00363 setexec = true;
00364 free(x);
00365 }
00366 qpol_iterator_destroy(&iter);
00367
00368 if (proc_trans || ep || setexec) {
00369 for (size_t i = 0; i < apol_vector_get_size(sources); i++) {
00370 dom_node_t *dnode = NULL;
00371 dom_node_t dummy = { apol_vector_get_element(sources, i), NULL, NULL, NULL };
00372 if (apol_bst_get_element(dta_table->domain_table, &dummy, NULL, (void **)&dnode)) {
00373 dom_node_t *new_dnode = NULL;
00374 if (!(new_dnode = dom_node_create(dummy.type)) ||
00375 apol_bst_insert(dta_table->domain_table, (void *)new_dnode, NULL)) {
00376 error = errno;
00377 dom_node_free(new_dnode);
00378 goto err;
00379 }
00380 dnode = new_dnode;
00381 }
00382 if (setexec) {
00383 if (apol_vector_append_unique(dnode->setexec_rules, (void *)rule, NULL, NULL)) {
00384 error = errno;
00385 goto err;
00386 }
00387 }
00388 for (size_t j = 0; j < apol_vector_get_size(targets); j++) {
00389 if (proc_trans) {
00390 avrule_node_t *new_node =
00391 avrule_node_create((const qpol_type_t *)apol_vector_get_element(targets, j), rule);
00392 if (!new_node ||
00393 apol_bst_insert_and_get(dnode->process_transition_tree, (void **)&new_node, NULL) < 0) {
00394 error = errno;
00395 free(new_node);
00396 goto err;
00397 }
00398 }
00399 if (ep) {
00400 avrule_node_t *new_node =
00401 avrule_node_create((const qpol_type_t *)apol_vector_get_element(targets, j), rule);
00402 if (!new_node ||
00403 apol_bst_insert_and_get(dnode->entrypoint_tree, (void **)&new_node, NULL) < 0) {
00404 error = errno;
00405 free(new_node);
00406 goto err;
00407 }
00408 }
00409 }
00410 }
00411 }
00412 if (exec) {
00413 for (size_t i = 0; i < apol_vector_get_size(targets); i++) {
00414 ep_node_t *enode = NULL;
00415 ep_node_t dummy = { apol_vector_get_element(targets, i), NULL, NULL };
00416 if (apol_bst_get_element(dta_table->entrypoint_table, &dummy, NULL, (void **)&enode)) {
00417 ep_node_t *new_enode = NULL;
00418 if (!(new_enode = ep_node_create(dummy.type)) ||
00419 apol_bst_insert(dta_table->entrypoint_table, (void *)new_enode, NULL)) {
00420 error = errno;
00421 ep_node_free(new_enode);
00422 goto err;
00423 }
00424 enode = new_enode;
00425 }
00426 for (size_t j = 0; j < apol_vector_get_size(sources); j++) {
00427 avrule_node_t *new_node =
00428 avrule_node_create((const qpol_type_t *)apol_vector_get_element(sources, j), rule);
00429 if (!new_node || apol_bst_insert_and_get(enode->execute_tree, (void **)&new_node, NULL) < 0) {
00430 error = errno;
00431 free(new_node);
00432 goto err;
00433 }
00434 }
00435 }
00436 }
00437
00438 apol_vector_destroy(&sources);
00439 apol_vector_destroy(&targets);
00440 return 0;
00441
00442 err:
00443 qpol_iterator_destroy(&iter);
00444 apol_vector_destroy(&sources);
00445 apol_vector_destroy(&targets);
00446 errno = error;
00447 return -1;
00448 }
00449
00450 static int table_add_terule(apol_policy_t * policy, apol_domain_trans_table_t * dta_table, const qpol_terule_t * rule)
00451 {
00452 qpol_policy_t *qp = apol_policy_get_qpol(policy);
00453 const qpol_type_t *src;
00454 const qpol_type_t *tgt;
00455 const qpol_type_t *dflt;
00456 qpol_terule_get_source_type(qp, rule, &src);
00457 qpol_terule_get_target_type(qp, rule, &tgt);
00458 qpol_terule_get_default_type(qp, rule, &dflt);
00459 apol_vector_t *sources = apol_query_expand_type(policy, src);
00460 apol_vector_t *targets = apol_query_expand_type(policy, tgt);
00461 int error = 0;
00462 for (size_t i = 0; i < apol_vector_get_size(targets); i++) {
00463 ep_node_t *enode = NULL;
00464 ep_node_t dummy = { apol_vector_get_element(targets, i), NULL, NULL };
00465 if (apol_bst_get_element(dta_table->entrypoint_table, &dummy, NULL, (void **)&enode)) {
00466 ep_node_t *new_enode = NULL;
00467 if (!(new_enode = ep_node_create(dummy.type)) ||
00468 apol_bst_insert(dta_table->entrypoint_table, (void *)new_enode, NULL)) {
00469 error = errno;
00470 ep_node_free(new_enode);
00471 goto err;
00472 }
00473 enode = new_enode;
00474 }
00475 for (size_t j = 0; j < apol_vector_get_size(sources); j++) {
00476 terule_node_t *new_node =
00477 terule_node_create((const qpol_type_t *)apol_vector_get_element(sources, j), dflt, rule);
00478 if (apol_bst_insert_and_get(enode->type_transition_tree, (void **)&new_node, NULL) < 0) {
00479 error = errno;
00480 free(new_node);
00481 goto err;
00482 }
00483 }
00484 }
00485
00486 apol_vector_destroy(&sources);
00487 apol_vector_destroy(&targets);
00488 return 0;
00489 err:
00490 apol_vector_destroy(&sources);
00491 apol_vector_destroy(&targets);
00492 errno = error;
00493 return -1;
00494 }
00495
00496
00497 apol_domain_trans_result_t *domain_trans_result_create()
00498 {
00499 apol_domain_trans_result_t *res = calloc(1, sizeof(*res));
00500 if (!res)
00501 return NULL;
00502
00503 int error = 0;
00504 if (!(res->proc_trans_rules = apol_vector_create(NULL)) || !(res->ep_rules = apol_vector_create(NULL)) ||
00505 !(res->exec_rules = apol_vector_create(NULL)) || !(res->setexec_rules = apol_vector_create(NULL)) ||
00506 !(res->type_trans_rules = apol_vector_create(NULL))) {
00507 error = errno;
00508 goto err;
00509 }
00510
00511 return res;
00512 err:
00513 apol_domain_trans_result_destroy(&res);
00514 errno = error;
00515 return NULL;
00516 }
00517
00518
00519
00520 int apol_policy_build_domain_trans_table(apol_policy_t * policy)
00521 {
00522 int error = 0;
00523 apol_avrule_query_t *avq = NULL;
00524 apol_terule_query_t *teq = NULL;
00525 apol_vector_t *avrules = NULL;
00526 apol_vector_t *terules = NULL;
00527
00528 if (!policy) {
00529 ERR(policy, "%s", strerror(EINVAL));
00530 errno = EINVAL;
00531 return -1;
00532 }
00533
00534 if (policy->domain_trans_table) {
00535 return 0;
00536 }
00537
00538 apol_domain_trans_table_t *dta_table = policy->domain_trans_table = apol_domain_trans_table_new(policy);
00539 if (!policy->domain_trans_table) {
00540 error = errno;
00541 goto err;
00542 }
00543
00544 avq = apol_avrule_query_create();
00545 apol_avrule_query_set_rules(policy, avq, QPOL_RULE_ALLOW);
00546 apol_avrule_query_append_class(policy, avq, "file");
00547 apol_avrule_query_append_class(policy, avq, "process");
00548 apol_avrule_query_append_perm(policy, avq, "execute");
00549 apol_avrule_query_append_perm(policy, avq, "entrypoint");
00550 apol_avrule_query_append_perm(policy, avq, "transition");
00551 apol_avrule_query_append_perm(policy, avq, "setexec");
00552 if (apol_avrule_get_by_query(policy, avq, &avrules)) {
00553 error = errno;
00554 goto err;
00555 }
00556 apol_avrule_query_destroy(&avq);
00557 for (size_t i = 0; i < apol_vector_get_size(avrules); i++) {
00558 if (table_add_avrule(policy, dta_table, (const qpol_avrule_t *)apol_vector_get_element(avrules, i))) {
00559 error = errno;
00560 goto err;
00561 }
00562 }
00563 apol_vector_destroy(&avrules);
00564
00565 teq = apol_terule_query_create();
00566 apol_terule_query_set_rules(policy, teq, QPOL_RULE_TYPE_TRANS);
00567 apol_terule_query_append_class(policy, teq, "process");
00568 if (apol_terule_get_by_query(policy, teq, &terules)) {
00569 error = errno;
00570 goto err;
00571 }
00572 apol_terule_query_destroy(&teq);
00573 for (size_t i = 0; i < apol_vector_get_size(terules); i++) {
00574 if (table_add_terule(policy, dta_table, (const qpol_terule_t *)apol_vector_get_element(terules, i))) {
00575 error = errno;
00576 goto err;
00577 }
00578 }
00579 apol_vector_destroy(&terules);
00580
00581 return 0;
00582
00583 err:
00584 apol_avrule_query_destroy(&avq);
00585 apol_vector_destroy(&avrules);
00586 apol_terule_query_destroy(&teq);
00587 apol_vector_destroy(&terules);
00588 domain_trans_table_destroy(&dta_table);
00589 policy->domain_trans_table = NULL;
00590 errno = error;
00591 return -1;
00592 }
00593
00594 int apol_policy_domain_trans_table_build(apol_policy_t * policy)
00595 {
00596 return apol_policy_build_domain_trans_table(policy);
00597 }
00598
00599 void domain_trans_table_destroy(apol_domain_trans_table_t ** table)
00600 {
00601 if (!table || !(*table))
00602 return;
00603
00604 apol_bst_destroy(&(*table)->domain_table);
00605 apol_bst_destroy(&(*table)->entrypoint_table);
00606 free(*table);
00607 *table = NULL;
00608 }
00609
00610 void apol_policy_reset_domain_trans_table(apol_policy_t * policy)
00611 {
00612 if (!policy || !policy->domain_trans_table)
00613 return;
00614 apol_bst_inorder_map(policy->domain_trans_table->domain_table, dom_node_reset, NULL);
00615 apol_bst_inorder_map(policy->domain_trans_table->entrypoint_table, ep_node_reset, NULL);
00616 return;
00617 }
00618
00619 void apol_domain_trans_table_reset(apol_policy_t * policy)
00620 {
00621 apol_policy_reset_domain_trans_table(policy);
00622 }
00623
00624
00625 apol_domain_trans_analysis_t *apol_domain_trans_analysis_create(void)
00626 {
00627 apol_domain_trans_analysis_t *new_dta = NULL;
00628 int error = 0;
00629
00630 if (!(new_dta = calloc(1, sizeof(apol_domain_trans_analysis_t)))) {
00631 error = errno;
00632 goto err;
00633 }
00634
00635 new_dta->valid = APOL_DOMAIN_TRANS_SEARCH_VALID;
00636
00637 return new_dta;
00638
00639 err:
00640 apol_domain_trans_analysis_destroy(&new_dta);
00641 errno = error;
00642 return NULL;
00643 }
00644
00645 void apol_domain_trans_analysis_destroy(apol_domain_trans_analysis_t ** dta)
00646 {
00647 if (!dta || !(*dta))
00648 return;
00649
00650 free((*dta)->start_type);
00651 free((*dta)->result);
00652 apol_vector_destroy(&((*dta)->access_types));
00653 apol_vector_destroy(&((*dta)->access_classes));
00654 apol_vector_destroy(&((*dta)->access_perms));
00655 apol_regex_destroy(&((*dta)->result_regex));
00656 free(*dta);
00657 *dta = NULL;
00658 }
00659
00660 int apol_domain_trans_analysis_set_direction(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00661 unsigned char direction)
00662 {
00663 if (!dta || (direction != APOL_DOMAIN_TRANS_DIRECTION_FORWARD && direction != APOL_DOMAIN_TRANS_DIRECTION_REVERSE)) {
00664 ERR(policy, "Error setting analysis direction: %s", strerror(EINVAL));
00665 errno = EINVAL;
00666 return -1;
00667 }
00668
00669 dta->direction = direction;
00670
00671 return 0;
00672 }
00673
00674 int apol_domain_trans_analysis_set_valid(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta, unsigned char valid)
00675 {
00676 if (!dta || valid & ~(APOL_DOMAIN_TRANS_SEARCH_BOTH)) {
00677 ERR(policy, "Error setting analysis validity flag: %s", strerror(EINVAL));
00678 errno = EINVAL;
00679 return -1;
00680 }
00681
00682 dta->valid = valid;
00683
00684 return 0;
00685 }
00686
00687 int apol_domain_trans_analysis_set_start_type(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00688 const char *type_name)
00689 {
00690 char *tmp = NULL;
00691 int error = 0;
00692
00693 if (!dta || !type_name) {
00694 ERR(policy, "%s", strerror(EINVAL));
00695 errno = EINVAL;
00696 return -1;
00697 }
00698
00699 if (!(tmp = strdup(type_name))) {
00700 error = errno;
00701 ERR(policy, "%s", strerror(error));
00702 errno = error;
00703 return -1;
00704 }
00705
00706 free(dta->start_type);
00707 dta->start_type = tmp;
00708
00709 return 0;
00710 }
00711
00712 int apol_domain_trans_analysis_set_result_regex(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta, const char *regex)
00713 {
00714 if (!dta) {
00715 ERR(policy, "%s", strerror(EINVAL));
00716 errno = EINVAL;
00717 return -1;
00718 }
00719
00720 if (!regex) {
00721 apol_regex_destroy(&dta->result_regex);
00722 return 0;
00723 }
00724
00725 return apol_query_set(policy, &dta->result, &dta->result_regex, regex);
00726 }
00727
00728 int apol_domain_trans_analysis_append_access_type(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00729 const char *type_name)
00730 {
00731 char *tmp = NULL;
00732 int error = 0;
00733
00734 if (!dta) {
00735 ERR(policy, "Error appending type to analysis: %s", strerror(EINVAL));
00736 errno = EINVAL;
00737 return -1;
00738 }
00739
00740 if (!type_name) {
00741 apol_vector_destroy(&dta->access_types);
00742 return 0;
00743 }
00744
00745 if (!dta->access_types) {
00746 if (!(dta->access_types = apol_vector_create(free))) {
00747 error = errno;
00748 ERR(policy, "%s", strerror(error));
00749 errno = error;
00750 return -1;
00751 }
00752 }
00753
00754 if (!(tmp = strdup(type_name))) {
00755 error = errno;
00756 ERR(policy, "%s", strerror(error));
00757 errno = error;
00758 return -1;
00759 }
00760
00761 if (apol_vector_append(dta->access_types, tmp)) {
00762 error = errno;
00763 free(tmp);
00764 ERR(policy, "%s", strerror(error));
00765 errno = error;
00766 return -1;
00767 }
00768
00769 return 0;
00770 }
00771
00772 int apol_domain_trans_analysis_append_class_perm(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00773 const char *class_name, const char *perm_name)
00774 {
00775 if (apol_domain_trans_analysis_append_class(policy, dta, class_name))
00776 return -1;
00777 return apol_domain_trans_analysis_append_perm(policy, dta, perm_name);
00778 }
00779
00780 int apol_domain_trans_analysis_append_class(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00781 const char *class_name)
00782 {
00783 char *tmp = NULL;
00784 int error = 0;
00785
00786 if (!dta) {
00787 ERR(policy, "Error appending class to analysis: %s", strerror(EINVAL));
00788 errno = EINVAL;
00789 return -1;
00790 }
00791
00792 if (!class_name) {
00793 apol_vector_destroy(&dta->access_classes);
00794 return 0;
00795 }
00796
00797 if (!dta->access_classes) {
00798 if (!(dta->access_classes = apol_vector_create(free))) {
00799 error = errno;
00800 ERR(policy, "%s", strerror(error));
00801 errno = error;
00802 return -1;
00803 }
00804 }
00805
00806 if (!(tmp = strdup(class_name))) {
00807 error = errno;
00808 ERR(policy, "%s", strerror(error));
00809 errno = error;
00810 return -1;
00811 }
00812
00813 if (apol_vector_append(dta->access_classes, tmp)) {
00814 error = errno;
00815 free(tmp);
00816 ERR(policy, "%s", strerror(error));
00817 errno = error;
00818 return -1;
00819 }
00820
00821 return 0;
00822 }
00823
00824 int apol_domain_trans_analysis_append_perm(const apol_policy_t * policy, apol_domain_trans_analysis_t * dta, const char *perm_name)
00825 {
00826 char *tmp = NULL;
00827 int error = 0;
00828
00829 if (!dta) {
00830 ERR(policy, "Error appending perm to analysis: %s", strerror(EINVAL));
00831 errno = EINVAL;
00832 return -1;
00833 }
00834
00835 if (!perm_name) {
00836 apol_vector_destroy(&dta->access_perms);
00837 return 0;
00838 }
00839
00840 if (!dta->access_perms) {
00841 if (!(dta->access_perms = apol_vector_create(free))) {
00842 error = errno;
00843 ERR(policy, "%s", strerror(error));
00844 errno = error;
00845 return -1;
00846 }
00847 }
00848
00849 if (!(tmp = strdup(perm_name))) {
00850 error = errno;
00851 ERR(policy, "%s", strerror(error));
00852 errno = error;
00853 return -1;
00854 }
00855
00856 if (apol_vector_append(dta->access_perms, tmp)) {
00857 error = errno;
00858 free(tmp);
00859 ERR(policy, "%s", strerror(error));
00860 errno = error;
00861 return -1;
00862 }
00863
00864 return 0;
00865 }
00866
00867 static bool requires_setexec_or_type_trans(apol_policy_t * policy)
00868 {
00869 const qpol_policy_t *qp = apol_policy_get_qpol(policy);
00870 unsigned int policy_version = 0;
00871 qpol_policy_get_policy_version(qp, &policy_version);
00872 int is_modular = qpol_policy_has_capability(policy->p, QPOL_CAP_MODULES);
00873 return (policy_version >= 15 || is_modular);
00874 }
00875
00876 struct rule_map_data
00877 {
00878 const qpol_type_t *search;
00879 const qpol_type_t *dflt;
00880 apol_vector_t *node_list;
00881 bool is_avnode;
00882 };
00883
00884 static int node_list_map_fn(void *node, void *data)
00885 {
00886 struct rule_map_data *rm = data;
00887 if (rm->is_avnode) {
00888 avrule_node_t *anode = node;
00889 if (anode->type == rm->search && !anode->used)
00890 if (apol_vector_append(rm->node_list, node))
00891 return -1;
00892 return 0;
00893 } else {
00894 terule_node_t *tnode = node;
00895 if ((!rm->search || (rm->search == tnode->src)) && (!rm->dflt || (rm->dflt == tnode->dflt)) &&
00896 rm->search != rm->dflt && !tnode->used)
00897 if (apol_vector_append(rm->node_list, node))
00898 return -1;
00899 return 0;
00900 }
00901 }
00902
00903 static apol_vector_t *find_avrules_in_node(void *node, unsigned int rule_type, const qpol_type_t * search)
00904 {
00905 int error = 0;
00906 apol_vector_t *rule_nodes = apol_vector_create(NULL);
00907 struct rule_map_data data = { search, NULL, rule_nodes, true };
00908 switch (rule_type) {
00909 case APOL_DOMAIN_TRANS_RULE_PROC_TRANS:
00910 {
00911 dom_node_t *dnode = node;
00912 if (apol_bst_inorder_map(dnode->process_transition_tree, node_list_map_fn, (void *)&data) < 0) {
00913 error = errno;
00914 goto err;
00915 }
00916 break;
00917 }
00918 case APOL_DOMAIN_TRANS_RULE_ENTRYPOINT:
00919 {
00920 dom_node_t *dnode = node;
00921 if (apol_bst_inorder_map(dnode->entrypoint_tree, node_list_map_fn, (void *)&data) < 0) {
00922 error = errno;
00923 goto err;
00924 }
00925 break;
00926 }
00927 case APOL_DOMAIN_TRANS_RULE_EXEC:
00928 {
00929 ep_node_t *enode = node;
00930 if (apol_bst_inorder_map(enode->execute_tree, node_list_map_fn, (void *)&data) < 0) {
00931 error = errno;
00932 goto err;
00933 }
00934 break;
00935 }
00936 default:
00937 {
00938 error = EINVAL;
00939 goto err;
00940 }
00941 }
00942
00943 return rule_nodes;
00944
00945 err:
00946 apol_vector_destroy(&rule_nodes);
00947 errno = error;
00948 return NULL;
00949 }
00950
00951 static apol_vector_t *find_terules_in_node(ep_node_t * node, const qpol_type_t * search, const qpol_type_t * dflt)
00952 {
00953 int error = 0;
00954 apol_vector_t *rule_nodes = apol_vector_create(NULL);
00955 struct rule_map_data data = { search, dflt, rule_nodes, false };
00956 if (apol_bst_inorder_map(node->type_transition_tree, node_list_map_fn, (void *)&data) < 0) {
00957 error = errno;
00958 goto err;
00959 }
00960
00961 return rule_nodes;
00962
00963 err:
00964 apol_vector_destroy(&rule_nodes);
00965 errno = error;
00966 return NULL;
00967 }
00968
00969 static apol_domain_trans_result_t *find_result(apol_vector_t * local_results, const qpol_type_t * src, const qpol_type_t * tgt,
00970 const qpol_type_t * dflt)
00971 {
00972 for (size_t i = 0; i < apol_vector_get_size(local_results); i++) {
00973 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
00974 if (res->start_type == src && res->end_type == dflt && res->ep_type == tgt)
00975 return res;
00976 }
00977 return NULL;
00978 }
00979
00980 static int domain_trans_table_find_orphan_type_transitions(apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
00981 apol_vector_t * local_results)
00982 {
00983 int error = 0;
00984 const qpol_type_t *search = NULL;
00985 qpol_policy_get_type_by_name(apol_policy_get_qpol(policy), dta->start_type, &search);
00986 apol_domain_trans_result_t *tmp_result = NULL;
00987
00988 apol_vector_t *epnodes = apol_bst_get_vector(policy->domain_trans_table->entrypoint_table, 0);
00989 if (!epnodes)
00990 return -1;
00991 for (size_t i = 0; i < apol_vector_get_size(epnodes); i++) {
00992 ep_node_t *node = apol_vector_get_element(epnodes, i);
00993
00994 apol_vector_t *ttnodes = NULL;
00995 if (dta->direction == APOL_DOMAIN_TRANS_DIRECTION_FORWARD)
00996 ttnodes = find_terules_in_node(node, search, NULL);
00997 else
00998 ttnodes = find_terules_in_node(node, NULL, search);
00999 for (size_t j = 0; j < apol_vector_get_size(ttnodes); j++) {
01000 bool add = false;
01001 terule_node_t *tn = apol_vector_get_element(ttnodes, j);
01002 tn->used = true;
01003
01004 tmp_result = find_result(local_results, tn->src, node->type, tn->dflt);
01005 if (!tmp_result) {
01006 add = true;
01007 tmp_result = domain_trans_result_create();
01008 }
01009 if (!tmp_result) {
01010 error = errno;
01011 apol_vector_destroy(&ttnodes);
01012 goto err;
01013 }
01014 tmp_result->start_type = tn->src;
01015 tmp_result->end_type = tn->dflt;
01016 tmp_result->ep_type = node->type;
01017
01018 apol_vector_t *execrules =
01019 find_avrules_in_node((void *)node, APOL_DOMAIN_TRANS_RULE_EXEC, tmp_result->start_type);
01020 for (size_t k = 0; k < apol_vector_get_size(execrules); k++) {
01021 avrule_node_t *n = apol_vector_get_element(execrules, k);
01022 if (apol_vector_append(tmp_result->exec_rules, (void *)n->rule)) {
01023 error = errno;
01024 apol_vector_destroy(&execrules);
01025 if (!add)
01026 tmp_result = NULL;
01027 goto err;
01028 }
01029 }
01030 apol_vector_destroy(&execrules);
01031
01032 dom_node_t dummy = { tmp_result->start_type, NULL, NULL, NULL };
01033 dom_node_t *start_node = NULL;
01034 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&dummy, NULL, (void **)&start_node);
01035 if (start_node) {
01036
01037 if (add && apol_vector_get_size(start_node->setexec_rules)) {
01038 if (apol_vector_cat(tmp_result->setexec_rules, start_node->setexec_rules)) {
01039 error = errno;
01040 goto err;
01041 }
01042 }
01043
01044 apol_vector_t *proc_trans_rules =
01045 find_avrules_in_node((void *)start_node, APOL_DOMAIN_TRANS_RULE_PROC_TRANS,
01046 tmp_result->end_type);
01047 for (size_t k = 0; k < apol_vector_get_size(proc_trans_rules); k++) {
01048 avrule_node_t *avr = apol_vector_get_element(proc_trans_rules, k);
01049 if (apol_vector_append(tmp_result->proc_trans_rules, (void *)avr->rule)) {
01050 error = errno;
01051 if (!add)
01052 tmp_result = NULL;
01053 apol_vector_destroy(&proc_trans_rules);
01054 goto err;
01055 }
01056 }
01057 apol_vector_destroy(&proc_trans_rules);
01058 apol_vector_sort_uniquify(tmp_result->proc_trans_rules, NULL, NULL);
01059 }
01060 if (add) {
01061 if (apol_vector_append(local_results, (void *)tmp_result)) {
01062 error = errno;
01063 goto err;
01064 }
01065 }
01066 tmp_result = NULL;
01067 }
01068 apol_vector_destroy(&ttnodes);
01069 }
01070 apol_vector_destroy(&epnodes);
01071
01072 return 0;
01073
01074 err:
01075 apol_vector_destroy(&epnodes);
01076 apol_domain_trans_result_destroy(&tmp_result);
01077 errno = error;
01078 return -1;
01079 }
01080
01081 static int domain_trans_table_get_all_forward_trans(apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
01082 apol_vector_t * local_results, const qpol_type_t * start_type)
01083 {
01084 int error = 0;
01085
01086 apol_domain_trans_result_t *tmpl_result = domain_trans_result_create();
01087 if (!tmpl_result) {
01088 error = errno;
01089 goto err;
01090 }
01091
01092 dom_node_t dummy = { start_type, NULL, NULL, NULL };
01093 dom_node_t *start_node = NULL;
01094 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&dummy, NULL, (void **)&start_node);
01095 if (start_node) {
01096 tmpl_result->start_type = start_type;
01097
01098 if (requires_setexec_or_type_trans(policy) && apol_vector_get_size(start_node->setexec_rules)) {
01099 if (apol_vector_cat(tmpl_result->setexec_rules, start_node->setexec_rules)) {
01100 error = errno;
01101 goto err;
01102 }
01103 }
01104
01105 apol_vector_t *proc_trans_rules = apol_bst_get_vector(start_node->process_transition_tree, 0);
01106 apol_vector_t *potential_end_types = apol_vector_create(NULL);
01107 for (size_t i = 0; i < apol_vector_get_size(proc_trans_rules); i++) {
01108 avrule_node_t *ptnode = apol_vector_get_element(proc_trans_rules, i);
01109 apol_vector_append(potential_end_types, (void *)ptnode->type);
01110 }
01111 apol_vector_destroy(&proc_trans_rules);
01112 apol_vector_sort_uniquify(potential_end_types, NULL, NULL);
01113
01114 for (size_t i = 0; i < apol_vector_get_size(potential_end_types); i++) {
01115 dummy.type = tmpl_result->end_type = apol_vector_get_element(potential_end_types, i);
01116 dom_node_t *end_node = NULL;
01117 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&dummy, NULL, (void **)&end_node);
01118 const qpol_type_t *end_type = dummy.type;
01119 if (end_type == start_type)
01120 continue;
01121
01122 apol_vector_t *ptrules =
01123 find_avrules_in_node((void *)start_node, APOL_DOMAIN_TRANS_RULE_PROC_TRANS, end_type);
01124 apol_vector_destroy(&tmpl_result->proc_trans_rules);
01125 tmpl_result->proc_trans_rules = apol_vector_create(NULL);
01126 for (size_t j = 0; j < apol_vector_get_size(ptrules); j++) {
01127 avrule_node_t *pt_ent = apol_vector_get_element(ptrules, j);
01128 pt_ent->used = true;
01129 if (apol_vector_append(tmpl_result->proc_trans_rules, (void *)pt_ent->rule)) {
01130 error = errno;
01131 apol_vector_destroy(&ptrules);
01132 apol_vector_destroy(&potential_end_types);
01133 goto err;
01134 }
01135 }
01136 apol_vector_destroy(&ptrules);
01137 apol_vector_sort_uniquify(tmpl_result->proc_trans_rules, NULL, NULL);
01138 if (end_node) {
01139
01140 apol_vector_t *eprules = apol_bst_get_vector(end_node->entrypoint_tree, 0);
01141 apol_vector_t *potential_ep_types = apol_vector_create(NULL);
01142 if (!eprules || !potential_ep_types) {
01143 error = errno;
01144 apol_vector_destroy(&eprules);
01145 apol_vector_destroy(&potential_end_types);
01146 goto err;
01147 }
01148 for (size_t j = 0; j < apol_vector_get_size(eprules); j++) {
01149 avrule_node_t *epr = apol_vector_get_element(eprules, j);
01150 if (apol_vector_append(potential_ep_types, (void *)epr->type)) {
01151 error = errno;
01152 apol_vector_destroy(&eprules);
01153 apol_vector_destroy(&potential_end_types);
01154 apol_vector_destroy(&potential_ep_types);
01155 goto err;
01156 }
01157 }
01158 apol_vector_destroy(&eprules);
01159 apol_vector_sort_uniquify(potential_ep_types, NULL, NULL);
01160
01161 for (size_t j = 0; j < apol_vector_get_size(potential_ep_types); j++) {
01162 tmpl_result->ep_type = apol_vector_get_element(potential_ep_types, j);
01163 ep_node_t edummy =
01164 { (const qpol_type_t *)apol_vector_get_element(potential_ep_types, j), NULL, NULL };
01165 ep_node_t *epnode = NULL;
01166 apol_bst_get_element(policy->domain_trans_table->entrypoint_table, (void *)&edummy, NULL,
01167 (void **)&epnode);
01168
01169 apol_vector_destroy(&tmpl_result->ep_rules);
01170 tmpl_result->ep_rules = apol_vector_create(NULL);
01171 if (!tmpl_result->ep_rules) {
01172 error = errno;
01173 apol_vector_destroy(&potential_end_types);
01174 apol_vector_destroy(&potential_ep_types);
01175 goto err;
01176 }
01177 eprules = find_avrules_in_node((void *)end_node, APOL_DOMAIN_TRANS_RULE_ENTRYPOINT,
01178 tmpl_result->ep_type);
01179 for (size_t k = 0; k < apol_vector_get_size(eprules); k++) {
01180 avrule_node_t *ep_ent = apol_vector_get_element(eprules, k);
01181 ep_ent->used = true;
01182 if (apol_vector_append(tmpl_result->ep_rules, (void *)ep_ent->rule)) {
01183 error = errno;
01184 apol_vector_destroy(&eprules);
01185 apol_vector_destroy(&potential_end_types);
01186 apol_vector_destroy(&potential_ep_types);
01187 goto err;
01188 }
01189 }
01190 apol_vector_destroy(&eprules);
01191 apol_vector_sort_uniquify(tmpl_result->ep_rules, NULL, NULL);
01192 if (epnode) {
01193
01194 apol_vector_destroy(&tmpl_result->type_trans_rules);
01195 tmpl_result->type_trans_rules = apol_vector_create(NULL);
01196 if (!tmpl_result->type_trans_rules) {
01197 error = errno;
01198 apol_vector_destroy(&potential_end_types);
01199 apol_vector_destroy(&potential_ep_types);
01200 goto err;
01201 }
01202 apol_vector_t *ttrules = find_terules_in_node(epnode, start_type, end_type);
01203 for (size_t l = 0; l < apol_vector_get_size(ttrules); l++) {
01204 terule_node_t *tn = apol_vector_get_element(ttrules, l);
01205 if (apol_vector_append(tmpl_result->type_trans_rules, (void *)tn->rule)) {
01206 error = errno;
01207 apol_vector_destroy(&ttrules);
01208 apol_vector_destroy(&potential_end_types);
01209 apol_vector_destroy(&potential_ep_types);
01210 goto err;
01211 }
01212 }
01213 apol_vector_destroy(&ttrules);
01214 apol_vector_sort_uniquify(tmpl_result->type_trans_rules, NULL, NULL);
01215
01216 apol_vector_destroy(&tmpl_result->exec_rules);
01217 tmpl_result->exec_rules = apol_vector_create(NULL);
01218 if (!tmpl_result->exec_rules) {
01219 error = errno;
01220 apol_vector_destroy(&potential_end_types);
01221 apol_vector_destroy(&potential_ep_types);
01222 goto err;
01223 }
01224 apol_vector_t *execrules =
01225 find_avrules_in_node(epnode, APOL_DOMAIN_TRANS_RULE_EXEC, start_type);
01226 if (apol_vector_get_size(execrules)) {
01227 for (size_t l = 0; l < apol_vector_get_size(execrules); l++) {
01228 avrule_node_t *xnode = apol_vector_get_element(execrules, l);
01229
01230 if (apol_vector_append
01231 (tmpl_result->exec_rules, (void *)xnode->rule)) {
01232 error = errno;
01233 apol_vector_destroy(&execrules);
01234 apol_vector_destroy(&potential_end_types);
01235 apol_vector_destroy(&potential_ep_types);
01236 goto err;
01237 }
01238 }
01239 apol_vector_destroy(&execrules);
01240 apol_vector_sort_uniquify(tmpl_result->exec_rules, NULL, NULL);
01241
01242 apol_domain_trans_result_t *tmp =
01243 apol_domain_trans_result_create_from_domain_trans_result
01244 (tmpl_result);
01245 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01246 error = errno;
01247 apol_domain_trans_result_destroy(&tmp);
01248 apol_vector_destroy(&potential_end_types);
01249 apol_vector_destroy(&potential_ep_types);
01250 goto err;
01251 }
01252
01253 apol_vector_destroy(&tmpl_result->exec_rules);
01254 tmpl_result->exec_rules = apol_vector_create(NULL);
01255 if (!tmpl_result->exec_rules) {
01256 error = errno;
01257 apol_vector_destroy(&potential_end_types);
01258 apol_vector_destroy(&potential_ep_types);
01259 goto err;
01260 }
01261
01262 apol_vector_destroy(&tmpl_result->type_trans_rules);
01263 tmpl_result->type_trans_rules = apol_vector_create(NULL);
01264 if (!tmpl_result->type_trans_rules) {
01265 error = errno;
01266 apol_vector_destroy(&potential_end_types);
01267 apol_vector_destroy(&potential_ep_types);
01268 goto err;
01269 }
01270 } else {
01271
01272 apol_domain_trans_result_t *tmp =
01273 apol_domain_trans_result_create_from_domain_trans_result
01274 (tmpl_result);
01275 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01276 error = errno;
01277 apol_domain_trans_result_destroy(&tmp);
01278 apol_vector_destroy(&potential_end_types);
01279 apol_vector_destroy(&potential_ep_types);
01280 goto err;
01281 }
01282 }
01283 apol_vector_destroy(&execrules);
01284 } else {
01285
01286 apol_domain_trans_result_t *tmp =
01287 apol_domain_trans_result_create_from_domain_trans_result(tmpl_result);
01288 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01289 error = errno;
01290 apol_domain_trans_result_destroy(&tmp);
01291 apol_vector_destroy(&potential_end_types);
01292 apol_vector_destroy(&potential_ep_types);
01293 goto err;
01294 }
01295 }
01296
01297 apol_vector_destroy(&tmpl_result->ep_rules);
01298 tmpl_result->ep_rules = apol_vector_create(NULL);
01299 if (!tmpl_result->ep_rules) {
01300 error = errno;
01301 apol_vector_destroy(&potential_end_types);
01302 apol_vector_destroy(&potential_ep_types);
01303 goto err;
01304 }
01305 }
01306 apol_vector_destroy(&potential_ep_types);
01307 } else {
01308
01309 apol_domain_trans_result_t *tmp =
01310 apol_domain_trans_result_create_from_domain_trans_result(tmpl_result);
01311 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01312 error = errno;
01313 apol_domain_trans_result_destroy(&tmp);
01314 goto err;
01315 }
01316 }
01317 }
01318 apol_vector_destroy(&potential_end_types);
01319
01320 for (size_t i = 0; i < apol_vector_get_size(local_results); i++) {
01321 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
01322 if (res->start_type && res->ep_type && res->end_type && apol_vector_get_size(res->proc_trans_rules) &&
01323 apol_vector_get_size(res->ep_rules) && apol_vector_get_size(res->exec_rules) &&
01324 (requires_setexec_or_type_trans(policy)
01325 ? (apol_vector_get_size(res->setexec_rules) || apol_vector_get_size(res->type_trans_rules)) : true)) {
01326 res->valid = true;
01327 }
01328 }
01329 }
01330
01331 if (dta->valid & APOL_DOMAIN_TRANS_SEARCH_INVALID) {
01332 if (domain_trans_table_find_orphan_type_transitions(policy, dta, local_results)) {
01333 error = errno;
01334 goto err;
01335 }
01336 }
01337 apol_domain_trans_result_destroy(&tmpl_result);
01338
01339 return 0;
01340 err:
01341 apol_domain_trans_result_destroy(&tmpl_result);
01342 errno = error;
01343 return -1;
01344 }
01345
01346 static int domain_trans_table_get_all_reverse_trans(apol_policy_t * policy, apol_domain_trans_analysis_t * dta,
01347 apol_vector_t * local_results, const qpol_type_t * end_type)
01348 {
01349 int error = 0;
01350
01351 apol_domain_trans_result_t *tmpl_result = domain_trans_result_create();
01352 if (!tmpl_result) {
01353 error = errno;
01354 goto err;
01355 }
01356
01357 dom_node_t dummy = { end_type, NULL, NULL, NULL };
01358 dom_node_t *end_node = NULL;
01359 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&dummy, NULL, (void **)&end_node);
01360 if (end_node) {
01361 tmpl_result->end_type = end_type;
01362
01363 apol_vector_t *eprules = apol_bst_get_vector(end_node->entrypoint_tree, 0);
01364 apol_vector_t *potential_ep_types = apol_vector_create(NULL);
01365 if (!eprules || !potential_ep_types) {
01366 error = errno;
01367 apol_vector_destroy(&eprules);
01368 goto err;
01369 }
01370 for (size_t j = 0; j < apol_vector_get_size(eprules); j++) {
01371 avrule_node_t *epr = apol_vector_get_element(eprules, j);
01372 if (apol_vector_append(potential_ep_types, (void *)epr->type)) {
01373 error = errno;
01374 apol_vector_destroy(&eprules);
01375 apol_vector_destroy(&potential_ep_types);
01376 goto err;
01377 }
01378 }
01379 apol_vector_destroy(&eprules);
01380 apol_vector_sort_uniquify(potential_ep_types, NULL, NULL);
01381 for (size_t i = 0; i < apol_vector_get_size(potential_ep_types); i++) {
01382 tmpl_result->ep_type = apol_vector_get_element(potential_ep_types, i);
01383
01384 eprules = find_avrules_in_node((void *)end_node, APOL_DOMAIN_TRANS_RULE_ENTRYPOINT, tmpl_result->ep_type);
01385 apol_vector_destroy(&tmpl_result->ep_rules);
01386 tmpl_result->ep_rules = apol_vector_create(NULL);
01387 for (size_t j = 0; j < apol_vector_get_size(eprules); j++) {
01388 avrule_node_t *ep_ent = apol_vector_get_element(eprules, j);
01389 ep_ent->used = true;
01390 if (apol_vector_append(tmpl_result->ep_rules, (void *)ep_ent->rule)) {
01391 error = errno;
01392 apol_vector_destroy(&eprules);
01393 apol_vector_destroy(&potential_ep_types);
01394 goto err;
01395 }
01396 }
01397 apol_vector_destroy(&eprules);
01398 apol_vector_sort_uniquify(tmpl_result->ep_rules, NULL, NULL);
01399 ep_node_t edummy = { tmpl_result->ep_type, NULL, NULL };
01400 ep_node_t *epnode = NULL;
01401 apol_bst_get_element(policy->domain_trans_table->entrypoint_table, (void *)&edummy, NULL, (void **)&epnode);
01402
01403 if (epnode) {
01404 apol_vector_t *execrules = apol_bst_get_vector(epnode->execute_tree, 0);
01405 apol_vector_t *potential_start_types = apol_vector_create(NULL);
01406 if (!execrules || !potential_start_types) {
01407 error = errno;
01408 apol_vector_destroy(&execrules);
01409 goto err;
01410 }
01411 for (size_t k = 0; k < apol_vector_get_size(execrules); k++) {
01412 avrule_node_t *n = apol_vector_get_element(execrules, k);
01413 if (apol_vector_append(potential_start_types, (void *)n->type)) {
01414 error = errno;
01415 apol_vector_destroy(&execrules);
01416 apol_vector_destroy(&potential_start_types);
01417 apol_vector_destroy(&potential_ep_types);
01418 goto err;
01419 }
01420 }
01421 apol_vector_destroy(&execrules);
01422 apol_vector_sort_uniquify(potential_start_types, NULL, NULL);
01423 for (size_t k = 0; k < apol_vector_get_size(potential_start_types); k++) {
01424 tmpl_result->start_type = apol_vector_get_element(potential_start_types, k);
01425
01426 if (tmpl_result->end_type == tmpl_result->start_type)
01427 continue;
01428
01429 apol_vector_t *exec_rules =
01430 find_avrules_in_node((void *)epnode, APOL_DOMAIN_TRANS_RULE_EXEC,
01431 tmpl_result->start_type);
01432 apol_vector_destroy(&tmpl_result->exec_rules);
01433 tmpl_result->exec_rules = apol_vector_create(NULL);
01434 for (size_t l = 0; l < apol_vector_get_size(exec_rules); l++) {
01435 avrule_node_t *n = apol_vector_get_element(exec_rules, l);
01436 n->used = true;
01437 if (apol_vector_append(tmpl_result->exec_rules, (void *)n->rule)) {
01438 error = errno;
01439 apol_vector_destroy(&exec_rules);
01440 apol_vector_destroy(&potential_start_types);
01441 apol_vector_destroy(&potential_ep_types);
01442 goto err;
01443 }
01444 }
01445 apol_vector_destroy(&exec_rules);
01446 apol_vector_sort_uniquify(tmpl_result->exec_rules, NULL, NULL);
01447
01448 apol_vector_t *ttrules =
01449 find_terules_in_node(epnode, tmpl_result->start_type, tmpl_result->end_type);
01450 apol_vector_destroy(&tmpl_result->type_trans_rules);
01451 tmpl_result->type_trans_rules = apol_vector_create(NULL);
01452 if (!tmpl_result->type_trans_rules) {
01453 error = errno;
01454 apol_vector_destroy(&ttrules);
01455 apol_vector_destroy(&potential_start_types);
01456 apol_vector_destroy(&potential_ep_types);
01457 goto err;
01458 }
01459 for (size_t l = 0; l < apol_vector_get_size(ttrules); l++) {
01460 terule_node_t *n = apol_vector_get_element(ttrules, l);
01461 n->used = true;
01462 if (apol_vector_append(tmpl_result->type_trans_rules, (void *)n->rule)) {
01463 error = errno;
01464 apol_vector_destroy(&ttrules);
01465 apol_vector_destroy(&potential_start_types);
01466 apol_vector_destroy(&potential_ep_types);
01467 goto err;
01468 }
01469 }
01470 apol_vector_destroy(&ttrules);
01471 apol_vector_sort_uniquify(tmpl_result->type_trans_rules, NULL, NULL);
01472 dummy.type = tmpl_result->start_type;
01473 dom_node_t *start_node = NULL;
01474 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&dummy, NULL,
01475 (void **)&start_node);
01476 if (start_node) {
01477
01478 if (requires_setexec_or_type_trans(policy)) {
01479 apol_vector_destroy(&tmpl_result->setexec_rules);
01480 tmpl_result->setexec_rules = apol_vector_create(NULL);
01481 if (!tmpl_result->setexec_rules ||
01482 apol_vector_cat(tmpl_result->setexec_rules,
01483 start_node->setexec_rules)) {
01484 error = errno;
01485 apol_vector_destroy(&potential_start_types);
01486 apol_vector_destroy(&potential_ep_types);
01487 goto err;
01488 }
01489 }
01490
01491 apol_vector_destroy(&tmpl_result->proc_trans_rules);
01492 tmpl_result->proc_trans_rules = apol_vector_create(NULL);
01493 if (!tmpl_result->proc_trans_rules) {
01494 error = errno;
01495 apol_vector_destroy(&potential_start_types);
01496 apol_vector_destroy(&potential_ep_types);
01497 goto err;
01498 }
01499 apol_vector_t *pt_rules = NULL;
01500 pt_rules =
01501 find_avrules_in_node(start_node, APOL_DOMAIN_TRANS_RULE_PROC_TRANS,
01502 tmpl_result->end_type);
01503 if (apol_vector_get_size(pt_rules)) {
01504 for (size_t l = 0; l < apol_vector_get_size(pt_rules); l++) {
01505 avrule_node_t *n = apol_vector_get_element(pt_rules, l);
01506 apol_vector_append(tmpl_result->proc_trans_rules, (void *)n->rule);
01507 }
01508 apol_vector_destroy(&pt_rules);
01509 apol_vector_sort_uniquify(tmpl_result->proc_trans_rules, NULL, NULL);
01510
01511 apol_domain_trans_result_t *tmp =
01512 apol_domain_trans_result_create_from_domain_trans_result
01513 (tmpl_result);
01514 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01515 error = errno;
01516 apol_domain_trans_result_destroy(&tmp);
01517 apol_vector_destroy(&potential_start_types);
01518 apol_vector_destroy(&potential_ep_types);
01519 goto err;
01520 }
01521
01522 apol_vector_destroy(&tmpl_result->proc_trans_rules);
01523 tmpl_result->proc_trans_rules = apol_vector_create(NULL);
01524 if (!tmpl_result->proc_trans_rules) {
01525 error = errno;
01526 apol_vector_destroy(&potential_start_types);
01527 apol_vector_destroy(&potential_ep_types);
01528 goto err;
01529 }
01530
01531 apol_vector_destroy(&tmpl_result->setexec_rules);
01532 tmpl_result->setexec_rules = apol_vector_create(NULL);
01533 if (!tmpl_result->setexec_rules) {
01534 error = errno;
01535 apol_vector_destroy(&potential_start_types);
01536 apol_vector_destroy(&potential_ep_types);
01537 goto err;
01538 }
01539 } else {
01540
01541 apol_domain_trans_result_t *tmp =
01542 apol_domain_trans_result_create_from_domain_trans_result
01543 (tmpl_result);
01544 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01545 error = errno;
01546 apol_domain_trans_result_destroy(&tmp);
01547 apol_vector_destroy(&potential_start_types);
01548 apol_vector_destroy(&potential_ep_types);
01549 apol_vector_destroy(&pt_rules);
01550 goto err;
01551 }
01552 }
01553 apol_vector_destroy(&pt_rules);
01554 } else {
01555
01556 apol_domain_trans_result_t *tmp =
01557 apol_domain_trans_result_create_from_domain_trans_result(tmpl_result);
01558 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01559 error = errno;
01560 apol_domain_trans_result_destroy(&tmp);
01561 apol_vector_destroy(&potential_start_types);
01562 apol_vector_destroy(&potential_ep_types);
01563 goto err;
01564 }
01565 }
01566
01567 apol_vector_destroy(&tmpl_result->exec_rules);
01568 tmpl_result->exec_rules = apol_vector_create(NULL);
01569 if (!tmpl_result->exec_rules) {
01570 error = errno;
01571 apol_vector_destroy(&potential_start_types);
01572 apol_vector_destroy(&potential_ep_types);
01573 goto err;
01574 }
01575
01576 apol_vector_destroy(&tmpl_result->type_trans_rules);
01577 tmpl_result->type_trans_rules = apol_vector_create(NULL);
01578 if (!tmpl_result->type_trans_rules) {
01579 error = errno;
01580 apol_vector_destroy(&potential_start_types);
01581 apol_vector_destroy(&potential_ep_types);
01582 goto err;
01583 }
01584 }
01585 apol_vector_destroy(&potential_start_types);
01586 } else {
01587
01588 apol_domain_trans_result_t *tmp =
01589 apol_domain_trans_result_create_from_domain_trans_result(tmpl_result);
01590 if (!tmp || apol_vector_append(local_results, (void *)tmp)) {
01591 error = errno;
01592 apol_domain_trans_result_destroy(&tmp);
01593 goto err;
01594 }
01595 }
01596 }
01597 apol_vector_destroy(&potential_ep_types);
01598
01599
01600 for (size_t i = 0; i < apol_vector_get_size(local_results); i++) {
01601 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
01602 if (res->start_type && res->ep_type && res->end_type && apol_vector_get_size(res->proc_trans_rules) &&
01603 apol_vector_get_size(res->ep_rules) && apol_vector_get_size(res->exec_rules) &&
01604 (requires_setexec_or_type_trans(policy)
01605 ? (apol_vector_get_size(res->setexec_rules) || apol_vector_get_size(res->type_trans_rules)) : true)) {
01606 res->valid = true;
01607 }
01608 }
01609 }
01610
01611 if (dta->valid & APOL_DOMAIN_TRANS_SEARCH_INVALID) {
01612 if (domain_trans_table_find_orphan_type_transitions(policy, dta, local_results)) {
01613 error = errno;
01614 goto err;
01615 }
01616 }
01617
01618 apol_domain_trans_result_destroy(&tmpl_result);
01619 return 0;
01620
01621 err:
01622 apol_domain_trans_result_destroy(&tmpl_result);
01623 errno = error;
01624 return -1;
01625 }
01626
01627 int apol_domain_trans_analysis_do(apol_policy_t * policy, apol_domain_trans_analysis_t * dta, apol_vector_t ** results)
01628 {
01629 apol_vector_t *local_results = NULL;
01630 apol_avrule_query_t *accessq = NULL;
01631 int error = 0;
01632 if (!results)
01633 *results = NULL;
01634 if (!policy || !dta || !results) {
01635 ERR(policy, "%s", strerror(EINVAL));
01636 errno = EINVAL;
01637 return -1;
01638 }
01639
01640
01641 if (!(policy->domain_trans_table)) {
01642 if (apol_policy_build_domain_trans_table(policy))
01643 return -1;
01644 }
01645
01646
01647 if (dta->direction == 0 || dta->valid & ~(APOL_DOMAIN_TRANS_SEARCH_BOTH) || !(dta->start_type)) {
01648 error = EINVAL;
01649 ERR(policy, "%s", strerror(EINVAL));
01650 goto err;
01651 }
01652 size_t num_atypes = apol_vector_get_size(dta->access_types);
01653 size_t num_aclasses = apol_vector_get_size(dta->access_classes);
01654 size_t num_aprems = apol_vector_get_size(dta->access_perms);
01655 if ((num_atypes == 0 && (num_aclasses != 0 || num_aprems != 0)) ||
01656 (num_aclasses == 0 && (num_atypes != 0 || num_aprems != 0)) ||
01657 (num_aprems == 0 && (num_aclasses != 0 || num_atypes != 0))) {
01658 error = EINVAL;
01659 ERR(policy, "%s", strerror(EINVAL));
01660 goto err;
01661 }
01662
01663
01664 const qpol_type_t *start_type = NULL;
01665 if (qpol_policy_get_type_by_name(policy->p, dta->start_type, &start_type)) {
01666 error = errno;
01667 ERR(policy, "Unable to perform analysis: Invalid starting type %s", dta->start_type);
01668 goto err;
01669 }
01670 unsigned char isattr = 0;
01671 qpol_type_get_isattr(policy->p, start_type, &isattr);
01672 if (isattr) {
01673 ERR(policy, "%s", "Attributes are not valid here.");
01674 error = EINVAL;
01675 goto err;
01676 }
01677
01678 local_results = apol_vector_create(domain_trans_result_free);
01679
01680 if (dta->direction == APOL_DOMAIN_TRANS_DIRECTION_REVERSE) {
01681 if (domain_trans_table_get_all_reverse_trans(policy, dta, local_results, start_type)) {
01682 error = errno;
01683 goto err;
01684 }
01685 } else {
01686 if (domain_trans_table_get_all_forward_trans(policy, dta, local_results, start_type)) {
01687 error = errno;
01688 goto err;
01689 }
01690 }
01691
01692
01693 if (dta->valid != APOL_DOMAIN_TRANS_SEARCH_BOTH) {
01694 for (size_t i = 0; i < apol_vector_get_size(local_results); ) {
01695 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
01696 if (res->valid != (dta->valid == APOL_DOMAIN_TRANS_SEARCH_VALID)) {
01697 apol_vector_remove(local_results, i);
01698 domain_trans_result_free(res);
01699 } else {
01700 i++;
01701 }
01702 }
01703 }
01704
01705
01706 if (dta->result) {
01707 for (size_t i = 0; i < apol_vector_get_size(local_results); ) {
01708 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
01709 const qpol_type_t *type = NULL;
01710 if (dta->direction == APOL_DOMAIN_TRANS_DIRECTION_REVERSE) {
01711 type = res->start_type;
01712 } else {
01713 type = res->end_type;
01714 }
01715 int compval = apol_compare_type(policy, type, dta->result, APOL_QUERY_REGEX, &dta->result_regex);
01716 if (compval < 0) {
01717 error = errno;
01718 goto err;
01719 } else if (compval > 0) {
01720 i++;
01721 } else {
01722 apol_vector_remove(local_results, i);
01723 domain_trans_result_free(res);
01724 }
01725 }
01726 }
01727
01728
01729 if (dta->direction == APOL_DOMAIN_TRANS_DIRECTION_FORWARD && num_atypes && num_aclasses && num_aprems) {
01730 accessq = apol_avrule_query_create();
01731 apol_avrule_query_set_rules(policy, accessq, QPOL_RULE_ALLOW);
01732 for (size_t i = 0; i < num_aclasses; i++) {
01733 if (apol_avrule_query_append_class
01734 (policy, accessq, (char *)apol_vector_get_element(dta->access_classes, i))) {
01735 error = errno;
01736 goto err;
01737 }
01738 }
01739 for (size_t i = 0; i < num_aprems; i++) {
01740 if (apol_avrule_query_append_perm(policy, accessq, (char *)apol_vector_get_element(dta->access_perms, i))) {
01741 error = errno;
01742 goto err;
01743 }
01744 }
01745 for (size_t i = 0; i < apol_vector_get_size(local_results); ) {
01746 const char *end_name = NULL;
01747 apol_domain_trans_result_t *res = apol_vector_get_element(local_results, i);
01748 if (qpol_type_get_name(apol_policy_get_qpol(policy), res->end_type, &end_name) ||
01749 apol_avrule_query_set_source(policy, accessq, end_name, 1)) {
01750 error = errno;
01751 goto err;
01752 }
01753 apol_vector_t *tmp_access = apol_vector_create(NULL);
01754 for (size_t j = 0; j < num_atypes; j++) {
01755 if (apol_avrule_query_set_target
01756 (policy, accessq, (char *)apol_vector_get_element(dta->access_types, j), 1)) {
01757 error = errno;
01758 apol_vector_destroy(&tmp_access);
01759 goto err;
01760 }
01761 apol_vector_t *cur_tgt_v = NULL;
01762 apol_avrule_get_by_query(policy, accessq, &cur_tgt_v);
01763 apol_vector_cat(tmp_access, cur_tgt_v);
01764 apol_vector_destroy(&cur_tgt_v);
01765 }
01766 if (apol_vector_get_size(tmp_access)) {
01767 res->access_rules = tmp_access;
01768 tmp_access = NULL;
01769 i++;
01770 } else {
01771 apol_vector_remove(local_results, i);
01772 domain_trans_result_free(res);
01773 }
01774 apol_vector_destroy(&tmp_access);
01775 }
01776 apol_avrule_query_destroy(&accessq);
01777 }
01778
01779 *results = apol_vector_create(domain_trans_result_free);
01780 if (!(*results)) {
01781 error = errno;
01782 goto err;
01783 }
01784 for (size_t i = 0; i < apol_vector_get_size(local_results); i++) {
01785 apol_domain_trans_result_t *res =
01786 apol_domain_trans_result_create_from_domain_trans_result((apol_domain_trans_result_t *)
01787 apol_vector_get_element(local_results, i));
01788 if (!res || apol_vector_append(*results, (void *)res)) {
01789 error = errno;
01790 domain_trans_result_free(res);
01791 goto err;
01792 }
01793 }
01794 apol_vector_destroy(&local_results);
01795
01796 return 0;
01797 err:
01798 apol_vector_destroy(&local_results);
01799 apol_vector_destroy(results);
01800 apol_avrule_query_destroy(&accessq);
01801 errno = error;
01802 return -1;
01803 }
01804
01805
01806
01807 const qpol_type_t *apol_domain_trans_result_get_start_type(const apol_domain_trans_result_t * dtr)
01808 {
01809 if (dtr) {
01810 return dtr->start_type;
01811 } else {
01812 errno = EINVAL;
01813 return NULL;
01814 }
01815 }
01816
01817 const qpol_type_t *apol_domain_trans_result_get_entrypoint_type(const apol_domain_trans_result_t * dtr)
01818 {
01819 if (dtr) {
01820 return dtr->ep_type;
01821 } else {
01822 errno = EINVAL;
01823 return NULL;
01824 }
01825 }
01826
01827 const qpol_type_t *apol_domain_trans_result_get_end_type(const apol_domain_trans_result_t * dtr)
01828 {
01829 if (dtr) {
01830 return dtr->end_type;
01831 } else {
01832 errno = EINVAL;
01833 return NULL;
01834 }
01835 }
01836
01837 const apol_vector_t *apol_domain_trans_result_get_proc_trans_rules(const apol_domain_trans_result_t * dtr)
01838 {
01839 if (dtr) {
01840 return dtr->proc_trans_rules;
01841 } else {
01842 errno = EINVAL;
01843 return NULL;
01844 }
01845 }
01846
01847 const apol_vector_t *apol_domain_trans_result_get_entrypoint_rules(const apol_domain_trans_result_t * dtr)
01848 {
01849 if (dtr) {
01850 return dtr->ep_rules;
01851 } else {
01852 errno = EINVAL;
01853 return NULL;
01854 }
01855 }
01856
01857 const apol_vector_t *apol_domain_trans_result_get_exec_rules(const apol_domain_trans_result_t * dtr)
01858 {
01859 if (dtr) {
01860 return dtr->exec_rules;
01861 } else {
01862 errno = EINVAL;
01863 return NULL;
01864 }
01865 }
01866
01867 const apol_vector_t *apol_domain_trans_result_get_setexec_rules(const apol_domain_trans_result_t * dtr)
01868 {
01869 if (dtr) {
01870 return dtr->setexec_rules;
01871 } else {
01872 errno = EINVAL;
01873 return NULL;
01874 }
01875 }
01876
01877 const apol_vector_t *apol_domain_trans_result_get_type_trans_rules(const apol_domain_trans_result_t * dtr)
01878 {
01879 if (dtr) {
01880 return dtr->type_trans_rules;
01881 } else {
01882 errno = EINVAL;
01883 return NULL;
01884 }
01885 }
01886
01887 int apol_domain_trans_result_is_trans_valid(const apol_domain_trans_result_t * dtr)
01888 {
01889 if (dtr) {
01890 return dtr->valid;
01891 } else {
01892 errno = EINVAL;
01893 return 0;
01894 }
01895 }
01896
01897 const apol_vector_t *apol_domain_trans_result_get_access_rules(const apol_domain_trans_result_t * dtr)
01898 {
01899 if (dtr) {
01900 return dtr->access_rules;
01901 } else {
01902 errno = EINVAL;
01903 return NULL;
01904 }
01905 }
01906
01907 int apol_domain_trans_table_verify_trans(apol_policy_t * policy, const qpol_type_t * start_dom, const qpol_type_t * ep_type,
01908 const qpol_type_t * end_dom)
01909 {
01910 int missing_rules = 0;
01911
01912 if (!policy || !policy->domain_trans_table) {
01913 errno = EINVAL;
01914 return -1;
01915 }
01916
01917 apol_policy_reset_domain_trans_table(policy);
01918
01919 dom_node_t start_dummy = { start_dom, NULL, NULL, NULL };
01920 dom_node_t *start_node = NULL;
01921 if (start_dom)
01922 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&start_dummy, NULL, (void **)&start_node);
01923 ep_node_t ep_dummy = { ep_type, NULL, NULL };
01924 ep_node_t *ep_node = NULL;
01925 if (ep_type)
01926 apol_bst_get_element(policy->domain_trans_table->entrypoint_table, (void *)&ep_dummy, NULL, (void **)&ep_node);
01927 dom_node_t end_dummy = { end_dom, NULL, NULL, NULL };
01928 dom_node_t *end_node = NULL;
01929 if (end_dom)
01930 apol_bst_get_element(policy->domain_trans_table->domain_table, (void *)&end_dummy, NULL, (void **)&end_node);
01931
01932 bool tt = false, sx = false, ex = false, pt = false, ep = false;
01933
01934
01935 if (start_node && end_dom) {
01936 apol_vector_t *v = find_avrules_in_node(start_node, APOL_DOMAIN_TRANS_RULE_PROC_TRANS, end_dom);
01937 if (apol_vector_get_size(v))
01938 pt = true;
01939 apol_vector_destroy(&v);
01940 }
01941
01942 if (start_dom && ep_node) {
01943 apol_vector_t *v = find_avrules_in_node(ep_node, APOL_DOMAIN_TRANS_RULE_EXEC, start_dom);
01944 if (apol_vector_get_size(v))
01945 ex = true;
01946 apol_vector_destroy(&v);
01947 }
01948
01949 if (end_node && ep_type) {
01950 apol_vector_t *v = find_avrules_in_node(end_node, APOL_DOMAIN_TRANS_RULE_ENTRYPOINT, ep_type);
01951 if (apol_vector_get_size(v))
01952 ep = true;
01953 apol_vector_destroy(&v);
01954 }
01955 if (requires_setexec_or_type_trans(policy)) {
01956
01957 if (start_node)
01958 if (apol_vector_get_size(start_node->setexec_rules))
01959 sx = true;
01960
01961 if (ep_node && start_dom && end_dom) {
01962 apol_vector_t *v = find_terules_in_node(ep_node, start_dom, end_dom);
01963 if (apol_vector_get_size(v)) {
01964 tt = true;
01965 }
01966 apol_vector_destroy(&v);
01967 }
01968 } else {
01969
01970 tt = sx = true;
01971 }
01972
01973 if (!(pt && ep && ex && (tt || sx))) {
01974 if (!pt)
01975 missing_rules |= APOL_DOMAIN_TRANS_RULE_PROC_TRANS;
01976 if (!ep)
01977 missing_rules |= APOL_DOMAIN_TRANS_RULE_ENTRYPOINT;
01978 if (!ex)
01979 missing_rules |= APOL_DOMAIN_TRANS_RULE_EXEC;
01980 if (!tt && !sx) {
01981 missing_rules |= APOL_DOMAIN_TRANS_RULE_SETEXEC;
01982
01983 const char *start_name = NULL, *end_name = NULL;
01984 qpol_type_get_name(apol_policy_get_qpol(policy), start_dom, &start_name);
01985 qpol_type_get_name(apol_policy_get_qpol(policy), end_dom, &end_name);
01986 apol_terule_query_t *tq = NULL;
01987 if (!start_name || !end_name || !(tq = apol_terule_query_create())) {
01988 return -1;
01989 }
01990 apol_terule_query_set_rules(policy, tq, QPOL_RULE_TYPE_TRANS);
01991 apol_terule_query_set_source(policy, tq, start_name, 1);
01992 apol_terule_query_set_default(policy, tq, end_name);
01993 apol_vector_t *v = NULL;
01994 if (apol_terule_get_by_query(policy, tq, &v)) {
01995 apol_terule_query_destroy(&tq);
01996 return -1;
01997 }
01998 apol_terule_query_destroy(&tq);
01999 if (!apol_vector_get_size(v))
02000 missing_rules |= APOL_DOMAIN_TRANS_RULE_TYPE_TRANS;
02001 apol_vector_destroy(&v);
02002 }
02003 }
02004
02005 return missing_rules;
02006 }
02007
02008 apol_domain_trans_result_t *apol_domain_trans_result_create_from_domain_trans_result(const apol_domain_trans_result_t * result)
02009 {
02010 apol_domain_trans_result_t *new_r = NULL;
02011 int retval = -1;
02012 if ((new_r = calloc(1, sizeof(*new_r))) == NULL) {
02013 goto cleanup;
02014 }
02015 if (result->proc_trans_rules != NULL &&
02016 (new_r->proc_trans_rules = apol_vector_create_from_vector(result->proc_trans_rules, NULL, NULL, NULL)) == NULL) {
02017 goto cleanup;
02018 }
02019 if (result->ep_rules != NULL
02020 && (new_r->ep_rules = apol_vector_create_from_vector(result->ep_rules, NULL, NULL, NULL)) == NULL) {
02021 goto cleanup;
02022 }
02023 if (result->exec_rules != NULL
02024 && (new_r->exec_rules = apol_vector_create_from_vector(result->exec_rules, NULL, NULL, NULL)) == NULL) {
02025 goto cleanup;
02026 }
02027 if (result->setexec_rules != NULL
02028 && (new_r->setexec_rules = apol_vector_create_from_vector(result->setexec_rules, NULL, NULL, NULL)) == NULL) {
02029 goto cleanup;
02030 }
02031 if (result->type_trans_rules != NULL &&
02032 (new_r->type_trans_rules = apol_vector_create_from_vector(result->type_trans_rules, NULL, NULL, NULL)) == NULL) {
02033 goto cleanup;
02034 }
02035 if (result->access_rules != NULL
02036 && (new_r->access_rules = apol_vector_create_from_vector(result->access_rules, NULL, NULL, NULL)) == NULL) {
02037 goto cleanup;
02038 }
02039 new_r->start_type = result->start_type;
02040 new_r->ep_type = result->ep_type;
02041 new_r->end_type = result->end_type;
02042 new_r->valid = result->valid;
02043 retval = 0;
02044 cleanup:
02045 if (retval != 0) {
02046 domain_trans_result_free(new_r);
02047 return NULL;
02048 }
02049 return new_r;
02050 }
02051
02052
02053
02054 void domain_trans_result_free(void *dtr)
02055 {
02056 apol_domain_trans_result_t *res = (apol_domain_trans_result_t *) dtr;
02057
02058 if (!res)
02059 return;
02060
02061 apol_vector_destroy(&res->proc_trans_rules);
02062 apol_vector_destroy(&res->ep_rules);
02063 apol_vector_destroy(&res->exec_rules);
02064 apol_vector_destroy(&res->setexec_rules);
02065 apol_vector_destroy(&res->type_trans_rules);
02066 apol_vector_destroy(&res->access_rules);
02067 free(res);
02068 }
02069
02070 void apol_domain_trans_result_destroy(apol_domain_trans_result_t ** res)
02071 {
02072 if (!res || !(*res))
02073 return;
02074 domain_trans_result_free((void *)*res);
02075 *res = NULL;
02076 }