1/* Authors: Karl MacMillan <kmacmillan@tresys.com>
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
22char *progname = NULL;
23extern char *optarg;
24
25static void usage(const char *prog)
26{
27	printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n",
28	       prog);
29	printf("Options:\n");
30	printf("  -o --outfile		Output file (required)\n");
31	printf("  -m --module		Module file (required)\n");
32	printf("  -f --fc		File contexts file\n");
33	printf("  -s --seuser		Seusers file (only valid in base)\n");
34	printf
35	    ("  -u --user_extra	user_extra file (only valid in base)\n");
36	printf("  -n --nc		Netfilter contexts file\n");
37	exit(1);
38}
39
40static int file_to_policy_file(const char *filename, struct sepol_policy_file **pf,
41			       const char *mode)
42{
43	FILE *f;
44
45	if (sepol_policy_file_create(pf)) {
46		fprintf(stderr, "%s:  Out of memory\n", progname);
47		return -1;
48	}
49
50	f = fopen(filename, mode);
51	if (!f) {
52		fprintf(stderr, "%s:  Could not open file %s:  %s\n", progname,
53			strerror(errno), filename);
54		return -1;
55	}
56	sepol_policy_file_set_fp(*pf, f);
57	return 0;
58}
59
60static int file_to_data(const char *path, char **data, size_t * len)
61{
62	int fd;
63	struct stat sb;
64	fd = open(path, O_RDONLY);
65	if (fd < 0) {
66		fprintf(stderr, "%s:  Failed to open %s:  %s\n", progname, path,
67			strerror(errno));
68		return -1;
69	}
70	if (fstat(fd, &sb) < 0) {
71		fprintf(stderr, "%s:  Failed to fstat %s:  %s\n", progname,
72			path, strerror(errno));
73		goto err;
74	}
75
76	*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
77	if (*data == MAP_FAILED) {
78		fprintf(stderr, "%s:  Failed to mmap %s:  %s\n", progname, path,
79			strerror(errno));
80		goto err;
81	}
82	*len = sb.st_size;
83	close(fd);
84	return 0;
85      err:
86	close(fd);
87	return -1;
88}
89
90int main(int argc, char **argv)
91{
92	struct sepol_module_package *pkg;
93	struct sepol_policy_file *mod, *out;
94	char *module = NULL, *file_contexts = NULL, *seusers =
95	    NULL, *user_extra = NULL;
96	char *fcdata = NULL, *outfile = NULL, *seusersdata =
97	    NULL, *user_extradata = NULL;
98	char *netfilter_contexts = NULL, *ncdata = NULL;
99	size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
100	int i;
101
102	static struct option opts[] = {
103		{"module", required_argument, NULL, 'm'},
104		{"fc", required_argument, NULL, 'f'},
105		{"seuser", required_argument, NULL, 's'},
106		{"user_extra", required_argument, NULL, 'u'},
107		{"nc", required_argument, NULL, 'n'},
108		{"outfile", required_argument, NULL, 'o'},
109		{"help", 0, NULL, 'h'},
110		{NULL, 0, NULL, 0}
111	};
112
113	while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
114		switch (i) {
115		case 'h':
116			usage(argv[0]);
117			exit(0);
118		case 'm':
119			if (module) {
120				fprintf(stderr,
121					"May not specify more than one module\n");
122				exit(1);
123			}
124			module = strdup(optarg);
125			if (!module)
126				exit(1);
127			break;
128		case 'f':
129			if (file_contexts) {
130				fprintf(stderr,
131					"May not specify more than one file context file\n");
132				exit(1);
133			}
134			file_contexts = strdup(optarg);
135			if (!file_contexts)
136				exit(1);
137			break;
138		case 'o':
139			if (outfile) {
140				fprintf(stderr,
141					"May not specify more than one output file\n");
142				exit(1);
143			}
144			outfile = strdup(optarg);
145			if (!outfile)
146				exit(1);
147			break;
148		case 's':
149			if (seusers) {
150				fprintf(stderr,
151					"May not specify more than one seuser file\n");
152				exit(1);
153			}
154			seusers = strdup(optarg);
155			if (!seusers)
156				exit(1);
157			break;
158		case 'u':
159			if (user_extra) {
160				fprintf(stderr,
161					"May not specify more than one user_extra file\n");
162				exit(1);
163			}
164			user_extra = strdup(optarg);
165			if (!user_extra)
166				exit(1);
167			break;
168		case 'n':
169			if (netfilter_contexts) {
170				fprintf(stderr,
171					"May not specify more than one netfilter contexts file\n");
172				exit(1);
173			}
174			netfilter_contexts = strdup(optarg);
175			if (!netfilter_contexts)
176				exit(1);
177			break;
178		}
179	}
180
181	progname = argv[0];
182
183	if (!module || !outfile) {
184		usage(argv[0]);
185		exit(0);
186	}
187
188	if (file_contexts) {
189		if (file_to_data(file_contexts, &fcdata, &fclen))
190			exit(1);
191	}
192
193	if (seusers) {
194		if (file_to_data(seusers, &seusersdata, &seuserslen))
195			exit(1);
196	}
197
198	if (user_extra) {
199		if (file_to_data(user_extra, &user_extradata, &user_extralen))
200			exit(1);
201	}
202
203	if (netfilter_contexts) {
204		if (file_to_data(netfilter_contexts, &ncdata, &nclen))
205			exit(1);
206	}
207
208	if (file_to_policy_file(module, &mod, "r"))
209		exit(1);
210
211	if (sepol_module_package_create(&pkg)) {
212		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
213		exit(1);
214	}
215
216	if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
217		fprintf(stderr,
218			"%s:  Error while reading policy module from %s\n",
219			argv[0], module);
220		exit(1);
221	}
222
223	if (fclen)
224		sepol_module_package_set_file_contexts(pkg, fcdata, fclen);
225
226	if (seuserslen)
227		sepol_module_package_set_seusers(pkg, seusersdata, seuserslen);
228
229	if (user_extra)
230		sepol_module_package_set_user_extra(pkg, user_extradata,
231						    user_extralen);
232
233	if (nclen)
234		sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen);
235
236	if (file_to_policy_file(outfile, &out, "w"))
237		exit(1);
238
239	if (sepol_module_package_write(pkg, out)) {
240		fprintf(stderr,
241			"%s:  Error while writing module package to %s\n",
242			argv[0], argv[1]);
243		exit(1);
244	}
245
246	if (fclen)
247		munmap(fcdata, fclen);
248	if (nclen)
249		munmap(ncdata, nclen);
250	sepol_policy_file_free(mod);
251	sepol_policy_file_free(out);
252	sepol_module_package_free(pkg);
253	free(file_contexts);
254	free(outfile);
255	free(module);
256	exit(0);
257}
258