1 /* 2 * Copyright 2011 Tresys Technology, LLC. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * 1. Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS 15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 * The views and conclusions contained in the software and documentation are those 26 * of the authors and should not be interpreted as representing official policies, 27 * either expressed or implied, of Tresys Technology, LLC. 28 */ 29 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <stdint.h> 33 #include <string.h> 34 #include <getopt.h> 35 #include <sys/stat.h> 36 37 #ifdef ANDROID 38 #include <sepol/cil.h> 39 #else 40 #include <sepol/cil/cil.h> 41 #endif 42 #include <sepol/policydb.h> 43 44 void usage(char *prog) 45 { 46 printf("Usage: %s [OPTION]... FILE...\n", prog); 47 printf("\n"); 48 printf("Options:\n"); 49 printf(" -o, --output=<file> write binary policy to <file>\n"); 50 printf(" (default: policy.<version>)\n"); 51 printf(" -f, --filecontext=<file> write file contexts to <file>\n"); 52 printf(" (default: file_contexts)\n"); 53 printf(" -t, --target=<type> specify target architecture. may be selinux or\n"); 54 printf(" xen. (default: selinux)\n"); 55 printf(" -M, --mls true|false build an mls policy. Must be true or false.\n"); 56 printf(" This will override the (mls boolean) statement\n"); 57 printf(" if present in the policy\n"); 58 printf(" -c, --policyvers=<version> build a binary policy with a given <version>\n"); 59 printf(" (default: %i)\n", POLICYDB_VERSION_MAX); 60 printf(" -U, --handle-unknown=<action> how to handle unknown classes or permissions.\n"); 61 printf(" may be deny, allow, or reject. (default: deny)\n"); 62 printf(" This will override the (handleunknown action)\n"); 63 printf(" statement if present in the policy\n"); 64 printf(" -D, --disable-dontaudit do not add dontaudit rules to the binary policy\n"); 65 printf(" -P, --preserve-tunables treat tunables as booleans\n"); 66 printf(" -N, --disable-neverallow do not check neverallow rules\n"); 67 printf(" -v, --verbose increment verbosity level\n"); 68 printf(" -h, --help display usage information\n"); 69 exit(1); 70 } 71 72 int main(int argc, char *argv[]) 73 { 74 int rc = SEPOL_ERR; 75 sepol_policydb_t *pdb = NULL; 76 struct sepol_policy_file *pf = NULL; 77 FILE *binary = NULL; 78 FILE *file_contexts; 79 FILE *file = NULL; 80 char *buffer = NULL; 81 struct stat filedata; 82 uint32_t file_size; 83 char *output = NULL; 84 char *filecontexts = NULL; 85 struct cil_db *db = NULL; 86 int target = SEPOL_TARGET_SELINUX; 87 int mls = -1; 88 int disable_dontaudit = 0; 89 int disable_neverallow = 0; 90 int preserve_tunables = 0; 91 int handle_unknown = -1; 92 int policyvers = POLICYDB_VERSION_MAX; 93 int opt_char; 94 int opt_index = 0; 95 char *fc_buf = NULL; 96 size_t fc_size; 97 enum cil_log_level log_level = CIL_ERR; 98 static struct option long_opts[] = { 99 {"help", no_argument, 0, 'h'}, 100 {"verbose", no_argument, 0, 'v'}, 101 {"target", required_argument, 0, 't'}, 102 {"mls", required_argument, 0, 'M'}, 103 {"policyversion", required_argument, 0, 'c'}, 104 {"handle-unknown", required_argument, 0, 'U'}, 105 {"disable-dontaudit", no_argument, 0, 'D'}, 106 {"disable-neverallow", no_argument, 0, 'N'}, 107 {"preserve-tunables", no_argument, 0, 'P'}, 108 {"output", required_argument, 0, 'o'}, 109 {"filecontexts", required_argument, 0, 'f'}, 110 {0, 0, 0, 0} 111 }; 112 int i; 113 114 while (1) { 115 opt_char = getopt_long(argc, argv, "o:f:U:hvt:M:PDNc:", long_opts, &opt_index); 116 if (opt_char == -1) { 117 break; 118 } 119 switch (opt_char) { 120 case 'v': 121 log_level++; 122 break; 123 case 't': 124 if (!strcmp(optarg, "selinux")) { 125 target = SEPOL_TARGET_SELINUX; 126 } else if (!strcmp(optarg, "xen")) { 127 target = SEPOL_TARGET_XEN; 128 } else { 129 fprintf(stderr, "Unknown target: %s\n", optarg); 130 usage(argv[0]); 131 } 132 break; 133 case 'M': 134 if (!strcasecmp(optarg, "true") || !strcasecmp(optarg, "1")) { 135 mls = 1; 136 } else if (!strcasecmp(optarg, "false") || !strcasecmp(optarg, "0")) { 137 mls = 0; 138 } else { 139 usage(argv[0]); 140 } 141 break; 142 case 'c': { 143 char *endptr = NULL; 144 errno = 0; 145 policyvers = strtol(optarg, &endptr, 10); 146 if (errno != 0 || endptr == optarg || *endptr != '\0') { 147 fprintf(stderr, "Bad policy version: %s\n", optarg); 148 usage(argv[0]); 149 } 150 if (policyvers > POLICYDB_VERSION_MAX || policyvers < POLICYDB_VERSION_MIN) { 151 fprintf(stderr, "Policy version must be between %d and %d\n", 152 POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); 153 usage(argv[0]); 154 } 155 break; 156 } 157 case 'U': 158 if (!strcasecmp(optarg, "deny")) { 159 handle_unknown = SEPOL_DENY_UNKNOWN; 160 } else if (!strcasecmp(optarg, "allow")) { 161 handle_unknown = SEPOL_ALLOW_UNKNOWN; 162 } else if (!strcasecmp(optarg, "reject")) { 163 handle_unknown = SEPOL_REJECT_UNKNOWN; 164 } else { 165 usage(argv[0]); 166 } 167 break; 168 case 'D': 169 disable_dontaudit = 1; 170 break; 171 case 'N': 172 disable_neverallow = 1; 173 break; 174 case 'P': 175 preserve_tunables = 1; 176 break; 177 case 'o': 178 output = strdup(optarg); 179 break; 180 case 'f': 181 filecontexts = strdup(optarg); 182 break; 183 case 'h': 184 usage(argv[0]); 185 case '?': 186 break; 187 default: 188 fprintf(stderr, "Unsupported option: %s\n", optarg); 189 usage(argv[0]); 190 } 191 } 192 if (optind >= argc) { 193 fprintf(stderr, "No cil files specified\n"); 194 usage(argv[0]); 195 } 196 197 cil_set_log_level(log_level); 198 199 cil_db_init(&db); 200 cil_set_disable_dontaudit(db, disable_dontaudit); 201 cil_set_disable_neverallow(db, disable_neverallow); 202 cil_set_preserve_tunables(db, preserve_tunables); 203 if (handle_unknown != -1) { 204 rc = cil_set_handle_unknown(db, handle_unknown); 205 if (rc != SEPOL_OK) { 206 goto exit; 207 } 208 } 209 210 cil_set_mls(db, mls); 211 cil_set_target_platform(db, target); 212 cil_set_policy_version(db, policyvers); 213 214 for (i = optind; i < argc; i++) { 215 file = fopen(argv[i], "r"); 216 if (!file) { 217 fprintf(stderr, "Could not open file: %s\n", argv[i]); 218 rc = SEPOL_ERR; 219 goto exit; 220 } 221 rc = stat(argv[i], &filedata); 222 if (rc == -1) { 223 fprintf(stderr, "Could not stat file: %s\n", argv[i]); 224 goto exit; 225 } 226 file_size = filedata.st_size; 227 228 buffer = malloc(file_size); 229 rc = fread(buffer, file_size, 1, file); 230 if (rc != 1) { 231 fprintf(stderr, "Failure reading file: %s\n", argv[i]); 232 goto exit; 233 } 234 fclose(file); 235 file = NULL; 236 237 rc = cil_add_file(db, argv[i], buffer, file_size); 238 if (rc != SEPOL_OK) { 239 fprintf(stderr, "Failure adding %s\n", argv[i]); 240 goto exit; 241 } 242 243 free(buffer); 244 buffer = NULL; 245 } 246 247 rc = cil_compile(db); 248 if (rc != SEPOL_OK) { 249 fprintf(stderr, "Failed to compile cildb: %d\n", rc); 250 goto exit; 251 } 252 253 rc = cil_build_policydb(db, &pdb); 254 if (rc != SEPOL_OK) { 255 fprintf(stderr, "Failed to build policydb\n"); 256 goto exit; 257 } 258 259 if (output == NULL) { 260 int size = snprintf(NULL, 0, "policy.%d", policyvers); 261 output = malloc((size + 1) * sizeof(char)); 262 if (output == NULL) { 263 fprintf(stderr, "Failed to create output filename\n"); 264 rc = SEPOL_ERR; 265 goto exit; 266 } 267 if (snprintf(output, size + 1, "policy.%d", policyvers) != size) { 268 fprintf(stderr, "Failed to create output filename\n"); 269 rc = SEPOL_ERR; 270 goto exit; 271 } 272 } 273 274 binary = fopen(output, "w"); 275 if (binary == NULL) { 276 fprintf(stderr, "Failure opening binary file for writing\n"); 277 rc = SEPOL_ERR; 278 goto exit; 279 } 280 281 rc = sepol_policy_file_create(&pf); 282 if (rc != 0) { 283 fprintf(stderr, "Failed to create policy file: %d\n", rc); 284 goto exit; 285 } 286 287 sepol_policy_file_set_fp(pf, binary); 288 289 rc = sepol_policydb_write(pdb, pf); 290 if (rc != 0) { 291 fprintf(stderr, "Failed to write binary policy: %d\n", rc); 292 goto exit; 293 } 294 295 fclose(binary); 296 binary = NULL; 297 298 rc = cil_filecons_to_string(db, &fc_buf, &fc_size); 299 if (rc != SEPOL_OK) { 300 fprintf(stderr, "Failed to get file context data\n"); 301 goto exit; 302 } 303 304 if (filecontexts == NULL) { 305 file_contexts = fopen("file_contexts", "w+"); 306 } else { 307 file_contexts = fopen(filecontexts, "w+"); 308 } 309 310 if (file_contexts == NULL) { 311 fprintf(stderr, "Failed to open file_contexts file\n"); 312 goto exit; 313 } 314 315 if (fwrite(fc_buf, sizeof(char), fc_size, file_contexts) != fc_size) { 316 fprintf(stderr, "Failed to write file_contexts file\n"); 317 goto exit; 318 } 319 320 fclose(file_contexts); 321 file_contexts = NULL; 322 323 rc = SEPOL_OK; 324 325 exit: 326 if (binary != NULL) { 327 fclose(binary); 328 } 329 if (file != NULL) { 330 fclose(file); 331 } 332 free(buffer); 333 free(output); 334 free(filecontexts); 335 cil_db_destroy(&db); 336 sepol_policydb_free(pdb); 337 sepol_policy_file_free(pf); 338 free(fc_buf); 339 return rc; 340 } 341