void nomls_tests() { size_t first_diff = 0; int test_result; unchanged_users_v = apol_vector_create(free); changed_users_v = apol_vector_create(free); apol_vector_t *correct_unchanged_users_v = string_array_to_vector(nomls_unchanged_users); apol_vector_t *correct_changed_users_v = string_array_to_vector(nomls_changed_users); build_nomls_vecs(); apol_vector_sort(unchanged_users_v, compare_str, NULL); apol_vector_sort(correct_unchanged_users_v, compare_str, NULL); CU_ASSERT_FALSE(test_result = apol_vector_compare(unchanged_users_v, correct_unchanged_users_v, compare_str, NULL, &first_diff)); if (test_result) { print_test_failure(unchanged_users_v, correct_unchanged_users_v, first_diff, "Unchanged MLS Users"); } apol_vector_sort(changed_users_v, compare_str, NULL); apol_vector_sort(correct_changed_users_v, compare_str, NULL); CU_ASSERT_FALSE(test_result = apol_vector_compare(changed_users_v, correct_changed_users_v, compare_str, NULL, &first_diff)); if (test_result) { print_test_failure(changed_users_v, correct_changed_users_v, first_diff, "Changed MLS Users"); } apol_vector_destroy(&unchanged_users_v); apol_vector_destroy(&changed_users_v); apol_vector_destroy(&correct_unchanged_users_v); apol_vector_destroy(&correct_changed_users_v); }
seaudit_log_t *seaudit_log_create(seaudit_handle_fn_t fn, void *callback_arg) { seaudit_log_t *log = NULL; int error; if ((log = calloc(1, sizeof(*log))) == NULL) { return NULL; } log->fn = fn; log->handle_arg = callback_arg; if ((log->messages = apol_vector_create(message_free)) == NULL || (log->malformed_msgs = apol_vector_create(free)) == NULL || (log->models = apol_vector_create(NULL)) == NULL || (log->types = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->classes = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->roles = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->users = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->perms = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->mls_lvl = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->mls_clr = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->hosts = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->bools = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->managers = apol_bst_create(apol_str_strcmp, free)) == NULL) { error = errno; seaudit_log_destroy(&log); errno = error; return NULL; } return log; }
sechk_module_t *sechk_module_new(void) { sechk_module_t *mod = NULL; int error = 0; mod = calloc(1, sizeof(sechk_module_t)); if (!mod) return NULL; /* create empty vectors */ if (!(mod->options = apol_vector_create(sechk_name_value_free)) || !(mod->requirements = apol_vector_create(sechk_name_value_free)) || !(mod->dependencies = apol_vector_create(sechk_name_value_free)) || !(mod->functions = apol_vector_create(sechk_fn_free))) { error = errno; apol_vector_destroy(&mod->options); apol_vector_destroy(&mod->requirements); apol_vector_destroy(&mod->dependencies); apol_vector_destroy(&mod->functions); free(mod); errno = error; return NULL; } return mod; }
/** * Allocate and return a new level difference object. * * @param diff Policy diff error handler. * @param form Form of the difference. * @param name Name of the level that is different. * * @return A newly allocated and initialized diff, or NULL upon error. * The caller is responsible for calling level_free() upon the returned * value. */ static poldiff_level_t *make_diff(const poldiff_t * diff, poldiff_form_e form, const char *name) { poldiff_level_t *pl; int error; if ((pl = calloc(1, sizeof(*pl))) == NULL || (pl->name = strdup(name)) == NULL || (pl->added_cats = apol_vector_create(free)) == NULL || (pl->removed_cats = apol_vector_create(free)) == NULL || (pl->unmodified_cats = apol_vector_create(free)) == NULL) { error = errno; level_free(pl); ERR(diff, "%s", strerror(error)); errno = error; return NULL; } pl->form = form; return pl; }
apol_policy_path_t *apol_policy_path_create(apol_policy_path_type_e path_type, const char *path, const apol_vector_t * modules) { apol_policy_path_t *p = NULL; if (path == NULL) { errno = EINVAL; return NULL; } if ((p = calloc(1, sizeof(*p))) == NULL) { return NULL; } p->path_type = path_type; if ((p->base = strdup(path)) == NULL) { apol_policy_path_destroy(&p); return NULL; } if (p->path_type == APOL_POLICY_PATH_TYPE_MODULAR) { if (modules == NULL) { p->modules = apol_vector_create(free); } else { p->modules = apol_vector_create_from_vector(modules, apol_str_strdup, NULL, free); } if (p->modules == NULL) { apol_policy_path_destroy(&p); return NULL; } apol_vector_sort_uniquify(p->modules, apol_str_strcmp, NULL); } return p; }
int apol_userbounds_get_by_query(const apol_policy_t * p, apol_userbounds_query_t * q, apol_vector_t ** v) { qpol_iterator_t *iter; int retval = -1; *v = NULL; if (qpol_policy_get_userbounds_iter(p->p, &iter) < 0) { return -1; } if ((*v = apol_vector_create(NULL)) == NULL) { ERR(p, "%s", strerror(errno)); goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { const qpol_userbounds_t *userbounds; if (qpol_iterator_get_item(iter, (void **)&userbounds) < 0) { goto cleanup; } if (q != NULL) { if (apol_vector_append(*v, (void *)userbounds)) { ERR(p, "%s", strerror(ENOMEM)); goto cleanup; } } } retval = 0; cleanup: if (retval != 0) { apol_vector_destroy(v); } qpol_iterator_destroy(&iter); return retval; }
int apol_portcon_get_by_query(const apol_policy_t * p, const apol_portcon_query_t * po, apol_vector_t ** v) { qpol_iterator_t *iter; int retval = -1, retval2; *v = NULL; if (qpol_policy_get_portcon_iter(p->p, &iter) < 0) { return -1; } if ((*v = apol_vector_create(NULL)) == NULL) { ERR(p, "%s", strerror(errno)); goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { qpol_portcon_t *portcon; if (qpol_iterator_get_item(iter, (void **)&portcon) < 0) { goto cleanup; } if (po != NULL) { uint16_t low, high; uint8_t proto; const qpol_context_t *context; if (qpol_portcon_get_low_port(p->p, portcon, &low) < 0 || qpol_portcon_get_high_port(p->p, portcon, &high) < 0 || qpol_portcon_get_protocol(p->p, portcon, &proto) < 0 || qpol_portcon_get_context(p->p, portcon, &context) < 0) { goto cleanup; } if ((po->low >= 0 && ((uint16_t) po->low) != low) || (po->high >= 0 && ((uint16_t) po->high) != high) || (po->proto >= 0 && ((uint8_t) po->proto) != proto)) { continue; } retval2 = apol_compare_context(p, context, po->context, po->flags); if (retval2 < 0) { goto cleanup; } else if (retval2 == 0) { continue; } } if (apol_vector_append(*v, portcon)) { ERR(p, "%s", strerror(ENOMEM)); goto cleanup; } } retval = 0; cleanup: if (retval != 0) { apol_vector_destroy(v); } qpol_iterator_destroy(&iter); return retval; }
poldiff_level_summary_t *level_create(void) { poldiff_level_summary_t *ls = calloc(1, sizeof(poldiff_level_summary_t)); if (ls == NULL) return NULL; if ((ls->diffs = apol_vector_create(level_free)) == NULL) { level_destroy(&ls); return NULL; } return ls; }
seaudit_bool_message_t *bool_message_create(void) { seaudit_bool_message_t *boolm = calloc(1, sizeof(seaudit_bool_message_t)); if (boolm == NULL) { return NULL; } if ((boolm->changes = apol_vector_create(seaudit_bool_change_free)) == NULL) { bool_message_free(boolm); return NULL; } return boolm; }
int apol_filename_trans_query_append_class(const apol_policy_t * p, apol_filename_trans_query_t * t, const char *obj_class) { char *s = NULL; if (obj_class == NULL) { apol_vector_destroy(&t->classes); } else if ((s = strdup(obj_class)) == NULL || (t->classes == NULL && (t->classes = apol_vector_create(free)) == NULL) || apol_vector_append(t->classes, s) < 0) { ERR(p, "%s", strerror(errno)); free(s); return -1; } return 0; }
void seaudit_log_clear(seaudit_log_t * log) { if (log == NULL) { errno = EINVAL; return; } apol_vector_destroy(&log->messages); apol_vector_destroy(&log->malformed_msgs); apol_bst_destroy(&log->types); apol_bst_destroy(&log->classes); apol_bst_destroy(&log->roles); apol_bst_destroy(&log->users); apol_bst_destroy(&log->perms); apol_bst_destroy(&log->hosts); apol_bst_destroy(&log->bools); apol_bst_destroy(&log->managers); apol_bst_destroy(&log->mls_lvl); apol_bst_destroy(&log->mls_clr); if ((log->messages = apol_vector_create(message_free)) == NULL || (log->malformed_msgs = apol_vector_create(free)) == NULL || (log->types = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->classes = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->roles = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->users = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->perms = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->mls_lvl = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->mls_clr = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->hosts = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->bools = apol_bst_create(apol_str_strcmp, free)) == NULL || (log->managers = apol_bst_create(apol_str_strcmp, free)) == NULL) { /* hopefully will never get here... */ return; } for (size_t i = 0; i < apol_vector_get_size(log->models); i++) { seaudit_model_t *m = apol_vector_get_element(log->models, i); model_notify_log_changed(m, log); } }
apol_vector_t *seaudit_filter_create_from_file(const char *filename) { struct filter_parse_state state; int retval, error; memset(&state, 0, sizeof(state)); if ((state.filters = apol_vector_create(filter_free)) == NULL) { return NULL; } retval = filter_parse_xml(&state, filename); error = errno; free(state.view_name); if (retval < 0) { apol_vector_destroy(&state.filters); errno = error; return NULL; } return state.filters; }
int apol_permissive_get_by_query(const apol_policy_t * p, apol_permissive_query_t * q, apol_vector_t ** v) { qpol_iterator_t *iter; int retval = -1; *v = NULL; if (qpol_policy_get_permissive_iter(p->p, &iter) < 0) { return -1; } if ((*v = apol_vector_create(NULL)) == NULL) { ERR(p, "%s", strerror(errno)); goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { const qpol_permissive_t *permissive; if (qpol_iterator_get_item(iter, (void **)&permissive) < 0) { goto cleanup; } if (q != NULL) { int compval = apol_compare_permissive(p, permissive, q->permissive_name, q->flags, &(q->regex)); if (compval < 0) { goto cleanup; } else if (compval == 0) { continue; } } if (apol_vector_append(*v, (void *)permissive)) { ERR(p, "%s", strerror(ENOMEM)); goto cleanup; } } retval = 0; cleanup: if (retval != 0) { apol_vector_destroy(v); } qpol_iterator_destroy(&iter); return retval; }
/** * Given a level, return a vector of its allowed categories (in the * form of strings). These will be sorted in policy order. * * @param diff Policy diff error handler. * @param p Policy from which the level came. * @param level Level whose categories to get. * * @return Vector of category strings for the level. The caller is * responsible for calling apol_vector_destroy(). On error, return * NULL. */ static apol_vector_t *level_get_cats(const poldiff_t * diff, const apol_policy_t * p, const qpol_level_t * level) { qpol_iterator_t *iter = NULL; const qpol_cat_t *cat; const char *cat_name; apol_vector_t *v = NULL; qpol_policy_t *q = apol_policy_get_qpol(p); int retval = -1, error = 0; if ((v = apol_vector_create(NULL)) == NULL) { ERR(diff, "%s", strerror(errno)); goto cleanup; } if (qpol_level_get_cat_iter(q, level, &iter) < 0) { goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { if (qpol_iterator_get_item(iter, (void **)&cat) < 0 || qpol_cat_get_name(q, cat, &cat_name)) { error = errno; goto cleanup; } if (apol_vector_append(v, (void *)cat_name) < 0) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } } retval = 0; cleanup: qpol_iterator_destroy(&iter); if (retval < 0) { apol_vector_destroy(&v); errno = error; return NULL; } return v; }
PyObject* search(bool allow, bool neverallow, bool auditallow, bool dontaudit, bool transition, bool role_allow, const char *src_name, const char *tgt_name, const char *class_name, const char *permlist ) { options_t cmd_opts; PyObject *output = NULL; apol_vector_t *v = NULL; memset(&cmd_opts, 0, sizeof(cmd_opts)); cmd_opts.indirect = true; cmd_opts.show_cond = true; cmd_opts.allow = allow; cmd_opts.nallow = neverallow; cmd_opts.auditallow = auditallow; cmd_opts.dontaudit = dontaudit; cmd_opts.type = transition; cmd_opts.role_allow = role_allow; if (src_name) cmd_opts.src_name = strdup(src_name); if (tgt_name) cmd_opts.tgt_name = strdup(tgt_name); if (class_name) cmd_opts.class_name = strdup(class_name); if (permlist){ cmd_opts.perm_vector = apol_vector_create(free); cmd_opts.permlist = strdup(permlist); } if (!cmd_opts.semantic && qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { if (qpol_policy_build_syn_rule_table(apol_policy_get_qpol(policy))) { PyErr_SetString(PyExc_RuntimeError,"Query failed"); goto cleanup; } } /* if syntactic rules are not available always do semantic search */ if (!qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_SYN_RULES)) { cmd_opts.semantic = 1; } /* supress line numbers if doing semantic search or not available */ if (cmd_opts.semantic || !qpol_policy_has_capability(apol_policy_get_qpol(policy), QPOL_CAP_LINE_NUMBERS)) { cmd_opts.lineno = 0; } if (perform_av_query(policy, &cmd_opts, &v)) { goto cleanup; } output = PyList_New(0); if (!output) goto cleanup; if (v) { get_av_results(policy, v, output); } apol_vector_destroy(&v); if (perform_te_query(policy, &cmd_opts, &v)) { goto cleanup; } if (v) { get_te_results(policy, v, output); } if (cmd_opts.all || cmd_opts.type) { apol_vector_destroy(&v); if (perform_ft_query(policy, &cmd_opts, &v)) { goto cleanup; } if (v) { get_ft_results(policy, v, output); } } if (cmd_opts.all || cmd_opts.role_allow) { apol_vector_destroy(&v); if (perform_ra_query(policy, &cmd_opts, &v)) { goto cleanup; } if (v) { get_ra_results(policy, v, output); } } apol_vector_destroy(&v); cleanup: free(cmd_opts.src_name); free(cmd_opts.tgt_name); free(cmd_opts.class_name); free(cmd_opts.permlist); free(cmd_opts.bool_name); free(cmd_opts.src_role_name); free(cmd_opts.tgt_role_name); apol_vector_destroy(&cmd_opts.perm_vector); apol_vector_destroy(&cmd_opts.class_vector); if (output && PyList_GET_SIZE(output) == 0) { py_decref(output); return Py_None; } return output; }
int apol_role_allow_get_by_query(const apol_policy_t * p, const apol_role_allow_query_t * r, apol_vector_t ** v) { qpol_iterator_t *iter = NULL; apol_vector_t *source_list = NULL, *target_list = NULL; int retval = -1, source_as_any = 0; *v = NULL; if (r != NULL) { if (r->source != NULL && (source_list = apol_query_create_candidate_role_list(p, r->source, r->flags & APOL_QUERY_REGEX)) == NULL) { goto cleanup; } if ((r->flags & APOL_QUERY_SOURCE_AS_ANY) && r->source != NULL) { target_list = source_list; source_as_any = 1; } else if (r->target != NULL && (target_list = apol_query_create_candidate_role_list(p, r->target, r->flags & APOL_QUERY_REGEX)) == NULL) { goto cleanup; } } if (qpol_policy_get_role_allow_iter(p->p, &iter) < 0) { goto cleanup; } if ((*v = apol_vector_create(NULL)) == NULL) { ERR(p, "%s", strerror(errno)); goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { qpol_role_allow_t *rule; int match_source = 0, match_target = 0; size_t i; if (qpol_iterator_get_item(iter, (void **)&rule) < 0) { goto cleanup; } if (source_list == NULL) { match_source = 1; } else { const qpol_role_t *source_role; if (qpol_role_allow_get_source_role(p->p, rule, &source_role) < 0) { goto cleanup; } if (apol_vector_get_index(source_list, source_role, NULL, NULL, &i) == 0) { match_source = 1; } } /* if source did not match, but treating source symbol * as any field, then delay rejecting this rule until * the target has been checked */ if (!source_as_any && !match_source) { continue; } if (target_list == NULL || (source_as_any && match_source)) { match_target = 1; } else { const qpol_role_t *target_role; if (qpol_role_allow_get_target_role(p->p, rule, &target_role) < 0) { goto cleanup; } if (apol_vector_get_index(target_list, target_role, NULL, NULL, &i) == 0) { match_target = 1; } } if (!match_target) { continue; } if (apol_vector_append(*v, rule)) { ERR(p, "%s", strerror(ENOMEM)); goto cleanup; } } retval = 0; cleanup: if (retval != 0) { apol_vector_destroy(v); } apol_vector_destroy(&source_list); if (!source_as_any) { apol_vector_destroy(&target_list); } qpol_iterator_destroy(&iter); return retval; }
int apol_filename_trans_get_by_query(const apol_policy_t * p, const apol_filename_trans_query_t * t, apol_vector_t ** v) { apol_vector_t *source_list = NULL, *target_list = NULL, *class_list = NULL, *default_list = NULL; int retval = -1, source_as_any = 0, is_regex = 0; *v = NULL; qpol_iterator_t *iter = NULL; if (t != NULL) { is_regex = t->flags & APOL_QUERY_REGEX; if (t->source != NULL && (source_list = apol_query_create_candidate_type_list(p, t->source, is_regex, t->flags & APOL_QUERY_SOURCE_INDIRECT, ((t->flags & (APOL_QUERY_SOURCE_TYPE | APOL_QUERY_SOURCE_ATTRIBUTE)) / APOL_QUERY_SOURCE_TYPE))) == NULL) { goto cleanup; } if ((t->flags & APOL_QUERY_SOURCE_AS_ANY) && t->source != NULL) { default_list = target_list = source_list; source_as_any = 1; } else { if (t->target != NULL && (target_list = apol_query_create_candidate_type_list(p, t->target, is_regex, t->flags & APOL_QUERY_TARGET_INDIRECT, ((t-> flags & (APOL_QUERY_TARGET_TYPE | APOL_QUERY_TARGET_ATTRIBUTE)) / APOL_QUERY_TARGET_TYPE))) == NULL) { goto cleanup; } if (t->default_type != NULL && (default_list = apol_query_create_candidate_type_list(p, t->default_type, is_regex, 0, APOL_QUERY_SYMBOL_IS_TYPE)) == NULL) { goto cleanup; } } if (t->classes != NULL && apol_vector_get_size(t->classes) > 0 && (class_list = apol_query_create_candidate_class_list(p, t->classes)) == NULL) { goto cleanup; } } if (qpol_policy_get_filename_trans_iter(p->p, &iter) < 0) { goto cleanup; } if ((*v = apol_vector_create(NULL)) == NULL) { ERR(p, "%s", strerror(errno)); goto cleanup; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { int match_source = 0, match_target = 0, match_default = 0; size_t i; qpol_filename_trans_t *filename_trans; if (qpol_iterator_get_item(iter, (void **)&filename_trans) < 0) { goto cleanup; } if (source_list == NULL) { match_source = 1; } else { const qpol_type_t *source_type; if (qpol_filename_trans_get_source_type(p->p, filename_trans, &source_type) < 0) { goto cleanup; } if (apol_vector_get_index(source_list, source_type, NULL, NULL, &i) == 0) { match_source = 1; } } /* if source did not match, but treating source symbol * as any field, then delay rejecting this filename_trans until * the target and default have been checked */ if (!source_as_any && !match_source) { continue; } if (target_list == NULL || (source_as_any && match_source)) { match_target = 1; } else { const qpol_type_t *target_type; if (qpol_filename_trans_get_target_type(p->p, filename_trans, &target_type) < 0) { goto cleanup; } if (apol_vector_get_index(target_list, target_type, NULL, NULL, &i) == 0) { match_target = 1; } } if (!source_as_any && !match_target) { continue; } if (default_list == NULL || (source_as_any && match_source) || (source_as_any && match_target)) { match_default = 1; } else { const qpol_type_t *default_type; if (qpol_filename_trans_get_default_type(p->p, filename_trans, &default_type) < 0) { goto cleanup; } if (apol_vector_get_index(default_list, default_type, NULL, NULL, &i) == 0) { match_default = 1; } } if (!source_as_any && !match_default) { continue; } /* at least one thing must match if source_as_any was given */ if (source_as_any && (!match_source && !match_target && !match_default)) { continue; } if (class_list != NULL) { const qpol_class_t *obj_class; if (qpol_filename_trans_get_object_class(p->p, filename_trans, &obj_class) < 0) { goto cleanup; } if (apol_vector_get_index(class_list, obj_class, NULL, NULL, &i) < 0) { continue; } } if (apol_vector_append(*v, filename_trans)) { ERR(p, "%s", strerror(ENOMEM)); goto cleanup; } } retval = 0; cleanup: if (retval != 0) { apol_vector_destroy(v); } apol_vector_destroy(&source_list); if (!source_as_any) { apol_vector_destroy(&target_list); apol_vector_destroy(&default_list); } apol_vector_destroy(&class_list); qpol_iterator_destroy(&iter); return retval; }
sechk_lib_t *sechk_lib_new(void) { sechk_lib_t *lib = NULL; int retv, error; const sechk_module_name_reg_t *reg_list; size_t num_known_modules = 0; size_t i = 0; sechk_module_t *tmp = NULL; /* allocate the new sechk_lib_t structure */ lib = (sechk_lib_t *) calloc(1, sizeof(sechk_lib_t)); if (!lib) { error = errno; perror("Error creating module library"); goto exit_err; } /* create the module array from the known modules in register list */ num_known_modules = sechk_register_list_get_num_modules(); reg_list = sechk_register_list_get_modules(); lib->modules = apol_vector_create(sechk_module_free); if (!lib->modules) { error = errno; perror("Error adding modules"); goto exit_err; } for (i = 0; i < num_known_modules; i++) { tmp = sechk_module_new(); if (!tmp) { error = errno; perror("Error adding modules"); goto exit_err; } tmp->name = strdup(reg_list[i].name); if (!tmp->name) { error = errno; perror("Error adding modules"); goto exit_err; } if (apol_vector_append(lib->modules, tmp)) { error = errno; perror("Error adding modules"); goto exit_err; } tmp = NULL; } /* set the default output format */ lib->outputformat = SECHK_OUT_SHORT; lib->minsev = SECHK_SEV_LOW; /* register modules */ if ((retv = sechk_lib_register_modules(reg_list, lib)) != 0) { error = errno; perror("Error registering modules"); goto exit_err; } exit: return lib; exit_err: sechk_lib_destroy(&lib); sechk_module_free(tmp); errno = error; goto exit; }
apol_vector_t *apol_mls_range_get_levels(const apol_policy_t * p, const apol_mls_range_t * range) { qpol_policy_t *q = apol_policy_get_qpol(p); apol_vector_t *v = NULL, *catv = NULL; const qpol_level_t *l; uint32_t low_value, high_value, value; int error = 0; qpol_iterator_t *iter = NULL, *catiter = NULL; if (p == NULL || range == NULL || range->low == NULL) { error = EINVAL; ERR(p, "%s", strerror(error)); goto err; } apol_mls_level_t *low_level, *high_level; low_level = range->low; if (range->high == NULL) { high_level = low_level; } else { high_level = range->high; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(low_level), &l) < 0 || qpol_level_get_value(q, l, &low_value) < 0) { error = errno; goto err; } if (qpol_policy_get_level_by_name(q, apol_mls_level_get_sens(high_level), &l) < 0 || qpol_level_get_value(q, l, &high_value) < 0) { error = errno; goto err; } assert(low_value <= high_value); if ((v = apol_vector_create(mls_level_free)) == NULL) { error = errno; ERR(p, "%s", strerror(error)); goto err; } if (qpol_policy_get_level_iter(q, &iter) < 0) { error = errno; goto err; } for (; !qpol_iterator_end(iter); qpol_iterator_next(iter)) { const char *name; apol_mls_level_t *ml; if (qpol_iterator_get_item(iter, (void **)&l) < 0 || qpol_level_get_value(q, l, &value) < 0 || qpol_level_get_name(q, l, &name) < 0) { error = errno; goto err; } if (value < low_value || value > high_value) { continue; } if ((ml = apol_mls_level_create()) == NULL || (apol_mls_level_set_sens(p, ml, name) < 0)) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } if (qpol_level_get_cat_iter(q, l, &catiter) < 0 || (catv = apol_vector_create_from_iter(catiter, NULL)) == NULL) { error = errno; goto err; } const apol_vector_t *high_cats = apol_mls_level_get_cats(high_level); for (size_t i = 0; i < apol_vector_get_size(high_cats); i++) { char *cat_name = apol_vector_get_element(high_cats, i); size_t j; /* do not add categories that are not members of the level */ if (apol_vector_get_index(catv, cat_name, mls_level_name_to_cat_comp, q, &j) < 0) { /* this category is not legal under the given policy */ continue; } if (apol_mls_level_append_cats(p, ml, cat_name) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); if (apol_vector_append(v, ml) < 0) { error = errno; apol_mls_level_destroy(&ml); ERR(p, "%s", strerror(error)); goto err; } } apol_vector_sort(v, mls_range_comp, q); qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&catv); return v; err: qpol_iterator_destroy(&iter); qpol_iterator_destroy(&catiter); apol_vector_destroy(&v); apol_vector_destroy(&catv); errno = error; return NULL; }
int level_deep_diff_cats(poldiff_t * diff, const apol_vector_t * v1, const apol_vector_t * v2, apol_vector_t ** added, apol_vector_t ** removed, apol_vector_t ** unmodified) { size_t i, j; char *cat1, *cat2; int compval, retval = -1, error = 0; *added = *removed = *unmodified = NULL; if ((*added = apol_vector_create(free)) == NULL || (*removed = apol_vector_create(free)) == NULL || (*unmodified = apol_vector_create(free)) == NULL) { error = errno; ERR(diff, "%s", strerror(error)); goto cleanup; } for (i = j = 0; i < apol_vector_get_size(v1);) { if (j >= apol_vector_get_size(v2)) { break; } cat1 = (char *)apol_vector_get_element(v1, i); cat2 = (char *)apol_vector_get_element(v2, j); compval = strcmp(cat1, cat2); if (compval < 0) { if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*removed, cat1) < 0) { error = errno; ERR(diff, "%s", strerror(error)); free(cat1); goto cleanup; } i++; } else if (compval > 0) { if ((cat2 = strdup(cat2)) == NULL || apol_vector_append(*added, cat2) < 0) { error = errno; ERR(diff, "%s", strerror(error)); free(cat2); goto cleanup; } j++; } else { if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*unmodified, cat1) < 0) { error = errno; ERR(diff, "%s", strerror(error)); free(cat1); goto cleanup; } i++; j++; } } for (; i < apol_vector_get_size(v1); i++) { cat1 = (char *)apol_vector_get_element(v1, i); if ((cat1 = strdup(cat1)) == NULL || apol_vector_append(*removed, cat1) < 0) { error = errno; ERR(diff, "%s", strerror(error)); free(cat1); goto cleanup; } } for (; j < apol_vector_get_size(v2); j++) { cat2 = (char *)apol_vector_get_element(v2, j); if ((cat2 = strdup(cat2)) == NULL || apol_vector_append(*added, cat2) < 0) { error = errno; ERR(diff, "%s", strerror(error)); free(cat2); goto cleanup; } } if (apol_vector_get_size(*added) > 0 || apol_vector_get_size(*removed) > 0) { retval = 1; } else { retval = 0; } cleanup: if (retval <= 0) { /* if no differences found, then destroy all vectors */ apol_vector_destroy(added); apol_vector_destroy(removed); apol_vector_destroy(unmodified); } if (retval < 0) { error = errno; } return retval; }