diff options
Diffstat (limited to 'libpoldiff/tests')
-rw-r--r-- | libpoldiff/tests/Makefile.am | 19 | ||||
-rw-r--r-- | libpoldiff/tests/components-tests.c | 544 | ||||
-rw-r--r-- | libpoldiff/tests/components-tests.h | 49 | ||||
-rw-r--r-- | libpoldiff/tests/libpoldiff-tests.c | 364 | ||||
-rw-r--r-- | libpoldiff/tests/libpoldiff-tests.h | 85 | ||||
-rw-r--r-- | libpoldiff/tests/mls-tests.c | 635 | ||||
-rw-r--r-- | libpoldiff/tests/mls-tests.h | 39 | ||||
-rw-r--r-- | libpoldiff/tests/nomls-tests.c | 139 | ||||
-rw-r--r-- | libpoldiff/tests/nomls-tests.h | 33 | ||||
-rw-r--r-- | libpoldiff/tests/policy-defs.h | 44 | ||||
-rw-r--r-- | libpoldiff/tests/rules-tests.c | 914 | ||||
-rw-r--r-- | libpoldiff/tests/rules-tests.h | 40 |
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 |