1 /* Authors: Christopher Ashworth <cashworth@tresys.com>
2  *
3  * Copyright (C) 2006 Tresys Technology, LLC
4  * Copyright (C) 2019 Red Hat, Inc.
5  *
6  *  This library is free software; you can redistribute it and/or
7  *  modify it under the terms of the GNU Lesser General Public
8  *  License as published by the Free Software Foundation; either
9  *  version 2.1 of the License, or (at your option) any later version.
10  *
11  *  This library is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  *  Lesser General Public License for more details.
15  *
16  *  You should have received a copy of the GNU Lesser General Public
17  *  License along with this library; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 /*  The purpose of this file is to provide some functions commonly needed
22  *  by our unit tests.
23  */
24 
25 #include "utilities.h"
26 
27 int test_store_enabled = 0;
28 
29 semanage_handle_t *sh = NULL;
30 
31 /* Silence any error output caused by our tests
32  * by using this dummy function to catch messages.
33  */
test_msg_handler(void * varg,semanage_handle_t * handle,const char * fmt,...)34 void test_msg_handler(void *varg, semanage_handle_t *handle, const char *fmt,
35 		      ...)
36 {
37 }
38 
create_test_store()39 int create_test_store() {
40 	FILE *fptr;
41 
42 	if (mkdir("test-policy", 0700) < 0)
43 		return -1;
44 
45 	if (mkdir("test-policy/store", 0700) < 0)
46 		return -1;
47 
48 	if (mkdir("test-policy/store/active", 0700) < 0)
49 		return -1;
50 
51 	if (mkdir("test-policy/store/active/modules", 0700) < 0)
52 		return -1;
53 
54 	if (mkdir("test-policy/etc", 0700) < 0)
55 		return -1;
56 
57 	if (mkdir("test-policy/etc/selinux", 0700) < 0)
58 		return -1;
59 
60 	fptr = fopen("test-policy/etc/selinux/semanage.conf", "w+");
61 
62 	if (!fptr)
63 		return -1;
64 
65 	fclose(fptr);
66 
67 	enable_test_store();
68 	return 0;
69 }
70 
disable_test_store(void)71 void disable_test_store(void) {
72 	test_store_enabled = 0;
73 }
74 
enable_test_store(void)75 void enable_test_store(void) {
76 	test_store_enabled = 1;
77 }
78 
write_test_policy(char * data,size_t data_len)79 int write_test_policy(char *data, size_t data_len) {
80 	FILE *fptr = fopen("test-policy/store/active/policy.kern", "wb+");
81 
82 	if (!fptr) {
83 		perror("fopen");
84 		return -1;
85 	}
86 
87 	if (fwrite(data, data_len, 1, fptr) != 1) {
88 		perror("fwrite");
89 		fclose(fptr);
90 		return -1;
91 	}
92 
93 	fclose(fptr);
94 
95 	return 0;
96 }
97 
write_test_policy_from_file(const char * filename)98 int write_test_policy_from_file(const char *filename) {
99 	char *buf = NULL;
100 	size_t len = 0;
101 	FILE *fptr = fopen(filename, "rb");
102 
103 	if (!fptr) {
104 		perror("fopen");
105 		return -1;
106 	}
107 
108 	fseek(fptr, 0, SEEK_END);
109 	len = ftell(fptr);
110 	fseek(fptr, 0, SEEK_SET);
111 
112 	buf = (char *) malloc(len);
113 
114 	if (!buf) {
115 		perror("malloc");
116 		fclose(fptr);
117 		return -1;
118 	}
119 
120 	fread(buf, len, 1, fptr);
121 	fclose(fptr);
122 
123 	return write_test_policy(buf, len);
124 }
125 
write_test_policy_src(unsigned char * data,unsigned int data_len)126 int write_test_policy_src(unsigned char *data, unsigned int data_len) {
127 	if (mkdir("test-policy/store/active/modules/100", 0700) < 0)
128 		return -1;
129 
130 	if (mkdir("test-policy/store/active/modules/100/base", 0700) < 0)
131 		return -1;
132 
133 	FILE *fptr = fopen("test-policy/store/active/modules/100/base/cil",
134 			   "w+");
135 
136 	if (!fptr) {
137 		perror("fopen");
138 		return -1;
139 	}
140 
141 	if (fwrite(data, data_len, 1, fptr) != 1) {
142 		perror("fwrite");
143 		fclose(fptr);
144 		return -1;
145 	}
146 
147 	fclose(fptr);
148 
149 	fptr = fopen("test-policy/store/active/modules/100/base/lang_ext",
150 		     "w+");
151 
152 	if (!fptr) {
153 		perror("fopen");
154 		return -1;
155 	}
156 
157 	if (fwrite("cil", sizeof("cil"), 1, fptr) != 1) {
158 		perror("fwrite");
159 		fclose(fptr);
160 		return -1;
161 	}
162 
163 	fclose(fptr);
164 
165 	return 0;
166 }
167 
destroy_test_store()168 int destroy_test_store() {
169 	FTS *ftsp = NULL;
170 	FTSENT *curr = NULL;
171 	int ret = 0;
172 
173 	disable_test_store();
174 
175 	char *files[] = { (char *) "test-policy", NULL };
176 
177 	ftsp = fts_open(files, FTS_NOCHDIR | FTS_PHYSICAL | FTS_XDEV, NULL);
178 
179 	if (!ftsp)
180 		return -1;
181 
182 	while ((curr = fts_read(ftsp)))
183 		switch (curr->fts_info) {
184 		case FTS_DP:
185 		case FTS_F:
186 		case FTS_SL:
187 		case FTS_SLNONE:
188 		case FTS_DEFAULT:
189 			if (remove(curr->fts_accpath) < 0)
190 				ret = -1;
191 		default:
192 			break;
193 		}
194 
195 	fts_close(ftsp);
196 
197 	return ret;
198 }
199 
helper_handle_create(void)200 void helper_handle_create(void) {
201 	if (test_store_enabled)
202 		semanage_set_root("test-policy");
203 
204 	sh = semanage_handle_create();
205 	CU_ASSERT_PTR_NOT_NULL(sh);
206 
207 	semanage_msg_set_callback(sh, test_msg_handler, NULL);
208 
209 	if (test_store_enabled) {
210 		semanage_set_create_store(sh, 1);
211 		semanage_set_reload(sh, 0);
212 		semanage_set_store_root(sh, "");
213 		semanage_select_store(sh, (char *) "store",
214 				      SEMANAGE_CON_DIRECT);
215 	}
216 }
217 
helper_handle_destroy(void)218 void helper_handle_destroy(void) {
219 	semanage_handle_destroy(sh);
220 }
221 
helper_connect(void)222 void helper_connect(void) {
223 	CU_ASSERT(semanage_connect(sh) >= 0);
224 }
225 
helper_disconnect(void)226 void helper_disconnect(void) {
227 	CU_ASSERT(semanage_disconnect(sh) >= 0);
228 }
229 
helper_begin_transaction(void)230 void helper_begin_transaction(void) {
231 	CU_ASSERT(semanage_begin_transaction(sh) >= 0);
232 }
233 
helper_commit(void)234 void helper_commit(void) {
235 	CU_ASSERT(semanage_commit(sh) >= 0);
236 }
237 
setup_handle(level_t level)238 void setup_handle(level_t level) {
239 	if (level >= SH_NULL)
240 		sh = NULL;
241 
242 	if (level >= SH_HANDLE)
243 		helper_handle_create();
244 
245 	if (level >= SH_CONNECT)
246 		helper_connect();
247 
248 	if (level >= SH_TRANS)
249 		helper_begin_transaction();
250 }
251 
cleanup_handle(level_t level)252 void cleanup_handle(level_t level) {
253 	if (level >= SH_TRANS)
254 		helper_commit();
255 
256 	if (level >= SH_CONNECT)
257 		helper_disconnect();
258 
259 	if (level >= SH_HANDLE)
260 		helper_handle_destroy();
261 
262 	if (level >= SH_NULL)
263 		sh = NULL;
264 }
265 
setup_handle_invalid_store(level_t level)266 void setup_handle_invalid_store(level_t level) {
267 	CU_ASSERT(level >= SH_HANDLE);
268 
269 	helper_handle_create();
270 
271 	semanage_select_store(sh, (char *) "", SEMANAGE_CON_INVALID);
272 
273 	if (level >= SH_CONNECT)
274 		helper_connect();
275 
276 	if (level >= SH_TRANS)
277 		helper_begin_transaction();
278 }
279