ia64/xen-unstable

view tools/security/secpol_tool.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 3233e7ecfa9f
children 06d84bf87159
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 <getopt.h>
29 #include <sys/mman.h>
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdlib.h>
33 #include <sys/ioctl.h>
34 #include <string.h>
35 #include <netinet/in.h>
36 #include "secpol_compat.h"
37 #include <xen/acm.h>
38 #include <xen/acm_ops.h>
39 #include <xen/linux/privcmd.h>
41 #define PERROR(_m, _a...) \
42 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
43 errno, strerror(errno))
45 void usage(char *progname)
46 {
47 printf("Use: %s \n"
48 "\t getpolicy\n"
49 "\t dumpstats\n"
50 "\t loadpolicy <binary policy file>\n"
51 "\t getssid -d <domainid> [-f]\n"
52 "\t getssid -s <ssidref> [-f]\n", progname);
53 exit(-1);
54 }
56 static inline int do_policycmd(int xc_handle, unsigned int cmd,
57 unsigned long data)
58 {
59 return ioctl(xc_handle, cmd, data);
60 }
62 static inline int do_xen_hypercall(int xc_handle,
63 privcmd_hypercall_t * hypercall)
64 {
65 return do_policycmd(xc_handle,
66 IOCTL_PRIVCMD_HYPERCALL,
67 (unsigned long) hypercall);
68 }
70 static inline int do_acm_op(int xc_handle, acm_op_t * op)
71 {
72 int ret = -1;
73 privcmd_hypercall_t hypercall;
75 op->interface_version = ACM_INTERFACE_VERSION;
77 hypercall.op = __HYPERVISOR_acm_op;
78 hypercall.arg[0] = (unsigned long) op;
80 if (mlock(op, sizeof(*op)) != 0)
81 {
82 PERROR("Could not lock memory for Xen policy hypercall");
83 goto out1;
84 }
86 if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
87 {
88 if (errno == EACCES)
89 fprintf(stderr, "ACM operation failed -- need to"
90 " rebuild the user-space tool set?\n");
91 goto out2;
92 }
94 out2:(void) munlock(op, sizeof(*op));
95 out1:return ret;
96 }
98 /*************************** DUMPS *******************************/
100 void acm_dump_chinesewall_buffer(void *buf, int buflen)
101 {
103 struct acm_chwall_policy_buffer *cwbuf =
104 (struct acm_chwall_policy_buffer *) buf;
105 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
106 int i, j;
109 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
110 {
111 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
112 return;
113 }
114 printf("\n\nChinese Wall policy:\n");
115 printf("====================\n");
116 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
117 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
118 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
119 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
120 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
121 printf("Conflicts Off = %x.\n",
122 ntohl(cwbuf->chwall_conflict_sets_offset));
123 printf("Runing T. Off = %x.\n",
124 ntohl(cwbuf->chwall_running_types_offset));
125 printf("C. Agg. Off = %x.\n",
126 ntohl(cwbuf->chwall_conflict_aggregate_offset));
127 printf("\nSSID To CHWALL-Type matrix:\n");
129 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
130 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
131 {
132 printf("\n ssidref%2x: ", i);
133 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
134 printf("%02x ",
135 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
136 }
137 printf("\n\nConfict Sets:\n");
138 conflicts =
139 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
140 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
141 {
142 printf("\n c-set%2x: ", i);
143 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
144 printf("%02x ",
145 ntohs(conflicts
146 [i * ntohl(cwbuf->chwall_max_types) + j]));
147 }
148 printf("\n");
150 printf("\nRunning\nTypes: ");
151 if (ntohl(cwbuf->chwall_running_types_offset))
152 {
153 running_types =
154 (domaintype_t *) (buf +
155 ntohl(cwbuf->chwall_running_types_offset));
156 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
157 {
158 printf("%02x ", ntohs(running_types[i]));
159 }
160 printf("\n");
161 } else {
162 printf("Not Reported!\n");
163 }
164 printf("\nConflict\nAggregate Set: ");
165 if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
166 {
167 conflict_aggregate =
168 (domaintype_t *) (buf +
169 ntohl(cwbuf->chwall_conflict_aggregate_offset));
170 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
171 {
172 printf("%02x ", ntohs(conflict_aggregate[i]));
173 }
174 printf("\n\n");
175 } else {
176 printf("Not Reported!\n");
177 }
178 }
180 void acm_dump_ste_buffer(void *buf, int buflen)
181 {
183 struct acm_ste_policy_buffer *stebuf =
184 (struct acm_ste_policy_buffer *) buf;
185 domaintype_t *ssids;
186 int i, j;
189 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
190 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
191 return;
192 }
193 printf("\nSimple Type Enforcement policy:\n");
194 printf("===============================\n");
195 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
196 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
197 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
198 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
199 printf("\nSSID To STE-Type matrix:\n");
201 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
202 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
203 {
204 printf("\n ssidref%2x: ", i);
205 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
206 printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
207 }
208 printf("\n\n");
209 }
211 void acm_dump_policy_buffer(void *buf, int buflen)
212 {
213 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
215 printf("\nPolicy dump:\n");
216 printf("============\n");
217 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
218 printf("Magic = %x.\n", ntohl(pol->magic));
219 printf("Len = %x.\n", ntohl(pol->len));
220 printf("Primary = %s (c=%x, off=%x).\n",
221 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
222 ntohl(pol->primary_policy_code),
223 ntohl(pol->primary_buffer_offset));
224 printf("Secondary = %s (c=%x, off=%x).\n",
225 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
226 ntohl(pol->secondary_policy_code),
227 ntohl(pol->secondary_buffer_offset));
228 switch (ntohl(pol->primary_policy_code))
229 {
230 case ACM_CHINESE_WALL_POLICY:
231 acm_dump_chinesewall_buffer(buf +
232 ntohl(pol->primary_buffer_offset),
233 ntohl(pol->len) -
234 ntohl(pol->primary_buffer_offset));
235 break;
237 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
238 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
239 ntohl(pol->len) -
240 ntohl(pol->primary_buffer_offset));
241 break;
243 case ACM_NULL_POLICY:
244 printf("Primary policy is NULL Policy (n/a).\n");
245 break;
247 default:
248 printf("UNKNOWN POLICY!\n");
249 }
251 switch (ntohl(pol->secondary_policy_code))
252 {
253 case ACM_CHINESE_WALL_POLICY:
254 acm_dump_chinesewall_buffer(buf +
255 ntohl(pol->secondary_buffer_offset),
256 ntohl(pol->len) -
257 ntohl(pol->secondary_buffer_offset));
258 break;
260 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
261 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
262 ntohl(pol->len) -
263 ntohl(pol->secondary_buffer_offset));
264 break;
266 case ACM_NULL_POLICY:
267 printf("Secondary policy is NULL Policy (n/a).\n");
268 break;
270 default:
271 printf("UNKNOWN POLICY!\n");
272 }
273 }
275 /******************************* get policy ******************************/
277 #define PULL_CACHE_SIZE 8192
278 u8 pull_buffer[PULL_CACHE_SIZE];
279 int acm_domain_getpolicy(int xc_handle)
280 {
281 acm_op_t op;
282 int ret;
284 memset(pull_buffer, 0x00, sizeof(pull_buffer));
285 op.cmd = ACM_GETPOLICY;
286 op.interface_version = ACM_INTERFACE_VERSION;
287 op.u.getpolicy.pullcache = (void *) pull_buffer;
288 op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
289 ret = do_acm_op(xc_handle, &op);
290 /* dump policy */
291 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
292 return ret;
293 }
295 /************************ load binary policy ******************************/
297 int acm_domain_loadpolicy(int xc_handle, const char *filename)
298 {
299 struct stat mystat;
300 int ret, fd;
301 off_t len;
302 u8 *buffer;
304 if ((ret = stat(filename, &mystat)))
305 {
306 printf("File %s not found.\n", filename);
307 goto out;
308 }
310 len = mystat.st_size;
311 if ((buffer = malloc(len)) == NULL)
312 {
313 ret = -ENOMEM;
314 goto out;
315 }
316 if ((fd = open(filename, O_RDONLY)) <= 0)
317 {
318 ret = -ENOENT;
319 printf("File %s not found.\n", filename);
320 goto free_out;
321 }
322 if (len == read(fd, buffer, len))
323 {
324 acm_op_t op;
325 /* dump it and then push it down into xen/acm */
326 acm_dump_policy_buffer(buffer, len);
327 op.cmd = ACM_SETPOLICY;
328 op.interface_version = ACM_INTERFACE_VERSION;
329 op.u.setpolicy.pushcache = (void *) buffer;
330 op.u.setpolicy.pushcache_size = len;
331 ret = do_acm_op(xc_handle, &op);
333 if (ret)
334 printf
335 ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
336 else
337 printf("Successfully changed policy.\n");
339 } else {
340 ret = -1;
341 }
342 close(fd);
343 free_out:
344 free(buffer);
345 out:
346 return ret;
347 }
349 /************************ dump hook statistics ******************************/
350 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
351 {
352 printf("STE-Policy Security Hook Statistics:\n");
353 printf("ste: event_channel eval_count = %d\n",
354 ntohl(ste_stats->ec_eval_count));
355 printf("ste: event_channel denied_count = %d\n",
356 ntohl(ste_stats->ec_denied_count));
357 printf("ste: event_channel cache_hit_count = %d\n",
358 ntohl(ste_stats->ec_cachehit_count));
359 printf("ste:\n");
360 printf("ste: grant_table eval_count = %d\n",
361 ntohl(ste_stats->gt_eval_count));
362 printf("ste: grant_table denied_count = %d\n",
363 ntohl(ste_stats->gt_denied_count));
364 printf("ste: grant_table cache_hit_count = %d\n",
365 ntohl(ste_stats->gt_cachehit_count));
366 }
368 #define PULL_STATS_SIZE 8192
369 int acm_domain_dumpstats(int xc_handle)
370 {
371 u8 stats_buffer[PULL_STATS_SIZE];
372 acm_op_t op;
373 int ret;
374 struct acm_stats_buffer *stats;
376 memset(stats_buffer, 0x00, sizeof(stats_buffer));
377 op.cmd = ACM_DUMPSTATS;
378 op.interface_version = ACM_INTERFACE_VERSION;
379 op.u.dumpstats.pullcache = (void *) stats_buffer;
380 op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
381 ret = do_acm_op(xc_handle, &op);
383 if (ret < 0)
384 {
385 printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
386 return ret;
387 }
388 stats = (struct acm_stats_buffer *) stats_buffer;
390 printf("\nPolicy dump:\n");
391 printf("============\n");
392 printf("Magic = %x.\n", ntohl(stats->magic));
393 printf("Len = %x.\n", ntohl(stats->len));
395 switch (ntohl(stats->primary_policy_code))
396 {
397 case ACM_NULL_POLICY:
398 printf("NULL Policy: No statistics apply.\n");
399 break;
401 case ACM_CHINESE_WALL_POLICY:
402 printf("Chinese Wall Policy: No statistics apply.\n");
403 break;
405 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
406 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
407 ntohl(stats->
408 primary_stats_offset)));
409 break;
411 default:
412 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
413 }
415 switch (ntohl(stats->secondary_policy_code))
416 {
417 case ACM_NULL_POLICY:
418 printf("NULL Policy: No statistics apply.\n");
419 break;
421 case ACM_CHINESE_WALL_POLICY:
422 printf("Chinese Wall Policy: No statistics apply.\n");
423 break;
425 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
426 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
427 ntohl(stats->
428 secondary_stats_offset)));
429 break;
431 default:
432 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
433 }
434 return ret;
435 }
436 /************************ get ssidref & types ******************************/
437 /*
438 * the ssid (types) can be looked up either by domain id or by ssidref
439 */
440 int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
441 {
442 /* this includes header and a set of types */
443 #define MAX_SSIDBUFFER 2000
444 int ret, i;
445 acm_op_t op;
446 struct acm_ssid_buffer *hdr;
447 unsigned char *buf;
448 int nice_print = 1;
450 op.cmd = ACM_GETSSID;
451 op.interface_version = ACM_INTERFACE_VERSION;
452 op.u.getssid.get_ssid_by = UNSET;
453 /* arguments
454 -d ... domain id to look up
455 -s ... ssidref number to look up
456 -f ... formatted print (scripts depend on this format)
457 */
458 while (1)
459 {
460 int c = getopt(argc, argv, "d:s:f");
461 if (c == -1)
462 break;
463 if (c == 'd')
464 {
465 if (op.u.getssid.get_ssid_by != UNSET)
466 usage(argv[0]);
467 op.u.getssid.get_ssid_by = DOMAINID;
468 op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
469 }
470 else if (c== 's')
471 {
472 if (op.u.getssid.get_ssid_by != UNSET)
473 usage(argv[0]);
474 op.u.getssid.get_ssid_by = SSIDREF;
475 op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
476 }
477 else if (c== 'f')
478 {
479 nice_print = 0;
480 }
481 else
482 usage(argv[0]);
483 }
484 if (op.u.getssid.get_ssid_by == UNSET)
485 usage(argv[0]);
487 buf = malloc(MAX_SSIDBUFFER);
488 if (!buf)
489 return -ENOMEM;
491 /* dump it and then push it down into xen/acm */
492 op.u.getssid.ssidbuf = buf; /* out */
493 op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
494 ret = do_acm_op(xc_handle, &op);
496 if (ret)
497 {
498 printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
499 goto out;
500 }
501 hdr = (struct acm_ssid_buffer *)buf;
502 if (hdr->len > MAX_SSIDBUFFER)
503 {
504 printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
505 ret, hdr->len);
506 return -EIO;
507 }
508 if (nice_print)
509 {
510 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
511 printf(" P: %s, max_types = %d\n",
512 ACM_POLICY_NAME(hdr->primary_policy_code), hdr->primary_max_types);
513 printf(" Types: ");
514 for (i=0; i< hdr->primary_max_types; i++)
515 if (buf[hdr->primary_types_offset + i])
516 printf("%02x ", i);
517 else
518 printf("-- ");
519 printf("\n");
521 printf(" S: %s, max_types = %d\n",
522 ACM_POLICY_NAME(hdr->secondary_policy_code), hdr->secondary_max_types);
523 printf(" Types: ");
524 for (i=0; i< hdr->secondary_max_types; i++)
525 if (buf[hdr->secondary_types_offset + i])
526 printf("%02x ", i);
527 else
528 printf("-- ");
529 printf("\n");
530 }
531 else
532 {
533 /* formatted print for use with scripts (.sh)
534 * update scripts when updating here (usually
535 * used in combination with -d to determine a
536 * running domain's label
537 */
538 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
539 }
541 /* return ste ssidref */
542 if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
543 ret = (hdr->ssidref) & 0xffff;
544 else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
545 ret = (hdr->ssidref) >> 16;
546 out:
547 return ret;
548 }
550 /***************************** main **************************************/
552 int main(int argc, char **argv)
553 {
555 int acm_cmd_fd, ret = 0;
557 if (argc < 2)
558 usage(argv[0]);
560 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
561 {
562 printf("ERROR: Could not open xen privcmd device!\n");
563 exit(-1);
564 }
566 if (!strcmp(argv[1], "getpolicy")) {
567 if (argc != 2)
568 usage(argv[0]);
569 ret = acm_domain_getpolicy(acm_cmd_fd);
570 } else if (!strcmp(argv[1], "loadpolicy")) {
571 if (argc != 3)
572 usage(argv[0]);
573 ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
574 } else if (!strcmp(argv[1], "dumpstats")) {
575 if (argc != 2)
576 usage(argv[0]);
577 ret = acm_domain_dumpstats(acm_cmd_fd);
578 } else if (!strcmp(argv[1], "getssid")) {
579 ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
580 } else
581 usage(argv[0]);
583 close(acm_cmd_fd);
584 return ret;
585 }