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 
11 #include <getopt.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <errno.h>
15 #include <sys/mman.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 
22 #define LINKPOLICY_VERSION "1.0"
23 
24 char *progname;
25 extern char *optarg;
26 extern int optind;
27 
usage(char * program_name)28 static void usage(char *program_name)
29 {
30 	printf("usage: %s [-Vv] [-o outfile] basemodpkg modpkg1 [modpkg2]...\n",
31 	       program_name);
32 	exit(1);
33 }
34 
load_module(char * filename)35 static sepol_module_package_t *load_module(char *filename)
36 {
37 	int ret;
38 	FILE *fp = NULL;
39 	struct sepol_policy_file *pf = NULL;
40 	sepol_module_package_t *p = NULL;
41 
42 	if (sepol_module_package_create(&p)) {
43 		fprintf(stderr, "%s:  Out of memory\n", progname);
44 		goto bad;
45 	}
46 	if (sepol_policy_file_create(&pf)) {
47 		fprintf(stderr, "%s:  Out of memory\n", progname);
48 		goto bad;
49 	}
50 	fp = fopen(filename, "r");
51 	if (!fp) {
52 		fprintf(stderr, "%s:  Could not open package %s:  %s", progname,
53 			filename, strerror(errno));
54 		goto bad;
55 	}
56 	sepol_policy_file_set_fp(pf, fp);
57 
58 	printf("%s:  loading package from file %s\n", progname, filename);
59 
60 	ret = sepol_module_package_read(p, pf, 0);
61 	if (ret) {
62 		fprintf(stderr, "%s:  Error while reading package from %s\n",
63 			progname, filename);
64 		goto bad;
65 	}
66 	fclose(fp);
67 	sepol_policy_file_free(pf);
68 	return p;
69       bad:
70 	sepol_module_package_free(p);
71 	sepol_policy_file_free(pf);
72 	if (fp)
73 		fclose(fp);
74 	return NULL;
75 }
76 
main(int argc,char ** argv)77 int main(int argc, char **argv)
78 {
79 	int ch, i, show_version = 0, verbose = 0, num_mods;
80 	char *basename, *outname = NULL;
81 	sepol_module_package_t *base, **mods;
82 	FILE *outfile;
83 	struct sepol_policy_file *pf;
84 
85 	progname = argv[0];
86 
87 	while ((ch = getopt(argc, argv, "o:Vv")) != EOF) {
88 		switch (ch) {
89 		case 'V':
90 			show_version = 1;
91 			break;
92 		case 'v':
93 			verbose = 1;
94 			break;
95 		case 'o':
96 			outname = optarg;
97 			break;
98 		default:
99 			usage(argv[0]);
100 		}
101 	}
102 
103 	if (show_version) {
104 		printf("%s\n", LINKPOLICY_VERSION);
105 		exit(0);
106 	}
107 
108 	/* check args */
109 	if (argc < 3 || !(optind != (argc - 1))) {
110 		fprintf(stderr,
111 			"%s:  You must provide the base module package and at least one other module package\n",
112 			argv[0]);
113 		usage(argv[0]);
114 	}
115 
116 	basename = argv[optind++];
117 	base = load_module(basename);
118 	if (!base) {
119 		fprintf(stderr,
120 			"%s:  Could not load base module from file %s\n",
121 			argv[0], basename);
122 		exit(1);
123 	}
124 
125 	num_mods = argc - optind;
126 	mods =
127 	    (sepol_module_package_t **) malloc(sizeof(sepol_module_package_t *)
128 					       * num_mods);
129 	if (!mods) {
130 		fprintf(stderr, "%s:  Out of memory\n", argv[0]);
131 		exit(1);
132 	}
133 	memset(mods, 0, sizeof(sepol_module_package_t *) * num_mods);
134 
135 	for (i = 0; optind < argc; optind++, i++) {
136 		mods[i] = load_module(argv[optind]);
137 		if (!mods[i]) {
138 			fprintf(stderr,
139 				"%s:  Could not load module from file %s\n",
140 				argv[0], argv[optind]);
141 			exit(1);
142 		}
143 	}
144 
145 	if (sepol_link_packages(NULL, base, mods, num_mods, verbose)) {
146 		fprintf(stderr, "%s:  Error while linking packages\n", argv[0]);
147 		exit(1);
148 	}
149 
150 	if (outname) {
151 		outfile = fopen(outname, "w");
152 		if (!outfile) {
153 			perror(outname);
154 			exit(1);
155 		}
156 
157 		if (sepol_policy_file_create(&pf)) {
158 			fprintf(stderr, "%s:  Out of memory\n", argv[0]);
159 			exit(1);
160 		}
161 		sepol_policy_file_set_fp(pf, outfile);
162 		if (sepol_module_package_write(base, pf)) {
163 			fprintf(stderr, "%s:  Error writing linked package.\n",
164 				argv[0]);
165 			exit(1);
166 		}
167 		sepol_policy_file_free(pf);
168 		fclose(outfile);
169 	}
170 
171 	sepol_module_package_free(base);
172 	for (i = 0; i < num_mods; i++)
173 		sepol_module_package_free(mods[i]);
174 	free(mods);
175 	exit(0);
176 }
177