summaryrefslogtreecommitdiffstats
path: root/libpoldiff/tests
diff options
context:
space:
mode:
Diffstat (limited to 'libpoldiff/tests')
-rw-r--r--libpoldiff/tests/Makefile.am19
-rw-r--r--libpoldiff/tests/components-tests.c544
-rw-r--r--libpoldiff/tests/components-tests.h49
-rw-r--r--libpoldiff/tests/libpoldiff-tests.c364
-rw-r--r--libpoldiff/tests/libpoldiff-tests.h85
-rw-r--r--libpoldiff/tests/mls-tests.c635
-rw-r--r--libpoldiff/tests/mls-tests.h39
-rw-r--r--libpoldiff/tests/nomls-tests.c139
-rw-r--r--libpoldiff/tests/nomls-tests.h33
-rw-r--r--libpoldiff/tests/policy-defs.h44
-rw-r--r--libpoldiff/tests/rules-tests.c914
-rw-r--r--libpoldiff/tests/rules-tests.h40
12 files changed, 2905 insertions, 0 deletions
diff --git a/libpoldiff/tests/Makefile.am b/libpoldiff/tests/Makefile.am
new file mode 100644
index 0000000..f46f739
--- /dev/null
+++ b/libpoldiff/tests/Makefile.am
@@ -0,0 +1,19 @@
+TESTS = libpoldiff-tests
+check_PROGRAMS = libpoldiff-tests
+
+libpoldiff_tests_SOURCES = \
+ components-tests.c components-tests.h \
+ libpoldiff-tests.c libpoldiff-tests.h \
+ mls-tests.c mls-tests.h \
+ nomls-tests.c nomls-tests.h \
+ policy-defs.h \
+ rules-tests.c rules-tests.h
+
+AM_CFLAGS = @DEBUGCFLAGS@ @WARNCFLAGS@ @PROFILECFLAGS@ @SELINUX_CFLAGS@ \
+ @QPOL_CFLAGS@ @APOL_CFLAGS@ @POLDIFF_CFLAGS@
+
+AM_LDFLAGS = @DEBUGLDFLAGS@ @WARNLDFLAGS@ @PROFILELDFLAGS@
+
+LDADD = @SELINUX_LIB_FLAG@ @POLDIFF_LIB_FLAG@ @APOL_LIB_FLAG@ @QPOL_LIB_FLAG@ @CUNIT_LIB_FLAG@
+
+libpoldiff_tests_DEPENDENCIES = ../src/libpoldiff.so
diff --git a/libpoldiff/tests/components-tests.c b/libpoldiff/tests/components-tests.c
new file mode 100644
index 0000000..4d70e80
--- /dev/null
+++ b/libpoldiff/tests/components-tests.c
@@ -0,0 +1,544 @@
+/**
+ * @file
+ *
+ * Test the libpoldiff's correctness for components.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "libpoldiff-tests.h"
+#include "components-tests.h"
+#include "policy-defs.h"
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+#include <apol/util.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *unchanged_attributes[] = {
+/* 00.0 */
+ "data",
+ NULL
+};
+char *added_attributes[] = {
+/* 00.1 */
+ "mineral",
+ NULL
+};
+char *removed_attributes[] = {
+/* 00.2 */
+ "other",
+ NULL
+};
+char *modified_attributes[] = {
+/* 00.3.0 */
+ "tree +holly_t",
+/* 00.3.1 */
+ "fish -bass_t",
+ "plant -daikon_t",
+/* 00.3.2 */
+ "animal +hippo_t",
+ "animal -bass_t",
+ "animal -koala_t",
+ "mammal +hippo_t",
+ "mammal -bear_t",
+ NULL
+};
+char *unchanged_bools[] = {
+/* 02.0 */
+ "frog",
+ NULL
+};
+char *added_bools[] = {
+/* 02.1 */
+ "shark",
+ NULL
+};
+char *removed_bools[] = {
+/* 02.2 */
+ "dog",
+ NULL
+};
+char *modified_bools[] = {
+/* 02.3 */
+ "wark",
+ NULL
+};
+char *unchanged_classes[] = {
+/* 04.0 */
+ "filesystem", "dir", "blk_file", "sock_file", "fifo_file", "netif",
+ "process", "msg", "security", "system", "capability", "passwd",
+ "window", "font", "colormap", "property", "cursor", "xclient",
+ "xinput", "xserver", "xextension", "pax", "dbus", "ncsd",
+ "association", "context", NULL
+};
+char *added_classes[] = {
+/* 04.1 */
+ "thing",
+ NULL
+};
+char *removed_classes[] = {
+/* 04.2 */
+ "key",
+ NULL
+};
+char *modified_classes[] = {
+/* 04.3.00 */
+ "fd +be",
+/* 04.3.01 */
+ "chr_file -execmod",
+/* 04.3.02*/
+ "file +newperm",
+ "file -execmod",
+/* 04.3.03 */
+ "ipc +unix_exec",
+ "sem +unix_exec",
+/* 04.3.04 */
+ "socket -name_bind",
+ "tcp_socket -name_bind",
+ "udp_socket -name_bind",
+ "netlink_socket -name_bind",
+ "packet_socket -name_bind",
+ "key_socket -name_bind",
+ "unix_dgram_socket -name_bind",
+ "dccp_socket -name_bind",
+ "netlink_route_socket -name_bind",
+ "netlink_firewall_socket -name_bind",
+ "netlink_tcpdiag_socket -name_bind",
+ "netlink_nflog_socket -name_bind",
+ "netlink_xfrm_socket -name_bind",
+ "netlink_selinux_socket -name_bind",
+ "netlink_audit_socket -name_bind",
+ "netlink_ip6fw_socket -name_bind",
+ "netlink_dnrt_socket -name_bind",
+ "appletalk_socket -name_bind",
+ "netlink_kobject_uevent_socket -name_bind",
+/* 04.3.05 */
+ "drawable +bar",
+ "drawable -blah",
+/* 04.3.06 */
+ "msgq +unix_exec",
+ "msgq +dequeue",
+/* 04.3.07 */
+ "rawip_socket -name_bind",
+ "rawip_socket +ip_bind",
+/* 04.3.08 */
+ "shm +unix_exec",
+ "shm -lock",
+/* 04.3.09 */
+ "unix_stream_socket -newconn",
+ "unix_stream_socket -name_bind",
+/* 04.3.10 */
+ "gc +bar",
+ "gc +remove",
+ "gc -blah",
+ "gc -free",
+ NULL
+};
+
+char *unchanged_commons[] = {
+/* 05.0 */
+ "file",
+ NULL
+};
+char *added_commons[] = {
+/* 05.1 */
+ "new",
+ NULL
+};
+char *removed_commons[] = {
+/* 05.2 */
+ "old",
+ NULL
+};
+char *modified_commons[] = {
+/* 05.3.0 */
+ "ipc +unix_exec",
+/* 05.3.1 */
+ "socket -name_bind",
+/* 05.3.2 */
+ "bob -blah",
+ "bob +bar",
+ NULL
+};
+
+char *unchanged_roles[] = {
+/* 08.0 */
+ "placeholder_r", "admin_r", "intern_r",
+ NULL
+};
+char *added_roles[] = {
+/* 08.1 */
+ "strange_r",
+ NULL
+};
+char *removed_roles[] = {
+/* 08.2 */
+ "guest_r",
+ NULL
+};
+char *modified_roles[] = {
+/* 08.3.0 */
+ "user_r +hippo_t",
+/* 08.3.1 */
+ "lumberjack_r +holly_t",
+/* 08.3.2 */
+ "staff_r -bass_t",
+/* 08.3.3 */
+ "aquarium_r -bass_t",
+ "garden_r -daikon_t",
+/* 08.3.4 */
+ "object_r +hippo_t",
+ "object_r +acorn_t",
+ "object_r -bass_t",
+ "object_r -koala_t",
+ "deity_r +acorn_t",
+ "deity_r +hippo_t",
+ "deity_r -bass_t",
+ "deity_r -dirt_t",
+ "deity_r -koala_t",
+/* 08.3.5 */
+ "zoo_r +hippo_t",
+ "zoo_r -bass_t",
+ "zoo_r -koala_t",
+ "mammal_r +hippo_t",
+ "mammal_r -bear_t",
+ NULL
+};
+
+char *unchanged_types[] = {
+/* 12.0.0 */
+ "placeholder_t", "finch_t", "trout_t",
+ "birch_t", "oak_t", "potato_t", "tiger_t",
+ "lion_t", "pine_t", "log_t", "file_t",
+/* 12.0.1 */
+ "firefly_t", "lightningbug_t",
+/* 12.0.2 */
+ "rock_t", "big_stone_t",
+ NULL
+};
+
+char *added_types[] = {
+/* 12.1.0 */
+ "hippo_t",
+ "acorn_t",
+ NULL
+};
+
+/* 12.1.1 */
+char *removed_types[] = {
+/* 12.2.0 */
+ "bass_t",
+/* 12.2.1 */
+ "koala_t",
+ NULL
+};
+
+char *modified_types[] = {
+/* 12.3.0 */
+ "holly_t +tree",
+/* 12.3.1 */
+ "bear_t -mammal",
+/* 12.3.2 */
+ "daikon_t -plant",
+ "daikon_t +mineral",
+/* 12.3.3 */
+ "glass_t -> crystal_t +mineral",
+/* 12.3.4 */
+ "dirt_t -> soil_t +mineral",
+/* NEED TO BE ADDED */
+ "stone_t -other",
+ "system_t -other",
+ NULL
+};
+char *aliased_types[] = {
+ /* 12.2.1 */
+ "bear_t -> koala_t",
+ NULL
+};
+
+char *unchanged_users[] = {
+/* 13.0 */
+ "placeholder_u", "su_u", "cyn_u", "danika_u",
+ NULL
+};
+char *added_users[] = {
+/* 13.1 */
+ "gai_u",
+ NULL
+};
+char *removed_users[] = {
+/* 13.2 */
+ "mehnlo_u",
+ NULL
+};
+char *modified_users[] = {
+/* 13.3.0 */
+ "devona_u +aquarium_r",
+ "eve_u +strange_r",
+/* 13.3.1 */
+ "nika_u -user_r",
+/* 13.3.2 */
+ "meloni_u +garden_r",
+ "meloni_u -user_r",
+ NULL
+};
+
+/* This #define is kind of like a template since all of the "get_name" classes
+ * follow the same pattern. The wrapped function name comes out the same as the
+ * original, but with a _w at the end (for example: poldiff_attribute_get_name_w
+ * see definition in components-tests.h */
+WRAP_NAME_FUNC(attrib)
+ WRAP_NAME_FUNC(bool)
+ WRAP_NAME_FUNC(class)
+ WRAP_NAME_FUNC(common)
+ WRAP_NAME_FUNC(role)
+ WRAP_NAME_FUNC(type)
+ WRAP_NAME_FUNC(user)
+ WRAP_NAME_FUNC(cat)
+/* This is the same idea except for with "get_added" and "get_removed" */
+ WRAP_MOD_FUNC(class, perms, added)
+ WRAP_MOD_FUNC(class, perms, removed)
+ WRAP_MOD_FUNC(attrib, types, added)
+ WRAP_MOD_FUNC(attrib, types, removed)
+ WRAP_MOD_FUNC(common, perms, added)
+ WRAP_MOD_FUNC(common, perms, removed)
+ WRAP_MOD_FUNC(role, types, added)
+ WRAP_MOD_FUNC(role, types, removed)
+ WRAP_MOD_FUNC(user, roles, added)
+ WRAP_MOD_FUNC(user, roles, removed)
+ WRAP_MOD_FUNC(type, attribs, added)
+ WRAP_MOD_FUNC(type, attribs, removed)
+
+void build_component_vecs(component_funcs_t * component_funcs)
+{
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = component_funcs->get_diff_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ item = apol_vector_get_element(v, i);
+ const char *name_only = NULL;
+ name_only = component_funcs->get_name(item);
+ if (component_funcs->get_form(item) == POLDIFF_FORM_ADDED) {
+ apol_vector_append(added_v, strdup(name_only));
+ } else if (component_funcs->get_form(item) == POLDIFF_FORM_REMOVED) {
+ apol_vector_append(removed_v, strdup(name_only));
+ } else if (component_funcs->get_form(item) == POLDIFF_FORM_MODIFIED) {
+ apol_vector_append(modified_name_only_v, strdup(name_only));
+ size_t j;
+ if (component_funcs->get_added) {
+ const apol_vector_t *added_elements = component_funcs->get_added(item);
+ for (j = 0; j < apol_vector_get_size(added_elements); ++j) {
+ char *added_element;
+ added_element = apol_vector_get_element(added_elements, j);
+ char *modification_str = NULL;
+ size_t modification_str_len = 0;
+ apol_str_appendf(&modification_str, &modification_str_len, "%s %s%s", name_only, "+",
+ added_element);
+ apol_vector_append(modified_v, modification_str);
+ }
+ }
+ if (component_funcs->get_removed) {
+ const apol_vector_t *removed_elements = component_funcs->get_removed(item);
+ for (j = 0; j < apol_vector_get_size(removed_elements); ++j) {
+ char *removed_element;
+ removed_element = apol_vector_get_element(removed_elements, j);
+ char *modification_str = NULL;
+ size_t modification_str_len = 0;
+ apol_str_appendf(&modification_str, &modification_str_len, "%s %s%s", name_only, "-",
+ removed_element);
+ apol_vector_append(modified_v, modification_str);
+ }
+ }
+ if (!(component_funcs->get_added && component_funcs)) {
+ apol_vector_append(modified_v, strdup(name_only));
+ }
+ }
+ }
+}
+
+void components_types_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_types, removed_types, unchanged_types, modified_types);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_type_vector, poldiff_type_get_name_w,
+ poldiff_type_get_form, poldiff_type_get_added_attribs_w,
+ poldiff_type_get_removed_attribs_w);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ /* this is for the alias tests */
+ size_t i;
+ apol_vector_t *orig_aliases_v = apol_vector_create(free);
+ apol_vector_t *mod_aliases_v = apol_vector_create(free);
+ apol_vector_t *final_aliases_v = apol_vector_create(free);
+ apol_vector_t *correct_final_aliases_v = string_array_to_vector(aliased_types);
+ apol_vector_t *changed_aliases_v;
+
+ qpol_policy_t *orig_qpolicy = apol_policy_get_qpol(orig_policy);
+ qpol_policy_t *mod_qpolicy = apol_policy_get_qpol(mod_policy);
+
+ qpol_iterator_t *orig_types;
+ qpol_iterator_t *mod_types;
+
+ qpol_policy_get_type_iter(mod_qpolicy, &orig_types);
+ for (; !qpol_iterator_end(orig_types); qpol_iterator_next(orig_types)) {
+ unsigned char isalias = 0;
+ qpol_type_t *qpol_type;
+ const char *name;
+ qpol_iterator_get_item(orig_types, (void **)&qpol_type);
+ qpol_type_get_name(orig_qpolicy, qpol_type, &name);
+ qpol_type_get_isalias(orig_qpolicy, qpol_type, &isalias);
+ if (!isalias) {
+ apol_vector_append(orig_aliases_v, strdup(name));
+ }
+ }
+ qpol_policy_get_type_iter(mod_qpolicy, &mod_types);
+ for (; !qpol_iterator_end(mod_types); qpol_iterator_next(mod_types)) {
+ unsigned char isalias = 0;
+ const qpol_type_t *qpol_type;
+ const char *name;
+ qpol_iterator_get_item(mod_types, (void **)&qpol_type);
+ qpol_type_get_name(mod_qpolicy, qpol_type, &name);
+ qpol_type_get_isalias(mod_qpolicy, qpol_type, &isalias);
+ if (isalias) {
+ apol_vector_append(mod_aliases_v, strdup(name));
+ }
+ }
+
+ changed_aliases_v = apol_vector_create_from_intersection(orig_aliases_v, mod_aliases_v, apol_str_strcmp, NULL);
+ char *alias_str = NULL, *str = NULL;
+ size_t alias_str_len = 0, str_len = 0;
+ for (i = 0; i < apol_vector_get_size(changed_aliases_v); ++i) {
+ char *name = apol_vector_get_element(changed_aliases_v, i);
+ qpol_iterator_t *aliased_to;
+ const qpol_type_t *qtype;
+ qpol_policy_get_type_by_name(mod_qpolicy, name, &qtype);
+ qpol_type_get_alias_iter(mod_qpolicy, qtype, &aliased_to);
+ for (; !qpol_iterator_end(aliased_to); qpol_iterator_next(aliased_to)) {
+ const char *name;
+ qpol_iterator_get_item(aliased_to, (void **)&name);
+ apol_str_append(&alias_str, &alias_str_len, name);
+ }
+ apol_str_appendf(&str, &str_len, "%s -> %s", name, alias_str);
+ free(alias_str);
+ apol_vector_append(final_aliases_v, str);
+ qpol_iterator_destroy(&aliased_to);
+ }
+ apol_vector_sort(final_aliases_v, compare_str, NULL);
+ apol_vector_sort(correct_final_aliases_v, compare_str, NULL);
+ size_t first_diff = 0;
+ int test_result;
+
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(final_aliases_v, correct_final_aliases_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(final_aliases_v, correct_final_aliases_v, first_diff, "Aliases");
+ }
+ apol_vector_destroy(&orig_aliases_v);
+ apol_vector_destroy(&mod_aliases_v);
+ apol_vector_destroy(&final_aliases_v);
+ apol_vector_destroy(&correct_final_aliases_v);
+ apol_vector_destroy(&changed_aliases_v);
+ qpol_iterator_destroy(&mod_types);
+ qpol_iterator_destroy(&orig_types);
+
+ cleanup_test(answers);
+}
+
+void components_bools_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_bools, removed_bools, unchanged_bools, modified_bools);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_bool_vector, poldiff_bool_get_name_w,
+ poldiff_bool_get_form, NULL, NULL);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+void components_users_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_users, removed_users, unchanged_users, modified_users);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_user_vector, poldiff_user_get_name_w,
+ poldiff_user_get_form, poldiff_user_get_added_roles_w,
+ poldiff_user_get_removed_roles_w);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+void components_roles_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_roles, removed_roles, unchanged_roles, modified_roles);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_role_vector, poldiff_role_get_name_w, poldiff_role_get_form,
+ poldiff_role_get_added_types_w, poldiff_role_get_removed_types_w);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+void components_commons_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_commons, removed_commons, unchanged_commons, modified_commons);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_common_vector, poldiff_common_get_name_w, poldiff_common_get_form,
+ poldiff_common_get_added_perms_w, poldiff_common_get_removed_perms_w);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+void components_attributes_tests()
+{
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_attributes, removed_attributes, unchanged_attributes, modified_attributes);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_attrib_vector, poldiff_attrib_get_name_w,
+ poldiff_attrib_get_form, poldiff_attrib_get_added_types_w,
+ poldiff_attrib_get_removed_types_w);
+
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+void components_class_tests()
+{
+ poldiff_test_answers_t *answers = init_answer_vectors(added_classes, removed_classes, unchanged_classes, modified_classes);
+ component_funcs_t *funcs = init_test_funcs(poldiff_get_class_vector, poldiff_class_get_name_w,
+ poldiff_class_get_form, poldiff_class_get_added_perms_w,
+ poldiff_class_get_removed_perms_w);
+ run_test(funcs, answers, COMPONENT);
+ free(funcs);
+ cleanup_test(answers);
+}
+
+int components_test_init()
+{
+ if (!(diff = init_poldiff(COMPONENTS_ORIG_POLICY, COMPONENTS_MOD_POLICY))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/libpoldiff/tests/components-tests.h b/libpoldiff/tests/components-tests.h
new file mode 100644
index 0000000..8d8ed6f
--- /dev/null
+++ b/libpoldiff/tests/components-tests.h
@@ -0,0 +1,49 @@
+/**
+ * @file
+ *
+ * Header file for libpoldiff's correctness of components.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef COMPONENTS_TEST
+#define COMPONENTS_TEST
+
+#define WRAP_NAME_FUNC(component) const char *poldiff_##component##_get_name_w(const void *arg) { \
+ const poldiff_##component##_t *cls = (const poldiff_##component##_t *)arg; \
+ return poldiff_##component##_get_name(cls); }
+
+#define WRAP_MOD_FUNC(component,mod_component,mod_type) const apol_vector_t* poldiff_##component##_get_##mod_type##_##mod_component##_w(const void* arg) { \
+ const poldiff_##component##_t *cls = (const poldiff_##component##_t *)arg; \
+ return poldiff_##component##_get_##mod_type##_##mod_component(cls); }
+
+void build_component_vecs(component_funcs_t *);
+
+int components_test_init();
+int components_test_cleanup();
+
+void components_attributes_tests();
+void components_bools_tests();
+void components_commons_tests();
+void components_roles_tests();
+void components_users_tests();
+void components_class_tests();
+void components_types_tests();
+
+#endif
diff --git a/libpoldiff/tests/libpoldiff-tests.c b/libpoldiff/tests/libpoldiff-tests.c
new file mode 100644
index 0000000..c665c1b
--- /dev/null
+++ b/libpoldiff/tests/libpoldiff-tests.c
@@ -0,0 +1,364 @@
+/**
+ * @file
+ *
+ * CUnit testing framework for libpoldiff's correctness.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "libpoldiff-tests.h"
+
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+#include <apol/util.h>
+#include <apol/vector.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "components-tests.h"
+#include "rules-tests.h"
+#include "mls-tests.h"
+#include "nomls-tests.h"
+
+apol_vector_t *string_array_to_vector(char *arr[])
+{
+ apol_vector_t *v = apol_vector_create(free);
+ int i;
+ for (i = 0; arr[i] != NULL; ++i) {
+ apol_vector_append(v, strdup(arr[i]));
+ }
+ return v;
+}
+
+char *vector_to_string(const apol_vector_t * v, const char *pre, const char *sep)
+{
+ char *item = NULL, *str = NULL, *tmp = NULL;
+ size_t i = 0, str_len = 0, tmp_len = 0;
+ size_t num_elements = apol_vector_get_size(v);
+ for (i = 0; v && i < num_elements; i++) {
+ item = apol_vector_get_element(v, i);
+ if (apol_str_appendf(&tmp, &tmp_len, "%s%s", sep, item) < 0) {
+ return NULL;
+ }
+ }
+ apol_str_trim(tmp);
+ if (tmp) {
+ apol_str_appendf(&str, &str_len, "%s%s", pre, tmp);
+ } else {
+ str = strdup("");
+ }
+ free(tmp);
+ return str;
+}
+
+apol_vector_t *shallow_copy_str_vec_and_sort(const apol_vector_t * v)
+{
+ apol_vector_t *copy = apol_vector_create_from_vector(v, NULL, NULL, NULL);
+ apol_vector_sort(copy, apol_str_strcmp, NULL);
+ return copy;
+}
+
+void run_test(component_funcs_t * component_funcs, poldiff_test_answers_t * poldiff_test_answers, test_numbers_e test_num)
+{
+ added_v = apol_vector_create(free);
+ removed_v = apol_vector_create(free);
+ modified_v = apol_vector_create(free);
+ modified_name_only_v = apol_vector_create(free);
+ switch (test_num) {
+ case COMPONENT:
+ build_component_vecs(component_funcs);
+ break;
+ case RULES_AVRULE:
+ build_avrule_vecs();
+ break;
+ case RULES_TERULE:
+ build_terule_vecs();
+ break;
+ case RULES_ROLEALLOW:
+ build_roleallow_vecs();
+ break;
+ case RULES_ROLETRANS:
+ build_roletrans_vecs();
+ break;
+ case MLS_CATEGORY:
+ build_category_vecs();
+ break;
+ case MLS_LEVEL:
+ build_level_vecs();
+ break;
+ case MLS_RANGETRANS:
+ build_rangetrans_vecs();
+ break;
+ case MLS_USER:
+ build_user_vecs();
+ break;
+ }
+ size_t first_diff;
+ apol_vector_t *intersect = NULL, *all_changes = NULL;
+ if (!(all_changes = apol_vector_create(NULL))) {
+ goto err;
+ }
+ apol_vector_cat(all_changes, added_v);
+ apol_vector_cat(all_changes, removed_v);
+ apol_vector_cat(all_changes, modified_name_only_v);
+ if (!
+ (intersect =
+ apol_vector_create_from_intersection(all_changes, poldiff_test_answers->correct_unchanged_v, compare_str, NULL))) {
+ goto err;
+ }
+ /* unchanged */
+ CU_ASSERT_EQUAL(apol_vector_get_size(intersect), 0);
+ /* added */
+ apol_vector_sort(added_v, compare_str, NULL);
+ apol_vector_sort(poldiff_test_answers->correct_added_v, compare_str, NULL);
+ int test_result;
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(added_v, poldiff_test_answers->correct_added_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(added_v, poldiff_test_answers->correct_added_v, first_diff, "Added");
+ }
+ /* removed */
+ apol_vector_sort(removed_v, compare_str, NULL);
+ apol_vector_sort(poldiff_test_answers->correct_removed_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(removed_v, poldiff_test_answers->correct_removed_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(removed_v, poldiff_test_answers->correct_removed_v, first_diff, "Removed");
+ }
+ /* modified */
+ apol_vector_sort(modified_v, compare_str, NULL);
+ apol_vector_sort(poldiff_test_answers->correct_modified_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(modified_v, poldiff_test_answers->correct_modified_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(modified_v, poldiff_test_answers->correct_modified_v, first_diff, "Modified");
+ }
+
+ apol_vector_destroy(&intersect);
+ apol_vector_destroy(&added_v);
+ apol_vector_destroy(&removed_v);
+ apol_vector_destroy(&modified_name_only_v);
+ apol_vector_destroy(&modified_v);
+ apol_vector_destroy(&all_changes);
+ return;
+ err:
+ apol_vector_destroy(&intersect);
+ apol_vector_destroy(&added_v);
+ apol_vector_destroy(&removed_v);
+ apol_vector_destroy(&modified_name_only_v);
+ apol_vector_destroy(&modified_v);
+ apol_vector_destroy(&all_changes);
+ CU_FAIL_FATAL("Could not initialize vectors for test");
+}
+
+void print_test_failure(apol_vector_t * actual, apol_vector_t * expected, size_t first_diff, const char *test_name)
+{
+ printf("\nTEST FAILED\n");
+ size_t i;
+ printf("--- ACTUAL RESULT (%s) -----\n", test_name);
+ for (i = first_diff; i < apol_vector_get_size(actual); ++i) {
+ char *item = (char *)apol_vector_get_element(actual, i);
+ printf("\t%3d. %s\n", (int)i, item);
+ }
+ printf("--- EXPECTED RESULT (%s) ---\n", test_name);
+ for (i = first_diff; i < apol_vector_get_size(expected); ++i) {
+ char *item = (char *)apol_vector_get_element(expected, i);
+ printf("\t%3d. %s\n", (int)i, item);
+ }
+}
+
+int compare_str(const void *s1, const void *s2, void *debug)
+{
+ char *str1 = strdup((char *)s1);
+ char *str2 = strdup((char *)s2);
+ apol_str_trim(str1);
+ apol_str_trim(str2);
+ int result = strcmp(str1, str2);
+ free(str1);
+ free(str2);
+ return result;
+}
+
+poldiff_test_answers_t *init_answer_vectors(char *added_arr[], char *removed_arr[], char *unchanged_arr[], char *modified_arr[])
+{
+ poldiff_test_answers_t *answers = (poldiff_test_answers_t *) malloc(sizeof(poldiff_test_answers_t));
+ answers->correct_added_v = string_array_to_vector(added_arr);
+ answers->correct_removed_v = string_array_to_vector(removed_arr);
+ answers->correct_unchanged_v = string_array_to_vector(unchanged_arr);
+ answers->correct_modified_v = string_array_to_vector(modified_arr);
+ return answers;
+}
+
+component_funcs_t *init_test_funcs(poldiff_get_diff_vector get_diff_vector, poldiff_get_name get_name, poldiff_get_form get_form,
+ poldiff_get_added get_added, poldiff_get_removed get_removed)
+{
+ component_funcs_t *funcs = (component_funcs_t *) malloc(sizeof(component_funcs_t));
+ funcs->get_diff_vector = get_diff_vector;
+ funcs->get_name = get_name;
+ funcs->get_form = get_form;
+ funcs->get_added = get_added;
+ funcs->get_removed = get_removed;
+ return funcs;
+}
+
+poldiff_t *init_poldiff(char *orig_base_path, char *mod_base_path)
+{
+ poldiff_t *return_diff = NULL;
+ uint32_t flags = POLDIFF_DIFF_ALL;
+ apol_policy_path_t *mod_pol_path = NULL;
+ apol_policy_path_t *orig_pol_path = NULL;
+
+ orig_pol_path = apol_policy_path_create(APOL_POLICY_PATH_TYPE_MONOLITHIC, orig_base_path, NULL);
+ if (!orig_pol_path) {
+ ERR(NULL, "%s", strerror(errno));
+ goto err;
+ }
+
+ mod_pol_path = apol_policy_path_create(APOL_POLICY_PATH_TYPE_MONOLITHIC, mod_base_path, NULL);
+ if (!mod_pol_path) {
+ ERR(NULL, "%s", strerror(errno));
+ goto err;
+ }
+
+ orig_policy = apol_policy_create_from_policy_path(orig_pol_path, 0, NULL, NULL);
+ if (!orig_policy) {
+ ERR(NULL, "%s", strerror(errno));
+ goto err;
+ }
+
+ mod_policy = apol_policy_create_from_policy_path(mod_pol_path, 0, NULL, NULL);
+ if (!mod_policy) {
+ ERR(NULL, "%s", strerror(errno));
+ goto err;
+ }
+
+ if (!(return_diff = poldiff_create(orig_policy, mod_policy, NULL, NULL))) {
+ ERR(NULL, "%s", strerror(errno));
+ goto err;
+ }
+ if (poldiff_run(return_diff, flags)) {
+ goto err;
+ }
+ apol_policy_path_destroy(&orig_pol_path);
+ apol_policy_path_destroy(&mod_pol_path);
+ return return_diff;
+ 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);
+ poldiff_destroy(&return_diff);
+ return NULL;
+}
+
+void cleanup_test(poldiff_test_answers_t * answers)
+{
+ if (answers != NULL) {
+ apol_vector_destroy(&answers->correct_added_v);
+ apol_vector_destroy(&answers->correct_unchanged_v);
+ apol_vector_destroy(&answers->correct_removed_v);
+ apol_vector_destroy(&answers->correct_modified_v);
+ free(answers);
+ }
+}
+
+int poldiff_cleanup()
+{
+ poldiff_destroy(&diff);
+ return 0;
+}
+
+int main()
+{
+ if (CU_initialize_registry() != CUE_SUCCESS) {
+ return CU_get_error();
+ }
+
+ CU_TestInfo components_tests_arr[] = {
+ {"Attributes", components_attributes_tests}
+ ,
+ {"Classes", components_class_tests}
+ ,
+ {"Commons", components_commons_tests}
+ ,
+ {"Roles", components_roles_tests}
+ ,
+ {"Users", components_users_tests}
+ ,
+ {"Bools", components_bools_tests}
+ ,
+ {"Types", components_types_tests}
+ ,
+ CU_TEST_INFO_NULL
+ };
+
+ CU_TestInfo rules_tests_arr[] = {
+ {"AV Rules", rules_avrules_tests}
+ ,
+ {"TE Rules", rules_terules_tests}
+ ,
+ {"Role Allow Rules", rules_roleallow_tests}
+ ,
+ {"Role Transition Rules", rules_roletrans_tests}
+ ,
+ CU_TEST_INFO_NULL
+ };
+
+ CU_TestInfo mls_tests_arr[] = {
+ {"Categories", mls_category_tests}
+ ,
+ {"Levels", mls_level_tests}
+ ,
+ {"Range Transitions", mls_rangetrans_tests}
+ ,
+ {"Users (MLS)", mls_user_tests}
+ ,
+ CU_TEST_INFO_NULL
+ };
+ CU_TestInfo nomls_tests_arr[] = {
+ {"Changed & Unchanged Users", nomls_tests}
+ ,
+ CU_TEST_INFO_NULL
+ };
+
+ CU_SuiteInfo suites[] = {
+ {"Components", components_test_init, poldiff_cleanup, components_tests_arr}
+ ,
+ {"Rules", rules_test_init, poldiff_cleanup, rules_tests_arr}
+ ,
+ {"MLS", mls_test_init, poldiff_cleanup, mls_tests_arr}
+ ,
+ {"Non-MLS vs. MLS Users", nomls_test_init, poldiff_cleanup, nomls_tests_arr}
+ ,
+ CU_SUITE_INFO_NULL
+ };
+
+ CU_register_suites(suites);
+ CU_basic_set_mode(CU_BRM_VERBOSE);
+ CU_basic_run_tests();
+ unsigned int num_failures = CU_get_number_of_failure_records();
+ CU_cleanup_registry();
+ return (int)num_failures;
+}
diff --git a/libpoldiff/tests/libpoldiff-tests.h b/libpoldiff/tests/libpoldiff-tests.h
new file mode 100644
index 0000000..d34c847
--- /dev/null
+++ b/libpoldiff/tests/libpoldiff-tests.h
@@ -0,0 +1,85 @@
+/**
+ * @file
+ *
+ * Header for for CUnit testing framework of libpoldiff's correctness.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef LIBPOLDIFF_TESTS
+#define LIBPOLDIFF_TESTS
+
+#include <poldiff/poldiff.h>
+#include <apol/vector.h>
+
+typedef const apol_vector_t *(*poldiff_get_diff_vector) (const poldiff_t *);
+typedef const char *(*poldiff_get_name) (const void *);
+typedef poldiff_form_e(*poldiff_get_form) (const void *);
+typedef const apol_vector_t *(*poldiff_get_added) (const void *);
+typedef const apol_vector_t *(*poldiff_get_removed) (const void *);
+
+typedef struct _test_answers
+{
+ apol_vector_t *correct_added_v;
+ apol_vector_t *correct_removed_v;
+ apol_vector_t *correct_unchanged_v;
+ apol_vector_t *correct_modified_v;
+} poldiff_test_answers_t;
+
+typedef struct _component_funcs
+{
+ poldiff_get_diff_vector get_diff_vector;
+ poldiff_get_name get_name;
+ poldiff_get_form get_form;
+ poldiff_get_added get_added;
+ poldiff_get_removed get_removed;
+} component_funcs_t;
+
+typedef enum _test_numbers
+{
+ COMPONENT = 0, RULES_AVRULE, RULES_TERULE, RULES_ROLEALLOW, RULES_ROLETRANS,
+ MLS_CATEGORY, MLS_LEVEL, MLS_RANGETRANS, MLS_USER
+} test_numbers_e;
+
+poldiff_t *init_poldiff(char *orig_base_path, char *mod_base_path);
+component_funcs_t *init_test_funcs(poldiff_get_diff_vector, poldiff_get_name, poldiff_get_form, poldiff_get_added,
+ poldiff_get_removed);
+void run_test(component_funcs_t *, poldiff_test_answers_t *, test_numbers_e);
+
+apol_vector_t *string_array_to_vector(char *[]);
+void cleanup_test(poldiff_test_answers_t *);
+char *vector_to_string(const apol_vector_t *, const char *, const char *);
+
+int compare_str(const void *s1, const void *s2, void *debug);
+poldiff_test_answers_t *init_answer_vectors(char *[], char *[], char *[], char *[]);
+void print_test_failure(apol_vector_t *, apol_vector_t *, size_t, const char *);
+
+apol_vector_t *shallow_copy_str_vec_and_sort(const apol_vector_t * v);
+
+poldiff_t *diff;
+
+apol_policy_t *orig_policy;
+apol_policy_t *mod_policy;
+
+apol_vector_t *added_v;
+apol_vector_t *removed_v;
+apol_vector_t *modified_v;
+apol_vector_t *modified_name_only_v;
+
+#endif
diff --git a/libpoldiff/tests/mls-tests.c b/libpoldiff/tests/mls-tests.c
new file mode 100644
index 0000000..ad03feb
--- /dev/null
+++ b/libpoldiff/tests/mls-tests.c
@@ -0,0 +1,635 @@
+/**
+ * @file
+ *
+ * Test the libpoldiff's correctness for MLS.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "libpoldiff-tests.h"
+#include "mls-tests.h"
+#include "policy-defs.h"
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+#include <poldiff/poldiff.h>
+#include <apol/policy.h>
+#include <apol/vector.h>
+#include <apol/util.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *unchanged_users_mls[] = {
+ /* 13.0 */
+ "placeholder_u",
+ "reyna_u",
+ NULL
+};
+
+/* these aren't real tests, but the arrays must be declared anyways */
+char *added_users_mls[] = { NULL };
+char *removed_users_mls[] = { NULL };
+
+/* These strings are always in the same order: added, removed, modified
+ *
+ * Modified User fields are always in this order:
+ * d[...] represents a change in the default level
+ * range[...]
+ * roles[...]
+ */
+char *modified_users_mls[] = {
+ /* 13.3.03 */
+ "su_u: d[+s2 -s1]",
+ /* 13.3.04 */
+ "cyn_u: d[s1 +c2] range[*{s1:c1 c2 +c3}]",
+ /* 13.3.05 */
+ "devona_u: d[s1 -c1]",
+ /* 13.3.06 */
+ "danika_u: d[s1 +c3 -c1] range[*{s1:c1 c2 +c3}]",
+ /* 13.3.07 */
+ "mehnlo_u: range[+{s4:c4}]",
+ /* 13.3.08 */
+ "meloni_u: range[-{s4:c4 c5}]",
+ /* 13.3.09 */
+ "eve_u: range[+{s6} -{s0}]",
+ /* 13.3.10 */
+ "nika_u: range[*{s1:c1 c2 +c3} *{s2:c1 c2 c3 +c4}]",
+ /* 13.3.11 */
+ "koss_u: range[*{s3:c4 -c5} *{s4:c4 -c5} *{s5:c4 -c5}]",
+ /* 13.3.12 */
+ "kihm_u: range[+{s6:c1 c2 c3 c4 c5 c6} -{s0:c0 c1 c2} *{s1:c1 c2 +c3} *{s2:c1 c2 c3 c4 c5 -c0} *{s3:c1 c4 c5 +c6} *{s5:c1 c2 c3 c4 c5 +c6 -c0}]",
+ /* 13.3.13 */
+ "aidan_u: range[*{s1:c1 +c3 -c2} *{s2:c1 c3 -c2}]",
+ /* 13.3.14 */
+ "timera_u: d[+s2 -s1] roles[-admin_r]",
+ /* 13.3.15 */
+ "sheena_u: range[+{s4:c5} *{s2:+c5} *{s3:+c5}] roles[+user_r]",
+ /* 13.3.16 */
+ "chiyo_u: d[+s2 -s1] range[+{s4:c5} *{s2:+c5} *{s3:+c5}]",
+ /* 13.3.17 -- separate test -- see nomls-tests.c */
+ /* 13.3.18 -- separate test -- see nomls-tests.c */
+
+ /* 13.3.19 */
+ "jamei_u: d[+s2 -s1] range[+{s4:c5} *{s2:+c5} *{s3:+c5}] roles[-aquarium_r]",
+ NULL
+};
+
+char *unchanged_rangetrans[] = {
+/* 07.0 */
+ "range_transition placeholder_t oak_t : file s2",
+ NULL
+};
+
+char *added_rangetrans[] = {
+/* 07.1 */
+ "range_transition bear_t stone_t : gc s1",
+ "range_transition log_t bear_t : ipc s2",
+ "range_transition log_t file_t : fd s1",
+ "range_transition rock_t stone_t : dir s3",
+ NULL
+};
+char *removed_rangetrans[] = {
+
+/* 07.2 */
+ "range_transition potato_t daikon_t : dir s0:c2",
+ "range_transition rock_t stone_t : file s3",
+ "range_transition bear_t file_t : msg s1 - s5",
+ "range_transition bear_t log_t : msg s1 - s5",
+ "range_transition trout_t bear_t : pax s1",
+ NULL
+};
+
+/* m{...} represents a change in the minimum set of the transition and is always first,
+ * the rest of string is in the same order: added, removed, modified*/
+char *modified_rangetrans[] = {
+/* 07.3.0 */
+ "range_transition file_t system_t : process +{s2:c1} ",
+/* 07.3.1 */
+ "range_transition tiger_t trout_t : node m{+c1 +c2} -{s0:c1 c2}",
+/* 07.3.2 */
+ "range_transition glass_t log_t : netif +{s6:c1 c2 c3 c4 c5} -{s0:c1 c2} *{s1:c1 c2 +c3}",
+/* 07.3.3 */
+ "range_transition pine_t holly_t : lnk_file m{+c5} *{s3:c4 +c5}",
+/* 07.3.4 */
+ "range_transition rock_t finch_t : chr_file m{-c5} *{s3:c4 -c5}",
+/* 07.3.5 */
+ "range_transition trout_t dirt_t : blk_file m{-c0} *{s2:c1 c2 c3 c4 c5 -c0} *{s3:c1 c4 c5 +c6} *{s5:c1 c2 c3 c4 c5 +c6 -c0}",
+/* 07.3.6 */
+ "range_transition tiger_t stone_t : sock_file m{+c3} *{s1:c1 c2 +c3}",
+/* 07.3.7 */
+ "range_transition firefly_t log_t : fd m{+c5}",
+/* 07.3.8 */
+ "range_transition file_t trout_t : process m{-c2} *{s1:c1 c2 +c3}",
+/* 07.3.9 */
+ "range_transition pine_t oak_t : lnk_file m{+c5 -c0} *{s2:c1 c2 c3 c4 c5 -c0} *{s5:c1 c2 c3 c4 c5 -c0}",
+ NULL
+};
+char *added_rangetrans_type[] = {
+/* 07.4.0 */
+ "range_transition pipe_t rock_t : file s3",
+/* 07.4.1 */
+ "range_transition glass_t pipe_t : process s1",
+/* 07.4.2 */
+ "range_transition hippo_t file_t : msg s1 - s5",
+ "range_transition hippo_t log_t : msg s1 - s5",
+ "range_transition pipe_t oak_t : fifo_file s2 - s3:c5",
+/* 07.4.3 */
+ "range_transition lion_t pipe_t : msg s1 - s5",
+ "range_transition pine_t pipe_t : sem s1 - s4:c4.c5",
+ "range_transition tiger_t pipe_t : msg s1 - s5",
+/* 07.4.4 */
+ "range_transition pipe_t acorn_t : file s2",
+/* 07.4.5 */
+ "range_transition hippo_t pipe_t : msg s1 - s5",
+/* needs to be added */
+ "range_transition trout_t hippo_t : pax s1",
+ NULL
+};
+char *removed_rangetrans_type[] = {
+/* 07.5.0 */
+ "range_transition koala_t stone_t : gc s1",
+/* 07.5.1 */
+ "range_transition log_t koala_t : ipc s2",
+/* 07.5.2 */
+ "range_transition bass_t bear_t : pax s1",
+ "range_transition bass_t lion_t : pax s1",
+ "range_transition bass_t log_t : dir s3:c1",
+ "range_transition bass_t tiger_t : pax s1",
+/* 07.5.3 */
+ "range_transition firefly_t bass_t : passwd s2:c1.c5 - s5:c1.c5",
+/* "range_transition trout_t bear_t : pax s1", this rule is "simply removed" so its in the
+ normal removed array */
+/* 07.5.4 */
+ "range_transition bass_t koala_t : shm s0",
+/* 07.5.5 is a duplicate of the first rule in 07.5.2 */
+
+ NULL
+};
+
+char *unchanged_levels[] = {
+/* 06.0 */
+ "s4",
+ NULL
+};
+char *added_levels[] = {
+/* 06.1 */
+ "s6",
+ NULL
+};
+char *removed_levels[] = {
+/* 06.2 */
+ "s0",
+ NULL
+};
+char *modified_levels[] = {
+/* 06.3.0 */
+ "s3 +c6",
+/* 06.3.1 */
+ "s2 -c0",
+/* 06.3.2 */
+ "s5 +c6 -c0",
+/* 06.3.3 */
+ "s1 +c3",
+ NULL
+};
+
+char *unchanged_categories[] = {
+ /* 03.0 */
+ "c1", "c2", "c3", "c4", "c5",
+ NULL
+};
+char *added_categories[] = {
+ /* 03.1 */
+ "c6",
+ NULL
+};
+char *removed_categories[] = {
+ /* 03.2 */
+ "c0",
+ NULL
+};
+
+char *modified_categories[] = { NULL };
+
+int mls_test_init()
+{
+ if (!(diff = init_poldiff(MLS_ORIG_POLICY, MLS_MOD_POLICY))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+void build_category_vecs()
+{
+ char *str = NULL;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_cat_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); ++i) {
+ item = apol_vector_get_element(v, i);
+ const char *name = poldiff_cat_get_name(item);
+ str = strdup(name);
+ poldiff_form_e form = poldiff_cat_get_form(item);
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ default:
+ // can never get here
+ assert(0);
+ }
+ str = NULL;
+ }
+}
+
+char *level_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ poldiff_level_t *level = (poldiff_level_t *) arg;
+ char *str = NULL, *cat = NULL;
+ size_t i, str_len = 0;
+ const char *name = poldiff_level_get_name(level);
+ if (name) {
+ apol_str_appendf(&str, &str_len, "%s", name);
+ if (show_changes) {
+ if (form == POLDIFF_FORM_MODIFIED) {
+ const apol_vector_t *added_cats = poldiff_level_get_added_cats(level);
+ for (i = 0; i < apol_vector_get_size(added_cats); ++i) {
+ cat = apol_vector_get_element(added_cats, i);
+ apol_str_appendf(&str, &str_len, " +%s", cat);
+ }
+ const apol_vector_t *removed_cats = poldiff_level_get_removed_cats(level);
+ for (i = 0; i < apol_vector_get_size(removed_cats); ++i) {
+ cat = apol_vector_get_element(removed_cats, i);
+ apol_str_appendf(&str, &str_len, " -%s", cat);
+ }
+ }
+ }
+ }
+ if (str)
+ apol_str_trim(str);
+ return str;
+}
+
+char *modified_mls_range_to_string(const poldiff_range_t * range)
+{
+ char *str = NULL;
+ apol_vector_t *levels = NULL;
+ if (!(levels = poldiff_range_get_levels(range)))
+ goto err;
+ size_t i, str_len = 0;
+ char *min_set_str = NULL;
+ size_t min_set_str_len = 0;
+
+ apol_vector_t *min_set_added = poldiff_range_get_min_added_cats(range);
+ apol_vector_t *min_set_removed = poldiff_range_get_min_removed_cats(range);
+ size_t num_min_added = apol_vector_get_size(min_set_added);
+ size_t num_min_removed = apol_vector_get_size(min_set_removed);
+ if (min_set_added && num_min_added > 0) {
+ char *min_set_added_str = vector_to_string(min_set_added, "", " +");
+ apol_str_appendf(&min_set_str, &min_set_str_len, "%s", min_set_added_str);
+ free(min_set_added_str);
+ }
+ if (min_set_removed && num_min_removed > 0) {
+ char *min_set_removed_str = vector_to_string(min_set_removed, "", " -");
+ apol_str_appendf(&min_set_str, &min_set_str_len, "%s%s", num_min_added > 0 ? " " : "", min_set_removed_str);
+ free(min_set_removed_str);
+ }
+ if (num_min_added || num_min_removed) {
+ char *tmp = strdup(min_set_str);
+ free(min_set_str);
+ min_set_str = NULL;
+ min_set_str_len = 0;
+ apol_str_appendf(&min_set_str, &min_set_str_len, "m{%s} ", tmp);
+ free(tmp);
+ }
+ if (min_set_str) {
+ apol_str_appendf(&str, &str_len, "%s", min_set_str);
+ free(min_set_str);
+ }
+
+ for (i = 0; i < apol_vector_get_size(levels); ++i) {
+ poldiff_level_t *level = apol_vector_get_element(levels, i);
+ poldiff_form_e form = poldiff_level_get_form(level);
+ const char *level_str = poldiff_level_get_name(level);
+ char *sep = NULL, *add_sep = " +", *remove_sep = " -";
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ sep = "+";
+ add_sep = " ";
+ break;
+ case POLDIFF_FORM_REMOVED:
+ sep = "-";
+ remove_sep = " ";
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ sep = "*";
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ const apol_vector_t *unmod_cats = poldiff_level_get_unmodified_cats(level);
+ const apol_vector_t *added_cats = poldiff_level_get_added_cats(level);
+ const apol_vector_t *removed_cats = poldiff_level_get_removed_cats(level);
+ size_t num_unmod_cats = apol_vector_get_size(unmod_cats);
+ size_t num_added_cats = apol_vector_get_size(added_cats);
+ size_t num_removed_cats = apol_vector_get_size(removed_cats);
+ size_t num_cats = num_unmod_cats + num_added_cats + num_removed_cats;
+ char *unmod_cats_str = vector_to_string(unmod_cats, "", " ");
+ char *added_cats_str = vector_to_string(added_cats, num_unmod_cats > 0 ? " " : "", add_sep);
+ char *removed_cats_str = vector_to_string(removed_cats, num_added_cats > 0 ||
+ num_unmod_cats > 0 ? " " : "", remove_sep);
+ apol_str_appendf(&str, &str_len, "%s{%s%s%s%s%s} ", sep, level_str, num_cats > 0 ? ":" : "", unmod_cats_str,
+ added_cats_str, removed_cats_str);
+ free(unmod_cats_str);
+ free(added_cats_str);
+ free(removed_cats_str);
+ }
+ apol_str_trim(str);
+ return str;
+ err:
+ return NULL;
+}
+
+char *rangetrans_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ char *str = NULL;
+ size_t str_len = 0;
+ poldiff_range_trans_t *rt = (poldiff_range_trans_t *) arg;
+ const poldiff_range_t *range = poldiff_range_trans_get_range(rt);
+ const apol_mls_range_t *mod_range = poldiff_range_get_modified_range(range);
+ const apol_mls_range_t *orig_range = poldiff_range_get_original_range(range);
+ char *range_str = NULL;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ case POLDIFF_FORM_ADD_TYPE:
+ range_str = apol_mls_range_render(mod_policy, mod_range);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ case POLDIFF_FORM_REMOVE_TYPE:
+ range_str = apol_mls_range_render(orig_policy, orig_range);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ range_str = modified_mls_range_to_string(range);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ const char *source_type = poldiff_range_trans_get_source_type(rt);
+ const char *target_type = poldiff_range_trans_get_target_type(rt);
+ const char *target_class = poldiff_range_trans_get_target_class(rt);
+ if (show_changes) {
+ apol_str_appendf(&str, &str_len, "range_transition %s %s : %s %s", source_type, target_type, target_class,
+ range_str);
+ } else {
+ apol_str_appendf(&str, &str_len, "range_transition %s %s : %s", source_type, target_type, target_class);
+ }
+ free(range_str);
+ return str;
+}
+
+void build_rangetrans_vecs()
+{
+ apol_vector_t *added_rangetrans_type_v = apol_vector_create(free);
+ apol_vector_t *removed_rangetrans_type_v = apol_vector_create(free);
+ apol_vector_t *correct_added_rangetrans_type_v = string_array_to_vector(added_rangetrans_type);
+ apol_vector_t *correct_removed_rangetrans_type_v = string_array_to_vector(removed_rangetrans_type);
+
+ char *str = NULL, *name_only = NULL;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_range_trans_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); ++i) {
+ item = apol_vector_get_element(v, i);
+ poldiff_form_e form = poldiff_range_trans_get_form(item);
+ str = rangetrans_to_string(item, form, 1);
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_ADD_TYPE:
+ apol_vector_append(added_rangetrans_type_v, str);
+ break;
+ case POLDIFF_FORM_REMOVE_TYPE:
+ apol_vector_append(removed_rangetrans_type_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = rangetrans_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+ int test_result;
+ size_t first_diff = 0;
+ apol_vector_sort(added_rangetrans_type_v, compare_str, NULL);
+ apol_vector_sort(correct_added_rangetrans_type_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(added_rangetrans_type_v, correct_added_rangetrans_type_v, compare_str, NULL,
+ &first_diff));
+ if (test_result) {
+ print_test_failure(added_rangetrans_type_v, correct_added_rangetrans_type_v, first_diff, "Added Due to Types");
+ }
+ apol_vector_sort(removed_rangetrans_type_v, compare_str, NULL);
+ apol_vector_sort(correct_removed_rangetrans_type_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(removed_rangetrans_type_v, correct_removed_rangetrans_type_v, compare_str, NULL,
+ &first_diff));
+ if (test_result) {
+ print_test_failure(removed_rangetrans_type_v, correct_removed_rangetrans_type_v, first_diff,
+ "Removed Due to Types");
+ }
+ apol_vector_destroy(&added_rangetrans_type_v);
+ apol_vector_destroy(&correct_added_rangetrans_type_v);
+ apol_vector_destroy(&removed_rangetrans_type_v);
+ apol_vector_destroy(&correct_removed_rangetrans_type_v);
+
+}
+
+void build_level_vecs()
+{
+ char *str = NULL, *name_only = NULL;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_level_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); ++i) {
+ item = apol_vector_get_element(v, i);
+ poldiff_form_e form = poldiff_cat_get_form(item);
+ str = level_to_string(item, form, 1);
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = level_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+}
+
+char *mls_user_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ poldiff_user_t *u = (poldiff_user_t *) arg;
+ char *str = NULL, *dlevel_str = NULL, *range_str = NULL, *roles_str = NULL;
+ size_t str_len = 0, dlevel_str_len = 0, range_str_len = 0, roles_str_len = 0;
+ const poldiff_range_t *range = poldiff_user_get_range(u);
+ const poldiff_level_t *orig_level = poldiff_user_get_original_dfltlevel(u);
+ const poldiff_level_t *mod_level = poldiff_user_get_modified_dfltlevel(u);
+ poldiff_form_e orig_form = poldiff_level_get_form(orig_level);
+ poldiff_form_e mod_form = poldiff_level_get_form(mod_level);
+ char *orig_level_str = level_to_string(orig_level, orig_form, 1);
+ char *mod_level_str = level_to_string(mod_level, mod_form, 1);
+ //change of default sensitivity
+ if (mod_level_str && orig_level_str) {
+ apol_str_appendf(&dlevel_str, &dlevel_str_len, "d[+%s -%s] ", mod_level_str, orig_level_str);
+ }
+ //change of default category within a sensitivity
+ else if (!mod_level_str && orig_level_str) {
+ apol_str_appendf(&dlevel_str, &dlevel_str_len, "d[%s] ", orig_level_str);
+ } else if (!orig_level_str && mod_level_str) {
+ //this should never happen
+ CU_ASSERT_FALSE(1);
+ }
+ if ((range_str = modified_mls_range_to_string(range)) != NULL) {
+ char *tmp = strdup(range_str);
+ free(range_str);
+ range_str = NULL;
+ range_str_len = 0;
+ apol_str_appendf(&range_str, &range_str_len, "range[%s] ", tmp);
+ free(tmp);
+ }
+ char *added_roles_str = vector_to_string(poldiff_user_get_added_roles(u), "", " +");
+ char *removed_roles_str = vector_to_string(poldiff_user_get_removed_roles(u), "", " -");
+ if (strlen(added_roles_str) > 0 || strlen(removed_roles_str) > 0) {
+ apol_str_appendf(&roles_str, &roles_str_len, "roles[%s%s] ", added_roles_str ? added_roles_str : "",
+ removed_roles_str ? removed_roles_str : "");
+ }
+ const char *user_name = poldiff_user_get_name(u);
+ if (show_changes) {
+ apol_str_appendf(&str, &str_len, "%s: %s%s%s", user_name, dlevel_str ? dlevel_str : "", range_str ? range_str : "",
+ roles_str ? roles_str : "");
+ } else {
+ apol_str_appendf(&str, &str_len, "%s", user_name);
+ }
+
+ free(range_str);
+ free(roles_str);
+ free(dlevel_str);
+ free(mod_level_str);
+ free(orig_level_str);
+ free(added_roles_str);
+ free(removed_roles_str);
+ return str;
+}
+
+void build_user_vecs()
+{
+ char *str = NULL, *name_only;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_user_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); ++i) {
+ item = apol_vector_get_element(v, i);
+ poldiff_form_e form = poldiff_cat_get_form(item);
+ str = mls_user_to_string(item, form, 1);
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = mls_user_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ str = NULL;
+ }
+}
+
+void mls_category_tests()
+{
+ test_numbers_e test_num = MLS_CATEGORY;
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_categories, removed_categories, unchanged_categories, modified_categories);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void mls_rangetrans_tests()
+{
+ test_numbers_e test_num = MLS_RANGETRANS;
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_rangetrans, removed_rangetrans, unchanged_rangetrans, modified_rangetrans);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void mls_level_tests()
+{
+ test_numbers_e test_num = MLS_LEVEL;
+ poldiff_test_answers_t *answers = init_answer_vectors(added_levels, removed_levels, unchanged_levels, modified_levels);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void mls_user_tests()
+{
+ test_numbers_e test_num = MLS_USER;
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_users_mls, removed_users_mls, unchanged_users_mls, modified_users_mls);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
diff --git a/libpoldiff/tests/mls-tests.h b/libpoldiff/tests/mls-tests.h
new file mode 100644
index 0000000..8922ebb
--- /dev/null
+++ b/libpoldiff/tests/mls-tests.h
@@ -0,0 +1,39 @@
+/**
+ * @file
+ *
+ * Header file for libpoldiff's correctness of MLS.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MLS_TEST
+#define MLS_TEST
+int mls_test_init();
+int mls_test_cleanup();
+
+void mls_category_tests();
+void mls_user_tests();
+void mls_rangetrans_tests();
+void mls_level_tests();
+void build_category_vecs();
+void build_rangetrans_vecs();
+void build_level_vecs();
+void build_user_vecs();
+
+#endif
diff --git a/libpoldiff/tests/nomls-tests.c b/libpoldiff/tests/nomls-tests.c
new file mode 100644
index 0000000..da7dad2
--- /dev/null
+++ b/libpoldiff/tests/nomls-tests.c
@@ -0,0 +1,139 @@
+/**
+ * @file
+ *
+ * Test the libpoldiff's correctness for MLS versus non-MLS policies.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "libpoldiff-tests.h"
+#include "nomls-tests.h"
+#include "policy-defs.h"
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+#include <poldiff/poldiff.h>
+#include <apol/util.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *nomls_unchanged_users[] = {
+/* 13.3.17 */
+ "placeholder_u",
+ "su_u",
+ "cyn_u",
+ "devona_u",
+ "danika_u",
+ "mehnlo_u",
+ "meloni_u",
+ "eve_u",
+ "nika_u",
+ "koss_u",
+ "kihm_u",
+ "aidan_u",
+ "chiyo_u",
+ "reyna_u",
+ NULL
+};
+apol_vector_t *unchanged_users_v;
+apol_vector_t *changed_users_v;
+
+char *nomls_changed_users[] = {
+/* 13.3.18 */
+ "timera_u -admin_r",
+ "sheena_u +user_r",
+ "jamei_u -aquarium_r",
+ NULL
+};
+
+int nomls_test_init()
+{
+ if (!(diff = init_poldiff(NOMLS_ORIG_POLICY, NOMLS_MOD_POLICY))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static void build_nomls_vecs()
+{
+ const void *item;
+ const apol_vector_t *v = NULL;
+ size_t i, str_len = 0;
+ char *str = NULL;
+ v = poldiff_get_user_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); ++i) {
+ item = apol_vector_get_element(v, i);
+ poldiff_user_t *u = (poldiff_user_t *) item;
+ const char *name = poldiff_user_get_name(u);
+ const apol_vector_t *added_roles = poldiff_user_get_added_roles(u);
+ const apol_vector_t *removed_roles = poldiff_user_get_removed_roles(u);
+ if (apol_vector_get_size(added_roles) == 0 && apol_vector_get_size(removed_roles) == 0) {
+ apol_vector_append(unchanged_users_v, strdup(name));
+ } else {
+ char *added_roles_str = vector_to_string(added_roles, "", " +");
+ char *removed_roles_str = vector_to_string(removed_roles, "-", " ");
+ apol_str_appendf(&str, &str_len, "%s %s%s", name, added_roles_str, removed_roles_str);
+ free(added_roles_str);
+ free(removed_roles_str);
+ apol_str_trim(str);
+ apol_vector_append(changed_users_v, str);
+ str = NULL;
+ str_len = 0;
+ }
+ }
+}
+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);
+
+}
diff --git a/libpoldiff/tests/nomls-tests.h b/libpoldiff/tests/nomls-tests.h
new file mode 100644
index 0000000..3232fd0
--- /dev/null
+++ b/libpoldiff/tests/nomls-tests.h
@@ -0,0 +1,33 @@
+/**
+ * @file
+ *
+ * Header file for libpoldiff's correctness of MLS versus non-MLS policies.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef NOMLS_TEST
+#define NOMLS_TEST
+int nomls_test_init();
+int nomls_test_cleanup();
+
+void nomls_tests();
+void nomls_unchanged_test();
+
+#endif
diff --git a/libpoldiff/tests/policy-defs.h b/libpoldiff/tests/policy-defs.h
new file mode 100644
index 0000000..37a925b
--- /dev/null
+++ b/libpoldiff/tests/policy-defs.h
@@ -0,0 +1,44 @@
+/**
+ * @file
+ *
+ * Header file defining location of test policies.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef POLICY_DEFS
+#define POLICY_DEFS
+
+#include <config.h>
+
+#define POLICY_ROOT TEST_POLICIES "/setools-3.2/sediff"
+
+#define COMPONENTS_ORIG_POLICY (POLICY_ROOT "/testing-component-orig.conf")
+#define COMPONENTS_MOD_POLICY (POLICY_ROOT "/testing-component-mod.conf")
+
+#define RULES_ORIG_POLICY (POLICY_ROOT "/testing-rules-orig.conf")
+#define RULES_MOD_POLICY (POLICY_ROOT "/testing-rules-mod.conf")
+
+#define MLS_ORIG_POLICY (POLICY_ROOT "/testing-mls-orig.conf")
+#define MLS_MOD_POLICY (POLICY_ROOT "/testing-mls-mod.conf")
+
+#define NOMLS_ORIG_POLICY (POLICY_ROOT "/testing-mls-orig.conf")
+#define NOMLS_MOD_POLICY (POLICY_ROOT "/testing-mls-mod-nomls.conf")
+
+#endif
diff --git a/libpoldiff/tests/rules-tests.c b/libpoldiff/tests/rules-tests.c
new file mode 100644
index 0000000..c7b7ef1
--- /dev/null
+++ b/libpoldiff/tests/rules-tests.c
@@ -0,0 +1,914 @@
+/**
+ * @file
+ *
+ * Test the libpoldiff's correctness for rules.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <config.h>
+
+#include "libpoldiff-tests.h"
+#include "rules-tests.h"
+#include "policy-defs.h"
+#include <CUnit/Basic.h>
+#include <CUnit/TestDB.h>
+
+#include <poldiff/poldiff.h>
+#include <apol/policy.h>
+#include <apol/vector.h>
+#include <apol/util.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+static apol_vector_t *added_type_rules_v;
+static apol_vector_t *removed_type_rules_v;
+static apol_vector_t *correct_added_type_rules_v;
+static apol_vector_t *correct_removed_type_rules_v;
+
+char *unchanged_avrules[] = {
+/* 01.0 */
+ "allow placeholder_t placeholder_t : file read",
+ "auditallow potato_t pine_t : dir setattr",
+ NULL
+};
+char *added_avrules[] = {
+/* 01.1 */
+ "allow bear_t oak_t : fifo_file write",
+ "allow rock_t log_t : file getattr",
+ "allow tiger_t bear_t : file execute",
+ "auditallow system_t log_t : netif udp_recv",
+ "neverallow lion_t bear_t : file execute",
+ NULL
+};
+char *removed_avrules[] = {
+/* 01.2 */
+ "allow rock_t log_t : dir search",
+ "auditallow system_t log_t : node udp_recv",
+ "allow bear_t bear_t : dir search",
+ "allow bear_t birch_t : fd use",
+ "allow bear_t daikon_t : fd use",
+ "allow bear_t glass_t : file getattr",
+ "allow bear_t holly_t : fd use",
+ "allow bear_t oak_t : fd use",
+ "allow bear_t pine_t : fd use",
+ "allow bear_t potato_t : fd use",
+ NULL
+};
+
+char *modified_avrules[] = {
+/*01.3.0*/
+ "allow firefly_t file_t : file execute +lock",
+/*01.3.1*/
+ "dontaudit bass_t stone_t : dir read search -getattr",
+ "dontaudit trout_t stone_t : dir read search -getattr",
+/*01.3.2*/
+ "allow potato_t daikon_t : file getattr ioctl setattr +write -read",
+ NULL
+};
+
+char *added_type_avrules[] = {
+/* 01.4.00 */
+ "auditallow pipe_t bear_t : blk_file ioctl",
+/* 01.4.01 */
+ "auditallow dirt_t hippo_t : sock_file read",
+/* 01.4.02 */
+ "allow hippo_t birch_t : fd use",
+ "allow hippo_t daikon_t : fd use",
+ "allow hippo_t glass_t : file getattr",
+ "allow hippo_t holly_t : fd use",
+ "allow hippo_t oak_t : fd use",
+ "allow hippo_t pine_t : fd use",
+ "allow hippo_t potato_t : fd use",
+/* 01.4.03 */
+ "allow system_t pipe_t : file getattr ioctl read",
+ "neverallow bear_t pipe_t : process transition",
+ "neverallow lion_t pipe_t : process transition",
+ "neverallow tiger_t pipe_t : process transition",
+/* 01.4.04 */
+ "allow hippo_t pipe_t : lnk_file write",
+/* 01.4.05 */
+ "neverallow hippo_t pipe_t : process transition",
+/* 01.4.06 */
+ "allow hippo_t hippo_t : file getattr",
+/* 01.4.07 */
+ "allow hippo_t hippo_t : dir search",
+/* 01.4.08 */
+ "neverallow hippo_t finch_t : dir add_name",
+/*"neverallow pipe_t finch_t : dir add_name",*/
+ "neverallow pipe_t potato_t : lnk_file write",
+ "neverallow pipe_t system_t : lnk_file write",
+ "neverallow pipe_t bass_t : lnk_file write",
+ "neverallow pipe_t bear_t : lnk_file write",
+ "neverallow pipe_t birch_t : lnk_file write",
+ "neverallow pipe_t daikon_t : lnk_file write",
+ "neverallow pipe_t dirt_t : lnk_file write",
+ "neverallow pipe_t finch_t : lnk_file write",
+ "neverallow pipe_t firefly_t : lnk_file write",
+ "neverallow pipe_t glass_t : lnk_file write",
+ "neverallow pipe_t holly_t : lnk_file write",
+ "neverallow pipe_t lion_t : lnk_file write",
+ "neverallow pipe_t oak_t : lnk_file write",
+ "neverallow pipe_t pine_t : lnk_file write",
+ "neverallow pipe_t placeholder_t : lnk_file write",
+ "neverallow pipe_t rock_t : lnk_file write",
+ "neverallow pipe_t stone_t : lnk_file write",
+ "neverallow pipe_t tiger_t : lnk_file write",
+ "neverallow pipe_t trout_t : lnk_file write",
+/*01.4.09*/
+ "neverallow birch_t hippo_t : lnk_file write",
+ "neverallow daikon_t hippo_t : lnk_file write",
+ "neverallow dirt_t hippo_t : lnk_file write",
+ "neverallow file_t hippo_t : lnk_file write",
+ "neverallow glass_t hippo_t : lnk_file write",
+ "neverallow holly_t hippo_t : lnk_file write",
+ "neverallow lion_t pipe_t : file execute",
+ "neverallow log_t hippo_t : lnk_file write",
+ "neverallow oak_t hippo_t : lnk_file write",
+ "neverallow pine_t hippo_t : lnk_file write",
+ "neverallow potato_t hippo_t : lnk_file write",
+ "neverallow placeholder_t hippo_t : lnk_file write",
+ "neverallow rock_t hippo_t : lnk_file write",
+ "neverallow stone_t hippo_t : lnk_file write",
+ "neverallow system_t hippo_t : lnk_file write",
+/* 01.4.10 */
+ "neverallow pipe_t hippo_t : lnk_file write",
+/* 01.4.11 */
+ "neverallow hippo_t log_t : file execute",
+ "neverallow pipe_t log_t : file execute",
+/* 01.4.12 */
+ "neverallow placeholder_t hippo_t : fd use",
+ "neverallow placeholder_t pipe_t : fd use",
+/*********** NEED TO BE ADDED TO DOCUMENT *******/
+ "neverallow bass_t pipe_t : process transition",
+ "neverallow finch_t pipe_t : process transition",
+ "neverallow firefly_t pipe_t : process transition",
+ "neverallow hippo_t file_t : process transition",
+ "neverallow hippo_t log_t : process transition",
+ "neverallow trout_t pipe_t : process transition",
+ NULL
+};
+char *removed_type_avrules[] = {
+/* 01.5.00 */
+ "allow koala_t oak_t : fifo_file write",
+/* 01.5.01 */
+ "allow tiger_t koala_t : file execute",
+/* 01.5.02 */
+/*"allow bear_t glass_t : file getattr",
+BEAR_T IS NO LONGER MAMMAL, THIS RULES DOESN'T APPLY*/
+ "allow turnip_t dirt_t : dir search",
+ "neverallow koala_t file_t : process transition",
+ "neverallow koala_t log_t : process transition",
+/* 01.5.03 */
+ "allow bear_t turnip_t : fd use",
+ "allow lion_t turnip_t : fd use",
+ "allow stone_t turnip_t : blk_file write",
+ "allow tiger_t turnip_t : fd use",
+/* 01.5.04 */
+ "allow koala_t turnip_t : lnk_file read",
+/* 01.5.05
+"allow bear_t turnip_t : fd use",
+WRONG
+*/
+/* 01.5.06 */
+ "allow turnip_t turnip_t : fd use",
+/* 01.5.07 */
+/*"allow bear_t bear_t : dir search",
+BEAR_T IS NO LONGER MAMMAL, THIS RULE DOESNT APPLY*/
+/* 01.5.08 */
+ "neverallow koala_t finch_t : dir add_name",
+ "neverallow turnip_t finch_t : dir add_name",
+ "neverallow turnip_t potato_t : lnk_file write",
+ "neverallow turnip_t system_t : lnk_file write",
+ "neverallow turnip_t bass_t : lnk_file write",
+ "neverallow turnip_t bear_t : lnk_file write",
+ "neverallow turnip_t birch_t : lnk_file write",
+ "neverallow turnip_t daikon_t : lnk_file write",
+ "neverallow turnip_t dirt_t : lnk_file write",
+ "neverallow turnip_t finch_t : lnk_file write",
+ "neverallow turnip_t firefly_t : lnk_file write",
+ "neverallow turnip_t glass_t : lnk_file write",
+ "neverallow turnip_t holly_t : lnk_file write",
+ "neverallow turnip_t lion_t : lnk_file write",
+ "neverallow turnip_t oak_t : lnk_file write",
+ "neverallow turnip_t pine_t : lnk_file write",
+ "neverallow turnip_t placeholder_t : lnk_file write",
+ "neverallow turnip_t rock_t : lnk_file write",
+ "neverallow turnip_t stone_t : lnk_file write",
+ "neverallow turnip_t tiger_t : lnk_file write",
+ "neverallow turnip_t trout_t : lnk_file write",
+/* 01.5.09 */
+ "neverallow birch_t koala_t : lnk_file write",
+ "neverallow birch_t turnip_t : lnk_file write",
+ "neverallow daikon_t koala_t : lnk_file write",
+ "neverallow daikon_t turnip_t : lnk_file write",
+ "neverallow dirt_t koala_t : lnk_file write",
+ "neverallow dirt_t turnip_t : lnk_file write",
+ "neverallow file_t koala_t : lnk_file write",
+ "neverallow file_t turnip_t : lnk_file write",
+ "neverallow glass_t koala_t : lnk_file write",
+ "neverallow glass_t turnip_t : lnk_file write",
+ "neverallow holly_t koala_t : lnk_file write",
+ "neverallow holly_t turnip_t : lnk_file write",
+ "neverallow lion_t koala_t : file execute",
+ "neverallow log_t koala_t : lnk_file write",
+ "neverallow log_t turnip_t : lnk_file write",
+ "neverallow oak_t koala_t : lnk_file write",
+ "neverallow oak_t turnip_t : lnk_file write",
+ "neverallow placeholder_t koala_t : lnk_file write",
+ "neverallow placeholder_t turnip_t : lnk_file write",
+ "neverallow pine_t koala_t : lnk_file write",
+ "neverallow pine_t turnip_t : lnk_file write",
+ "neverallow potato_t koala_t : lnk_file write",
+ "neverallow potato_t turnip_t : lnk_file write",
+ "neverallow rock_t koala_t : lnk_file write",
+ "neverallow rock_t turnip_t : lnk_file write",
+ "neverallow stone_t koala_t : lnk_file write",
+ "neverallow stone_t turnip_t : lnk_file write",
+ "neverallow system_t koala_t : lnk_file write",
+ "neverallow system_t turnip_t : lnk_file write",
+/* 01.5.10 */
+ "neverallow turnip_t koala_t : lnk_file write",
+ "neverallow turnip_t turnip_t : lnk_file write",
+/* 01.5.11 */
+ "neverallow koala_t log_t : file execute",
+ "neverallow turnip_t log_t : file execute",
+/* 01.5.12 */
+ "neverallow placeholder_t koala_t : fd use",
+ "neverallow placeholder_t turnip_t : fd use",
+ NULL
+};
+
+char *unchanged_roleallowrules[] = {
+/* 09.0*/
+ "allow admin_r staff_r user_r",
+ "allow deity_r { admin_r aquarium_r garden_r guest_r intern_r lumberjack_r mammal_r placeholder_r staff_r user_r zoo_r }",
+ "allow mammal_r intern_r user_r",
+ "allow placeholder_r staff_r",
+ NULL
+};
+char *added_roleallowrules[] = {
+/* 09.1 */
+ "allow intern_r user_r",
+ NULL
+};
+char *removed_roleallowrules[] = {
+/* 09.2 */
+ "allow guest_r user_r",
+ NULL
+};
+char *modified_roleallowrules[] = {
+/* 09.3.0 */
+ "allow aquarium_r { guest_r staff_r +admin_r }",
+ "allow user_r { placeholder_r +guest_r }",
+/* 09.3.1 */
+ "allow garden_r { guest_r -user_r -zoo_r }",
+ "allow lumberjack_r { garden_r -staff_r }",
+ "allow zoo_r { aquarium_r garden_r mammal_r -admin_r }",
+/* 09.3.2 */
+ "allow staff_r { guest_r user_r +mammal_r -intern_r }",
+ NULL
+};
+
+char *unchanged_roletrans_rules[] = {
+/* 10.0*/
+ "role_transition garden_r birch_t lumberjack_r",
+ "role_transition garden_r oak_t lumberjack_r",
+ "role_transition garden_r pine_t lumberjack_r",
+ "role_transition staff_r holly_t garden_r",
+ NULL
+};
+char *added_roletrans_rules[] = {
+/* 10.1 */
+ "role_transition guest_r bear_t staff_r",
+ "role_transition intern_r file_t staff_r",
+ NULL
+};
+char *removed_roletrans_rules[] = {
+/* 10.2 */
+ "role_transition zoo_r bass_t aquarium_r",
+ "role_transition zoo_r bear_t mammal_r",
+ "role_transition zoo_r trout_t aquarium_r",
+ NULL
+};
+char *modified_roletrans_rules[] = {
+/* 10.3.0 */
+ "role_transition guest_r dirt_t { +admin_r -intern_r }",
+ NULL
+};
+char *added_roletrans_type[] = {
+/* 10.4.0 */
+ "role_transition guest_r pipe_t staff_r",
+/* 10.4.1 */
+ "role_transition admin_r pipe_t staff_r",
+ "role_transition staff_r hippo_t zoo_r",
+ "role_transition zoo_r hippo_t mammal_r",
+ NULL
+};
+
+char *removed_roletrans_type[] = {
+/* 10.5.0 */
+ "role_transition guest_r koala_t staff_r",
+/* 10.5.1 */
+ "role_transition staff_r koala_t zoo_r",
+ NULL
+};
+
+char *unchanged_terules[] = {
+/* 11.0 */
+ "type_transition system_t dirt_t : process daikon_t",
+ NULL
+};
+char *added_terules[] = {
+/* 11.1 */
+ "type_member log_t file_t : netif rock_t",
+ "type_transition holly_t bear_t : dir oak_t",
+ NULL
+};
+char *removed_terules[] = {
+/* 11.2 */
+ "type_transition potato_t pine_t : fd log_t",
+ "type_change file_t bear_t : passwd daikon_t",
+ "type_member log_t file_t : node rock_t",
+ "type_change log_t bear_t : passwd daikon_t",
+ NULL
+};
+char *added_type_terules[] = {
+/*11.4.0 */
+ "type_transition hippo_t log_t : file system_t",
+/*11.4.1 */
+ "type_transition bear_t pipe_t : chr_file birch_t",
+/*11.4.2 */
+ "type_transition hippo_t stone_t : netif potato_t",
+/*11.4.3 */
+ "type_change glass_t hippo_t : socket bass_t",
+/*11.4.4 */
+ "type_change hippo_t pipe_t : gc log_t",
+/*11.4.5 */
+ "type_change file_t hippo_t : passwd daikon_t",
+ "type_change log_t hippo_t : passwd daikon_t",
+ "type_change pipe_t hippo_t : passwd daikon_t",
+ "type_change pipe_t lion_t : passwd daikon_t",
+ "type_change pipe_t tiger_t : passwd daikon_t",
+ "type_member hippo_t birch_t : chr_file file_t",
+ "type_member hippo_t daikon_t : chr_file file_t",
+ "type_member hippo_t holly_t : chr_file file_t",
+ "type_member hippo_t oak_t : chr_file file_t",
+ "type_member hippo_t pine_t : chr_file file_t",
+ "type_member hippo_t potato_t : chr_file file_t",
+ NULL
+};
+char *removed_type_terules[] = {
+/* 11.5.0 */
+ "type_change turnip_t glass_t : dir stone_t",
+/* 11.5.1 */
+ "type_change tiger_t turnip_t : file file_t",
+/* 11.5.2 */
+ "type_member turnip_t dirt_t : dir glass_t",
+/* 11.5.3 */
+ "type_member firefly_t turnip_t : file pine_t",
+/* 11.5.4 */
+ "type_member turnip_t turnip_t : fd lion_t",
+/* 11.5.5 */
+ "type_member bass_t turnip_t : chr_file file_t",
+ "type_member bear_t turnip_t : chr_file file_t",
+ "type_member finch_t turnip_t : chr_file file_t",
+ "type_member firefly_t turnip_t : chr_file file_t",
+/* these rules are incorrect because there was no hippo_t in the original policy, so it cannot be removed
+"type_member hippo_t birch_t : chr_file file_t",
+"type_member hippo_t daikon_t : chr_file file_t",
+"type_member hippo_t holly_t : chr_file file_t",
+"type_member hippo_t oak_t : chr_file file_t",
+"type_member hippo_t pine_t : chr_file file_t",
+"type_member hippo_t potato_t : chr_file file_t",
+*/
+ "type_member koala_t birch_t : chr_file file_t",
+ "type_member koala_t daikon_t : chr_file file_t",
+ "type_member koala_t holly_t : chr_file file_t",
+ "type_member koala_t oak_t : chr_file file_t",
+ "type_member koala_t pine_t : chr_file file_t",
+ "type_member koala_t potato_t : chr_file file_t",
+ "type_member koala_t turnip_t : chr_file file_t",
+ "type_member lion_t turnip_t : chr_file file_t",
+ "type_member tiger_t turnip_t : chr_file file_t",
+ "type_member trout_t turnip_t : chr_file file_t",
+/* koala_t is now an alias of animal, thus this rule now applies:
+ type_change glass_t animal : socket bass_t;
+ */
+ "type_change glass_t koala_t : socket bass_t",
+/* also this rule applies:
+ type_transition animal stone_t : netif potato_t;
+*/
+ "type_transition koala_t stone_t : netif potato_t",
+ NULL
+};
+
+char *modified_terules[] = {
+ "type_transition lion_t tiger_t : file +bear_t -koala_t",
+ NULL
+};
+
+static char *get_rule_modification_str(const apol_vector_t * unmodified, const apol_vector_t * added, const apol_vector_t * removed,
+ poldiff_form_e form, int show_changes)
+{
+ char *perm_add_char = "+", *perm_remove_char = "-";
+ apol_vector_t *added_copy = shallow_copy_str_vec_and_sort(added);
+ apol_vector_t *removed_copy = shallow_copy_str_vec_and_sort(removed);
+ apol_vector_t *unmodified_copy = shallow_copy_str_vec_and_sort(unmodified);
+ int error = 0;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ case POLDIFF_FORM_ADD_TYPE:
+ perm_add_char = "";
+ break;
+ case POLDIFF_FORM_REMOVE_TYPE:
+ case POLDIFF_FORM_REMOVED:
+ perm_remove_char = "";
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ // do nothing
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ size_t i, str_len;
+ char *perm_name = NULL, *str = NULL;
+ for (i = 0; unmodified_copy != NULL && i < apol_vector_get_size(unmodified_copy); ++i) {
+ char *unmod_perm = apol_vector_get_element(unmodified_copy, i);
+ apol_str_appendf(&str, &str_len, " %s", unmod_perm);
+ }
+ if (show_changes) {
+ for (i = 0; added != NULL && i < apol_vector_get_size(added); i++) {
+ perm_name = (char *)apol_vector_get_element(added_copy, i);
+ if (apol_str_appendf(&str, &str_len, " %s%s", perm_add_char, perm_name) < 0) {
+ error = errno;
+ goto err;
+ }
+ }
+ for (i = 0; removed != NULL && i < apol_vector_get_size(removed_copy); i++) {
+ perm_name = (char *)apol_vector_get_element(removed_copy, i);
+ if (apol_str_appendf(&str, &str_len, " %s%s", perm_remove_char, perm_name) < 0) {
+ error = errno;
+ goto err;
+ }
+ }
+ }
+ apol_vector_destroy(&added_copy);
+ apol_vector_destroy(&removed_copy);
+ apol_vector_destroy(&unmodified_copy);
+ return str;
+ err:
+ free(str);
+ return NULL;
+}
+
+static char *avrule_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ const poldiff_avrule_t *avr = (const poldiff_avrule_t *)arg;
+ char *str = NULL;
+ size_t str_len = 0;
+ uint32_t rule_type = poldiff_avrule_get_rule_type(avr);
+ const char *rule_type_str = apol_rule_type_to_str(rule_type);
+ const char *target_type = poldiff_avrule_get_target_type(avr);
+ const char *source_type = poldiff_avrule_get_source_type(avr);
+ const char *object_class = poldiff_avrule_get_object_class(avr);
+ apol_str_appendf(&str, &str_len, "%s %s %s : %s", rule_type_str, source_type, target_type, object_class);
+ if (show_changes) {
+ const apol_vector_t *unmodified_perms = poldiff_avrule_get_unmodified_perms(avr);
+ const apol_vector_t *removed_perms = poldiff_avrule_get_removed_perms(avr);
+ const apol_vector_t *added_perms = poldiff_avrule_get_added_perms(avr);
+ char *perm_str = get_rule_modification_str(unmodified_perms, added_perms, removed_perms, form, show_changes);
+ apol_str_appendf(&str, &str_len, "%s", perm_str);
+ free(perm_str);
+ }
+ return str;
+}
+
+static char *terule_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ poldiff_terule_t *ter = (poldiff_terule_t *) arg;
+ char *str = NULL;
+ size_t str_len = 0;
+ uint32_t rule_type = poldiff_terule_get_rule_type(ter);
+ const char *rule_type_str = apol_rule_type_to_str(rule_type);
+ const char *target_type = poldiff_terule_get_target_type(ter);
+ const char *source_type = poldiff_terule_get_source_type(ter);
+ const char *object_class = poldiff_terule_get_object_class(ter);
+ const char *default_type;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ case POLDIFF_FORM_ADD_TYPE:
+ default_type = poldiff_terule_get_modified_default(ter);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ case POLDIFF_FORM_REMOVE_TYPE:
+ case POLDIFF_FORM_MODIFIED:
+ default_type = poldiff_terule_get_original_default(ter);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ if (form == POLDIFF_FORM_MODIFIED && show_changes) {
+ const char *orig_default = poldiff_terule_get_original_default(ter);
+ const char *mod_default = poldiff_terule_get_modified_default(ter);
+ apol_str_appendf(&str, &str_len, "%s %s %s : %s +%s -%s", rule_type_str, source_type, target_type, object_class,
+ mod_default, orig_default);
+ } else
+ apol_str_appendf(&str, &str_len, "%s %s %s : %s %s", rule_type_str, source_type, target_type, object_class,
+ default_type);
+ return str;
+}
+
+static char *roletrans_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ poldiff_role_trans_t *rt = (poldiff_role_trans_t *) arg;
+ char *str = NULL;
+ size_t str_len = 0;
+ const char *source_role = poldiff_role_trans_get_source_role(rt);
+ const char *target_type = poldiff_role_trans_get_target_type(rt);
+ apol_str_appendf(&str, &str_len, "role_transition %s %s", source_role, target_type);
+ if (show_changes) {
+ const char *orig_default = poldiff_role_trans_get_original_default(rt);
+ const char *mod_default = poldiff_role_trans_get_modified_default(rt);
+
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ case POLDIFF_FORM_ADD_TYPE:
+ apol_str_appendf(&str, &str_len, " %s", mod_default);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ case POLDIFF_FORM_REMOVE_TYPE:
+ apol_str_appendf(&str, &str_len, " %s", orig_default);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ apol_str_appendf(&str, &str_len, " { +%s -%s }", mod_default, orig_default);
+ break;
+ default:
+ // should never get here:
+ assert(0);
+ }
+ }
+ return str;
+}
+
+static char *roleallow_to_string(const void *arg, poldiff_form_e form, int show_changes)
+{
+ poldiff_role_allow_t *rat = (poldiff_role_allow_t *) arg;
+ char *str = NULL, *orig_roles_str = NULL;
+ size_t str_len = 0, orig_roles_str_len = 0;
+ const char *name = poldiff_role_allow_get_name(rat);
+ const apol_vector_t *orig_roles;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ orig_roles = poldiff_role_allow_get_added_roles(rat);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ orig_roles = poldiff_role_allow_get_removed_roles(rat);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ orig_roles = poldiff_role_allow_get_unmodified_roles(rat);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ size_t i;
+ size_t num_orig_roles = apol_vector_get_size(orig_roles);
+ const char *fmt;
+ if (num_orig_roles > 1 || (show_changes && form == POLDIFF_FORM_MODIFIED))
+ fmt = "allow %s {%s }";
+ else
+ fmt = "allow %s%s";
+ for (i = 0; i < num_orig_roles; ++i) {
+ char *role = apol_vector_get_element(orig_roles, i);
+ apol_str_appendf(&orig_roles_str, &orig_roles_str_len, " %s", role);
+ }
+ if (show_changes && form == POLDIFF_FORM_MODIFIED) {
+ const apol_vector_t *added_role_v = poldiff_role_allow_get_added_roles(rat);
+ for (i = 0; i < apol_vector_get_size(added_role_v); ++i) {
+ char *added_role = apol_vector_get_element(added_role_v, i);
+ apol_str_appendf(&orig_roles_str, &orig_roles_str_len, " +%s", added_role);
+ }
+ const apol_vector_t *removed_role_v = poldiff_role_allow_get_removed_roles(rat);
+ for (i = 0; i < apol_vector_get_size(removed_role_v); ++i) {
+ char *removed_role = apol_vector_get_element(removed_role_v, i);
+ apol_str_appendf(&orig_roles_str, &orig_roles_str_len, " -%s", removed_role);
+ }
+ }
+ apol_str_appendf(&str, &str_len, fmt, name, orig_roles_str);
+ free(orig_roles_str);
+ return str;
+}
+
+void build_roleallow_vecs()
+{
+ char *str = NULL, *name_only = NULL;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_role_allow_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ item = apol_vector_get_element(v, i);
+ if (!item)
+ return;
+ poldiff_form_e form = poldiff_role_allow_get_form(item);
+ str = roleallow_to_string(item, form, 1);
+ if (!str)
+ break;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = roleallow_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+}
+
+void build_roletrans_vecs()
+{
+ added_type_rules_v = apol_vector_create(free);
+ removed_type_rules_v = apol_vector_create(free);
+ correct_added_type_rules_v = string_array_to_vector(added_roletrans_type);
+ correct_removed_type_rules_v = string_array_to_vector(removed_roletrans_type);
+
+ char *str = NULL, *name_only;
+ size_t i;
+ const void *item = NULL;
+ const apol_vector_t *v = NULL;
+ v = poldiff_get_role_trans_vector(diff);
+ for (i = 0; i < apol_vector_get_size(v); i++) {
+ item = apol_vector_get_element(v, i);
+ if (!item)
+ return;
+ poldiff_form_e form = poldiff_role_trans_get_form(item);
+ str = roletrans_to_string(item, form, 1);
+ if (!str)
+ break;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_ADD_TYPE:
+ apol_vector_append(added_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_REMOVE_TYPE:
+ apol_vector_append(removed_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = roletrans_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+ int test_result;
+ size_t first_diff = 0;
+ apol_vector_sort(added_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_added_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(added_type_rules_v, correct_added_type_rules_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(added_type_rules_v, correct_added_type_rules_v, first_diff, "Added Rule (due to Type)");
+ }
+ apol_vector_sort(removed_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_removed_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(removed_type_rules_v, correct_removed_type_rules_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(removed_type_rules_v, correct_removed_type_rules_v, first_diff, "Removed Rule (due to Type)");
+ }
+ apol_vector_destroy(&added_type_rules_v);
+ apol_vector_destroy(&correct_added_type_rules_v);
+ apol_vector_destroy(&removed_type_rules_v);
+ apol_vector_destroy(&correct_removed_type_rules_v);
+}
+
+void build_terule_vecs()
+{
+ added_type_rules_v = apol_vector_create(free);
+ removed_type_rules_v = apol_vector_create(free);
+ correct_added_type_rules_v = string_array_to_vector(added_type_terules);
+ correct_removed_type_rules_v = string_array_to_vector(removed_type_terules);
+
+ size_t i;
+ char *str = NULL;
+ const void *item = NULL;
+ const apol_vector_t *member_v = NULL, *change_v = NULL, *trans_v = NULL;
+ member_v = poldiff_get_terule_vector_member(diff);
+ change_v = poldiff_get_terule_vector_change(diff);
+ trans_v = poldiff_get_terule_vector_trans(diff);
+ apol_vector_t *all_terules = apol_vector_create(NULL);
+ apol_vector_cat(all_terules, member_v);
+ apol_vector_cat(all_terules, change_v);
+ apol_vector_cat(all_terules, trans_v);
+
+ for (i = 0; i < apol_vector_get_size(all_terules); i++) {
+ item = apol_vector_get_element(all_terules, i);
+ if (!item)
+ return;
+ poldiff_form_e form = poldiff_terule_get_form(item);
+ str = terule_to_string(item, form, 1);
+ if (!str)
+ break;
+ char *name_only = NULL;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_ADD_TYPE:
+ apol_vector_append(added_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_REMOVE_TYPE:
+ apol_vector_append(removed_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = terule_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+ size_t first_diff = 0;
+ int test_result = 0;
+ apol_vector_sort(added_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_added_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(added_type_rules_v, correct_added_type_rules_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(added_type_rules_v, correct_added_type_rules_v, first_diff, "Added Rules (due to types)");
+ }
+
+ apol_vector_sort(removed_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_removed_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(test_result =
+ apol_vector_compare(removed_type_rules_v, correct_removed_type_rules_v, compare_str, NULL, &first_diff));
+ if (test_result) {
+ print_test_failure(removed_type_rules_v, correct_removed_type_rules_v, first_diff, "Removed Rules (due to types)");
+ }
+ apol_vector_destroy(&all_terules);
+ apol_vector_destroy(&added_type_rules_v);
+ apol_vector_destroy(&correct_added_type_rules_v);
+ apol_vector_destroy(&removed_type_rules_v);
+ apol_vector_destroy(&correct_removed_type_rules_v);
+}
+
+void build_avrule_vecs()
+{
+ added_type_rules_v = apol_vector_create(free);
+ removed_type_rules_v = apol_vector_create(free);
+ correct_added_type_rules_v = string_array_to_vector(added_type_avrules);
+ correct_removed_type_rules_v = string_array_to_vector(removed_type_avrules);
+
+ size_t i;
+ char *str = NULL, *name_only = NULL;
+ const void *item = NULL;
+ const apol_vector_t *allow_v = NULL, *neverallow_v = NULL, *auditallow_v = NULL, *dontaudit_v = NULL;
+ apol_vector_t *all_avrules_v = apol_vector_create(NULL);
+
+ allow_v = poldiff_get_avrule_vector_allow(diff);
+ neverallow_v = poldiff_get_avrule_vector_neverallow(diff);
+ auditallow_v = poldiff_get_avrule_vector_auditallow(diff);
+ dontaudit_v = poldiff_get_avrule_vector_dontaudit(diff);
+
+ apol_vector_cat(all_avrules_v, allow_v);
+ apol_vector_cat(all_avrules_v, neverallow_v);
+ apol_vector_cat(all_avrules_v, auditallow_v);
+ apol_vector_cat(all_avrules_v, dontaudit_v);
+
+ for (i = 0; i < apol_vector_get_size(all_avrules_v); i++) {
+ item = apol_vector_get_element(all_avrules_v, i);
+ if (!item)
+ return;
+ poldiff_form_e form = poldiff_avrule_get_form(item);
+ str = avrule_to_string(item, form, 1);
+ if (!str)
+ break;
+ switch (form) {
+ case POLDIFF_FORM_ADDED:
+ apol_vector_append(added_v, str);
+ break;
+ case POLDIFF_FORM_REMOVED:
+ apol_vector_append(removed_v, str);
+ break;
+ case POLDIFF_FORM_ADD_TYPE:
+ apol_vector_append(added_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_REMOVE_TYPE:
+ apol_vector_append(removed_type_rules_v, str);
+ break;
+ case POLDIFF_FORM_MODIFIED:
+ name_only = avrule_to_string(item, form, 0);
+ apol_vector_append(modified_name_only_v, name_only);
+ apol_vector_append(modified_v, str);
+ break;
+ default:
+ // should never get here
+ assert(0);
+ }
+ }
+ size_t first_diff = 0;
+ apol_vector_sort(added_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_added_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(apol_vector_compare(added_type_rules_v, correct_added_type_rules_v, compare_str, NULL, &first_diff));
+
+ apol_vector_sort(removed_type_rules_v, compare_str, NULL);
+ apol_vector_sort(correct_removed_type_rules_v, compare_str, NULL);
+ CU_ASSERT_FALSE(apol_vector_compare(removed_type_rules_v, correct_removed_type_rules_v, compare_str, NULL, &first_diff));
+
+ apol_vector_destroy(&removed_type_rules_v);
+ apol_vector_destroy(&correct_removed_type_rules_v);
+ apol_vector_destroy(&added_type_rules_v);
+ apol_vector_destroy(&correct_added_type_rules_v);
+ apol_vector_destroy(&all_avrules_v);
+}
+
+void rules_avrules_tests()
+{
+ test_numbers_e test_num = RULES_AVRULE;
+ poldiff_test_answers_t *answers = init_answer_vectors(added_avrules, removed_avrules, unchanged_avrules, modified_avrules);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void rules_terules_tests()
+{
+ test_numbers_e test_num = RULES_TERULE;
+ poldiff_test_answers_t *answers = init_answer_vectors(added_terules, removed_terules, unchanged_terules, modified_terules);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void rules_roleallow_tests()
+{
+ test_numbers_e test_num = RULES_ROLEALLOW;
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_roleallowrules, removed_roleallowrules, unchanged_roleallowrules,
+ modified_roleallowrules);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+void rules_roletrans_tests()
+{
+ test_numbers_e test_num = RULES_ROLETRANS;
+ poldiff_test_answers_t *answers =
+ init_answer_vectors(added_roletrans_rules, removed_roletrans_rules, unchanged_roletrans_rules,
+ modified_roletrans_rules);
+ run_test(NULL, answers, test_num);
+ cleanup_test(answers);
+}
+
+int rules_test_init()
+{
+ if (!(diff = init_poldiff(RULES_ORIG_POLICY, RULES_MOD_POLICY))) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/libpoldiff/tests/rules-tests.h b/libpoldiff/tests/rules-tests.h
new file mode 100644
index 0000000..34a30eb
--- /dev/null
+++ b/libpoldiff/tests/rules-tests.h
@@ -0,0 +1,40 @@
+/**
+ * @file
+ *
+ * Header file for libpoldiff's correctness of rules.
+ *
+ * @author Paul Rosenfeld prosenfeld@tresys.com
+ *
+ * Copyright (C) 2007 Tresys Technology, LLC
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RULES_TEST
+#define RULES_TEST
+int rules_test_init();
+int rules_test_cleanup();
+
+void rules_avrules_tests();
+void rules_roleallow_tests();
+void rules_roletrans_tests();
+void rules_terules_tests();
+
+void build_avrule_vecs();
+void build_terule_vecs();
+void build_roletrans_vecs();
+void build_roleallow_vecs();
+
+#endif