ia64/xen-unstable

view tools/python/xen/lowlevel/acm/acm.c @ 9835:cf20dbbf5c2b

This patch adds new python access control management scripts, which
integrate into Xen Management and which support the new access control
labels (labels replace the ssidref numbers at the management user
interface).

Signed-off by: Reiner Sailer <sailer@us.ibm.com>
author smh22@firebug.cl.cam.ac.uk
date Mon Apr 24 10:58:25 2006 +0100 (2006-04-24)
parents
children 24dbb153ab39
line source
1 /****************************************************************
2 * acm.c
3 *
4 * Copyright (C) 2006 IBM Corporation
5 *
6 * Authors:
7 * Reiner Sailer <sailer@watson.ibm.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 *
14 * ACM low-level code that allows Python control code to leverage
15 * the ACM hypercall interface to retrieve real-time information
16 * from the Xen hypervisor security module.
17 *
18 * indent -i4 -kr -nut
19 */
20 #include <Python.h>
22 #include <stdio.h>
23 #include <fcntl.h>
24 #include <sys/mman.h>
25 #include <sys/types.h>
26 #include <stdlib.h>
27 #include <sys/ioctl.h>
28 #include <netinet/in.h>
29 #include <xen/acm.h>
30 #include <xen/acm_ops.h>
31 #include <xen/linux/privcmd.h>
33 #define PERROR(_m, _a...) \
34 fprintf(stderr, "ERROR: " _m " (%d = %s)\n" , ## _a , \
35 errno, strerror(errno))
39 static inline int do_acm_op(int xc_handle, struct acm_op *op)
40 {
41 int ret = -1;
42 privcmd_hypercall_t hypercall;
44 op->interface_version = ACM_INTERFACE_VERSION;
46 hypercall.op = __HYPERVISOR_acm_op;
47 hypercall.arg[0] = (unsigned long) op;
49 if (mlock(op, sizeof(*op)) != 0) {
50 PERROR("Could not lock memory for Xen policy hypercall");
51 goto out1;
52 }
53 ret = ioctl(xc_handle, IOCTL_PRIVCMD_HYPERCALL, &hypercall);
54 if (ret < 0) {
55 if (errno == EACCES)
56 PERROR("ACM operation failed.");
57 goto out2;
58 }
59 out2:
60 munlock(op, sizeof(*op));
61 out1:
62 return ret;
63 }
67 /* generic shared function */
68 void * __getssid(int domid, uint32_t *buflen)
69 {
70 struct acm_op op;
71 int acm_cmd_fd;
72 #define SSID_BUFFER_SIZE 4096
73 void *buf = NULL;
75 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) < 0) {
76 goto out1;
77 }
78 if ((buf = malloc(SSID_BUFFER_SIZE)) == NULL) {
79 PERROR("acm.policytype: Could not allocate ssid buffer!\n");
80 goto out2;
81 }
82 memset(buf, 0, SSID_BUFFER_SIZE);
83 op.cmd = ACM_GETSSID;
84 op.interface_version = ACM_INTERFACE_VERSION;
85 op.u.getssid.ssidbuf = buf;
86 op.u.getssid.ssidbuf_size = SSID_BUFFER_SIZE;
87 op.u.getssid.get_ssid_by = DOMAINID;
88 op.u.getssid.id.domainid = domid;
90 if (do_acm_op(acm_cmd_fd, &op) < 0) {
91 free(buf);
92 buf = NULL;
93 goto out2;
94 } else {
95 *buflen = SSID_BUFFER_SIZE;
96 goto out2;
97 }
98 out2:
99 close(acm_cmd_fd);
100 out1:
101 return buf;
102 }
105 /* retrieve the policytype indirectly by retrieving the
106 * ssidref for domain 0 (always exists) */
107 static PyObject *policy(PyObject * self, PyObject * args)
108 {
109 /* out */
110 char *policyreference;
111 PyObject *ret = NULL;
112 void *ssid_buffer;
113 uint32_t buf_len;
115 if (!PyArg_ParseTuple(args, "", NULL)) {
116 goto out1;
117 }
118 ssid_buffer = __getssid(0, &buf_len);
119 if (ssid_buffer == NULL) {
120 goto out1;
121 } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
122 goto out2;
123 } else {
124 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *)ssid_buffer;
125 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
126 + sizeof (struct acm_policy_reference_buffer));
127 }
128 ret = Py_BuildValue("s", policyreference);
129 out2:
130 free(ssid_buffer);
131 out1:
132 return ret;
133 }
136 /* retrieve ssid info for a domain domid*/
137 static PyObject *getssid(PyObject * self, PyObject * args)
138 {
139 /* in */
140 uint32_t domid;
141 /* out */
142 char *policytype, *policyreference;
143 uint32_t ssidref;
145 void *ssid_buffer;
146 uint32_t buf_len;
148 if (!PyArg_ParseTuple(args, "i", &domid)) {
149 return NULL;
150 }
151 ssid_buffer = __getssid(domid, &buf_len);
152 if (ssid_buffer == NULL) {
153 return NULL;
154 } else if (buf_len < sizeof(struct acm_ssid_buffer)) {
155 free(ssid_buffer);
156 return NULL;
157 } else {
158 struct acm_ssid_buffer *ssid = (struct acm_ssid_buffer *) ssid_buffer;
159 policytype = ACM_POLICY_NAME(ssid->secondary_policy_code << 4 |
160 ssid->primary_policy_code);
161 ssidref = ssid->ssidref;
162 policyreference = (char *)(ssid_buffer + ssid->policy_reference_offset
163 + sizeof (struct acm_policy_reference_buffer));
164 }
165 free(ssid_buffer);
166 return Py_BuildValue("{s:s,s:s,s:i}",
167 "policyreference", policyreference,
168 "policytype", policytype,
169 "ssidref", ssidref);
170 }
173 /* retrieve access decision based on domain ids or ssidrefs */
174 static PyObject *getdecision(PyObject * self, PyObject * args)
175 {
176 char *arg1_name, *arg1, *arg2_name, *arg2, *decision = NULL;
177 struct acm_op op;
178 int acm_cmd_fd, ret;
180 if (!PyArg_ParseTuple(args, "ssss", &arg1_name, &arg1, &arg2_name, &arg2)) {
181 return NULL;
182 }
184 if ((acm_cmd_fd = open("/proc/xen/privcmd", O_RDONLY)) <= 0) {
185 PERROR("Could not open xen privcmd device!\n");
186 return NULL;
187 }
189 if ((strcmp(arg1_name, "domid") && strcmp(arg1_name, "ssidref")) ||
190 (strcmp(arg2_name, "domid") && strcmp(arg2_name, "ssidref")))
191 return NULL;
193 op.cmd = ACM_GETDECISION;
194 op.interface_version = ACM_INTERFACE_VERSION;
195 op.u.getdecision.hook = SHARING;
196 if (!strcmp(arg1_name, "domid")) {
197 op.u.getdecision.get_decision_by1 = DOMAINID;
198 op.u.getdecision.id1.domainid = atoi(arg1);
199 } else {
200 op.u.getdecision.get_decision_by1 = SSIDREF;
201 op.u.getdecision.id1.ssidref = atol(arg1);
202 }
203 if (!strcmp(arg2_name, "domid")) {
204 op.u.getdecision.get_decision_by2 = DOMAINID;
205 op.u.getdecision.id2.domainid = atoi(arg2);
206 } else {
207 op.u.getdecision.get_decision_by2 = SSIDREF;
208 op.u.getdecision.id2.ssidref = atol(arg2);
209 }
211 ret = do_acm_op(acm_cmd_fd, &op);
212 close(acm_cmd_fd);
214 if (op.u.getdecision.acm_decision == ACM_ACCESS_PERMITTED)
215 decision = "PERMITTED";
216 else if (op.u.getdecision.acm_decision == ACM_ACCESS_DENIED)
217 decision = "DENIED";
219 return Py_BuildValue("s", decision);
220 }
222 /*=================General Python Extension Declarations=================*/
224 /* methods */
225 static PyMethodDef acmMethods[] = {
226 {"policy", policy, METH_VARARGS, "Retrieve Active ACM Policy Reference Name"},
227 {"getssid", getssid, METH_VARARGS, "Retrieve label information and ssidref for a domain"},
228 {"getdecision", getdecision, METH_VARARGS, "Retrieve ACM access control decision"},
229 /* end of list (extend list above this line) */
230 {NULL, NULL, 0, NULL}
231 };
233 /* inits */
234 PyMODINIT_FUNC initacm(void)
235 {
236 Py_InitModule("acm", acmMethods);
237 }