summaryrefslogtreecommitdiffstats
path: root/sechecker/modules/spurious_audit.c
diff options
context:
space:
mode:
Diffstat (limited to 'sechecker/modules/spurious_audit.c')
-rw-r--r--sechecker/modules/spurious_audit.c778
1 files changed, 778 insertions, 0 deletions
diff --git a/sechecker/modules/spurious_audit.c b/sechecker/modules/spurious_audit.c
new file mode 100644
index 0000000..21698df
--- /dev/null
+++ b/sechecker/modules/spurious_audit.c
@@ -0,0 +1,778 @@
+/**
+ * @file
+ * Implementation of the spurious audit rule module.
+ *
+ * @author Kevin Carr kcarr@tresys.com
+ * @author Jeremy A. Mowery jmowery@tresys.com
+ * @author Jason Tang jtang@tresys.com
+ * @author Ryan Jordan rjordan@tresys.com
+ *
+ * Copyright (C) 2005-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 "sechecker.h"
+#include "spurious_audit.h"
+#include <apol/policy-query.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* This string is the name of the module and should match the stem
+ * of the file name; it should also match the prefix of all functions
+ * defined in this module and the private data storage structure */
+static const char *const mod_name = "spurious_audit";
+
+/* The register function registers all of a module's functions
+ * with the library. */
+int spurious_audit_register(sechk_lib_t * lib)
+{
+ sechk_module_t *mod = NULL;
+ sechk_fn_t *fn_struct = NULL;
+
+ if (!lib) {
+ ERR(NULL, "%s", "no library");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Modules are declared by the config file and their name and options
+ * are stored in the module array. The name is looked up to determine
+ * where to store the function structures */
+ mod = sechk_lib_get_module(mod_name, lib);
+ if (!mod) {
+ ERR(NULL, "%s%s%s", "module unknown, \"", mod_name, "\"");
+ errno = ENOENT;
+ return -1;
+ }
+
+ mod->parent_lib = lib;
+
+ /* assign the descriptions */
+ mod->brief_description = "audit rules with no effect";
+ mod->detailed_description =
+ "--------------------------------------------------------------------------------\n"
+ "This module finds audit rules in the policy which do not affect the auditing of\n"
+ "the policy. This could happen in the following situations:\n"
+ "\n"
+ " 1) there is an allow rule with the same key and permissions for a dontaudit\n"
+ " rule\n"
+ " 2) there is an auditallow rule without an allow rule with the same key or\n"
+ " with permissions that do not appear in an allow rule with the same key.\n";
+ mod->opt_description =
+ " Module requirements:\n" " none\n" " Module dependencies:\n" " none\n" " Module options:\n" " none\n";
+ mod->severity = SECHK_SEV_LOW;
+
+ /* register functions */
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(lib->policy, "%s", strerror(errno));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_INIT);
+ if (!fn_struct->name) {
+ ERR(lib->policy, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = spurious_audit_init;
+ apol_vector_append(mod->functions, (void *)fn_struct);
+
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(lib->policy, "%s", strerror(errno));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_RUN);
+ if (!fn_struct->name) {
+ ERR(lib->policy, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = spurious_audit_run;
+ apol_vector_append(mod->functions, (void *)fn_struct);
+
+ mod->data_free = NULL;
+
+ fn_struct = sechk_fn_new();
+ if (!fn_struct) {
+ ERR(lib->policy, "%s", strerror(errno));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->name = strdup(SECHK_MOD_FN_PRINT);
+ if (!fn_struct->name) {
+ ERR(lib->policy, "%s", strerror(ENOMEM));
+ errno = ENOMEM;
+ return -1;
+ }
+ fn_struct->fn = spurious_audit_print;
+ apol_vector_append(mod->functions, (void *)fn_struct);
+
+ return 0;
+}
+
+/* The init function creates the module's private data storage object
+ * and initializes its values based on the options parsed in the config
+ * file. */
+int spurious_audit_init(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ if (!mod || !policy) {
+ ERR(policy, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "%s%s%s", "wrong module (", mod->name, ")");
+ errno = EINVAL;
+ return -1;
+ }
+
+ mod->data = NULL;
+
+ return 0;
+}
+
+/* The run function performs the check. This function runs only once
+ * even if called multiple times. This function allocates the result
+ * structure and fills in all relavant item and proof data. */
+int spurious_audit_run(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ sechk_result_t *res = NULL;
+ sechk_item_t *item = NULL;
+ sechk_proof_t *proof = NULL;
+ int error, rule_found;
+ apol_avrule_query_t *query = 0;
+ apol_vector_t *allow_rules = NULL, *auditallow_rules = NULL;
+ apol_vector_t *dontaudit_rules = NULL, *perm_vector1 = NULL;
+ apol_vector_t *perm_vector2 = NULL, *perm_intersection = NULL;
+ apol_vector_t *tmp_v = NULL;
+ size_t i, j, k, l, tmp_counter;
+ const qpol_avrule_t *rule1, *rule2;
+ const qpol_type_t *source, *target;
+ const qpol_class_t *object;
+ qpol_iterator_t *perm_iter1, *perm_iter2;
+ qpol_policy_t *q = apol_policy_get_qpol(policy);
+ char *string1, *string2, *tmp;
+ const char *src_name, *tgt_name, *obj_name, *perms;
+
+ error = rule_found = 0;
+ allow_rules = auditallow_rules = dontaudit_rules = perm_vector1 = perm_vector2 = perm_intersection = NULL;
+ rule1 = rule2 = 0;
+ source = target = NULL;
+ perm_iter1 = perm_iter2 = NULL;
+ string1 = string2 = tmp = NULL;
+ src_name = tgt_name = obj_name = perms = NULL;
+
+ if (!mod || !policy) {
+ ERR(NULL, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "%s%s%s", "wrong module (", mod->name, ")");
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* if already run return */
+ if (mod->result)
+ return 0;
+
+ res = sechk_result_new();
+ if (!res) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ errno = error;
+ return -1;
+ }
+ res->test_name = strdup(mod_name);
+ if (!res->test_name) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ res->item_type = SECHK_ITEM_AVRULE;
+
+ query = apol_avrule_query_create();
+ if (!query) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ apol_avrule_query_set_rules(policy, query, QPOL_RULE_AUDITALLOW);
+ if (apol_avrule_get_by_query(policy, query, &auditallow_rules)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ apol_avrule_query_set_rules(policy, query, QPOL_RULE_DONTAUDIT);
+ if (apol_avrule_get_by_query(policy, query, &dontaudit_rules)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* First error case: Allow && Don't Audit */
+ for (i = 0; i < apol_vector_get_size(dontaudit_rules); i++) {
+ /* get first (DONT_AUDIT) rule */
+ rule1 = (qpol_avrule_t *) apol_vector_get_element(dontaudit_rules, i);
+ if (!rule1) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* get source, target, object for Don't Audit rule */
+ if (qpol_avrule_get_source_type(q, rule1, &source)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_avrule_get_target_type(q, rule1, &target)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_avrule_get_object_class(q, rule1, &object)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* extract name strings from source, target, object */
+ if (qpol_type_get_name(q, source, &src_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_type_get_name(q, target, &tgt_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_class_get_name(q, object, &obj_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* configure Allow rule query to match above Don't Audit rule */
+ apol_avrule_query_set_rules(policy, query, QPOL_RULE_ALLOW);
+ apol_avrule_query_set_source(policy, query, src_name, 1);
+ apol_avrule_query_set_target(policy, query, tgt_name, 1);
+ apol_avrule_query_append_class(policy, query, NULL);
+ apol_avrule_query_append_class(policy, query, obj_name);
+
+ /* get vector of matching ALLOW rules */
+ if (apol_avrule_get_by_query(policy, query, &allow_rules)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (apol_vector_get_size(allow_rules) != 0) {
+ /* Bad News: Allow && Don't Audit */
+ for (j = 0; j < apol_vector_get_size(allow_rules); j++) {
+ /* get second (Allow) rule */
+ rule2 = (qpol_avrule_t *) apol_vector_get_element(allow_rules, j);
+ if (!rule2) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* get permission iterators for both rules, and make vectors from them */
+ if (qpol_avrule_get_perm_iter(q, rule1, &perm_iter1)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ perm_vector1 = apol_vector_create_from_iter(perm_iter1, free);
+ if (!perm_vector1) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (qpol_avrule_get_perm_iter(q, rule2, &perm_iter2)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ perm_vector2 = apol_vector_create_from_iter(perm_iter2, free);
+ if (!perm_vector2) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* create intersection of permissions */
+ perm_intersection = apol_vector_create_from_intersection(perm_vector1,
+ perm_vector2, apol_str_strcmp, NULL);
+ if (!perm_intersection) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (apol_vector_get_size(perm_intersection) != 0) {
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ proof->elem = (void *)rule2; /* proof is the allow rule */
+ proof->type = SECHK_ITEM_AVRULE;
+ /* text will show the permissions that conflict */
+ tmp_counter = 0;
+ for (k = 0; k < apol_vector_get_size(perm_intersection); k++) {
+ apol_str_append(&(proof->text), &tmp_counter,
+ (char *)apol_vector_get_element(perm_intersection, k));
+ if (k != (apol_vector_get_size(perm_intersection) - 1))
+ apol_str_append(&(proof->text), &tmp_counter, ", ");
+ }
+ if (!item) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ item->item = (void *)rule1; /* item is the dontaudit rule */
+ }
+ if (!item->proof) {
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ apol_vector_append(item->proof, (void *)proof);
+
+ } else {
+ /* these two rules don't overlap, no problem */
+ }
+ /* clean up */
+ rule2 = NULL;
+ apol_vector_destroy(&perm_vector1);
+ apol_vector_destroy(&perm_vector2);
+ apol_vector_destroy(&perm_intersection);
+ qpol_iterator_destroy(&perm_iter1);
+ qpol_iterator_destroy(&perm_iter2);
+ }
+ apol_vector_destroy(&allow_rules);
+ if (!res->items) {
+ res->items = apol_vector_create(sechk_item_free);
+ if (!res->items) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ if (item)
+ apol_vector_append(res->items, (void *)item);
+
+ item = NULL;
+ }
+ apol_vector_destroy(&allow_rules);
+ }
+ apol_vector_destroy(&dontaudit_rules);
+
+ /* Second error case: AuditAllow w/out Allow */
+ for (i = 0; i < apol_vector_get_size(auditallow_rules); i++) {
+ /* get first (AuditAllow) rule */
+ rule1 = (qpol_avrule_t *) apol_vector_get_element(auditallow_rules, i);
+ if (!rule1) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ /* get first rule's source, target, object class */
+ if (qpol_avrule_get_source_type(q, rule1, &source)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_avrule_get_target_type(q, rule1, &target)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_avrule_get_object_class(q, rule1, &object)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ /* extract name strings from source, target, object */
+ if (qpol_type_get_name(q, source, &src_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_type_get_name(q, target, &tgt_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (qpol_class_get_name(q, object, &obj_name)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* configure ALLOW rule query to match above rule */
+ apol_avrule_query_set_rules(policy, query, QPOL_RULE_ALLOW);
+ apol_avrule_query_set_source(policy, query, src_name, 1);
+ apol_avrule_query_set_target(policy, query, tgt_name, 1);
+ apol_avrule_query_append_class(policy, query, obj_name);
+
+ if (apol_avrule_get_by_query(policy, query, &allow_rules)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (!apol_vector_get_size(allow_rules)) {
+ /* No ALLOW rule for given AUDIT_ALLOW rule */
+
+ /* Make proof: missing allow rule */
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ proof->elem = NULL;
+ proof->type = SECHK_ITEM_AVRULE;
+
+ /* grab permisisons of auditallow rule, and make text */
+ if (qpol_avrule_get_perm_iter(q, rule1, &perm_iter1)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ perm_vector1 = apol_vector_create_from_iter(perm_iter1, free);
+ if (!perm_vector1) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ tmp_counter = 0;
+ for (j = 0; j < apol_vector_get_size(perm_vector1); j++) {
+ if (apol_str_append(&(proof->text), &tmp_counter, (char *)apol_vector_get_element(perm_vector1, j))) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (j != (apol_vector_get_size(perm_vector1) - 1)) {
+ if (apol_str_append(&(proof->text), &tmp_counter, " ")) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ }
+ apol_vector_destroy(&perm_vector1);
+ qpol_iterator_destroy(&perm_iter1);
+
+ /* Make item: inconsistent auditallow rule */
+ if (!item) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ item->item = (void *)rule1;
+ if (!item->proof) {
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ apol_vector_append(item->proof, (void *)proof);
+
+ /* Add item to test result */
+ if (!res->items) {
+ res->items = apol_vector_create(sechk_item_free);
+ if (!res->items) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ if (item)
+ apol_vector_append(res->items, (void *)item);
+ item = NULL;
+ apol_vector_destroy(&allow_rules);
+ continue;
+ }
+
+ /* Here we have AuditAllow rule and Allow rule(s) with same key */
+ /* Checking to make sure they have the same permissions */
+
+ /* Make vector of AuditAllow permissions */
+ if (qpol_avrule_get_perm_iter(q, rule1, &perm_iter1)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ perm_vector1 = apol_vector_create_from_iter(perm_iter1, free);
+ if (!perm_vector1) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ /* Get permissions vector for Allow rule(s) */
+ for (j = 0; j < apol_vector_get_size(allow_rules); j++) {
+ /* get Allow rule */
+ rule2 = (qpol_avrule_t *) apol_vector_get_element(allow_rules, j);
+ if (!rule2) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (qpol_avrule_get_perm_iter(q, rule2, &perm_iter2)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+
+ if (!perm_vector2) {
+ perm_vector2 = apol_vector_create(free);
+ if (!perm_vector2) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+
+ /* concatenate permissions from this rule, check for errors, all in one go */
+ if (apol_vector_cat(perm_vector2, (tmp_v = apol_vector_create_from_iter(perm_iter2, NULL)))) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ apol_vector_destroy(&tmp_v);
+ goto spurious_audit_run_fail;
+ }
+ apol_vector_destroy(&tmp_v);
+ }
+
+ /* Find intersection of permission, put into a vector */
+ perm_intersection = apol_vector_create_from_intersection(perm_vector1, perm_vector2, apol_str_strcmp, NULL);
+
+ if (apol_vector_get_size(perm_intersection) != apol_vector_get_size(perm_vector1)) {
+ /* Auditallow rule audits things that are not allowed */
+
+ /* item for result is the AuditAllow rule */
+ if (!item) {
+ item = sechk_item_new(NULL);
+ if (!item) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));;
+ goto spurious_audit_run_fail;
+ }
+ }
+ item->item = (void *)rule1;
+ /* proof is the lack of Allow rule */
+ proof = sechk_proof_new(NULL);
+ if (!proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ proof->elem = NULL;
+ proof->type = SECHK_ITEM_AVRULE;
+
+ /* the next series of if statements prints the following:
+ * missing: allow <src_name> <tgt_name> : <obj_name> { perms }; */
+ tmp_counter = 0;
+ for (j = 0; j < apol_vector_get_size(perm_vector1); j++) {
+ string1 = (char *)apol_vector_get_element(perm_vector1, j);
+ if (apol_vector_get_index(perm_intersection, (void *)string1, apol_str_strcmp, NULL, &l) < 0) {
+ if (apol_str_append(&(proof->text), &tmp_counter, string1)) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ if (apol_str_append(&(proof->text), &tmp_counter, " ")) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ string1 = NULL;
+ }
+
+ if (!item->proof) {
+ item->proof = apol_vector_create(sechk_proof_free);
+ if (!item->proof) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ apol_vector_append(item->proof, (void *)proof);
+ proof = NULL;
+ if (!res->items) {
+ res->items = apol_vector_create(sechk_item_free);
+ if (!res->items) {
+ error = errno;
+ ERR(policy, "%s", strerror(error));
+ goto spurious_audit_run_fail;
+ }
+ }
+ apol_vector_append(res->items, (void *)item);
+ item = NULL;
+ }
+
+ /* clean up */
+ apol_vector_destroy(&perm_vector1);
+ apol_vector_destroy(&perm_vector2);
+ apol_vector_destroy(&perm_intersection);
+ apol_vector_destroy(&allow_rules);
+ qpol_iterator_destroy(&perm_iter1);
+ qpol_iterator_destroy(&perm_iter2);
+ }
+
+ apol_vector_destroy(&auditallow_rules);
+ apol_avrule_query_destroy(&query);
+
+ mod->result = res;
+
+ /* If module finds something that would be considered a fail
+ * on the policy return 1 here */
+ if (apol_vector_get_size(res->items) > 0)
+ return 1;
+
+ return 0;
+
+ spurious_audit_run_fail:
+ sechk_proof_free(proof);
+ sechk_item_free(item);
+ sechk_result_destroy(&res);
+ apol_vector_destroy(&allow_rules);
+ apol_vector_destroy(&auditallow_rules);
+ apol_vector_destroy(&dontaudit_rules);
+ apol_vector_destroy(&perm_vector1);
+ apol_vector_destroy(&perm_vector2);
+ apol_vector_destroy(&perm_intersection);
+ qpol_iterator_destroy(&perm_iter1);
+ qpol_iterator_destroy(&perm_iter2);
+ apol_avrule_query_destroy(&query);
+ free(tmp);
+ tmp = NULL;
+ sechk_result_destroy(&res);
+ errno = error;
+ return -1;
+}
+
+/* The print function generates the text and prints the
+ * results to stdout. */
+int spurious_audit_print(sechk_module_t * mod, apol_policy_t * policy, void *arg __attribute__ ((unused)))
+{
+ unsigned char outformat = 0x00;
+ sechk_item_t *item = NULL;
+ sechk_proof_t *proof = NULL;
+ size_t i = 0, j = 0;
+ uint32_t ruletype;
+ qpol_policy_t *q = apol_policy_get_qpol(policy);
+ char *tmp;
+
+ if (!mod || !policy) {
+ ERR(NULL, "%s", strerror(EINVAL));
+ errno = EINVAL;
+ return -1;
+ }
+ if (strcmp(mod_name, mod->name)) {
+ ERR(policy, "%s%s%s", "wrong module (", mod->name, ")");
+ errno = EINVAL;
+ return -1;
+ }
+
+ outformat = mod->outputformat;
+
+ if (!mod->result) {
+ ERR(policy, "%s%s%s", "module ", mod->name, "has not been run");
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!outformat || (outformat & SECHK_OUT_QUIET))
+ return 0; /* not an error - no output is requested */
+
+ if (outformat & SECHK_OUT_STATS) {
+ i = apol_vector_get_size(mod->result->items);
+ printf("Found %zd rule%s.\n", i, (i == 1) ? "" : "s");
+ }
+ /* The list report component is a display of all items
+ * found without any supporting proof. */
+ if (outformat & SECHK_OUT_LIST) {
+ printf("\n");
+ for (i = 0; i < apol_vector_get_size(mod->result->items); i++) {
+ item = apol_vector_get_element(mod->result->items, i);
+ printf("%s\n", (tmp = apol_avrule_render(policy, (qpol_avrule_t *) item->item)));
+ free(tmp);
+ }
+ printf("\n");
+ }
+ /* The proof report component is a display of a list of items
+ * with an indented list of proof statements supporting the result
+ * of the check for that item. */
+ if (outformat & SECHK_OUT_PROOF) {
+ printf("\n");
+ for (i = 0; i < apol_vector_get_size(mod->result->items); i++) {
+ item = apol_vector_get_element(mod->result->items, i);
+ printf("%s\n", (tmp = apol_avrule_render(policy, (qpol_avrule_t *) item->item)));
+
+ qpol_avrule_get_rule_type(q, (qpol_avrule_t *) item->item, &ruletype);
+ if (ruletype == QPOL_RULE_DONTAUDIT) {
+ for (j = 0; j < apol_vector_get_size(item->proof); j++) {
+ proof = apol_vector_get_element(item->proof, j);
+ printf("\tinconsistent: ");
+ printf("%s\n", apol_avrule_render(policy, (qpol_avrule_t *) proof->elem));
+ printf("\tinconsistent permissions:\n");
+ printf("\t%s\n", proof->text);
+ }
+ } else if (ruletype == QPOL_RULE_AUDITALLOW) {
+ printf("\tmissing: ");
+ printf("%s\n", strstr(apol_avrule_render(policy, (qpol_avrule_t *) item->item), "allow"));
+ printf("\tmissing permissions:\n");
+ for (j = 0; j < apol_vector_get_size(item->proof); j++) {
+ proof = apol_vector_get_element(item->proof, j);
+ printf("\t%s\n", proof->text);
+ }
+ }
+ printf("\n");
+ }
+ printf("\n");
+ }
+
+ return 0;
+}