/* Authors: Christopher Ashworth <cashworth@tresys.com>
* Caleb Case <ccase@tresys.com>
* Chris PeBenito <cpebenito@tresys.com>
*
* 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>
semanage_handle_t *sh = NULL;
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);
}