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 #include <config.h>
00026
00027 #include "poldiff_internal.h"
00028 #include <poldiff/component_record.h>
00029
00030 #include <apol/util.h>
00031 #include <qpol/policy_extend.h>
00032 #include <errno.h>
00033 #include <stdio.h>
00034 #include <string.h>
00035
00036
00037
00038
00039
00040
00041 struct poldiff_component_record
00042 {
00043 const char *item_name;
00044 uint32_t flag_bit;
00045 poldiff_get_item_stats_fn_t get_stats;
00046 poldiff_get_result_items_fn_t get_results;
00047 poldiff_item_get_form_fn_t get_form;
00048 poldiff_item_to_string_fn_t to_string;
00049 poldiff_reset_fn_t reset;
00050 poldiff_get_items_fn_t get_items;
00051 poldiff_item_comp_fn_t comp;
00052 poldiff_new_diff_fn_t new_diff;
00053 poldiff_deep_diff_fn_t deep_diff;
00054 };
00055
00056 static const poldiff_component_record_t component_records[] = {
00057 {
00058 "attribute",
00059 POLDIFF_DIFF_ATTRIBS,
00060 poldiff_attrib_get_stats,
00061 poldiff_get_attrib_vector,
00062 poldiff_attrib_get_form,
00063 poldiff_attrib_to_string,
00064 attrib_reset,
00065 attrib_get_items,
00066 attrib_comp,
00067 attrib_new_diff,
00068 attrib_deep_diff,
00069 },
00070 {
00071 "Allow Rules",
00072 POLDIFF_DIFF_AVALLOW,
00073 poldiff_avrule_get_stats_allow,
00074 poldiff_get_avrule_vector_allow,
00075 poldiff_avrule_get_form,
00076 poldiff_avrule_to_string,
00077 avrule_reset_allow,
00078 avrule_get_items_allow,
00079 avrule_comp,
00080 avrule_new_diff_allow,
00081 avrule_deep_diff_allow,
00082 },
00083 {
00084 "Audit Allow Rules",
00085 POLDIFF_DIFF_AVAUDITALLOW,
00086 poldiff_avrule_get_stats_auditallow,
00087 poldiff_get_avrule_vector_auditallow,
00088 poldiff_avrule_get_form,
00089 poldiff_avrule_to_string,
00090 avrule_reset_auditallow,
00091 avrule_get_items_auditallow,
00092 avrule_comp,
00093 avrule_new_diff_auditallow,
00094 avrule_deep_diff_auditallow,
00095 },
00096 {
00097 "Don't Audit Rules",
00098 POLDIFF_DIFF_AVDONTAUDIT,
00099 poldiff_avrule_get_stats_dontaudit,
00100 poldiff_get_avrule_vector_dontaudit,
00101 poldiff_avrule_get_form,
00102 poldiff_avrule_to_string,
00103 avrule_reset_dontaudit,
00104 avrule_get_items_dontaudit,
00105 avrule_comp,
00106 avrule_new_diff_dontaudit,
00107 avrule_deep_diff_dontaudit,
00108 },
00109 {
00110 "Never Allow Rules",
00111 POLDIFF_DIFF_AVNEVERALLOW,
00112 poldiff_avrule_get_stats_neverallow,
00113 poldiff_get_avrule_vector_neverallow,
00114 poldiff_avrule_get_form,
00115 poldiff_avrule_to_string,
00116 avrule_reset_neverallow,
00117 avrule_get_items_neverallow,
00118 avrule_comp,
00119 avrule_new_diff_neverallow,
00120 avrule_deep_diff_neverallow,
00121 },
00122 {
00123 "bool",
00124 POLDIFF_DIFF_BOOLS,
00125 poldiff_bool_get_stats,
00126 poldiff_get_bool_vector,
00127 poldiff_bool_get_form,
00128 poldiff_bool_to_string,
00129 bool_reset,
00130 bool_get_items,
00131 bool_comp,
00132 bool_new_diff,
00133 bool_deep_diff,
00134 },
00135 {
00136 "category",
00137 POLDIFF_DIFF_CATS,
00138 poldiff_cat_get_stats,
00139 poldiff_get_cat_vector,
00140 poldiff_cat_get_form,
00141 poldiff_cat_to_string,
00142 cat_reset,
00143 cat_get_items,
00144 cat_comp,
00145 cat_new_diff,
00146 cat_deep_diff,
00147 },
00148 {
00149 "class",
00150 POLDIFF_DIFF_CLASSES,
00151 poldiff_class_get_stats,
00152 poldiff_get_class_vector,
00153 poldiff_class_get_form,
00154 poldiff_class_to_string,
00155 class_reset,
00156 class_get_items,
00157 class_comp,
00158 class_new_diff,
00159 class_deep_diff,
00160 },
00161 {
00162 "common",
00163 POLDIFF_DIFF_COMMONS,
00164 poldiff_common_get_stats,
00165 poldiff_get_common_vector,
00166 poldiff_common_get_form,
00167 poldiff_common_to_string,
00168 common_reset,
00169 common_get_items,
00170 common_comp,
00171 common_new_diff,
00172 common_deep_diff,
00173 },
00174 {
00175 "level",
00176 POLDIFF_DIFF_LEVELS,
00177 poldiff_level_get_stats,
00178 poldiff_get_level_vector,
00179 poldiff_level_get_form,
00180 poldiff_level_to_string,
00181 level_reset,
00182 level_get_items,
00183 level_comp,
00184 level_new_diff,
00185 level_deep_diff,
00186 },
00187 {
00188 "range transition",
00189 POLDIFF_DIFF_RANGE_TRANS,
00190 poldiff_range_trans_get_stats,
00191 poldiff_get_range_trans_vector,
00192 poldiff_range_trans_get_form,
00193 poldiff_range_trans_to_string,
00194 range_trans_reset,
00195 range_trans_get_items,
00196 range_trans_comp,
00197 range_trans_new_diff,
00198 range_trans_deep_diff,
00199 },
00200 {
00201 "role",
00202 POLDIFF_DIFF_ROLES,
00203 poldiff_role_get_stats,
00204 poldiff_get_role_vector,
00205 poldiff_role_get_form,
00206 poldiff_role_to_string,
00207 role_reset,
00208 role_get_items,
00209 role_comp,
00210 role_new_diff,
00211 role_deep_diff,
00212 },
00213 {
00214 "role_allow",
00215 POLDIFF_DIFF_ROLE_ALLOWS,
00216 poldiff_role_allow_get_stats,
00217 poldiff_get_role_allow_vector,
00218 poldiff_role_allow_get_form,
00219 poldiff_role_allow_to_string,
00220 role_allow_reset,
00221 role_allow_get_items,
00222 role_allow_comp,
00223 role_allow_new_diff,
00224 role_allow_deep_diff,
00225 },
00226 {
00227 "role_transition",
00228 POLDIFF_DIFF_ROLE_TRANS,
00229 poldiff_role_trans_get_stats,
00230 poldiff_get_role_trans_vector,
00231 poldiff_role_trans_get_form,
00232 poldiff_role_trans_to_string,
00233 role_trans_reset,
00234 role_trans_get_items,
00235 role_trans_comp,
00236 role_trans_new_diff,
00237 role_trans_deep_diff,
00238 },
00239 {
00240 "Type Change rules",
00241 POLDIFF_DIFF_TECHANGE,
00242 poldiff_terule_get_stats_change,
00243 poldiff_get_terule_vector_change,
00244 poldiff_terule_get_form,
00245 poldiff_terule_to_string,
00246 terule_reset_change,
00247 terule_get_items_change,
00248 terule_comp,
00249 terule_new_diff_change,
00250 terule_deep_diff_change,
00251 },
00252 {
00253 "Type Member Rules",
00254 POLDIFF_DIFF_TEMEMBER,
00255 poldiff_terule_get_stats_member,
00256 poldiff_get_terule_vector_member,
00257 poldiff_terule_get_form,
00258 poldiff_terule_to_string,
00259 terule_reset_member,
00260 terule_get_items_member,
00261 terule_comp,
00262 terule_new_diff_member,
00263 terule_deep_diff_member,
00264 },
00265 {
00266 "Type Transition Rules",
00267 POLDIFF_DIFF_TETRANS,
00268 poldiff_terule_get_stats_trans,
00269 poldiff_get_terule_vector_trans,
00270 poldiff_terule_get_form,
00271 poldiff_terule_to_string,
00272 terule_reset_trans,
00273 terule_get_items_trans,
00274 terule_comp,
00275 terule_new_diff_trans,
00276 terule_deep_diff_trans,
00277 },
00278 {
00279 "type",
00280 POLDIFF_DIFF_TYPES,
00281 poldiff_type_get_stats,
00282 poldiff_get_type_vector,
00283 poldiff_type_get_form,
00284 poldiff_type_to_string,
00285 type_reset,
00286 type_get_items,
00287 type_comp,
00288 type_new_diff,
00289 type_deep_diff,
00290 },
00291 {
00292 "user",
00293 POLDIFF_DIFF_USERS,
00294 poldiff_user_get_stats,
00295 poldiff_get_user_vector,
00296 poldiff_user_get_form,
00297 poldiff_user_to_string,
00298 user_reset,
00299 user_get_items,
00300 user_comp,
00301 user_new_diff,
00302 user_deep_diff,
00303 },
00304 };
00305
00306 const poldiff_component_record_t *poldiff_get_component_record(uint32_t which)
00307 {
00308 size_t i = 0;
00309 size_t num_items;
00310
00311 num_items = sizeof(component_records) / sizeof(poldiff_component_record_t);
00312 for (i = 0; i < num_items; i++) {
00313 if (component_records[i].flag_bit == which)
00314 return &component_records[i];
00315 }
00316 return NULL;
00317 }
00318
00319 poldiff_t *poldiff_create(apol_policy_t * orig_policy, apol_policy_t * mod_policy, poldiff_handle_fn_t fn, void *callback_arg)
00320 {
00321 poldiff_t *diff = NULL;
00322 int error;
00323
00324 if (!orig_policy || !mod_policy) {
00325 ERR(NULL, "%s", strerror(EINVAL));
00326 errno = EINVAL;
00327 return NULL;
00328 }
00329
00330 if (!(diff = calloc(1, sizeof(poldiff_t)))) {
00331 ERR(NULL, "%s", strerror(ENOMEM));
00332 errno = ENOMEM;
00333 return NULL;
00334 }
00335 diff->orig_pol = orig_policy;
00336 diff->mod_pol = mod_policy;
00337 diff->orig_qpol = apol_policy_get_qpol(diff->orig_pol);
00338 diff->mod_qpol = apol_policy_get_qpol(diff->mod_pol);
00339 diff->fn = fn;
00340 diff->handle_arg = callback_arg;
00341 if ((diff->type_map = type_map_create()) == NULL) {
00342 ERR(diff, "%s", strerror(ENOMEM));
00343 poldiff_destroy(&diff);
00344 errno = ENOMEM;
00345 return NULL;
00346 }
00347 if (type_map_infer(diff) < 0) {
00348 error = errno;
00349 poldiff_destroy(&diff);
00350 errno = error;
00351 return NULL;
00352 }
00353
00354 if ((diff->attrib_diffs = attrib_summary_create()) == NULL ||
00355 (diff->avrule_diffs[AVRULE_OFFSET_ALLOW] = avrule_create()) == NULL ||
00356 (diff->avrule_diffs[AVRULE_OFFSET_AUDITALLOW] = avrule_create()) == NULL ||
00357 (diff->avrule_diffs[AVRULE_OFFSET_DONTAUDIT] = avrule_create()) == NULL ||
00358 (diff->avrule_diffs[AVRULE_OFFSET_NEVERALLOW] = avrule_create()) == NULL ||
00359 (diff->bool_diffs = bool_create()) == NULL ||
00360 (diff->cat_diffs = cat_create()) == NULL ||
00361 (diff->class_diffs = class_create()) == NULL ||
00362 (diff->common_diffs = common_create()) == NULL ||
00363 (diff->level_diffs = level_create()) == NULL ||
00364 (diff->range_trans_diffs = range_trans_create()) == NULL ||
00365 (diff->role_diffs = role_create()) == NULL ||
00366 (diff->role_allow_diffs = role_allow_create()) == NULL ||
00367 (diff->role_trans_diffs = role_trans_create()) == NULL ||
00368 (diff->terule_diffs[TERULE_OFFSET_CHANGE] = terule_create()) == NULL ||
00369 (diff->terule_diffs[TERULE_OFFSET_MEMBER] = terule_create()) == NULL ||
00370 (diff->terule_diffs[TERULE_OFFSET_TRANS] = terule_create()) == NULL ||
00371 (diff->type_diffs = type_summary_create()) == NULL || (diff->user_diffs = user_create()) == NULL) {
00372 ERR(diff, "%s", strerror(ENOMEM));
00373 poldiff_destroy(&diff);
00374 errno = ENOMEM;
00375 return NULL;
00376 }
00377
00378 diff->policy_opts = QPOL_POLICY_OPTION_NO_RULES | QPOL_POLICY_OPTION_NO_NEVERALLOWS;
00379 return diff;
00380 }
00381
00382 void poldiff_destroy(poldiff_t ** diff)
00383 {
00384 if (!diff || !(*diff))
00385 return;
00386 apol_policy_destroy(&(*diff)->orig_pol);
00387 apol_policy_destroy(&(*diff)->mod_pol);
00388 apol_bst_destroy(&(*diff)->class_bst);
00389 apol_bst_destroy(&(*diff)->perm_bst);
00390 apol_bst_destroy(&(*diff)->bool_bst);
00391
00392 type_map_destroy(&(*diff)->type_map);
00393 attrib_summary_destroy(&(*diff)->attrib_diffs);
00394 avrule_destroy(&(*diff)->avrule_diffs[AVRULE_OFFSET_ALLOW]);
00395 avrule_destroy(&(*diff)->avrule_diffs[AVRULE_OFFSET_AUDITALLOW]);
00396 avrule_destroy(&(*diff)->avrule_diffs[AVRULE_OFFSET_DONTAUDIT]);
00397 avrule_destroy(&(*diff)->avrule_diffs[AVRULE_OFFSET_NEVERALLOW]);
00398 bool_destroy(&(*diff)->bool_diffs);
00399 cat_destroy(&(*diff)->cat_diffs);
00400 class_destroy(&(*diff)->class_diffs);
00401 common_destroy(&(*diff)->common_diffs);
00402 level_destroy(&(*diff)->level_diffs);
00403 range_trans_destroy(&(*diff)->range_trans_diffs);
00404 role_destroy(&(*diff)->role_diffs);
00405 role_allow_destroy(&(*diff)->role_allow_diffs);
00406 role_trans_destroy(&(*diff)->role_trans_diffs);
00407 user_destroy(&(*diff)->user_diffs);
00408 terule_destroy(&(*diff)->terule_diffs[TERULE_OFFSET_CHANGE]);
00409 terule_destroy(&(*diff)->terule_diffs[TERULE_OFFSET_MEMBER]);
00410 terule_destroy(&(*diff)->terule_diffs[TERULE_OFFSET_TRANS]);
00411 type_summary_destroy(&(*diff)->type_diffs);
00412 free(*diff);
00413 *diff = NULL;
00414 }
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 static int poldiff_do_item_diff(poldiff_t * diff, const poldiff_component_record_t * component_record)
00432 {
00433 apol_vector_t *p1_v = NULL, *p2_v = NULL;
00434 int error = 0, retv;
00435 size_t x = 0, y = 0;
00436 void *item_x = NULL, *item_y = NULL;
00437
00438 if (!diff || !component_record) {
00439 ERR(diff, "%s", strerror(EINVAL));
00440 errno = EINVAL;
00441 return -1;
00442 }
00443 diff->diff_status &= (~component_record->flag_bit);
00444
00445 INFO(diff, "Getting %s items from original policy.", component_record->item_name);
00446 p1_v = component_record->get_items(diff, diff->orig_pol);
00447 if (!p1_v) {
00448 error = errno;
00449 goto err;
00450 }
00451
00452 INFO(diff, "Getting %s items from modified policy.", component_record->item_name);
00453 p2_v = component_record->get_items(diff, diff->mod_pol);
00454 if (!p2_v) {
00455 error = errno;
00456 goto err;
00457 }
00458
00459 INFO(diff, "Finding differences in %s.", component_record->item_name);
00460 for (x = 0, y = 0; x < apol_vector_get_size(p1_v);) {
00461 if (y >= apol_vector_get_size(p2_v))
00462 break;
00463 item_x = apol_vector_get_element(p1_v, x);
00464 item_y = apol_vector_get_element(p2_v, y);
00465 retv = component_record->comp(item_x, item_y, diff);
00466 if (retv < 0) {
00467 if (component_record->new_diff(diff, POLDIFF_FORM_REMOVED, item_x)) {
00468 error = errno;
00469 goto err;
00470 }
00471 x++;
00472 } else if (retv > 0) {
00473 if (component_record->new_diff(diff, POLDIFF_FORM_ADDED, item_y)) {
00474 error = errno;
00475 goto err;
00476 }
00477 y++;
00478 } else {
00479 if (component_record->deep_diff(diff, item_x, item_y)) {
00480 error = errno;
00481 goto err;
00482 }
00483 x++;
00484 y++;
00485 }
00486 }
00487 for (; x < apol_vector_get_size(p1_v); x++) {
00488 item_x = apol_vector_get_element(p1_v, x);
00489 if (component_record->new_diff(diff, POLDIFF_FORM_REMOVED, item_x)) {
00490 error = errno;
00491 goto err;
00492 }
00493 }
00494 for (; y < apol_vector_get_size(p2_v); y++) {
00495 item_y = apol_vector_get_element(p2_v, y);
00496 if (component_record->new_diff(diff, POLDIFF_FORM_ADDED, item_y)) {
00497 error = errno;
00498 goto err;
00499 }
00500 }
00501
00502 apol_vector_destroy(&p1_v);
00503 apol_vector_destroy(&p2_v);
00504 diff->diff_status |= component_record->flag_bit;
00505 return 0;
00506 err:
00507 apol_vector_destroy(&p1_v);
00508 apol_vector_destroy(&p2_v);
00509 errno = error;
00510 return -1;
00511 }
00512
00513 int poldiff_run(poldiff_t * diff, uint32_t flags)
00514 {
00515 size_t i, num_items;
00516
00517 if (!flags)
00518 return 0;
00519
00520 if (!diff) {
00521 ERR(diff, "%s", strerror(EINVAL));
00522 errno = EINVAL;
00523 return -1;
00524 }
00525
00526 int policy_opts = diff->policy_opts;
00527 if (flags & (POLDIFF_DIFF_AVRULES | POLDIFF_DIFF_TERULES)) {
00528 policy_opts &= ~(QPOL_POLICY_OPTION_NO_RULES);
00529 }
00530 if (flags & POLDIFF_DIFF_AVNEVERALLOW) {
00531 policy_opts &= ~(QPOL_POLICY_OPTION_NO_NEVERALLOWS);
00532 }
00533 if (policy_opts != diff->policy_opts) {
00534 INFO(diff, "%s", "Loading rules from original policy.");
00535 if (qpol_policy_rebuild(diff->orig_qpol, policy_opts)) {
00536 return -1;
00537 }
00538 INFO(diff, "%s", "Loading rules from modified policy.");
00539 if (qpol_policy_rebuild(diff->mod_qpol, policy_opts)) {
00540 return -1;
00541 }
00542
00543 diff->remapped = 1;
00544 diff->policy_opts = policy_opts;
00545 }
00546
00547 num_items = sizeof(component_records) / sizeof(poldiff_component_record_t);
00548 if (diff->remapped) {
00549 for (i = 0; i < num_items; i++) {
00550 if (component_records[i].flag_bit & POLDIFF_DIFF_REMAPPED) {
00551 INFO(diff, "Resetting %s diff.", component_records[i].item_name);
00552 if (component_records[i].reset(diff))
00553 return -1;
00554 }
00555 }
00556 diff->diff_status &= ~(POLDIFF_DIFF_REMAPPED);
00557 diff->remapped = 0;
00558 }
00559
00560 INFO(diff, "%s", "Building type map.");
00561 if (type_map_build(diff)) {
00562 return -1;
00563 }
00564
00565 diff->line_numbers_enabled = 0;
00566 for (i = 0; i < num_items; i++) {
00567
00568 if ((flags & component_records[i].flag_bit) && !(component_records[i].flag_bit & diff->diff_status)) {
00569 INFO(diff, "Running %s diff.", component_records[i].item_name);
00570 if (poldiff_do_item_diff(diff, &(component_records[i]))) {
00571 return -1;
00572 }
00573 }
00574 }
00575
00576 return 0;
00577 }
00578
00579 int poldiff_is_run(const poldiff_t * diff, uint32_t flags)
00580 {
00581 if (!flags)
00582 return 1;
00583
00584 if (!diff) {
00585 ERR(diff, "%s", strerror(EINVAL));
00586 errno = EINVAL;
00587 return -1;
00588 }
00589 if ((diff->diff_status & flags) == flags) {
00590 return 1;
00591 }
00592 return 0;
00593 }
00594
00595 int poldiff_get_stats(const poldiff_t * diff, uint32_t flags, size_t stats[5])
00596 {
00597 size_t i, j, num_items, tmp_stats[5] = { 0, 0, 0, 0, 0 };
00598
00599 if (!diff || !flags) {
00600 ERR(diff, "%s", strerror(EINVAL));
00601 errno = EINVAL;
00602 return -1;
00603 }
00604
00605 stats[0] = stats[1] = stats[2] = stats[3] = stats[4] = 0;
00606
00607 num_items = sizeof(component_records) / sizeof(poldiff_component_record_t);
00608 for (i = 0; i < num_items; i++) {
00609 if (flags & component_records[i].flag_bit) {
00610 component_records[i].get_stats(diff, tmp_stats);
00611 for (j = 0; j < 5; j++)
00612 stats[j] += tmp_stats[j];
00613 }
00614 }
00615
00616 return 0;
00617 }
00618
00619 int poldiff_enable_line_numbers(poldiff_t * diff)
00620 {
00621 int retval;
00622 if (diff == NULL) {
00623 errno = EINVAL;
00624 return -1;
00625 }
00626 if (!diff->line_numbers_enabled) {
00627 if (qpol_policy_build_syn_rule_table(diff->orig_qpol))
00628 return -1;
00629 if (qpol_policy_build_syn_rule_table(diff->mod_qpol))
00630 return -1;
00631 if ((retval = avrule_enable_line_numbers(diff, AVRULE_OFFSET_ALLOW)) < 0) {
00632 return retval;
00633 }
00634 if ((retval = avrule_enable_line_numbers(diff, AVRULE_OFFSET_AUDITALLOW)) < 0) {
00635 return retval;
00636 }
00637 if ((retval = avrule_enable_line_numbers(diff, AVRULE_OFFSET_DONTAUDIT)) < 0) {
00638 return retval;
00639 }
00640 if ((retval = avrule_enable_line_numbers(diff, AVRULE_OFFSET_NEVERALLOW)) < 0) {
00641 return retval;
00642 }
00643 if ((retval = terule_enable_line_numbers(diff, TERULE_OFFSET_CHANGE)) < 0) {
00644 return retval;
00645 }
00646 if ((retval = terule_enable_line_numbers(diff, TERULE_OFFSET_MEMBER)) < 0) {
00647 return retval;
00648 }
00649 if ((retval = terule_enable_line_numbers(diff, TERULE_OFFSET_TRANS)) < 0) {
00650 return retval;
00651 }
00652 diff->line_numbers_enabled = 1;
00653 }
00654 return 0;
00655 }
00656
00657 int poldiff_build_bsts(poldiff_t * diff)
00658 {
00659 apol_vector_t *classes[2] = { NULL, NULL };
00660 apol_vector_t *perms[2] = { NULL, NULL };
00661 apol_vector_t *bools[2] = { NULL, NULL };
00662 size_t i, j;
00663 const qpol_class_t *cls;
00664 qpol_bool_t *qbool;
00665 const char *name;
00666 char *new_name;
00667 int retval = -1, error = 0;
00668 if (diff->class_bst != NULL) {
00669 return 0;
00670 }
00671 if ((diff->class_bst = apol_bst_create(apol_str_strcmp, free)) == NULL ||
00672 (diff->perm_bst = apol_bst_create(apol_str_strcmp, free)) == NULL ||
00673 (diff->bool_bst = apol_bst_create(apol_str_strcmp, free)) == NULL) {
00674 error = errno;
00675 ERR(diff, "%s", strerror(error));
00676 goto cleanup;
00677 }
00678 for (i = 0; i < 2; i++) {
00679 apol_policy_t *p = (i == 0 ? diff->orig_pol : diff->mod_pol);
00680 qpol_policy_t *q = apol_policy_get_qpol(p);
00681 if (apol_class_get_by_query(p, NULL, &classes[i]) < 0 ||
00682 apol_perm_get_by_query(p, NULL, &perms[i]) < 0 || apol_bool_get_by_query(p, NULL, &bools[i]) < 0) {
00683 error = errno;
00684 goto cleanup;
00685 }
00686 for (j = 0; j < apol_vector_get_size(classes[i]); j++) {
00687 cls = apol_vector_get_element(classes[i], j);
00688 if (qpol_class_get_name(q, cls, &name) < 0) {
00689 error = errno;
00690 goto cleanup;
00691 }
00692 if ((new_name = strdup(name)) == NULL ||
00693 apol_bst_insert_and_get(diff->class_bst, (void **)&new_name, NULL) < 0) {
00694 error = errno;
00695 ERR(diff, "%s", strerror(error));
00696 goto cleanup;
00697 }
00698 }
00699 for (j = 0; j < apol_vector_get_size(perms[i]); j++) {
00700 name = (char *)apol_vector_get_element(perms[i], j);
00701 if ((new_name = strdup(name)) == NULL ||
00702 apol_bst_insert_and_get(diff->perm_bst, (void **)&new_name, NULL) < 0) {
00703 error = errno;
00704 ERR(diff, "%s", strerror(error));
00705 goto cleanup;
00706 }
00707 }
00708 for (j = 0; j < apol_vector_get_size(bools[i]); j++) {
00709 qbool = (qpol_bool_t *) apol_vector_get_element(bools[i], j);
00710 if (qpol_bool_get_name(q, qbool, &name) < 0) {
00711 error = errno;
00712 goto cleanup;
00713 }
00714 if ((new_name = strdup(name)) == NULL ||
00715 apol_bst_insert_and_get(diff->bool_bst, (void **)&new_name, NULL) < 0) {
00716 error = errno;
00717 ERR(diff, "%s", strerror(error));
00718 goto cleanup;
00719 }
00720 }
00721 }
00722 retval = 0;
00723 cleanup:
00724 apol_vector_destroy(&classes[0]);
00725 apol_vector_destroy(&classes[1]);
00726 apol_vector_destroy(&perms[0]);
00727 apol_vector_destroy(&perms[1]);
00728 apol_vector_destroy(&bools[0]);
00729 apol_vector_destroy(&bools[1]);
00730 errno = error;
00731 return retval;
00732 }
00733
00734 static void poldiff_handle_default_callback(void *arg __attribute__ ((unused)),
00735 poldiff_t * p __attribute__ ((unused)), int level, const char *fmt, va_list va_args)
00736 {
00737 switch (level) {
00738 case POLDIFF_MSG_INFO:
00739 {
00740
00741 return;
00742 }
00743 case POLDIFF_MSG_WARN:
00744 {
00745 fprintf(stderr, "WARNING: ");
00746 break;
00747 }
00748 case POLDIFF_MSG_ERR:
00749 default:
00750 {
00751 fprintf(stderr, "ERROR: ");
00752 break;
00753 }
00754 }
00755 vfprintf(stderr, fmt, va_args);
00756 fprintf(stderr, "\n");
00757 }
00758
00759 void poldiff_handle_msg(const poldiff_t * p, int level, const char *fmt, ...)
00760 {
00761 va_list ap;
00762 va_start(ap, fmt);
00763 if (p == NULL || p->fn == NULL) {
00764 poldiff_handle_default_callback(NULL, NULL, level, fmt, ap);
00765 } else {
00766 p->fn(p->handle_arg, p, level, fmt, ap);
00767 }
00768 va_end(ap);
00769 }
00770
00771 poldiff_item_get_form_fn_t poldiff_component_record_get_form_fn(const poldiff_component_record_t * diff)
00772 {
00773 if (!diff) {
00774 errno = EINVAL;
00775 return NULL;
00776 }
00777 return diff->get_form;
00778 }
00779
00780 poldiff_item_to_string_fn_t poldiff_component_record_get_to_string_fn(const poldiff_component_record_t * diff)
00781 {
00782 if (!diff) {
00783 errno = EINVAL;
00784 return NULL;
00785 }
00786 return diff->to_string;
00787 }
00788
00789 poldiff_get_item_stats_fn_t poldiff_component_record_get_stats_fn(const poldiff_component_record_t * diff)
00790 {
00791 if (!diff) {
00792 errno = EINVAL;
00793 return NULL;
00794 }
00795 return diff->get_stats;
00796 }
00797
00798 poldiff_get_result_items_fn_t poldiff_component_record_get_results_fn(const poldiff_component_record_t * diff)
00799 {
00800 if (!diff) {
00801 errno = EINVAL;
00802 return NULL;
00803 }
00804 return diff->get_results;
00805 }
00806
00807 const char *poldiff_component_record_get_label(const poldiff_component_record_t * diff)
00808 {
00809 if (!diff) {
00810 errno = EINVAL;
00811 return NULL;
00812 }
00813 return diff->item_name;
00814 }