diff mbox series

[01/11] libsemanage: add helper functions to tests

Message ID 20190612080404.4529-2-jzarsky@redhat.com (mailing list archive)
State Accepted
Headers show
Series libsemanage: add tests | expand

Commit Message

Jan Zarsky June 12, 2019, 8:03 a.m. UTC
- Add functions for creating and destroying test semanage store.
- Add functions for writing SELinux policy to the test store.
- Add functions for creating semanage handle, connecting to the store and for
  beginning a transaction.
- Update Makefile to compile test policies from CIL source.

Signed-off-by: Jan Zarsky <jzarsky@redhat.com>
---
 libsemanage/tests/.gitignore            |   1 +
 libsemanage/tests/Makefile              |  11 +-
 libsemanage/tests/test_semanage_store.c |   2 +-
 libsemanage/tests/utilities.c           | 254 +++++++++++++++++++++++-
 libsemanage/tests/utilities.h           |  53 ++++-
 5 files changed, 311 insertions(+), 10 deletions(-)
diff mbox series

Patch

diff --git a/libsemanage/tests/.gitignore b/libsemanage/tests/.gitignore
index f07111db..8a2a866a 100644
--- a/libsemanage/tests/.gitignore
+++ b/libsemanage/tests/.gitignore
@@ -1 +1,2 @@ 
 libsemanage-tests
+*.policy
diff --git a/libsemanage/tests/Makefile b/libsemanage/tests/Makefile
index 324766a0..69f49a36 100644
--- a/libsemanage/tests/Makefile
+++ b/libsemanage/tests/Makefile
@@ -1,5 +1,6 @@ 
 # Add your test source files here:
 SOURCES = $(sort $(wildcard *.c))
+CILS = $(sort $(wildcard *.cil))
 
 ###########################################################################
 
@@ -8,15 +9,19 @@  CFLAGS += -g -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute
 override CFLAGS += -I../src -I../include
 override LDLIBS += -lcunit -lbz2 -laudit -lselinux -lsepol
 
-OBJECTS = $(SOURCES:.c=.o) 
+OBJECTS = $(SOURCES:.c=.o)
+POLICIES = $(CILS:.cil=.policy)
 
-all: $(EXECUTABLE) 
+all: $(EXECUTABLE) $(POLICIES)
 
 $(EXECUTABLE): $(OBJECTS) ../src/libsemanage.a
 	$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS)
 
+%.policy: %.cil
+	../../secilc/secilc $*.cil -o $*.policy -f /dev/null
+
 clean distclean: 
-	rm -rf $(OBJECTS) $(EXECUTABLE)
+	rm -rf $(OBJECTS) $(POLICIES) $(EXECUTABLE)
 
 test: all 
 	./$(EXECUTABLE)
diff --git a/libsemanage/tests/test_semanage_store.c b/libsemanage/tests/test_semanage_store.c
index b324d502..92085361 100644
--- a/libsemanage/tests/test_semanage_store.c
+++ b/libsemanage/tests/test_semanage_store.c
@@ -43,7 +43,7 @@ 
 #include <unistd.h>
 #include <CUnit/Basic.h>
 
-semanage_handle_t *sh = NULL;
+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";
diff --git a/libsemanage/tests/utilities.c b/libsemanage/tests/utilities.c
index 7cc726c6..18393215 100644
--- a/libsemanage/tests/utilities.c
+++ b/libsemanage/tests/utilities.c
@@ -1,6 +1,7 @@ 
 /* Authors: Christopher Ashworth <cashworth@tresys.com>
  *
  * Copyright (C) 2006 Tresys Technology, LLC
+ * Copyright (C) 2019 Red Hat, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -17,16 +18,261 @@ 
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-/*  The purpose of this file is to provide some functions commonly needed 
+/*  The purpose of this file is to provide some functions commonly needed
  *  by our unit tests.
  */
 
 #include "utilities.h"
 
+int test_store_enabled = 0;
+
+semanage_handle_t *sh = NULL;
+
 /* Silence any error output caused by our tests
- * by using this dummy function to catch messages. 
+ * by using this dummy function to catch messages.
  */
-void test_msg_handler(void *varg,
-		      semanage_handle_t * handle, const char *fmt, ...)
+void test_msg_handler(void *varg, semanage_handle_t *handle, const char *fmt,
+		      ...)
 {
 }
+
+int create_test_store() {
+	FILE *fptr;
+
+	if (mkdir("test-policy", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active/modules", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/etc", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/etc/selinux", 0700) < 0)
+		return -1;
+
+	fptr = fopen("test-policy/etc/selinux/semanage.conf", "w+");
+
+	if (!fptr)
+		return -1;
+
+	fclose(fptr);
+
+	enable_test_store();
+	return 0;
+}
+
+void disable_test_store(void) {
+	test_store_enabled = 0;
+}
+
+void enable_test_store(void) {
+	test_store_enabled = 1;
+}
+
+int write_test_policy(char *data, size_t data_len) {
+	FILE *fptr = fopen("test-policy/store/active/policy.kern", "wb+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite(data, data_len, 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	return 0;
+}
+
+int write_test_policy_from_file(const char *filename) {
+	char *buf = NULL;
+	size_t len = 0;
+	FILE *fptr = fopen(filename, "rb");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	fseek(fptr, 0, SEEK_END);
+	len = ftell(fptr);
+	fseek(fptr, 0, SEEK_SET);
+
+	buf = (char *) malloc(len);
+
+	if (!buf) {
+		perror("malloc");
+		fclose(fptr);
+		return -1;
+	}
+
+	fread(buf, len, 1, fptr);
+	fclose(fptr);
+
+	return write_test_policy(buf, len);
+}
+
+int write_test_policy_src(unsigned char *data, unsigned int data_len) {
+	if (mkdir("test-policy/store/active/modules/100", 0700) < 0)
+		return -1;
+
+	if (mkdir("test-policy/store/active/modules/100/base", 0700) < 0)
+		return -1;
+
+	FILE *fptr = fopen("test-policy/store/active/modules/100/base/cil",
+			   "w+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite(data, data_len, 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	fptr = fopen("test-policy/store/active/modules/100/base/lang_ext",
+		     "w+");
+
+	if (!fptr) {
+		perror("fopen");
+		return -1;
+	}
+
+	if (fwrite("cil", sizeof("cil"), 1, fptr) != 1) {
+		perror("fwrite");
+		fclose(fptr);
+		return -1;
+	}
+
+	fclose(fptr);
+
+	return 0;
+}
+
+int destroy_test_store() {
+	FTS *ftsp = NULL;
+	FTSENT *curr = NULL;
+	int ret = 0;
+
+	disable_test_store();
+
+	char *files[] = { (char *) "test-policy", NULL };
+
+	ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
+
+	if (!ftsp)
+		return -1;
+
+	while ((curr = fts_read(ftsp)))
+		switch (curr->fts_info) {
+		case FTS_DP:
+		case FTS_F:
+		case FTS_SL:
+		case FTS_SLNONE:
+		case FTS_DEFAULT:
+			if (remove(curr->fts_accpath) < 0)
+				ret = -1;
+		default:
+			break;
+		}
+
+	fts_close(ftsp);
+
+	return ret;
+}
+
+void helper_handle_create(void) {
+	if (test_store_enabled)
+		semanage_set_root("test-policy");
+
+	sh = semanage_handle_create();
+	CU_ASSERT_PTR_NOT_NULL(sh);
+
+	semanage_msg_set_callback(sh, test_msg_handler, NULL);
+
+	if (test_store_enabled) {
+		semanage_set_create_store(sh, 1);
+		semanage_set_reload(sh, 0);
+		semanage_set_store_root(sh, "");
+		semanage_select_store(sh, (char *) "store",
+				      SEMANAGE_CON_DIRECT);
+	}
+}
+
+void helper_handle_destroy(void) {
+	semanage_handle_destroy(sh);
+}
+
+void helper_connect(void) {
+	CU_ASSERT(semanage_connect(sh) >= 0);
+}
+
+void helper_disconnect(void) {
+	CU_ASSERT(semanage_disconnect(sh) >= 0);
+}
+
+void helper_begin_transaction(void) {
+	CU_ASSERT(semanage_begin_transaction(sh) >= 0);
+}
+
+void helper_commit(void) {
+	CU_ASSERT(semanage_commit(sh) >= 0);
+}
+
+void setup_handle(level_t level) {
+	if (level >= SH_NULL)
+		sh = NULL;
+
+	if (level >= SH_HANDLE)
+		helper_handle_create();
+
+	if (level >= SH_CONNECT)
+		helper_connect();
+
+	if (level >= SH_TRANS)
+		helper_begin_transaction();
+}
+
+void cleanup_handle(level_t level) {
+	if (level >= SH_TRANS)
+		helper_commit();
+
+	if (level >= SH_CONNECT)
+		helper_disconnect();
+
+	if (level >= SH_HANDLE)
+		helper_handle_destroy();
+
+	if (level >= SH_NULL)
+		sh = NULL;
+}
+
+void setup_handle_invalid_store(level_t level) {
+	CU_ASSERT(level >= SH_HANDLE);
+
+	helper_handle_create();
+
+	semanage_select_store(sh, (char *) "", SEMANAGE_CON_INVALID);
+
+	if (level >= SH_CONNECT)
+		helper_connect();
+
+	if (level >= SH_TRANS)
+		helper_begin_transaction();
+}
diff --git a/libsemanage/tests/utilities.h b/libsemanage/tests/utilities.h
index 781867d1..c9d54d1e 100644
--- a/libsemanage/tests/utilities.h
+++ b/libsemanage/tests/utilities.h
@@ -1,6 +1,7 @@ 
 /* Authors: Christopher Ashworth <cashworth@tresys.com>
  *
  * Copyright (C) 2006 Tresys Technology, LLC
+ * Copyright (C) 2019 Red Hat, Inc.
  *
  *  This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,55 @@ 
  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include "handle.h"
+#ifndef __UTILITIES_H__
+#define __UTILITIES_H__
 
-void test_msg_handler(void *varg, semanage_handle_t * handle, const char *fmt,
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <fts.h>
+#include <assert.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <CUnit/Basic.h>
+
+#include "semanage/semanage.h"
+
+#define CU_ASSERT_CONTEXT_EQUAL(CON1,CON2) \
+	do { \
+		char *__str; \
+		char *__str2; \
+		CU_ASSERT(semanage_context_to_string(sh, CON1, &__str) >= 0); \
+		CU_ASSERT(semanage_context_to_string(sh, CON2, &__str2) >= 0); \
+		CU_ASSERT_STRING_EQUAL(__str, __str2); \
+	} while (0)
+
+#define I_NULL  -1
+#define I_FIRST  0
+#define I_SECOND 1
+#define I_THIRD  2
+
+typedef enum { SH_NULL, SH_HANDLE, SH_CONNECT, SH_TRANS } level_t;
+
+void test_msg_handler(void *varg, semanage_handle_t *handle, const char *fmt,
 		      ...);
+
+void setup_handle(level_t level);
+void cleanup_handle(level_t level);
+void setup_handle_invalid_store(level_t level);
+
+void helper_handle_create(void);
+void helper_handle_destroy(void);
+void helper_connect(void);
+void helper_disconnect(void);
+void helper_begin_transaction(void);
+void helper_commit(void);
+
+int create_test_store(void);
+int write_test_policy_from_file(const char *filename);
+int write_test_policy_src(unsigned char *data, unsigned int data_len);
+int destroy_test_store(void);
+void enable_test_store(void);
+void disable_test_store(void);
+
+#endif