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 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
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
main(int argc,char ** argv)90 int 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