Home | History | Annotate | Download | only in tools
      1 /*
      2  * version_policy.c - Takes the given public platform policy, a private policy
      3  * and a version number to produced a combined "versioned" policy file.
      4  */
      5 #include <errno.h>
      6 #include <getopt.h>
      7 #include <stdbool.h>
      8 #include <stdio.h>
      9 #include <sys/stat.h>
     10 #include <cil/android.h>
     11 #include <cil/cil.h>
     12 #include <cil/cil_write_ast.h>
     13 
     14 void __attribute__ ((noreturn)) static usage(char *prog) {
     15 	printf("Usage: %s [OPTION]...\n", prog);
     16 	printf("\n");
     17 	printf("Options:\n");
     18 	printf("  -b, --base=<file>          (req'd) base policy for versioning.\n");
     19 	printf("  -m, --mapping              generate cil version  mapping from base policy\n");
     20 	printf("  -n, --number               (req'd) version number to use.\n");
     21 	printf("  -o, --output=<file>        write cil policy to <file>\n");
     22 	printf("  -t, --tgt_policy           policy to be versioned according to base policy\n");
     23 	printf("  -h, --help                 display usage information\n");
     24 	exit(1);
     25 }
     26 
     27 /*
     28  * read_cil_file - Initialize db and parse CIL input file.
     29  */
     30 static int read_cil_file(struct cil_db **db, char *path) {
     31 	int rc = SEPOL_ERR;
     32 	FILE *file;
     33 	struct stat filedata;
     34 	uint32_t file_size;
     35 	char *buff = NULL;
     36 
     37 	cil_db_init(db);
     38 	file = fopen(path, "re");
     39 	if (!file) {
     40 		fprintf(stderr, "Could not open file: %s\n", path);
     41 		goto file_err;
     42 	}
     43 	rc = stat(path, &filedata);
     44 	if (rc == -1) {
     45 		fprintf(stderr, "Could not stat file: %s - %s\n", path, strerror(errno));
     46 		goto err;
     47 	}
     48 	file_size = filedata.st_size;
     49 	buff = malloc(file_size);
     50 	if (buff == NULL) {
     51 		fprintf(stderr, "OOM!\n");
     52 		rc = SEPOL_ERR;
     53 		goto err;
     54 	}
     55 	rc = fread(buff, file_size, 1, file);
     56 	if (rc != 1) {
     57 		fprintf(stderr, "Failure reading file: %s\n", path);
     58 		rc = SEPOL_ERR;
     59 		goto err;
     60 	}
     61 	fclose(file);
     62 	file = NULL;
     63 
     64 	/* creates parse_tree */
     65 	rc = cil_add_file(*db, path, buff, file_size);
     66 	if (rc != SEPOL_OK) {
     67 		fprintf(stderr, "Failure adding %s to parse tree\n", path);
     68 		goto err;
     69 	}
     70 	free(buff);
     71 
     72 	return SEPOL_OK;
     73 err:
     74 	free(buff);
     75 	fclose(file);
     76 file_err:
     77 	cil_db_destroy(db);
     78 	return rc;
     79 }
     80 
     81 int main(int argc, char *argv[])
     82 {
     83 	int opt_char;
     84 	int opt_index = 0;
     85 	int rc = SEPOL_ERR;
     86 	bool mapping = false;
     87 	char *base = NULL;
     88 	char *tgt_policy = NULL;
     89 	char *num = NULL;
     90 	char *dot;
     91 	char *output = NULL;
     92 	struct cil_db *base_db = NULL;
     93 	struct cil_db *out_db = NULL;
     94 
     95 	static struct option long_opts[] = {
     96 		{"help", no_argument, 0, 'h'},
     97 		{"base", required_argument, 0, 'b'},
     98 		{"mapping", no_argument, 0, 'm'},
     99 		{"number", required_argument, 0, 'n'},
    100 		{"output", required_argument, 0, 'o'},
    101 		{"tgt_policy", required_argument, 0, 't'},
    102 		{0, 0, 0, 0}
    103 	};
    104 
    105 	while (1) {
    106 		opt_char = getopt_long(argc, argv, "b:mn:o:t:h", long_opts, &opt_index);
    107 		if (opt_char == -1) {
    108 			break;
    109 		}
    110 		switch (opt_char) {
    111 		case 'b':
    112 			base = strdup(optarg);
    113 			break;
    114 		case 'm':
    115 			mapping = true;
    116 			break;
    117 		case 'n':
    118 			num = strdup(optarg);
    119 			break;
    120 		case 'o':
    121 			output = strdup(optarg);
    122 			break;
    123 		case 't':
    124 			tgt_policy = strdup(optarg);
    125 			break;
    126 		case 'h':
    127 			usage(argv[0]);
    128 		default:
    129 			fprintf(stderr, "Unsupported option: %s\n", optarg);
    130 			usage(argv[0]);
    131 		}
    132 	}
    133 	if (optind < argc) {
    134 		fprintf(stderr, "Unknown arguments supplied\n");
    135 		usage(argv[0]);
    136 	}
    137 	if (num == NULL || base == NULL || (mapping == false && tgt_policy == NULL)) {
    138 		fprintf(stderr, "Please specify required arguments\n");
    139 		usage(argv[0]);
    140 	}
    141 
    142 	/* policy language doesn't like '.', so replace them with '_' in mapping version */
    143 	dot = num;
    144 	while ((dot = strchr(dot, '.')) != NULL) {
    145 		*dot = '_';
    146 		++dot;
    147 	}
    148 
    149 	if (mapping && tgt_policy) {
    150 		fprintf(stderr, "Please select only one mode between --mapping and --tgt_policy\n");
    151 		usage(argv[0]);
    152 	}
    153 
    154 	/* gimme all the details */
    155 	cil_set_log_level(CIL_INFO);
    156 
    157 	/* read platform policy */
    158 	rc = read_cil_file(&base_db, base);
    159 	if (rc != SEPOL_OK) {
    160 		goto exit;
    161 	}
    162 
    163 	if (mapping) {
    164 		rc = cil_android_attrib_mapping(&out_db, base_db, num);
    165 		if (rc != SEPOL_OK)
    166 			goto exit;
    167 	} else {
    168 		/* read target policy, ready for manipulation */
    169 		rc = read_cil_file(&out_db, tgt_policy);
    170 		if (rc != SEPOL_OK) {
    171 			goto exit;
    172 		}
    173 		/* attributize the target policy */
    174 		rc = cil_android_attributize(out_db, base_db, num);
    175 		if (rc != SEPOL_OK) {
    176 			goto exit;
    177 		}
    178 	}
    179 	rc = cil_write_ast(out_db, output);
    180 	if (rc != SEPOL_OK) {
    181 		goto exit;
    182 	}
    183 
    184 exit:
    185 	free(base);
    186 	free(tgt_policy);
    187 	free(num);
    188 	free(output);
    189 	cil_db_destroy(&base_db);
    190 	cil_db_destroy(&out_db);
    191 	return rc;
    192 }
    193