1 /* Authors: Karl MacMillan <kmacmillan (at) 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 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 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 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 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