blob: 24b2a3cc65e2b2a40309134f6adfc38de6716e1c [file] [log] [blame]
dcashman2e00e632016-10-12 14:58:09 -07001/*
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
14void __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 */
30static 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;
73err:
74 free(buff);
75 fclose(file);
76file_err:
77 cil_db_destroy(db);
78 return rc;
79}
80
81int 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;
Sandeep Patil42f95982017-04-07 14:18:48 -070090 char *dot;
dcashman2e00e632016-10-12 14:58:09 -070091 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
Sandeep Patil42f95982017-04-07 14:18:48 -0700142 /* 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
dcashman2e00e632016-10-12 14:58:09 -0700149 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
184exit:
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}