/* Authors: Karl MacMillan <kmacmillan@tresys.com>
*
* 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 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;
}
*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);
exit(0);
}