16cd6a6acSopenharmony_ci/* 26cd6a6acSopenharmony_ci * Copyright 2011 Tresys Technology, LLC. All rights reserved. 36cd6a6acSopenharmony_ci * 46cd6a6acSopenharmony_ci * Redistribution and use in source and binary forms, with or without 56cd6a6acSopenharmony_ci * modification, are permitted provided that the following conditions are met: 66cd6a6acSopenharmony_ci * 76cd6a6acSopenharmony_ci * 1. Redistributions of source code must retain the above copyright notice, 86cd6a6acSopenharmony_ci * this list of conditions and the following disclaimer. 96cd6a6acSopenharmony_ci * 106cd6a6acSopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright notice, 116cd6a6acSopenharmony_ci * this list of conditions and the following disclaimer in the documentation 126cd6a6acSopenharmony_ci * and/or other materials provided with the distribution. 136cd6a6acSopenharmony_ci * 146cd6a6acSopenharmony_ci * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS 156cd6a6acSopenharmony_ci * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 166cd6a6acSopenharmony_ci * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 176cd6a6acSopenharmony_ci * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 186cd6a6acSopenharmony_ci * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 196cd6a6acSopenharmony_ci * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 206cd6a6acSopenharmony_ci * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 216cd6a6acSopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 226cd6a6acSopenharmony_ci * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 236cd6a6acSopenharmony_ci * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 246cd6a6acSopenharmony_ci * 256cd6a6acSopenharmony_ci * The views and conclusions contained in the software and documentation are those 266cd6a6acSopenharmony_ci * of the authors and should not be interpreted as representing official policies, 276cd6a6acSopenharmony_ci * either expressed or implied, of Tresys Technology, LLC. 286cd6a6acSopenharmony_ci */ 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci#include <stdlib.h> 316cd6a6acSopenharmony_ci#include <stdio.h> 326cd6a6acSopenharmony_ci#include <stdint.h> 336cd6a6acSopenharmony_ci#include <string.h> 346cd6a6acSopenharmony_ci#include <getopt.h> 356cd6a6acSopenharmony_ci#include <sys/stat.h> 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_ci#ifdef ANDROID 386cd6a6acSopenharmony_ci#include <cil/cil.h> 396cd6a6acSopenharmony_ci#else 406cd6a6acSopenharmony_ci#include <sepol/cil/cil.h> 416cd6a6acSopenharmony_ci#endif 426cd6a6acSopenharmony_ci#include <sepol/policydb.h> 436cd6a6acSopenharmony_ci 446cd6a6acSopenharmony_cienum write_ast_phase { 456cd6a6acSopenharmony_ci WRITE_AST_PHASE_PARSE = 0, 466cd6a6acSopenharmony_ci WRITE_AST_PHASE_BUILD, 476cd6a6acSopenharmony_ci WRITE_AST_PHASE_RESOLVE, 486cd6a6acSopenharmony_ci}; 496cd6a6acSopenharmony_ci 506cd6a6acSopenharmony_cistatic __attribute__((__noreturn__)) void usage(const char *prog) 516cd6a6acSopenharmony_ci{ 526cd6a6acSopenharmony_ci printf("Usage: %s [OPTION]... FILE...\n", prog); 536cd6a6acSopenharmony_ci printf("\n"); 546cd6a6acSopenharmony_ci printf("Options:\n"); 556cd6a6acSopenharmony_ci printf(" -o, --output=<file> write AST to <file>. (default: stdout)\n"); 566cd6a6acSopenharmony_ci printf(" -P, --preserve-tunables treat tunables as booleans\n"); 576cd6a6acSopenharmony_ci printf(" -Q, --qualified-names Allow names containing dots (qualified names).\n"); 586cd6a6acSopenharmony_ci printf(" Blocks, blockinherits, blockabstracts, and\n"); 596cd6a6acSopenharmony_ci printf(" in-statements will not be allowed.\n"); 606cd6a6acSopenharmony_ci printf(" -A, --ast-phase=<phase> write AST of phase <phase>. Phase must be parse, \n"); 616cd6a6acSopenharmony_ci printf(" build, or resolve. (default: resolve)\n"); 626cd6a6acSopenharmony_ci printf(" -v, --verbose increment verbosity level\n"); 636cd6a6acSopenharmony_ci printf(" -h, --help display usage information\n"); 646cd6a6acSopenharmony_ci exit(1); 656cd6a6acSopenharmony_ci} 666cd6a6acSopenharmony_ci 676cd6a6acSopenharmony_ciint main(int argc, char *argv[]) 686cd6a6acSopenharmony_ci{ 696cd6a6acSopenharmony_ci int rc = SEPOL_ERR; 706cd6a6acSopenharmony_ci FILE *file = NULL; 716cd6a6acSopenharmony_ci char *buffer = NULL; 726cd6a6acSopenharmony_ci struct stat filedata; 736cd6a6acSopenharmony_ci uint32_t file_size; 746cd6a6acSopenharmony_ci char *output = NULL; 756cd6a6acSopenharmony_ci struct cil_db *db = NULL; 766cd6a6acSopenharmony_ci int preserve_tunables = 0; 776cd6a6acSopenharmony_ci int qualified_names = 0; 786cd6a6acSopenharmony_ci enum write_ast_phase write_ast = WRITE_AST_PHASE_RESOLVE; 796cd6a6acSopenharmony_ci int opt_char; 806cd6a6acSopenharmony_ci int opt_index = 0; 816cd6a6acSopenharmony_ci enum cil_log_level log_level = CIL_ERR; 826cd6a6acSopenharmony_ci static struct option long_opts[] = { 836cd6a6acSopenharmony_ci {"help", no_argument, 0, 'h'}, 846cd6a6acSopenharmony_ci {"verbose", no_argument, 0, 'v'}, 856cd6a6acSopenharmony_ci {"preserve-tunables", no_argument, 0, 'P'}, 866cd6a6acSopenharmony_ci {"qualified-names", no_argument, 0, 'Q'}, 876cd6a6acSopenharmony_ci {"output", required_argument, 0, 'o'}, 886cd6a6acSopenharmony_ci {"ast-phase", required_argument, 0, 'A'}, 896cd6a6acSopenharmony_ci {0, 0, 0, 0} 906cd6a6acSopenharmony_ci }; 916cd6a6acSopenharmony_ci int i; 926cd6a6acSopenharmony_ci 936cd6a6acSopenharmony_ci while (1) { 946cd6a6acSopenharmony_ci opt_char = getopt_long(argc, argv, "o:hvPQA:", long_opts, &opt_index); 956cd6a6acSopenharmony_ci if (opt_char == -1) { 966cd6a6acSopenharmony_ci break; 976cd6a6acSopenharmony_ci } 986cd6a6acSopenharmony_ci switch (opt_char) { 996cd6a6acSopenharmony_ci case 'v': 1006cd6a6acSopenharmony_ci log_level++; 1016cd6a6acSopenharmony_ci break; 1026cd6a6acSopenharmony_ci case 'P': 1036cd6a6acSopenharmony_ci preserve_tunables = 1; 1046cd6a6acSopenharmony_ci break; 1056cd6a6acSopenharmony_ci case 'Q': 1066cd6a6acSopenharmony_ci qualified_names = 1; 1076cd6a6acSopenharmony_ci break; 1086cd6a6acSopenharmony_ci case 'o': 1096cd6a6acSopenharmony_ci output = strdup(optarg); 1106cd6a6acSopenharmony_ci break; 1116cd6a6acSopenharmony_ci case 'A': 1126cd6a6acSopenharmony_ci if (!strcasecmp(optarg, "parse")) { 1136cd6a6acSopenharmony_ci write_ast = WRITE_AST_PHASE_PARSE; 1146cd6a6acSopenharmony_ci } else if (!strcasecmp(optarg, "build")) { 1156cd6a6acSopenharmony_ci write_ast = WRITE_AST_PHASE_BUILD; 1166cd6a6acSopenharmony_ci } else if (!strcasecmp(optarg, "resolve")) { 1176cd6a6acSopenharmony_ci write_ast = WRITE_AST_PHASE_RESOLVE; 1186cd6a6acSopenharmony_ci } else { 1196cd6a6acSopenharmony_ci fprintf(stderr, "Invalid AST phase: %s\n", optarg); 1206cd6a6acSopenharmony_ci usage(argv[0]); 1216cd6a6acSopenharmony_ci } 1226cd6a6acSopenharmony_ci break; 1236cd6a6acSopenharmony_ci case 'h': 1246cd6a6acSopenharmony_ci usage(argv[0]); 1256cd6a6acSopenharmony_ci case '?': 1266cd6a6acSopenharmony_ci break; 1276cd6a6acSopenharmony_ci default: 1286cd6a6acSopenharmony_ci fprintf(stderr, "Unsupported option: %s\n", optarg); 1296cd6a6acSopenharmony_ci usage(argv[0]); 1306cd6a6acSopenharmony_ci } 1316cd6a6acSopenharmony_ci } 1326cd6a6acSopenharmony_ci 1336cd6a6acSopenharmony_ci if (optind >= argc) { 1346cd6a6acSopenharmony_ci fprintf(stderr, "No cil files specified\n"); 1356cd6a6acSopenharmony_ci usage(argv[0]); 1366cd6a6acSopenharmony_ci } 1376cd6a6acSopenharmony_ci 1386cd6a6acSopenharmony_ci cil_set_log_level(log_level); 1396cd6a6acSopenharmony_ci 1406cd6a6acSopenharmony_ci cil_db_init(&db); 1416cd6a6acSopenharmony_ci cil_set_preserve_tunables(db, preserve_tunables); 1426cd6a6acSopenharmony_ci cil_set_qualified_names(db, qualified_names); 1436cd6a6acSopenharmony_ci cil_set_attrs_expand_generated(db, 0); 1446cd6a6acSopenharmony_ci cil_set_attrs_expand_size(db, 0); 1456cd6a6acSopenharmony_ci 1466cd6a6acSopenharmony_ci for (i = optind; i < argc; i++) { 1476cd6a6acSopenharmony_ci file = fopen(argv[i], "r"); 1486cd6a6acSopenharmony_ci if (!file) { 1496cd6a6acSopenharmony_ci fprintf(stderr, "Could not open file: %s\n", argv[i]); 1506cd6a6acSopenharmony_ci rc = SEPOL_ERR; 1516cd6a6acSopenharmony_ci goto exit; 1526cd6a6acSopenharmony_ci } 1536cd6a6acSopenharmony_ci rc = stat(argv[i], &filedata); 1546cd6a6acSopenharmony_ci if (rc == -1) { 1556cd6a6acSopenharmony_ci fprintf(stderr, "Could not stat file: %s\n", argv[i]); 1566cd6a6acSopenharmony_ci goto exit; 1576cd6a6acSopenharmony_ci } 1586cd6a6acSopenharmony_ci file_size = filedata.st_size; 1596cd6a6acSopenharmony_ci 1606cd6a6acSopenharmony_ci buffer = malloc(file_size); 1616cd6a6acSopenharmony_ci rc = fread(buffer, file_size, 1, file); 1626cd6a6acSopenharmony_ci if (rc != 1) { 1636cd6a6acSopenharmony_ci fprintf(stderr, "Failure reading file: %s\n", argv[i]); 1646cd6a6acSopenharmony_ci goto exit; 1656cd6a6acSopenharmony_ci } 1666cd6a6acSopenharmony_ci fclose(file); 1676cd6a6acSopenharmony_ci file = NULL; 1686cd6a6acSopenharmony_ci 1696cd6a6acSopenharmony_ci rc = cil_add_file(db, argv[i], buffer, file_size); 1706cd6a6acSopenharmony_ci if (rc != SEPOL_OK) { 1716cd6a6acSopenharmony_ci fprintf(stderr, "Failure adding %s\n", argv[i]); 1726cd6a6acSopenharmony_ci goto exit; 1736cd6a6acSopenharmony_ci } 1746cd6a6acSopenharmony_ci 1756cd6a6acSopenharmony_ci free(buffer); 1766cd6a6acSopenharmony_ci buffer = NULL; 1776cd6a6acSopenharmony_ci } 1786cd6a6acSopenharmony_ci 1796cd6a6acSopenharmony_ci if (output == NULL) { 1806cd6a6acSopenharmony_ci file = stdout; 1816cd6a6acSopenharmony_ci } else { 1826cd6a6acSopenharmony_ci file = fopen(output, "w"); 1836cd6a6acSopenharmony_ci if (file == NULL) { 1846cd6a6acSopenharmony_ci fprintf(stderr, "Failure opening file %s for writing\n", output); 1856cd6a6acSopenharmony_ci rc = SEPOL_ERR; 1866cd6a6acSopenharmony_ci goto exit; 1876cd6a6acSopenharmony_ci } 1886cd6a6acSopenharmony_ci } 1896cd6a6acSopenharmony_ci 1906cd6a6acSopenharmony_ci switch (write_ast) { 1916cd6a6acSopenharmony_ci case WRITE_AST_PHASE_PARSE: 1926cd6a6acSopenharmony_ci rc = cil_write_parse_ast(file, db); 1936cd6a6acSopenharmony_ci break; 1946cd6a6acSopenharmony_ci case WRITE_AST_PHASE_BUILD: 1956cd6a6acSopenharmony_ci rc = cil_write_build_ast(file, db); 1966cd6a6acSopenharmony_ci break; 1976cd6a6acSopenharmony_ci case WRITE_AST_PHASE_RESOLVE: 1986cd6a6acSopenharmony_ci rc = cil_write_resolve_ast(file, db); 1996cd6a6acSopenharmony_ci break; 2006cd6a6acSopenharmony_ci } 2016cd6a6acSopenharmony_ci 2026cd6a6acSopenharmony_ci if (rc != SEPOL_OK) { 2036cd6a6acSopenharmony_ci fprintf(stderr, "Failed to write AST\n"); 2046cd6a6acSopenharmony_ci goto exit; 2056cd6a6acSopenharmony_ci } 2066cd6a6acSopenharmony_ci 2076cd6a6acSopenharmony_ciexit: 2086cd6a6acSopenharmony_ci if (file != NULL && file != stdin) { 2096cd6a6acSopenharmony_ci fclose(file); 2106cd6a6acSopenharmony_ci } 2116cd6a6acSopenharmony_ci free(buffer); 2126cd6a6acSopenharmony_ci free(output); 2136cd6a6acSopenharmony_ci cil_db_destroy(&db); 2146cd6a6acSopenharmony_ci return rc; 2156cd6a6acSopenharmony_ci} 216