1 /* Authors: Karl MacMillan <[email protected]>
2 *
3 * Copyright (C) 2004 Tresys Technology, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 2.
7 */
8
9 #include <sepol/module.h>
10 #include <getopt.h>
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sys/mman.h>
19 #include <fcntl.h>
20 #include <errno.h>
21
usage(const char * prog)22 static void usage(const char *prog)
23 {
24 printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n",
25 prog);
26 printf("Options:\n");
27 printf(" -o --outfile Output file (required)\n");
28 printf(" -m --module Module file (required)\n");
29 printf(" -f --fc File contexts file\n");
30 printf(" -s --seuser Seusers file (only valid in base)\n");
31 printf
32 (" -u --user_extra user_extra file (only valid in base)\n");
33 printf(" -n --nc Netfilter contexts file\n");
34 printf(" -h --help Show this help message\n");
35 }
36
file_to_data(const char * path,char ** data,size_t * len,const char * progname)37 static int file_to_data(const char *path, char **data, size_t * len, const char *progname)
38 {
39 int fd;
40 struct stat sb;
41 fd = open(path, O_RDONLY | O_CLOEXEC);
42 if (fd < 0) {
43 fprintf(stderr, "%s: Failed to open %s: %s\n", progname, path,
44 strerror(errno));
45 return -1;
46 }
47 if (fstat(fd, &sb) < 0) {
48 fprintf(stderr, "%s: Failed to fstat %s: %s\n", progname,
49 path, strerror(errno));
50 goto err;
51 }
52 if (!sb.st_size) {
53 close(fd);
54 *len = 0;
55 return 0;
56 }
57
58 *data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
59 if (*data == MAP_FAILED) {
60 fprintf(stderr, "%s: Failed to mmap %s: %s\n", progname, path,
61 strerror(errno));
62 goto err;
63 }
64 *len = sb.st_size;
65 close(fd);
66 return 0;
67 err:
68 close(fd);
69 return -1;
70 }
71
main(int argc,char ** argv)72 int main(int argc, char **argv)
73 {
74 struct sepol_module_package *pkg = NULL;
75 struct sepol_policy_file *mod = NULL, *out = NULL;
76 FILE *fp = NULL;
77 char *module = NULL, *file_contexts = NULL, *seusers =
78 NULL, *user_extra = NULL;
79 char *fcdata = NULL, *outfile = NULL, *seusersdata =
80 NULL, *user_extradata = NULL;
81 char *netfilter_contexts = NULL, *ncdata = NULL;
82 size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
83 int i, ret;
84
85 const struct option opts[] = {
86 {"module", required_argument, NULL, 'm'},
87 {"fc", required_argument, NULL, 'f'},
88 {"seuser", required_argument, NULL, 's'},
89 {"user_extra", required_argument, NULL, 'u'},
90 {"nc", required_argument, NULL, 'n'},
91 {"outfile", required_argument, NULL, 'o'},
92 {"help", 0, NULL, 'h'},
93 {NULL, 0, NULL, 0}
94 };
95
96 while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
97 switch (i) {
98 case 'h':
99 usage(argv[0]);
100 return EXIT_SUCCESS;
101 case 'm':
102 if (module) {
103 fprintf(stderr,
104 "May not specify more than one module\n");
105 return EXIT_FAILURE;
106 }
107 module = strdup(optarg);
108 if (!module) {
109 fprintf(stderr, "%s: Out of memory\n", argv[0]);
110 return EXIT_FAILURE;
111 }
112 break;
113 case 'f':
114 if (file_contexts) {
115 fprintf(stderr,
116 "May not specify more than one file context file\n");
117 return EXIT_FAILURE;
118 }
119 file_contexts = strdup(optarg);
120 if (!file_contexts) {
121 fprintf(stderr, "%s: Out of memory\n", argv[0]);
122 return EXIT_FAILURE;
123 }
124 break;
125 case 'o':
126 if (outfile) {
127 fprintf(stderr,
128 "May not specify more than one output file\n");
129 return EXIT_FAILURE;
130 }
131 outfile = strdup(optarg);
132 if (!outfile) {
133 fprintf(stderr, "%s: Out of memory\n", argv[0]);
134 return EXIT_FAILURE;
135 }
136 break;
137 case 's':
138 if (seusers) {
139 fprintf(stderr,
140 "May not specify more than one seuser file\n");
141 return EXIT_FAILURE;
142 }
143 seusers = strdup(optarg);
144 if (!seusers) {
145 fprintf(stderr, "%s: Out of memory\n", argv[0]);
146 return EXIT_FAILURE;
147 }
148 break;
149 case 'u':
150 if (user_extra) {
151 fprintf(stderr,
152 "May not specify more than one user_extra file\n");
153 return EXIT_FAILURE;
154 }
155 user_extra = strdup(optarg);
156 if (!user_extra) {
157 fprintf(stderr, "%s: Out of memory\n", argv[0]);
158 return EXIT_FAILURE;
159 }
160 break;
161 case 'n':
162 if (netfilter_contexts) {
163 fprintf(stderr,
164 "May not specify more than one netfilter contexts file\n");
165 return EXIT_FAILURE;
166 }
167 netfilter_contexts = strdup(optarg);
168 if (!netfilter_contexts) {
169 fprintf(stderr, "%s: Out of memory\n", argv[0]);
170 return EXIT_FAILURE;
171 }
172 break;
173 default:
174 usage(argv[0]);
175 return EXIT_FAILURE;
176 }
177 }
178
179 if (optind < argc) {
180 fprintf(stderr, "%s: Superfluous command line arguments: ", argv[0]);
181 while (optind < argc)
182 fprintf(stderr, "%s ", argv[optind++]);
183 fprintf(stderr, "\n");
184 usage(argv[0]);
185 return EXIT_FAILURE;
186 }
187
188 if (!module || !outfile) {
189 usage(argv[0]);
190 return EXIT_FAILURE;
191 }
192
193 if (file_contexts && file_to_data(file_contexts, &fcdata, &fclen, argv[0]))
194 goto failure;
195
196 if (seusers && file_to_data(seusers, &seusersdata, &seuserslen, argv[0]))
197 goto failure;
198
199 if (user_extra && file_to_data(user_extra, &user_extradata, &user_extralen, argv[0]))
200 goto failure;
201
202 if (netfilter_contexts && file_to_data(netfilter_contexts, &ncdata, &nclen, argv[0]))
203 goto failure;
204
205 if (sepol_policy_file_create(&mod)) {
206 fprintf(stderr, "%s: Out of memory\n", argv[0]);
207 goto failure;
208 }
209
210 fp = fopen(module, "re");
211 if (!fp) {
212 fprintf(stderr, "%s: Could not open file %s: %s\n", argv[0],
213 module, strerror(errno));
214 goto failure;
215 }
216 sepol_policy_file_set_fp(mod, fp);
217
218 if (sepol_module_package_create(&pkg)) {
219 fprintf(stderr, "%s: Out of memory\n", argv[0]);
220 goto failure;
221 }
222
223 if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
224 fprintf(stderr,
225 "%s: Error while reading policy module from %s\n",
226 argv[0], module);
227 goto failure;
228 }
229
230 fclose(fp);
231 fp = NULL;
232
233 if (fclen && sepol_module_package_set_file_contexts(pkg, fcdata, fclen)) {
234 fprintf(stderr, "%s: Error while setting file contexts\n", argv[0]);
235 goto failure;
236 }
237
238 if (seuserslen && sepol_module_package_set_seusers(pkg, seusersdata, seuserslen)) {
239 fprintf(stderr, "%s: Error while setting seusers\n", argv[0]);
240 goto failure;
241 }
242
243 if (user_extra && sepol_module_package_set_user_extra(pkg, user_extradata, user_extralen)) {
244 fprintf(stderr, "%s: Error while setting extra users\n", argv[0]);
245 goto failure;
246 }
247
248 if (nclen && sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen)) {
249 fprintf(stderr, "%s: Error while setting netfilter contexts\n", argv[0]);
250 goto failure;
251 }
252
253 if (sepol_policy_file_create(&out)) {
254 fprintf(stderr, "%s: Out of memory\n", argv[0]);
255 goto failure;
256 }
257
258 fp = fopen(outfile, "we");
259 if (!fp) {
260 fprintf(stderr, "%s: Could not open file %s: %s\n", argv[0],
261 outfile, strerror(errno));
262 goto failure;
263 }
264 sepol_policy_file_set_fp(out, fp);
265
266 if (sepol_module_package_write(pkg, out)) {
267 fprintf(stderr,
268 "%s: Error while writing module package to %s\n",
269 argv[0], argv[1]);
270 goto failure;
271 }
272
273 ret = fclose(fp);
274 fp = NULL;
275 if (ret) {
276 fprintf(stderr, "%s: Could not close file %s: %s\n", argv[0],
277 outfile, strerror(errno));
278 goto failure;
279 }
280
281 ret = EXIT_SUCCESS;
282 goto cleanup;
283
284 failure:
285 ret = EXIT_FAILURE;
286
287 cleanup:
288 if (fp)
289 fclose(fp);
290 sepol_policy_file_free(out);
291 if (nclen)
292 munmap(ncdata, nclen);
293 if (user_extradata)
294 munmap(user_extradata, user_extralen);
295 if (seuserslen)
296 munmap(seusersdata, seuserslen);
297 if (fclen)
298 munmap(fcdata, fclen);
299 sepol_module_package_free(pkg);
300 sepol_policy_file_free(mod);
301 free(netfilter_contexts);
302 free(user_extra);
303 free(seusers);
304 free(outfile);
305 free(file_contexts);
306 free(module);
307
308 return ret;
309 }
310