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 
22 char *progname = NULL;
23 extern char *optarg;
24 
usage(const char * prog)25 static __attribute__((__noreturn__)) 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 
file_to_policy_file(const char * filename,struct sepol_policy_file ** pf,const char * mode)40 static 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 
file_to_data(const char * path,char ** data,size_t * len)60 static 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 	if (!sb.st_size) {
76 		*len = 0;
77 		return 0;
78 	}
79 
80 	*data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
81 	if (*data == MAP_FAILED) {
82 		fprintf(stderr, "%s:  Failed to mmap %s:  %s\n", progname, path,
83 			strerror(errno));
84 		goto err;
85 	}
86 	*len = sb.st_size;
87 	close(fd);
88 	return 0;
89       err:
90 	close(fd);
91 	return -1;
92 }
93 
main(int argc,char ** argv)94 int main(int argc, char **argv)
95 {
96 	struct sepol_module_package *pkg;
97 	struct sepol_policy_file *mod, *out;
98 	char *module = NULL, *file_contexts = NULL, *seusers =
99 	    NULL, *user_extra = NULL;
100 	char *fcdata = NULL, *outfile = NULL, *seusersdata =
101 	    NULL, *user_extradata = NULL;
102 	char *netfilter_contexts = NULL, *ncdata = NULL;
103 	size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0;
104 	int i;
105 
106 	static struct option opts[] = {
107 		{"module", required_argument, NULL, 'm'},
108 		{"fc", required_argument, NULL, 'f'},
109 		{"seuser", required_argument, NULL, 's'},
110 		{"user_extra", required_argument, NULL, 'u'},
111 		{"nc", required_argument, NULL, 'n'},
112 		{"outfile", required_argument, NULL, 'o'},
113 		{"help", 0, NULL, 'h'},
114 		{NULL, 0, NULL, 0}
115 	};
116 
117 	while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) {
118 		switch (i) {
119 		case 'h':
120 			usage(argv[0]);
121 			exit(0);
122 		case 'm':
123 			if (module) {
124 				fprintf(stderr,
125 					"May not specify more than one module\n");
126 				exit(1);
127 			}
128 			module = strdup(optarg);
129 			if (!module)
130 				exit(1);
131 			break;
132 		case 'f':
133 			if (file_contexts) {
134 				fprintf(stderr,
135 					"May not specify more than one file context file\n");
136 				exit(1);
137 			}
138 			file_contexts = strdup(optarg);
139 			if (!file_contexts)
140 				exit(1);
141 			break;
142 		case 'o':
143 			if (outfile) {
144 				fprintf(stderr,
145 					"May not specify more than one output file\n");
146 				exit(1);
147 			}
148 			outfile = strdup(optarg);
149 			if (!outfile)
150 				exit(1);
151 			break;
152 		case 's':
153 			if (seusers) {
154 				fprintf(stderr,
155 					"May not specify more than one seuser file\n");
156 				exit(1);
157 			}
158 			seusers = strdup(optarg);
159 			if (!seusers)
160 				exit(1);
161 			break;
162 		case 'u':
163 			if (user_extra) {
164 				fprintf(stderr,
165 					"May not specify more than one user_extra file\n");
166 				exit(1);
167 			}
168 			user_extra = strdup(optarg);
169 			if (!user_extra)
170 				exit(1);
171 			break;
172 		case 'n':
173 			if (netfilter_contexts) {
174 				fprintf(stderr,
175 					"May not specify more than one netfilter contexts file\n");
176 				exit(1);
177 			}
178 			netfilter_contexts = strdup(optarg);
179 			if (!netfilter_contexts)
180 				exit(1);
181 			break;
182 		}
183 	}
184 
185 	progname = argv[0];
186 
187 	if (!module || !outfile) {
188 		usage(argv[0]);
189 		exit(0);
190 	}
191 
192 	if (file_contexts) {
193 		if (file_to_data(file_contexts, &fcdata, &fclen))
194 			exit(1);
195 	}
196 
197 	if (seusers) {
198 		if (file_to_data(seusers, &seusersdata, &seuserslen))
199 			exit(1);
200 	}
201 
202 	if (user_extra) {
203 		if (file_to_data(user_extra, &user_extradata, &user_extralen))
204 			exit(1);
205 	}
206 
207 	if (netfilter_contexts) {
208 		if (file_to_data(netfilter_contexts, &ncdata, &nclen))
209 			exit(1);
210 	}
211 
212 	if (file_to_policy_file(module, &mod, "r"))
213 		exit(1);
214 
215 	if (sepol_module_package_create(&pkg)) {
216 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
217 		exit(1);
218 	}
219 
220 	if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) {
221 		fprintf(stderr,
222 			"%s:  Error while reading policy module from %s\n",
223 			argv[0], module);
224 		exit(1);
225 	}
226 
227 	if (fclen)
228 		sepol_module_package_set_file_contexts(pkg, fcdata, fclen);
229 
230 	if (seuserslen)
231 		sepol_module_package_set_seusers(pkg, seusersdata, seuserslen);
232 
233 	if (user_extra)
234 		sepol_module_package_set_user_extra(pkg, user_extradata,
235 						    user_extralen);
236 
237 	if (nclen)
238 		sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen);
239 
240 	if (file_to_policy_file(outfile, &out, "w"))
241 		exit(1);
242 
243 	if (sepol_module_package_write(pkg, out)) {
244 		fprintf(stderr,
245 			"%s:  Error while writing module package to %s\n",
246 			argv[0], argv[1]);
247 		exit(1);
248 	}
249 
250 	if (fclen)
251 		munmap(fcdata, fclen);
252 	if (nclen)
253 		munmap(ncdata, nclen);
254 	sepol_policy_file_free(mod);
255 	sepol_policy_file_free(out);
256 	sepol_module_package_free(pkg);
257 	free(file_contexts);
258 	free(outfile);
259 	free(module);
260 	free(seusers);
261 	free(user_extra);
262 	exit(0);
263 }
264