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 <config.h>
00027
00028 #include "poldiff_internal.h"
00029
00030 #include <apol/bst.h>
00031 #include <apol/util.h>
00032 #include <assert.h>
00033 #include <errno.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036
00037 struct poldiff_role_allow_summary
00038 {
00039 size_t num_added;
00040 size_t num_removed;
00041 size_t num_modified;
00042 apol_vector_t *diffs;
00043 };
00044
00045 struct poldiff_role_trans_summary
00046 {
00047 size_t num_added;
00048 size_t num_removed;
00049 size_t num_modified;
00050 size_t num_added_type;
00051 size_t num_removed_type;
00052 apol_vector_t *diffs;
00053 };
00054
00055 struct poldiff_role_allow
00056 {
00057 const char *source_role;
00058 poldiff_form_e form;
00059 apol_vector_t *orig_roles;
00060 apol_vector_t *added_roles;
00061 apol_vector_t *removed_roles;
00062 };
00063
00064 struct poldiff_role_trans
00065 {
00066 const char *source_role;
00067 char *target_type;
00068 const char *orig_default;
00069 const char *mod_default;
00070 poldiff_form_e form;
00071 };
00072
00073
00074
00075 void poldiff_role_allow_get_stats(const poldiff_t * diff, size_t stats[5])
00076 {
00077 if (diff == NULL || stats == NULL) {
00078 ERR(diff, "%s", strerror(EINVAL));
00079 errno = EINVAL;
00080 return;
00081 }
00082 stats[0] = diff->role_allow_diffs->num_added;
00083 stats[1] = diff->role_allow_diffs->num_removed;
00084 stats[2] = diff->role_allow_diffs->num_modified;
00085 stats[3] = 0;
00086 stats[4] = 0;
00087 }
00088
00089 char *poldiff_role_allow_to_string(const poldiff_t * diff, const void *role_allow)
00090 {
00091 const poldiff_role_allow_t *ra = role_allow;
00092 size_t len = 0, i;
00093 char *s = NULL, *role;
00094 if (diff == NULL || role_allow == NULL) {
00095 ERR(diff, "%s", strerror(EINVAL));
00096 errno = EINVAL;
00097 return NULL;
00098 }
00099 switch (ra->form) {
00100 case POLDIFF_FORM_ADDED:
00101 {
00102 if (apol_str_appendf(&s, &len, "+ allow %s { ", ra->source_role) < 0) {
00103 s = NULL;
00104 break;
00105 }
00106 for (i = 0; i < apol_vector_get_size(ra->added_roles); i++) {
00107 role = apol_vector_get_element(ra->added_roles, i);
00108 if (apol_str_appendf(&s, &len, "%s ", role) < 0) {
00109 goto err;
00110 }
00111 }
00112 if (apol_str_append(&s, &len, "};") < 0) {
00113 break;
00114 }
00115 return s;
00116 }
00117 case POLDIFF_FORM_REMOVED:
00118 {
00119 if (apol_str_appendf(&s, &len, "- allow %s { ", ra->source_role) < 0) {
00120 break;
00121 }
00122 for (i = 0; i < apol_vector_get_size(ra->removed_roles); i++) {
00123 role = apol_vector_get_element(ra->removed_roles, i);
00124 if (apol_str_appendf(&s, &len, "%s ", role) < 0) {
00125 goto err;
00126 }
00127 }
00128 if (apol_str_append(&s, &len, "};") < 0) {
00129 break;
00130 }
00131 return s;
00132 }
00133 case POLDIFF_FORM_MODIFIED:
00134 {
00135 if (apol_str_appendf(&s, &len, "* allow %s { ", ra->source_role) < 0) {
00136 s = NULL;
00137 break;
00138 }
00139 for (i = 0; i < apol_vector_get_size(ra->orig_roles); i++) {
00140 role = apol_vector_get_element(ra->orig_roles, i);
00141 if (apol_str_appendf(&s, &len, "%s ", role) < 0) {
00142 goto err;
00143 }
00144 }
00145 for (i = 0; i < apol_vector_get_size(ra->added_roles); i++) {
00146 role = apol_vector_get_element(ra->added_roles, i);
00147 if (apol_str_appendf(&s, &len, "+%s ", role) < 0) {
00148 goto err;
00149 }
00150 }
00151 for (i = 0; i < apol_vector_get_size(ra->removed_roles); i++) {
00152 role = apol_vector_get_element(ra->removed_roles, i);
00153 if (apol_str_appendf(&s, &len, "-%s ", role) < 0) {
00154 goto err;
00155 }
00156 }
00157 if (apol_str_append(&s, &len, "};") < 0) {
00158 break;
00159 }
00160 return s;
00161 }
00162 default:
00163 {
00164 ERR(diff, "%s", strerror(ENOTSUP));
00165 errno = ENOTSUP;
00166 return NULL;
00167 }
00168 }
00169
00170 err:
00171 free(s);
00172 ERR(diff, "%s", strerror(ENOMEM));
00173 errno = ENOMEM;
00174 return NULL;
00175 }
00176
00177 const apol_vector_t *poldiff_get_role_allow_vector(const poldiff_t * diff)
00178 {
00179 if (diff == NULL) {
00180 ERR(diff, "%s", strerror(EINVAL));
00181 errno = EINVAL;
00182 return NULL;
00183 }
00184 return diff->role_allow_diffs->diffs;
00185 }
00186
00187 const char *poldiff_role_allow_get_name(const poldiff_role_allow_t * role_allow)
00188 {
00189 if (role_allow == NULL) {
00190 errno = EINVAL;
00191 return NULL;
00192 }
00193 return role_allow->source_role;
00194 }
00195
00196 poldiff_form_e poldiff_role_allow_get_form(const void *role_allow)
00197 {
00198 if (role_allow == NULL) {
00199 errno = EINVAL;
00200 return POLDIFF_FORM_NONE;
00201 }
00202 return ((const poldiff_role_allow_t *)role_allow)->form;
00203 }
00204
00205 const apol_vector_t *poldiff_role_allow_get_unmodified_roles(const poldiff_role_allow_t * role_allow)
00206 {
00207 if (role_allow == NULL) {
00208 errno = EINVAL;
00209 return NULL;
00210 }
00211 return role_allow->orig_roles;
00212 }
00213
00214 const apol_vector_t *poldiff_role_allow_get_added_roles(const poldiff_role_allow_t * role_allow)
00215 {
00216 if (role_allow == NULL) {
00217 errno = EINVAL;
00218 return NULL;
00219 }
00220 return role_allow->added_roles;
00221 }
00222
00223 const apol_vector_t *poldiff_role_allow_get_removed_roles(const poldiff_role_allow_t * role_allow)
00224 {
00225 if (role_allow == NULL) {
00226 errno = EINVAL;
00227 return NULL;
00228 }
00229 return role_allow->removed_roles;
00230 }
00231
00232 static void role_allow_free(void *elem)
00233 {
00234 if (elem != NULL) {
00235 poldiff_role_allow_t *r = (poldiff_role_allow_t *) elem;
00236 apol_vector_destroy(&r->orig_roles);
00237 apol_vector_destroy(&r->added_roles);
00238 apol_vector_destroy(&r->removed_roles);
00239 free(r);
00240 }
00241 }
00242
00243 poldiff_role_allow_summary_t *role_allow_create(void)
00244 {
00245 poldiff_role_allow_summary_t *ras = calloc(1, sizeof(*ras));
00246 if (ras == NULL) {
00247 return NULL;
00248 }
00249 if ((ras->diffs = apol_vector_create(role_allow_free)) == NULL) {
00250 role_allow_destroy(&ras);
00251 return NULL;
00252 }
00253 return ras;
00254 }
00255
00256 void role_allow_destroy(poldiff_role_allow_summary_t ** ras)
00257 {
00258 if (ras != NULL && *ras != NULL) {
00259 apol_vector_destroy(&(*ras)->diffs);
00260 free(*ras);
00261 *ras = NULL;
00262 }
00263 }
00264
00265 typedef struct pseudo_role_allow
00266 {
00267 const char *source_role;
00268 apol_vector_t *target_roles;
00269 } pseudo_role_allow_t;
00270
00271 static void role_allow_free_item(void *item)
00272 {
00273 pseudo_role_allow_t *pra = item;
00274
00275 if (!item)
00276 return;
00277
00278
00279 apol_vector_destroy(&pra->target_roles);
00280 free(item);
00281 }
00282
00283 static int role_allow_source_comp(const void *x, const void *y, void *arg __attribute__ ((unused)))
00284 {
00285 const pseudo_role_allow_t *p1 = x;
00286 const pseudo_role_allow_t *p2 = y;
00287
00288 return strcmp(p1->source_role, p2->source_role);
00289 }
00290
00291 apol_vector_t *role_allow_get_items(poldiff_t * diff, const apol_policy_t * policy)
00292 {
00293 qpol_iterator_t *iter = NULL;
00294 apol_vector_t *tmp = NULL, *v = NULL;
00295 int error = 0, retv;
00296 size_t i;
00297 apol_bst_t *bst = NULL;
00298 pseudo_role_allow_t *pra = NULL;
00299 const qpol_role_t *sr = NULL, *tr = NULL;
00300 const char *sr_name = NULL, *tr_name = NULL;
00301 const qpol_role_allow_t *qra = NULL;
00302 qpol_policy_t *q = apol_policy_get_qpol(policy);
00303
00304 if (qpol_policy_get_role_allow_iter(q, &iter) < 0) {
00305 return NULL;
00306 }
00307
00308 tmp = apol_vector_create_from_iter(iter, NULL);
00309 if (tmp == NULL) {
00310 error = errno;
00311 ERR(diff, "%s", strerror(error));
00312 qpol_iterator_destroy(&iter);
00313 errno = error;
00314 return NULL;
00315 }
00316 qpol_iterator_destroy(&iter);
00317
00318 bst = apol_bst_create(role_allow_source_comp, role_allow_free_item);
00319
00320 for (i = 0; i < apol_vector_get_size(tmp); i++) {
00321 qra = apol_vector_get_element(tmp, i);
00322 if (!(pra = calloc(1, sizeof(*pra))) || (!(pra->target_roles = apol_vector_create_with_capacity(1, NULL)))) {
00323 error = errno;
00324 ERR(diff, "%s", strerror(error));
00325 goto err;
00326 }
00327 if (qpol_role_allow_get_source_role(q, qra, &sr) || qpol_role_get_name(q, sr, &sr_name)) {
00328 error = errno;
00329 ERR(diff, "%s", strerror(error));
00330 goto err;
00331 }
00332 sr = NULL;
00333 if (qpol_role_allow_get_target_role(q, qra, &tr) || qpol_role_get_name(q, tr, &tr_name)) {
00334 error = errno;
00335 ERR(diff, "%s", strerror(error));
00336 goto err;
00337 }
00338 tr = NULL;
00339 pra->source_role = sr_name;
00340 retv = apol_bst_insert_and_get(bst, (void **)&pra, NULL);
00341 if (retv < 0) {
00342 error = errno;
00343 ERR(diff, "%s", strerror(error));
00344 goto err;
00345 }
00346 apol_vector_append_unique(pra->target_roles, (void *)tr_name, apol_str_strcmp, NULL);
00347 pra = NULL;
00348 }
00349 apol_vector_destroy(&tmp);
00350
00351 v = apol_bst_get_vector(bst, 1);
00352 if (!v) {
00353 error = errno;
00354 ERR(diff, "%s", strerror(error));
00355 goto err;
00356 }
00357 apol_bst_destroy(&bst);
00358
00359 return v;
00360
00361 err:
00362 role_allow_free_item(pra);
00363 apol_bst_destroy(&bst);
00364 errno = error;
00365 return NULL;
00366 }
00367
00368 int role_allow_comp(const void *x, const void *y, const poldiff_t * diff __attribute__ ((unused)))
00369 {
00370 const pseudo_role_allow_t *p1 = x;
00371 const pseudo_role_allow_t *p2 = y;
00372
00373 return strcmp(p1->source_role, p2->source_role);
00374 }
00375
00376 int role_allow_reset(poldiff_t * diff)
00377 {
00378 int error = 0;
00379
00380 if (diff == NULL) {
00381 ERR(diff, "%s", strerror(EINVAL));
00382 errno = EINVAL;
00383 return -1;
00384 }
00385
00386 role_allow_destroy(&diff->role_allow_diffs);
00387 diff->role_allow_diffs = role_allow_create();
00388 if (diff->role_allow_diffs == NULL) {
00389 error = errno;
00390 ERR(diff, "%s", strerror(error));
00391 errno = error;
00392 return -1;
00393 }
00394
00395 return 0;
00396 }
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 static poldiff_role_allow_t *make_ra_diff(const poldiff_t * diff, poldiff_form_e form, const char *source_role)
00410 {
00411 poldiff_role_allow_t *ra = NULL;
00412 int error = 0;
00413 if ((ra = calloc(1, sizeof(*ra))) == NULL ||
00414 (ra->source_role = source_role) == NULL ||
00415 (ra->added_roles = apol_vector_create_with_capacity(1, NULL)) == NULL ||
00416 (ra->orig_roles = apol_vector_create_with_capacity(1, NULL)) == NULL ||
00417 (ra->removed_roles = apol_vector_create_with_capacity(1, NULL)) == NULL) {
00418 error = errno;
00419 role_allow_free(ra);
00420 ERR(diff, "%s", strerror(error));
00421 errno = error;
00422 return NULL;
00423 }
00424 ra->form = form;
00425 return ra;
00426 }
00427
00428 int role_allow_new_diff(poldiff_t * diff, poldiff_form_e form, const void *item)
00429 {
00430 pseudo_role_allow_t *ra = (pseudo_role_allow_t *) item;
00431 poldiff_role_allow_t *pra;
00432 int error;
00433
00434 pra = make_ra_diff(diff, form, ra->source_role);
00435 if (pra == NULL) {
00436 return -1;
00437 }
00438 int rt;
00439 if (form == POLDIFF_FORM_ADDED) {
00440 rt = apol_vector_cat(pra->added_roles, ra->target_roles);
00441 } else {
00442 rt = apol_vector_cat(pra->removed_roles, ra->target_roles);
00443 }
00444 if (rt < 0) {
00445 error = errno;
00446 ERR(diff, "%s", strerror(error));
00447 role_allow_free(pra);
00448 errno = error;
00449 return -1;
00450 }
00451 if (apol_vector_append(diff->role_allow_diffs->diffs, pra) < 0) {
00452 error = errno;
00453 ERR(diff, "%s", strerror(error));
00454 role_allow_free(pra);
00455 errno = error;
00456 return -1;
00457 }
00458 if (form == POLDIFF_FORM_ADDED) {
00459 diff->role_allow_diffs->num_added++;
00460 } else {
00461 diff->role_allow_diffs->num_removed++;
00462 }
00463 return 0;
00464 }
00465
00466 int role_allow_deep_diff(poldiff_t * diff, const void *x, const void *y)
00467 {
00468 const pseudo_role_allow_t *p1 = x;
00469 const pseudo_role_allow_t *p2 = y;
00470 apol_vector_t *v1 = NULL, *v2 = NULL;
00471 char *role1, *role2;
00472 poldiff_role_allow_t *pra = NULL;
00473 size_t i, j;
00474 int retval = -1, error = 0, compval;
00475
00476 v1 = p1->target_roles;
00477 v2 = p2->target_roles;
00478
00479 apol_vector_sort(v1, apol_str_strcmp, NULL);
00480 apol_vector_sort(v2, apol_str_strcmp, NULL);
00481 for (i = j = 0; i < apol_vector_get_size(v1);) {
00482 if (j >= apol_vector_get_size(v2))
00483 break;
00484 role1 = (char *)apol_vector_get_element(v1, i);
00485 role2 = (char *)apol_vector_get_element(v2, j);
00486 compval = strcmp(role1, role2);
00487 if (pra == NULL) {
00488 if ((pra = make_ra_diff(diff, POLDIFF_FORM_MODIFIED, p1->source_role)) == NULL) {
00489 error = errno;
00490 goto cleanup;
00491 }
00492 }
00493 if (compval < 0) {
00494 if (apol_vector_append(pra->removed_roles, role1) < 0) {
00495 error = errno;
00496 ERR(diff, "%s", strerror(error));
00497 goto cleanup;
00498 }
00499 i++;
00500 } else if (compval > 0) {
00501 if (apol_vector_append(pra->added_roles, role2) < 0) {
00502 error = errno;
00503 ERR(diff, "%s", strerror(error));
00504 goto cleanup;
00505 }
00506 j++;
00507 } else {
00508 if (apol_vector_append(pra->orig_roles, role1) < 0) {
00509 error = errno;
00510 ERR(diff, "%s", strerror(error));
00511 goto cleanup;
00512 }
00513 i++;
00514 j++;
00515 }
00516 }
00517 for (; i < apol_vector_get_size(v1); i++) {
00518 role1 = (char *)apol_vector_get_element(v1, i);
00519 if (pra == NULL) {
00520 if ((pra = make_ra_diff(diff, POLDIFF_FORM_MODIFIED, p1->source_role)) == NULL) {
00521 error = errno;
00522 goto cleanup;
00523 }
00524 }
00525 if (apol_vector_append(pra->removed_roles, role1) < 0) {
00526 error = errno;
00527 free(role1);
00528 ERR(diff, "%s", strerror(error));
00529 goto cleanup;
00530 }
00531 }
00532 for (; j < apol_vector_get_size(v2); j++) {
00533 role2 = (char *)apol_vector_get_element(v2, j);
00534 if (pra == NULL) {
00535 if ((pra = make_ra_diff(diff, POLDIFF_FORM_MODIFIED, p1->source_role)) == NULL) {
00536 error = errno;
00537 goto cleanup;
00538 }
00539 }
00540 if (apol_vector_append(pra->added_roles, role2) < 0) {
00541 error = errno;
00542 free(role2);
00543 ERR(diff, "%s", strerror(error));
00544 goto cleanup;
00545 }
00546 }
00547 if (apol_vector_get_size(pra->added_roles) || apol_vector_get_size(pra->removed_roles)) {
00548 apol_vector_sort(pra->removed_roles, apol_str_strcmp, NULL);
00549 apol_vector_sort(pra->added_roles, apol_str_strcmp, NULL);
00550 apol_vector_sort(pra->orig_roles, apol_str_strcmp, NULL);
00551 if (apol_vector_append(diff->role_allow_diffs->diffs, pra) < 0) {
00552 error = errno;
00553 ERR(diff, "%s", strerror(error));
00554 goto cleanup;
00555 }
00556 diff->role_allow_diffs->num_modified++;
00557 } else {
00558 role_allow_free(pra);
00559 pra = NULL;
00560 }
00561 retval = 0;
00562 cleanup:
00563 if (retval != 0) {
00564 role_allow_free(pra);
00565 }
00566 errno = error;
00567 return retval;
00568 }
00569
00570
00571
00572 void poldiff_role_trans_get_stats(const poldiff_t * diff, size_t stats[5])
00573 {
00574 if (diff == NULL || stats == NULL) {
00575 ERR(diff, "%s", strerror(EINVAL));
00576 errno = EINVAL;
00577 return;
00578 }
00579 stats[0] = diff->role_trans_diffs->num_added;
00580 stats[1] = diff->role_trans_diffs->num_removed;
00581 stats[2] = diff->role_trans_diffs->num_modified;
00582 stats[3] = diff->role_trans_diffs->num_added_type;
00583 stats[4] = diff->role_trans_diffs->num_removed_type;
00584 }
00585
00586 extern char *poldiff_role_trans_to_string(const poldiff_t * diff, const void *role_trans)
00587 {
00588 const poldiff_role_trans_t *rt = role_trans;
00589 char *s = NULL;
00590
00591 if (diff == NULL || role_trans == NULL) {
00592 ERR(diff, "%s", strerror(EINVAL));
00593 errno = EINVAL;
00594 return NULL;
00595 }
00596 switch (rt->form) {
00597 case POLDIFF_FORM_ADDED:
00598 case POLDIFF_FORM_ADD_TYPE:
00599 {
00600 if (asprintf(&s, "+ role_transition %s %s %s;", rt->source_role, rt->target_type, rt->mod_default) < 0)
00601 break;
00602 return s;
00603 }
00604 case POLDIFF_FORM_REMOVED:
00605 case POLDIFF_FORM_REMOVE_TYPE:
00606 {
00607 if (asprintf(&s, "- role_transition %s %s %s;", rt->source_role, rt->target_type, rt->orig_default) < 0)
00608 break;
00609 return s;
00610 }
00611 case POLDIFF_FORM_MODIFIED:
00612 {
00613 if (asprintf
00614 (&s, "* role_transition %s %s { +%s -%s };", rt->source_role, rt->target_type, rt->mod_default,
00615 rt->orig_default) < 0)
00616 break;
00617 return s;
00618 }
00619 case POLDIFF_FORM_NONE:
00620 default:
00621 {
00622 ERR(diff, "%s", strerror(ENOTSUP));
00623 errno = ENOTSUP;
00624 return NULL;
00625 }
00626 }
00627
00628 free(s);
00629 ERR(diff, "%s", strerror(ENOMEM));
00630 errno = ENOMEM;
00631 return NULL;
00632 }
00633
00634 const apol_vector_t *poldiff_get_role_trans_vector(const poldiff_t * diff)
00635 {
00636 if (diff == NULL) {
00637 ERR(diff, "%s", strerror(EINVAL));
00638 errno = EINVAL;
00639 return NULL;
00640 }
00641 return diff->role_trans_diffs->diffs;
00642 }
00643
00644 extern const char *poldiff_role_trans_get_source_role(const poldiff_role_trans_t * role_trans)
00645 {
00646 if (role_trans == NULL) {
00647 errno = EINVAL;
00648 return NULL;
00649 }
00650 return role_trans->source_role;
00651 }
00652
00653 extern const char *poldiff_role_trans_get_target_type(const poldiff_role_trans_t * role_trans)
00654 {
00655 if (role_trans == NULL) {
00656 errno = EINVAL;
00657 return NULL;
00658 }
00659 return role_trans->target_type;
00660 }
00661
00662 extern poldiff_form_e poldiff_role_trans_get_form(const void *role_trans)
00663 {
00664 if (role_trans == NULL) {
00665 errno = EINVAL;
00666 return POLDIFF_FORM_NONE;
00667 }
00668 return ((const poldiff_role_trans_t *)role_trans)->form;
00669 }
00670
00671 extern const char *poldiff_role_trans_get_original_default(const poldiff_role_trans_t * role_trans)
00672 {
00673 if (role_trans == NULL) {
00674 errno = EINVAL;
00675 return NULL;
00676 }
00677 return role_trans->orig_default;
00678 }
00679
00680 extern const char *poldiff_role_trans_get_modified_default(const poldiff_role_trans_t * role_trans)
00681 {
00682 if (role_trans == NULL) {
00683 errno = EINVAL;
00684 return NULL;
00685 }
00686 return role_trans->mod_default;
00687 }
00688
00689 static void role_trans_free(void *elem)
00690 {
00691 if (elem != NULL) {
00692 poldiff_role_trans_t *rt = elem;
00693 free(rt->target_type);
00694 free(rt);
00695 }
00696 }
00697
00698 poldiff_role_trans_summary_t *role_trans_create(void)
00699 {
00700 poldiff_role_trans_summary_t *rts = calloc(1, sizeof(*rts));
00701 if (rts == NULL) {
00702 return NULL;
00703 }
00704 if ((rts->diffs = apol_vector_create(role_trans_free)) == NULL) {
00705 role_trans_destroy(&rts);
00706 return NULL;
00707 }
00708 return rts;
00709 }
00710
00711 void role_trans_destroy(poldiff_role_trans_summary_t ** rts)
00712 {
00713 if (rts != NULL && *rts != NULL) {
00714 apol_vector_destroy(&(*rts)->diffs);
00715 free(*rts);
00716 *rts = NULL;
00717 }
00718 }
00719
00720 int role_trans_reset(poldiff_t * diff)
00721 {
00722 int error = 0;
00723
00724 if (diff == NULL) {
00725 ERR(diff, "%s", strerror(EINVAL));
00726 errno = EINVAL;
00727 return -1;
00728 }
00729
00730 role_trans_destroy(&diff->role_trans_diffs);
00731 diff->role_trans_diffs = role_trans_create();
00732 if (diff->role_trans_diffs == NULL) {
00733 error = errno;
00734 ERR(diff, "%s", strerror(error));
00735 errno = error;
00736 return -1;
00737 }
00738
00739 return 0;
00740 }
00741
00742 typedef struct pseudo_role_trans
00743 {
00744 const char *source_role;
00745 uint32_t pseudo_target;
00746 const char *default_role;
00747 } pseudo_role_trans_t;
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 static int pseudo_role_trans_comp(const void *x, const void *y, void *arg)
00762 {
00763 int retv = 0;
00764 const pseudo_role_trans_t *a = x;
00765 const pseudo_role_trans_t *b = y;
00766 poldiff_t *diff = arg;
00767
00768 retv = strcmp(a->source_role, b->source_role);
00769 if (!retv)
00770 retv = a->pseudo_target - b->pseudo_target;
00771 else
00772 return retv;
00773 if (!retv && strcmp(a->default_role, b->default_role))
00774 WARN(diff, "Multiple role_transition rules for %s %s with different default roles.", a->source_role,
00775 type_map_get_name(diff, a->pseudo_target, POLDIFF_POLICY_ORIG));
00776 return retv;
00777 }
00778
00779 static void role_trans_free_item(void *item)
00780 {
00781
00782 free(item);
00783 }
00784
00785 apol_vector_t *role_trans_get_items(poldiff_t * diff, const apol_policy_t * policy)
00786 {
00787 qpol_iterator_t *iter = NULL, *attr_types = NULL;
00788 apol_vector_t *v = NULL;
00789 const qpol_role_trans_t *qrt = NULL;
00790 pseudo_role_trans_t *tmp_prt = NULL;
00791 const char *tmp_name = NULL;
00792 const qpol_role_t *tmp_role = NULL;
00793 const qpol_type_t *tmp_type = NULL;
00794 qpol_policy_t *q = apol_policy_get_qpol(policy);
00795 int error = 0, which_pol;
00796 unsigned char isattr = 0;
00797
00798 which_pol = (policy == diff->orig_pol ? POLDIFF_POLICY_ORIG : POLDIFF_POLICY_MOD);
00799 if (qpol_policy_get_role_trans_iter(q, &iter)) {
00800 error = errno;
00801 goto err;
00802 }
00803 v = apol_vector_create(role_trans_free_item);
00804 if (!v) {
00805 error = errno;
00806 ERR(diff, "%s", strerror(error));
00807 goto err;
00808 }
00809 for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) {
00810 isattr = 0;
00811 if (qpol_iterator_get_item(iter, (void **)&qrt) < 0) {
00812 error = errno;
00813 ERR(diff, "%s", strerror(error));
00814 goto err;
00815 }
00816 if (qpol_role_trans_get_target_type(q, qrt, &tmp_type) < 0) {
00817 error = errno;
00818 goto err;
00819 }
00820 qpol_type_get_isattr(q, tmp_type, &isattr);
00821 if (isattr) {
00822 qpol_type_get_type_iter(q, tmp_type, &attr_types);
00823 for (; !qpol_iterator_end(attr_types); qpol_iterator_next(attr_types)) {
00824 qpol_iterator_get_item(attr_types, (void **)&tmp_type);
00825 if (!(tmp_prt = calloc(1, sizeof(*tmp_prt)))) {
00826 error = errno;
00827 ERR(diff, "%s", strerror(error));
00828 goto err;
00829 }
00830 tmp_prt->pseudo_target = type_map_lookup(diff, tmp_type, which_pol);
00831 qpol_role_trans_get_source_role(q, qrt, &tmp_role);
00832 qpol_role_get_name(q, tmp_role, &tmp_name);
00833 tmp_prt->source_role = tmp_name;
00834 qpol_role_trans_get_default_role(q, qrt, &tmp_role);
00835 qpol_role_get_name(q, tmp_role, &tmp_name);
00836 tmp_prt->default_role = tmp_name;
00837 if (apol_vector_append(v, tmp_prt)) {
00838 error = errno;
00839 ERR(diff, "%s", strerror(error));
00840 goto err;
00841 }
00842 tmp_prt = NULL;
00843 }
00844 qpol_iterator_destroy(&attr_types);
00845 } else {
00846 if (!(tmp_prt = calloc(1, sizeof(*tmp_prt)))) {
00847 error = errno;
00848 ERR(diff, "%s", strerror(error));
00849 goto err;
00850 }
00851 tmp_prt->pseudo_target = type_map_lookup(diff, tmp_type, which_pol);
00852 qpol_role_trans_get_source_role(q, qrt, &tmp_role);
00853 qpol_role_get_name(q, tmp_role, &tmp_name);
00854 tmp_prt->source_role = tmp_name;
00855 qpol_role_trans_get_default_role(q, qrt, &tmp_role);
00856 qpol_role_get_name(q, tmp_role, &tmp_name);
00857 tmp_prt->default_role = tmp_name;
00858 if (apol_vector_append(v, tmp_prt)) {
00859 error = errno;
00860 ERR(diff, "%s", strerror(error));
00861 goto err;
00862 }
00863 tmp_prt = NULL;
00864 }
00865 }
00866 qpol_iterator_destroy(&iter);
00867 apol_vector_sort_uniquify(v, pseudo_role_trans_comp, diff);
00868
00869 return v;
00870
00871 err:
00872 qpol_iterator_destroy(&iter);
00873 qpol_iterator_destroy(&attr_types);
00874 apol_vector_destroy(&v);
00875 free(tmp_prt);
00876 errno = error;
00877 return NULL;
00878 }
00879
00880 int role_trans_comp(const void *x, const void *y, const poldiff_t * diff __attribute__ ((unused)))
00881 {
00882 int retv = 0;
00883 const pseudo_role_trans_t *a = x;
00884 const pseudo_role_trans_t *b = y;
00885
00886 retv = strcmp(a->source_role, b->source_role);
00887 if (!retv)
00888 return a->pseudo_target - b->pseudo_target;
00889 else
00890 return retv;
00891 }
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905 static poldiff_role_trans_t *make_rt_diff(const poldiff_t * diff, poldiff_form_e form, const char *src, const char *tgt)
00906 {
00907 poldiff_role_trans_t *rt = NULL;
00908 int error = 0;
00909 if ((rt = calloc(1, sizeof(*rt))) == NULL || (rt->source_role = src) == NULL || (rt->target_type = strdup(tgt)) == NULL) {
00910 error = errno;
00911 role_trans_free(rt);
00912 ERR(diff, "%s", strerror(error));
00913 errno = error;
00914 return NULL;
00915 }
00916 rt->form = form;
00917 return rt;
00918 }
00919
00920 int role_trans_new_diff(poldiff_t * diff, poldiff_form_e form, const void *item)
00921 {
00922 const pseudo_role_trans_t *rt = item;
00923 poldiff_role_trans_t *prt = NULL;
00924 const char *tgt_name = NULL;
00925 int error = 0;
00926
00927
00928 switch (form) {
00929 case POLDIFF_FORM_ADDED:
00930 {
00931 tgt_name = type_map_get_name(diff, rt->pseudo_target, POLDIFF_POLICY_MOD);
00932 if (type_map_get_name(diff, rt->pseudo_target, POLDIFF_POLICY_ORIG) == NULL) {
00933 form = POLDIFF_FORM_ADD_TYPE;
00934 }
00935 break;
00936 }
00937 case POLDIFF_FORM_REMOVED:
00938 {
00939 tgt_name = type_map_get_name(diff, rt->pseudo_target, POLDIFF_POLICY_ORIG);
00940 if (type_map_get_name(diff, rt->pseudo_target, POLDIFF_POLICY_MOD) == NULL) {
00941 form = POLDIFF_FORM_REMOVE_TYPE;
00942 }
00943 break;
00944 }
00945 case POLDIFF_FORM_MODIFIED:
00946 case POLDIFF_FORM_NONE:
00947 default:
00948 {
00949 assert(0);
00950 return -1;
00951 }
00952 }
00953 assert(tgt_name != NULL);
00954
00955
00956 prt = make_rt_diff(diff, form, rt->source_role, tgt_name);
00957 if (!prt)
00958 return -1;
00959
00960
00961 switch (form) {
00962 case POLDIFF_FORM_ADDED:
00963 case POLDIFF_FORM_ADD_TYPE:
00964 {
00965 prt->mod_default = rt->default_role;
00966 break;
00967 }
00968 case POLDIFF_FORM_REMOVED:
00969 case POLDIFF_FORM_REMOVE_TYPE:
00970 {
00971 prt->orig_default = rt->default_role;
00972 break;
00973 }
00974 default:
00975 {
00976
00977 assert(0);
00978 }
00979 }
00980 if (apol_vector_append(diff->role_trans_diffs->diffs, prt)) {
00981 error = errno;
00982 ERR(diff, "%s", strerror(error));
00983 role_trans_free(prt);
00984 errno = error;
00985 return -1;
00986 };
00987
00988
00989 switch (form) {
00990 case POLDIFF_FORM_ADDED:
00991 {
00992 diff->role_trans_diffs->num_added++;
00993 break;
00994 }
00995 case POLDIFF_FORM_ADD_TYPE:
00996 {
00997 diff->role_trans_diffs->num_added_type++;
00998 break;
00999 }
01000 case POLDIFF_FORM_REMOVED:
01001 {
01002 diff->role_trans_diffs->num_removed++;
01003 break;
01004 }
01005 case POLDIFF_FORM_REMOVE_TYPE:
01006 {
01007 diff->role_trans_diffs->num_removed_type++;
01008 break;
01009 }
01010 default:
01011 {
01012
01013 assert(0);
01014 }
01015 }
01016
01017 return 0;
01018 }
01019
01020 int role_trans_deep_diff(poldiff_t * diff, const void *x, const void *y)
01021 {
01022 const pseudo_role_trans_t *prt1 = x;
01023 const pseudo_role_trans_t *prt2 = y;
01024 const char *default1 = NULL, *default2 = NULL;
01025 poldiff_role_trans_t *rt = NULL;
01026 const char *tgt = NULL;
01027 int error = 0;
01028
01029 default1 = prt1->default_role;
01030 default2 = prt2->default_role;
01031
01032 if (!strcmp(default1, default2))
01033 return 0;
01034
01035 tgt = type_map_get_name(diff, prt1->pseudo_target, POLDIFF_POLICY_ORIG);
01036 assert(tgt != NULL);
01037 rt = make_rt_diff(diff, POLDIFF_FORM_MODIFIED, prt1->source_role, tgt);
01038 if (!rt)
01039 return -1;
01040 rt->orig_default = default1;
01041 rt->mod_default = default2;
01042 if (apol_vector_append(diff->role_trans_diffs->diffs, rt)) {
01043 error = errno;
01044 ERR(diff, "%s", strerror(error));
01045 role_trans_free(rt);
01046 errno = error;
01047 return -1;
01048 };
01049 diff->role_trans_diffs->num_modified++;
01050
01051 return 0;
01052 }