| /* Authors: Christopher Ashworth <[email protected]> |
| * Caleb Case <[email protected]> |
| * Chris PeBenito <[email protected]> |
| * |
| * Copyright (C) 2006 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 |
| */ |
| |
| /* The purpose of this file is to provide unit tests of the functions in: |
| * |
| * libsemanage/src/semanage_store.c |
| * |
| */ |
| |
| #include "handle.h" |
| #include "semanage_store.h" |
| |
| #include "utilities.h" |
| #include "test_semanage_store.h" |
| |
| #include <libgen.h> |
| #include <limits.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/mman.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <CUnit/Basic.h> |
| |
| extern semanage_handle_t *sh; |
| const char *rootpath = "./test-policy"; |
| const char *polpath = "./test-policy/store/"; |
| const char *readlockpath = "./test-policy/store/semanage.read.LOCK"; |
| const char *translockpath = "./test-policy/store/semanage.trans.LOCK"; |
| const char *actpath = "./test-policy/store/active"; |
| const char *modpath = "./test-policy/store/active/modules"; |
| |
| /* The suite initialization function. |
| * Returns zero on success, non-zero otherwise. |
| */ |
| int semanage_store_test_init(void) |
| { |
| int err; |
| |
| /* create directories */ |
| err = mkdir(rootpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| if (err != 0) |
| return -1; |
| |
| err = mkdir(polpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| if (err != 0) |
| return -1; |
| |
| err = mkdir(actpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| if (err != 0) |
| return -1; |
| |
| err = mkdir(modpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| if (err != 0) |
| return -1; |
| |
| /* initialize the handle */ |
| sh = semanage_handle_create(); |
| if (sh == NULL) |
| return -1; |
| |
| /* hide error messages */ |
| sh->msg_callback = test_msg_handler; |
| |
| /* use our own policy store */ |
| free(sh->conf->store_path); |
| sh->conf->store_path = strdup("store"); |
| |
| /* initialize paths */ |
| err = semanage_check_init(sh, rootpath); |
| if (err != 0) |
| return -1; |
| |
| return 0; |
| } |
| |
| /* The suite cleanup function. |
| * Returns zero on success, non-zero otherwise. |
| */ |
| int semanage_store_test_cleanup(void) |
| { |
| int err; |
| |
| /* remove the test policy directories */ |
| err = rmdir(modpath); |
| if (err != 0) |
| return -1; |
| |
| err = rmdir(actpath); |
| if (err != 0) |
| return -1; |
| |
| err = rmdir(polpath); |
| if (err != 0) |
| return -1; |
| |
| err = rmdir(rootpath); |
| if (err != 0) |
| return -1; |
| |
| /* cleanup the handle */ |
| semanage_handle_destroy(sh); |
| return 0; |
| } |
| |
| /* Adds all the tests needed for this suite. |
| */ |
| int semanage_store_add_tests(CU_pSuite suite) |
| { |
| if (NULL == |
| CU_add_test(suite, "semanage_store_access_check", |
| test_semanage_store_access_check)) { |
| CU_cleanup_registry(); |
| return CU_get_error(); |
| } |
| |
| if (NULL == |
| CU_add_test(suite, "semanage_get_lock", test_semanage_get_lock)) { |
| CU_cleanup_registry(); |
| return CU_get_error(); |
| } |
| |
| if (NULL == |
| CU_add_test(suite, "semanage_nc_sort", test_semanage_nc_sort)) { |
| CU_cleanup_registry(); |
| return CU_get_error(); |
| } |
| |
| return 0; |
| } |
| |
| /* Tests the semanage_store_access_check function in semanage_store.c |
| */ |
| void test_semanage_store_access_check(void) |
| { |
| int err; |
| |
| /* create lock file */ |
| err = mknod(readlockpath, S_IRUSR | S_IWUSR, S_IFREG); |
| |
| /* check with permissions 000 */ |
| err = chmod(modpath, 0); |
| CU_ASSERT(err == 0); |
| err = chmod(readlockpath, 0); |
| CU_ASSERT(err == 0); |
| err = chmod(polpath, 0); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == -1); |
| |
| /* check with permissions 500 */ |
| err = chmod(polpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(readlockpath, S_IRUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == SEMANAGE_CAN_READ); |
| |
| /* check with permissions 700 */ |
| err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(readlockpath, S_IRUSR | S_IWUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == SEMANAGE_CAN_WRITE); |
| |
| /* check with lock file 000 and others 500 */ |
| err = chmod(polpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(readlockpath, 0); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == 0); |
| |
| /* check with lock file 000 and others 700 */ |
| err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(readlockpath, 0); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == 0); |
| |
| /* remove lock file */ |
| err = remove(readlockpath); |
| CU_ASSERT(err == 0); |
| |
| /* check with no lock file and 000 */ |
| err = chmod(modpath, 0); |
| CU_ASSERT(err == 0); |
| err = chmod(polpath, 0); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == -1); |
| |
| /* check with no lock file and 500 */ |
| err = chmod(polpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == 0); |
| |
| /* check with no lock file but write in polpath */ |
| err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == SEMANAGE_CAN_READ); |
| |
| /* check with no lock file and 700 */ |
| err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR); |
| CU_ASSERT(err == 0); |
| |
| err = semanage_store_access_check(); |
| CU_ASSERT(err == SEMANAGE_CAN_WRITE); |
| } |
| |
| /* Tests the semanage_get_lock functions in semanage_store.c |
| */ |
| void test_semanage_get_lock(void) |
| { |
| int err; |
| |
| /* attempt to get an active lock */ |
| err = semanage_get_active_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to get the lock again */ |
| err = semanage_get_active_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to release the active lock */ |
| semanage_release_active_lock(sh); |
| |
| /* attempt to get an active lock */ |
| err = semanage_get_active_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to release the active lock */ |
| semanage_release_active_lock(sh); |
| |
| /* attempt to get a trans lock */ |
| err = semanage_get_trans_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to get the lock again */ |
| err = semanage_get_trans_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to release the trans lock */ |
| semanage_release_trans_lock(sh); |
| |
| /* attempt to get a trans lock */ |
| err = semanage_get_trans_lock(sh); |
| CU_ASSERT(err == 0); |
| |
| /* attempt to release the trans lock */ |
| semanage_release_trans_lock(sh); |
| |
| /* remove the lock files */ |
| err = remove(readlockpath); |
| CU_ASSERT(err == 0); |
| err = remove(translockpath); |
| CU_ASSERT(err == 0); |
| } |
| |
| /* Tests the semanage_nc_sort function in semanage_store.c |
| */ |
| void test_semanage_nc_sort(void) |
| { |
| char *source_buf, *sorted_buf = NULL, *good_buf, *bad_buf; |
| size_t source_buf_len, sorted_buf_len, good_buf_len, bad_buf_len; |
| int sourcefd, goodfd, badfd, err; |
| struct stat sb; |
| |
| /* open source file */ |
| sourcefd = open("nc_sort_unsorted", O_RDONLY); |
| if (sourcefd < 0) { |
| CU_FAIL("Missing nc_sort_unsorted test file."); |
| return; |
| } |
| fstat(sourcefd, &sb); |
| source_buf_len = sb.st_size; |
| source_buf = |
| (char *)mmap(NULL, source_buf_len, PROT_READ, MAP_PRIVATE, sourcefd, |
| 0); |
| |
| /* open good result file */ |
| goodfd = open("nc_sort_sorted", O_RDONLY); |
| if (goodfd < 0) { |
| CU_FAIL("Missing nc_sort_sorted test file."); |
| goto out2; |
| } |
| fstat(goodfd, &sb); |
| good_buf_len = sb.st_size; |
| good_buf = |
| (char *)mmap(NULL, good_buf_len, PROT_READ, MAP_PRIVATE, goodfd, 0); |
| |
| /* open malformed source file (missing priorities) */ |
| badfd = open("nc_sort_malformed", O_RDONLY); |
| if (badfd < 0) { |
| CU_FAIL("Missing nc_sort_malformed test file."); |
| goto out1; |
| } |
| fstat(badfd, &sb); |
| bad_buf_len = sb.st_size; |
| bad_buf = |
| (char *)mmap(NULL, bad_buf_len, PROT_READ, MAP_PRIVATE, badfd, 0); |
| |
| /* sort test file */ |
| err = |
| semanage_nc_sort(sh, source_buf, source_buf_len, &sorted_buf, |
| &sorted_buf_len); |
| CU_ASSERT_FALSE(err); |
| CU_ASSERT_STRING_EQUAL(sorted_buf, good_buf); |
| |
| /* reset for reuse in next test */ |
| free(sorted_buf); |
| sorted_buf = NULL; |
| |
| /* sort malformed source file */ |
| err = |
| semanage_nc_sort(sh, bad_buf, bad_buf_len, &sorted_buf, |
| &sorted_buf_len); |
| CU_ASSERT_EQUAL(err, -1); |
| |
| free(sorted_buf); |
| |
| munmap(bad_buf, bad_buf_len); |
| close(badfd); |
| out1: |
| munmap(good_buf, good_buf_len); |
| close(goodfd); |
| out2: |
| munmap(source_buf, source_buf_len); |
| close(sourcefd); |
| } |