113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Authors: Karl MacMillan <kmacmillan@tresys.com>
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * 	    Joshua Brindle <jbrindle@tresys.com>
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Copyright (C) 2004 Tresys Technology, LLC
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	This program is free software; you can redistribute it and/or modify
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *  	it under the terms of the GNU General Public License as published by
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *	the Free Software Foundation, version 2.
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/policydb.h>
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sepol/module.h>
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <getopt.h>
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/mman.h>
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/stat.h>
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern char *optarg;
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleextern int optind;
2613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint policyvers = 0;
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define EXPANDPOLICY_VERSION "1.0"
3013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic void usage(char *program_name)
3213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
3313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
3413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	       program_name);
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	exit(1);
3613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
3713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint main(int argc, char **argv)
3913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
4013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *basename, *outname;
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ch, ret, show_version = 0, verbose = 0;
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct sepol_policy_file *pf;
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_t *base;
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policydb_t *out, *p;
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	FILE *fp, *outfile;
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int check_assertions = 1;
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_handle_t *handle;
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		switch (ch) {
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'V':
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			show_version = 1;
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'v':
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			verbose = 1;
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			break;
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'c':{
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				long int n = strtol(optarg, NULL, 10);
5913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (errno) {
6013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					fprintf(stderr,
6113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						"%s:  Invalid policyvers specified: %s\n",
6213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						argv[0], optarg);
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					usage(argv[0]);
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					exit(1);
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				if (n < sepol_policy_kern_vers_min()
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				    || n > sepol_policy_kern_vers_max()) {
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					fprintf(stderr,
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						"%s:  policyvers value %ld not in range %d-%d\n",
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						argv[0], n,
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						sepol_policy_kern_vers_min(),
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle						sepol_policy_kern_vers_max());
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					usage(argv[0]);
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle					exit(1);
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				}
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policyvers = n;
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		case 'a':{
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				check_assertions = 0;
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				break;
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			}
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		default:
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			usage(argv[0]);
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (verbose) {
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (policyvers)
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			printf("Building version %d policy\n", policyvers);
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (show_version) {
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		printf("%s\n", EXPANDPOLICY_VERSION);
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(0);
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* check args */
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (argc < 3 || !(optind != (argc - 1))) {
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr,
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"%s:  You must provide the base module package and output filename\n",
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0]);
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		usage(argv[0]);
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	basename = argv[optind++];
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	outname = argv[optind];
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	handle = sepol_handle_create();
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!handle)
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_policy_file_create(&pf)) {
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* read the base module */
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_module_package_create(&base)) {
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fp = fopen(basename, "r");
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!fp) {
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0], basename, strerror(errno));
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_set_fp(pf, fp);
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = sepol_module_package_read(base, pf, 0);
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Error in reading package from %s\n",
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0], basename);
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(fp);
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* linking the base takes care of enabling optional avrules */
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	p = sepol_module_package_get_policy(base);
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	/* create the output policy */
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_policydb_create(&out)) {
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_set_expand_consume_base(handle, 1);
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
15713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (policyvers) {
16013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (sepol_policydb_set_vers(out, policyvers)) {
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle				policyvers);
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			exit(1);
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_module_package_free(base);
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	outfile = fopen(outname, "w");
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!outfile) {
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		perror(outname);
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
17513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_set_fp(pf, outfile);
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = sepol_policydb_write(out, pf);
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret) {
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fprintf(stderr,
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			"%s:  Error while writing expanded policy to %s\n",
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			argv[0], outname);
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		exit(1);
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fclose(outfile);
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_handle_destroy(handle);
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policydb_free(out);
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	sepol_policy_file_free(pf);
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
190