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