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 46semanage_handle_t *sh = NULL; 47const char *rootpath = "./test-policy"; 48const char *polpath = "./test-policy/store/"; 49const char *readlockpath = "./test-policy/store/semanage.read.LOCK"; 50const char *translockpath = "./test-policy/store/semanage.trans.LOCK"; 51const char *actpath = "./test-policy/store/active"; 52const char *modpath = "./test-policy/store/active/modules"; 53 54/* The suite initialization function. 55 * Returns zero on success, non-zero otherwise. 56 */ 57int 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 */ 101int 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 */ 129int 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 */ 155void 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 */ 258void 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 */ 307void 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