1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2  * 	    Joshua Brindle <jbrindle@tresys.com>
3  *
4  * Copyright (C) 2004 Tresys Technology, LLC
5  *	This program is free software; you can redistribute it and/or modify
6  *  	it under the terms of the GNU General Public License as published by
7  *	the Free Software Foundation, version 2.
8  */
9 
10 #include <sepol/policydb.h>
11 #include <sepol/module.h>
12 
13 #include <getopt.h>
14 #include <fcntl.h>
15 #include <stdio.h>
16 #include <errno.h>
17 #include <sys/mman.h>
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 
24 extern char *optarg;
25 extern int optind;
26 
27 int policyvers = 0;
28 
29 #define EXPANDPOLICY_VERSION "1.0"
30 
usage(const char * program_name)31 static __attribute__((__noreturn__)) void usage(const char *program_name)
32 {
33 	printf("usage: %s [-V -a -c [version]] basemodpkg outputfile\n",
34 	       program_name);
35 	exit(1);
36 }
37 
main(int argc,char ** argv)38 int main(int argc, char **argv)
39 {
40 	char *basename, *outname;
41 	int ch, ret, show_version = 0, verbose = 0;
42 	struct sepol_policy_file *pf;
43 	sepol_module_package_t *base;
44 	sepol_policydb_t *out, *p;
45 	FILE *fp, *outfile;
46 	int check_assertions = 1;
47 	sepol_handle_t *handle;
48 
49 	while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
50 		switch (ch) {
51 		case 'V':
52 			show_version = 1;
53 			break;
54 		case 'v':
55 			verbose = 1;
56 			break;
57 		case 'c':{
58 				long int n = strtol(optarg, NULL, 10);
59 				if (errno) {
60 					fprintf(stderr,
61 						"%s:  Invalid policyvers specified: %s\n",
62 						argv[0], optarg);
63 					usage(argv[0]);
64 					exit(1);
65 				}
66 				if (n < sepol_policy_kern_vers_min()
67 				    || n > sepol_policy_kern_vers_max()) {
68 					fprintf(stderr,
69 						"%s:  policyvers value %ld not in range %d-%d\n",
70 						argv[0], n,
71 						sepol_policy_kern_vers_min(),
72 						sepol_policy_kern_vers_max());
73 					usage(argv[0]);
74 					exit(1);
75 				}
76 				policyvers = n;
77 				break;
78 			}
79 		case 'a':{
80 				check_assertions = 0;
81 				break;
82 			}
83 		default:
84 			usage(argv[0]);
85 		}
86 	}
87 
88 	if (verbose) {
89 		if (policyvers)
90 			printf("Building version %d policy\n", policyvers);
91 	}
92 
93 	if (show_version) {
94 		printf("%s\n", EXPANDPOLICY_VERSION);
95 		exit(0);
96 	}
97 
98 	/* check args */
99 	if (argc < 3 || !(optind != (argc - 1))) {
100 		fprintf(stderr,
101 			"%s:  You must provide the base module package and output filename\n",
102 			argv[0]);
103 		usage(argv[0]);
104 	}
105 
106 	basename = argv[optind++];
107 	outname = argv[optind];
108 
109 	handle = sepol_handle_create();
110 	if (!handle)
111 		exit(1);
112 
113 	if (sepol_policy_file_create(&pf)) {
114 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
115 		exit(1);
116 	}
117 
118 	/* read the base module */
119 	if (sepol_module_package_create(&base)) {
120 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
121 		exit(1);
122 	}
123 	fp = fopen(basename, "r");
124 	if (!fp) {
125 		fprintf(stderr, "%s:  Can't open '%s':  %s\n",
126 			argv[0], basename, strerror(errno));
127 		exit(1);
128 	}
129 	sepol_policy_file_set_fp(pf, fp);
130 	ret = sepol_module_package_read(base, pf, 0);
131 	if (ret) {
132 		fprintf(stderr, "%s:  Error in reading package from %s\n",
133 			argv[0], basename);
134 		exit(1);
135 	}
136 	fclose(fp);
137 
138 	/* linking the base takes care of enabling optional avrules */
139 	p = sepol_module_package_get_policy(base);
140 	if (sepol_link_modules(handle, p, NULL, 0, 0)) {
141 		fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
142 		exit(1);
143 	}
144 
145 	/* create the output policy */
146 
147 	if (sepol_policydb_create(&out)) {
148 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
149 		exit(1);
150 	}
151 
152 	sepol_set_expand_consume_base(handle, 1);
153 
154 	if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
155 		fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
156 		exit(1);
157 	}
158 
159 	if (policyvers) {
160 		if (sepol_policydb_set_vers(out, policyvers)) {
161 			fprintf(stderr, "%s:  Invalid version %d\n", argv[0],
162 				policyvers);
163 			exit(1);
164 		}
165 	}
166 
167 	sepol_module_package_free(base);
168 
169 	outfile = fopen(outname, "w");
170 	if (!outfile) {
171 		perror(outname);
172 		exit(1);
173 	}
174 
175 	sepol_policy_file_set_fp(pf, outfile);
176 	ret = sepol_policydb_write(out, pf);
177 	if (ret) {
178 		fprintf(stderr,
179 			"%s:  Error while writing expanded policy to %s\n",
180 			argv[0], outname);
181 		exit(1);
182 	}
183 	fclose(outfile);
184 	sepol_handle_destroy(handle);
185 	sepol_policydb_free(out);
186 	sepol_policy_file_free(pf);
187 
188 	return 0;
189 }
190