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/util.h>
00031 #include <errno.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034
00035
00036
00037 struct poldiff_class_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_class
00046 {
00047 char *name;
00048 poldiff_form_e form;
00049 apol_vector_t *added_perms;
00050 apol_vector_t *removed_perms;
00051 };
00052
00053 void poldiff_class_get_stats(const poldiff_t * diff, size_t stats[5])
00054 {
00055 if (diff == NULL || stats == NULL) {
00056 ERR(diff, "%s", strerror(EINVAL));
00057 errno = EINVAL;
00058 return;
00059 }
00060 stats[0] = diff->class_diffs->num_added;
00061 stats[1] = diff->class_diffs->num_removed;
00062 stats[2] = diff->class_diffs->num_modified;
00063 stats[3] = 0;
00064 stats[4] = 0;
00065 }
00066
00067 char *poldiff_class_to_string(const poldiff_t * diff, const void *cls)
00068 {
00069 poldiff_class_t *c = (poldiff_class_t *) cls;
00070 size_t num_added, num_removed, len = 0, i;
00071 char *s = NULL, *perm;
00072 if (diff == NULL || cls == NULL) {
00073 ERR(diff, "%s", strerror(EINVAL));
00074 errno = EINVAL;
00075 return NULL;
00076 }
00077 num_added = apol_vector_get_size(c->added_perms);
00078 num_removed = apol_vector_get_size(c->removed_perms);
00079 switch (c->form) {
00080 case POLDIFF_FORM_ADDED:
00081 {
00082 if (apol_str_appendf(&s, &len, "+ %s", c->name) < 0) {
00083 break;
00084 }
00085 return s;
00086 }
00087 case POLDIFF_FORM_REMOVED:
00088 {
00089 if (apol_str_appendf(&s, &len, "- %s", c->name) < 0) {
00090 break;
00091 }
00092 return s;
00093 }
00094 case POLDIFF_FORM_MODIFIED:
00095 {
00096 if (apol_str_appendf(&s, &len, "* %s (", c->name) < 0) {
00097 s = NULL;
00098 break;
00099 }
00100 if (num_added > 0) {
00101 if (apol_str_appendf(&s, &len, "%zd Added Permission%s", num_added, (num_added == 1 ? "" : "s")) < 0) {
00102 break;
00103 }
00104 }
00105 if (num_removed > 0) {
00106 if (apol_str_appendf
00107 (&s, &len, "%s%zd Removed Permission%s", (num_added > 0 ? ", " : ""), num_removed,
00108 (num_removed == 1 ? "" : "s")) < 0) {
00109 break;
00110 }
00111 }
00112 if (apol_str_append(&s, &len, ")\n") < 0) {
00113 break;
00114 }
00115 for (i = 0; i < apol_vector_get_size(c->added_perms); i++) {
00116 perm = (char *)apol_vector_get_element(c->added_perms, i);
00117 if (apol_str_appendf(&s, &len, "\t+ %s\n", perm) < 0) {
00118 goto err;
00119 }
00120 }
00121 for (i = 0; i < apol_vector_get_size(c->removed_perms); i++) {
00122 perm = (char *)apol_vector_get_element(c->removed_perms, i);
00123 if (apol_str_appendf(&s, &len, "\t- %s\n", perm) < 0) {
00124 goto err;
00125 }
00126 }
00127 return s;
00128 }
00129 default:
00130 {
00131 ERR(diff, "%s", strerror(ENOTSUP));
00132 errno = ENOTSUP;
00133 return NULL;
00134 }
00135 }
00136 err:
00137
00138 free(s);
00139 ERR(diff, "%s", strerror(ENOMEM));
00140 errno = ENOMEM;
00141 return NULL;
00142 }
00143
00144 const apol_vector_t *poldiff_get_class_vector(const poldiff_t * diff)
00145 {
00146 if (diff == NULL) {
00147 errno = EINVAL;
00148 return NULL;
00149 }
00150 return diff->class_diffs->diffs;
00151 }
00152
00153 const char *poldiff_class_get_name(const poldiff_class_t * cls)
00154 {
00155 if (cls == NULL) {
00156 errno = EINVAL;
00157 return NULL;
00158 }
00159 return cls->name;
00160 }
00161
00162 poldiff_form_e poldiff_class_get_form(const void *cls)
00163 {
00164 if (cls == NULL) {
00165 errno = EINVAL;
00166 return 0;
00167 }
00168 return ((const poldiff_class_t *)cls)->form;
00169 }
00170
00171 const apol_vector_t *poldiff_class_get_added_perms(const poldiff_class_t * cls)
00172 {
00173 if (cls == NULL) {
00174 errno = EINVAL;
00175 return NULL;
00176 }
00177 return cls->added_perms;
00178 }
00179
00180 const apol_vector_t *poldiff_class_get_removed_perms(const poldiff_class_t * cls)
00181 {
00182 if (cls == NULL) {
00183 errno = EINVAL;
00184 return NULL;
00185 }
00186 return cls->removed_perms;
00187 }
00188
00189
00190
00191 static void class_free(void *elem)
00192 {
00193 if (elem != NULL) {
00194 poldiff_class_t *c = (poldiff_class_t *) elem;
00195 free(c->name);
00196 apol_vector_destroy(&c->added_perms);
00197 apol_vector_destroy(&c->removed_perms);
00198 free(c);
00199 }
00200 }
00201
00202 poldiff_class_summary_t *class_create(void)
00203 {
00204 poldiff_class_summary_t *cs = calloc(1, sizeof(*cs));
00205 if (cs == NULL) {
00206 return NULL;
00207 }
00208 if ((cs->diffs = apol_vector_create(class_free)) == NULL) {
00209 class_destroy(&cs);
00210 return NULL;
00211 }
00212 return cs;
00213 }
00214
00215 void class_destroy(poldiff_class_summary_t ** cs)
00216 {
00217 if (cs != NULL && *cs != NULL) {
00218 apol_vector_destroy(&(*cs)->diffs);
00219 free(*cs);
00220 *cs = NULL;
00221 }
00222 }
00223
00224 int class_reset(poldiff_t * diff)
00225 {
00226 int error = 0;
00227
00228 if (diff == NULL) {
00229 ERR(diff, "%s", strerror(EINVAL));
00230 errno = EINVAL;
00231 return -1;
00232 }
00233
00234 class_destroy(&diff->class_diffs);
00235 diff->class_diffs = class_create();
00236 if (diff->class_diffs == NULL) {
00237 error = errno;
00238 ERR(diff, "%s", strerror(error));
00239 errno = error;
00240 return -1;
00241 }
00242
00243 return 0;
00244 }
00245
00246
00247
00248
00249 static int class_name_comp(const void *x, const void *y, void *arg)
00250 {
00251 const qpol_class_t *c1 = x;
00252 const qpol_class_t *c2 = y;
00253 apol_policy_t *p = (apol_policy_t *) arg;
00254 qpol_policy_t *q = apol_policy_get_qpol(p);
00255 const char *name1, *name2;
00256 if (qpol_class_get_name(q, c1, &name1) < 0 || qpol_class_get_name(q, c2, &name2) < 0) {
00257 return 0;
00258 }
00259 return strcmp(name1, name2);
00260 }
00261
00262 apol_vector_t *class_get_items(poldiff_t * diff, const apol_policy_t * policy)
00263 {
00264 qpol_iterator_t *iter = NULL;
00265 apol_vector_t *v = NULL;
00266 qpol_policy_t *q = apol_policy_get_qpol(policy);
00267 int error = 0;
00268 if (qpol_policy_get_class_iter(q, &iter) < 0) {
00269 return NULL;
00270 }
00271 v = apol_vector_create_from_iter(iter, NULL);
00272 if (v == NULL) {
00273 error = errno;
00274 ERR(diff, "%s", strerror(error));
00275 qpol_iterator_destroy(&iter);
00276 errno = error;
00277 return NULL;
00278 }
00279 qpol_iterator_destroy(&iter);
00280 apol_vector_sort(v, class_name_comp, (void *)policy);
00281 return v;
00282 }
00283
00284 int class_comp(const void *x, const void *y, const poldiff_t * diff)
00285 {
00286 const qpol_class_t *c1 = x;
00287 const qpol_class_t *c2 = y;
00288 const char *name1, *name2;
00289 if (qpol_class_get_name(diff->orig_qpol, c1, &name1) < 0 || qpol_class_get_name(diff->mod_qpol, c2, &name2) < 0) {
00290 return 0;
00291 }
00292 return strcmp(name1, name2);
00293 }
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306 static poldiff_class_t *make_diff(const poldiff_t * diff, poldiff_form_e form, const char *name)
00307 {
00308 poldiff_class_t *pc;
00309 int error;
00310 if ((pc = calloc(1, sizeof(*pc))) == NULL ||
00311 (pc->name = strdup(name)) == NULL ||
00312 (pc->added_perms = apol_vector_create_with_capacity(1, free)) == NULL ||
00313 (pc->removed_perms = apol_vector_create_with_capacity(1, free)) == NULL) {
00314 error = errno;
00315 class_free(pc);
00316 ERR(diff, "%s", strerror(error));
00317 errno = error;
00318 return NULL;
00319 }
00320 pc->form = form;
00321 return pc;
00322 }
00323
00324 int class_new_diff(poldiff_t * diff, poldiff_form_e form, const void *item)
00325 {
00326 const qpol_class_t *c = item;
00327 const char *name = NULL;
00328 poldiff_class_t *pc;
00329 int error;
00330 if ((form == POLDIFF_FORM_ADDED &&
00331 qpol_class_get_name(diff->mod_qpol, c, &name) < 0) ||
00332 ((form == POLDIFF_FORM_REMOVED || form == POLDIFF_FORM_MODIFIED) && qpol_class_get_name(diff->orig_qpol, c, &name) < 0))
00333 {
00334 return -1;
00335 }
00336 pc = make_diff(diff, form, name);
00337 if (pc == NULL) {
00338 return -1;
00339 }
00340 if (apol_vector_append(diff->class_diffs->diffs, pc) < 0) {
00341 error = errno;
00342 ERR(diff, "%s", strerror(error));
00343 class_free(pc);
00344 errno = error;
00345 return -1;
00346 }
00347 if (form == POLDIFF_FORM_ADDED) {
00348 diff->class_diffs->num_added++;
00349 } else {
00350 diff->class_diffs->num_removed++;
00351 }
00352 return 0;
00353 }
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368 static apol_vector_t *class_get_perms(const poldiff_t * diff, const apol_policy_t * p, const qpol_class_t * class)
00369 {
00370 const qpol_common_t *common;
00371 qpol_iterator_t *perm_iter = NULL, *common_iter = NULL;
00372 char *perm;
00373 apol_vector_t *v = NULL;
00374 qpol_policy_t *q = apol_policy_get_qpol(p);
00375 int retval = -1;
00376
00377 if ((v = apol_vector_create(NULL)) == NULL) {
00378 ERR(diff, "%s", strerror(errno));
00379 goto cleanup;
00380 }
00381 if (qpol_class_get_common(q, class, &common) < 0 || qpol_class_get_perm_iter(q, class, &perm_iter) < 0) {
00382 goto cleanup;
00383 }
00384 for (; !qpol_iterator_end(perm_iter); qpol_iterator_next(perm_iter)) {
00385 if (qpol_iterator_get_item(perm_iter, (void **)&perm) < 0) {
00386 goto cleanup;
00387 }
00388 if (apol_vector_append(v, perm) < 0) {
00389 ERR(diff, "%s", strerror(errno));
00390 goto cleanup;
00391 }
00392 }
00393 if (common != NULL) {
00394 if (qpol_common_get_perm_iter(q, common, &common_iter) < 0) {
00395 goto cleanup;
00396 }
00397 for (; !qpol_iterator_end(common_iter); qpol_iterator_next(common_iter)) {
00398 if (qpol_iterator_get_item(common_iter, (void **)&perm) < 0) {
00399 goto cleanup;
00400 }
00401 if (apol_vector_append(v, perm) < 0) {
00402 ERR(diff, "%s", strerror(errno));
00403 goto cleanup;
00404 }
00405 }
00406 }
00407
00408 retval = 0;
00409 cleanup:
00410 qpol_iterator_destroy(&perm_iter);
00411 qpol_iterator_destroy(&common_iter);
00412 if (retval < 0) {
00413 apol_vector_destroy(&v);
00414 return NULL;
00415 }
00416 return v;
00417 }
00418
00419 int class_deep_diff(poldiff_t * diff, const void *x, const void *y)
00420 {
00421 const qpol_class_t *c1 = x;
00422 const qpol_class_t *c2 = y;
00423 apol_vector_t *v1 = NULL, *v2 = NULL;
00424 char *perm1 = NULL, *perm2 = NULL;
00425 const char *name;
00426 poldiff_class_t *c = NULL;
00427 size_t i, j;
00428 int retval = -1, error = 0, compval;
00429
00430 if (qpol_class_get_name(diff->orig_qpol, c1, &name) < 0 ||
00431 (v1 = class_get_perms(diff, diff->orig_pol, c1)) == NULL || (v2 = class_get_perms(diff, diff->mod_pol, c2)) == NULL) {
00432 error = errno;
00433 goto cleanup;
00434 }
00435 apol_vector_sort(v1, apol_str_strcmp, NULL);
00436 apol_vector_sort(v2, apol_str_strcmp, NULL);
00437 for (i = j = 0; i < apol_vector_get_size(v1);) {
00438 if (j >= apol_vector_get_size(v2))
00439 break;
00440 perm1 = (char *)apol_vector_get_element(v1, i);
00441 perm2 = (char *)apol_vector_get_element(v2, j);
00442 compval = strcmp(perm1, perm2);
00443 if (compval != 0 && c == NULL) {
00444 if ((c = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00445 error = errno;
00446 goto cleanup;
00447 }
00448 }
00449 if (compval < 0) {
00450 if ((perm1 = strdup(perm1)) == NULL || apol_vector_append(c->removed_perms, perm1) < 0) {
00451 error = errno;
00452 free(perm1);
00453 ERR(diff, "%s", strerror(error));
00454 goto cleanup;
00455 }
00456 i++;
00457 } else if (compval > 0) {
00458 if ((perm2 = strdup(perm2)) == NULL || apol_vector_append(c->added_perms, perm2) < 0) {
00459 error = errno;
00460 free(perm2);
00461 ERR(diff, "%s", strerror(error));
00462 goto cleanup;
00463 }
00464 j++;
00465 } else {
00466 i++;
00467 j++;
00468 }
00469 }
00470 for (; i < apol_vector_get_size(v1); i++) {
00471 perm1 = (char *)apol_vector_get_element(v1, i);
00472 if (c == NULL) {
00473 if ((c = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00474 error = errno;
00475 goto cleanup;
00476 }
00477 }
00478 if ((perm1 = strdup(perm1)) == NULL || apol_vector_append(c->removed_perms, perm1) < 0) {
00479 error = errno;
00480 free(perm1);
00481 ERR(diff, "%s", strerror(error));
00482 goto cleanup;
00483 }
00484 }
00485 for (; j < apol_vector_get_size(v2); j++) {
00486 perm2 = (char *)apol_vector_get_element(v2, j);
00487 if (c == NULL) {
00488 if ((c = make_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00489 error = errno;
00490 goto cleanup;
00491 }
00492 }
00493 if ((perm2 = strdup(perm2)) == NULL || apol_vector_append(c->added_perms, perm2) < 0) {
00494 error = errno;
00495 free(perm2);
00496 ERR(diff, "%s", strerror(error));
00497 goto cleanup;
00498 }
00499 }
00500 if (c != NULL) {
00501 apol_vector_sort(c->removed_perms, apol_str_strcmp, NULL);
00502 apol_vector_sort(c->added_perms, apol_str_strcmp, NULL);
00503 if (apol_vector_append(diff->class_diffs->diffs, c) < 0) {
00504 error = errno;
00505 ERR(diff, "%s", strerror(error));
00506 goto cleanup;
00507 }
00508 diff->class_diffs->num_modified++;
00509 }
00510 retval = 0;
00511 cleanup:
00512 apol_vector_destroy(&v1);
00513 apol_vector_destroy(&v2);
00514 if (retval != 0) {
00515 class_free(c);
00516 }
00517 errno = error;
00518 return retval;
00519 }
00520
00521
00522
00523 struct poldiff_common_summary
00524 {
00525 size_t num_added;
00526 size_t num_removed;
00527 size_t num_modified;
00528 apol_vector_t *diffs;
00529 };
00530
00531 struct poldiff_common
00532 {
00533 char *name;
00534 poldiff_form_e form;
00535 apol_vector_t *added_perms;
00536 apol_vector_t *removed_perms;
00537 };
00538
00539 void poldiff_common_get_stats(const poldiff_t * diff, size_t stats[5])
00540 {
00541 if (diff == NULL || stats == NULL) {
00542 ERR(diff, "%s", strerror(EINVAL));
00543 errno = EINVAL;
00544 return;
00545 }
00546 stats[0] = diff->common_diffs->num_added;
00547 stats[1] = diff->common_diffs->num_removed;
00548 stats[2] = diff->common_diffs->num_modified;
00549 stats[3] = 0;
00550 stats[4] = 0;
00551 }
00552
00553 char *poldiff_common_to_string(const poldiff_t * diff, const void *cls)
00554 {
00555 poldiff_common_t *c = (poldiff_common_t *) cls;
00556 size_t num_added, num_removed, len = 0, i;
00557 char *s = NULL, *perm;
00558 if (diff == NULL || cls == NULL) {
00559 ERR(diff, "%s", strerror(EINVAL));
00560 errno = EINVAL;
00561 return NULL;
00562 }
00563 num_added = apol_vector_get_size(c->added_perms);
00564 num_removed = apol_vector_get_size(c->removed_perms);
00565 switch (c->form) {
00566 case POLDIFF_FORM_ADDED:
00567 {
00568 if (apol_str_appendf(&s, &len, "+ %s", c->name) < 0) {
00569 s = NULL;
00570 break;
00571 }
00572 return s;
00573 }
00574 case POLDIFF_FORM_REMOVED:
00575 {
00576 if (apol_str_appendf(&s, &len, "- %s", c->name) < 0) {
00577 s = NULL;
00578 break;
00579 }
00580 return s;
00581 }
00582 case POLDIFF_FORM_MODIFIED:
00583 {
00584 if (apol_str_appendf(&s, &len, "* %s (", c->name) < 0) {
00585 s = NULL;
00586 break;
00587 }
00588 if (num_added > 0) {
00589 if (apol_str_appendf(&s, &len, "%zd Added Permission%s", num_added, (num_added == 1 ? "" : "s")) < 0) {
00590 break;
00591 }
00592 }
00593 if (num_removed > 0) {
00594 if (apol_str_appendf
00595 (&s, &len, "%s%zd Removed Permission%s", (num_added > 0 ? ", " : ""), num_removed,
00596 (num_removed == 1 ? "" : "s")) < 0) {
00597 break;
00598 }
00599 }
00600 if (apol_str_append(&s, &len, ")\n") < 0) {
00601 break;
00602 }
00603 for (i = 0; i < apol_vector_get_size(c->added_perms); i++) {
00604 perm = (char *)apol_vector_get_element(c->added_perms, i);
00605 if (apol_str_appendf(&s, &len, "\t+ %s\n", perm) < 0) {
00606 goto err;
00607 }
00608 }
00609 for (i = 0; i < apol_vector_get_size(c->removed_perms); i++) {
00610 perm = (char *)apol_vector_get_element(c->removed_perms, i);
00611 if (apol_str_appendf(&s, &len, "\t- %s\n", perm) < 0) {
00612 goto err;
00613 }
00614 }
00615 return s;
00616 }
00617 default:
00618 {
00619 ERR(diff, "%s", strerror(ENOTSUP));
00620 errno = ENOTSUP;
00621 return NULL;
00622 }
00623 }
00624 err:
00625
00626 free(s);
00627 ERR(diff, "%s", strerror(ENOMEM));
00628 errno = ENOMEM;
00629 return NULL;
00630 }
00631
00632 const apol_vector_t *poldiff_get_common_vector(const poldiff_t * diff)
00633 {
00634 if (diff == NULL) {
00635 errno = EINVAL;
00636 return NULL;
00637 }
00638 return diff->common_diffs->diffs;
00639 }
00640
00641 const char *poldiff_common_get_name(const poldiff_common_t * cls)
00642 {
00643 if (cls == NULL) {
00644 errno = EINVAL;
00645 return NULL;
00646 }
00647 return cls->name;
00648 }
00649
00650 poldiff_form_e poldiff_common_get_form(const void *cls)
00651 {
00652 if (cls == NULL) {
00653 errno = EINVAL;
00654 return 0;
00655 }
00656 return ((const poldiff_common_t *)cls)->form;
00657 }
00658
00659 const apol_vector_t *poldiff_common_get_added_perms(const poldiff_common_t * cls)
00660 {
00661 if (cls == NULL) {
00662 errno = EINVAL;
00663 return NULL;
00664 }
00665 return cls->added_perms;
00666 }
00667
00668 const apol_vector_t *poldiff_common_get_removed_perms(const poldiff_common_t * cls)
00669 {
00670 if (cls == NULL) {
00671 errno = EINVAL;
00672 return NULL;
00673 }
00674 return cls->removed_perms;
00675 }
00676
00677
00678
00679 static void common_free(void *elem)
00680 {
00681 if (elem != NULL) {
00682 poldiff_common_t *c = (poldiff_common_t *) elem;
00683 free(c->name);
00684 apol_vector_destroy(&c->added_perms);
00685 apol_vector_destroy(&c->removed_perms);
00686 free(c);
00687 }
00688 }
00689
00690 poldiff_common_summary_t *common_create(void)
00691 {
00692 poldiff_common_summary_t *cs = calloc(1, sizeof(*cs));
00693 if (cs == NULL) {
00694 return NULL;
00695 }
00696 if ((cs->diffs = apol_vector_create(common_free)) == NULL) {
00697 common_destroy(&cs);
00698 return NULL;
00699 }
00700 return cs;
00701 }
00702
00703 void common_destroy(poldiff_common_summary_t ** cs)
00704 {
00705 if (cs != NULL && *cs != NULL) {
00706 apol_vector_destroy(&(*cs)->diffs);
00707 free(*cs);
00708 *cs = NULL;
00709 }
00710 }
00711
00712 int common_reset(poldiff_t * diff)
00713 {
00714 int error = 0;
00715
00716 if (diff == NULL) {
00717 ERR(diff, "%s", strerror(EINVAL));
00718 errno = EINVAL;
00719 return -1;
00720 }
00721
00722 common_destroy(&diff->common_diffs);
00723 diff->common_diffs = common_create();
00724 if (diff->common_diffs == NULL) {
00725 error = errno;
00726 ERR(diff, "%s", strerror(error));
00727 errno = error;
00728 return -1;
00729 }
00730
00731 return 0;
00732 }
00733
00734
00735
00736
00737 static int common_name_comp(const void *x, const void *y, void *arg)
00738 {
00739 const qpol_common_t *c1 = x;
00740 const qpol_common_t *c2 = y;
00741 apol_policy_t *p = (apol_policy_t *) arg;
00742 qpol_policy_t *q = apol_policy_get_qpol(p);
00743 const char *name1, *name2;
00744 if (qpol_common_get_name(q, c1, &name1) < 0 || qpol_common_get_name(q, c2, &name2) < 0) {
00745 return 0;
00746 }
00747 return strcmp(name1, name2);
00748 }
00749
00750 apol_vector_t *common_get_items(poldiff_t * diff, const apol_policy_t * policy)
00751 {
00752 qpol_iterator_t *iter = NULL;
00753 apol_vector_t *v = NULL;
00754 qpol_policy_t *q = apol_policy_get_qpol(policy);
00755 int error = 0;
00756 if (qpol_policy_get_common_iter(q, &iter) < 0) {
00757 return NULL;
00758 }
00759 v = apol_vector_create_from_iter(iter, NULL);
00760 if (v == NULL) {
00761 error = errno;
00762 ERR(diff, "%s", strerror(error));
00763 qpol_iterator_destroy(&iter);
00764 errno = error;
00765 return NULL;
00766 }
00767 qpol_iterator_destroy(&iter);
00768 apol_vector_sort(v, common_name_comp, (void *)policy);
00769 return v;
00770 }
00771
00772 int common_comp(const void *x, const void *y, const poldiff_t * diff)
00773 {
00774 const qpol_common_t *c1 = x;
00775 const qpol_common_t *c2 = y;
00776 const char *name1, *name2;
00777 if (qpol_common_get_name(diff->orig_qpol, c1, &name1) < 0 || qpol_common_get_name(diff->mod_qpol, c2, &name2) < 0) {
00778 return 0;
00779 }
00780 return strcmp(name1, name2);
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 static poldiff_common_t *make_common_diff(const poldiff_t * diff, poldiff_form_e form, const char *name)
00795 {
00796 poldiff_common_t *pc;
00797 int error;
00798 if ((pc = calloc(1, sizeof(*pc))) == NULL ||
00799 (pc->name = strdup(name)) == NULL ||
00800 (pc->added_perms = apol_vector_create_with_capacity(1, free)) == NULL ||
00801 (pc->removed_perms = apol_vector_create_with_capacity(1, free)) == NULL) {
00802 error = errno;
00803 common_free(pc);
00804 ERR(diff, "%s", strerror(error));
00805 errno = error;
00806 return NULL;
00807 }
00808 pc->form = form;
00809 return pc;
00810 }
00811
00812 int common_new_diff(poldiff_t * diff, poldiff_form_e form, const void *item)
00813 {
00814 const qpol_common_t *c = item;
00815 const char *name = NULL;
00816 poldiff_common_t *pc;
00817 int error;
00818 if ((form == POLDIFF_FORM_ADDED &&
00819 qpol_common_get_name(diff->mod_qpol, c, &name) < 0) ||
00820 ((form == POLDIFF_FORM_REMOVED || form == POLDIFF_FORM_MODIFIED) &&
00821 qpol_common_get_name(diff->orig_qpol, c, &name) < 0)) {
00822 return -1;
00823 }
00824 pc = make_common_diff(diff, form, name);
00825 if (pc == NULL) {
00826 return -1;
00827 }
00828 if (apol_vector_append(diff->common_diffs->diffs, pc) < 0) {
00829 error = errno;
00830 ERR(diff, "%s", strerror(error));
00831 common_free(pc);
00832 errno = error;
00833 return -1;
00834 }
00835 if (form == POLDIFF_FORM_ADDED) {
00836 diff->common_diffs->num_added++;
00837 } else {
00838 diff->common_diffs->num_removed++;
00839 }
00840 return 0;
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 static apol_vector_t *common_get_perms(const poldiff_t * diff, const apol_policy_t * p, const qpol_common_t * common)
00856 {
00857 qpol_iterator_t *perm_iter = NULL;
00858 char *perm;
00859 apol_vector_t *v = NULL;
00860 qpol_policy_t *q = apol_policy_get_qpol(p);
00861 int retval = -1;
00862
00863 if ((v = apol_vector_create(NULL)) == NULL) {
00864 ERR(diff, "%s", strerror(errno));
00865 goto cleanup;
00866 }
00867 if (qpol_common_get_perm_iter(q, common, &perm_iter) < 0) {
00868 goto cleanup;
00869 }
00870 for (; !qpol_iterator_end(perm_iter); qpol_iterator_next(perm_iter)) {
00871 if (qpol_iterator_get_item(perm_iter, (void **)&perm) < 0) {
00872 goto cleanup;
00873 }
00874 if (apol_vector_append(v, perm) < 0) {
00875 ERR(diff, "%s", strerror(errno));
00876 goto cleanup;
00877 }
00878 }
00879
00880 retval = 0;
00881 cleanup:
00882 qpol_iterator_destroy(&perm_iter);
00883 if (retval < 0) {
00884 apol_vector_destroy(&v);
00885 return NULL;
00886 }
00887 return v;
00888 }
00889
00890 int common_deep_diff(poldiff_t * diff, const void *x, const void *y)
00891 {
00892 const qpol_common_t *c1 = x;
00893 const qpol_common_t *c2 = y;
00894 apol_vector_t *v1 = NULL, *v2 = NULL;
00895 char *perm1 = NULL, *perm2 = NULL;
00896 const char *name;
00897 poldiff_common_t *c = NULL;
00898 size_t i, j;
00899 int retval = -1, error = 0, compval;
00900
00901 if (qpol_common_get_name(diff->orig_qpol, c1, &name) < 0 ||
00902 (v1 = common_get_perms(diff, diff->orig_pol, c1)) == NULL || (v2 = common_get_perms(diff, diff->mod_pol, c2)) == NULL) {
00903 error = errno;
00904 goto cleanup;
00905 }
00906 apol_vector_sort(v1, apol_str_strcmp, NULL);
00907 apol_vector_sort(v2, apol_str_strcmp, NULL);
00908 for (i = j = 0; i < apol_vector_get_size(v1);) {
00909 if (j >= apol_vector_get_size(v2))
00910 break;
00911 perm1 = (char *)apol_vector_get_element(v1, i);
00912 perm2 = (char *)apol_vector_get_element(v2, j);
00913 compval = strcmp(perm1, perm2);
00914 if (compval != 0 && c == NULL) {
00915 if ((c = make_common_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00916 error = errno;
00917 goto cleanup;
00918 }
00919 }
00920 if (compval < 0) {
00921 if ((perm1 = strdup(perm1)) == NULL || apol_vector_append(c->removed_perms, perm1) < 0) {
00922 error = errno;
00923 free(perm1);
00924 ERR(diff, "%s", strerror(error));
00925 goto cleanup;
00926 }
00927 i++;
00928 } else if (compval > 0) {
00929 if ((perm2 = strdup(perm2)) == NULL || apol_vector_append(c->added_perms, perm2) < 0) {
00930 error = errno;
00931 free(perm2);
00932 ERR(diff, "%s", strerror(error));
00933 goto cleanup;
00934 }
00935 j++;
00936 } else {
00937 i++;
00938 j++;
00939 }
00940 }
00941 for (; i < apol_vector_get_size(v1); i++) {
00942 perm1 = (char *)apol_vector_get_element(v1, i);
00943 if (c == NULL) {
00944 if ((c = make_common_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00945 error = errno;
00946 goto cleanup;
00947 }
00948 }
00949 if ((perm1 = strdup(perm1)) == NULL || apol_vector_append(c->removed_perms, perm1) < 0) {
00950 error = errno;
00951 free(perm1);
00952 ERR(diff, "%s", strerror(error));
00953 goto cleanup;
00954 }
00955 }
00956 for (; j < apol_vector_get_size(v2); j++) {
00957 perm2 = (char *)apol_vector_get_element(v2, j);
00958 if (c == NULL) {
00959 if ((c = make_common_diff(diff, POLDIFF_FORM_MODIFIED, name)) == NULL) {
00960 error = errno;
00961 goto cleanup;
00962 }
00963 }
00964 if ((perm2 = strdup(perm2)) == NULL || apol_vector_append(c->added_perms, perm2) < 0) {
00965 error = errno;
00966 free(perm2);
00967 ERR(diff, "%s", strerror(error));
00968 goto cleanup;
00969 }
00970 }
00971 if (c != NULL) {
00972 apol_vector_sort(c->removed_perms, apol_str_strcmp, NULL);
00973 apol_vector_sort(c->added_perms, apol_str_strcmp, NULL);
00974 if (apol_vector_append(diff->common_diffs->diffs, c) < 0) {
00975 error = errno;
00976 ERR(diff, "%s", strerror(error));
00977 goto cleanup;
00978 }
00979 diff->common_diffs->num_modified++;
00980 }
00981 retval = 0;
00982 cleanup:
00983 apol_vector_destroy(&v1);
00984 apol_vector_destroy(&v2);
00985 if (retval != 0) {
00986 common_free(c);
00987 }
00988 errno = error;
00989 return retval;
00990 }