ia64/xen-unstable

view tools/security/secpol_tool.c @ 6552:a9873d384da4

Merge.
author adsharma@los-vmm.sc.intel.com
date Thu Aug 25 12:24:48 2005 -0700 (2005-08-25)
parents 112d44270733 fa0754a9f64f
children dfaf788ab18c
line source
1 /****************************************************************
2 * secpol_tool.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Authors:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 * Stefan Berger <stefanb@watson.ibm.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation, version 2 of the
13 * License.
14 *
15 * sHype policy management tool. This code runs in a domain and
16 * manages the Xen security policy by interacting with the
17 * Xen access control module via a /proc/xen/privcmd proc-ioctl,
18 * which is translated into a acm_op hypercall into Xen.
19 *
20 * indent -i4 -kr -nut
21 */
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <sys/mman.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <stdlib.h>
32 #include <sys/ioctl.h>
33 #include <string.h>
34 #include <netinet/in.h>
35 #include "secpol_compat.h"
36 #include <xen/acm.h>
37 #include <xen/acm_ops.h>
38 #include <xen/linux/privcmd.h>
40 #define PERROR(_m, _a...) \
41 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
42 errno, strerror(errno))
44 static inline int do_policycmd(int xc_handle, unsigned int cmd,
45 unsigned long data)
46 {
47 return ioctl(xc_handle, cmd, data);
48 }
50 static inline int do_xen_hypercall(int xc_handle,
51 privcmd_hypercall_t * hypercall)
52 {
53 return do_policycmd(xc_handle,
54 IOCTL_PRIVCMD_HYPERCALL,
55 (unsigned long) hypercall);
56 }
58 static inline int do_acm_op(int xc_handle, acm_op_t * op)
59 {
60 int ret = -1;
61 privcmd_hypercall_t hypercall;
63 op->interface_version = ACM_INTERFACE_VERSION;
65 hypercall.op = __HYPERVISOR_acm_op;
66 hypercall.arg[0] = (unsigned long) op;
68 if (mlock(op, sizeof(*op)) != 0)
69 {
70 PERROR("Could not lock memory for Xen policy hypercall");
71 goto out1;
72 }
74 if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
75 {
76 if (errno == EACCES)
77 fprintf(stderr, "ACM operation failed -- need to"
78 " rebuild the user-space tool set?\n");
79 goto out2;
80 }
82 out2:(void) munlock(op, sizeof(*op));
83 out1:return ret;
84 }
86 /*************************** DUMPS *******************************/
88 void acm_dump_chinesewall_buffer(void *buf, int buflen)
89 {
91 struct acm_chwall_policy_buffer *cwbuf =
92 (struct acm_chwall_policy_buffer *) buf;
93 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
94 int i, j;
97 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
98 {
99 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
100 return;
101 }
102 printf("\n\nChinese Wall policy:\n");
103 printf("====================\n");
104 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
105 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
106 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
107 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
108 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
109 printf("Conflicts Off = %x.\n",
110 ntohl(cwbuf->chwall_conflict_sets_offset));
111 printf("Runing T. Off = %x.\n",
112 ntohl(cwbuf->chwall_running_types_offset));
113 printf("C. Agg. Off = %x.\n",
114 ntohl(cwbuf->chwall_conflict_aggregate_offset));
115 printf("\nSSID To CHWALL-Type matrix:\n");
117 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
118 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
119 {
120 printf("\n ssidref%2x: ", i);
121 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
122 printf("%02x ",
123 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
124 }
125 printf("\n\nConfict Sets:\n");
126 conflicts =
127 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
128 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
129 {
130 printf("\n c-set%2x: ", i);
131 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
132 printf("%02x ",
133 ntohs(conflicts
134 [i * ntohl(cwbuf->chwall_max_types) + j]));
135 }
136 printf("\n");
138 printf("\nRunning\nTypes: ");
139 if (ntohl(cwbuf->chwall_running_types_offset))
140 {
141 running_types =
142 (domaintype_t *) (buf +
143 ntohl(cwbuf->chwall_running_types_offset));
144 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
145 {
146 printf("%02x ", ntohs(running_types[i]));
147 }
148 printf("\n");
149 } else {
150 printf("Not Reported!\n");
151 }
152 printf("\nConflict\nAggregate Set: ");
153 if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
154 {
155 conflict_aggregate =
156 (domaintype_t *) (buf +
157 ntohl(cwbuf->chwall_conflict_aggregate_offset));
158 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
159 {
160 printf("%02x ", ntohs(conflict_aggregate[i]));
161 }
162 printf("\n\n");
163 } else {
164 printf("Not Reported!\n");
165 }
166 }
168 void acm_dump_ste_buffer(void *buf, int buflen)
169 {
171 struct acm_ste_policy_buffer *stebuf =
172 (struct acm_ste_policy_buffer *) buf;
173 domaintype_t *ssids;
174 int i, j;
177 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
178 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
179 return;
180 }
181 printf("\nSimple Type Enforcement policy:\n");
182 printf("===============================\n");
183 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
184 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
185 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
186 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
187 printf("\nSSID To STE-Type matrix:\n");
189 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
190 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
191 {
192 printf("\n ssidref%2x: ", i);
193 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
194 printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
195 }
196 printf("\n\n");
197 }
199 void acm_dump_policy_buffer(void *buf, int buflen)
200 {
201 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
203 printf("\nPolicy dump:\n");
204 printf("============\n");
205 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
206 printf("Magic = %x.\n", ntohl(pol->magic));
207 printf("Len = %x.\n", ntohl(pol->len));
208 printf("Primary = %s (c=%x, off=%x).\n",
209 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
210 ntohl(pol->primary_policy_code),
211 ntohl(pol->primary_buffer_offset));
212 printf("Secondary = %s (c=%x, off=%x).\n",
213 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
214 ntohl(pol->secondary_policy_code),
215 ntohl(pol->secondary_buffer_offset));
216 switch (ntohl(pol->primary_policy_code))
217 {
218 case ACM_CHINESE_WALL_POLICY:
219 acm_dump_chinesewall_buffer(buf +
220 ntohl(pol->primary_buffer_offset),
221 ntohl(pol->len) -
222 ntohl(pol->primary_buffer_offset));
223 break;
225 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
226 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
227 ntohl(pol->len) -
228 ntohl(pol->primary_buffer_offset));
229 break;
231 case ACM_NULL_POLICY:
232 printf("Primary policy is NULL Policy (n/a).\n");
233 break;
235 default:
236 printf("UNKNOWN POLICY!\n");
237 }
239 switch (ntohl(pol->secondary_policy_code))
240 {
241 case ACM_CHINESE_WALL_POLICY:
242 acm_dump_chinesewall_buffer(buf +
243 ntohl(pol->secondary_buffer_offset),
244 ntohl(pol->len) -
245 ntohl(pol->secondary_buffer_offset));
246 break;
248 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
249 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
250 ntohl(pol->len) -
251 ntohl(pol->secondary_buffer_offset));
252 break;
254 case ACM_NULL_POLICY:
255 printf("Secondary policy is NULL Policy (n/a).\n");
256 break;
258 default:
259 printf("UNKNOWN POLICY!\n");
260 }
261 }
263 /******************************* get policy ******************************/
265 #define PULL_CACHE_SIZE 8192
266 u8 pull_buffer[PULL_CACHE_SIZE];
267 int acm_domain_getpolicy(int xc_handle)
268 {
269 acm_op_t op;
270 int ret;
272 memset(pull_buffer, 0x00, sizeof(pull_buffer));
273 op.cmd = ACM_GETPOLICY;
274 op.interface_version = ACM_INTERFACE_VERSION;
275 op.u.getpolicy.pullcache = (void *) pull_buffer;
276 op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
277 ret = do_acm_op(xc_handle, &op);
278 /* dump policy */
279 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
280 return ret;
281 }
283 /************************ load binary policy ******************************/
285 int acm_domain_loadpolicy(int xc_handle, const char *filename)
286 {
287 struct stat mystat;
288 int ret, fd;
289 off_t len;
290 u8 *buffer;
292 if ((ret = stat(filename, &mystat)))
293 {
294 printf("File %s not found.\n", filename);
295 goto out;
296 }
298 len = mystat.st_size;
299 if ((buffer = malloc(len)) == NULL)
300 {
301 ret = -ENOMEM;
302 goto out;
303 }
304 if ((fd = open(filename, O_RDONLY)) <= 0)
305 {
306 ret = -ENOENT;
307 printf("File %s not found.\n", filename);
308 goto free_out;
309 }
310 if (len == read(fd, buffer, len))
311 {
312 acm_op_t op;
313 /* dump it and then push it down into xen/acm */
314 acm_dump_policy_buffer(buffer, len);
315 op.cmd = ACM_SETPOLICY;
316 op.interface_version = ACM_INTERFACE_VERSION;
317 op.u.setpolicy.pushcache = (void *) buffer;
318 op.u.setpolicy.pushcache_size = len;
319 ret = do_acm_op(xc_handle, &op);
321 if (ret)
322 printf
323 ("ERROR setting policy. Use 'xm dmesg' to see details.\n");
324 else
325 printf("Successfully changed policy.\n");
327 } else {
328 ret = -1;
329 }
330 close(fd);
331 free_out:
332 free(buffer);
333 out:
334 return ret;
335 }
337 /************************ dump hook statistics ******************************/
338 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
339 {
340 printf("STE-Policy Security Hook Statistics:\n");
341 printf("ste: event_channel eval_count = %d\n",
342 ntohl(ste_stats->ec_eval_count));
343 printf("ste: event_channel denied_count = %d\n",
344 ntohl(ste_stats->ec_denied_count));
345 printf("ste: event_channel cache_hit_count = %d\n",
346 ntohl(ste_stats->ec_cachehit_count));
347 printf("ste:\n");
348 printf("ste: grant_table eval_count = %d\n",
349 ntohl(ste_stats->gt_eval_count));
350 printf("ste: grant_table denied_count = %d\n",
351 ntohl(ste_stats->gt_denied_count));
352 printf("ste: grant_table cache_hit_count = %d\n",
353 ntohl(ste_stats->gt_cachehit_count));
354 }
356 #define PULL_STATS_SIZE 8192
357 int acm_domain_dumpstats(int xc_handle)
358 {
359 u8 stats_buffer[PULL_STATS_SIZE];
360 acm_op_t op;
361 int ret;
362 struct acm_stats_buffer *stats;
364 memset(stats_buffer, 0x00, sizeof(stats_buffer));
365 op.cmd = ACM_DUMPSTATS;
366 op.interface_version = ACM_INTERFACE_VERSION;
367 op.u.dumpstats.pullcache = (void *) stats_buffer;
368 op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
369 ret = do_acm_op(xc_handle, &op);
371 if (ret < 0)
372 {
373 printf("ERROR dumping policy stats. Use 'xm dmesg' to see details.\n");
374 return ret;
375 }
376 stats = (struct acm_stats_buffer *) stats_buffer;
378 printf("\nPolicy dump:\n");
379 printf("============\n");
380 printf("Magic = %x.\n", ntohl(stats->magic));
381 printf("Len = %x.\n", ntohl(stats->len));
383 switch (ntohl(stats->primary_policy_code))
384 {
385 case ACM_NULL_POLICY:
386 printf("NULL Policy: No statistics apply.\n");
387 break;
389 case ACM_CHINESE_WALL_POLICY:
390 printf("Chinese Wall Policy: No statistics apply.\n");
391 break;
393 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
394 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
395 ntohl(stats->
396 primary_stats_offset)));
397 break;
399 default:
400 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
401 }
403 switch (ntohl(stats->secondary_policy_code))
404 {
405 case ACM_NULL_POLICY:
406 printf("NULL Policy: No statistics apply.\n");
407 break;
409 case ACM_CHINESE_WALL_POLICY:
410 printf("Chinese Wall Policy: No statistics apply.\n");
411 break;
413 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
414 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
415 ntohl(stats->
416 secondary_stats_offset)));
417 break;
419 default:
420 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
421 }
422 return ret;
423 }
425 /***************************** main **************************************/
427 void usage(char *progname)
428 {
429 printf("Use: %s \n"
430 "\t getpolicy\n"
431 "\t dumpstats\n"
432 "\t loadpolicy <binary policy file>\n", progname);
433 exit(-1);
434 }
436 int main(int argc, char **argv)
437 {
439 int acm_cmd_fd, ret = 0;
441 if (argc < 2)
442 usage(argv[0]);
444 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
445 {
446 printf("ERROR: Could not open xen privcmd device!\n");
447 exit(-1);
448 }
450 if (!strcmp(argv[1], "getpolicy")) {
451 if (argc != 2)
452 usage(argv[0]);
453 ret = acm_domain_getpolicy(acm_cmd_fd);
454 } else if (!strcmp(argv[1], "loadpolicy")) {
455 if (argc != 3)
456 usage(argv[0]);
457 ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
458 } else if (!strcmp(argv[1], "dumpstats")) {
459 if (argc != 2)
460 usage(argv[0]);
461 ret = acm_domain_dumpstats(acm_cmd_fd);
462 } else
463 usage(argv[0]);
465 close(acm_cmd_fd);
466 return ret;
467 }