| /* Authors: Karl MacMillan <[email protected]> |
| * |
| * Copyright (C) 2004 Tresys Technology, LLC |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation, version 2. |
| */ |
| |
| #include <sepol/module.h> |
| #include <getopt.h> |
| #include <fcntl.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <sys/mman.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| |
| char *progname = NULL; |
| extern char *optarg; |
| |
| static __attribute__((__noreturn__)) void usage(const char *prog) |
| { |
| printf("usage: %s -o <output file> -m <module> [-f <file contexts>]\n", |
| prog); |
| printf("Options:\n"); |
| printf(" -o --outfile Output file (required)\n"); |
| printf(" -m --module Module file (required)\n"); |
| printf(" -f --fc File contexts file\n"); |
| printf(" -s --seuser Seusers file (only valid in base)\n"); |
| printf |
| (" -u --user_extra user_extra file (only valid in base)\n"); |
| printf(" -n --nc Netfilter contexts file\n"); |
| exit(1); |
| } |
| |
| static int file_to_policy_file(const char *filename, struct sepol_policy_file **pf, |
| const char *mode) |
| { |
| FILE *f; |
| |
| if (sepol_policy_file_create(pf)) { |
| fprintf(stderr, "%s: Out of memory\n", progname); |
| return -1; |
| } |
| |
| f = fopen(filename, mode); |
| if (!f) { |
| fprintf(stderr, "%s: Could not open file %s: %s\n", progname, |
| strerror(errno), filename); |
| return -1; |
| } |
| sepol_policy_file_set_fp(*pf, f); |
| return 0; |
| } |
| |
| static int file_to_data(const char *path, char **data, size_t * len) |
| { |
| int fd; |
| struct stat sb; |
| fd = open(path, O_RDONLY); |
| if (fd < 0) { |
| fprintf(stderr, "%s: Failed to open %s: %s\n", progname, path, |
| strerror(errno)); |
| return -1; |
| } |
| if (fstat(fd, &sb) < 0) { |
| fprintf(stderr, "%s: Failed to fstat %s: %s\n", progname, |
| path, strerror(errno)); |
| goto err; |
| } |
| if (!sb.st_size) { |
| close(fd); |
| *len = 0; |
| return 0; |
| } |
| |
| *data = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
| if (*data == MAP_FAILED) { |
| fprintf(stderr, "%s: Failed to mmap %s: %s\n", progname, path, |
| strerror(errno)); |
| goto err; |
| } |
| *len = sb.st_size; |
| close(fd); |
| return 0; |
| err: |
| close(fd); |
| return -1; |
| } |
| |
| int main(int argc, char **argv) |
| { |
| struct sepol_module_package *pkg; |
| struct sepol_policy_file *mod, *out; |
| char *module = NULL, *file_contexts = NULL, *seusers = |
| NULL, *user_extra = NULL; |
| char *fcdata = NULL, *outfile = NULL, *seusersdata = |
| NULL, *user_extradata = NULL; |
| char *netfilter_contexts = NULL, *ncdata = NULL; |
| size_t fclen = 0, seuserslen = 0, user_extralen = 0, nclen = 0; |
| int i; |
| |
| static struct option opts[] = { |
| {"module", required_argument, NULL, 'm'}, |
| {"fc", required_argument, NULL, 'f'}, |
| {"seuser", required_argument, NULL, 's'}, |
| {"user_extra", required_argument, NULL, 'u'}, |
| {"nc", required_argument, NULL, 'n'}, |
| {"outfile", required_argument, NULL, 'o'}, |
| {"help", 0, NULL, 'h'}, |
| {NULL, 0, NULL, 0} |
| }; |
| |
| while ((i = getopt_long(argc, argv, "m:f:s:u:o:n:h", opts, NULL)) != -1) { |
| switch (i) { |
| case 'h': |
| usage(argv[0]); |
| exit(0); |
| case 'm': |
| if (module) { |
| fprintf(stderr, |
| "May not specify more than one module\n"); |
| exit(1); |
| } |
| module = strdup(optarg); |
| if (!module) |
| exit(1); |
| break; |
| case 'f': |
| if (file_contexts) { |
| fprintf(stderr, |
| "May not specify more than one file context file\n"); |
| exit(1); |
| } |
| file_contexts = strdup(optarg); |
| if (!file_contexts) |
| exit(1); |
| break; |
| case 'o': |
| if (outfile) { |
| fprintf(stderr, |
| "May not specify more than one output file\n"); |
| exit(1); |
| } |
| outfile = strdup(optarg); |
| if (!outfile) |
| exit(1); |
| break; |
| case 's': |
| if (seusers) { |
| fprintf(stderr, |
| "May not specify more than one seuser file\n"); |
| exit(1); |
| } |
| seusers = strdup(optarg); |
| if (!seusers) |
| exit(1); |
| break; |
| case 'u': |
| if (user_extra) { |
| fprintf(stderr, |
| "May not specify more than one user_extra file\n"); |
| exit(1); |
| } |
| user_extra = strdup(optarg); |
| if (!user_extra) |
| exit(1); |
| break; |
| case 'n': |
| if (netfilter_contexts) { |
| fprintf(stderr, |
| "May not specify more than one netfilter contexts file\n"); |
| exit(1); |
| } |
| netfilter_contexts = strdup(optarg); |
| if (!netfilter_contexts) |
| exit(1); |
| break; |
| } |
| } |
| |
| progname = argv[0]; |
| |
| if (!module || !outfile) { |
| usage(argv[0]); |
| exit(0); |
| } |
| |
| if (file_contexts) { |
| if (file_to_data(file_contexts, &fcdata, &fclen)) |
| exit(1); |
| } |
| |
| if (seusers) { |
| if (file_to_data(seusers, &seusersdata, &seuserslen)) |
| exit(1); |
| } |
| |
| if (user_extra) { |
| if (file_to_data(user_extra, &user_extradata, &user_extralen)) |
| exit(1); |
| } |
| |
| if (netfilter_contexts) { |
| if (file_to_data(netfilter_contexts, &ncdata, &nclen)) |
| exit(1); |
| } |
| |
| if (file_to_policy_file(module, &mod, "r")) |
| exit(1); |
| |
| if (sepol_module_package_create(&pkg)) { |
| fprintf(stderr, "%s: Out of memory\n", argv[0]); |
| exit(1); |
| } |
| |
| if (sepol_policydb_read(sepol_module_package_get_policy(pkg), mod)) { |
| fprintf(stderr, |
| "%s: Error while reading policy module from %s\n", |
| argv[0], module); |
| exit(1); |
| } |
| |
| if (fclen) |
| sepol_module_package_set_file_contexts(pkg, fcdata, fclen); |
| |
| if (seuserslen) |
| sepol_module_package_set_seusers(pkg, seusersdata, seuserslen); |
| |
| if (user_extra) |
| sepol_module_package_set_user_extra(pkg, user_extradata, |
| user_extralen); |
| |
| if (nclen) |
| sepol_module_package_set_netfilter_contexts(pkg, ncdata, nclen); |
| |
| if (file_to_policy_file(outfile, &out, "w")) |
| exit(1); |
| |
| if (sepol_module_package_write(pkg, out)) { |
| fprintf(stderr, |
| "%s: Error while writing module package to %s\n", |
| argv[0], argv[1]); |
| exit(1); |
| } |
| |
| if (fclen) |
| munmap(fcdata, fclen); |
| if (nclen) |
| munmap(ncdata, nclen); |
| sepol_policy_file_free(mod); |
| sepol_policy_file_free(out); |
| sepol_module_package_free(pkg); |
| free(file_contexts); |
| free(outfile); |
| free(module); |
| free(seusers); |
| free(user_extra); |
| exit(0); |
| } |