ia64/xen-unstable

view tools/security/secpol_tool.c @ 8740:3d7ea7972b39

Update patches for linux 2.6.15.

Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Thu Feb 02 17:16:00 2006 +0000 (2006-02-02)
parents 8aac8746047b
children ad30019015a2
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 <stdint.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("Usage: %s ACTION\n"
48 "ACTION is one of:\n"
49 "\t getpolicy\n"
50 "\t dumpstats\n"
51 "\t loadpolicy <binary policy file>\n"
52 "\t getssid -d <domainid> [-f]\n"
53 "\t getssid -s <ssidref> [-f]\n", progname);
54 exit(-1);
55 }
57 static inline int do_policycmd(int xc_handle, unsigned int cmd,
58 unsigned long data)
59 {
60 return ioctl(xc_handle, cmd, data);
61 }
63 static inline int do_xen_hypercall(int xc_handle,
64 privcmd_hypercall_t * hypercall)
65 {
66 return do_policycmd(xc_handle,
67 IOCTL_PRIVCMD_HYPERCALL,
68 (unsigned long) hypercall);
69 }
71 static inline int do_acm_op(int xc_handle, struct acm_op * op)
72 {
73 int ret = -1;
74 privcmd_hypercall_t hypercall;
76 op->interface_version = ACM_INTERFACE_VERSION;
78 hypercall.op = __HYPERVISOR_acm_op;
79 hypercall.arg[0] = (unsigned long) op;
81 if (mlock(op, sizeof(*op)) != 0)
82 {
83 PERROR("Could not lock memory for Xen policy hypercall");
84 goto out1;
85 }
87 if ((ret = do_xen_hypercall(xc_handle, &hypercall)) < 0)
88 {
89 printf( "ACM operation failed: errno=%d\n", errno );
90 if (errno == EACCES)
91 fprintf(stderr, "ACM operation failed -- need to"
92 " rebuild the user-space tool set?\n");
93 goto out2;
94 }
96 out2:(void) munlock(op, sizeof(*op));
97 out1:return ret;
98 }
100 /*************************** DUMPS *******************************/
102 void acm_dump_chinesewall_buffer(void *buf, int buflen)
103 {
105 struct acm_chwall_policy_buffer *cwbuf =
106 (struct acm_chwall_policy_buffer *) buf;
107 domaintype_t *ssids, *conflicts, *running_types, *conflict_aggregate;
108 int i, j;
111 if (htonl(cwbuf->policy_code) != ACM_CHINESE_WALL_POLICY)
112 {
113 printf("CHINESE WALL POLICY CODE not found ERROR!!\n");
114 return;
115 }
116 printf("\n\nChinese Wall policy:\n");
117 printf("====================\n");
118 printf("Policy version= %x.\n", ntohl(cwbuf->policy_version));
119 printf("Max Types = %x.\n", ntohl(cwbuf->chwall_max_types));
120 printf("Max Ssidrefs = %x.\n", ntohl(cwbuf->chwall_max_ssidrefs));
121 printf("Max ConfSets = %x.\n", ntohl(cwbuf->chwall_max_conflictsets));
122 printf("Ssidrefs Off = %x.\n", ntohl(cwbuf->chwall_ssid_offset));
123 printf("Conflicts Off = %x.\n",
124 ntohl(cwbuf->chwall_conflict_sets_offset));
125 printf("Runing T. Off = %x.\n",
126 ntohl(cwbuf->chwall_running_types_offset));
127 printf("C. Agg. Off = %x.\n",
128 ntohl(cwbuf->chwall_conflict_aggregate_offset));
129 printf("\nSSID To CHWALL-Type matrix:\n");
131 ssids = (domaintype_t *) (buf + ntohl(cwbuf->chwall_ssid_offset));
132 for (i = 0; i < ntohl(cwbuf->chwall_max_ssidrefs); i++)
133 {
134 printf("\n ssidref%2x: ", i);
135 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
136 printf("%02x ",
137 ntohs(ssids[i * ntohl(cwbuf->chwall_max_types) + j]));
138 }
139 printf("\n\nConfict Sets:\n");
140 conflicts =
141 (domaintype_t *) (buf + ntohl(cwbuf->chwall_conflict_sets_offset));
142 for (i = 0; i < ntohl(cwbuf->chwall_max_conflictsets); i++)
143 {
144 printf("\n c-set%2x: ", i);
145 for (j = 0; j < ntohl(cwbuf->chwall_max_types); j++)
146 printf("%02x ",
147 ntohs(conflicts
148 [i * ntohl(cwbuf->chwall_max_types) + j]));
149 }
150 printf("\n");
152 printf("\nRunning\nTypes: ");
153 if (ntohl(cwbuf->chwall_running_types_offset))
154 {
155 running_types =
156 (domaintype_t *) (buf +
157 ntohl(cwbuf->chwall_running_types_offset));
158 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
159 {
160 printf("%02x ", ntohs(running_types[i]));
161 }
162 printf("\n");
163 } else {
164 printf("Not Reported!\n");
165 }
166 printf("\nConflict\nAggregate Set: ");
167 if (ntohl(cwbuf->chwall_conflict_aggregate_offset))
168 {
169 conflict_aggregate =
170 (domaintype_t *) (buf +
171 ntohl(cwbuf->chwall_conflict_aggregate_offset));
172 for (i = 0; i < ntohl(cwbuf->chwall_max_types); i++)
173 {
174 printf("%02x ", ntohs(conflict_aggregate[i]));
175 }
176 printf("\n\n");
177 } else {
178 printf("Not Reported!\n");
179 }
180 }
182 void acm_dump_ste_buffer(void *buf, int buflen)
183 {
185 struct acm_ste_policy_buffer *stebuf =
186 (struct acm_ste_policy_buffer *) buf;
187 domaintype_t *ssids;
188 int i, j;
191 if (ntohl(stebuf->policy_code) != ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY) {
192 printf("SIMPLE TYPE ENFORCEMENT POLICY CODE not found ERROR!!\n");
193 return;
194 }
195 printf("\nSimple Type Enforcement policy:\n");
196 printf("===============================\n");
197 printf("Policy version= %x.\n", ntohl(stebuf->policy_version));
198 printf("Max Types = %x.\n", ntohl(stebuf->ste_max_types));
199 printf("Max Ssidrefs = %x.\n", ntohl(stebuf->ste_max_ssidrefs));
200 printf("Ssidrefs Off = %x.\n", ntohl(stebuf->ste_ssid_offset));
201 printf("\nSSID To STE-Type matrix:\n");
203 ssids = (domaintype_t *) (buf + ntohl(stebuf->ste_ssid_offset));
204 for (i = 0; i < ntohl(stebuf->ste_max_ssidrefs); i++)
205 {
206 printf("\n ssidref%2x: ", i);
207 for (j = 0; j < ntohl(stebuf->ste_max_types); j++)
208 printf("%02x ", ntohs(ssids[i * ntohl(stebuf->ste_max_types) + j]));
209 }
210 printf("\n\n");
211 }
213 void acm_dump_policy_buffer(void *buf, int buflen)
214 {
215 struct acm_policy_buffer *pol = (struct acm_policy_buffer *) buf;
217 printf("\nPolicy dump:\n");
218 printf("============\n");
219 printf("PolicyVer = %x.\n", ntohl(pol->policy_version));
220 printf("Magic = %x.\n", ntohl(pol->magic));
221 printf("Len = %x.\n", ntohl(pol->len));
222 printf("Primary = %s (c=%x, off=%x).\n",
223 ACM_POLICY_NAME(ntohl(pol->primary_policy_code)),
224 ntohl(pol->primary_policy_code),
225 ntohl(pol->primary_buffer_offset));
226 printf("Secondary = %s (c=%x, off=%x).\n",
227 ACM_POLICY_NAME(ntohl(pol->secondary_policy_code)),
228 ntohl(pol->secondary_policy_code),
229 ntohl(pol->secondary_buffer_offset));
230 switch (ntohl(pol->primary_policy_code))
231 {
232 case ACM_CHINESE_WALL_POLICY:
233 acm_dump_chinesewall_buffer(buf +
234 ntohl(pol->primary_buffer_offset),
235 ntohl(pol->len) -
236 ntohl(pol->primary_buffer_offset));
237 break;
239 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
240 acm_dump_ste_buffer(buf + ntohl(pol->primary_buffer_offset),
241 ntohl(pol->len) -
242 ntohl(pol->primary_buffer_offset));
243 break;
245 case ACM_NULL_POLICY:
246 printf("Primary policy is NULL Policy (n/a).\n");
247 break;
249 default:
250 printf("UNKNOWN POLICY!\n");
251 }
253 switch (ntohl(pol->secondary_policy_code))
254 {
255 case ACM_CHINESE_WALL_POLICY:
256 acm_dump_chinesewall_buffer(buf +
257 ntohl(pol->secondary_buffer_offset),
258 ntohl(pol->len) -
259 ntohl(pol->secondary_buffer_offset));
260 break;
262 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
263 acm_dump_ste_buffer(buf + ntohl(pol->secondary_buffer_offset),
264 ntohl(pol->len) -
265 ntohl(pol->secondary_buffer_offset));
266 break;
268 case ACM_NULL_POLICY:
269 printf("Secondary policy is NULL Policy (n/a).\n");
270 break;
272 default:
273 printf("UNKNOWN POLICY!\n");
274 }
275 }
277 /******************************* get policy ******************************/
279 #define PULL_CACHE_SIZE 8192
280 uint8_t pull_buffer[PULL_CACHE_SIZE];
281 int acm_domain_getpolicy(int xc_handle)
282 {
283 struct acm_op op;
284 int ret;
286 memset(pull_buffer, 0x00, sizeof(pull_buffer));
287 op.cmd = ACM_GETPOLICY;
288 op.interface_version = ACM_INTERFACE_VERSION;
289 op.u.getpolicy.pullcache = (void *) pull_buffer;
290 op.u.getpolicy.pullcache_size = sizeof(pull_buffer);
291 ret = do_acm_op(xc_handle, &op);
292 /* dump policy */
293 acm_dump_policy_buffer(pull_buffer, sizeof(pull_buffer));
294 return ret;
295 }
297 /************************ load binary policy ******************************/
299 int acm_domain_loadpolicy(int xc_handle, const char *filename)
300 {
301 struct stat mystat;
302 int ret, fd;
303 off_t len;
304 uint8_t *buffer;
306 if ((ret = stat(filename, &mystat)))
307 {
308 printf("File %s not found.\n", filename);
309 goto out;
310 }
312 len = mystat.st_size;
313 if ((buffer = malloc(len)) == NULL)
314 {
315 ret = -ENOMEM;
316 goto out;
317 }
318 if ((fd = open(filename, O_RDONLY)) <= 0)
319 {
320 ret = -ENOENT;
321 printf("File %s not found.\n", filename);
322 goto free_out;
323 }
324 if (len == read(fd, buffer, len))
325 {
326 struct acm_op op;
327 /* dump it and then push it down into xen/acm */
328 acm_dump_policy_buffer(buffer, len);
329 op.cmd = ACM_SETPOLICY;
330 op.interface_version = ACM_INTERFACE_VERSION;
331 op.u.setpolicy.pushcache = (void *) buffer;
332 op.u.setpolicy.pushcache_size = len;
333 ret = do_acm_op(xc_handle, &op);
335 if (ret)
336 printf
337 ("ERROR setting policy. Try 'xm dmesg' to see details.\n");
338 else
339 printf("Successfully changed policy.\n");
341 } else {
342 ret = -1;
343 }
344 close(fd);
345 free_out:
346 free(buffer);
347 out:
348 return ret;
349 }
351 /************************ dump hook statistics ******************************/
352 void dump_ste_stats(struct acm_ste_stats_buffer *ste_stats)
353 {
354 printf("STE-Policy Security Hook Statistics:\n");
355 printf("ste: event_channel eval_count = %d\n",
356 ntohl(ste_stats->ec_eval_count));
357 printf("ste: event_channel denied_count = %d\n",
358 ntohl(ste_stats->ec_denied_count));
359 printf("ste: event_channel cache_hit_count = %d\n",
360 ntohl(ste_stats->ec_cachehit_count));
361 printf("ste:\n");
362 printf("ste: grant_table eval_count = %d\n",
363 ntohl(ste_stats->gt_eval_count));
364 printf("ste: grant_table denied_count = %d\n",
365 ntohl(ste_stats->gt_denied_count));
366 printf("ste: grant_table cache_hit_count = %d\n",
367 ntohl(ste_stats->gt_cachehit_count));
368 }
370 #define PULL_STATS_SIZE 8192
371 int acm_domain_dumpstats(int xc_handle)
372 {
373 uint8_t stats_buffer[PULL_STATS_SIZE];
374 struct acm_op op;
375 int ret;
376 struct acm_stats_buffer *stats;
378 memset(stats_buffer, 0x00, sizeof(stats_buffer));
379 op.cmd = ACM_DUMPSTATS;
380 op.interface_version = ACM_INTERFACE_VERSION;
381 op.u.dumpstats.pullcache = (void *) stats_buffer;
382 op.u.dumpstats.pullcache_size = sizeof(stats_buffer);
383 ret = do_acm_op(xc_handle, &op);
385 if (ret < 0)
386 {
387 printf("ERROR dumping policy stats. Try 'xm dmesg' to see details.\n");
388 return ret;
389 }
390 stats = (struct acm_stats_buffer *) stats_buffer;
392 printf("\nPolicy dump:\n");
393 printf("============\n");
394 printf("Magic = %x.\n", ntohl(stats->magic));
395 printf("Len = %x.\n", ntohl(stats->len));
397 switch (ntohl(stats->primary_policy_code))
398 {
399 case ACM_NULL_POLICY:
400 printf("NULL Policy: No statistics apply.\n");
401 break;
403 case ACM_CHINESE_WALL_POLICY:
404 printf("Chinese Wall Policy: No statistics apply.\n");
405 break;
407 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
408 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
409 ntohl(stats->
410 primary_stats_offset)));
411 break;
413 default:
414 printf("UNKNOWN PRIMARY POLICY ERROR!\n");
415 }
417 switch (ntohl(stats->secondary_policy_code))
418 {
419 case ACM_NULL_POLICY:
420 printf("NULL Policy: No statistics apply.\n");
421 break;
423 case ACM_CHINESE_WALL_POLICY:
424 printf("Chinese Wall Policy: No statistics apply.\n");
425 break;
427 case ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY:
428 dump_ste_stats((struct acm_ste_stats_buffer *) (stats_buffer +
429 ntohl(stats->
430 secondary_stats_offset)));
431 break;
433 default:
434 printf("UNKNOWN SECONDARY POLICY ERROR!\n");
435 }
436 return ret;
437 }
438 /************************ get ssidref & types ******************************/
439 /*
440 * the ssid (types) can be looked up either by domain id or by ssidref
441 */
442 int acm_domain_getssid(int xc_handle, int argc, char * const argv[])
443 {
444 /* this includes header and a set of types */
445 #define MAX_SSIDBUFFER 2000
446 int ret, i;
447 struct acm_op op;
448 struct acm_ssid_buffer *hdr;
449 unsigned char *buf;
450 int nice_print = 1;
452 op.cmd = ACM_GETSSID;
453 op.interface_version = ACM_INTERFACE_VERSION;
454 op.u.getssid.get_ssid_by = UNSET;
455 /* arguments
456 -d ... domain id to look up
457 -s ... ssidref number to look up
458 -f ... formatted print (scripts depend on this format)
459 */
460 while (1)
461 {
462 int c = getopt(argc, argv, "d:s:f");
463 if (c == -1)
464 break;
465 if (c == 'd')
466 {
467 if (op.u.getssid.get_ssid_by != UNSET)
468 usage(argv[0]);
469 op.u.getssid.get_ssid_by = DOMAINID;
470 op.u.getssid.id.domainid = strtoul(optarg, NULL, 0);
471 }
472 else if (c== 's')
473 {
474 if (op.u.getssid.get_ssid_by != UNSET)
475 usage(argv[0]);
476 op.u.getssid.get_ssid_by = SSIDREF;
477 op.u.getssid.id.ssidref = strtoul(optarg, NULL, 0);
478 }
479 else if (c== 'f')
480 {
481 nice_print = 0;
482 }
483 else
484 usage(argv[0]);
485 }
486 if (op.u.getssid.get_ssid_by == UNSET)
487 usage(argv[0]);
489 buf = malloc(MAX_SSIDBUFFER);
490 if (!buf)
491 return -ENOMEM;
493 /* dump it and then push it down into xen/acm */
494 op.u.getssid.ssidbuf = buf; /* out */
495 op.u.getssid.ssidbuf_size = MAX_SSIDBUFFER;
496 ret = do_acm_op(xc_handle, &op);
498 if (ret)
499 {
500 printf("ERROR getting ssidref. Try 'xm dmesg' to see details.\n");
501 goto out;
502 }
503 hdr = (struct acm_ssid_buffer *)buf;
504 if (hdr->len > MAX_SSIDBUFFER)
505 {
506 printf("ERROR: Buffer length inconsistent (ret=%d, hdr->len=%d)!\n",
507 ret, hdr->len);
508 return -EIO;
509 }
510 if (nice_print)
511 {
512 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
513 printf(" P: %s, max_types = %d\n",
514 ACM_POLICY_NAME(hdr->primary_policy_code), hdr->primary_max_types);
515 printf(" Types: ");
516 for (i=0; i< hdr->primary_max_types; i++)
517 if (buf[hdr->primary_types_offset + i])
518 printf("%02x ", i);
519 else
520 printf("-- ");
521 printf("\n");
523 printf(" S: %s, max_types = %d\n",
524 ACM_POLICY_NAME(hdr->secondary_policy_code), hdr->secondary_max_types);
525 printf(" Types: ");
526 for (i=0; i< hdr->secondary_max_types; i++)
527 if (buf[hdr->secondary_types_offset + i])
528 printf("%02x ", i);
529 else
530 printf("-- ");
531 printf("\n");
532 }
533 else
534 {
535 /* formatted print for use with scripts (.sh)
536 * update scripts when updating here (usually
537 * used in combination with -d to determine a
538 * running domain's label
539 */
540 printf("SSID: ssidref = 0x%08x \n", hdr->ssidref);
541 }
543 /* return ste ssidref */
544 if (hdr->primary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
545 ret = (hdr->ssidref) & 0xffff;
546 else if (hdr->secondary_policy_code == ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY)
547 ret = (hdr->ssidref) >> 16;
548 out:
549 return ret;
550 }
552 /***************************** main **************************************/
554 int main(int argc, char **argv)
555 {
557 int acm_cmd_fd, ret = 0;
559 if (argc < 2)
560 usage(argv[0]);
562 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0)
563 {
564 printf("ERROR: Could not open xen privcmd device!\n");
565 exit(-1);
566 }
568 if (!strcmp(argv[1], "getpolicy")) {
569 if (argc != 2)
570 usage(argv[0]);
571 ret = acm_domain_getpolicy(acm_cmd_fd);
572 } else if (!strcmp(argv[1], "loadpolicy")) {
573 if (argc != 3)
574 usage(argv[0]);
575 ret = acm_domain_loadpolicy(acm_cmd_fd, argv[2]);
576 } else if (!strcmp(argv[1], "dumpstats")) {
577 if (argc != 2)
578 usage(argv[0]);
579 ret = acm_domain_dumpstats(acm_cmd_fd);
580 } else if (!strcmp(argv[1], "getssid")) {
581 ret = acm_domain_getssid(acm_cmd_fd, argc, argv);
582 } else
583 usage(argv[0]);
585 close(acm_cmd_fd);
586 return ret;
587 }