From 47be9ff57e72906660bb62a515222f482131e1fb Mon Sep 17 00:00:00 2001 From: Miroslav Grepl Date: Fri, 11 Apr 2014 09:37:53 +0200 Subject: Create setools-3.3.7 git repo --- sediff/sediff.c | 653 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 653 insertions(+) create mode 100644 sediff/sediff.c (limited to 'sediff/sediff.c') diff --git a/sediff/sediff.c b/sediff/sediff.c new file mode 100644 index 0000000..6022775 --- /dev/null +++ b/sediff/sediff.c @@ -0,0 +1,653 @@ +/** + * @file + * Command line frontend for computing a semantic policy difference. + * + * @author Jeremy A. Mowery jmowery@tresys.com + * @author Jason Tang jtang@tresys.com + * + * Copyright (C) 2006-2007 Tresys Technology, LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define COPYRIGHT_INFO "Copyright (C) 2004-2007 Tresys Technology, LLC" + +enum opt_values +{ + DIFF_LEVEL = 256, DIFF_CATEGORY, + DIFF_AUDITALLOW, DIFF_DONTAUDIT, DIFF_NEVERALLOW, + DIFF_TYPE_CHANGE, DIFF_TYPE_MEMBER, DIFF_TYPE_TRANS, + DIFF_ROLE_TRANS, DIFF_ROLE_ALLOW, DIFF_RANGE_TRANS, + OPT_STATS +}; + +/* command line options struct */ +static struct option const longopts[] = { + {"class", no_argument, NULL, 'c'}, + {"level", no_argument, NULL, DIFF_LEVEL}, + {"category", no_argument, NULL, DIFF_CATEGORY}, + {"type", no_argument, NULL, 't'}, + {"attribute", no_argument, NULL, 'a'}, + {"role", no_argument, NULL, 'r'}, + {"user", no_argument, NULL, 'u'}, + {"bool", no_argument, NULL, 'b'}, + {"allow", no_argument, NULL, 'A'}, + {"auditallow", no_argument, NULL, DIFF_AUDITALLOW}, + {"dontaudit", no_argument, NULL, DIFF_DONTAUDIT}, + {"neverallow", no_argument, NULL, DIFF_NEVERALLOW}, + {"type_change", no_argument, NULL, DIFF_TYPE_CHANGE}, + {"type_trans", no_argument, NULL, DIFF_TYPE_TRANS}, + {"type_member", no_argument, NULL, DIFF_TYPE_MEMBER}, + {"role_trans", no_argument, NULL, DIFF_ROLE_TRANS}, + {"role_allow", no_argument, NULL, DIFF_ROLE_ALLOW}, + {"range_trans", no_argument, NULL, DIFF_RANGE_TRANS}, + {"stats", no_argument, NULL, OPT_STATS}, + {"quiet", no_argument, NULL, 'q'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, 0} +}; + +static void usage(const char *prog_name, int brief) +{ + printf("Usage: %s [OPTIONS] ORIGINAL_POLICY ; MODIFIED_POLICY\n\n", prog_name); + if (brief) { + printf("\tTry %s --help for more help.\n\n", prog_name); + return; + } + printf("Semantically differentiate two policies. By default, all supported\n"); + printf("policy elements sans neverallows are examined. The following options\n"); + printf("are available:\n\n"); + printf(" -c, --class object class and common permission definitions\n"); + printf(" --level MLS level definitions\n"); + printf(" --category MLS category definitions\n"); + printf(" -t, --type type definitions\n"); + printf(" -a, --attribute attribute definitions\n"); + printf(" -r, --role role definitions\n"); + printf(" -u, --user user definitions\n"); + printf(" -b, --bool boolean definitions and default values\n"); + printf(" -A, --allow allow rules\n"); + printf(" --auditallow auditallow rules\n"); + printf(" --dontaudit dontaudit rules\n"); + printf(" --neverallow neverallow rules\n"); + printf(" --type_change type_change rules\n"); + printf(" --type_member type_member rules\n"); + printf(" --type_trans type_transition rules\n"); + printf(" --role_trans role_transition rules\n"); + printf(" --role_allow role allow rules\n"); + printf(" --range_trans range_transition rules\n"); + printf("\n"); + printf(" -q, --quiet suppress status output for elements with no differences\n"); + printf(" --stats print only statistics\n"); + printf(" -h, --help print this help text and exit\n"); + printf(" -V, --version print version information and exit\n\n"); +} + +static void print_diff_string(const char *str, unsigned int indent_level) +{ + const char *c = str; + unsigned int i; + static const char *indent = " "; + + for (i = 0; i < indent_level; i++) + printf("%s", indent); + for (; *c; c++) { + if (*c == '\n') { + if (*(c + 1) == '\0') + break; + printf("%c", *c); + for (i = 0; i < indent_level; i++) + printf("%s", indent); + } else if (*c == '\t') { + printf("%s", indent); + } else { + printf("%c", *c); + } + } +} + +static void print_rule_section(const poldiff_t * diff, const poldiff_component_record_t * rec, const apol_vector_t * v, + poldiff_form_e form) +{ + int i; + char *str = NULL; + const void *item1; + + for (i = 0; i < apol_vector_get_size(v); i++) { + item1 = apol_vector_get_element(v, i); + if (poldiff_component_record_get_form_fn(rec) (item1) == form) { + if ((str = poldiff_component_record_get_to_string_fn(rec) (diff, item1)) == NULL) { + return; + } + print_diff_string(str, 1); + printf("\n"); + free(str); + str = NULL; + } + } +} + +#define PRINT_ADDED_REMOVED 1 +#define PRINT_MODIFIED 2 +#define PRINT_ALL 4 + +static void print_rule_diffs(const poldiff_t * diff, const poldiff_component_record_t * rec, int stats_only, const char *name, + uint32_t flags, apol_vector_comp_func sort_by) +{ + const apol_vector_t *internal_v = NULL; + apol_vector_t *v = NULL; + size_t stats[5] = { 0, 0, 0, 0, 0 }; + + if (!rec || !diff) + return; + + poldiff_component_record_get_stats_fn(rec) (diff, stats); + if (flags == PRINT_ADDED_REMOVED) { + printf("%s (Added %zd, Removed %zd)\n", name, stats[0], stats[1]); + } else if (flags == PRINT_MODIFIED) { + printf("%s (Added %zd, Removed %zd, Modified %zd)\n", name, stats[0], stats[1], stats[2]); + } else if (flags == PRINT_ALL) { + printf("%s (Added %zd, Added New Type %zd, Removed %zd, Removed Missing Type %zd, Modified %zd)\n", name, stats[0], + stats[3], stats[1], stats[4], stats[2]); + } else { + fprintf(stderr, "Error, unhandled flag type\n"); + } + + if (stats_only) + return; + if ((internal_v = poldiff_component_record_get_results_fn(rec) (diff)) == NULL) { + return; + } + if (!(v = apol_vector_create_from_vector(internal_v, NULL, NULL, NULL))) { + perror("Error printig results"); + return; + } + + if (sort_by) { + apol_vector_sort(v, sort_by, NULL); + } + + printf(" Added %s: %zd\n", name, stats[0]); + print_rule_section(diff, rec, v, POLDIFF_FORM_ADDED); + + if (flags == PRINT_ALL) { + printf(" Added %s because of new type: %zd\n", name, stats[3]); + print_rule_section(diff, rec, v, POLDIFF_FORM_ADD_TYPE); + } + + printf(" Removed %s: %zd\n", name, stats[1]); + print_rule_section(diff, rec, v, POLDIFF_FORM_REMOVED); + + if (flags == PRINT_ALL) { + printf(" Removed %s because of missing type: %zd\n", name, stats[4]); + print_rule_section(diff, rec, v, POLDIFF_FORM_REMOVE_TYPE); + } + if (flags == PRINT_MODIFIED || flags == PRINT_ALL) { + printf(" Modified %s: %zd\n", name, stats[2]); + print_rule_section(diff, rec, v, POLDIFF_FORM_MODIFIED); + } + printf("\n"); + apol_vector_destroy(&v); + return; +} + +static void print_class_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_CLASSES), stats_only, "Classes", PRINT_MODIFIED, NULL); + return; +} + +static void print_bool_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_BOOLS), stats_only, "Booleans", PRINT_MODIFIED, NULL); + return; +} + +static void print_common_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_COMMONS), stats_only, "Commons", PRINT_MODIFIED, NULL); + return; +} + +static void print_level_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_LEVELS), stats_only, "Levels", PRINT_MODIFIED, NULL); + return; +} + +static void print_cat_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_CATS), stats_only, "Categories", PRINT_MODIFIED, NULL); + return; +} + +static void print_role_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_ROLES), stats_only, "Roles", PRINT_MODIFIED, NULL); + return; +} + +static void print_user_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_USERS), stats_only, "Users", PRINT_MODIFIED, NULL); + return; +} + +static void print_avallow_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_AVALLOW), stats_only, "AV-Allow Rules", PRINT_ALL, NULL); +} + +static void print_avauditallow_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_AVAUDITALLOW), stats_only, "AV-Audit Allow Rules", + PRINT_ALL, NULL); +} + +static void print_avdontaudit_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_AVDONTAUDIT), stats_only, "AV-Don't Audit Rules", + PRINT_ALL, NULL); +} + +static void print_avneverallow_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_AVNEVERALLOW), stats_only, "AV-Never Allow Rules", + PRINT_ALL, NULL); +} + +static void print_role_allow_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_ROLE_ALLOWS), stats_only, "Role Allow Rules", + PRINT_MODIFIED, NULL); +} + +static void print_role_trans_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_ROLE_TRANS), stats_only, "Role Transitions", PRINT_ALL, + NULL); +} + +static void print_range_trans_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_RANGE_TRANS), stats_only, "Range Transitions", + PRINT_MODIFIED, NULL); +} + +/** compare the names for two poldiff_type_t objects. + * used to sort items prior to display. */ +static int type_name_cmp(const void *a, const void *b, void *user_data __attribute__ ((unused))) +{ + poldiff_type_t *ta = (poldiff_type_t *) a; + poldiff_type_t *tb = (poldiff_type_t *) b; + if (ta == NULL || tb == NULL) + return -1; + return strcmp(poldiff_type_get_name(ta), poldiff_type_get_name(tb)); +} + +static void print_type_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_TYPES), stats_only, "Types", PRINT_MODIFIED, + type_name_cmp); +} + +static void print_attrib_diffs(const poldiff_t * diff, int stats_only) +{ + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_ATTRIBS), stats_only, "Attributes", PRINT_MODIFIED, NULL); +} + +static size_t get_diff_total(const poldiff_t * diff, uint32_t flags) +{ + size_t total = 0; + uint32_t i; + size_t stats[5] = { 0, 0, 0, 0, 0 }; + + if (!diff || !flags) + return 0; + + /* for all 32 bits possible in flags */ + for (i = 0x80000000; i; i = i >> 1) { + if (flags & i) { + poldiff_get_stats(diff, i, stats); + total += (stats[0] + stats[1] + stats[2] + stats[3] + stats[4]); + } + } + + return total; +} + +static void print_diff(const poldiff_t * diff, uint32_t flags, int stats, int quiet) +{ + if (flags & POLDIFF_DIFF_CLASSES && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_CLASSES))) { + print_class_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_COMMONS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_COMMONS))) { + print_common_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_LEVELS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_LEVELS))) { + print_level_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_CATS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_CATS))) { + print_cat_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_TYPES && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_TYPES))) { + print_type_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_ATTRIBS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_ATTRIBS))) { + print_attrib_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_ROLES && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_ROLES))) { + print_role_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_USERS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_USERS))) { + print_user_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_BOOLS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_BOOLS))) { + print_bool_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_AVALLOW && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_AVALLOW))) { + print_avallow_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_AVAUDITALLOW && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_AVAUDITALLOW))) { + print_avauditallow_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_AVDONTAUDIT && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_AVDONTAUDIT))) { + print_avdontaudit_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_AVNEVERALLOW && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_AVNEVERALLOW))) { + print_avneverallow_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_TECHANGE && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_TECHANGE))) { + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_TECHANGE), stats, "TE type_change", PRINT_ALL, + NULL); + } + if (flags & POLDIFF_DIFF_TEMEMBER && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_TEMEMBER))) { + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_TEMEMBER), stats, "TE type_member", PRINT_ALL, + NULL); + } + if (flags & POLDIFF_DIFF_TETRANS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_TETRANS))) { + print_rule_diffs(diff, poldiff_get_component_record(POLDIFF_DIFF_TETRANS), stats, "TE type_trans", PRINT_ALL, NULL); + } + if (flags & POLDIFF_DIFF_ROLE_ALLOWS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_ROLE_ALLOWS))) { + print_role_allow_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_ROLE_TRANS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_ROLE_TRANS))) { + print_role_trans_diffs(diff, stats); + } + if (flags & POLDIFF_DIFF_RANGE_TRANS && !(quiet && !get_diff_total(diff, POLDIFF_DIFF_RANGE_TRANS))) { + print_range_trans_diffs(diff, stats); + } +} + +int main(int argc, char **argv) +{ + int optc = 0, quiet = 0, stats = 0, default_all = 0; + uint32_t flags = 0; + apol_policy_t *orig_policy = NULL, *mod_policy = NULL; + apol_policy_path_type_e orig_path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + char *orig_base_path = NULL; + apol_vector_t *orig_module_paths = NULL; + apol_policy_path_t *orig_pol_path = NULL; + apol_policy_path_type_e mod_path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + char *mod_base_path = NULL; + apol_vector_t *mod_module_paths = NULL; + apol_policy_path_t *mod_pol_path = NULL; + poldiff_t *diff = NULL; + size_t total = 0; + + while ((optc = getopt_long(argc, argv, "ctarubANDLMCRqhV", longopts, NULL)) != -1) { + switch (optc) { + case 0: + break; + case 'c': + flags |= (POLDIFF_DIFF_CLASSES | POLDIFF_DIFF_COMMONS); + break; + case DIFF_LEVEL: + flags |= POLDIFF_DIFF_LEVELS; + break; + case DIFF_CATEGORY: + flags |= POLDIFF_DIFF_CATS; + break; + case 't': + flags |= POLDIFF_DIFF_TYPES; + break; + case 'a': + flags |= POLDIFF_DIFF_ATTRIBS; + break; + case 'r': + flags |= POLDIFF_DIFF_ROLES; + break; + case 'u': + flags |= POLDIFF_DIFF_USERS; + break; + case 'b': + flags |= POLDIFF_DIFF_BOOLS; + break; + case 'A': + flags |= POLDIFF_DIFF_AVALLOW; + break; + case DIFF_AUDITALLOW: + flags |= POLDIFF_DIFF_AVAUDITALLOW; + break; + case DIFF_DONTAUDIT: + flags |= POLDIFF_DIFF_AVDONTAUDIT; + break; + case DIFF_NEVERALLOW: + flags |= POLDIFF_DIFF_AVNEVERALLOW; + break; + case DIFF_TYPE_CHANGE: + flags |= POLDIFF_DIFF_TECHANGE; + break; + case DIFF_TYPE_MEMBER: + flags |= POLDIFF_DIFF_TEMEMBER; + break; + case DIFF_TYPE_TRANS: + flags |= POLDIFF_DIFF_TETRANS; + break; + case DIFF_ROLE_ALLOW: + flags |= POLDIFF_DIFF_ROLE_ALLOWS; + break; + case DIFF_ROLE_TRANS: + flags |= POLDIFF_DIFF_ROLE_TRANS; + break; + case DIFF_RANGE_TRANS: + flags |= POLDIFF_DIFF_RANGE_TRANS; + break; + case OPT_STATS: + stats = 1; + break; + case 'q': + quiet = 1; + break; + case 'h': + usage(argv[0], 0); + exit(0); + case 'V': + printf("sediff %s\n%s\n", VERSION, COPYRIGHT_INFO); + exit(0); + default: + usage(argv[0], 1); + exit(1); + } + } + + if (!flags) { + flags = POLDIFF_DIFF_ALL & ~POLDIFF_DIFF_AVNEVERALLOW; + default_all = 1; + } + + if (argc - optind < 2) { + usage(argv[0], 1); + exit(1); + } + + if (!strcmp(";", argv[optind])) { + ERR(NULL, "%s", "Missing path to original policy."); + goto err; + } + orig_base_path = argv[optind++]; + orig_path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + if (!(orig_module_paths = apol_vector_create(NULL))) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + for (; argc - optind; optind++) { + if (!strcmp(";", argv[optind])) { + optind++; + break; + } + if (apol_vector_append(orig_module_paths, (void *)argv[optind])) { + ERR(NULL, "Error loading module %s", argv[optind]); + goto err; + } + orig_path_type = APOL_POLICY_PATH_TYPE_MODULAR; + } + if (apol_file_is_policy_path_list(orig_base_path) > 0) { + orig_pol_path = apol_policy_path_create_from_file(orig_base_path); + if (!orig_pol_path) { + ERR(NULL, "%s", "invalid policy list"); + goto err; + } + } else { + orig_pol_path = apol_policy_path_create(orig_path_type, orig_base_path, orig_module_paths); + if (!orig_pol_path) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + } + apol_vector_destroy(&orig_module_paths); + + if (argc - optind == 0) { + ERR(NULL, "%s", "Missing path to modified policy."); + goto err; + } + + mod_base_path = argv[optind++]; + mod_path_type = APOL_POLICY_PATH_TYPE_MONOLITHIC; + if (!(mod_module_paths = apol_vector_create(NULL))) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + for (; argc - optind; optind++) { + if (apol_vector_append(mod_module_paths, (void *)argv[optind])) { + ERR(NULL, "Error loading module %s", argv[optind]); + goto err; + } + mod_path_type = APOL_POLICY_PATH_TYPE_MODULAR; + } + if (apol_file_is_policy_path_list(mod_base_path) > 0) { + mod_pol_path = apol_policy_path_create_from_file(mod_base_path); + if (!mod_pol_path) { + ERR(NULL, "%s", "invalid policy list"); + goto err; + } + } else { + mod_pol_path = apol_policy_path_create(mod_path_type, mod_base_path, mod_module_paths); + if (!mod_pol_path) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + } + apol_vector_destroy(&mod_module_paths); + + int policy_opt = 0; + if (!(flags & POLDIFF_DIFF_AVNEVERALLOW)) { + policy_opt |= QPOL_POLICY_OPTION_NO_NEVERALLOWS; + } + if (!(flags & POLDIFF_DIFF_RULES)) { + policy_opt |= QPOL_POLICY_OPTION_NO_RULES; + } + orig_policy = apol_policy_create_from_policy_path(orig_pol_path, policy_opt, NULL, NULL); + if (!orig_policy) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + mod_policy = apol_policy_create_from_policy_path(mod_pol_path, policy_opt, NULL, NULL); + if (!mod_policy) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + + qpol_policy_t *orig_qpol = apol_policy_get_qpol(orig_policy); + qpol_policy_t *mod_qpol = apol_policy_get_qpol(mod_policy); + /* we disable attribute diffs if either policy does not + * support attribute names because the fake attribute names + * won't make sense */ + if ((flags & POLDIFF_DIFF_ATTRIBS) + && (!(qpol_policy_has_capability(orig_qpol, QPOL_CAP_ATTRIB_NAMES)) + || !(qpol_policy_has_capability(mod_qpol, QPOL_CAP_ATTRIB_NAMES)))) { + flags &= ~POLDIFF_DIFF_ATTRIBS; + WARN(NULL, "%s", "Attribute diffs are not supported for current policies."); + } + + /* we disable MLS diffs if both policies do not support MLS + * but do not warn if it was implicitly requested for two + * non-MLS policies */ + if ((flags & POLDIFF_DIFF_MLS) + && (!(qpol_policy_has_capability(orig_qpol, QPOL_CAP_MLS)) && !(qpol_policy_has_capability(mod_qpol, QPOL_CAP_MLS)))) { + flags &= ~(POLDIFF_DIFF_MLS); + if (!default_all) { + WARN(NULL, "%s", "MLS diffs are not supported for current policies."); + } + } + + /* default callback for error handling is sufficient here */ + if (!(diff = poldiff_create(orig_policy, mod_policy, NULL, NULL))) { + ERR(NULL, "%s", strerror(errno)); + goto err; + } + /* poldiff now owns the policies */ + orig_policy = mod_policy = NULL; + + if (poldiff_run(diff, flags)) { + goto err; + } + + print_diff(diff, flags, stats, quiet); + + total = get_diff_total(diff, flags); + + apol_policy_path_destroy(&orig_pol_path); + apol_policy_path_destroy(&mod_pol_path); + poldiff_destroy(&diff); + + if (total) + return 1; + else + return 0; + + err: + apol_policy_destroy(&orig_policy); + apol_policy_destroy(&mod_policy); + apol_policy_path_destroy(&orig_pol_path); + apol_policy_path_destroy(&mod_pol_path); + apol_vector_destroy(&orig_module_paths); + apol_vector_destroy(&mod_module_paths); + poldiff_destroy(&diff); + return 1; +} -- cgit