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 __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 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 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 94int 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