1 /* Authors: Christopher Ashworth <cashworth@tresys.com>
2  *          Caleb Case <ccase@tresys.com>
3  *          Chris PeBenito <cpebenito@tresys.com>
4  *
5  * Copyright (C) 2006 Tresys Technology, LLC
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Lesser General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2.1 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public
18  *  License along with this library; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 /*  The purpose of this file is to provide unit tests of the functions in:
23  *
24  *  libsemanage/src/semanage_store.c
25  *
26  */
27 
28 #include "handle.h"
29 #include "semanage_store.h"
30 
31 #include "utilities.h"
32 #include "test_semanage_store.h"
33 
34 #include <libgen.h>
35 #include <limits.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/mman.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <CUnit/Basic.h>
45 
46 semanage_handle_t *sh = NULL;
47 const char *rootpath = "./test-policy";
48 const char *polpath = "./test-policy/store/";
49 const char *readlockpath = "./test-policy/store/semanage.read.LOCK";
50 const char *translockpath = "./test-policy/store/semanage.trans.LOCK";
51 const char *actpath = "./test-policy/store/active";
52 const char *modpath = "./test-policy/store/active/modules";
53 
54 /* The suite initialization function.
55  * Returns zero on success, non-zero otherwise.
56  */
semanage_store_test_init(void)57 int semanage_store_test_init(void)
58 {
59 	int err;
60 
61 	/* create directories */
62 	err = mkdir(rootpath, S_IRUSR | S_IWUSR | S_IXUSR);
63 	if (err != 0)
64 		return -1;
65 
66 	err = mkdir(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
67 	if (err != 0)
68 		return -1;
69 
70 	err = mkdir(actpath, S_IRUSR | S_IWUSR | S_IXUSR);
71 	if (err != 0)
72 		return -1;
73 
74 	err = mkdir(modpath, S_IRUSR | S_IWUSR | S_IXUSR);
75 	if (err != 0)
76 		return -1;
77 
78 	/* initialize the handle */
79 	sh = semanage_handle_create();
80 	if (sh == NULL)
81 		return -1;
82 
83 	/* hide error messages */
84 	sh->msg_callback = test_msg_handler;
85 
86 	/* use our own policy store */
87 	free(sh->conf->store_path);
88 	sh->conf->store_path = strdup("store");
89 
90 	/* initialize paths */
91 	err = semanage_check_init(sh, rootpath);
92 	if (err != 0)
93 		return -1;
94 
95 	return 0;
96 }
97 
98 /* The suite cleanup function.
99  * Returns zero on success, non-zero otherwise.
100  */
semanage_store_test_cleanup(void)101 int semanage_store_test_cleanup(void)
102 {
103 	int err;
104 
105 	/* remove the test policy directories */
106 	err = rmdir(modpath);
107 	if (err != 0)
108 		return -1;
109 
110 	err = rmdir(actpath);
111 	if (err != 0)
112 		return -1;
113 
114 	err = rmdir(polpath);
115 	if (err != 0)
116 		return -1;
117 
118 	err = rmdir(rootpath);
119 	if (err != 0)
120 		return -1;
121 
122 	/* cleanup the handle */
123 	semanage_handle_destroy(sh);
124 	return 0;
125 }
126 
127 /* Adds all the tests needed for this suite.
128  */
semanage_store_add_tests(CU_pSuite suite)129 int semanage_store_add_tests(CU_pSuite suite)
130 {
131 	if (NULL ==
132 	    CU_add_test(suite, "semanage_store_access_check",
133 			test_semanage_store_access_check)) {
134 		CU_cleanup_registry();
135 		return CU_get_error();
136 	}
137 
138 	if (NULL ==
139 	    CU_add_test(suite, "semanage_get_lock", test_semanage_get_lock)) {
140 		CU_cleanup_registry();
141 		return CU_get_error();
142 	}
143 
144 	if (NULL ==
145 	    CU_add_test(suite, "semanage_nc_sort", test_semanage_nc_sort)) {
146 		CU_cleanup_registry();
147 		return CU_get_error();
148 	}
149 
150 	return 0;
151 }
152 
153 /* Tests the semanage_store_access_check function in semanage_store.c
154  */
test_semanage_store_access_check(void)155 void test_semanage_store_access_check(void)
156 {
157 	int err;
158 
159 	/* create lock file */
160 	err = mknod(readlockpath, S_IRUSR | S_IWUSR, S_IFREG);
161 
162 	/* check with permissions 000 */
163 	err = chmod(modpath, 0);
164 	CU_ASSERT(err == 0);
165 	err = chmod(readlockpath, 0);
166 	CU_ASSERT(err == 0);
167 	err = chmod(polpath, 0);
168 	CU_ASSERT(err == 0);
169 
170 	err = semanage_store_access_check();
171 	CU_ASSERT(err == -1);
172 
173 	/* check with permissions 500 */
174 	err = chmod(polpath, S_IRUSR | S_IXUSR);
175 	CU_ASSERT(err == 0);
176 	err = chmod(readlockpath, S_IRUSR);
177 	CU_ASSERT(err == 0);
178 	err = chmod(modpath, S_IRUSR | S_IXUSR);
179 	CU_ASSERT(err == 0);
180 
181 	err = semanage_store_access_check();
182 	CU_ASSERT(err == SEMANAGE_CAN_READ);
183 
184 	/* check with permissions 700 */
185 	err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
186 	CU_ASSERT(err == 0);
187 	err = chmod(readlockpath, S_IRUSR | S_IWUSR);
188 	CU_ASSERT(err == 0);
189 	err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR);
190 	CU_ASSERT(err == 0);
191 
192 	err = semanage_store_access_check();
193 	CU_ASSERT(err == SEMANAGE_CAN_WRITE);
194 
195 	/* check with lock file 000 and others 500 */
196 	err = chmod(polpath, S_IRUSR | S_IXUSR);
197 	CU_ASSERT(err == 0);
198 	err = chmod(readlockpath, 0);
199 	CU_ASSERT(err == 0);
200 	err = chmod(modpath, S_IRUSR | S_IXUSR);
201 	CU_ASSERT(err == 0);
202 
203 	err = semanage_store_access_check();
204 	CU_ASSERT(err == 0);
205 
206 	/* check with lock file 000 and others 700 */
207 	err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
208 	CU_ASSERT(err == 0);
209 	err = chmod(readlockpath, 0);
210 	CU_ASSERT(err == 0);
211 	err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR);
212 	CU_ASSERT(err == 0);
213 
214 	err = semanage_store_access_check();
215 	CU_ASSERT(err == 0);
216 
217 	/* remove lock file */
218 	err = remove(readlockpath);
219 	CU_ASSERT(err == 0);
220 
221 	/* check with no lock file and 000 */
222 	err = chmod(modpath, 0);
223 	CU_ASSERT(err == 0);
224 	err = chmod(polpath, 0);
225 	CU_ASSERT(err == 0);
226 
227 	err = semanage_store_access_check();
228 	CU_ASSERT(err == -1);
229 
230 	/* check with no lock file and 500 */
231 	err = chmod(polpath, S_IRUSR | S_IXUSR);
232 	CU_ASSERT(err == 0);
233 	err = chmod(modpath, S_IRUSR | S_IXUSR);
234 	CU_ASSERT(err == 0);
235 
236 	err = semanage_store_access_check();
237 	CU_ASSERT(err == 0);
238 
239 	/* check with no lock file but write in polpath */
240 	err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
241 	CU_ASSERT(err == 0);
242 
243 	err = semanage_store_access_check();
244 	CU_ASSERT(err == SEMANAGE_CAN_READ);
245 
246 	/* check with no lock file and 700 */
247 	err = chmod(polpath, S_IRUSR | S_IWUSR | S_IXUSR);
248 	CU_ASSERT(err == 0);
249 	err = chmod(modpath, S_IRUSR | S_IWUSR | S_IXUSR);
250 	CU_ASSERT(err == 0);
251 
252 	err = semanage_store_access_check();
253 	CU_ASSERT(err == SEMANAGE_CAN_WRITE);
254 }
255 
256 /* Tests the semanage_get_lock functions in semanage_store.c
257  */
test_semanage_get_lock(void)258 void test_semanage_get_lock(void)
259 {
260 	int err;
261 
262 	/* attempt to get an active lock */
263 	err = semanage_get_active_lock(sh);
264 	CU_ASSERT(err == 0);
265 
266 	/* attempt to get the lock again */
267 	err = semanage_get_active_lock(sh);
268 	CU_ASSERT(err == 0);
269 
270 	/* attempt to release the active lock */
271 	semanage_release_active_lock(sh);
272 
273 	/* attempt to get an active lock */
274 	err = semanage_get_active_lock(sh);
275 	CU_ASSERT(err == 0);
276 
277 	/* attempt to release the active lock */
278 	semanage_release_active_lock(sh);
279 
280 	/* attempt to get a trans lock */
281 	err = semanage_get_trans_lock(sh);
282 	CU_ASSERT(err == 0);
283 
284 	/* attempt to get the lock again */
285 	err = semanage_get_trans_lock(sh);
286 	CU_ASSERT(err == 0);
287 
288 	/* attempt to release the trans lock */
289 	semanage_release_trans_lock(sh);
290 
291 	/* attempt to get a trans lock */
292 	err = semanage_get_trans_lock(sh);
293 	CU_ASSERT(err == 0);
294 
295 	/* attempt to release the trans lock */
296 	semanage_release_trans_lock(sh);
297 
298 	/* remove the lock files */
299 	err = remove(readlockpath);
300 	CU_ASSERT(err == 0);
301 	err = remove(translockpath);
302 	CU_ASSERT(err == 0);
303 }
304 
305 /* Tests the semanage_nc_sort function in semanage_store.c
306  */
test_semanage_nc_sort(void)307 void test_semanage_nc_sort(void)
308 {
309 	char *source_buf, *sorted_buf = NULL, *good_buf, *bad_buf;
310 	size_t source_buf_len, sorted_buf_len, good_buf_len, bad_buf_len;
311 	int sourcefd, goodfd, badfd, err;
312 	struct stat sb;
313 
314 	/* open source file */
315 	sourcefd = open("nc_sort_unsorted", O_RDONLY);
316 	if (sourcefd < 0) {
317 		CU_FAIL("Missing nc_sort_unsorted test file.");
318 		return;
319 	}
320 	fstat(sourcefd, &sb);
321 	source_buf_len = sb.st_size;
322 	source_buf =
323 	    (char *)mmap(NULL, source_buf_len, PROT_READ, MAP_PRIVATE, sourcefd,
324 			 0);
325 
326 	/* open good result file */
327 	goodfd = open("nc_sort_sorted", O_RDONLY);
328 	if (goodfd < 0) {
329 		CU_FAIL("Missing nc_sort_sorted test file.");
330 		goto out2;
331 	}
332 	fstat(goodfd, &sb);
333 	good_buf_len = sb.st_size;
334 	good_buf =
335 	    (char *)mmap(NULL, good_buf_len, PROT_READ, MAP_PRIVATE, goodfd, 0);
336 
337 	/* open malformed source file (missing priorities) */
338 	badfd = open("nc_sort_malformed", O_RDONLY);
339 	if (badfd < 0) {
340 		CU_FAIL("Missing nc_sort_malformed test file.");
341 		goto out1;
342 	}
343 	fstat(badfd, &sb);
344 	bad_buf_len = sb.st_size;
345 	bad_buf =
346 	    (char *)mmap(NULL, bad_buf_len, PROT_READ, MAP_PRIVATE, badfd, 0);
347 
348 	/* sort test file */
349 	err =
350 	    semanage_nc_sort(sh, source_buf, source_buf_len, &sorted_buf,
351 			     &sorted_buf_len);
352 	CU_ASSERT_FALSE(err);
353 	CU_ASSERT_STRING_EQUAL(sorted_buf, good_buf);
354 
355 	/* reset for reuse in next test */
356 	free(sorted_buf);
357 	sorted_buf = NULL;
358 
359 	/* sort malformed source file */
360 	err =
361 	    semanage_nc_sort(sh, bad_buf, bad_buf_len, &sorted_buf,
362 			     &sorted_buf_len);
363 	CU_ASSERT_EQUAL(err, -1);
364 
365 	free(sorted_buf);
366 
367 	munmap(bad_buf, bad_buf_len);
368 	close(badfd);
369       out1:
370 	munmap(good_buf, good_buf_len);
371 	close(goodfd);
372       out2:
373 	munmap(source_buf, source_buf_len);
374 	close(sourcefd);
375 }
376