376 lines
9.0 KiB
C
376 lines
9.0 KiB
C
/* 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);
|
|
}
|